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