00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00035 #include <stdlib.h>
00036 #include <string.h>
00037 #include <assert.h>
00038 #include <math.h>
00039 #include <errno.h>
00040 #ifdef __MINGW32__
00041 #include <windows.h>
00042 #else
00043 #include <arpa/inet.h>
00044 #endif
00045 #include <stdint.h>
00046 #include "smf.h"
00047 #include "smf_private.h"
00048
00049 #define BUFFER_SIZE 1024
00050
00056 int
00057 smf_event_is_metadata(const smf_event_t *event)
00058 {
00059 assert(event->midi_buffer);
00060 assert(event->midi_buffer_length > 0);
00061
00062 if (event->midi_buffer[0] == 0xFF)
00063 return (1);
00064
00065 return (0);
00066 }
00067
00071 int
00072 smf_event_is_system_realtime(const smf_event_t *event)
00073 {
00074 assert(event->midi_buffer);
00075 assert(event->midi_buffer_length > 0);
00076
00077 if (smf_event_is_metadata(event))
00078 return (0);
00079
00080 if (event->midi_buffer[0] >= 0xF8)
00081 return (1);
00082
00083 return (0);
00084 }
00085
00089 int
00090 smf_event_is_system_common(const smf_event_t *event)
00091 {
00092 assert(event->midi_buffer);
00093 assert(event->midi_buffer_length > 0);
00094
00095 if (event->midi_buffer[0] >= 0xF0 && event->midi_buffer[0] <= 0xF7)
00096 return (1);
00097
00098 return (0);
00099 }
00103 int
00104 smf_event_is_sysex(const smf_event_t *event)
00105 {
00106 assert(event->midi_buffer);
00107 assert(event->midi_buffer_length > 0);
00108
00109 if (event->midi_buffer[0] == 0xF0)
00110 return (1);
00111
00112 return (0);
00113 }
00114
00115 static char *
00116 smf_event_decode_textual(const smf_event_t *event, const char *name)
00117 {
00118 int off = 0;
00119 char *buf, *extracted;
00120
00121 buf = malloc(BUFFER_SIZE);
00122 if (buf == NULL) {
00123 g_critical("smf_event_decode_textual: malloc failed.");
00124 return (NULL);
00125 }
00126
00127 extracted = smf_event_extract_text(event);
00128 if (extracted == NULL) {
00129 free(buf);
00130 return (NULL);
00131 }
00132
00133 snprintf(buf + off, BUFFER_SIZE - off, "%s: %s", name, extracted);
00134
00135 return (buf);
00136 }
00137
00138 static char *
00139 smf_event_decode_metadata(const smf_event_t *event)
00140 {
00141 int off = 0, mspqn, flats, isminor;
00142 char *buf;
00143
00144 static const char *const major_keys[] = {"Fb", "Cb", "Gb", "Db", "Ab",
00145 "Eb", "Bb", "F", "C", "G", "D", "A", "E", "B", "F#", "C#", "G#"};
00146
00147 static const char *const minor_keys[] = {"Dbm", "Abm", "Ebm", "Bbm", "Fm",
00148 "Cm", "Gm", "Dm", "Am", "Em", "Bm", "F#m", "C#m", "G#m", "D#m", "A#m", "E#m"};
00149
00150 assert(smf_event_is_metadata(event));
00151
00152 switch (event->midi_buffer[1]) {
00153 case 0x01:
00154 return (smf_event_decode_textual(event, "Text"));
00155
00156 case 0x02:
00157 return (smf_event_decode_textual(event, "Copyright"));
00158
00159 case 0x03:
00160 return (smf_event_decode_textual(event, "Sequence/Track Name"));
00161
00162 case 0x04:
00163 return (smf_event_decode_textual(event, "Instrument"));
00164
00165 case 0x05:
00166 return (smf_event_decode_textual(event, "Lyric"));
00167
00168 case 0x06:
00169 return (smf_event_decode_textual(event, "Marker"));
00170
00171 case 0x07:
00172 return (smf_event_decode_textual(event, "Cue Point"));
00173
00174 case 0x08:
00175 return (smf_event_decode_textual(event, "Program Name"));
00176
00177 case 0x09:
00178 return (smf_event_decode_textual(event, "Device (Port) Name"));
00179
00180 default:
00181 break;
00182 }
00183
00184 buf = malloc(BUFFER_SIZE);
00185 if (buf == NULL) {
00186 g_critical("smf_event_decode_metadata: malloc failed.");
00187 return (NULL);
00188 }
00189
00190 switch (event->midi_buffer[1]) {
00191 case 0x00:
00192 off += snprintf(buf + off, BUFFER_SIZE - off, "Sequence number");
00193 break;
00194
00195
00196 case 0x20:
00197 if (event->midi_buffer_length < 4) {
00198 g_critical("smf_event_decode_metadata: truncated MIDI message.");
00199 goto error;
00200 }
00201
00202 off += snprintf(buf + off, BUFFER_SIZE - off, "Channel Prefix: %d", event->midi_buffer[3]);
00203 break;
00204
00205 case 0x21:
00206 if (event->midi_buffer_length < 4) {
00207 g_critical("smf_event_decode_metadata: truncated MIDI message.");
00208 goto error;
00209 }
00210
00211 off += snprintf(buf + off, BUFFER_SIZE - off, "MIDI Port: %d", event->midi_buffer[3]);
00212 break;
00213
00214 case 0x2F:
00215 off += snprintf(buf + off, BUFFER_SIZE - off, "End Of Track");
00216 break;
00217
00218 case 0x51:
00219 if (event->midi_buffer_length < 6) {
00220 g_critical("smf_event_decode_metadata: truncated MIDI message.");
00221 goto error;
00222 }
00223
00224 mspqn = (event->midi_buffer[3] << 16) + (event->midi_buffer[4] << 8) + event->midi_buffer[5];
00225
00226 off += snprintf(buf + off, BUFFER_SIZE - off, "Tempo: %d microseconds per quarter note, %.2f BPM",
00227 mspqn, 60000000.0 / (double)mspqn);
00228 break;
00229
00230 case 0x54:
00231 off += snprintf(buf + off, BUFFER_SIZE - off, "SMPTE Offset");
00232 break;
00233
00234 case 0x58:
00235 if (event->midi_buffer_length < 7) {
00236 g_critical("smf_event_decode_metadata: truncated MIDI message.");
00237 goto error;
00238 }
00239
00240 off += snprintf(buf + off, BUFFER_SIZE - off,
00241 "Time Signature: %d/%d, %d clocks per click, %d notated 32nd notes per quarter note",
00242 event->midi_buffer[3], (int)pow(2, event->midi_buffer[4]), event->midi_buffer[5],
00243 event->midi_buffer[6]);
00244 break;
00245
00246 case 0x59:
00247 if (event->midi_buffer_length < 5) {
00248 g_critical("smf_event_decode_metadata: truncated MIDI message.");
00249 goto error;
00250 }
00251
00252 flats = event->midi_buffer[3];
00253 isminor = event->midi_buffer[4];
00254
00255 if (isminor != 0 && isminor != 1) {
00256 g_critical("smf_event_decode_metadata: last byte of the Key Signature event has invalid value %d.", isminor);
00257 goto error;
00258 }
00259
00260 off += snprintf(buf + off, BUFFER_SIZE - off, "Key Signature: ");
00261
00262 if (flats > 8 && flats < 248) {
00263 off += snprintf(buf + off, BUFFER_SIZE - off, "%d %s, %s key", abs((int8_t)flats),
00264 flats > 127 ? "flats" : "sharps", isminor ? "minor" : "major");
00265 } else {
00266 int i = (flats - 248) & 255;
00267
00268 assert(i >= 0 && i < sizeof(minor_keys) / sizeof(*minor_keys));
00269 assert(i >= 0 && i < sizeof(major_keys) / sizeof(*major_keys));
00270
00271 if (isminor)
00272 off += snprintf(buf + off, BUFFER_SIZE - off, "%s", minor_keys[i]);
00273 else
00274 off += snprintf(buf + off, BUFFER_SIZE - off, "%s", major_keys[i]);
00275 }
00276
00277 break;
00278
00279 case 0x7F:
00280 off += snprintf(buf + off, BUFFER_SIZE - off, "Proprietary (aka Sequencer) Event, length %d",
00281 event->midi_buffer_length);
00282 break;
00283
00284 default:
00285 goto error;
00286 }
00287
00288 return (buf);
00289
00290 error:
00291 free(buf);
00292
00293 return (NULL);
00294 }
00295
00296 static char *
00297 smf_event_decode_system_realtime(const smf_event_t *event)
00298 {
00299 int off = 0;
00300 char *buf;
00301
00302 assert(smf_event_is_system_realtime(event));
00303
00304 if (event->midi_buffer_length != 1) {
00305 g_critical("smf_event_decode_system_realtime: event length is not 1.");
00306 return (NULL);
00307 }
00308
00309 buf = malloc(BUFFER_SIZE);
00310 if (buf == NULL) {
00311 g_critical("smf_event_decode_system_realtime: malloc failed.");
00312 return (NULL);
00313 }
00314
00315 switch (event->midi_buffer[0]) {
00316 case 0xF8:
00317 off += snprintf(buf + off, BUFFER_SIZE - off, "MIDI Clock (realtime)");
00318 break;
00319
00320 case 0xF9:
00321 off += snprintf(buf + off, BUFFER_SIZE - off, "Tick (realtime)");
00322 break;
00323
00324 case 0xFA:
00325 off += snprintf(buf + off, BUFFER_SIZE - off, "MIDI Start (realtime)");
00326 break;
00327
00328 case 0xFB:
00329 off += snprintf(buf + off, BUFFER_SIZE - off, "MIDI Continue (realtime)");
00330 break;
00331
00332 case 0xFC:
00333 off += snprintf(buf + off, BUFFER_SIZE - off, "MIDI Stop (realtime)");
00334 break;
00335
00336 case 0xFE:
00337 off += snprintf(buf + off, BUFFER_SIZE - off, "Active Sense (realtime)");
00338 break;
00339
00340 default:
00341 free(buf);
00342 return (NULL);
00343 }
00344
00345 return (buf);
00346 }
00347
00348 static char *
00349 smf_event_decode_sysex(const smf_event_t *event)
00350 {
00351 int off = 0;
00352 char *buf, manufacturer, subid, subid2;
00353
00354 assert(smf_event_is_sysex(event));
00355
00356 if (event->midi_buffer_length < 5) {
00357 g_critical("smf_event_decode_sysex: truncated MIDI message.");
00358 return (NULL);
00359 }
00360
00361 buf = malloc(BUFFER_SIZE);
00362 if (buf == NULL) {
00363 g_critical("smf_event_decode_sysex: malloc failed.");
00364 return (NULL);
00365 }
00366
00367 manufacturer = event->midi_buffer[1];
00368
00369 if (manufacturer == 0x7F) {
00370 off += snprintf(buf + off, BUFFER_SIZE - off, "SysEx, realtime, channel %d", event->midi_buffer[2]);
00371 } else if (manufacturer == 0x7E) {
00372 off += snprintf(buf + off, BUFFER_SIZE - off, "SysEx, non-realtime, channel %d", event->midi_buffer[2]);
00373 } else {
00374 off += snprintf(buf + off, BUFFER_SIZE - off, "SysEx, manufacturer 0x%x", manufacturer);
00375
00376 return (buf);
00377 }
00378
00379 subid = event->midi_buffer[3];
00380 subid2 = event->midi_buffer[4];
00381
00382 if (subid == 0x01)
00383 off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump Header");
00384
00385 else if (subid == 0x02)
00386 off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump Data Packet");
00387
00388 else if (subid == 0x03)
00389 off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump Request");
00390
00391 else if (subid == 0x04 && subid2 == 0x01)
00392 off += snprintf(buf + off, BUFFER_SIZE - off, ", Master Volume");
00393
00394 else if (subid == 0x05 && subid2 == 0x01)
00395 off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump Loop Point Retransmit");
00396
00397 else if (subid == 0x05 && subid2 == 0x02)
00398 off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump Loop Point Request");
00399
00400 else if (subid == 0x06 && subid2 == 0x01)
00401 off += snprintf(buf + off, BUFFER_SIZE - off, ", Identity Request");
00402
00403 else if (subid == 0x06 && subid2 == 0x02)
00404 off += snprintf(buf + off, BUFFER_SIZE - off, ", Identity Reply");
00405
00406 else if (subid == 0x08 && subid2 == 0x00)
00407 off += snprintf(buf + off, BUFFER_SIZE - off, ", Bulk Tuning Dump Request");
00408
00409 else if (subid == 0x08 && subid2 == 0x01)
00410 off += snprintf(buf + off, BUFFER_SIZE - off, ", Bulk Tuning Dump");
00411
00412 else if (subid == 0x08 && subid2 == 0x02)
00413 off += snprintf(buf + off, BUFFER_SIZE - off, ", Single Note Tuning Change");
00414
00415 else if (subid == 0x08 && subid2 == 0x03)
00416 off += snprintf(buf + off, BUFFER_SIZE - off, ", Bulk Tuning Dump Request (Bank)");
00417
00418 else if (subid == 0x08 && subid2 == 0x04)
00419 off += snprintf(buf + off, BUFFER_SIZE - off, ", Key Based Tuning Dump");
00420
00421 else if (subid == 0x08 && subid2 == 0x05)
00422 off += snprintf(buf + off, BUFFER_SIZE - off, ", Scale/Octave Tuning Dump, 1 byte format");
00423
00424 else if (subid == 0x08 && subid2 == 0x06)
00425 off += snprintf(buf + off, BUFFER_SIZE - off, ", Scale/Octave Tuning Dump, 2 byte format");
00426
00427 else if (subid == 0x08 && subid2 == 0x07)
00428 off += snprintf(buf + off, BUFFER_SIZE - off, ", Single Note Tuning Change (Bank)");
00429
00430 else if (subid == 0x09)
00431 off += snprintf(buf + off, BUFFER_SIZE - off, ", General MIDI %s", subid2 == 0 ? "disable" : "enable");
00432
00433 else if (subid == 0x7C)
00434 off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump Wait");
00435
00436 else if (subid == 0x7D)
00437 off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump Cancel");
00438
00439 else if (subid == 0x7E)
00440 off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump NAK");
00441
00442 else if (subid == 0x7F)
00443 off += snprintf(buf + off, BUFFER_SIZE - off, ", Sample Dump ACK");
00444
00445 else
00446 off += snprintf(buf + off, BUFFER_SIZE - off, ", Unknown");
00447
00448 return (buf);
00449 }
00450
00451 static char *
00452 smf_event_decode_system_common(const smf_event_t *event)
00453 {
00454 int off = 0;
00455 char *buf;
00456
00457 assert(smf_event_is_system_common(event));
00458
00459 if (smf_event_is_sysex(event))
00460 return (smf_event_decode_sysex(event));
00461
00462 buf = malloc(BUFFER_SIZE);
00463 if (buf == NULL) {
00464 g_critical("smf_event_decode_system_realtime: malloc failed.");
00465 return (NULL);
00466 }
00467
00468 switch (event->midi_buffer[0]) {
00469 case 0xF1:
00470 off += snprintf(buf + off, BUFFER_SIZE - off, "MTC Quarter Frame");
00471 break;
00472
00473 case 0xF2:
00474 off += snprintf(buf + off, BUFFER_SIZE - off, "Song Position Pointer");
00475 break;
00476
00477 case 0xF3:
00478 off += snprintf(buf + off, BUFFER_SIZE - off, "Song Select");
00479 break;
00480
00481 case 0xF6:
00482 off += snprintf(buf + off, BUFFER_SIZE - off, "Tune Request");
00483 break;
00484
00485 default:
00486 free(buf);
00487 return (NULL);
00488 }
00489
00490 return (buf);
00491 }
00492
00493 static void
00494 note_from_int(char *buf, int note_number)
00495 {
00496 int note, octave;
00497 char *names[] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
00498
00499 octave = note_number / 12 - 1;
00500 note = note_number % 12;
00501
00502 sprintf(buf, "%s%d", names[note], octave);
00503 }
00504
00513 char *
00514 smf_event_decode(const smf_event_t *event)
00515 {
00516 int off = 0, channel;
00517 char *buf, note[5];
00518
00519 if (smf_event_is_metadata(event))
00520 return (smf_event_decode_metadata(event));
00521
00522 if (smf_event_is_system_realtime(event))
00523 return (smf_event_decode_system_realtime(event));
00524
00525 if (smf_event_is_system_common(event))
00526 return (smf_event_decode_system_common(event));
00527
00528 if (!smf_event_length_is_valid(event)) {
00529 g_critical("smf_event_decode: incorrect MIDI message length.");
00530 return (NULL);
00531 }
00532
00533 buf = malloc(BUFFER_SIZE);
00534 if (buf == NULL) {
00535 g_critical("smf_event_decode: malloc failed.");
00536 return (NULL);
00537 }
00538
00539
00540 channel = (event->midi_buffer[0] & 0x0F) + 1;
00541
00542 switch (event->midi_buffer[0] & 0xF0) {
00543 case 0x80:
00544 note_from_int(note, event->midi_buffer[1]);
00545 off += snprintf(buf + off, BUFFER_SIZE - off, "Note Off, channel %d, note %s, velocity %d",
00546 channel, note, event->midi_buffer[2]);
00547 break;
00548
00549 case 0x90:
00550 note_from_int(note, event->midi_buffer[1]);
00551 off += snprintf(buf + off, BUFFER_SIZE - off, "Note On, channel %d, note %s, velocity %d",
00552 channel, note, event->midi_buffer[2]);
00553 break;
00554
00555 case 0xA0:
00556 note_from_int(note, event->midi_buffer[1]);
00557 off += snprintf(buf + off, BUFFER_SIZE - off, "Aftertouch, channel %d, note %s, pressure %d",
00558 channel, note, event->midi_buffer[2]);
00559 break;
00560
00561 case 0xB0:
00562 off += snprintf(buf + off, BUFFER_SIZE - off, "Controller, channel %d, controller %d, value %d",
00563 channel, event->midi_buffer[1], event->midi_buffer[2]);
00564 break;
00565
00566 case 0xC0:
00567 off += snprintf(buf + off, BUFFER_SIZE - off, "Program Change, channel %d, controller %d",
00568 channel, event->midi_buffer[1]);
00569 break;
00570
00571 case 0xD0:
00572 off += snprintf(buf + off, BUFFER_SIZE - off, "Channel Pressure, channel %d, pressure %d",
00573 channel, event->midi_buffer[1]);
00574 break;
00575
00576 case 0xE0:
00577 off += snprintf(buf + off, BUFFER_SIZE - off, "Pitch Wheel, channel %d, value %d",
00578 channel, ((int)event->midi_buffer[2] << 7) | (int)event->midi_buffer[2]);
00579 break;
00580
00581 default:
00582 free(buf);
00583 return (NULL);
00584 }
00585
00586 return (buf);
00587 }
00588
00597 char *
00598 smf_decode(const smf_t *smf)
00599 {
00600 int off = 0;
00601 char *buf;
00602
00603 buf = malloc(BUFFER_SIZE);
00604 if (buf == NULL) {
00605 g_critical("smf_event_decode: malloc failed.");
00606 return (NULL);
00607 }
00608
00609 off += snprintf(buf + off, BUFFER_SIZE - off, "format: %d ", smf->format);
00610
00611 switch (smf->format) {
00612 case 0:
00613 off += snprintf(buf + off, BUFFER_SIZE - off, "(single track)");
00614 break;
00615
00616 case 1:
00617 off += snprintf(buf + off, BUFFER_SIZE - off, "(several simultaneous tracks)");
00618 break;
00619
00620 case 2:
00621 off += snprintf(buf + off, BUFFER_SIZE - off, "(several independent tracks)");
00622 break;
00623
00624 default:
00625 off += snprintf(buf + off, BUFFER_SIZE - off, "(INVALID FORMAT)");
00626 break;
00627 }
00628
00629 off += snprintf(buf + off, BUFFER_SIZE - off, "; number of tracks: %d", smf->number_of_tracks);
00630
00631 if (smf->ppqn != 0)
00632 off += snprintf(buf + off, BUFFER_SIZE - off, "; division: %d PPQN", smf->ppqn);
00633 else
00634 off += snprintf(buf + off, BUFFER_SIZE - off, "; division: %d FPS, %d resolution", smf->frames_per_second, smf->resolution);
00635
00636 return (buf);
00637 }
00638