ardour
smf_decode.c
Go to the documentation of this file.
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 
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 
56 int
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 
71 int
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 
89 int
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 }
103 int
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 *
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  assert (off <= BUFFER_SIZE);
289  return (buf);
290 
291 error:
292  free(buf);
293 
294  return (NULL);
295 }
296 
297 static char *
299 {
300  int off = 0;
301  char *buf;
302 
303  assert(smf_event_is_system_realtime(event));
304 
305  if (event->midi_buffer_length != 1) {
306  g_critical("smf_event_decode_system_realtime: event length is not 1.");
307  return (NULL);
308  }
309 
310  buf = (char*)malloc(BUFFER_SIZE);
311  if (buf == NULL) {
312  g_critical("smf_event_decode_system_realtime: malloc failed.");
313  return (NULL);
314  }
315 
316  switch (event->midi_buffer[0]) {
317  case 0xF8:
318  off += snprintf(buf + off, BUFFER_SIZE - off, "MIDI Clock (realtime)");
319  break;
320 
321  case 0xF9:
322  off += snprintf(buf + off, BUFFER_SIZE - off, "Tick (realtime)");
323  break;
324 
325  case 0xFA:
326  off += snprintf(buf + off, BUFFER_SIZE - off, "MIDI Start (realtime)");
327  break;
328 
329  case 0xFB:
330  off += snprintf(buf + off, BUFFER_SIZE - off, "MIDI Continue (realtime)");
331  break;
332 
333  case 0xFC:
334  off += snprintf(buf + off, BUFFER_SIZE - off, "MIDI Stop (realtime)");
335  break;
336 
337  case 0xFE:
338  off += snprintf(buf + off, BUFFER_SIZE - off, "Active Sense (realtime)");
339  break;
340 
341  default:
342  free(buf);
343  return (NULL);
344  }
345 
346  assert (off <= BUFFER_SIZE);
347  return (buf);
348 }
349 
350 static char *
352 {
353  int off = 0;
354  char *buf, manufacturer, subid, subid2;
355 
356  assert(smf_event_is_sysex(event));
357 
358  if (event->midi_buffer_length < 5) {
359  g_critical("smf_event_decode_sysex: truncated MIDI message.");
360  return (NULL);
361  }
362 
363  buf = (char*)malloc(BUFFER_SIZE);
364  if (buf == NULL) {
365  g_critical("smf_event_decode_sysex: malloc failed.");
366  return (NULL);
367  }
368 
369  manufacturer = event->midi_buffer[1];
370 
371  if (manufacturer == 0x7F) {
372  off += snprintf(buf + off, BUFFER_SIZE - off, "SysEx, realtime, channel %d", event->midi_buffer[2]);
373  } else if (manufacturer == 0x7E) {
374  off += snprintf(buf + off, BUFFER_SIZE - off, "SysEx, non-realtime, channel %d", event->midi_buffer[2]);
375  } else {
376  off += snprintf(buf + off, BUFFER_SIZE - off, "SysEx, manufacturer 0x%x", manufacturer);
377 
378  assert (off <= BUFFER_SIZE);
379  return (buf);
380  }
381 
382  subid = event->midi_buffer[3];
383  subid2 = event->midi_buffer[4];
384 
385  if (subid == 0x01)
386  off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump Header");
387 
388  else if (subid == 0x02)
389  off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump Data Packet");
390 
391  else if (subid == 0x03)
392  off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump Request");
393 
394  else if (subid == 0x04 && subid2 == 0x01)
395  off += snprintf(buf + off, BUFFER_SIZE - off, ", Master Volume");
396 
397  else if (subid == 0x05 && subid2 == 0x01)
398  off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump Loop Point Retransmit");
399 
400  else if (subid == 0x05 && subid2 == 0x02)
401  off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump Loop Point Request");
402 
403  else if (subid == 0x06 && subid2 == 0x01)
404  off += snprintf(buf + off, BUFFER_SIZE - off, ", Identity Request");
405 
406  else if (subid == 0x06 && subid2 == 0x02)
407  off += snprintf(buf + off, BUFFER_SIZE - off, ", Identity Reply");
408 
409  else if (subid == 0x08 && subid2 == 0x00)
410  off += snprintf(buf + off, BUFFER_SIZE - off, ", Bulk Tuning Dump Request");
411 
412  else if (subid == 0x08 && subid2 == 0x01)
413  off += snprintf(buf + off, BUFFER_SIZE - off, ", Bulk Tuning Dump");
414 
415  else if (subid == 0x08 && subid2 == 0x02)
416  off += snprintf(buf + off, BUFFER_SIZE - off, ", Single Note Tuning Change");
417 
418  else if (subid == 0x08 && subid2 == 0x03)
419  off += snprintf(buf + off, BUFFER_SIZE - off, ", Bulk Tuning Dump Request (Bank)");
420 
421  else if (subid == 0x08 && subid2 == 0x04)
422  off += snprintf(buf + off, BUFFER_SIZE - off, ", Key Based Tuning Dump");
423 
424  else if (subid == 0x08 && subid2 == 0x05)
425  off += snprintf(buf + off, BUFFER_SIZE - off, ", Scale/Octave Tuning Dump, 1 byte format");
426 
427  else if (subid == 0x08 && subid2 == 0x06)
428  off += snprintf(buf + off, BUFFER_SIZE - off, ", Scale/Octave Tuning Dump, 2 byte format");
429 
430  else if (subid == 0x08 && subid2 == 0x07)
431  off += snprintf(buf + off, BUFFER_SIZE - off, ", Single Note Tuning Change (Bank)");
432 
433  else if (subid == 0x09)
434  off += snprintf(buf + off, BUFFER_SIZE - off, ", General MIDI %s", subid2 == 0 ? "disable" : "enable");
435 
436  else if (subid == 0x7C)
437  off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump Wait");
438 
439  else if (subid == 0x7D)
440  off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump Cancel");
441 
442  else if (subid == 0x7E)
443  off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump NAK");
444 
445  else if (subid == 0x7F)
446  off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump ACK");
447 
448  else
449  off += snprintf(buf + off, BUFFER_SIZE - off, ", Unknown");
450 
451  assert (off <= BUFFER_SIZE);
452  return (buf);
453 }
454 
455 static char *
457 {
458  int off = 0;
459  char *buf;
460 
461  assert(smf_event_is_system_common(event));
462 
463  if (smf_event_is_sysex(event))
464  return (smf_event_decode_sysex(event));
465 
466  buf = (char*)malloc(BUFFER_SIZE);
467  if (buf == NULL) {
468  g_critical("smf_event_decode_system_realtime: malloc failed.");
469  return (NULL);
470  }
471 
472  switch (event->midi_buffer[0]) {
473  case 0xF1:
474  off += snprintf(buf + off, BUFFER_SIZE - off, "MTC Quarter Frame");
475  break;
476 
477  case 0xF2:
478  off += snprintf(buf + off, BUFFER_SIZE - off, "Song Position Pointer");
479  break;
480 
481  case 0xF3:
482  off += snprintf(buf + off, BUFFER_SIZE - off, "Song Select");
483  break;
484 
485  case 0xF6:
486  off += snprintf(buf + off, BUFFER_SIZE - off, "Tune Request");
487  break;
488 
489  default:
490  free(buf);
491  return (NULL);
492  }
493 
494  assert (off <= BUFFER_SIZE);
495  return (buf);
496 }
497 
498 static void
499 note_from_int(char *buf, int note_number)
500 {
501  int note, octave;
502  const char *names[] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
503 
504  octave = note_number / 12 - 1;
505  note = note_number % 12;
506 
507  sprintf(buf, "%s%d", names[note], octave);
508 }
509 
518 char *
520 {
521  int off = 0, channel;
522  char *buf, note[5];
523 
524  if (smf_event_is_metadata(event))
525  return (smf_event_decode_metadata(event));
526 
527  if (smf_event_is_system_realtime(event))
528  return (smf_event_decode_system_realtime(event));
529 
530  if (smf_event_is_system_common(event))
531  return (smf_event_decode_system_common(event));
532 
533  if (!smf_event_length_is_valid(event)) {
534  g_critical("smf_event_decode: incorrect MIDI message length.");
535  return (NULL);
536  }
537 
538  buf = (char*)malloc(BUFFER_SIZE);
539  if (buf == NULL) {
540  g_critical("smf_event_decode: malloc failed.");
541  return (NULL);
542  }
543 
544  /* + 1, because user-visible channels used to be in range <1-16>. */
545  channel = (event->midi_buffer[0] & 0x0F) + 1;
546 
547  switch (event->midi_buffer[0] & 0xF0) {
548  case 0x80:
549  note_from_int(note, event->midi_buffer[1]);
550  off += snprintf(buf + off, BUFFER_SIZE - off, "Note Off, channel %d, note %s, velocity %d",
551  channel, note, event->midi_buffer[2]);
552  break;
553 
554  case 0x90:
555  note_from_int(note, event->midi_buffer[1]);
556  off += snprintf(buf + off, BUFFER_SIZE - off, "Note On, channel %d, note %s, velocity %d",
557  channel, note, event->midi_buffer[2]);
558  break;
559 
560  case 0xA0:
561  note_from_int(note, event->midi_buffer[1]);
562  off += snprintf(buf + off, BUFFER_SIZE - off, "Aftertouch, channel %d, note %s, pressure %d",
563  channel, note, event->midi_buffer[2]);
564  break;
565 
566  case 0xB0:
567  off += snprintf(buf + off, BUFFER_SIZE - off, "Controller, channel %d, controller %d, value %d",
568  channel, event->midi_buffer[1], event->midi_buffer[2]);
569  break;
570 
571  case 0xC0:
572  off += snprintf(buf + off, BUFFER_SIZE - off, "Program Change, channel %d, controller %d",
573  channel, event->midi_buffer[1]);
574  break;
575 
576  case 0xD0:
577  off += snprintf(buf + off, BUFFER_SIZE - off, "Channel Pressure, channel %d, pressure %d",
578  channel, event->midi_buffer[1]);
579  break;
580 
581  case 0xE0:
582  off += snprintf(buf + off, BUFFER_SIZE - off, "Pitch Wheel, channel %d, value %d",
583  channel, ((int)event->midi_buffer[2] << 7) | (int)event->midi_buffer[2]);
584  break;
585 
586  default:
587  free(buf);
588  return (NULL);
589  }
590 
591  assert(off <= BUFFER_SIZE);
592 
593  return (buf);
594 }
595 
604 char *
606 {
607  int off = 0;
608  char *buf;
609 
610  buf = (char*)malloc(BUFFER_SIZE);
611  if (buf == NULL) {
612  g_critical("smf_event_decode: malloc failed.");
613  return (NULL);
614  }
615 
616  off += snprintf(buf + off, BUFFER_SIZE - off, "format: %d ", smf->format);
617 
618  switch (smf->format) {
619  case 0:
620  off += snprintf(buf + off, BUFFER_SIZE - off, "(single track)");
621  break;
622 
623  case 1:
624  off += snprintf(buf + off, BUFFER_SIZE - off, "(several simultaneous tracks)");
625  break;
626 
627  case 2:
628  off += snprintf(buf + off, BUFFER_SIZE - off, "(several independent tracks)");
629  break;
630 
631  default:
632  off += snprintf(buf + off, BUFFER_SIZE - off, "(INVALID FORMAT)");
633  break;
634  }
635 
636  off += snprintf(buf + off, BUFFER_SIZE - off, "; number of tracks: %d", smf->number_of_tracks);
637 
638  if (smf->ppqn != 0)
639  off += snprintf(buf + off, BUFFER_SIZE - off, "; division: %d PPQN", smf->ppqn);
640  else
641  off += snprintf(buf + off, BUFFER_SIZE - off, "; division: %d FPS, %d resolution", smf->frames_per_second, smf->resolution);
642 
643  assert (off <= BUFFER_SIZE);
644  return (buf);
645 }
646 
#define BUFFER_SIZE
Definition: smf_decode.c:49
int format
Definition: smf.h:235
char * smf_decode(const smf_t *smf)
Definition: smf_decode.c:605
int smf_event_is_system_common(const smf_event_t *event)
Definition: smf_decode.c:90
size_t midi_buffer_length
Definition: smf.h:324
LIBPBD_API Transmitter error
int smf_event_is_sysex(const smf_event_t *event)
Definition: smf_decode.c:104
int smf_event_is_system_realtime(const smf_event_t *event)
Definition: smf_decode.c:72
uint16_t ppqn
Definition: smf.h:239
int smf_event_length_is_valid(const smf_event_t *event)
Definition: smf_load.c:740
int frames_per_second
Definition: smf.h:240
int number_of_tracks
Definition: smf.h:242
static void note_from_int(char *buf, int note_number)
Definition: smf_decode.c:499
static char * smf_event_decode_textual(const smf_event_t *event, const char *name)
Definition: smf_decode.c:116
int resolution
Definition: smf.h:241
char * smf_event_extract_text(const smf_event_t *event) WARN_UNUSED_RESULT
Definition: smf_load.c:668
const char * name
int smf_event_is_metadata(const smf_event_t *event)
Definition: smf_decode.c:57
char * smf_event_decode(const smf_event_t *event)
Definition: smf_decode.c:519
static char * smf_event_decode_sysex(const smf_event_t *event)
Definition: smf_decode.c:351
static char * smf_event_decode_system_realtime(const smf_event_t *event)
Definition: smf_decode.c:298
static char * smf_event_decode_metadata(const smf_event_t *event)
Definition: smf_decode.c:139
uint8_t * midi_buffer
Definition: smf.h:321
static char * smf_event_decode_system_common(const smf_event_t *event)
Definition: smf_decode.c:456
smf_t * smf
Definition: smfsh.c:51