mfmidi.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. /*
  2. * Read a Standard MIDI File. Externally-assigned function pointers are
  3. * called upon recognizing things in the file. See midifile(3).
  4. */
  5. /*****************************************************************************
  6. * Change Log
  7. * Date | who : Change
  8. *-----------+-----------------------------------------------------------------
  9. * 2-Mar-92 | GWL : created changelog; MIDIFILE_ERROR to satisfy compiler
  10. *****************************************************************************/
  11. #include "stdio.h"
  12. #include "mfmidi.h"
  13. #include "string.h"
  14. #include "assert.h"
  15. #define MIDIFILE_ERROR -1
  16. /* public stuff */
  17. extern int abort_flag;
  18. void Midifile_reader::midifile()
  19. {
  20. int ntrks;
  21. midifile_error = 0;
  22. ntrks = readheader();
  23. if (midifile_error) return;
  24. if (ntrks <= 0) {
  25. mferror("No tracks!");
  26. /* no need to return since midifile_error is set */
  27. }
  28. while (ntrks-- > 0 && !midifile_error) readtrack();
  29. }
  30. int Midifile_reader::readmt(const char *s, int skip)
  31. /* read through the "MThd" or "MTrk" header string */
  32. /* if skip == 1, we attempt to skip initial garbage. */
  33. {
  34. assert(strlen(s) == 4); // must be "MThd" or "MTrk"
  35. int nread = 0;
  36. char b[4];
  37. char buff[32];
  38. int c;
  39. const char *errmsg = "expecting ";
  40. retry:
  41. while ( nread<4 ) {
  42. c = Mf_getc();
  43. if ( c == EOF ) {
  44. errmsg = "EOF while expecting ";
  45. goto err;
  46. }
  47. b[nread++] = c;
  48. }
  49. /* See if we found the 4 characters we're looking for */
  50. if ( s[0]==b[0] && s[1]==b[1] && s[2]==b[2] && s[3]==b[3] )
  51. return(0);
  52. if ( skip ) {
  53. /* If we are supposed to skip initial garbage, */
  54. /* try again with the next character. */
  55. b[0]=b[1];
  56. b[1]=b[2];
  57. b[2]=b[3];
  58. nread = 3;
  59. goto retry;
  60. }
  61. err:
  62. //#pragma warning(disable: 4996) // strcpy is safe since strings have known lengths
  63. (void) strcpy(buff,errmsg);
  64. (void) strcat(buff,s);
  65. //#pragma warning(default: 4996) // turn it back on
  66. mferror(buff);
  67. return(0);
  68. }
  69. int Midifile_reader::egetc()
  70. /* read a single character and abort on EOF */
  71. {
  72. int c = Mf_getc();
  73. if ( c == EOF ) {
  74. mferror("premature EOF");
  75. return EOF;
  76. }
  77. Mf_toberead--;
  78. return(c);
  79. }
  80. int Midifile_reader::readheader()
  81. /* read a header chunk */
  82. {
  83. int format, ntrks, division;
  84. if ( readmt("MThd",Mf_skipinit) == EOF )
  85. return(0);
  86. Mf_toberead = read32bit();
  87. if (midifile_error) return MIDIFILE_ERROR;
  88. format = read16bit();
  89. if (midifile_error) return MIDIFILE_ERROR;
  90. ntrks = read16bit();
  91. if (midifile_error) return MIDIFILE_ERROR;
  92. division = read16bit();
  93. if (midifile_error) return MIDIFILE_ERROR;
  94. Mf_header(format,ntrks,division);
  95. /* flush any extra stuff, in case the length of header is not 6 */
  96. while ( Mf_toberead > 0 && !midifile_error)
  97. (void) egetc();
  98. return(ntrks);
  99. }
  100. void Midifile_reader::readtrack()
  101. /* read a track chunk */
  102. {
  103. /* This array is indexed by the high half of a status byte. It's */
  104. /* value is either the number of bytes needed (1 or 2) for a channel */
  105. /* message, or 0 (meaning it's not a channel message). */
  106. static int chantype[] = {
  107. 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 through 0x70 */
  108. 2, 2, 2, 2, 1, 1, 2, 0 /* 0x80 through 0xf0 */
  109. };
  110. long lookfor, lng;
  111. int c, c1, type;
  112. int sysexcontinue = 0; /* 1 if last message was an unfinished sysex */
  113. int running = 0; /* 1 when running status used */
  114. int status = 0; /* (possibly running) status byte */
  115. int needed;
  116. if ( readmt("MTrk",0) == EOF )
  117. return;
  118. Mf_toberead = read32bit();
  119. if (midifile_error) return;
  120. Mf_currtime = 0L;
  121. Mf_starttrack();
  122. while ( Mf_toberead > 0 ) {
  123. Mf_currtime += readvarinum(); /* delta time */
  124. if (midifile_error) return;
  125. c = egetc();
  126. if (midifile_error) return;
  127. if ( sysexcontinue && c != 0xf7 ) {
  128. mferror("didn't find expected continuation of a sysex");
  129. return;
  130. }
  131. if ( (c & 0x80) == 0 ) { /* running status? */
  132. if ( status == 0 ) {
  133. mferror("unexpected running status");
  134. return;
  135. }
  136. running = 1;
  137. } else {
  138. status = c;
  139. running = 0;
  140. }
  141. needed = chantype[ (status>>4) & 0xf ];
  142. if ( needed ) { /* ie. is it a channel message? */
  143. if ( running )
  144. c1 = c;
  145. else {
  146. c1 = egetc();
  147. if (midifile_error) return;
  148. }
  149. chanmessage( status, c1, (needed>1) ? egetc() : 0 );
  150. if (midifile_error) return;
  151. continue;;
  152. }
  153. switch ( c ) {
  154. case 0xff: /* meta event */
  155. type = egetc();
  156. if (midifile_error) return;
  157. /* watch out - Don't combine the next 2 statements */
  158. lng = readvarinum();
  159. if (midifile_error) return;
  160. lookfor = Mf_toberead - lng;
  161. msginit();
  162. while ( Mf_toberead > lookfor ) {
  163. unsigned char c = egetc();
  164. if (midifile_error) return;
  165. msgadd(c);
  166. }
  167. metaevent(type);
  168. break;
  169. case 0xf0: /* start of system exclusive */
  170. /* watch out - Don't combine the next 2 statements */
  171. lng = readvarinum();
  172. if (midifile_error) return;
  173. lookfor = Mf_toberead - lng;
  174. msginit();
  175. msgadd(0xf0);
  176. while ( Mf_toberead > lookfor ) {
  177. c = egetc();
  178. if (midifile_error) return;
  179. msgadd(c);
  180. }
  181. if ( c==0xf7 || Mf_nomerge==0 )
  182. sysex();
  183. else
  184. sysexcontinue = 1; /* merge into next msg */
  185. break;
  186. case 0xf7: /* sysex continuation or arbitrary stuff */
  187. /* watch out - Don't combine the next 2 statements */
  188. lng = readvarinum();
  189. if (midifile_error) return;
  190. lookfor = Mf_toberead - lng;
  191. if ( ! sysexcontinue )
  192. msginit();
  193. while ( Mf_toberead > lookfor ) {
  194. c = egetc();
  195. if (midifile_error) return;
  196. msgadd(c);
  197. }
  198. if ( ! sysexcontinue ) {
  199. Mf_arbitrary(msgleng(), msg());
  200. }
  201. else if ( c == 0xf7 ) {
  202. sysex();
  203. sysexcontinue = 0;
  204. }
  205. break;
  206. default:
  207. badbyte(c);
  208. break;
  209. }
  210. }
  211. Mf_endtrack();
  212. return;
  213. }
  214. void Midifile_reader::badbyte(int c)
  215. {
  216. char buff[32];
  217. //#pragma warning(disable: 4996) // safe in this case
  218. (void) sprintf(buff,"unexpected byte: 0x%02x",c);
  219. //#pragma warning(default: 4996)
  220. mferror(buff);
  221. }
  222. void Midifile_reader::metaevent(int type)
  223. {
  224. int leng = msgleng();
  225. // made this unsigned to avoid sign extend
  226. unsigned char *m = msg();
  227. switch ( type ) {
  228. case 0x00:
  229. Mf_seqnum(to16bit(m[0],m[1]));
  230. break;
  231. case 0x01: /* Text event */
  232. case 0x02: /* Copyright notice */
  233. case 0x03: /* Sequence/Track name */
  234. case 0x04: /* Instrument name */
  235. case 0x05: /* Lyric */
  236. case 0x06: /* Marker */
  237. case 0x07: /* Cue point */
  238. case 0x08:
  239. case 0x09:
  240. case 0x0a:
  241. case 0x0b:
  242. case 0x0c:
  243. case 0x0d:
  244. case 0x0e:
  245. case 0x0f:
  246. /* These are all text events */
  247. Mf_text(type,leng,m);
  248. break;
  249. case 0x20:
  250. Mf_chanprefix(m[0]);
  251. break;
  252. case 0x21:
  253. Mf_portprefix(m[0]);
  254. break;
  255. case 0x2f: /* End of Track */
  256. Mf_eot();
  257. break;
  258. case 0x51: /* Set tempo */
  259. Mf_tempo(to32bit(0,m[0],m[1],m[2]));
  260. break;
  261. case 0x54:
  262. Mf_smpte(m[0],m[1],m[2],m[3],m[4]);
  263. break;
  264. case 0x58:
  265. Mf_timesig(m[0],m[1],m[2],m[3]);
  266. break;
  267. case 0x59:
  268. Mf_keysig(m[0],m[1]);
  269. break;
  270. case 0x7f:
  271. Mf_sqspecific(leng,m);
  272. break;
  273. default:
  274. Mf_metamisc(type,leng,m);
  275. }
  276. }
  277. void Midifile_reader::sysex()
  278. {
  279. Mf_sysex(msgleng(), msg());
  280. }
  281. void Midifile_reader::chanmessage(int status, int c1, int c2)
  282. {
  283. int chan = status & 0xf;
  284. switch ( status & 0xf0 ) {
  285. case NOTEOFF:
  286. Mf_off(chan,c1,c2);
  287. break;
  288. case NOTEON:
  289. Mf_on(chan,c1,c2);
  290. break;
  291. case PRESSURE:
  292. Mf_pressure(chan,c1,c2);
  293. break;
  294. case CONTROLLER:
  295. Mf_controller(chan,c1,c2);
  296. break;
  297. case PITCHBEND:
  298. Mf_pitchbend(chan,c1,c2);
  299. break;
  300. case PROGRAM:
  301. Mf_program(chan,c1);
  302. break;
  303. case CHANPRESSURE:
  304. Mf_chanpressure(chan,c1);
  305. break;
  306. }
  307. }
  308. /* readvarinum - read a varying-length number, and return the */
  309. /* number of characters it took. */
  310. long Midifile_reader::readvarinum()
  311. {
  312. long value;
  313. int c;
  314. c = egetc();
  315. if (midifile_error) return 0;
  316. value = (long) c;
  317. if ( c & 0x80 ) {
  318. value &= 0x7f;
  319. do {
  320. c = egetc();
  321. if (midifile_error) return 0;
  322. value = (value << 7) + (c & 0x7f);
  323. } while (c & 0x80);
  324. }
  325. return (value);
  326. }
  327. long Midifile_reader::to32bit(int c1, int c2, int c3, int c4)
  328. {
  329. long value = 0L;
  330. value = (c1 & 0xff);
  331. value = (value<<8) + (c2 & 0xff);
  332. value = (value<<8) + (c3 & 0xff);
  333. value = (value<<8) + (c4 & 0xff);
  334. return (value);
  335. }
  336. int Midifile_reader::to16bit(int c1, int c2)
  337. {
  338. return ((c1 & 0xff ) << 8) + (c2 & 0xff);
  339. }
  340. long Midifile_reader::read32bit()
  341. {
  342. int c1, c2, c3, c4;
  343. c1 = egetc(); if (midifile_error) return 0;
  344. c2 = egetc(); if (midifile_error) return 0;
  345. c3 = egetc(); if (midifile_error) return 0;
  346. c4 = egetc(); if (midifile_error) return 0;
  347. return to32bit(c1,c2,c3,c4);
  348. }
  349. int Midifile_reader::read16bit()
  350. {
  351. int c1, c2;
  352. c1 = egetc(); if (midifile_error) return 0;
  353. c2 = egetc(); if (midifile_error) return 0;
  354. return to16bit(c1,c2);
  355. }
  356. void Midifile_reader::mferror(char *s)
  357. {
  358. Mf_error(s);
  359. midifile_error = 1;
  360. }
  361. void Midifile_reader::mferror(const char *s)
  362. {
  363. mferror(const_cast<char *>(s));
  364. }
  365. /* The code below allows collection of a system exclusive message of */
  366. /* arbitrary length. The Msgbuff is expanded as necessary. The only */
  367. /* visible data/routines are msginit(), msgadd(), msg(), msgleng(). */
  368. #define MSGINCREMENT 128
  369. Midifile_reader::Midifile_reader()
  370. {
  371. Mf_nomerge = 0;
  372. Mf_currtime = 0L;
  373. Mf_skipinit = 0;
  374. Mf_toberead = 0;
  375. Msgbuff = 0; /* message buffer */
  376. Msgsize = 0; /* Size of currently allocated Msg */
  377. Msgindex = 0; /* index of next available location in Msg */
  378. }
  379. void Midifile_reader::finalize()
  380. {
  381. if (Msgbuff) Mf_free(Msgbuff, Msgsize);
  382. Msgbuff = nullptr;
  383. }
  384. void Midifile_reader::msginit()
  385. {
  386. Msgindex = 0;
  387. }
  388. unsigned char *Midifile_reader::msg()
  389. {
  390. return(Msgbuff);
  391. }
  392. int Midifile_reader::msgleng()
  393. {
  394. return(Msgindex);
  395. }
  396. void Midifile_reader::msgadd(int c)
  397. {
  398. /* If necessary, allocate larger message buffer. */
  399. if ( Msgindex >= Msgsize )
  400. msgenlarge();
  401. Msgbuff[Msgindex++] = c;
  402. }
  403. void Midifile_reader::msgenlarge()
  404. {
  405. unsigned char *newmess;
  406. unsigned char *oldmess = Msgbuff;
  407. int oldleng = Msgsize;
  408. Msgsize += MSGINCREMENT;
  409. newmess = (unsigned char *) Mf_malloc((sizeof(unsigned char) * Msgsize) );
  410. /* copy old message into larger new one */
  411. if ( oldmess != 0 ) {
  412. memcpy(newmess, oldmess, oldleng);
  413. Mf_free(oldmess, oldleng);
  414. }
  415. Msgbuff = newmess;
  416. }