0951a6e2f881cf86a24ed3b19e59143b5cd30dcf
[ardour.git] / libs / evoral / src / libsmf / smf_decode.c
1 /*-
2  * Copyright (c) 2007, 2008 Edward Tomasz NapieraƂa <trasz@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * ALTHOUGH THIS SOFTWARE IS MADE OF WIN AND SCIENCE, IT IS PROVIDED BY THE
15  * AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
16  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
18  * THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
20  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
21  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27
28 /**
29  * \file
30  *
31  * Event decoding routines.
32  *
33  */
34
35 #include <stdlib.h>
36 #include <string.h>
37 #include <assert.h>
38 #include <math.h>
39 #include <errno.h>
40 #include <arpa/inet.h>
41 #include <stdint.h>
42 #include "smf.h"
43 #include "smf_private.h"
44
45 #define BUFFER_SIZE 1024
46
47 /**
48  * \return Nonzero if event is metaevent.  You should never send metaevents;
49  * they are not really MIDI messages.  They carry information like track title,
50  * time signature etc.
51  */
52 int
53 smf_event_is_metadata(const smf_event_t *event)
54 {
55         assert(event->midi_buffer);
56         assert(event->midi_buffer_length > 0);
57         
58         if (event->midi_buffer[0] == 0xFF)
59                 return (1);
60
61         return (0);
62 }
63
64 /**
65  * \return Nonzero if event is System Realtime.
66  */
67 int
68 smf_event_is_system_realtime(const smf_event_t *event)
69 {
70         assert(event->midi_buffer);
71         assert(event->midi_buffer_length > 0);
72
73         if (smf_event_is_metadata(event))
74                 return (0);
75         
76         if (event->midi_buffer[0] >= 0xF8)
77                 return (1);
78
79         return (0);
80 }
81
82 /**
83  * \return Nonzero if event is System Common.
84  */
85 int
86 smf_event_is_system_common(const smf_event_t *event)
87 {
88         assert(event->midi_buffer);
89         assert(event->midi_buffer_length > 0);
90
91         if (event->midi_buffer[0] >= 0xF0 && event->midi_buffer[0] <= 0xF7)
92                 return (1);
93
94         return (0);
95 }
96 /**
97   * \return Nonzero if event is SysEx message.
98   */
99 int
100 smf_event_is_sysex(const smf_event_t *event)
101 {
102         assert(event->midi_buffer);
103         assert(event->midi_buffer_length > 0);
104         
105         if (event->midi_buffer[0] == 0xF0)
106                 return (1);
107
108         return (0);
109 }
110
111 static char *
112 smf_event_decode_textual(const smf_event_t *event, const char *name)
113 {
114         int off = 0;
115         char *buf, *extracted;
116
117         buf = malloc(BUFFER_SIZE);
118         if (buf == NULL) {
119                 g_critical("smf_event_decode_textual: malloc failed.");
120                 return (NULL);
121         }
122
123         extracted = smf_event_extract_text(event);
124         if (extracted == NULL) {
125                 free(buf);
126                 return (NULL);
127         }
128
129         snprintf(buf + off, BUFFER_SIZE - off, "%s: %s", name, extracted);
130
131         return (buf);
132 }
133
134 static char *
135 smf_event_decode_metadata(const smf_event_t *event)
136 {
137         int off = 0, mspqn, flats, isminor;
138         char *buf;
139
140         static const char *const major_keys[] = {"Fb", "Cb", "Gb", "Db", "Ab",
141                 "Eb", "Bb", "F", "C", "G", "D", "A", "E", "B", "F#", "C#", "G#"};
142
143         static const char *const minor_keys[] = {"Dbm", "Abm", "Ebm", "Bbm", "Fm",
144                 "Cm", "Gm", "Dm", "Am", "Em", "Bm", "F#m", "C#m", "G#m", "D#m", "A#m", "E#m"};
145
146         assert(smf_event_is_metadata(event));
147
148         switch (event->midi_buffer[1]) {
149                 case 0x01:
150                         return (smf_event_decode_textual(event, "Text"));
151
152                 case 0x02:
153                         return (smf_event_decode_textual(event, "Copyright"));
154
155                 case 0x03:
156                         return (smf_event_decode_textual(event, "Sequence/Track Name"));
157
158                 case 0x04:
159                         return (smf_event_decode_textual(event, "Instrument"));
160
161                 case 0x05:
162                         return (smf_event_decode_textual(event, "Lyric"));
163
164                 case 0x06:
165                         return (smf_event_decode_textual(event, "Marker"));
166
167                 case 0x07:
168                         return (smf_event_decode_textual(event, "Cue Point"));
169
170                 case 0x08:
171                         return (smf_event_decode_textual(event, "Program Name"));
172
173                 case 0x09:
174                         return (smf_event_decode_textual(event, "Device (Port) Name"));
175
176                 default:
177                         break;
178         }
179
180         buf = malloc(BUFFER_SIZE);
181         if (buf == NULL) {
182                 g_critical("smf_event_decode_metadata: malloc failed.");
183                 return (NULL);
184         }
185
186         switch (event->midi_buffer[1]) {
187                 case 0x00:
188                         off += snprintf(buf + off, BUFFER_SIZE - off, "Sequence number");
189                         break;
190
191                 /* http://music.columbia.edu/pipermail/music-dsp/2004-August/061196.html */
192                 case 0x20:
193                         if (event->midi_buffer_length < 4) {
194                                 g_critical("smf_event_decode_metadata: truncated MIDI message.");
195                                 goto error;
196                         }
197
198                         off += snprintf(buf + off, BUFFER_SIZE - off, "Channel Prefix: %d", event->midi_buffer[3]);
199                         break;
200
201                 case 0x21:
202                         if (event->midi_buffer_length < 4) {
203                                 g_critical("smf_event_decode_metadata: truncated MIDI message.");
204                                 goto error;
205                         }
206
207                         off += snprintf(buf + off, BUFFER_SIZE - off, "MIDI Port: %d", event->midi_buffer[3]);
208                         break;
209
210                 case 0x2F:
211                         off += snprintf(buf + off, BUFFER_SIZE - off, "End Of Track");
212                         break;
213
214                 case 0x51:
215                         if (event->midi_buffer_length < 6) {
216                                 g_critical("smf_event_decode_metadata: truncated MIDI message.");
217                                 goto error;
218                         }
219
220                         mspqn = (event->midi_buffer[3] << 16) + (event->midi_buffer[4] << 8) + event->midi_buffer[5];
221
222                         off += snprintf(buf + off, BUFFER_SIZE - off, "Tempo: %d microseconds per quarter note, %.2f BPM",
223                                 mspqn, 60000000.0 / (double)mspqn);
224                         break;
225
226                 case 0x54:
227                         off += snprintf(buf + off, BUFFER_SIZE - off, "SMPTE Offset");
228                         break;
229
230                 case 0x58:
231                         if (event->midi_buffer_length < 7) {
232                                 g_critical("smf_event_decode_metadata: truncated MIDI message.");
233                                 goto error;
234                         }
235
236                         off += snprintf(buf + off, BUFFER_SIZE - off,
237                                 "Time Signature: %d/%d, %d clocks per click, %d notated 32nd notes per quarter note",
238                                 event->midi_buffer[3], (int)pow(2, event->midi_buffer[4]), event->midi_buffer[5],
239                                 event->midi_buffer[6]);
240                         break;
241
242                 case 0x59:
243                         if (event->midi_buffer_length < 5) {
244                                 g_critical("smf_event_decode_metadata: truncated MIDI message.");
245                                 goto error;
246                         }
247
248                         flats = event->midi_buffer[3];
249                         isminor = event->midi_buffer[4];
250
251                         if (isminor != 0 && isminor != 1) {
252                                 g_critical("smf_event_decode_metadata: last byte of the Key Signature event has invalid value %d.", isminor);
253                                 goto error;
254                         }
255
256                         off += snprintf(buf + off, BUFFER_SIZE - off, "Key Signature: ");
257
258                         if (flats > 8 && flats < 248) {
259                                 off += snprintf(buf + off, BUFFER_SIZE - off, "%d %s, %s key", abs((int8_t)flats),
260                                         flats > 127 ? "flats" : "sharps", isminor ? "minor" : "major");
261                         } else {
262                                 int i = (flats - 248) & 255;
263
264                                 assert(i >= 0 && (size_t)i < sizeof(minor_keys) / sizeof(*minor_keys));
265                                 assert(i >= 0 && (size_t)i < sizeof(major_keys) / sizeof(*major_keys));
266
267                                 if (isminor)
268                                         off += snprintf(buf + off, BUFFER_SIZE - off, "%s", minor_keys[i]);
269                                 else
270                                         off += snprintf(buf + off, BUFFER_SIZE - off, "%s", major_keys[i]);
271                         }
272
273                         break;
274
275                 case 0x7F:
276                         off += snprintf(buf + off, BUFFER_SIZE - off, "Proprietary (aka Sequencer) Event, length %zu",
277                                 event->midi_buffer_length);
278                         break;
279
280                 default:
281                         goto error;
282         }
283
284         return (buf);
285
286 error:
287         free(buf);
288
289         return (NULL);
290 }
291
292 static char *
293 smf_event_decode_system_realtime(const smf_event_t *event)
294 {
295         int off = 0;
296         char *buf;
297
298         assert(smf_event_is_system_realtime(event));
299
300         if (event->midi_buffer_length != 1) {
301                 g_critical("smf_event_decode_system_realtime: event length is not 1.");
302                 return (NULL);
303         }
304
305         buf = malloc(BUFFER_SIZE);
306         if (buf == NULL) {
307                 g_critical("smf_event_decode_system_realtime: malloc failed.");
308                 return (NULL);
309         }
310
311         switch (event->midi_buffer[0]) {
312                 case 0xF8:
313                         off += snprintf(buf + off, BUFFER_SIZE - off, "MIDI Clock (realtime)");
314                         break;
315
316                 case 0xF9:
317                         off += snprintf(buf + off, BUFFER_SIZE - off, "Tick (realtime)");
318                         break;
319
320                 case 0xFA:
321                         off += snprintf(buf + off, BUFFER_SIZE - off, "MIDI Start (realtime)");
322                         break;
323
324                 case 0xFB:
325                         off += snprintf(buf + off, BUFFER_SIZE - off, "MIDI Continue (realtime)");
326                         break;
327
328                 case 0xFC:
329                         off += snprintf(buf + off, BUFFER_SIZE - off, "MIDI Stop (realtime)");
330                         break;
331
332                 case 0xFE:
333                         off += snprintf(buf + off, BUFFER_SIZE - off, "Active Sense (realtime)");
334                         break;
335
336                 default:
337                         free(buf);
338                         return (NULL);
339         }
340
341         return (buf);
342 }
343
344 static char *
345 smf_event_decode_sysex(const smf_event_t *event)
346 {
347         int off = 0;
348         char *buf, manufacturer, subid, subid2;
349
350         assert(smf_event_is_sysex(event));
351
352         if (event->midi_buffer_length < 5) {
353                 g_critical("smf_event_decode_sysex: truncated MIDI message.");
354                 return (NULL);
355         }
356
357         buf = malloc(BUFFER_SIZE);
358         if (buf == NULL) {
359                 g_critical("smf_event_decode_sysex: malloc failed.");
360                 return (NULL);
361         }
362
363         manufacturer = event->midi_buffer[1];
364
365         if (manufacturer == 0x7F) {
366                 off += snprintf(buf + off, BUFFER_SIZE - off, "SysEx, realtime, channel %d", event->midi_buffer[2]);
367         } else if (manufacturer == 0x7E) {
368                 off += snprintf(buf + off, BUFFER_SIZE - off, "SysEx, non-realtime, channel %d", event->midi_buffer[2]);
369         } else {
370                 off += snprintf(buf + off, BUFFER_SIZE - off, "SysEx, manufacturer 0x%x", manufacturer);
371
372                 return (buf);
373         }
374
375         subid = event->midi_buffer[3];
376         subid2 = event->midi_buffer[4];
377
378         if (subid == 0x01)
379                 off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump Header");
380
381         else if (subid == 0x02)
382                 off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump Data Packet");
383
384         else if (subid == 0x03)
385                 off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump Request");
386
387         else if (subid == 0x04 && subid2 == 0x01)
388                 off += snprintf(buf + off, BUFFER_SIZE - off, ", Master Volume");
389
390         else if (subid == 0x05 && subid2 == 0x01)
391                 off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump Loop Point Retransmit");
392
393         else if (subid == 0x05 && subid2 == 0x02)
394                 off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump Loop Point Request");
395
396         else if (subid == 0x06 && subid2 == 0x01)
397                 off += snprintf(buf + off, BUFFER_SIZE - off, ", Identity Request");
398
399         else if (subid == 0x06 && subid2 == 0x02)
400                 off += snprintf(buf + off, BUFFER_SIZE - off, ", Identity Reply");
401
402         else if (subid == 0x08 && subid2 == 0x00)
403                 off += snprintf(buf + off, BUFFER_SIZE - off, ", Bulk Tuning Dump Request");
404
405         else if (subid == 0x08 && subid2 == 0x01)
406                 off += snprintf(buf + off, BUFFER_SIZE - off, ", Bulk Tuning Dump");
407
408         else if (subid == 0x08 && subid2 == 0x02)
409                 off += snprintf(buf + off, BUFFER_SIZE - off, ", Single Note Tuning Change");
410
411         else if (subid == 0x08 && subid2 == 0x03)
412                 off += snprintf(buf + off, BUFFER_SIZE - off, ", Bulk Tuning Dump Request (Bank)");
413
414         else if (subid == 0x08 && subid2 == 0x04)
415                 off += snprintf(buf + off, BUFFER_SIZE - off, ", Key Based Tuning Dump");
416
417         else if (subid == 0x08 && subid2 == 0x05)
418                 off += snprintf(buf + off, BUFFER_SIZE - off, ", Scale/Octave Tuning Dump, 1 byte format");
419
420         else if (subid == 0x08 && subid2 == 0x06)
421                 off += snprintf(buf + off, BUFFER_SIZE - off, ", Scale/Octave Tuning Dump, 2 byte format");
422
423         else if (subid == 0x08 && subid2 == 0x07)
424                 off += snprintf(buf + off, BUFFER_SIZE - off, ", Single Note Tuning Change (Bank)");
425
426         else if (subid == 0x09)
427                 off += snprintf(buf + off, BUFFER_SIZE - off, ", General MIDI %s", subid2 == 0 ? "disable" : "enable");
428
429         else if (subid == 0x7C)
430                 off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump Wait");
431
432         else if (subid == 0x7D)
433                 off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump Cancel");
434
435         else if (subid == 0x7E)
436                 off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump NAK");
437
438         else if (subid == 0x7F)
439                 off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump ACK");
440
441         else
442                 off += snprintf(buf + off, BUFFER_SIZE - off, ", Unknown");
443
444         return (buf);
445 }
446
447 static char *
448 smf_event_decode_system_common(const smf_event_t *event)
449 {
450         int off = 0;
451         char *buf;
452
453         assert(smf_event_is_system_common(event));
454
455         if (smf_event_is_sysex(event))
456                 return (smf_event_decode_sysex(event));
457
458         buf = malloc(BUFFER_SIZE);
459         if (buf == NULL) {
460                 g_critical("smf_event_decode_system_realtime: malloc failed.");
461                 return (NULL);
462         }
463
464         switch (event->midi_buffer[0]) {
465                 case 0xF1:
466                         off += snprintf(buf + off, BUFFER_SIZE - off, "MTC Quarter Frame");
467                         break;
468
469                 case 0xF2:
470                         off += snprintf(buf + off, BUFFER_SIZE - off, "Song Position Pointer");
471                         break;
472
473                 case 0xF3:
474                         off += snprintf(buf + off, BUFFER_SIZE - off, "Song Select");
475                         break;
476
477                 case 0xF6:
478                         off += snprintf(buf + off, BUFFER_SIZE - off, "Tune Request");
479                         break;
480
481                 default:
482                         free(buf);
483                         return (NULL);
484         }
485
486         return (buf);
487 }
488
489 static void
490 note_from_int(char *buf, int note_number)
491 {
492         int note, octave;
493         char *names[] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
494
495         octave = note_number / 12 - 1;
496         note = note_number % 12;
497
498         sprintf(buf, "%s%d", names[note], octave);
499 }
500
501 /**
502  * \return Textual representation of the event given, or NULL, if event is unknown.
503  * Returned string looks like this:
504  *
505  * Note On, channel 1, note F#3, velocity 0
506  *
507  * You should free the returned string afterwards, using free(3).
508  */
509 char *
510 smf_event_decode(const smf_event_t *event)
511 {
512         int off = 0, channel;
513         char *buf, note[5];
514
515         if (smf_event_is_metadata(event))
516                 return (smf_event_decode_metadata(event));
517
518         if (smf_event_is_system_realtime(event))
519                 return (smf_event_decode_system_realtime(event));
520
521         if (smf_event_is_system_common(event))
522                 return (smf_event_decode_system_common(event));
523
524         if (!smf_event_length_is_valid(event)) {
525                 g_critical("smf_event_decode: incorrect MIDI message length.");
526                 return (NULL);
527         }
528
529         buf = malloc(BUFFER_SIZE);
530         if (buf == NULL) {
531                 g_critical("smf_event_decode: malloc failed.");
532                 return (NULL);
533         }
534
535         /* + 1, because user-visible channels used to be in range <1-16>. */
536         channel = (event->midi_buffer[0] & 0x0F) + 1;
537
538         switch (event->midi_buffer[0] & 0xF0) {
539                 case 0x80:
540                         note_from_int(note, event->midi_buffer[1]);
541                         off += snprintf(buf + off, BUFFER_SIZE - off, "Note Off, channel %d, note %s, velocity %d",
542                                         channel, note, event->midi_buffer[2]);
543                         break;
544
545                 case 0x90:
546                         note_from_int(note, event->midi_buffer[1]);
547                         off += snprintf(buf + off, BUFFER_SIZE - off, "Note On, channel %d, note %s, velocity %d",
548                                         channel, note, event->midi_buffer[2]);
549                         break;
550
551                 case 0xA0:
552                         note_from_int(note, event->midi_buffer[1]);
553                         off += snprintf(buf + off, BUFFER_SIZE - off, "Aftertouch, channel %d, note %s, pressure %d",
554                                         channel, note, event->midi_buffer[2]);
555                         break;
556
557                 case 0xB0:
558                         off += snprintf(buf + off, BUFFER_SIZE - off, "Controller, channel %d, controller %d, value %d",
559                                         channel, event->midi_buffer[1], event->midi_buffer[2]);
560                         break;
561
562                 case 0xC0:
563                         off += snprintf(buf + off, BUFFER_SIZE - off, "Program Change, channel %d, controller %d",
564                                         channel, event->midi_buffer[1]);
565                         break;
566
567                 case 0xD0:
568                         off += snprintf(buf + off, BUFFER_SIZE - off, "Channel Pressure, channel %d, pressure %d",
569                                         channel, event->midi_buffer[1]);
570                         break;
571
572                 case 0xE0:
573                         off += snprintf(buf + off, BUFFER_SIZE - off, "Pitch Wheel, channel %d, value %d",
574                                         channel, ((int)event->midi_buffer[2] << 7) | (int)event->midi_buffer[2]);
575                         break;
576
577                 default:
578                         free(buf);
579                         return (NULL);
580         }
581
582         return (buf);
583 }
584
585 /**
586  * \return Textual representation of the data extracted from MThd header, or NULL, if something goes wrong.
587  * Returned string looks like this:
588  *
589  * format: 1 (several simultaneous tracks); number of tracks: 4; division: 192 PPQN.
590  *
591  * You should free the returned string afterwards, using free(3).
592  */
593 char *
594 smf_decode(const smf_t *smf)
595 {
596         int off = 0;
597         char *buf;
598
599         buf = malloc(BUFFER_SIZE);
600         if (buf == NULL) {
601                 g_critical("smf_event_decode: malloc failed.");
602                 return (NULL);
603         }
604
605         off += snprintf(buf + off, BUFFER_SIZE - off, "format: %d ", smf->format);
606
607         switch (smf->format) {
608                 case 0:
609                         off += snprintf(buf + off, BUFFER_SIZE - off, "(single track)");
610                         break;
611
612                 case 1:
613                         off += snprintf(buf + off, BUFFER_SIZE - off, "(several simultaneous tracks)");
614                         break;
615
616                 case 2:
617                         off += snprintf(buf + off, BUFFER_SIZE - off, "(several independent tracks)");
618                         break;
619
620                 default:
621                         off += snprintf(buf + off, BUFFER_SIZE - off, "(INVALID FORMAT)");
622                         break;
623         }
624
625         off += snprintf(buf + off, BUFFER_SIZE - off, "; number of tracks: %d", smf->number_of_tracks);
626
627         if (smf->ppqn != 0)
628                 off += snprintf(buf + off, BUFFER_SIZE - off, "; division: %d PPQN", smf->ppqn);
629         else
630                 off += snprintf(buf + off, BUFFER_SIZE - off, "; division: %d FPS, %d resolution", smf->frames_per_second, smf->resolution);
631
632         return (buf);
633 }
634