PageRenderTime 65ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/exult/tags/Release0_40/audio/xmidi.cc

#
C++ | 1294 lines | 967 code | 227 blank | 100 comment | 210 complexity | 86ceac229f3bddaf9b88c00b14a2849e MD5 | raw file
Possible License(s): GPL-2.0
  1. #include <unistd.h>
  2. #include <stdio.h>
  3. #include <iostream>
  4. #include "utils.h"
  5. #include "xmidi.h"
  6. // This is used to correct incorrect patch, vol and pan changes in midi files
  7. // The bias is just a value to used to work out if a vol and pan belong with a
  8. // patch change. This is to ensure that the default state of a midi file is with
  9. // the tracks centred, unless the first patch change says otherwise.
  10. #define PATCH_VOL_PAN_BIAS 5
  11. // This is a default set of patches to convert from MT32 to GM
  12. // The index is the MT32 Patch nubmer and the value is the GM Patch
  13. // This is only suitable for music that doesn'tdo timbre changes
  14. // XMIDIs that contain Timbre changes will not convert properly
  15. unsigned char XMIDI::mt32asgm[128] = {
  16. 0, // 0 Piano 1
  17. 1, // 1 Piano 2
  18. 2, // 2 Piano 3 (synth)
  19. 4, // 3 EPiano 1
  20. 4, // 4 EPiano 2
  21. 5, // 5 EPiano 3
  22. 5, // 6 EPiano 4
  23. 3, // 7 Honkytonk
  24. 16, // 8 Organ 1
  25. 17, // 9 Organ 2
  26. 18, // 10 Organ 3
  27. 16, // 11 Organ 4
  28. 19, // 12 Pipe Organ 1
  29. 19, // 13 Pipe Organ 2
  30. 19, // 14 Pipe Organ 3
  31. 21, // 15 Accordion
  32. 6, // 16 Harpsichord 1
  33. 6, // 17 Harpsichord 2
  34. 6, // 18 Harpsichord 3
  35. 7, // 19 Clavinet 1
  36. 7, // 20 Clavinet 2
  37. 7, // 21 Clavinet 3
  38. 8, // 22 Celesta 1
  39. 8, // 23 Celesta 2
  40. 62, // 24 Synthbrass 1 (62)
  41. 63, // 25 Synthbrass 2 (63)
  42. 62, // 26 Synthbrass 3 Bank 8
  43. 63, // 27 Synthbrass 4 Bank 8
  44. 38, // 28 Synthbass 1
  45. 39, // 29 Synthbass 2
  46. 38, // 30 Synthbass 3 Bank 8
  47. 39, // 31 Synthbass 4 Bank 8
  48. 88, // 32 Fantasy
  49. 90, // 33 Harmonic Pan - No equiv closest is polysynth(90) :(
  50. 52, // 34 Choral ?? Currently set to SynthVox(54). Should it be ChoirAhhs(52)???
  51. 92, // 35 Glass
  52. 97, // 36 Soundtrack
  53. 99, // 37 Atmosphere
  54. 14, // 38 Warmbell, sounds kind of like crystal(98) perhaps Tubular Bells(14) would be better. It is!
  55. 54, // 39 FunnyVox, sounds alot like Bagpipe(109) and Shania(111)
  56. 98, // 40 EchoBell, no real equiv, sounds like Crystal(98)
  57. 96, // 41 IceRain
  58. 68, // 42 Oboe 2001, no equiv, just patching it to normal oboe(68)
  59. 95, // 43 EchoPans, no equiv, setting to SweepPad
  60. 81, // 44 DoctorSolo Bank 8
  61. 87, // 45 SchoolDaze, no real equiv
  62. 112, // 46 Bell Singer
  63. 80, // 47 SquareWave
  64. 48, // 48 Strings 1
  65. 48, // 49 Strings 2 - should be 49
  66. 44, // 50 Strings 3 (Synth) - Experimental set to Tremollo Strings - should be 50
  67. 45, // 51 Pizzicato Strings
  68. 40, // 52 Violin 1
  69. 40, // 53 Violin 2 ? Viola
  70. 42, // 54 Cello 1
  71. 42, // 55 Cello 2
  72. 43, // 56 Contrabass
  73. 46, // 57 Harp 1
  74. 46, // 58 Harp 2
  75. 24, // 59 Guitar 1 (Nylon)
  76. 25, // 60 Guitar 2 (Steel)
  77. 26, // 61 Elec Guitar 1
  78. 27, // 62 Elec Guitar 2
  79. 104, // 63 Sitar
  80. 32, // 64 Acou Bass 1
  81. 32, // 65 Acou Bass 2
  82. 33, // 66 Elec Bass 1
  83. 34, // 67 Elec Bass 2
  84. 36, // 68 Slap Bass 1
  85. 37, // 69 Slap Bass 2
  86. 35, // 70 Fretless Bass 1
  87. 35, // 71 Fretless Bass 2
  88. 73, // 72 Flute 1
  89. 73, // 73 Flute 2
  90. 72, // 74 Piccolo 1
  91. 72, // 75 Piccolo 2
  92. 74, // 76 Recorder
  93. 75, // 77 Pan Pipes
  94. 64, // 78 Sax 1
  95. 65, // 79 Sax 2
  96. 66, // 80 Sax 3
  97. 67, // 81 Sax 4
  98. 71, // 82 Clarinet 1
  99. 71, // 83 Clarinet 2
  100. 68, // 84 Oboe
  101. 69, // 85 English Horn (Cor Anglais)
  102. 70, // 86 Bassoon
  103. 22, // 87 Harmonica
  104. 56, // 88 Trumpet 1
  105. 56, // 89 Trumpet 2
  106. 57, // 90 Trombone 1
  107. 57, // 91 Trombone 2
  108. 60, // 92 French Horn 1
  109. 60, // 93 French Horn 2
  110. 58, // 94 Tuba
  111. 61, // 95 Brass Section 1
  112. 61, // 96 Brass Section 2
  113. 11, // 97 Vibes 1
  114. 11, // 98 Vibes 2
  115. 99, // 99 Syn Mallet Bank 1
  116. 112, // 100 WindBell no real equiv Set to TinkleBell(112)
  117. 9, // 101 Glockenspiel
  118. 14, // 102 Tubular Bells
  119. 13, // 103 Xylophone
  120. 12, // 104 Marimba
  121. 107, // 105 Koto
  122. 111, // 106 Sho?? set to Shanai(111)
  123. 77, // 107 Shakauhachi
  124. 78, // 108 Whistle 1
  125. 78, // 109 Whistle 2
  126. 76, // 110 Bottle Blow
  127. 76, // 111 Breathpipe no real equiv set to bottle blow(76)
  128. 47, // 112 Timpani
  129. 117, // 113 Melodic Tom
  130. 116, // 114 Deap Snare no equiv, set to Taiko(116)
  131. 118, // 115 Electric Perc 1
  132. 118, // 116 Electric Perc 2
  133. 116, // 117 Taiko
  134. 115, // 118 Taiko Rim, no real equiv, set to Woodblock(115)
  135. 119, // 119 Cymbal, no real equiv, set to reverse cymbal(119)
  136. 115, // 120 Castanets, no real equiv, in GM set to Woodblock(115)
  137. 112, // 121 Triangle, no real equiv, set to TinkleBell(112)
  138. 55, // 122 Orchestral Hit
  139. 124, // 123 Telephone
  140. 123, // 124 BirdTweet
  141. 94, // 125 Big Notes Pad no equiv, set to halo pad (94)
  142. 98, // 126 Water Bell set to Crystal Pad(98)
  143. 121, // 127 Jungle Tune set to Breath Noise
  144. };
  145. // Constructor
  146. XMIDI::XMIDI(DataSource *source, bool pconvert) : events(NULL),timing(NULL),fixed(NULL)
  147. {
  148. convert_from_mt32 = pconvert;
  149. ExtractTracks (source);
  150. }
  151. XMIDI::~XMIDI()
  152. {
  153. if (events)
  154. {
  155. for (int i=0; i < info.tracks; i++)
  156. DeleteEventList (events[i]);
  157. delete [] events;
  158. }
  159. if (timing) delete [] timing;
  160. if (fixed) delete [] fixed;
  161. }
  162. int XMIDI::retrieve (uint32 track, DataSource *dest)
  163. {
  164. int len = 0;
  165. if (!events)
  166. {
  167. cerr << "No midi data in loaded." << endl;
  168. return 0;
  169. }
  170. // Convert type 1 midi's to type 0
  171. if (info.type == 1)
  172. {
  173. DuplicateAndMerge(-1);
  174. for (int i=0; i < info.tracks; i++)
  175. DeleteEventList (events[i]);
  176. delete [] events;
  177. events = new midi_event *[1];
  178. events[0] = list;
  179. info.tracks = 1;
  180. info.type = 0;
  181. }
  182. if (track >= info.tracks)
  183. {
  184. cerr << "Can't retrieve MIDI data, track out of range" << endl;
  185. return 0;
  186. }
  187. // And fix the midis if they are broken
  188. if (!fixed[track])
  189. {
  190. list = events[track];
  191. MovePatchVolAndPan ();
  192. fixed[track] = true;
  193. events[track] = list;
  194. }
  195. // This is so if using buffer datasource, the caller can know how big to make the buffer
  196. if (!dest)
  197. {
  198. // Header is 14 bytes long and add the rest as well
  199. len = ConvertListToMTrk (NULL, events[track]);
  200. return 14 + len;
  201. }
  202. dest->write1 ('M');
  203. dest->write1 ('T');
  204. dest->write1 ('h');
  205. dest->write1 ('d');
  206. dest->write4high (6);
  207. dest->write2high (0);
  208. dest->write2high (1);
  209. dest->write2high (timing[track]);
  210. len = ConvertListToMTrk (dest, events[track]);
  211. return len + 14;
  212. }
  213. int XMIDI::retrieve (uint32 track, midi_event **dest, int &ppqn)
  214. {
  215. if (!events)
  216. {
  217. cerr << "No midi data in loaded." << endl;
  218. return 0;
  219. }
  220. if ((info.type == 1 && track != 0) || (track >= info.tracks))
  221. {
  222. cerr << "Can't retrieve MIDI data, track out of range" << endl;
  223. return 0;
  224. }
  225. DuplicateAndMerge(track);
  226. MovePatchVolAndPan ();
  227. *dest = list;
  228. ppqn = timing[track];
  229. return 1;
  230. }
  231. void XMIDI::DeleteEventList (midi_event *mlist)
  232. {
  233. midi_event *event;
  234. midi_event *next;
  235. next = mlist;
  236. event = mlist;
  237. while ((event = next))
  238. {
  239. next = event->next;
  240. if (event->buffer) delete [] event->buffer;
  241. delete event;
  242. }
  243. }
  244. // Sets current to the new event and updates list
  245. void XMIDI::CreateNewEvent (int time)
  246. {
  247. if (!list)
  248. {
  249. list = current = new midi_event;
  250. current->next = NULL;
  251. if (time < 0)
  252. current->time = 0;
  253. else
  254. current->time = time;
  255. current->buffer = NULL;
  256. current->len = 0;
  257. return;
  258. }
  259. if (time < 0)
  260. {
  261. midi_event *event = new midi_event;
  262. event->next = list;
  263. list = current = event;
  264. current->time = 0;
  265. current->buffer = NULL;
  266. current->len = 0;
  267. return;
  268. }
  269. if (current->time > time)
  270. current = list;
  271. while (current->next)
  272. {
  273. if (current->next->time > time)
  274. {
  275. midi_event *event = new midi_event;
  276. event->next = current->next;
  277. current->next = event;
  278. current = event;
  279. current->time = time;
  280. current->buffer = NULL;
  281. current->len = 0;
  282. return;
  283. }
  284. current = current->next;
  285. }
  286. current->next = new midi_event;
  287. current = current->next;
  288. current->next = NULL;
  289. current->time = time;
  290. current->buffer = NULL;
  291. current->len = 0;
  292. }
  293. // Conventional Variable Length Quantity
  294. int XMIDI::GetVLQ (DataSource *source, uint32 &quant)
  295. {
  296. int i;
  297. quant = 0;
  298. unsigned int data;
  299. for (i = 0; i < 4; i++)
  300. {
  301. data = source->read1();
  302. quant <<= 7;
  303. quant |= data & 0x7F;
  304. if (!(data & 0x80))
  305. {
  306. i++;
  307. break;
  308. }
  309. }
  310. return i;
  311. }
  312. // XMIDI Delta Variable Length Quantity
  313. int XMIDI::GetVLQ2 (DataSource *source, uint32 &quant)
  314. {
  315. int i;
  316. quant = 0;
  317. int data = 0;
  318. for (i = 0; i < 4; i++)
  319. {
  320. data = source->read1();
  321. if (data & 0x80)
  322. {
  323. source->skip(-1);
  324. break;
  325. }
  326. quant += data;
  327. }
  328. return i;
  329. }
  330. int XMIDI::PutVLQ(DataSource *dest, uint32 value)
  331. {
  332. int buffer;
  333. int i = 1;
  334. buffer = value & 0x7F;
  335. while (value >>= 7)
  336. {
  337. buffer <<= 8;
  338. buffer |= ((value & 0x7F) | 0x80);
  339. i++;
  340. }
  341. if (!dest) return i;
  342. for (int j = 0; j < i; j++)
  343. {
  344. dest->write1(buffer & 0xFF);
  345. buffer >>= 8;
  346. }
  347. return i;
  348. }
  349. // MovePatchVolAndPan
  350. //
  351. // This little function attempts to correct errors in midi files
  352. // that relate to patch, volume and pan changing
  353. void XMIDI::MovePatchVolAndPan (int channel)
  354. {
  355. if (channel == -1)
  356. {
  357. for (int i = 0; i < 16; i++)
  358. MovePatchVolAndPan (i);
  359. return;
  360. }
  361. midi_event *patch = NULL;
  362. midi_event *vol = NULL;
  363. midi_event *pan = NULL;
  364. midi_event *bank = NULL;
  365. midi_event *prev = NULL;
  366. for (current = list; current; )
  367. {
  368. if (!patch && (current->status >> 4) == 0xC && (current->status & 0xF) == channel)
  369. {
  370. patch = current;
  371. if (prev) prev->next = patch->next;
  372. else list = patch->next;
  373. current = prev;
  374. }
  375. else if (!vol && (current->status >> 4) == 0xB && current->data[0] == 7 && (current->status & 0xF) == channel)
  376. {
  377. vol = current;
  378. if (prev) prev->next = vol->next;
  379. else list = vol->next;
  380. current = prev;
  381. }
  382. else if (!pan && (current->status >> 4) == 0xB && current->data[0] == 10 && (current->status & 0xF) == channel)
  383. {
  384. pan = current;
  385. if (prev) prev->next = pan->next;
  386. else list = pan->next;
  387. current = prev;
  388. }
  389. else if (!bank && (current->status >> 4) == 0xB && current->data[0] == 0 && (current->status & 0xF) == channel)
  390. {
  391. bank = current;
  392. if (prev) prev->next = bank->next;
  393. else list = bank->next;
  394. current = prev;
  395. }
  396. else
  397. prev = current;
  398. if (pan && vol && patch) break;
  399. if (current) current = current->next;
  400. else current = list;
  401. }
  402. // Got none of them, do nothing
  403. if (!patch) return;
  404. if (!patch)
  405. {
  406. patch = new midi_event;
  407. patch->status = channel + 0xC0;
  408. patch->data[0] = 0;
  409. patch->len = 0;
  410. patch->buffer = NULL;
  411. }
  412. if (vol && (vol->time > patch->time+PATCH_VOL_PAN_BIAS || vol->time < patch->time-PATCH_VOL_PAN_BIAS))
  413. {
  414. vol = NULL;
  415. }
  416. if (!vol)
  417. {
  418. vol = new midi_event;
  419. vol->status = channel + 0xB0;
  420. vol->data[0] = 7;
  421. vol->data[1] = 64;
  422. vol->len = 0;
  423. vol->buffer = NULL;
  424. }
  425. if (bank && (bank->time > patch->time+PATCH_VOL_PAN_BIAS || bank->time < patch->time-PATCH_VOL_PAN_BIAS))
  426. {
  427. bank = NULL;
  428. }
  429. if (!bank)
  430. {
  431. bank = new midi_event;
  432. bank->status = channel + 0xB0;
  433. bank->data[0] = 0;
  434. bank->data[1] = 0;
  435. bank->len = 0;
  436. bank->buffer = NULL;
  437. }
  438. if (pan && (pan->time > patch->time+PATCH_VOL_PAN_BIAS || pan->time < patch->time-PATCH_VOL_PAN_BIAS))
  439. {
  440. pan = NULL;
  441. }
  442. if (!pan)
  443. {
  444. pan = new midi_event;
  445. pan->status = channel + 0xB0;
  446. pan->data[0] = 10;
  447. pan->data[1] = 64;
  448. pan->len = 0;
  449. pan->buffer = NULL;
  450. }
  451. vol->time = 0;
  452. pan->time = 0;
  453. patch->time = 0;
  454. bank->time = 0;
  455. bank->next = vol;
  456. vol->next = pan;
  457. pan->next = patch;
  458. patch->next = list;
  459. list = bank;
  460. }
  461. // DuplicateAndMerge
  462. void XMIDI::DuplicateAndMerge (int num)
  463. {
  464. int i;
  465. midi_event **track;
  466. int time = 0;
  467. int start = 0;
  468. int end = 1;
  469. if (info.type == 1)
  470. {
  471. start = 0;
  472. end = info.tracks;
  473. }
  474. else if (num >= 0 && num < info.tracks)
  475. {
  476. start += num;
  477. end += num;
  478. }
  479. track = new midi_event *[info.tracks];
  480. for (i = 0; i < info.tracks; i++) track[i] = events[i];
  481. current = list = NULL;
  482. while (1)
  483. {
  484. int lowest = 1 << 30;
  485. int selected = -1;
  486. int num_na = end-start;
  487. // Firstly we find the track with the lowest time
  488. // for it's current event
  489. for (i = start; i < end; i++)
  490. {
  491. if (!track[i])
  492. {
  493. num_na--;
  494. continue;
  495. }
  496. if (track[i]->time < lowest)
  497. {
  498. selected = i;
  499. lowest = track[i]->time;
  500. }
  501. }
  502. // This is just so I don't have to type [selected] all the time
  503. i = selected;
  504. // None left to convert
  505. if (!num_na) break;
  506. // Only need 1 end of track
  507. // So take the last one and ignore the rest;
  508. if ((num_na != 1) && (track[i]->status == 0xff) && (track[i]->data[0] == 0x2f))
  509. {
  510. track[i] = NULL;
  511. continue;
  512. }
  513. if (current)
  514. {
  515. current->next = new midi_event;
  516. current = current->next;
  517. }
  518. else
  519. list = current = new midi_event;
  520. current->next = NULL;
  521. time = track[i]->time;
  522. current->time = time;
  523. current->status = track[i]->status;
  524. current->data[0] = track[i]->data[0];
  525. current->data[1] = track[i]->data[1];
  526. current->len = track[i]->len;
  527. if (current->len)
  528. {
  529. current->buffer = new unsigned char[current->len];
  530. memcpy (current->buffer, track[i]->buffer, current->len);
  531. }
  532. else
  533. current->buffer = NULL;
  534. track[i] = track[i]->next;
  535. }
  536. }
  537. // Converts Events
  538. //
  539. // Source is at the first data byte
  540. // size 1 is single data byte
  541. // size 2 is dual data byte
  542. // size 3 is XMI Note on
  543. // Returns bytes converted
  544. #if 0
  545. static const char *event_type[] =
  546. {
  547. "note off",
  548. "note on",
  549. "after touch",
  550. "control change",
  551. "patch change",
  552. "channel pressure",
  553. "pitch wheel",
  554. "NME"
  555. };
  556. static void *load_global_timbre(FILE *GTL, int bank, int patch)
  557. {
  558. unsigned char *timb_ptr;
  559. static unsigned len;
  560. char GTL_hdr_patch;
  561. char GTL_hdr_bank;
  562. unsigned long GTL_hdr_offset;
  563. if (GTL==NULL) return NULL; // if no GTL, return failure
  564. rewind(GTL); // else rewind to GTL header
  565. do // search file for requested timbre
  566. {
  567. GTL_hdr_patch = getc (GTL);
  568. GTL_hdr_bank = getc (GTL);
  569. GTL_hdr_offset = Read4 (GTL);
  570. if (GTL_hdr_bank == -1)
  571. return NULL; // timbre not found, return NULL
  572. }
  573. while ((GTL_hdr_bank != bank) ||
  574. (GTL_hdr_patch != patch));
  575. fseek(GTL,GTL_hdr_offset,SEEK_SET);
  576. //fread(&len,2,1,GTL); // timbre found, read its length
  577. len = Read2 (GTL);
  578. timb_ptr = (unsigned char *) malloc(len); // allocate memory for timbre ..
  579. // and load it
  580. fread(timb_ptr,len-2,1,GTL);
  581. *timb_ptr = len;
  582. // and load it
  583. fread((timb_ptr+1),len-2,1,GTL);
  584. FILE *fout = fopen ("temp", "wb");
  585. fwrite ((timb_ptr+1),len-2,1,fout);
  586. fclose (fout);
  587. if (ferror(GTL)) // return NULL if any errors
  588. return NULL; // occurred
  589. else
  590. return timb_ptr; // else return pointer to timbre
  591. }
  592. int timbre[16] = {
  593. 0,0,0,0,
  594. 0,0,0,0,
  595. 0,0,0,0,
  596. 0,0,0,0
  597. };
  598. #endif
  599. int XMIDI::ConvertEvent (const int time, const unsigned char status, DataSource *source, const int size)
  600. {
  601. uint32 delta = 0;
  602. int data;
  603. CreateNewEvent (time);
  604. current->status = status;
  605. data = current->data[0] = source->read1();
  606. // Handling for patch change mt32 conversion, probably should go elsewhere
  607. if (((status >> 4) == 0xC) && convert_from_mt32)
  608. current->data[0] = mt32asgm[current->data[0]];
  609. #if 0 // This was just for a test, when working with the SFX
  610. if ((status >> 4) == 0xC && timbre[(status&0xF)])
  611. {
  612. FILE *tfile = U7open ("c:/uc/serpent/static/xmidi.mt", "rb");
  613. if (tfile)
  614. {
  615. char *timb = (char *) load_global_timbre(tfile, timbre[(status&0xF)], current->data[0]);
  616. if (timb)
  617. {
  618. timb[13] = 0;
  619. cout << timb+3 << endl;
  620. free (timb);
  621. }
  622. }
  623. }
  624. #endif
  625. if (size == 1)
  626. return 1;
  627. current->data[1] = source->read1();
  628. // XMIDI Bank change
  629. // if ((status >> 4) == 0xB && current->data[0] == 114)
  630. // timbre[(status&0xF)]=current->data[1];
  631. if (size == 2)
  632. return 2;
  633. // XMI Note On handling
  634. int i = GetVLQ (source, delta);
  635. CreateNewEvent (time+delta*3);
  636. current->status = status;
  637. current->data[0] = data;
  638. current->data[1] = 0;
  639. return i + 2;
  640. }
  641. // Simple routine to convert system messages
  642. int XMIDI::ConvertSystemMessage (const int time, const unsigned char status, DataSource *source)
  643. {
  644. int i=0;
  645. CreateNewEvent (time);
  646. current->status = status;
  647. // Handling of Meta events
  648. if (status == 0xFF)
  649. {
  650. current->data[0] = source->read1();
  651. i++;
  652. }
  653. i += GetVLQ (source, current->len);
  654. if (!current->len) return i;
  655. current->buffer = new unsigned char[current->len];
  656. source->read ((char *) current->buffer, current->len);
  657. return i+current->len;
  658. }
  659. // XMIDI and Midi to List
  660. // Returns XMIDI PPQN
  661. int XMIDI::ConvertFiletoList (DataSource *source, const bool is_xmi)
  662. {
  663. int time = 0;
  664. uint32 data;
  665. int end = 0;
  666. int tempo = 500000;
  667. int tempo_set = 0;
  668. uint32 status;
  669. int play_size = 2;
  670. if (is_xmi) play_size = 3;
  671. while (!end && source->getPos() < source->getSize())
  672. {
  673. if (!is_xmi)
  674. {
  675. GetVLQ (source, data);
  676. time += data;
  677. data = source->read1();
  678. if (data >= 0x80)
  679. {
  680. status = data;
  681. }
  682. else
  683. source->skip (-1);
  684. }
  685. else
  686. {
  687. GetVLQ2 (source, data);
  688. time += data*3;
  689. status = source->read1();
  690. }
  691. switch (status >> 4)
  692. {
  693. // Note On
  694. case 0x9:
  695. ConvertEvent (time, status, source, play_size);
  696. break;
  697. // 2 byte data
  698. // Note off, Aftertouch, Controller and Pitch Wheel
  699. case 0x8: case 0xA: case 0xB: case 0xE:
  700. ConvertEvent (time, status, source, 2);
  701. break;
  702. // 1 byte data
  703. // Program Change and Channel Pressure
  704. case 0xC: case 0xD:
  705. ConvertEvent (time, status, source, 1);
  706. break;
  707. // SysEx
  708. case 0xF:
  709. if (status == 0xFF)
  710. {
  711. int pos = source->getPos();
  712. uint32 data = source->read1();
  713. if (data == 0x2F) // End
  714. end = 1;
  715. else if (data == 0x51 && !tempo_set) // Tempo. Need it for PPQN
  716. {
  717. source->skip(1);
  718. tempo = source->read1() << 16;
  719. tempo += source->read1() << 8;
  720. tempo += source->read1();
  721. tempo *= 3;
  722. tempo_set = 1;
  723. }
  724. else if (data == 0x51 && tempo_set && is_xmi) // Skip any other tempo changes
  725. {
  726. GetVLQ (source, data);
  727. source->skip(data);
  728. break;
  729. }
  730. source->seek (pos);
  731. }
  732. ConvertSystemMessage (time, status, source);
  733. break;
  734. default:
  735. break;
  736. }
  737. }
  738. return (tempo*3)/25000;
  739. }
  740. // Converts and event list to a MTrk
  741. // Returns bytes of the array
  742. // buf can be NULL
  743. uint32 XMIDI::ConvertListToMTrk (DataSource *dest, midi_event *mlist)
  744. {
  745. int time = 0;
  746. midi_event *event;
  747. uint32 delta;
  748. unsigned char last_status = 0;
  749. uint32 i = 8;
  750. uint32 j;
  751. uint32 size_pos=0;
  752. bool end = false;
  753. if (dest)
  754. {
  755. dest->write1('M');
  756. dest->write1('T');
  757. dest->write1('r');
  758. dest->write1('k');
  759. size_pos = dest->getPos();
  760. dest->skip(4);
  761. }
  762. for (event = mlist; event && !end; event=event->next)
  763. {
  764. delta = (event->time - time);
  765. time = event->time;
  766. i += PutVLQ (dest, delta);
  767. if ((event->status != last_status) || (event->status >= 0xF0))
  768. {
  769. if (dest) dest->write1(event->status);
  770. i++;
  771. }
  772. last_status = event->status;
  773. switch (event->status >> 4)
  774. {
  775. // 2 bytes data
  776. // Note off, Note on, Aftertouch, Controller and Pitch Wheel
  777. case 0x8: case 0x9: case 0xA: case 0xB: case 0xE:
  778. if (dest)
  779. {
  780. dest->write1(event->data[0]);
  781. dest->write1(event->data[1]);
  782. }
  783. i += 2;
  784. break;
  785. // 1 bytes data
  786. // Program Change and Channel Pressure
  787. case 0xC: case 0xD:
  788. if (dest) dest->write1(event->data[0]);
  789. i++;
  790. break;
  791. // Variable length
  792. // SysEx
  793. case 0xF:
  794. if (event->status == 0xFF)
  795. {
  796. if (event->data[0] == 0x2f) end = true;
  797. if (dest) dest->write1(event->data[0]);
  798. i++;
  799. }
  800. i += PutVLQ (dest, event->len);
  801. if (event->len)
  802. {
  803. for (j = 0; j < event->len; j++)
  804. {
  805. if (dest) dest->write1(event->buffer[j]);
  806. i++;
  807. }
  808. }
  809. break;
  810. // Never occur
  811. default:
  812. cerr << "Not supposed to see this" << endl;
  813. break;
  814. }
  815. }
  816. if (dest)
  817. {
  818. int cur_pos = dest->getPos();
  819. dest->seek (size_pos);
  820. dest->write4high (i-8);
  821. dest->seek (cur_pos);
  822. }
  823. return i;
  824. }
  825. // Assumes correct xmidi
  826. int XMIDI::ExtractTracksFromXmi (DataSource *source)
  827. {
  828. int num = 0;
  829. signed short ppqn;
  830. uint32 len = 0;
  831. char buf[32];
  832. while (source->getPos() < source->getSize() && num != info.tracks)
  833. {
  834. // Read first 4 bytes of name
  835. source->read (buf, 4);
  836. len = source->read4high();
  837. // Skip the FORM entries
  838. if (!memcmp(buf,"FORM",4))
  839. {
  840. source->skip (4);
  841. source->read (buf, 4);
  842. len = source->read4high();
  843. }
  844. if (memcmp(buf,"EVNT",4))
  845. {
  846. source->skip ((len+1)&~1);
  847. continue;
  848. }
  849. list = NULL;
  850. int begin = source->getPos ();
  851. // Convert it
  852. if (!(ppqn = ConvertFiletoList (source, true)))
  853. {
  854. cerr << "Unable to convert data" << endl;
  855. break;
  856. }
  857. timing[num] = ppqn;
  858. events[num] = list;
  859. // Increment Counter
  860. num++;
  861. // go to start of next track
  862. source->seek (begin + ((len+1)&~1));
  863. }
  864. // Return how many were converted
  865. return num;
  866. }
  867. int XMIDI::ExtractTracksFromMid (DataSource *source)
  868. {
  869. int num = 0;
  870. uint32 len = 0;
  871. char buf[32];
  872. while (source->getPos() < source->getSize() && num != info.tracks)
  873. {
  874. // Read first 4 bytes of name
  875. source->read (buf, 4);
  876. len = source->read4high();
  877. if (memcmp(buf,"MTrk",4))
  878. {
  879. source->skip (len);
  880. continue;
  881. }
  882. list = NULL;
  883. int begin = source->getPos ();
  884. // Convert it
  885. if (!ConvertFiletoList (source, false))
  886. {
  887. cerr << "Unable to convert data" << endl;
  888. break;
  889. }
  890. events[num] = list;
  891. // Increment Counter
  892. num++;
  893. source->seek (begin+len);
  894. }
  895. // Return how many were converted
  896. return num;
  897. }
  898. int XMIDI::ExtractTracks (DataSource *source)
  899. {
  900. uint32 i = 0;
  901. int start;
  902. uint32 len;
  903. uint32 chunk_len;
  904. int count;
  905. char buf[32];
  906. // Read first 4 bytes of header
  907. source->read (buf, 4);
  908. // Could be XMIDI
  909. if (!memcmp (buf, "FORM", 4))
  910. {
  911. // Read length of
  912. len = source->read4high();
  913. start = source->getPos();
  914. // Read 4 bytes of type
  915. source->read (buf, 4);
  916. // XDIRless XMIDI, we can handle them here.
  917. if (!memcmp (buf, "XMID", 4))
  918. {
  919. cerr << "Warning: XMIDI doesn't have XDIR" << endl;
  920. info.tracks = 1;
  921. } // Not an XMIDI that we recognise
  922. else if (memcmp (buf, "XDIR", 4))
  923. {
  924. cerr << "Not a recognised XMID" << endl;
  925. return 0;
  926. } // Seems Valid
  927. else
  928. {
  929. info.tracks = 0;
  930. for (i = 4; i < len; i++)
  931. {
  932. // Read 4 bytes of type
  933. source->read (buf, 4);
  934. // Read length of chunk
  935. chunk_len = source->read4high();
  936. // Add eight bytes
  937. i+=8;
  938. if (memcmp (buf, "INFO", 4))
  939. {
  940. // Must allign
  941. source->skip((chunk_len+1)&~1);
  942. i+= (chunk_len+1)&~1;
  943. continue;
  944. }
  945. // Must be at least 2 bytes long
  946. if (chunk_len < 2)
  947. break;
  948. info.tracks = source->read2();
  949. break;
  950. }
  951. // Didn't get to fill the header
  952. if (info.tracks == 0)
  953. {
  954. cerr << "Not a valid XMID" << endl;
  955. return 0;
  956. }
  957. // Ok now to start part 2
  958. // Goto the right place
  959. source->seek (start+((len+1)&~1));
  960. // Read 4 bytes of type
  961. source->read (buf, 4);
  962. // Not an XMID
  963. if (memcmp (buf, "CAT ", 4))
  964. {
  965. cerr << "Not a recognised XMID (" << buf[0] << buf[1] << buf[2] << buf[3] << ") should be (CAT )" << endl;
  966. return 0;
  967. }
  968. // Now read length of this track
  969. len = source->read4high();
  970. // Read 4 bytes of type
  971. source->read (buf, 4);
  972. // Not an XMID
  973. if (memcmp (buf, "XMID", 4))
  974. {
  975. cerr << "Not a recognised XMID (" << buf[0] << buf[1] << buf[2] << buf[3] << ") should be (XMID)" << endl;
  976. return 0;
  977. }
  978. }
  979. // Ok it's an XMID, so pass it to the ExtractCode
  980. events = new midi_event *[info.tracks];
  981. timing = new short[info.tracks];
  982. fixed = new bool[info.tracks];
  983. info.type = 0;
  984. for (i = 0; i < info.tracks; i++)
  985. {
  986. events[i] = NULL;
  987. fixed[i] = false;
  988. }
  989. count = ExtractTracksFromXmi (source);
  990. if (count != info.tracks)
  991. {
  992. cerr << "Error: unable to extract all (" << info.tracks << ") tracks specified from XMIDI. Only ("<< count << ")" << endl;
  993. int i = 0;
  994. for (i = 0; i < info.tracks; i++)
  995. DeleteEventList (events[i]);
  996. delete [] events;
  997. delete [] timing;
  998. return 0;
  999. }
  1000. return 1;
  1001. }// Definately a Midi
  1002. else if (!memcmp (buf, "MThd", 4))
  1003. {
  1004. // Simple read length of header
  1005. len = source->read4high();
  1006. if (len < 6)
  1007. {
  1008. cerr << "Not a valid MIDI" << endl;
  1009. return 0;
  1010. }
  1011. info.type = source->read2high();
  1012. info.tracks = source->read2high();
  1013. events = new midi_event *[info.tracks];
  1014. timing = new short[info.tracks];
  1015. fixed = new bool[info.tracks];
  1016. timing[0] = source->read2high();
  1017. for (i = 0; i < info.tracks; i++)
  1018. {
  1019. timing[i] = timing[0];
  1020. events[i] = NULL;
  1021. fixed[i] = false;
  1022. }
  1023. count = ExtractTracksFromMid (source);
  1024. if (count != info.tracks)
  1025. {
  1026. cerr << "Error: unable to extract all (" << info.tracks << ") tracks specified from MIDI. Only ("<< count << ")" << endl;
  1027. for (i = 0; i < info.tracks; i++)
  1028. DeleteEventList (events[i]);
  1029. delete [] events;
  1030. delete [] timing;
  1031. return 0;
  1032. }
  1033. return 1;
  1034. }// A RIFF Midi, just pass the source back to this function at the start of the midi file
  1035. else if (!memcmp (buf, "RIFF", 4))
  1036. {
  1037. // Read len
  1038. len = source->read4();
  1039. // Read 4 bytes of type
  1040. source->read (buf, 4);
  1041. // Not an RMID
  1042. if (memcmp (buf, "RMID", 4))
  1043. {
  1044. cerr << "Invalid RMID" << endl;
  1045. return 0;
  1046. }
  1047. // Is a RMID
  1048. for (i = 4; i < len; i++)
  1049. {
  1050. // Read 4 bytes of type
  1051. source->read (buf, 4);
  1052. chunk_len = source->read4();
  1053. i+=8;
  1054. if (memcmp (buf, "data", 4))
  1055. {
  1056. // Must allign
  1057. source->skip ((chunk_len+1)&~1);
  1058. i+= (chunk_len+1)&~1;
  1059. continue;
  1060. }
  1061. return ExtractTracks (source);
  1062. }
  1063. cerr << "Failed to find midi data in RIFF Midi" << endl;
  1064. return 0;
  1065. }
  1066. return 0;
  1067. }