1 /*
2 * Copyright (C) 2018-2021 Alexandros Theodotou <alex at zrythm dot org>
3 *
4 * This file is part of Zrythm
5 *
6 * Zrythm is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Zrythm is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with Zrythm. If not, see <https://www.gnu.org/licenses/>.
18 *
19 * This file incorporates work covered by the following copyright and
20 * permission notice:
21 *
22 * Copyright (C) 2015 Tim Mayberry <mojofunk@gmail.com>
23 *
24 * This program is free software: you can redistribute it and/or modify
25 * it under the terms of the GNU General Public License as published by
26 * the Free Software Foundation, either version 2 of the License, or
27 * (at your option) any later version.
28 *
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
33 *
34 * You should have received a copy of the GNU General Public License
35 * along with this program. If not, see <https://www.gnu.org/licenses/>.
36 */
37
38 #include <inttypes.h>
39 #include <math.h>
40 #include <stdlib.h>
41 #include <signal.h>
42
43 #include "audio/channel.h"
44 #include "audio/chord_descriptor.h"
45 #include "audio/engine.h"
46 #include "audio/midi_event.h"
47 #include "audio/router.h"
48 #include "audio/transport.h"
49 #include "project.h"
50 #include "utils/objects.h"
51
52 static const char * midi_event_type_strings[] =
53 {
54 "pitchbend",
55 "controller",
56 "note off",
57 "note on",
58 "all notes off",
59 };
60
61 /**
62 * Prints a message saying unknown event, with
63 * information about the given event.
64 */
65 static void
print_unknown_event_message(uint8_t * buf,const int buf_size)66 print_unknown_event_message (
67 uint8_t * buf,
68 const int buf_size)
69 {
70 if (buf_size == 3)
71 {
72 g_message (
73 "Unknown MIDI event %#x %#x %#x"
74 " received", buf[0], buf[1], buf[2]);
75 }
76 else if (buf_size == 2)
77 {
78 g_message (
79 "Unknown MIDI event %#x %#x"
80 " received", buf[0], buf[1]);
81 }
82 else if (buf_size == 1)
83 {
84 g_message (
85 "Unknown MIDI event %#x"
86 " received", buf[0]);
87 }
88 else
89 {
90 g_message (
91 "Unknown MIDI event of size %d"
92 " received", buf_size);
93 }
94 }
95
96 /**
97 * Appends the events from src to dest
98 *
99 * @param queued Append queued events instead of
100 * main events.
101 * @param local_offset The start frame offset from 0
102 * in this cycle.
103 * @param nframes Number of frames to process.
104 */
105 void
midi_events_append(MidiEvents * src,MidiEvents * dest,const nframes_t local_offset,const nframes_t nframes,bool queued)106 midi_events_append (
107 MidiEvents * src,
108 MidiEvents * dest,
109 const nframes_t local_offset,
110 const nframes_t nframes,
111 bool queued)
112 {
113 midi_events_append_w_filter (
114 src, dest, NULL, local_offset, nframes, queued);
115 }
116
117 /**
118 * Appends the events from src to dest
119 *
120 * @param queued Append queued events instead of
121 * main events.
122 * @param channels Allowed channels (array of 16
123 * booleans).
124 * @param local_offset The start frame offset from 0
125 * in this cycle.
126 * @param nframes Number of frames to process.
127 */
128 void
midi_events_append_w_filter(MidiEvents * src,MidiEvents * dest,int * channels,const nframes_t local_offset,const nframes_t nframes,bool queued)129 midi_events_append_w_filter (
130 MidiEvents * src,
131 MidiEvents * dest,
132 int * channels,
133 const nframes_t local_offset,
134 const nframes_t nframes,
135 bool queued)
136 {
137 /* queued not implemented yet */
138 g_return_if_fail (!queued);
139
140 MidiEvent * src_ev, * dest_ev;
141 for (int i = 0; i < src->num_events; i++)
142 {
143 src_ev = &src->events[i];
144
145 /* only copy events inside the current time
146 * range */
147 if (ZRYTHM_TESTING
148 &&
149 (src_ev->time < local_offset ||
150 src_ev->time >= local_offset + nframes))
151 {
152 g_debug (
153 "skipping event: time %" PRIu8
154 " (local offset %" PRIu32
155 " nframes %" PRIu32 ")",
156 src_ev->time, local_offset, nframes);
157 continue;
158 }
159
160 /* if filtering, skip disabled channels */
161 if (channels)
162 {
163 midi_byte_t channel =
164 src_ev->raw_buffer[0] & 0xf;
165 if (!channels[channel])
166 {
167 continue;
168 }
169 }
170
171 g_return_if_fail (
172 dest->num_events < MAX_MIDI_EVENTS);
173
174 dest_ev =
175 &dest->events[dest->num_events++];
176 midi_event_copy (dest_ev, src_ev);
177 }
178
179 /* clear duplicates */
180 midi_events_clear_duplicates (dest, queued);
181 }
182
183 /**
184 * Sets the given MIDI channel on all applicable
185 * MIDI events.
186 *
187 * @param channel Channel, starting from 1.
188 */
189 void
midi_events_set_channel(MidiEvents * self,const int queued,const midi_byte_t channel)190 midi_events_set_channel (
191 MidiEvents * self,
192 const int queued,
193 const midi_byte_t channel)
194 {
195 /* queued not implemented yet */
196 g_return_if_fail (!queued);
197
198 for (int i = 0; i < self->num_events; i++)
199 {
200 MidiEvent * ev = &self->events[i];
201 ev->channel = channel;
202
203 /* do this on all MIDI events that have
204 * channels */
205 #define SET_CHANNEL(byte) \
206 if ((ev->raw_buffer[0] & byte) == byte) \
207 { \
208 ev->raw_buffer[0] = \
209 (ev->raw_buffer[0] & byte) | \
210 (channel - 1); \
211 continue; \
212 }
213
214 /* skip MIDI events starting with the given
215 * byte */
216 #define SKIP_CHANNEL(byte) \
217 if ((ev->raw_buffer[0] & byte) == byte) \
218 continue;
219
220 SKIP_CHANNEL (0xF0);
221 SET_CHANNEL (0xE0);
222 SET_CHANNEL (0xD0);
223 SET_CHANNEL (0xC0);
224 SET_CHANNEL (0xB0);
225 SET_CHANNEL (0xA0);
226 SET_CHANNEL (0x90);
227 SET_CHANNEL (0x80);
228
229 #undef SET_CHANNEL
230 #undef SKIP_CHANNEL
231 }
232 }
233
234 /**
235 * Clears midi events.
236 */
237 REALTIME
238 void
midi_events_clear(MidiEvents * self,int queued)239 midi_events_clear (
240 MidiEvents * self,
241 int queued)
242 {
243 if (queued)
244 {
245 self->num_queued_events = 0;
246 }
247 else
248 {
249 self->num_events = 0;
250 }
251 }
252
253 /**
254 * Returns if a note on event for the given note
255 * exists in the given events.
256 */
257 int
midi_events_check_for_note_on(MidiEvents * self,int note,int queued)258 midi_events_check_for_note_on (
259 MidiEvents * self,
260 int note,
261 int queued)
262 {
263 /*g_message ("waiting check note on");*/
264 zix_sem_wait (&self->access_sem);
265
266 MidiEvent * ev;
267 for (int i = 0;
268 i < queued ?
269 self->num_queued_events :
270 self->num_events;
271 i++)
272 {
273 if (queued)
274 ev = &self->queued_events[i];
275 else
276 ev = &self->events[i];
277
278 if (ev->type == MIDI_EVENT_TYPE_NOTE_ON &&
279 ev->note_pitch == note)
280 return 1;
281 }
282
283 zix_sem_post (&self->access_sem);
284 /*g_message ("posted check note on");*/
285
286 return 0;
287 }
288
289 /**
290 * Deletes the midi event with a note on signal
291 * from the queue, and returns if it deleted or not.
292 */
293 int
midi_events_delete_note_on(MidiEvents * self,int note,int queued)294 midi_events_delete_note_on (
295 MidiEvents * self,
296 int note,
297 int queued)
298 {
299 /*g_message ("waiting delete note on");*/
300 zix_sem_wait (&self->access_sem);
301
302 MidiEvent * ev, * ev2, * next_ev;
303 int match = 0;
304 for (int i = queued ?
305 self->num_queued_events - 1 :
306 self->num_events - 1;
307 i >= 0; i--)
308 {
309 ev = queued ?
310 &self->queued_events[i] :
311 &self->events[i];
312 if (ev->type == MIDI_EVENT_TYPE_NOTE_ON &&
313 ev->note_pitch == note)
314 {
315 match = 1;
316
317 if (queued)
318 --self->num_queued_events;
319 else
320 --self->num_events;
321
322 for (int ii = i;
323 ii < queued ?
324 self->num_queued_events :
325 self->num_events;
326 ii++)
327 {
328 if (queued)
329 {
330 ev2 = &self->queued_events[ii];
331 next_ev =
332 &self->queued_events[ii + 1];
333 }
334 else
335 {
336 ev2 = &self->events[ii];
337 next_ev =
338 &self->events[ii + 1];
339 }
340 midi_event_copy (ev2, next_ev);
341 }
342 }
343 }
344
345 zix_sem_post (&self->access_sem);
346
347 return match;
348 }
349
350 /**
351 * Inits the MidiEvents struct.
352 */
353 void
midi_events_init(MidiEvents * self)354 midi_events_init (
355 MidiEvents * self)
356 {
357 self->num_events = 0;
358 self->num_queued_events = 0;
359
360 zix_sem_init (&self->access_sem, 1);
361 }
362
363 /**
364 * Allocates and inits a MidiEvents struct.
365 */
366 MidiEvents *
midi_events_new(void)367 midi_events_new (void)
368 {
369 MidiEvents * self = object_new (MidiEvents);
370
371 midi_events_init (self);
372
373 return self;
374 }
375
376 /**
377 * Returrns if the MidiEvents have any note on
378 * events.
379 *
380 * @param check_main Check the main events.
381 * @param check_queued Check the queued events.
382 */
383 int
midi_events_has_note_on(MidiEvents * self,int check_main,int check_queued)384 midi_events_has_note_on (
385 MidiEvents * self,
386 int check_main,
387 int check_queued)
388 {
389 if (check_main)
390 {
391 for (int i = 0; i < self->num_events; i++)
392 {
393 if (self->events[i].type ==
394 MIDI_EVENT_TYPE_NOTE_ON)
395 return 1;
396 }
397 }
398 if (check_queued)
399 {
400 for (int i = 0;
401 i < self->num_queued_events; i++)
402 {
403 if (self->queued_events[i].type ==
404 MIDI_EVENT_TYPE_NOTE_ON)
405 return 1;
406 }
407 }
408
409 return 0;
410 }
411
412 /**
413 * Copies the queue contents to the original struct
414 */
415 REALTIME
416 NONNULL
417 void
midi_events_dequeue(MidiEvents * self)418 midi_events_dequeue (
419 MidiEvents * self)
420 {
421 /*g_message ("waiting dequeue");*/
422 zix_sem_wait (&self->access_sem);
423
424 MidiEvent * ev, * q_ev;
425 for (int i = 0;
426 i < self->num_queued_events; i++)
427 {
428 q_ev = &self->queued_events[i];
429 ev = &self->events[i];
430
431 midi_event_copy (ev, q_ev);
432 }
433
434 self->num_events = self->num_queued_events;
435 self->num_queued_events = 0;
436
437 zix_sem_post (&self->access_sem);
438 /*g_message ("posted dequeue");*/
439 }
440
441 /**
442 * Queues MIDI note off to event queue.
443 */
444 void
midi_events_add_all_notes_off(MidiEvents * self,midi_byte_t channel,midi_time_t time,bool queued)445 midi_events_add_all_notes_off (
446 MidiEvents * self,
447 midi_byte_t channel,
448 midi_time_t time,
449 bool queued)
450 {
451 MidiEvent * ev;
452 if (queued)
453 ev =
454 &self->queued_events[self->num_queued_events];
455 else
456 ev =
457 &self->events[self->num_events];
458
459 ev->type = MIDI_EVENT_TYPE_ALL_NOTES_OFF;
460 ev->channel = channel;
461 ev->time = time;
462 ev->raw_buffer[0] =
463 (midi_byte_t)
464 (MIDI_CH1_CTRL_CHANGE | (channel - 1));
465 ev->raw_buffer[1] = MIDI_ALL_NOTES_OFF;
466 ev->raw_buffer[2] = 0x00;
467
468 if (queued)
469 self->num_queued_events++;
470 else
471 self->num_events++;
472 }
473
474 void
midi_events_panic(MidiEvents * self,bool queued)475 midi_events_panic (
476 MidiEvents * self,
477 bool queued)
478 {
479 zix_sem_wait (&self->access_sem);
480 /*g_message ("sending PANIC");*/
481 for (midi_byte_t i = 0; i < 16; i++)
482 {
483 midi_events_add_all_notes_off (
484 self, i, 0, queued);
485 }
486 zix_sem_post (&self->access_sem);
487 }
488
489 static int
sort_events_func(const void * _a,const void * _b)490 sort_events_func (
491 const void * _a, const void * _b)
492 {
493 MidiEvent * a = (MidiEvent *) _a;
494 MidiEvent * b = (MidiEvent *) _b;
495
496 /* if same time put note ons first */
497 if (a->time == b->time)
498 {
499 return
500 a->type == MIDI_EVENT_TYPE_NOTE_ON ?
501 -1 : 1;
502 }
503
504 return (int) a->time - (int) b->time;
505 }
506
507 /**
508 * Sorts the MIDI events by time ascendingly.
509 */
510 void
midi_events_sort_by_time(MidiEvents * self)511 midi_events_sort_by_time (
512 MidiEvents * self)
513 {
514 qsort (
515 self->events, (size_t) self->num_events,
516 sizeof (MidiEvent), sort_events_func);
517 }
518
519 #ifdef HAVE_JACK
520 /**
521 * Writes the events to the given JACK buffer.
522 */
523 void
midi_events_copy_to_jack(MidiEvents * self,void * buff)524 midi_events_copy_to_jack (
525 MidiEvents * self,
526 void * buff)
527 {
528 jack_midi_clear_buffer (buff);
529
530 MidiEvent * ev;
531 jack_midi_data_t midi_data[3];
532 for (int i = 0; i < self->num_events; i++)
533 {
534 ev = &self->events[i];
535
536 for (size_t j = 0; j < ev->raw_buffer_sz;
537 j++)
538 {
539 midi_data[j] = ev->raw_buffer[j];
540 }
541 jack_midi_event_write (
542 buff, ev->time, midi_data,
543 ev->raw_buffer_sz);
544 #if 0
545 g_message (
546 "wrote MIDI event to JACK MIDI out at %d",
547 ev->time);
548 #endif
549 }
550 }
551 #endif
552
553 /**
554 * Adds a note off event to the given MidiEvents.
555 * FIXME should be wrapped in access sem?
556 *
557 * @param channel MIDI channel starting from 1.
558 * @param queued Add to queued events instead.
559 */
560 void
midi_events_add_note_off(MidiEvents * self,midi_byte_t channel,midi_byte_t note_pitch,midi_time_t time,int queued)561 midi_events_add_note_off (
562 MidiEvents * self,
563 midi_byte_t channel,
564 midi_byte_t note_pitch,
565 midi_time_t time,
566 int queued)
567 {
568 MidiEvent * ev;
569 if (queued)
570 ev =
571 &self->queued_events[self->num_queued_events];
572 else
573 ev =
574 &self->events[self->num_events];
575
576 ev->type = MIDI_EVENT_TYPE_NOTE_OFF;
577 ev->channel = channel;
578 ev->note_pitch = note_pitch;
579 ev->time = time;
580 ev->raw_buffer[0] =
581 (midi_byte_t)
582 (MIDI_CH1_NOTE_OFF | (channel - 1));
583 ev->raw_buffer[1] = note_pitch;
584 ev->raw_buffer[2] = 90;
585 ev->raw_buffer_sz = 3;
586
587 if (queued)
588 self->num_queued_events++;
589 else
590 self->num_events++;
591 }
592
593 void
midi_events_add_raw(MidiEvents * self,uint8_t * buf,size_t buf_sz,midi_time_t time,bool queued)594 midi_events_add_raw (
595 MidiEvents * self,
596 uint8_t * buf,
597 size_t buf_sz,
598 midi_time_t time,
599 bool queued)
600 {
601 if (buf_sz > 3)
602 {
603 print_unknown_event_message (buf, buf_sz);
604 g_return_if_reached ();
605 }
606
607 MidiEvent * ev;
608 if (queued)
609 ev =
610 &self->queued_events[self->num_queued_events];
611 else
612 ev =
613 &self->events[self->num_events];
614
615 ev->type = MIDI_EVENT_TYPE_RAW;
616 ev->channel = 0;
617 ev->controller = 0;
618 ev->control = 0;
619 ev->time = time;
620 for (size_t i = 0; i < buf_sz; i++)
621 {
622 ev->raw_buffer[i] = buf[i];
623 }
624
625 if (queued)
626 self->num_queued_events++;
627 else
628 self->num_events++;
629 }
630
631 /**
632 * Adds a control event to the given MidiEvents.
633 *
634 * @param channel MIDI channel starting from 1.
635 * @param queued Add to queued events instead.
636 */
637 void
midi_events_add_control_change(MidiEvents * self,uint8_t channel,uint8_t controller,uint8_t control,midi_time_t time,int queued)638 midi_events_add_control_change (
639 MidiEvents * self,
640 uint8_t channel,
641 uint8_t controller,
642 uint8_t control,
643 midi_time_t time,
644 int queued)
645 {
646 MidiEvent * ev;
647 if (queued)
648 ev =
649 &self->queued_events[self->num_queued_events];
650 else
651 ev =
652 &self->events[self->num_events];
653
654 ev->type = MIDI_EVENT_TYPE_CONTROLLER;
655 ev->channel = channel;
656 ev->controller = controller;
657 ev->control = control;
658 ev->time = time;
659 ev->raw_buffer[0] =
660 (midi_byte_t)
661 (MIDI_CH1_CTRL_CHANGE | (channel - 1));
662 ev->raw_buffer[1] = controller;
663 ev->raw_buffer[2] = control;
664 ev->raw_buffer_sz = 3;
665
666 if (queued)
667 self->num_queued_events++;
668 else
669 self->num_events++;
670 }
671
672 /**
673 * Adds a control event to the given MidiEvents.
674 *
675 * @param channel MIDI channel starting from 1.
676 * @param pitchbend -8192 to 8191
677 * @param queued Add to queued events instead.
678 */
679 void
midi_events_add_pitchbend(MidiEvents * self,midi_byte_t channel,int pitchbend,midi_time_t time,int queued)680 midi_events_add_pitchbend (
681 MidiEvents * self,
682 midi_byte_t channel,
683 int pitchbend,
684 midi_time_t time,
685 int queued)
686 {
687 MidiEvent * ev;
688 if (queued)
689 ev =
690 &self->queued_events[self->num_queued_events];
691 else
692 ev =
693 &self->events[self->num_events];
694
695 ev->type = MIDI_EVENT_TYPE_PITCHBEND;
696 ev->pitchbend = pitchbend;
697 ev->time = time;
698 ev->raw_buffer[0] =
699 (midi_byte_t)
700 (MIDI_CH1_PITCH_WHEEL_RANGE | (channel - 1));
701 midi_get_bytes_from_int (
702 pitchbend + 8192, &ev->raw_buffer[1],
703 &ev->raw_buffer[2]);
704 ev->raw_buffer_sz = 3;
705
706 if (queued)
707 self->num_queued_events++;
708 else
709 self->num_events++;
710 }
711
712 HOT
713 static int
midi_event_cmpfunc(const void * _a,const void * _b)714 midi_event_cmpfunc (
715 const void * _a,
716 const void * _b)
717 {
718 const MidiEvent * a =
719 (MidiEvent const *) _a;
720 const MidiEvent * b =
721 (MidiEvent const *) _b;
722 if (a->time == b->time)
723 {
724 return (int) a->type - (int) b->type;
725 }
726 return (int) a->time - (int) b->time;
727 }
728
729 /**
730 * Sorts the MidiEvents by time.
731 */
732 void
midi_events_sort(MidiEvents * self,const bool queued)733 midi_events_sort (
734 MidiEvents * self,
735 const bool queued)
736 {
737 MidiEvent * events;
738 size_t num_events;
739 if (queued)
740 {
741 events = self->queued_events;
742 num_events = (size_t) self->num_queued_events;
743 }
744 else
745 {
746 events = self->events;
747 num_events = (size_t) self->num_events;
748 }
749 qsort (
750 events, num_events, sizeof (MidiEvent),
751 midi_event_cmpfunc);
752 }
753
754 /**
755 * Adds a note on event to the given MidiEvents.
756 *
757 * @param channel MIDI channel starting from 1.
758 * @param queued Add to queued events instead.
759 */
760 void
midi_events_add_note_on(MidiEvents * self,uint8_t channel,uint8_t note_pitch,uint8_t velocity,midi_time_t time,int queued)761 midi_events_add_note_on (
762 MidiEvents * self,
763 uint8_t channel,
764 uint8_t note_pitch,
765 uint8_t velocity,
766 midi_time_t time,
767 int queued)
768 {
769 #if 0
770 g_message (
771 "%s: ch %"PRIu8", pitch %"PRIu8", vel %"PRIu8
772 ", time %"PRIu32,
773 __func__, channel, note_pitch, velocity, time);
774 #endif
775
776 MidiEvent * ev;
777 if (queued)
778 ev =
779 &self->queued_events[self->num_queued_events];
780 else
781 ev =
782 &self->events[self->num_events];
783
784 ev->type = MIDI_EVENT_TYPE_NOTE_ON;
785 ev->channel = channel;
786 ev->note_pitch = note_pitch;
787 ev->velocity = velocity;
788 ev->time = time;
789 ev->raw_buffer[0] =
790 (midi_byte_t)
791 (MIDI_CH1_NOTE_ON | (channel - 1));
792 ev->raw_buffer[1] = note_pitch;
793 ev->raw_buffer[2] = velocity;
794 ev->raw_buffer_sz = 3;
795
796 if (queued)
797 self->num_queued_events++;
798 else
799 self->num_events++;
800 }
801
802 /**
803 * Adds a note on for each note in the chord.
804 */
805 void
midi_events_add_note_ons_from_chord_descr(MidiEvents * self,ChordDescriptor * descr,midi_byte_t channel,midi_byte_t velocity,midi_time_t _time,bool queued)806 midi_events_add_note_ons_from_chord_descr (
807 MidiEvents * self,
808 ChordDescriptor * descr,
809 midi_byte_t channel,
810 midi_byte_t velocity,
811 midi_time_t _time,
812 bool queued)
813 {
814 #if 0
815 g_message (
816 "%s: vel %"PRIu8", time %"PRIu32,
817 __func__, velocity, _time);
818 #endif
819
820 for (int i = 0; i < CHORD_DESCRIPTOR_MAX_NOTES;
821 i++)
822 {
823 if (descr->notes[i])
824 {
825 midi_events_add_note_on (
826 self, channel, i + 36,
827 velocity, _time, queued);
828 }
829 }
830 }
831
832 /**
833 * Adds a note off for each note in the chord.
834 */
835 void
midi_events_add_note_offs_from_chord_descr(MidiEvents * self,ChordDescriptor * descr,midi_byte_t channel,midi_time_t time,bool queued)836 midi_events_add_note_offs_from_chord_descr (
837 MidiEvents * self,
838 ChordDescriptor * descr,
839 midi_byte_t channel,
840 midi_time_t time,
841 bool queued)
842 {
843 for (int i = 0; i < CHORD_DESCRIPTOR_MAX_NOTES;
844 i++)
845 {
846 if (descr->notes[i])
847 {
848 midi_events_add_note_off (
849 self, channel, i + 36, time, queued);
850 }
851 }
852 }
853
854 /**
855 * Parses a MidiEvent from a raw MIDI buffer.
856 *
857 * This must be a full 3-byte message. If in
858 * 'running status' mode, the caller is responsible
859 * for prepending the status byte.
860 */
861 REALTIME
862 void
midi_events_add_event_from_buf(MidiEvents * self,midi_time_t time,midi_byte_t * buf,int buf_size,int queued)863 midi_events_add_event_from_buf (
864 MidiEvents * self,
865 midi_time_t time,
866 midi_byte_t * buf,
867 int buf_size,
868 int queued)
869 {
870 #if 0
871 if (buf_size != 3)
872 {
873 g_debug (
874 "buf size of %d received (%"PRIu8" %"
875 PRIu8" %"PRIu8"), expected 3, skipping...",
876 buf_size > 0 ? buf[0] : 0,
877 buf_size > 1 ? buf[1] : 0,
878 buf_size > 2 ? buf[2] : 0, buf_size);
879 }
880 #endif
881
882 midi_byte_t type = buf[0] & 0xf0;
883 midi_byte_t channel =
884 (midi_byte_t) ((buf[0] & 0xf) + 1);
885 switch (type)
886 {
887 case MIDI_CH1_NOTE_ON:
888 /* velocity == 0 means note off */
889 if (buf[2] == 0)
890 goto note_off;
891
892 midi_events_add_note_on (
893 self, channel, buf[1], buf[2], time,
894 queued);
895 break;
896 case MIDI_CH1_NOTE_OFF:
897 note_off:
898 midi_events_add_note_off (
899 self, channel, buf[1], time, queued);
900 break;
901 case MIDI_CH1_PITCH_WHEEL_RANGE:
902 midi_events_add_pitchbend (
903 self, channel,
904 midi_combine_bytes_to_int (buf[1], buf[2]),
905 time, queued);
906 break;
907 case MIDI_SYSTEM_MESSAGE:
908 /* ignore active sensing */
909 if (buf[0] != 0xFE)
910 {
911 #if 0
912 print_unknown_event_message (
913 buf, buf_size);
914 #endif
915 }
916 break;
917 case MIDI_CH1_CTRL_CHANGE:
918 midi_events_add_control_change (
919 self, 1, buf[1], buf[2], time, queued);
920 break;
921 default:
922 midi_events_add_raw (
923 self, buf, (size_t) buf_size, time, queued);
924 break;
925 }
926 }
927
928 void
midi_events_delete_event(MidiEvents * self,const MidiEvent * ev,const bool queued)929 midi_events_delete_event (
930 MidiEvents * self,
931 const MidiEvent * ev,
932 const bool queued)
933 {
934 MidiEvent * arr =
935 queued ?
936 self->queued_events :
937 self->events;
938 #define NUM_EVENTS \
939 (queued ? self->num_queued_events : \
940 self->num_events)
941
942 for (int i = 0; i < NUM_EVENTS; i++)
943 {
944 MidiEvent * cur_ev = &arr[i];
945 if (cur_ev == ev)
946 {
947 for (int k = i; k < NUM_EVENTS - 1; k++)
948 {
949 midi_event_copy (
950 &arr[k + 1], &arr[k]);
951 }
952 if (queued)
953 self->num_queued_events--;
954 else
955 self->num_events--;
956 i--;
957 }
958 }
959 }
960
961 void
midi_event_set_velocity(MidiEvent * ev,midi_byte_t vel)962 midi_event_set_velocity (
963 MidiEvent * ev,
964 midi_byte_t vel)
965 {
966 ev->velocity = vel;
967 ev->raw_buffer[2] = vel;
968 }
969
970 void
midi_event_print(const MidiEvent * ev)971 midi_event_print (
972 const MidiEvent * ev)
973 {
974 char raw[300];
975 sprintf (raw, "Raw (%zu):", ev->raw_buffer_sz);
976 for (size_t i = 0; i < ev->raw_buffer_sz;
977 i++)
978 {
979 char part[20];
980 sprintf (
981 part, " %hhx", ev->raw_buffer[i]);
982 strcat (raw, part);
983 }
984
985 char msg[600];
986 sprintf (
987 msg,
988 "~MIDI EVENT~\n"
989 "Type: %s\n"
990 "Channel: %u\n"
991 "Pitch: %u\n"
992 "Velocity: %u\n"
993 "Time: %u\n"
994 "%s",
995 midi_event_type_strings[ev->type], ev->channel,
996 ev->note_pitch,
997 ev->velocity, ev->time, raw);
998
999 g_message ("%s", msg);
1000 }
1001
1002 int
midi_events_are_equal(const MidiEvent * src,const MidiEvent * dest)1003 midi_events_are_equal (
1004 const MidiEvent * src,
1005 const MidiEvent * dest)
1006 {
1007 int ret =
1008 dest->type == src->type &&
1009 dest->pitchbend == src->pitchbend &&
1010 dest->controller == src->controller &&
1011 dest->control == src->control &&
1012 dest->channel == src->channel &&
1013 dest->note_pitch == src->note_pitch &&
1014 (src->type != MIDI_EVENT_TYPE_NOTE_ON ||
1015 (src->type == MIDI_EVENT_TYPE_NOTE_ON &&
1016 dest->velocity == src->velocity)) &&
1017 dest->time == src->time &&
1018 dest->raw_buffer[0] == src->raw_buffer[0] &&
1019 dest->raw_buffer[1] == src->raw_buffer[1] &&
1020 dest->raw_buffer[2] == src->raw_buffer[2];
1021 return ret;
1022 }
1023
1024 void
midi_events_print(MidiEvents * self,const int queued)1025 midi_events_print (
1026 MidiEvents * self,
1027 const int queued)
1028 {
1029 MidiEvent * arr =
1030 queued ?
1031 self->queued_events :
1032 self->events;
1033 MidiEvent * ev1;
1034 #define NUM_EVENTS \
1035 (queued ? self->num_queued_events : \
1036 self->num_events)
1037
1038 int i;
1039 for (i = 0; i < NUM_EVENTS; i++)
1040 {
1041 ev1 = &arr[i];
1042 midi_event_print (ev1);
1043 }
1044 }
1045
1046 /**
1047 * Clears duplicates.
1048 *
1049 * @param queued Clear duplicates from queued events
1050 * instead.
1051 */
1052 void
midi_events_clear_duplicates(MidiEvents * self,const int queued)1053 midi_events_clear_duplicates (
1054 MidiEvents * self,
1055 const int queued)
1056 {
1057 MidiEvent * arr =
1058 queued ?
1059 self->queued_events :
1060 self->events;
1061 MidiEvent * ev1, * ev2;
1062 #define NUM_EVENTS \
1063 (queued ? self->num_queued_events : \
1064 self->num_events)
1065
1066 int i, j, k;
1067 for (i = 0; i < NUM_EVENTS; i++)
1068 {
1069 ev1 = &arr[i];
1070
1071 for (j = i + 1; j < NUM_EVENTS; j++)
1072 {
1073 ev2 = &arr[j];
1074
1075 if (midi_events_are_equal (ev1, ev2))
1076 {
1077 #if 0
1078 g_message (
1079 "removing duplicate MIDI event");
1080 #endif
1081 for (k = j; k < NUM_EVENTS; k++)
1082 {
1083 midi_event_copy (
1084 &arr[k], &arr[k + 1]);
1085 }
1086 if (queued)
1087 self->num_queued_events--;
1088 else
1089 self->num_events--;
1090 j--;
1091 }
1092 }
1093 }
1094 }
1095
1096 /**
1097 * Frees the MIDI events.
1098 */
1099 void
midi_events_free(MidiEvents * self)1100 midi_events_free (
1101 MidiEvents * self)
1102 {
1103 zix_sem_destroy (&self->access_sem);
1104
1105 object_zero_and_free (self);
1106 }
1107