1 /* GSequencer - Advanced GTK Sequencer
2 * Copyright (C) 2005-2021 Joël Krähemann
3 *
4 * This file is part of GSequencer.
5 *
6 * GSequencer is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU 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 * GSequencer 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 General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GSequencer. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <ags/audio/midi/ags_midi_buffer_util.h>
21
22 #include <alsa/seq_midi_event.h>
23 #include <alsa/seq_event.h>
24
25 #include <math.h>
26 #include <string.h>
27 #include <stdlib.h>
28
29 gpointer ags_midi_buffer_util_copy(gpointer ptr);
30 void ags_midi_buffer_util_free(gpointer ptr);
31
32 /**
33 * SECTION:ags_midi_buffer_util
34 * @short_description: MIDI buffer util
35 * @title: AgsMidiBufferUtil
36 * @section_id:
37 * @include: ags/audio/midi/ags_midi_buffer_util.h
38 *
39 * Utility functions for MIDI buffers.
40 */
41
42 GType
ags_midi_buffer_util_get_type(void)43 ags_midi_buffer_util_get_type(void)
44 {
45 static volatile gsize g_define_type_id__volatile = 0;
46
47 if(g_once_init_enter (&g_define_type_id__volatile)){
48 GType ags_type_midi_buffer_util = 0;
49
50 ags_type_midi_buffer_util =
51 g_boxed_type_register_static("AgsMidiBufferUtil",
52 (GBoxedCopyFunc) ags_midi_buffer_util_copy,
53 (GBoxedFreeFunc) ags_midi_buffer_util_free);
54
55 g_once_init_leave(&g_define_type_id__volatile, ags_type_midi_buffer_util);
56 }
57
58 return g_define_type_id__volatile;
59 }
60
61 gpointer
ags_midi_buffer_util_copy(gpointer ptr)62 ags_midi_buffer_util_copy(gpointer ptr)
63 {
64 gpointer retval;
65
66 retval = g_memdup(ptr, sizeof(AgsMidiBufferUtil));
67
68 return(retval);
69 }
70
71 void
ags_midi_buffer_util_free(gpointer ptr)72 ags_midi_buffer_util_free(gpointer ptr)
73 {
74 g_free(ptr);
75 }
76
77 /**
78 * ags_midi_buffer_util_get_varlength_size:
79 * @varlength: the variable length
80 *
81 * Retrieve the size needed to store the variable length.
82 *
83 * Returns: the size needed to be allocated
84 *
85 * Since: 3.0.0
86 */
87 guint
ags_midi_buffer_util_get_varlength_size(glong varlength)88 ags_midi_buffer_util_get_varlength_size(glong varlength)
89 {
90 guint current;
91 guchar c;
92 guint i;
93 glong mask;
94
95 /* retrieve new size */
96 mask = 0x7f;
97
98 current = 8 * 4 - 4;
99 i = current;
100
101 for(; current >= 8; ){
102 if(((mask << (i - 7)) & varlength) != 0){
103 break;
104 }
105
106 i -= 7;
107 current -= 8;
108 }
109
110 return(floor(current / 8.0) + 1);
111 }
112
113 /**
114 * ags_midi_buffer_util_put_varlength:
115 * @buffer: the character buffer
116 * @varlength: the value to put
117 *
118 * Put the variable lenght value to @buffer.
119 *
120 * Since: 3.0.0
121 */
122 void
ags_midi_buffer_util_put_varlength(guchar * buffer,glong varlength)123 ags_midi_buffer_util_put_varlength(guchar *buffer,
124 glong varlength)
125 {
126 guint varlength_size;
127 guint i, j;
128 glong mask;
129
130 if(buffer == NULL){
131 return;
132 }
133
134 varlength_size = ags_midi_buffer_util_get_varlength_size(varlength);
135
136 /* write to internal buffer */
137 mask = 0x7f;
138 j = 0;
139 i = 7 * varlength_size;
140
141 for(; j < varlength_size; ){
142 buffer[j] = ((mask << (i - 7)) & varlength) >> (i - 7);
143
144 if(j + 1 < varlength_size){
145 buffer[j] |= 0x80;
146 }
147
148 i -= 7;
149 j++;
150 }
151 }
152
153 /**
154 * ags_midi_buffer_util_get_varlength:
155 * @buffer: the character buffer
156 * @varlength: the return location
157 *
158 * Get the variable lenght value from @buffer.
159 *
160 * Returns: the number of bytes read.
161 *
162 * Since: 3.0.0
163 */
164 guint
ags_midi_buffer_util_get_varlength(guchar * buffer,glong * varlength)165 ags_midi_buffer_util_get_varlength(guchar *buffer,
166 glong *varlength)
167 {
168 glong value;
169 guint i;
170 char c;
171
172 if(buffer == NULL){
173 if(varlength != NULL){
174 *varlength = 0;
175 }
176
177 return(0);
178 }
179
180 c = buffer[0];
181 value = c;
182 i = 1;
183
184 if(c & 0x80){
185 value &= 0x7F;
186
187 do{
188 value = (value << 7) + ((c = buffer[i]) & 0x7F);
189 i++;
190 }while(c & 0x80);
191 }
192
193 if(varlength != NULL){
194 *varlength = value;
195 }
196
197 return(i);
198 }
199
200 /**
201 * ags_midi_buffer_util_put_int16:
202 * @buffer: the character buffer
203 * @val: the integer
204 *
205 * Put signed 16 bit integer.
206 *
207 * Since: 3.0.0
208 */
209 void
ags_midi_buffer_util_put_int16(guchar * buffer,glong val)210 ags_midi_buffer_util_put_int16(guchar *buffer,
211 glong val)
212 {
213 if(buffer == NULL){
214 return;
215 }
216
217 buffer[0] = (val & (0xff << 8)) >> 8;
218 buffer[1] = val & 0xff;
219 }
220
221 /**
222 * ags_midi_buffer_util_get_int16:
223 * @buffer: the character buffer
224 * @val: return location of the integer
225 *
226 * Get signed 32 bit integer.
227 *
228 * Since: 3.0.0
229 */
230 void
ags_midi_buffer_util_get_int16(guchar * buffer,glong * val)231 ags_midi_buffer_util_get_int16(guchar *buffer,
232 glong *val)
233 {
234 glong tmp;
235
236 if(buffer == NULL){
237 if(val != NULL){
238 *val = 0;
239 }
240
241 return;
242 }
243
244 tmp = (buffer[0] & 0xff);
245 tmp = (tmp << 8) + (buffer[1] & 0xff);
246
247 if(val != NULL){
248 *val = tmp;
249 }
250 }
251
252 /**
253 * ags_midi_buffer_util_put_int24:
254 * @buffer: the character buffer
255 * @val: the integer
256 *
257 * Put signed 24 bit integer.
258 *
259 * Since: 3.0.0
260 */
261 void
ags_midi_buffer_util_put_int24(guchar * buffer,glong val)262 ags_midi_buffer_util_put_int24(guchar *buffer,
263 glong val)
264 {
265 if(buffer == NULL){
266 return;
267 }
268
269 buffer[0] = (val & (0xff << 16)) >> 16;
270 buffer[1] = (val & (0xff << 8)) >> 8;
271 buffer[2] = val & 0xff;
272 }
273
274 /**
275 * ags_midi_buffer_util_get_int24:
276 * @buffer: the character buffer
277 * @val: return location of the integer
278 *
279 * Get signed 24 bit integer.
280 *
281 * Since: 3.0.0
282 */
283 void
ags_midi_buffer_util_get_int24(guchar * buffer,glong * val)284 ags_midi_buffer_util_get_int24(guchar *buffer,
285 glong *val)
286 {
287 glong tmp;
288
289 if(buffer == NULL){
290 if(val != NULL){
291 *val = 0;
292 }
293
294 return;
295 }
296
297 tmp = (buffer[0] & 0xff);
298 tmp = (tmp << 8) + (buffer[1] & 0xff);
299 tmp = (tmp << 8) + (buffer[2] & 0xff);
300
301 if(val != NULL){
302 *val = tmp;
303 }
304 }
305
306 /**
307 * ags_midi_buffer_util_put_int32:
308 * @buffer: the character buffer
309 * @val: the integer
310 *
311 * Put signed 32 bit integer.
312 *
313 * Since: 3.0.0
314 */
315 void
ags_midi_buffer_util_put_int32(guchar * buffer,glong val)316 ags_midi_buffer_util_put_int32(guchar *buffer,
317 glong val)
318 {
319 if(buffer == NULL){
320 return;
321 }
322
323 buffer[0] = (val & (0xff << 24)) >> 24;
324 buffer[1] = (val & (0xff << 16)) >> 16;
325 buffer[2] = (val & (0xff << 8)) >> 8;
326 buffer[3] = val & 0xff;
327 }
328
329 /**
330 * ags_midi_buffer_util_get_int32:
331 * @buffer: the character buffer
332 * @val: return location of the integer
333 *
334 * Get signed 32 bit integer.
335 *
336 * Since: 3.0.0
337 */
338 void
ags_midi_buffer_util_get_int32(guchar * buffer,glong * val)339 ags_midi_buffer_util_get_int32(guchar *buffer,
340 glong *val)
341 {
342 glong tmp;
343
344 if(buffer == NULL){
345 if(val != NULL){
346 *val = 0;
347 }
348
349 return;
350 }
351
352 tmp = (buffer[0] & 0xff);
353 tmp = (tmp << 8) + (buffer[1] & 0xff);
354 tmp = (tmp << 8) + (buffer[2] & 0xff);
355 tmp = (tmp << 8) + (buffer[3] & 0xff);
356
357 if(val != NULL){
358 *val = tmp;
359 }
360 }
361
362 /**
363 * ags_midi_buffer_util_put_header:
364 * @buffer: the character buffer
365 * @offset: start delta-time
366 * @format: either 0, 1 or 2.
367 * @track_count: the number of tracks
368 * @division: timing division
369 *
370 * Puts the midi header.
371 *
372 * Since: 3.0.0
373 */
374 void
ags_midi_buffer_util_put_header(guchar * buffer,glong offset,glong format,glong track_count,glong division)375 ags_midi_buffer_util_put_header(guchar *buffer,
376 glong offset, glong format,
377 glong track_count, glong division)
378 {
379 static gchar header[] = "MThd";
380
381 if(buffer == NULL){
382 return;
383 }
384
385 /* put MThd */
386 memcpy(buffer, header, 4 * sizeof(guchar));
387
388 /* chunk length */
389 ags_midi_buffer_util_put_int32(buffer + 4,
390 offset);
391
392 /* format */
393 ags_midi_buffer_util_put_int16(buffer + 8,
394 format);
395
396 /* track count */
397 ags_midi_buffer_util_put_int16(buffer + 10,
398 track_count);
399
400 /* division */
401 ags_midi_buffer_util_put_int16(buffer + 12,
402 division);
403 }
404
405 /**
406 * ags_midi_buffer_util_get_header:
407 * @buffer: the character buffer
408 * @offset: start delta-time
409 * @format: either 0, 1 or 2.
410 * @track_count: the number of tracks
411 * @division: timing division
412 *
413 * Gets the midi header
414 *
415 * Returns: the number of bytes read.
416 *
417 * Since: 3.0.0
418 */
419 guint
ags_midi_buffer_util_get_header(guchar * buffer,glong * offset,glong * format,glong * track_count,glong * division)420 ags_midi_buffer_util_get_header(guchar *buffer,
421 glong *offset, glong *format,
422 glong *track_count, glong *division)
423 {
424 static gchar header[] = "MThd";
425
426 if(buffer == NULL ||
427 (!g_ascii_strncasecmp(buffer,
428 header,
429 4)) == FALSE){
430 if(offset != NULL){
431 *offset = 0;
432 }
433
434 if(format != NULL){
435 *format = 0;
436 }
437
438 if(track_count != NULL){
439 *track_count = 0;
440 }
441
442 if(division != NULL){
443 *division = 0;
444 }
445
446 return(0);
447 }
448
449 /* offset */
450 ags_midi_buffer_util_get_int32(buffer + 4,
451 offset);
452
453 /* format */
454 ags_midi_buffer_util_get_int16(buffer + 8,
455 format);
456
457 /* track count */
458 ags_midi_buffer_util_get_int16(buffer + 10,
459 track_count);
460
461 /* division */
462 ags_midi_buffer_util_get_int16(buffer + 12,
463 division);
464
465 return(14);
466 }
467
468 /**
469 * ags_midi_buffer_util_put_track:
470 * @buffer: the midi buffer
471 * @offset: start delta-time
472 *
473 * Put track.
474 *
475 * Since: 3.0.0
476 */
477 void
ags_midi_buffer_util_put_track(guchar * buffer,glong offset)478 ags_midi_buffer_util_put_track(guchar *buffer,
479 glong offset)
480 {
481 static gchar track[] = "MTrk";
482
483 if(buffer == NULL){
484 return;
485 }
486
487 /* put MTrk */
488 memcpy(buffer, track, 4 * sizeof(guchar));
489
490 /* offset */
491 ags_midi_buffer_util_put_int32(buffer + 4,
492 offset);
493 }
494
495 /**
496 * ags_midi_buffer_util_get_track:
497 * @buffer: the midi buffer
498 * @offset: start delta-time
499 *
500 * Get track
501 *
502 * Returns: the number of bytes read.
503 *
504 * Since: 3.0.0
505 */
506 guint
ags_midi_buffer_util_get_track(guchar * buffer,glong * offset)507 ags_midi_buffer_util_get_track(guchar *buffer,
508 glong *offset)
509 {
510 static gchar track[] = "MTrk";
511
512 if(buffer == NULL ||
513 (!g_ascii_strncasecmp(buffer,
514 track,
515 4)) == FALSE){
516 if(offset != NULL){
517 *offset = 0;
518 }
519
520 return(0);
521 }
522
523 /* offset */
524 ags_midi_buffer_util_get_int32(buffer + 4,
525 offset);
526
527 return(8);
528 }
529
530 /**
531 * ags_midi_buffer_util_put_key_on:
532 * @buffer: the character buffer
533 * @delta_time: timing information
534 * @channel: valid channels from 0-15
535 * @key: valid keys to play 0-128
536 * @velocity: the key dynamics
537 *
538 * Puts the given values to @buffer with appropriate channel message.
539 *
540 * Since: 3.0.0
541 */
542 void
ags_midi_buffer_util_put_key_on(guchar * buffer,glong delta_time,glong channel,glong key,glong velocity)543 ags_midi_buffer_util_put_key_on(guchar *buffer,
544 glong delta_time,
545 glong channel,
546 glong key,
547 glong velocity)
548 {
549 guint delta_time_size;
550
551 if(buffer == NULL){
552 return;
553 }
554
555 /* delta time */
556 delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
557 ags_midi_buffer_util_put_varlength(buffer,
558 delta_time);
559
560 /* key-on channel message */
561 buffer[delta_time_size] = 0x90 | (channel & 0xf);
562
563 /* key */
564 buffer[delta_time_size + 1] = key & 0x7f;
565
566 /* velocity */
567 buffer[delta_time_size + 2] = velocity & 0x7f;
568 }
569
570 /**
571 * ags_midi_buffer_util_get_key_on:
572 * @buffer: the character buffer
573 * @delta_time: the return location of timing information
574 * @channel: the return location of channel
575 * @key: the return location of key
576 * @velocity: the return location of velocity
577 *
578 * Get the key-on message from @buffer.
579 *
580 * Returns: the number of bytes read.
581 *
582 * Since: 3.0.0
583 */
584 guint
ags_midi_buffer_util_get_key_on(guchar * buffer,glong * delta_time,glong * channel,glong * key,glong * velocity)585 ags_midi_buffer_util_get_key_on(guchar *buffer,
586 glong *delta_time,
587 glong *channel,
588 glong *key,
589 glong *velocity)
590 {
591 glong val;
592 guint delta_time_size;
593
594 if(buffer == NULL){
595 if(delta_time != NULL){
596 *delta_time = 0;
597 }
598
599 if(channel != NULL){
600 *channel = 0;
601 }
602
603 if(key != NULL){
604 *key = 0;
605 }
606
607 if(velocity != NULL){
608 *velocity = 0;
609 }
610
611 return(0);
612 }
613
614 /* delta time */
615 delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
616 &val);
617
618 if(delta_time != NULL){
619 *delta_time = val;
620 }
621
622 /* channel */
623 if(channel != NULL){
624 *channel = (0xf & buffer[delta_time_size]);
625 }
626
627 /* key */
628 if(key != NULL){
629 *key = (0x7f & buffer[delta_time_size + 1]);
630 }
631
632 /* velocity */
633 if(velocity != NULL){
634 *velocity = (0x7f & buffer[delta_time_size + 2]);
635 }
636
637 return(delta_time_size + 3);
638 }
639
640 /**
641 * ags_midi_buffer_util_put_key_off:
642 * @buffer: the character buffer
643 * @delta_time: timing information
644 * @channel: valid channels from 0-15
645 * @key: valid keys to play 0-128
646 * @velocity: the key dynamics
647 *
648 * Puts the given values to @buffer with appropriate channel message.
649 *
650 * Since: 3.0.0
651 */
652 void
ags_midi_buffer_util_put_key_off(guchar * buffer,glong delta_time,glong channel,glong key,glong velocity)653 ags_midi_buffer_util_put_key_off(guchar *buffer,
654 glong delta_time,
655 glong channel,
656 glong key,
657 glong velocity)
658 {
659 guint delta_time_size;
660
661 if(buffer == NULL){
662 return;
663 }
664
665 /* delta time */
666 delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
667 ags_midi_buffer_util_put_varlength(buffer,
668 delta_time);
669
670 /* key-off channel message */
671 buffer[delta_time_size] = 0x80;
672 buffer[delta_time_size] |= (channel & 0xf);
673
674 /* key */
675 buffer[delta_time_size + 1] = key & 0x7f;
676
677 /* velocity */
678 buffer[delta_time_size + 2] = velocity & 0x7f;
679 }
680
681 /**
682 * ags_midi_buffer_util_get_key_off:
683 * @buffer: the character buffer
684 * @delta_time: the return location of timing information
685 * @channel: the return location of channel
686 * @key: the return location of key
687 * @velocity: the return location of velocity
688 *
689 * Get the key-off message from @buffer.
690 *
691 * Returns: the number of bytes read.
692 *
693 * Since: 3.0.0
694 */
695 guint
ags_midi_buffer_util_get_key_off(guchar * buffer,glong * delta_time,glong * channel,glong * key,glong * velocity)696 ags_midi_buffer_util_get_key_off(guchar *buffer,
697 glong *delta_time,
698 glong *channel,
699 glong *key,
700 glong *velocity)
701 {
702 glong val;
703 guint delta_time_size;
704
705 if(buffer == NULL){
706 if(delta_time != NULL){
707 *delta_time = 0;
708 }
709
710 if(channel != NULL){
711 *channel = 0;
712 }
713
714 if(key != NULL){
715 *key = 0;
716 }
717
718 if(velocity != NULL){
719 *velocity = 0;
720 }
721
722 return(0);
723 }
724
725 /* delta time */
726 delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
727 &val);
728
729 if(delta_time != NULL){
730 *delta_time = val;
731 }
732
733 /* channel */
734 if(channel != NULL){
735 *channel = (0xf & buffer[delta_time_size]);
736 }
737
738 /* key */
739 if(key != NULL){
740 *key = (0x7f & buffer[delta_time_size + 1]);
741 }
742
743 /* velocity */
744 if(velocity != NULL){
745 *velocity = (0x7f & buffer[delta_time_size + 2]);
746 }
747
748 return(delta_time_size + 3);
749 }
750
751 /**
752 * ags_midi_buffer_util_put_key_pressure:
753 * @buffer: the character buffer
754 * @delta_time: timing information
755 * @channel: valid channels from 0-15
756 * @key: valid keys to play 0-128
757 * @pressure: the key dynamics
758 *
759 * Puts the given values to @buffer with appropriate channel message.
760 *
761 * Since: 3.0.0
762 */
763 void
ags_midi_buffer_util_put_key_pressure(guchar * buffer,glong delta_time,glong channel,glong key,glong pressure)764 ags_midi_buffer_util_put_key_pressure(guchar *buffer,
765 glong delta_time,
766 glong channel,
767 glong key,
768 glong pressure)
769 {
770 guint delta_time_size;
771
772 if(buffer == NULL){
773 return;
774 }
775
776 /* delta time */
777 delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
778 ags_midi_buffer_util_put_varlength(buffer,
779 delta_time);
780
781 /* key-pressure channel message */
782 buffer[delta_time_size] = 0xa0;
783 buffer[delta_time_size] |= (channel & 0xf);
784
785 /* key */
786 buffer[delta_time_size + 1] = key & 0x7f;
787
788 /* pressure */
789 buffer[delta_time_size + 2] = pressure & 0x7f;
790 }
791
792 /**
793 * ags_midi_buffer_util_get_key_pressure:
794 * @buffer: the character buffer
795 * @delta_time: the return location of timing information
796 * @channel: the return location of channel
797 * @key: the return location of key
798 * @pressure: the return location of pressure
799 *
800 * Get the key-pressure message from @buffer.
801 *
802 * Returns: the number of bytes read.
803 *
804 * Since: 3.0.0
805 */
806 guint
ags_midi_buffer_util_get_key_pressure(guchar * buffer,glong * delta_time,glong * channel,glong * key,glong * pressure)807 ags_midi_buffer_util_get_key_pressure(guchar *buffer,
808 glong *delta_time,
809 glong *channel,
810 glong *key,
811 glong *pressure)
812 {
813 glong val;
814 guint delta_time_size;
815
816 if(buffer == NULL){
817 if(delta_time != NULL){
818 *delta_time = 0;
819 }
820
821 if(channel != NULL){
822 *channel = 0;
823 }
824
825 if(key != NULL){
826 *key = 0;
827 }
828
829 if(pressure != NULL){
830 *pressure = 0;
831 }
832
833 return(0);
834 }
835
836 /* delta time */
837 delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
838 &val);
839
840 if(delta_time != NULL){
841 *delta_time = val;
842 }
843
844 /* channel */
845 if(channel != NULL){
846 *channel = (0xf & buffer[delta_time_size]);
847 }
848
849 /* key */
850 if(key != NULL){
851 *key = (0x7f & buffer[delta_time_size + 1]);
852 }
853
854 /* pressure */
855 if(pressure != NULL){
856 *pressure = (0x7f & buffer[delta_time_size + 2]);
857 }
858
859 return(delta_time_size + 3);
860 }
861
862 /**
863 * ags_midi_buffer_util_put_change_parameter:
864 * @buffer: the character buffer
865 * @delta_time: timing information
866 * @channel: channel
867 * @control: the control
868 * @value: the value
869 *
870 * Put change parameter.
871 *
872 * Since: 3.0.0
873 */
874 void
ags_midi_buffer_util_put_change_parameter(guchar * buffer,glong delta_time,glong channel,glong control,glong value)875 ags_midi_buffer_util_put_change_parameter(guchar *buffer,
876 glong delta_time,
877 glong channel,
878 glong control,
879 glong value)
880 {
881 guint delta_time_size;
882
883 if(buffer == NULL){
884 return;
885 }
886
887 /* delta time */
888 delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
889 ags_midi_buffer_util_put_varlength(buffer,
890 delta_time);
891
892 /* change-parameter channel message */
893 buffer[delta_time_size] = 0xb0;
894 buffer[delta_time_size] |= (channel & 0xf);
895
896 /* control */
897 buffer[delta_time_size + 1] = 0x7f & control;
898
899 /* value */
900 buffer[delta_time_size + 2] = 0x7f & value;
901 }
902
903 /**
904 * ags_midi_buffer_util_get_change_parameter:
905 * @buffer: the character buffer
906 * @delta_time: the return location of timing information
907 * @channel: the return location of channel
908 * @control: the return location of the control
909 * @value: the return location the value
910 *
911 * Get change parameter.
912 *
913 * Returns: the number of bytes read.
914 *
915 * Since: 3.0.0
916 */
917 guint
ags_midi_buffer_util_get_change_parameter(guchar * buffer,glong * delta_time,glong * channel,glong * control,glong * value)918 ags_midi_buffer_util_get_change_parameter(guchar *buffer,
919 glong *delta_time,
920 glong *channel,
921 glong *control,
922 glong *value)
923 {
924 glong val;
925 guint delta_time_size;
926
927 if(buffer == NULL){
928 if(delta_time != NULL){
929 *delta_time = 0;
930 }
931
932 if(channel != NULL){
933 *channel = 0;
934 }
935
936 if(control != NULL){
937 *control = 0;
938 }
939
940 if(value != NULL){
941 *value = 0;
942 }
943
944 return(0);
945 }
946
947 /* delta time */
948 delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
949 &val);
950
951 if(delta_time != NULL){
952 *delta_time = val;
953 }
954
955 /* channel */
956 if(channel != NULL){
957 *channel = (0xf & buffer[delta_time_size]);
958 }
959
960 /* control */
961 if(control != NULL){
962 *control = 0x7f & buffer[delta_time_size + 1];
963 }
964
965 /* value */
966 if(value != NULL){
967 *value = 0x7f & buffer[delta_time_size + 2];
968 }
969
970 return(delta_time_size + 3);
971 }
972
973 /**
974 * ags_midi_buffer_util_put_pitch_bend:
975 * @buffer: the character buffer
976 * @delta_time: timing information
977 * @channel: channel
978 * @pitch: the pitch
979 * @transmitter: the transmitter
980 *
981 * Put pitch bend.
982 *
983 * Since: 3.0.0
984 */
985 void
ags_midi_buffer_util_put_pitch_bend(guchar * buffer,glong delta_time,glong channel,glong pitch,glong transmitter)986 ags_midi_buffer_util_put_pitch_bend(guchar *buffer,
987 glong delta_time,
988 glong channel,
989 glong pitch,
990 glong transmitter)
991 {
992 guint delta_time_size;
993
994 if(buffer == NULL){
995 return;
996 }
997
998 /* delta time */
999 delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1000 ags_midi_buffer_util_put_varlength(buffer,
1001 delta_time);
1002
1003 /* pitch-bend channel message */
1004 buffer[delta_time_size] = 0xe0;
1005 buffer[delta_time_size] |= (channel & 0xf);
1006
1007 /* pitch */
1008 buffer[delta_time_size + 1] = 0x7f & pitch;
1009
1010 /* transmitter */
1011 buffer[delta_time_size + 2] = 0x7f & transmitter;
1012 }
1013
1014 /**
1015 * ags_midi_buffer_util_get_pitch_bend:
1016 * @buffer: the character buffer
1017 * @delta_time: the return location of timing information
1018 * @channel: the return location of channel
1019 * @pitch: the return location of the pitch
1020 * @transmitter: the return location the transmitter
1021 *
1022 * Get pitch bend.
1023 *
1024 * Returns: the number of bytes read.
1025 *
1026 * Since: 3.0.0
1027 */
1028 guint
ags_midi_buffer_util_get_pitch_bend(guchar * buffer,glong * delta_time,glong * channel,glong * pitch,glong * transmitter)1029 ags_midi_buffer_util_get_pitch_bend(guchar *buffer,
1030 glong *delta_time,
1031 glong *channel,
1032 glong *pitch,
1033 glong *transmitter)
1034 {
1035 glong val;
1036 guint delta_time_size;
1037
1038 if(buffer == NULL){
1039 if(delta_time != NULL){
1040 *delta_time = 0;
1041 }
1042
1043 if(channel != NULL){
1044 *channel = 0;
1045 }
1046
1047 if(pitch != NULL){
1048 *pitch = 0;
1049 }
1050
1051 if(transmitter != NULL){
1052 *transmitter = 0;
1053 }
1054
1055 return(0);
1056 }
1057
1058 /* delta time */
1059 delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
1060 &val);
1061
1062 if(delta_time != NULL){
1063 *delta_time = val;
1064 }
1065
1066 /* channel */
1067 if(channel != NULL){
1068 *channel = (0xf & buffer[delta_time_size]);
1069 }
1070
1071 /* pitch */
1072 if(pitch != NULL){
1073 *pitch = 0x7f & buffer[delta_time_size + 1];
1074 }
1075
1076 /* transmitter */
1077 if(transmitter != NULL){
1078 *transmitter = 0x7f & buffer[delta_time_size + 2];
1079 }
1080
1081 return(delta_time_size + 3);
1082 }
1083
1084 /**
1085 * ags_midi_buffer_util_put_change_program:
1086 * @buffer: the character buffer
1087 * @delta_time: timing information
1088 * @channel: channel
1089 * @program: the program
1090 *
1091 * Put change program.
1092 *
1093 * Since: 3.0.0
1094 */
1095 void
ags_midi_buffer_util_put_change_program(guchar * buffer,glong delta_time,glong channel,glong program)1096 ags_midi_buffer_util_put_change_program(guchar *buffer,
1097 glong delta_time,
1098 glong channel,
1099 glong program)
1100 {
1101 guint delta_time_size;
1102
1103 if(buffer == NULL){
1104 return;
1105 }
1106
1107 /* delta time */
1108 delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1109 ags_midi_buffer_util_put_varlength(buffer,
1110 delta_time);
1111
1112 /* change-parameter channel message */
1113 buffer[delta_time_size] = 0xc0;
1114 buffer[delta_time_size] |= (channel & 0xf);
1115
1116 /* program */
1117 buffer[delta_time_size + 1] = 0x7f & program;
1118 }
1119
1120 /**
1121 * ags_midi_buffer_util_get_change_program:
1122 * @buffer: the character buffer
1123 * @delta_time: the return location of timing information
1124 * @channel: the return location of channel
1125 * @program: the return location of the program
1126 *
1127 * Get change program.
1128 *
1129 * Returns: the number of bytes read.
1130 *
1131 * Since: 3.0.0
1132 */
1133 guint
ags_midi_buffer_util_get_change_program(guchar * buffer,glong * delta_time,glong * channel,glong * program)1134 ags_midi_buffer_util_get_change_program(guchar *buffer,
1135 glong *delta_time,
1136 glong *channel,
1137 glong *program)
1138 {
1139 glong val;
1140 guint delta_time_size;
1141
1142 if(buffer == NULL){
1143 if(delta_time != NULL){
1144 *delta_time = 0;
1145 }
1146
1147 if(channel != NULL){
1148 *channel = 0;
1149 }
1150
1151 if(program != NULL){
1152 *program = 0;
1153 }
1154
1155 return(0);
1156 }
1157
1158 /* delta time */
1159 delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
1160 &val);
1161
1162 if(delta_time != NULL){
1163 *delta_time = val;
1164 }
1165
1166 /* channel */
1167 if(channel != NULL){
1168 *channel = (0xf & buffer[delta_time_size]);
1169 }
1170
1171 /* program */
1172 if(program != NULL){
1173 *program = 0x7f & buffer[delta_time_size + 1];
1174 }
1175
1176 return(delta_time_size + 2);
1177 }
1178
1179 /**
1180 * ags_midi_buffer_util_put_change_pressure:
1181 * @buffer: the character buffer
1182 * @delta_time: timing information
1183 * @channel: channel
1184 * @pressure: the pressure
1185 *
1186 * Put change pressure.
1187 *
1188 * Since: 3.0.0
1189 */
1190 void
ags_midi_buffer_util_put_change_pressure(guchar * buffer,glong delta_time,glong channel,glong pressure)1191 ags_midi_buffer_util_put_change_pressure(guchar *buffer,
1192 glong delta_time,
1193 glong channel,
1194 glong pressure)
1195 {
1196 guint delta_time_size;
1197
1198 if(buffer == NULL){
1199 return;
1200 }
1201
1202 /* delta time */
1203 delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1204 ags_midi_buffer_util_put_varlength(buffer,
1205 delta_time);
1206
1207 /* change-parameter channel message */
1208 buffer[delta_time_size] = 0xd0;
1209 buffer[delta_time_size] |= (channel & 0xf);
1210
1211 /* pressure */
1212 buffer[delta_time_size + 1] = 0x7f & pressure;
1213 }
1214
1215 /**
1216 * ags_midi_buffer_util_get_change_pressure:
1217 * @buffer: the character buffer
1218 * @delta_time: the return location of timing information
1219 * @channel: the return location of channel
1220 * @pressure: the return location of the pressure
1221 *
1222 * Get change pressure.
1223 *
1224 * Returns: the number of bytes read.
1225 *
1226 * Since: 3.0.0
1227 */
1228 guint
ags_midi_buffer_util_get_change_pressure(guchar * buffer,glong * delta_time,glong * channel,glong * pressure)1229 ags_midi_buffer_util_get_change_pressure(guchar *buffer,
1230 glong *delta_time,
1231 glong *channel,
1232 glong *pressure)
1233 {
1234 glong val;
1235 guint delta_time_size;
1236
1237 if(buffer == NULL){
1238 if(delta_time != NULL){
1239 *delta_time = 0;
1240 }
1241
1242 if(channel != NULL){
1243 *channel = 0;
1244 }
1245
1246 if(pressure != NULL){
1247 *pressure = 0;
1248 }
1249
1250 return(0);
1251 }
1252
1253 /* delta time */
1254 delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
1255 &val);
1256
1257 if(delta_time != NULL){
1258 *delta_time = val;
1259 }
1260
1261 /* channel */
1262 if(channel != NULL){
1263 *channel = (0xf & buffer[delta_time_size]);
1264 }
1265
1266 /* pressure */
1267 if(pressure != NULL){
1268 *pressure = 0x7f & buffer[delta_time_size + 1];
1269 }
1270
1271 return(delta_time_size + 2);
1272 }
1273
1274 /**
1275 * ags_midi_buffer_util_put_sysex:
1276 * @buffer: the character buffer
1277 * @delta_time: timing information
1278 * @data: the data
1279 * @length: the data's length
1280 *
1281 * Put sysex.
1282 *
1283 * Since: 3.0.0
1284 */
1285 void
ags_midi_buffer_util_put_sysex(guchar * buffer,glong delta_time,guchar * data,glong length)1286 ags_midi_buffer_util_put_sysex(guchar *buffer,
1287 glong delta_time,
1288 guchar *data, glong length)
1289 {
1290 guint delta_time_size;
1291
1292 if(buffer == NULL){
1293 return;
1294 }
1295
1296 /* delta time */
1297 delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1298 ags_midi_buffer_util_put_varlength(buffer,
1299 delta_time);
1300
1301 /* status byte */
1302 buffer[delta_time_size] = 0xf0;
1303
1304 /* put data */
1305 memcpy(buffer + delta_time_size + 1, data, length * sizeof(guchar));
1306
1307 /* EOX end of sysex */
1308 buffer[delta_time_size + length + 1] = 0xf7;
1309 }
1310
1311 /**
1312 * ags_midi_buffer_util_get_sysex:
1313 * @buffer: the character buffer
1314 * @delta_time: the return location of timing information
1315 * @data: the return location of data
1316 * @length: the return location of length
1317 *
1318 * Get sysex.
1319 *
1320 * Returns: the number of bytes read.
1321 *
1322 * Since: 3.0.0
1323 */
1324 guint
ags_midi_buffer_util_get_sysex(guchar * buffer,glong * delta_time,guchar ** data,glong * length)1325 ags_midi_buffer_util_get_sysex(guchar *buffer,
1326 glong *delta_time,
1327 guchar **data, glong *length)
1328 {
1329 guchar *tmp_data;
1330
1331 glong val;
1332 guint delta_time_size;
1333 guint i;
1334
1335 if(buffer == NULL){
1336 if(delta_time != NULL){
1337 *delta_time = 0;
1338 }
1339
1340 if(data != NULL){
1341 *data = NULL;
1342 }
1343
1344 if(length != NULL){
1345 *length = 0;
1346 }
1347
1348 return(0);
1349 }
1350
1351 /* delta time */
1352 delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
1353 &val);
1354
1355 if(delta_time != NULL){
1356 *delta_time = val;
1357 }
1358
1359 for(i = 0; buffer[delta_time_size + i + 1] != 0xf7; i++);
1360
1361 if(data != NULL){
1362 if(i > 0){
1363 tmp_data = (guchar *) malloc(i * sizeof(guchar));
1364 }else{
1365 tmp_data = NULL;
1366 }
1367
1368 memcpy(tmp_data, buffer + delta_time_size + 1, i * sizeof(guchar));
1369
1370 *data = tmp_data;
1371 }
1372
1373 if(length != NULL){
1374 *length = i;
1375 }
1376
1377 return(delta_time_size + i + 2);
1378 }
1379
1380 /**
1381 * ags_midi_buffer_util_put_quarter_frame:
1382 * @buffer: the character buffer
1383 * @delta_time: timing information
1384 * @message_type: the message type
1385 * @values: the values
1386 *
1387 * Put quarter frame.
1388 *
1389 * Since: 3.0.0
1390 */
1391 void
ags_midi_buffer_util_put_quarter_frame(guchar * buffer,glong delta_time,glong message_type,glong values)1392 ags_midi_buffer_util_put_quarter_frame(guchar *buffer,
1393 glong delta_time,
1394 glong message_type,
1395 glong values)
1396 {
1397 guint delta_time_size;
1398
1399 if(buffer == NULL){
1400 return;
1401 }
1402
1403 /* delta time */
1404 delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1405 ags_midi_buffer_util_put_varlength(buffer,
1406 delta_time);
1407
1408 /* status byte */
1409 buffer[delta_time_size] = 0xf1;
1410
1411 /* message type */
1412 buffer[delta_time_size + 1] = 0x70 & message_type;
1413
1414 /* values */
1415 buffer[delta_time_size + 1] |= 0x0f & values;
1416 }
1417
1418 /**
1419 * ags_midi_buffer_util_get_quarter_frame:
1420 * @buffer: the character buffer
1421 * @delta_time: the return location of timing information
1422 * @message_type: the return location of the message type
1423 * @values: the return location of the values
1424 *
1425 * Get quarter frame.
1426 *
1427 * Returns: the number of bytes read.
1428 *
1429 * Since: 3.0.0
1430 */
1431 guint
ags_midi_buffer_util_get_quarter_frame(guchar * buffer,glong * delta_time,glong * message_type,glong * values)1432 ags_midi_buffer_util_get_quarter_frame(guchar *buffer,
1433 glong *delta_time,
1434 glong *message_type, glong *values)
1435 {
1436 glong val;
1437 guint delta_time_size;
1438
1439 if(buffer == NULL){
1440 if(delta_time != NULL){
1441 *delta_time = 0;
1442 }
1443
1444 if(message_type != NULL){
1445 *message_type = 0;
1446 }
1447
1448 if(values != NULL){
1449 *values = 0;
1450 }
1451
1452 return(0);
1453 }
1454
1455 /* delta time */
1456 delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
1457 &val);
1458
1459 if(delta_time != NULL){
1460 *delta_time = val;
1461 }
1462
1463 if(message_type != NULL){
1464 *message_type = 0x70 & buffer[delta_time_size + 1];
1465 }
1466
1467 if(values != NULL){
1468 *values = 0x0f & buffer[delta_time_size + 1];
1469 }
1470
1471 return(delta_time_size + 2);
1472 }
1473
1474 /**
1475 * ags_midi_buffer_util_put_song_position:
1476 * @buffer: the character buffer
1477 * @delta_time: timing information
1478 * @song_position: the song position
1479 *
1480 * Put song position.
1481 *
1482 * Since: 3.0.0
1483 */
1484 void
ags_midi_buffer_util_put_song_position(guchar * buffer,glong delta_time,glong song_position)1485 ags_midi_buffer_util_put_song_position(guchar *buffer,
1486 glong delta_time,
1487 glong song_position)
1488 {
1489 guint delta_time_size;
1490
1491 if(buffer == NULL){
1492 return;
1493 }
1494
1495 /* delta time */
1496 delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1497 ags_midi_buffer_util_put_varlength(buffer,
1498 delta_time);
1499
1500 /* status byte */
1501 buffer[delta_time_size] = 0xf2;
1502
1503 /* song position */
1504 buffer[delta_time_size + 1] = 0x7f & song_position;
1505 buffer[delta_time_size + 2] = 0x7f & (song_position >> 7);
1506 }
1507
1508 /**
1509 * ags_midi_buffer_util_get_song_position:
1510 * @buffer: the character buffer
1511 * @delta_time: the return location of timing information
1512 * @song_position: the return location of the song position
1513 *
1514 * Get song position.
1515 *
1516 * Returns: the number of bytes read.
1517 *
1518 * Since: 3.0.0
1519 */
1520 guint
ags_midi_buffer_util_get_song_position(guchar * buffer,glong * delta_time,glong * song_position)1521 ags_midi_buffer_util_get_song_position(guchar *buffer,
1522 glong *delta_time,
1523 glong *song_position)
1524 {
1525 glong val;
1526 guint delta_time_size;
1527
1528 if(buffer == NULL){
1529 if(delta_time != NULL){
1530 *delta_time = 0;
1531 }
1532
1533 if(song_position != NULL){
1534 *song_position = 0;
1535 }
1536
1537 return(0);
1538 }
1539
1540 /* delta time */
1541 delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
1542 &val);
1543
1544 if(delta_time != NULL){
1545 *delta_time = val;
1546 }
1547
1548 /* song position */
1549 if(song_position != NULL){
1550 *song_position = 0x7f & buffer[delta_time_size + 1];
1551 *song_position |= ((0x7f & buffer[delta_time_size + 2]) << 7);
1552 }
1553
1554 return(delta_time_size + 3);
1555 }
1556
1557 /**
1558 * ags_midi_buffer_util_put_song_select:
1559 * @buffer: the character buffer
1560 * @delta_time: timing information
1561 * @song_select: the song select
1562 *
1563 * Put song select.
1564 *
1565 * Since: 3.0.0
1566 */
1567 void
ags_midi_buffer_util_put_song_select(guchar * buffer,glong delta_time,glong song_select)1568 ags_midi_buffer_util_put_song_select(guchar *buffer,
1569 glong delta_time,
1570 glong song_select)
1571 {
1572 guint delta_time_size;
1573
1574 if(buffer == NULL){
1575 return;
1576 }
1577
1578 /* delta time */
1579 delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1580 ags_midi_buffer_util_put_varlength(buffer,
1581 delta_time);
1582
1583 /* status byte */
1584 buffer[delta_time_size] = 0xf3;
1585
1586 /* song select */
1587 buffer[delta_time_size + 1] = 0x7f & song_select;
1588 }
1589
1590 /**
1591 * ags_midi_buffer_util_get_song_select:
1592 * @buffer: the character buffer
1593 * @delta_time: the return location of timing information
1594 * @song_select: the return location of the song select
1595 *
1596 * Get song select.
1597 *
1598 * Returns: the number of bytes read.
1599 *
1600 * Since: 3.0.0
1601 */
1602 guint
ags_midi_buffer_util_get_song_select(guchar * buffer,glong * delta_time,glong * song_select)1603 ags_midi_buffer_util_get_song_select(guchar *buffer,
1604 glong *delta_time,
1605 glong *song_select)
1606 {
1607 glong val;
1608 guint delta_time_size;
1609
1610 if(buffer == NULL){
1611 if(delta_time != NULL){
1612 *delta_time = 0;
1613 }
1614
1615 if(song_select != NULL){
1616 *song_select = 0;
1617 }
1618
1619 return(0);
1620 }
1621
1622 /* delta time */
1623 delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
1624 &val);
1625
1626 if(delta_time != NULL){
1627 *delta_time = val;
1628 }
1629
1630 if(song_select != NULL){
1631 *song_select = 0x7f & buffer[delta_time_size + 1];
1632 }
1633
1634 return(delta_time_size + 2);
1635 }
1636
1637 /**
1638 * ags_midi_buffer_util_put_tune_request:
1639 * @buffer: the character buffer
1640 * @delta_time: timing information
1641 *
1642 * Put tune request
1643 *
1644 * Since: 3.0.0
1645 */
1646 void
ags_midi_buffer_util_put_tune_request(guchar * buffer,glong delta_time)1647 ags_midi_buffer_util_put_tune_request(guchar *buffer,
1648 glong delta_time)
1649 {
1650 guint delta_time_size;
1651
1652 if(buffer == NULL){
1653 return;
1654 }
1655
1656 /* delta time */
1657 delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1658 ags_midi_buffer_util_put_varlength(buffer,
1659 delta_time);
1660
1661 /* status byte */
1662 buffer[delta_time_size] = 0xf6;
1663 }
1664
1665 /**
1666 * ags_midi_buffer_util_get_tune_request:
1667 * @buffer: the character buffer
1668 * @delta_time: the return location of timing information
1669 *
1670 * Get tune request.
1671 *
1672 * Returns: the number of bytes read.
1673 *
1674 * Since: 3.0.0
1675 */
1676 guint
ags_midi_buffer_util_get_tune_request(guchar * buffer,glong * delta_time)1677 ags_midi_buffer_util_get_tune_request(guchar *buffer,
1678 glong *delta_time)
1679 {
1680 glong val;
1681 guint delta_time_size;
1682
1683 if(buffer == NULL){
1684 if(delta_time != NULL){
1685 *delta_time = 0;
1686 }
1687
1688 return(0);
1689 }
1690
1691 /* delta time */
1692 delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
1693 &val);
1694
1695 if(delta_time != NULL){
1696 *delta_time = val;
1697 }
1698
1699 return(delta_time_size + 1);
1700 }
1701
1702 /**
1703 * ags_midi_buffer_util_put_sequence_number:
1704 * @buffer: the character buffer
1705 * @delta_time: timing information
1706 * @sequence: the sequence
1707 *
1708 * Put sequence number.
1709 *
1710 * Since: 3.0.0
1711 */
1712 void
ags_midi_buffer_util_put_sequence_number(guchar * buffer,glong delta_time,glong sequence)1713 ags_midi_buffer_util_put_sequence_number(guchar *buffer,
1714 glong delta_time,
1715 glong sequence)
1716 {
1717 guint delta_time_size;
1718
1719 if(buffer == NULL){
1720 return;
1721 }
1722
1723 /* delta time */
1724 delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1725 ags_midi_buffer_util_put_varlength(buffer,
1726 delta_time);
1727
1728 /* status byte */
1729 buffer[delta_time_size] = 0xff;
1730
1731 /* type */
1732 buffer[delta_time_size + 1] = 0x00;
1733
1734 /* length */
1735 buffer[delta_time_size + 2] = 2;
1736
1737 /* data */
1738 buffer[delta_time_size + 3] = ((0xff00 & sequence) >> 8);
1739 buffer[delta_time_size + 4] = 0xff & sequence;
1740 }
1741
1742 /**
1743 * ags_midi_buffer_util_get_sequence_number:
1744 * @buffer: the character buffer
1745 * @delta_time: the return location of timing information
1746 * @sequence: the return location of the sequence
1747 *
1748 * Get sequence number.
1749 *
1750 * Returns: the number of bytes read.
1751 *
1752 * Since: 3.0.0
1753 */
1754 guint
ags_midi_buffer_util_get_sequence_number(guchar * buffer,glong * delta_time,glong * sequence)1755 ags_midi_buffer_util_get_sequence_number(guchar *buffer,
1756 glong *delta_time,
1757 glong *sequence)
1758 {
1759 glong val;
1760 guint delta_time_size;
1761
1762 if(buffer == NULL){
1763 if(delta_time != NULL){
1764 *delta_time = 0;
1765 }
1766
1767 if(sequence != NULL){
1768 *sequence = 0;
1769 }
1770
1771 return(0);
1772 }
1773
1774 /* delta time */
1775 delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
1776 &val);
1777
1778 if(delta_time != NULL){
1779 *delta_time = val;
1780 }
1781
1782 /* sequence */
1783 if(sequence != NULL){
1784 *sequence = buffer[delta_time_size + 3] << 8;
1785 *sequence |= buffer[delta_time_size + 4];
1786 }
1787
1788 return(delta_time_size + 5);
1789 }
1790
1791 /**
1792 * ags_midi_buffer_util_put_smtpe:
1793 * @buffer: the character buffer
1794 * @delta_time: timing information
1795 * @rr: frame rate
1796 * @hr: hour
1797 * @mn: minute
1798 * @se: second
1799 * @fr: frame number
1800 *
1801 * Put smtpe timestamp.
1802 *
1803 * Since: 3.0.0
1804 */
1805 void
ags_midi_buffer_util_put_smtpe(guchar * buffer,glong delta_time,glong rr,glong hr,glong mn,glong se,glong fr)1806 ags_midi_buffer_util_put_smtpe(guchar *buffer,
1807 glong delta_time,
1808 glong rr, glong hr, glong mn, glong se, glong fr)
1809 {
1810 guint delta_time_size;
1811
1812 if(buffer == NULL){
1813 return;
1814 }
1815
1816 /* delta time */
1817 delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1818 ags_midi_buffer_util_put_varlength(buffer,
1819 delta_time);
1820
1821 /* status byte */
1822 buffer[delta_time_size] = 0xff;
1823
1824 /* type */
1825 buffer[delta_time_size + 1] = 0x54;
1826
1827 /* length */
1828 buffer[delta_time_size + 2] = 5;
1829
1830 /* rr */
1831 buffer[delta_time_size + 3] = rr;
1832
1833 /* hr */
1834 buffer[delta_time_size + 3] |= hr;
1835
1836 /* mn */
1837 buffer[delta_time_size + 4] = mn;
1838
1839 /* se */
1840 buffer[delta_time_size + 5] = se;
1841
1842 /* fr */
1843 buffer[delta_time_size + 6] = fr;
1844 }
1845
1846 /**
1847 * ags_midi_buffer_util_get_smtpe:
1848 * @buffer: the character buffer
1849 * @delta_time: the return location of timing information
1850 * @rr: the return location of frame rate
1851 * @hr: the return location of hour
1852 * @mn: the return location of minute
1853 * @se: the return location of second
1854 * @fr: the return location of frame number
1855 *
1856 * Get smtpe timestamp.
1857 *
1858 * Returns: the number of bytes read.
1859 *
1860 * Since: 3.0.0
1861 */
1862 guint
ags_midi_buffer_util_get_smtpe(guchar * buffer,glong * delta_time,glong * rr,glong * hr,glong * mn,glong * se,glong * fr)1863 ags_midi_buffer_util_get_smtpe(guchar *buffer,
1864 glong *delta_time,
1865 glong *rr, glong *hr, glong *mn, glong *se, glong *fr)
1866 {
1867 glong val;
1868 guint delta_time_size;
1869
1870 if(buffer == NULL){
1871 if(delta_time != NULL){
1872 *delta_time = 0;
1873 }
1874
1875 if(rr != NULL){
1876 *rr = 0;
1877 }
1878
1879 if(hr != NULL){
1880 *hr = 0;
1881 }
1882
1883 if(mn != NULL){
1884 *mn = 0;
1885 }
1886
1887 if(se != NULL){
1888 *se = 0;
1889 }
1890
1891 if(fr != NULL){
1892 *fr = 0;
1893 }
1894
1895 return(0);
1896 }
1897
1898 /* delta time */
1899 delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
1900 &val);
1901
1902 if(delta_time != NULL){
1903 *delta_time = val;
1904 }
1905
1906 /* rr */
1907 if(rr != NULL){
1908 *rr = 0xc0 & buffer[delta_time_size + 3];
1909 }
1910
1911 /* hr */
1912 if(hr != NULL){
1913 *hr = 0x3f & buffer[delta_time_size + 3];
1914 }
1915
1916 /* mn */
1917 if(mn != NULL){
1918 *mn = buffer[delta_time_size + 4];
1919 }
1920
1921 /* se */
1922 if(se != NULL){
1923 *se = buffer[delta_time_size + 5];
1924 }
1925
1926 /* fr */
1927 if(fr != NULL){
1928 *fr = buffer[delta_time_size + 6];
1929 }
1930
1931 return(delta_time_size + 7);
1932 }
1933
1934 /**
1935 * ags_midi_buffer_util_put_tempo:
1936 * @buffer: the character buffer
1937 * @delta_time: timing information
1938 * @tempo: the tempo
1939 *
1940 * Put tempo.
1941 *
1942 * Since: 3.0.0
1943 */
1944 void
ags_midi_buffer_util_put_tempo(guchar * buffer,glong delta_time,glong tempo)1945 ags_midi_buffer_util_put_tempo(guchar *buffer,
1946 glong delta_time,
1947 glong tempo)
1948 {
1949 guint delta_time_size;
1950
1951 if(buffer == NULL){
1952 return;
1953 }
1954
1955 /* delta time */
1956 delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1957 ags_midi_buffer_util_put_varlength(buffer,
1958 delta_time);
1959
1960 /* status byte */
1961 buffer[delta_time_size] = 0xff;
1962
1963 /* type */
1964 buffer[delta_time_size + 1] = 0x51;
1965
1966 /* length */
1967 buffer[delta_time_size + 2] = 0x03;
1968
1969 /* tempo */
1970 ags_midi_buffer_util_put_int24(buffer + delta_time_size + 3,
1971 tempo);
1972 }
1973
1974 /**
1975 * ags_midi_buffer_util_get_tempo:
1976 * @buffer: the character buffer
1977 * @delta_time: the return location of timing information
1978 * @tempo: the tempo
1979 *
1980 * Get tempo.
1981 *
1982 * Returns: the number of bytes read.
1983 *
1984 * Since: 3.0.0
1985 */
1986 guint
ags_midi_buffer_util_get_tempo(guchar * buffer,glong * delta_time,glong * tempo)1987 ags_midi_buffer_util_get_tempo(guchar *buffer,
1988 glong *delta_time,
1989 glong *tempo)
1990 {
1991 glong val;
1992 guint delta_time_size;
1993
1994 if(buffer == NULL){
1995 if(delta_time != NULL){
1996 *delta_time = 0;
1997 }
1998
1999 if(tempo != NULL){
2000 *tempo = 0;
2001 }
2002
2003 return(0);
2004 }
2005
2006 /* delta time */
2007 delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
2008 &val);
2009
2010 if(delta_time != NULL){
2011 *delta_time = val;
2012 }
2013
2014 /* tempo */
2015 ags_midi_buffer_util_get_int24(buffer + delta_time_size + 3,
2016 tempo);
2017
2018 return(delta_time_size + 6);
2019 }
2020
2021 /**
2022 * ags_midi_buffer_util_put_time_signature:
2023 * @buffer: the character buffer
2024 * @delta_time: timing information
2025 * @nn: numerator
2026 * @dd: denominator
2027 * @cc: clocks
2028 * @bb: beats
2029 *
2030 * Put time signature
2031 *
2032 * Since: 3.0.0
2033 */
2034 void
ags_midi_buffer_util_put_time_signature(guchar * buffer,glong delta_time,glong nn,glong dd,glong cc,glong bb)2035 ags_midi_buffer_util_put_time_signature(guchar *buffer,
2036 glong delta_time,
2037 glong nn, glong dd, glong cc, glong bb)
2038 {
2039 guint delta_time_size;
2040
2041 if(buffer == NULL){
2042 return;
2043 }
2044
2045 /* delta time */
2046 delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
2047 ags_midi_buffer_util_put_varlength(buffer,
2048 delta_time);
2049
2050 /* status byte */
2051 buffer[delta_time_size] = 0xff;
2052
2053 /* type */
2054 buffer[delta_time_size + 1] = 0x58;
2055
2056 /* length */
2057 buffer[delta_time_size + 2] = 0x4;
2058
2059 /* nn */
2060 buffer[delta_time_size + 3] = nn;
2061
2062 /* dd */
2063 buffer[delta_time_size + 4] = dd;
2064
2065 /* cc */
2066 buffer[delta_time_size + 5] = cc;
2067
2068 /* bb */
2069 buffer[delta_time_size + 6] = bb;
2070 }
2071
2072 /**
2073 * ags_midi_buffer_util_get_time_signature:
2074 * @buffer: the character buffer
2075 * @delta_time: the return location of timing information
2076 * @nn: the return location of numerator
2077 * @dd: the return location of denominator
2078 * @cc: the return location of clocks
2079 * @bb: the return location of beats
2080 *
2081 * Get time signature.
2082 *
2083 * Returns: the number of bytes read.
2084 *
2085 * Since: 3.0.0
2086 */
2087 guint
ags_midi_buffer_util_get_time_signature(guchar * buffer,glong * delta_time,glong * nn,glong * dd,glong * cc,glong * bb)2088 ags_midi_buffer_util_get_time_signature(guchar *buffer,
2089 glong *delta_time,
2090 glong *nn, glong *dd, glong *cc, glong *bb)
2091 {
2092 glong val;
2093 guint delta_time_size;
2094
2095 if(buffer == NULL){
2096 if(delta_time != NULL){
2097 *delta_time = 0;
2098 }
2099
2100 if(nn != NULL){
2101 *nn = 0;
2102 }
2103
2104 if(dd != NULL){
2105 *dd = 0;
2106 }
2107
2108 if(cc != NULL){
2109 *cc = 0;
2110 }
2111
2112 if(bb != NULL){
2113 *bb = 0;
2114 }
2115
2116 return(0);
2117 }
2118
2119 /* delta time */
2120 delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
2121 &val);
2122
2123 if(delta_time != NULL){
2124 *delta_time = val;
2125 }
2126
2127 /* nn */
2128 if(nn != NULL){
2129 *nn = buffer[delta_time_size + 3];
2130 }
2131
2132 /* dd */
2133 if(dd != NULL){
2134 *dd = buffer[delta_time_size + 4];
2135 }
2136
2137 /* cc */
2138 if(cc != NULL){
2139 *cc = buffer[delta_time_size + 5];
2140 }
2141
2142 /* bb */
2143 if(bb != NULL){
2144 *bb = buffer[delta_time_size + 6];
2145 }
2146
2147 return(delta_time_size + 7);
2148 }
2149
2150 /**
2151 * ags_midi_buffer_util_put_key_signature:
2152 * @buffer: the character buffer
2153 * @delta_time: timing information
2154 * @sf: flats or sharps
2155 * @mi: 1 equals minor or 0 means major
2156 *
2157 * Put key signature.
2158 *
2159 * Since: 3.0.0
2160 */
2161 void
ags_midi_buffer_util_put_key_signature(guchar * buffer,glong delta_time,glong sf,glong mi)2162 ags_midi_buffer_util_put_key_signature(guchar *buffer,
2163 glong delta_time,
2164 glong sf, glong mi)
2165 {
2166 guint delta_time_size;
2167
2168 if(buffer == NULL){
2169 return;
2170 }
2171
2172 /* delta time */
2173 delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
2174 ags_midi_buffer_util_put_varlength(buffer,
2175 delta_time);
2176
2177 /* status byte */
2178 buffer[delta_time_size] = 0xff;
2179
2180 /* type */
2181 buffer[delta_time_size + 1] = 0x59;
2182
2183 /* length */
2184 buffer[delta_time_size + 2] = 2;
2185
2186 /* sf */
2187 buffer[delta_time_size + 3] = sf;
2188
2189 /* mi */
2190 buffer[delta_time_size + 4] = mi;
2191 }
2192
2193 /**
2194 * ags_midi_buffer_util_get_key_signature:
2195 * @buffer: the character buffer
2196 * @delta_time: the return location of timing information
2197 * @sf: the return location of flats or sharps
2198 * @mi: the return location of minor or major
2199 *
2200 * Get key signature.
2201 *
2202 * Returns: the number of bytes read.
2203 *
2204 * Since: 3.0.0
2205 */
2206 guint
ags_midi_buffer_util_get_key_signature(guchar * buffer,glong * delta_time,glong * sf,glong * mi)2207 ags_midi_buffer_util_get_key_signature(guchar *buffer,
2208 glong *delta_time,
2209 glong *sf, glong *mi)
2210 {
2211 glong val;
2212 guint delta_time_size;
2213
2214 if(buffer == NULL){
2215 if(delta_time != NULL){
2216 *delta_time = 0;
2217 }
2218
2219 if(sf != NULL){
2220 *sf = 0;
2221 }
2222
2223 if(mi != NULL){
2224 *mi = 0;
2225 }
2226
2227 return(0);
2228 }
2229
2230 /* delta time */
2231 delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
2232 &val);
2233
2234 if(delta_time != NULL){
2235 *delta_time = val;
2236 }
2237
2238 /* sf */
2239 if(sf != NULL){
2240 *sf = buffer[delta_time_size + 3];
2241 }
2242
2243 /* mi */
2244 if(mi != NULL){
2245 *mi = buffer[delta_time_size + 4];
2246 }
2247
2248 return(delta_time_size + 5);
2249 }
2250
2251 /**
2252 * ags_midi_buffer_util_put_sequencer_meta_event:
2253 * @buffer: the character buffer
2254 * @delta_time: timing information
2255 * @len: the length of data
2256 * @id: the manufacturer id
2257 * @data: the data
2258 *
2259 * Put sequencer meta event.
2260 *
2261 * Since: 3.0.0
2262 */
2263 void
ags_midi_buffer_util_put_sequencer_meta_event(guchar * buffer,glong delta_time,glong len,glong id,glong data)2264 ags_midi_buffer_util_put_sequencer_meta_event(guchar *buffer,
2265 glong delta_time,
2266 glong len, glong id, glong data)
2267 {
2268 guint delta_time_size;
2269
2270 if(buffer == NULL){
2271 return;
2272 }
2273
2274 /* delta time */
2275 delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
2276 ags_midi_buffer_util_put_varlength(buffer,
2277 delta_time);
2278
2279 /* status byte */
2280 buffer[delta_time_size] = 0xff;
2281
2282 /* type */
2283 buffer[delta_time_size + 1] = 0x7f;
2284
2285 /* length */
2286 buffer[delta_time_size + 2] = 0xff & len;
2287
2288 /* id */
2289 buffer[delta_time_size + 3] = 0xff & id;
2290
2291 /* data */
2292 switch(len){
2293 case 3:
2294 {
2295 buffer[delta_time_size + 6] = ((0xff << 16) & data) >> 16;
2296 }
2297 case 2:
2298 {
2299 buffer[delta_time_size + 4] = 0xff & data;
2300 buffer[delta_time_size + 5] = ((0xff << 8) & data) >> 8;
2301 }
2302 }
2303 }
2304
2305 /**
2306 * ags_midi_buffer_util_get_sequencer_meta_event:
2307 * @buffer: the character buffer
2308 * @delta_time: the return location of timing information
2309 * @len: the return location of the length of data
2310 * @id: the return location of the manufacturer id
2311 * @data: the return location of the data
2312 *
2313 * Get sequencer meta event.
2314 *
2315 * Returns: the number of bytes read.
2316 *
2317 * Since: 3.0.0
2318 */
2319 guint
ags_midi_buffer_util_get_sequencer_meta_event(guchar * buffer,glong * delta_time,glong * len,glong * id,glong * data)2320 ags_midi_buffer_util_get_sequencer_meta_event(guchar *buffer,
2321 glong *delta_time,
2322 glong *len, glong *id, glong *data)
2323 {
2324 glong val;
2325 guint delta_time_size;
2326
2327 if(buffer == NULL){
2328 if(delta_time != NULL){
2329 *delta_time = 0;
2330 }
2331
2332 if(len != NULL){
2333 *len = 0;
2334 }
2335
2336 if(id != NULL){
2337 *id = 0;
2338 }
2339
2340 if(data != NULL){
2341 *data = 0;
2342 }
2343
2344 return(0);
2345 }
2346
2347 /* delta time */
2348 delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
2349 &val);
2350
2351 if(delta_time != NULL){
2352 *delta_time = val;
2353 }
2354
2355 if(len != NULL){
2356 len[0] = buffer[delta_time_size + 2];
2357 }
2358
2359 if(id != NULL){
2360 *id = buffer[delta_time_size + 3];
2361 }
2362
2363 if(data != NULL){
2364 *data = 0;
2365
2366 switch(buffer[delta_time_size + 2]){
2367 case 3:
2368 {
2369 *data |= (buffer[delta_time_size + 6] << 16);
2370 }
2371 case 2:
2372 {
2373 *data |= buffer[delta_time_size + 4];
2374 *data |= (buffer[delta_time_size + 5] << 8);
2375 }
2376 }
2377 }
2378
2379 return(delta_time_size + buffer[delta_time_size + 2] + 3);
2380 }
2381
2382 /**
2383 * ags_midi_buffer_util_put_text_event:
2384 * @buffer: the character buffer
2385 * @delta_time: timing information
2386 * @text: the text
2387 * @length: the length
2388 *
2389 * Put text event.
2390 *
2391 * Since: 3.0.0
2392 */
2393 void
ags_midi_buffer_util_put_text_event(guchar * buffer,glong delta_time,gchar * text,glong length)2394 ags_midi_buffer_util_put_text_event(guchar *buffer,
2395 glong delta_time,
2396 gchar *text, glong length)
2397 {
2398 guint delta_time_size;
2399
2400 if(buffer == NULL){
2401 return;
2402 }
2403
2404 /* delta time */
2405 delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
2406 ags_midi_buffer_util_put_varlength(buffer,
2407 delta_time);
2408
2409 /* status byte */
2410 buffer[delta_time_size] = 0xff;
2411
2412 /* type */
2413 buffer[delta_time_size + 1] = 0x01;
2414
2415 /* length */
2416 buffer[delta_time_size + 2] = 0xff & length;
2417
2418 /* text */
2419 memcpy(buffer + delta_time_size + 3, text, length * sizeof(guchar));
2420 }
2421
2422 /**
2423 * ags_midi_buffer_util_get_text_event:
2424 * @buffer: the character buffer
2425 * @delta_time: the return location of timing information
2426 * @text: the return location of the text
2427 * @length: the return location of the length
2428 *
2429 * Get text event.
2430 *
2431 * Returns: the number of bytes read.
2432 *
2433 * Since: 3.0.0
2434 */
2435 guint
ags_midi_buffer_util_get_text_event(guchar * buffer,glong * delta_time,gchar ** text,glong * length)2436 ags_midi_buffer_util_get_text_event(guchar *buffer,
2437 glong *delta_time,
2438 gchar **text, glong *length)
2439 {
2440 glong val;
2441 guint text_size;
2442 guint delta_time_size;
2443
2444 if(buffer == NULL){
2445 if(delta_time != NULL){
2446 *delta_time = 0;
2447 }
2448
2449 if(text != NULL){
2450 *text = NULL;
2451 }
2452
2453 if(length != NULL){
2454 *length = 0;
2455 }
2456
2457 return(0);
2458 }
2459
2460 /* delta time */
2461 delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
2462 &val);
2463
2464 if(delta_time != NULL){
2465 *delta_time = val;
2466 }
2467
2468 /* length */
2469 text_size = 0x7f & buffer[delta_time_size + 2];
2470
2471 if(length != NULL){
2472 *length = text_size;
2473 }
2474
2475 /* text */
2476 if(text != NULL){
2477 text[0] = (gchar *) malloc(text_size * sizeof(gchar));
2478 memcpy(text[0], buffer + delta_time_size + 3, text_size * sizeof(gchar));
2479 }
2480
2481 return(delta_time_size + text_size + 3);
2482 }
2483
2484 /**
2485 * ags_midi_buffer_util_put_end_of_track:
2486 * @buffer: the character buffer
2487 * @delta_time: timing information
2488 *
2489 * Put end of track.
2490 *
2491 * Since: 3.0.0
2492 */
2493 void
ags_midi_buffer_util_put_end_of_track(guchar * buffer,glong delta_time)2494 ags_midi_buffer_util_put_end_of_track(guchar *buffer,
2495 glong delta_time)
2496 {
2497 guint delta_time_size;
2498
2499 if(buffer == NULL){
2500 return;
2501 }
2502
2503 /* delta time */
2504 delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
2505 ags_midi_buffer_util_put_varlength(buffer,
2506 delta_time);
2507
2508 /* status byte */
2509 buffer[delta_time_size] = 0xff;
2510
2511 /* type */
2512 buffer[delta_time_size + 1] = 0x2f;
2513
2514 /* length */
2515 buffer[delta_time_size + 2] = 0;
2516 }
2517
2518 /**
2519 * ags_midi_buffer_util_get_end_of_track:
2520 * @buffer: the character buffer
2521 * @delta_time: the return location of timing information
2522 *
2523 * Get end of track.
2524 *
2525 * Returns: the number of bytes read.
2526 *
2527 * Since: 3.0.0
2528 */
2529 guint
ags_midi_buffer_util_get_end_of_track(guchar * buffer,glong * delta_time)2530 ags_midi_buffer_util_get_end_of_track(guchar *buffer,
2531 glong *delta_time)
2532 {
2533 glong val;
2534 guint delta_time_size;
2535
2536 if(buffer == NULL){
2537 if(delta_time != NULL){
2538 *delta_time = 0;
2539 }
2540
2541 return(0);
2542 }
2543
2544 /* delta time */
2545 delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
2546 &val);
2547
2548 if(delta_time != NULL){
2549 *delta_time = val;
2550 }
2551
2552 return(delta_time_size + 3);
2553 }
2554
2555 /**
2556 * ags_midi_buffer_util_seek_message:
2557 * @buffer: the buffer to seek
2558 * @message_count: seek count messages
2559 * @delta_time: the return location of current delta time
2560 *
2561 * Seek MIDI messages from @buffer
2562 *
2563 * Returns: the buffer at offset at @message_count ahead
2564 *
2565 * Since: 3.0.0
2566 */
2567 guchar*
ags_midi_buffer_util_seek_message(guchar * buffer,guint message_count,glong * delta_time)2568 ags_midi_buffer_util_seek_message(guchar *buffer,
2569 guint message_count,
2570 glong *delta_time)
2571 {
2572 static const gchar header[] = "MThd";
2573 static const gchar track[] = "MTrk";
2574
2575 guchar *offset;
2576
2577 glong current_delta_time, tmp_delta_time;
2578 glong next_delta_time;
2579 guint delta_time_size;
2580 guchar status, prev_status;
2581 guchar meta_type;
2582 guint n;
2583 guint i;
2584 gboolean initial_run;
2585
2586 if(buffer == NULL){
2587 return(NULL);
2588 }
2589
2590 offset = buffer;
2591
2592 /* check for header */
2593 if(!g_ascii_strncasecmp(offset,
2594 header,
2595 4)){
2596 offset += 14;
2597 }
2598
2599 /* seek message count */
2600 current_delta_time = 0;
2601 initial_run = TRUE;
2602
2603 prev_status = 0;
2604
2605 for(i = 0; i < message_count; i++){
2606 /* check for track */
2607 if(initial_run){
2608 if(!g_ascii_strncasecmp(offset,
2609 track,
2610 4)){
2611 offset += 8;
2612 }
2613
2614 initial_run = FALSE;
2615 }
2616
2617 /* read delta time */
2618 tmp_delta_time = 0;
2619
2620 delta_time_size = ags_midi_buffer_util_get_varlength(offset,
2621 &tmp_delta_time);
2622
2623 if(delta_time_size > 0){
2624 current_delta_time = tmp_delta_time;
2625 }
2626
2627 /* read status byte */
2628 status = offset[delta_time_size];
2629
2630 n = 1;
2631 ags_midi_buffer_util_seek_message_REPEAT_STATUS:
2632
2633 if((0xf0 & status) != 0xf0){
2634 switch(status & 0xf0){
2635 case 0x80:
2636 {
2637 n += delta_time_size + 2;
2638
2639 prev_status = status;
2640 }
2641 break;
2642 case 0x90:
2643 {
2644 n += delta_time_size + 2;
2645
2646 prev_status = status;
2647 }
2648 break;
2649 case 0xa0:
2650 {
2651 n += delta_time_size + 2;
2652
2653 prev_status = status;
2654 }
2655 break;
2656 case 0xb0:
2657 {
2658 n += delta_time_size + 2;
2659
2660 prev_status = status;
2661 }
2662 break;
2663 case 0xc0:
2664 {
2665 n += delta_time_size + 1;
2666
2667 prev_status = status;
2668 }
2669 break;
2670 case 0xd0:
2671 {
2672 n += delta_time_size + 1;
2673
2674 prev_status = status;
2675 }
2676 break;
2677 case 0xe0:
2678 {
2679 n += delta_time_size + 2;
2680
2681 prev_status = status;
2682 }
2683 break;
2684 default:
2685 {
2686 #ifdef AGS_DEBUG
2687 g_message("repeat status=0x%x", prev_status);
2688 #endif
2689 status = prev_status;
2690
2691 goto ags_midi_buffer_util_seek_message_REPEAT_STATUS;
2692 }
2693 }
2694
2695 offset += n;
2696
2697 /* check if status is omitted */
2698 next_delta_time = 0;
2699
2700 delta_time_size = ags_midi_buffer_util_get_varlength(offset,
2701 &next_delta_time);
2702
2703 if((0xf0 & offset[delta_time_size]) != 0xf0){
2704 switch(status & 0xf0){
2705 case 0x80:
2706 case 0x90:
2707 case 0xa0:
2708 case 0xb0:
2709 case 0xc0:
2710 case 0xd0:
2711 case 0xe0:
2712 break;
2713 default:
2714 {
2715 n = 0;
2716 current_delta_time = next_delta_time;
2717
2718 goto ags_midi_buffer_util_seek_message_REPEAT_STATUS;
2719 }
2720 }
2721 }
2722 }else{
2723 status = offset[delta_time_size];
2724
2725 switch(status){
2726 case 0xf0:
2727 {
2728 /* start of system exclusive */
2729 n = ags_midi_buffer_util_get_sysex(offset,
2730 NULL,
2731 NULL, NULL);
2732
2733 offset += n;
2734 }
2735 break;
2736 case 0xf1:
2737 {
2738 /* quarter frame */
2739 n = ags_midi_buffer_util_get_quarter_frame(offset,
2740 NULL,
2741 NULL, NULL);
2742
2743 offset += n;
2744 }
2745 break;
2746 case 0xf2:
2747 {
2748 /* song position */
2749 n = ags_midi_buffer_util_get_song_position(offset,
2750 NULL,
2751 NULL);
2752
2753 offset += n;
2754 }
2755 break;
2756 case 0xf3:
2757 {
2758 /* song select */
2759 n = ags_midi_buffer_util_get_song_select(offset,
2760 NULL,
2761 NULL);
2762
2763 offset += n;
2764 }
2765 break;
2766 case 0xf4:
2767 case 0xf5:
2768 {
2769 #ifdef AGS_DEBUG
2770 g_message("undefined");
2771 #endif
2772
2773 offset += delta_time_size;
2774 }
2775 break;
2776 case 0xf6:
2777 {
2778 /* tune request */
2779 n = ags_midi_buffer_util_get_tune_request(offset,
2780 NULL);
2781
2782 offset += n;
2783 }
2784 break;
2785 case 0xf7:
2786 {
2787 /* sysex continuation or arbitrary stuff */
2788 #ifdef AGS_DEBUG
2789 g_message("sysex end");
2790 #endif
2791 }
2792 break;
2793 case 0xff:
2794 {
2795 guint meta_type;
2796
2797 meta_type = offset[delta_time_size + 1];
2798
2799
2800
2801 switch(meta_type){
2802 case 0x00:
2803 {
2804 int c;
2805
2806 // c = offset[delta_time_size + 1];
2807
2808 // if(c == 0x02){
2809 n = ags_midi_buffer_util_get_sequence_number(offset,
2810 NULL,
2811 NULL);
2812
2813 offset += n;
2814 // }
2815 }
2816 break;
2817 case 0x01: /* Text event */
2818 case 0x02: /* Copyright notice */
2819 case 0x03: /* Sequence/Track name */
2820 case 0x04: /* Instrument name */
2821 case 0x05: /* Lyric */
2822 case 0x06: /* Marker */
2823 case 0x07: /* Cue point */
2824 case 0x08:
2825 case 0x09:
2826 case 0x0a:
2827 case 0x0b:
2828 case 0x0c:
2829 case 0x0d:
2830 case 0x0e:
2831 case 0x0f:
2832 {
2833 /* These are all text events */
2834 n = ags_midi_buffer_util_get_text_event(offset,
2835 NULL,
2836 NULL, NULL);
2837
2838 offset += n;
2839 }
2840 break;
2841 case 0x2f:
2842 {
2843 int c;
2844
2845 // c = buffer[delta_time_size];
2846
2847 // if(c == 0x0){
2848 /* End of Track */
2849 n = ags_midi_buffer_util_get_end_of_track(offset,
2850 NULL);
2851
2852 offset = NULL;
2853 }
2854 break;
2855 case 0x51:
2856 {
2857 int c;
2858
2859 // c = offset[delta_time_size];
2860
2861 // if(c == 0x03){
2862 /* Set tempo */
2863 n = ags_midi_buffer_util_get_tempo(offset,
2864 NULL,
2865 NULL);
2866
2867 offset += n;
2868 // }
2869 }
2870 break;
2871 case 0x54:
2872 {
2873 int c;
2874
2875 c = offset[delta_time_size];
2876
2877 // if(c == 0x05){
2878 n = ags_midi_buffer_util_get_smtpe(offset,
2879 NULL,
2880 NULL, NULL, NULL, NULL, NULL);
2881
2882 offset += n;
2883 // }
2884 }
2885 break;
2886 case 0x58:
2887 {
2888 int c;
2889
2890 // c = ags_midi_parser_midi_getc(midi_parser);
2891
2892 n = ags_midi_buffer_util_get_time_signature(offset,
2893 NULL,
2894 NULL, NULL, NULL, NULL);
2895
2896 offset += n;
2897
2898 // if(c == 0x04){
2899 // }
2900 }
2901 break;
2902 case 0x59:
2903 {
2904 int c;
2905
2906 // c = offset[delta_time_size];
2907
2908 // if(c == 0x02){
2909 n = ags_midi_buffer_util_get_key_signature(offset,
2910 NULL,
2911 NULL, NULL);
2912
2913 offset += n;
2914 // }
2915 }
2916 break;
2917 case 0x7f:
2918 {
2919 n = ags_midi_buffer_util_get_sequencer_meta_event(NULL,
2920 NULL,
2921 NULL, NULL, NULL);
2922
2923 offset += n;
2924 }
2925 break;
2926 default:
2927 offset += 5;
2928 }
2929 }
2930 break;
2931 default:
2932 g_warning("bad byte");
2933 }
2934 }
2935 }
2936
2937 if(delta_time != NULL){
2938 *delta_time = current_delta_time;
2939 }
2940
2941 return(offset);
2942 }
2943
2944 /**
2945 * ags_midi_buffer_util_decode:
2946 * @buffer: the midi buffer
2947 * @event: the ALSA sequencer event
2948 *
2949 * Decode @event to @buffer
2950 *
2951 * Returns: the bytes written
2952 *
2953 * Since: 3.0.0
2954 */
2955 guint
ags_midi_buffer_util_decode(guchar * buffer,snd_seq_event_t * event)2956 ags_midi_buffer_util_decode(guchar *buffer,
2957 snd_seq_event_t *event)
2958 {
2959 guint count;
2960
2961 if(buffer == NULL ||
2962 event == NULL){
2963 return(0);
2964 }
2965
2966 count = 0;
2967
2968 switch(event->type){
2969 case SND_SEQ_EVENT_NOTEON:
2970 {
2971 guchar tmp[8];
2972
2973 ags_midi_buffer_util_put_key_on(tmp,
2974 0,
2975 event->data.note.channel,
2976 event->data.note.note,
2977 event->data.note.velocity);
2978
2979 count = ags_midi_buffer_util_get_varlength_size(0);
2980 memcpy(buffer, tmp + count, 3 * sizeof(guchar));
2981
2982 count = 3;
2983 }
2984 break;
2985 case SND_SEQ_EVENT_NOTEOFF:
2986 {
2987 guchar tmp[8];
2988
2989 ags_midi_buffer_util_put_key_off(tmp,
2990 0,
2991 event->data.note.channel,
2992 event->data.note.note,
2993 event->data.note.velocity);
2994
2995 count = ags_midi_buffer_util_get_varlength_size(0);
2996 memcpy(buffer, tmp + count, 3 * sizeof(guchar));
2997
2998 count = 3;
2999 }
3000 break;
3001 default:
3002 g_warning("ags_midi_buffer_util_decode() - unsupported MIDI event");
3003 break;
3004 }
3005
3006 return(count);
3007 }
3008