module.audio.midi.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. <?php
  2. /////////////////////////////////////////////////////////////////
  3. /// getID3() by James Heinrich <info@getid3.org> //
  4. // available at http://getid3.sourceforge.net //
  5. // or http://www.getid3.org //
  6. /////////////////////////////////////////////////////////////////
  7. // See readme.txt for more details //
  8. /////////////////////////////////////////////////////////////////
  9. // //
  10. // module.audio.midi.php //
  11. // module for Midi Audio files //
  12. // dependencies: NONE //
  13. // ///
  14. /////////////////////////////////////////////////////////////////
  15. class getid3_midi
  16. {
  17. function getid3_midi(&$fd, &$ThisFileInfo, $scanwholefile=true) {
  18. // shortcut
  19. $ThisFileInfo['midi']['raw'] = array();
  20. $thisfile_midi = &$ThisFileInfo['midi'];
  21. $thisfile_midi_raw = &$thisfile_midi['raw'];
  22. $ThisFileInfo['fileformat'] = 'midi';
  23. $ThisFileInfo['audio']['dataformat'] = 'midi';
  24. fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
  25. $MIDIdata = fread($fd, GETID3_FREAD_BUFFER_SIZE);
  26. $offset = 0;
  27. $MIDIheaderID = substr($MIDIdata, $offset, 4); // 'MThd'
  28. if ($MIDIheaderID != 'MThd') {
  29. $ThisFileInfo['error'][] = 'Expecting "MThd" at offset '.$ThisFileInfo['avdataoffset'].', found "'.$MIDIheaderID.'"';
  30. unset($ThisFileInfo['fileformat']);
  31. return false;
  32. }
  33. $offset += 4;
  34. $thisfile_midi_raw['headersize'] = getid3_lib::BigEndian2Int(substr($MIDIdata, $offset, 4));
  35. $offset += 4;
  36. $thisfile_midi_raw['fileformat'] = getid3_lib::BigEndian2Int(substr($MIDIdata, $offset, 2));
  37. $offset += 2;
  38. $thisfile_midi_raw['tracks'] = getid3_lib::BigEndian2Int(substr($MIDIdata, $offset, 2));
  39. $offset += 2;
  40. $thisfile_midi_raw['ticksperqnote'] = getid3_lib::BigEndian2Int(substr($MIDIdata, $offset, 2));
  41. $offset += 2;
  42. for ($i = 0; $i < $thisfile_midi_raw['tracks']; $i++) {
  43. if ((strlen($MIDIdata) - $offset) < 8) {
  44. $MIDIdata .= fread($fd, GETID3_FREAD_BUFFER_SIZE);
  45. }
  46. $trackID = substr($MIDIdata, $offset, 4);
  47. $offset += 4;
  48. if ($trackID == 'MTrk') {
  49. $tracksize = getid3_lib::BigEndian2Int(substr($MIDIdata, $offset, 4));
  50. $offset += 4;
  51. // $thisfile_midi['tracks'][$i]['size'] = $tracksize;
  52. $trackdataarray[$i] = substr($MIDIdata, $offset, $tracksize);
  53. $offset += $tracksize;
  54. } else {
  55. $ThisFileInfo['error'][] = 'Expecting "MTrk" at '.$offset.', found '.$trackID.' instead';
  56. return false;
  57. }
  58. }
  59. if (!isset($trackdataarray) || !is_array($trackdataarray)) {
  60. $ThisFileInfo['error'][] = 'Cannot find MIDI track information';
  61. unset($thisfile_midi);
  62. unset($ThisFileInfo['fileformat']);
  63. return false;
  64. }
  65. if ($scanwholefile) { // this can take quite a long time, so have the option to bypass it if speed is very important
  66. $thisfile_midi['totalticks'] = 0;
  67. $ThisFileInfo['playtime_seconds'] = 0;
  68. $CurrentMicroSecondsPerBeat = 500000; // 120 beats per minute; 60,000,000 microseconds per minute -> 500,000 microseconds per beat
  69. $CurrentBeatsPerMinute = 120; // 120 beats per minute; 60,000,000 microseconds per minute -> 500,000 microseconds per beat
  70. $MicroSecondsPerQuarterNoteAfter = array ();
  71. foreach ($trackdataarray as $tracknumber => $trackdata) {
  72. $eventsoffset = 0;
  73. $LastIssuedMIDIcommand = 0;
  74. $LastIssuedMIDIchannel = 0;
  75. $CumulativeDeltaTime = 0;
  76. $TicksAtCurrentBPM = 0;
  77. while ($eventsoffset < strlen($trackdata)) {
  78. $eventid = 0;
  79. if (isset($MIDIevents[$tracknumber]) && is_array($MIDIevents[$tracknumber])) {
  80. $eventid = count($MIDIevents[$tracknumber]);
  81. }
  82. $deltatime = 0;
  83. for ($i = 0; $i < 4; $i++) {
  84. $deltatimebyte = ord(substr($trackdata, $eventsoffset++, 1));
  85. $deltatime = ($deltatime << 7) + ($deltatimebyte & 0x7F);
  86. if ($deltatimebyte & 0x80) {
  87. // another byte follows
  88. } else {
  89. break;
  90. }
  91. }
  92. $CumulativeDeltaTime += $deltatime;
  93. $TicksAtCurrentBPM += $deltatime;
  94. $MIDIevents[$tracknumber][$eventid]['deltatime'] = $deltatime;
  95. $MIDI_event_channel = ord(substr($trackdata, $eventsoffset++, 1));
  96. if ($MIDI_event_channel & 0x80) {
  97. // OK, normal event - MIDI command has MSB set
  98. $LastIssuedMIDIcommand = $MIDI_event_channel >> 4;
  99. $LastIssuedMIDIchannel = $MIDI_event_channel & 0x0F;
  100. } else {
  101. // running event - assume last command
  102. $eventsoffset--;
  103. }
  104. $MIDIevents[$tracknumber][$eventid]['eventid'] = $LastIssuedMIDIcommand;
  105. $MIDIevents[$tracknumber][$eventid]['channel'] = $LastIssuedMIDIchannel;
  106. if ($MIDIevents[$tracknumber][$eventid]['eventid'] == 0x08) { // Note off (key is released)
  107. $notenumber = ord(substr($trackdata, $eventsoffset++, 1));
  108. $velocity = ord(substr($trackdata, $eventsoffset++, 1));
  109. } elseif ($MIDIevents[$tracknumber][$eventid]['eventid'] == 0x09) { // Note on (key is pressed)
  110. $notenumber = ord(substr($trackdata, $eventsoffset++, 1));
  111. $velocity = ord(substr($trackdata, $eventsoffset++, 1));
  112. } elseif ($MIDIevents[$tracknumber][$eventid]['eventid'] == 0x0A) { // Key after-touch
  113. $notenumber = ord(substr($trackdata, $eventsoffset++, 1));
  114. $velocity = ord(substr($trackdata, $eventsoffset++, 1));
  115. } elseif ($MIDIevents[$tracknumber][$eventid]['eventid'] == 0x0B) { // Control Change
  116. $controllernum = ord(substr($trackdata, $eventsoffset++, 1));
  117. $newvalue = ord(substr($trackdata, $eventsoffset++, 1));
  118. } elseif ($MIDIevents[$tracknumber][$eventid]['eventid'] == 0x0C) { // Program (patch) change
  119. $newprogramnum = ord(substr($trackdata, $eventsoffset++, 1));
  120. $thisfile_midi_raw['track'][$tracknumber]['instrumentid'] = $newprogramnum;
  121. if ($tracknumber == 10) {
  122. $thisfile_midi_raw['track'][$tracknumber]['instrument'] = $this->GeneralMIDIpercussionLookup($newprogramnum);
  123. } else {
  124. $thisfile_midi_raw['track'][$tracknumber]['instrument'] = $this->GeneralMIDIinstrumentLookup($newprogramnum);
  125. }
  126. } elseif ($MIDIevents[$tracknumber][$eventid]['eventid'] == 0x0D) { // Channel after-touch
  127. $channelnumber = ord(substr($trackdata, $eventsoffset++, 1));
  128. } elseif ($MIDIevents[$tracknumber][$eventid]['eventid'] == 0x0E) { // Pitch wheel change (2000H is normal or no change)
  129. $changeLSB = ord(substr($trackdata, $eventsoffset++, 1));
  130. $changeMSB = ord(substr($trackdata, $eventsoffset++, 1));
  131. $pitchwheelchange = (($changeMSB & 0x7F) << 7) & ($changeLSB & 0x7F);
  132. } elseif (($MIDIevents[$tracknumber][$eventid]['eventid'] == 0x0F) && ($MIDIevents[$tracknumber][$eventid]['channel'] == 0x0F)) {
  133. $METAeventCommand = ord(substr($trackdata, $eventsoffset++, 1));
  134. $METAeventLength = ord(substr($trackdata, $eventsoffset++, 1));
  135. $METAeventData = substr($trackdata, $eventsoffset, $METAeventLength);
  136. $eventsoffset += $METAeventLength;
  137. switch ($METAeventCommand) {
  138. case 0x00: // Set track sequence number
  139. $track_sequence_number = getid3_lib::BigEndian2Int(substr($METAeventData, 0, $METAeventLength));
  140. //$thisfile_midi_raw['events'][$tracknumber][$eventid]['seqno'] = $track_sequence_number;
  141. break;
  142. case 0x01: // Text: generic
  143. $text_generic = substr($METAeventData, 0, $METAeventLength);
  144. //$thisfile_midi_raw['events'][$tracknumber][$eventid]['text'] = $text_generic;
  145. $thisfile_midi['comments']['comment'][] = $text_generic;
  146. break;
  147. case 0x02: // Text: copyright
  148. $text_copyright = substr($METAeventData, 0, $METAeventLength);
  149. //$thisfile_midi_raw['events'][$tracknumber][$eventid]['copyright'] = $text_copyright;
  150. $thisfile_midi['comments']['copyright'][] = $text_copyright;
  151. break;
  152. case 0x03: // Text: track name
  153. $text_trackname = substr($METAeventData, 0, $METAeventLength);
  154. $thisfile_midi_raw['track'][$tracknumber]['name'] = $text_trackname;
  155. break;
  156. case 0x04: // Text: track instrument name
  157. $text_instrument = substr($METAeventData, 0, $METAeventLength);
  158. //$thisfile_midi_raw['events'][$tracknumber][$eventid]['instrument'] = $text_instrument;
  159. break;
  160. case 0x05: // Text: lyrics
  161. $text_lyrics = substr($METAeventData, 0, $METAeventLength);
  162. //$thisfile_midi_raw['events'][$tracknumber][$eventid]['lyrics'] = $text_lyrics;
  163. if (!isset($thisfile_midi['lyrics'])) {
  164. $thisfile_midi['lyrics'] = '';
  165. }
  166. $thisfile_midi['lyrics'] .= $text_lyrics."\n";
  167. break;
  168. case 0x06: // Text: marker
  169. $text_marker = substr($METAeventData, 0, $METAeventLength);
  170. //$thisfile_midi_raw['events'][$tracknumber][$eventid]['marker'] = $text_marker;
  171. break;
  172. case 0x07: // Text: cue point
  173. $text_cuepoint = substr($METAeventData, 0, $METAeventLength);
  174. //$thisfile_midi_raw['events'][$tracknumber][$eventid]['cuepoint'] = $text_cuepoint;
  175. break;
  176. case 0x2F: // End Of Track
  177. //$thisfile_midi_raw['events'][$tracknumber][$eventid]['EOT'] = $CumulativeDeltaTime;
  178. break;
  179. case 0x51: // Tempo: microseconds / quarter note
  180. $CurrentMicroSecondsPerBeat = getid3_lib::BigEndian2Int(substr($METAeventData, 0, $METAeventLength));
  181. if ($CurrentMicroSecondsPerBeat == 0) {
  182. $ThisFileInfo['error'][] = 'Corrupt MIDI file: CurrentMicroSecondsPerBeat == zero';
  183. return false;
  184. }
  185. $thisfile_midi_raw['events'][$tracknumber][$CumulativeDeltaTime]['us_qnote'] = $CurrentMicroSecondsPerBeat;
  186. $CurrentBeatsPerMinute = (1000000 / $CurrentMicroSecondsPerBeat) * 60;
  187. $MicroSecondsPerQuarterNoteAfter[$CumulativeDeltaTime] = $CurrentMicroSecondsPerBeat;
  188. $TicksAtCurrentBPM = 0;
  189. break;
  190. case 0x58: // Time signature
  191. $timesig_numerator = getid3_lib::BigEndian2Int($METAeventData{0});
  192. $timesig_denominator = pow(2, getid3_lib::BigEndian2Int($METAeventData{1})); // $02 -> x/4, $03 -> x/8, etc
  193. $timesig_32inqnote = getid3_lib::BigEndian2Int($METAeventData{2}); // number of 32nd notes to the quarter note
  194. //$thisfile_midi_raw['events'][$tracknumber][$eventid]['timesig_32inqnote'] = $timesig_32inqnote;
  195. //$thisfile_midi_raw['events'][$tracknumber][$eventid]['timesig_numerator'] = $timesig_numerator;
  196. //$thisfile_midi_raw['events'][$tracknumber][$eventid]['timesig_denominator'] = $timesig_denominator;
  197. //$thisfile_midi_raw['events'][$tracknumber][$eventid]['timesig_text'] = $timesig_numerator.'/'.$timesig_denominator;
  198. $thisfile_midi['timesignature'][] = $timesig_numerator.'/'.$timesig_denominator;
  199. break;
  200. case 0x59: // Keysignature
  201. $keysig_sharpsflats = getid3_lib::BigEndian2Int($METAeventData{0});
  202. if ($keysig_sharpsflats & 0x80) {
  203. // (-7 -> 7 flats, 0 ->key of C, 7 -> 7 sharps)
  204. $keysig_sharpsflats -= 256;
  205. }
  206. $keysig_majorminor = getid3_lib::BigEndian2Int($METAeventData{1}); // 0 -> major, 1 -> minor
  207. $keysigs = array(-7=>'Cb', -6=>'Gb', -5=>'Db', -4=>'Ab', -3=>'Eb', -2=>'Bb', -1=>'F', 0=>'C', 1=>'G', 2=>'D', 3=>'A', 4=>'E', 5=>'B', 6=>'F#', 7=>'C#');
  208. //$thisfile_midi_raw['events'][$tracknumber][$eventid]['keysig_sharps'] = (($keysig_sharpsflats > 0) ? abs($keysig_sharpsflats) : 0);
  209. //$thisfile_midi_raw['events'][$tracknumber][$eventid]['keysig_flats'] = (($keysig_sharpsflats < 0) ? abs($keysig_sharpsflats) : 0);
  210. //$thisfile_midi_raw['events'][$tracknumber][$eventid]['keysig_minor'] = (bool) $keysig_majorminor;
  211. //$thisfile_midi_raw['events'][$tracknumber][$eventid]['keysig_text'] = $keysigs[$keysig_sharpsflats].' '.($thisfile_midi_raw['events'][$tracknumber][$eventid]['keysig_minor'] ? 'minor' : 'major');
  212. // $keysigs[$keysig_sharpsflats] gets an int key (correct) - $keysigs["$keysig_sharpsflats"] gets a string key (incorrect)
  213. $thisfile_midi['keysignature'][] = $keysigs[$keysig_sharpsflats].' '.((bool) $keysig_majorminor ? 'minor' : 'major');
  214. break;
  215. case 0x7F: // Sequencer specific information
  216. $custom_data = substr($METAeventData, 0, $METAeventLength);
  217. break;
  218. default:
  219. $ThisFileInfo['warning'][] = 'Unhandled META Event Command: '.$METAeventCommand;
  220. break;
  221. }
  222. } else {
  223. $ThisFileInfo['warning'][] = 'Unhandled MIDI Event ID: '.$MIDIevents[$tracknumber][$eventid]['eventid'].' + Channel ID: '.$MIDIevents[$tracknumber][$eventid]['channel'];
  224. }
  225. }
  226. if (($tracknumber > 0) || (count($trackdataarray) == 1)) {
  227. $thisfile_midi['totalticks'] = max($thisfile_midi['totalticks'], $CumulativeDeltaTime);
  228. }
  229. }
  230. $previoustickoffset = null;
  231. ksort($MicroSecondsPerQuarterNoteAfter);
  232. foreach ($MicroSecondsPerQuarterNoteAfter as $tickoffset => $microsecondsperbeat) {
  233. if (is_null($previoustickoffset)) {
  234. $prevmicrosecondsperbeat = $microsecondsperbeat;
  235. $previoustickoffset = $tickoffset;
  236. continue;
  237. }
  238. if ($thisfile_midi['totalticks'] > $tickoffset) {
  239. if ($thisfile_midi_raw['ticksperqnote'] == 0) {
  240. $ThisFileInfo['error'][] = 'Corrupt MIDI file: ticksperqnote == zero';
  241. return false;
  242. }
  243. $ThisFileInfo['playtime_seconds'] += (($tickoffset - $previoustickoffset) / $thisfile_midi_raw['ticksperqnote']) * ($prevmicrosecondsperbeat / 1000000);
  244. $prevmicrosecondsperbeat = $microsecondsperbeat;
  245. $previoustickoffset = $tickoffset;
  246. }
  247. }
  248. if ($thisfile_midi['totalticks'] > $previoustickoffset) {
  249. if ($thisfile_midi_raw['ticksperqnote'] == 0) {
  250. $ThisFileInfo['error'][] = 'Corrupt MIDI file: ticksperqnote == zero';
  251. return false;
  252. }
  253. $ThisFileInfo['playtime_seconds'] += (($thisfile_midi['totalticks'] - $previoustickoffset) / $thisfile_midi_raw['ticksperqnote']) * ($microsecondsperbeat / 1000000);
  254. }
  255. }
  256. if (@$ThisFileInfo['playtime_seconds'] > 0) {
  257. $ThisFileInfo['bitrate'] = (($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / $ThisFileInfo['playtime_seconds'];
  258. }
  259. if (!empty($thisfile_midi['lyrics'])) {
  260. $thisfile_midi['comments']['lyrics'][] = $thisfile_midi['lyrics'];
  261. }
  262. return true;
  263. }
  264. function GeneralMIDIinstrumentLookup($instrumentid) {
  265. $begin = __LINE__;
  266. /** This is not a comment!
  267. 0 Acoustic Grand
  268. 1 Bright Acoustic
  269. 2 Electric Grand
  270. 3 Honky-Tonk
  271. 4 Electric Piano 1
  272. 5 Electric Piano 2
  273. 6 Harpsichord
  274. 7 Clavier
  275. 8 Celesta
  276. 9 Glockenspiel
  277. 10 Music Box
  278. 11 Vibraphone
  279. 12 Marimba
  280. 13 Xylophone
  281. 14 Tubular Bells
  282. 15 Dulcimer
  283. 16 Drawbar Organ
  284. 17 Percussive Organ
  285. 18 Rock Organ
  286. 19 Church Organ
  287. 20 Reed Organ
  288. 21 Accordian
  289. 22 Harmonica
  290. 23 Tango Accordian
  291. 24 Acoustic Guitar (nylon)
  292. 25 Acoustic Guitar (steel)
  293. 26 Electric Guitar (jazz)
  294. 27 Electric Guitar (clean)
  295. 28 Electric Guitar (muted)
  296. 29 Overdriven Guitar
  297. 30 Distortion Guitar
  298. 31 Guitar Harmonics
  299. 32 Acoustic Bass
  300. 33 Electric Bass (finger)
  301. 34 Electric Bass (pick)
  302. 35 Fretless Bass
  303. 36 Slap Bass 1
  304. 37 Slap Bass 2
  305. 38 Synth Bass 1
  306. 39 Synth Bass 2
  307. 40 Violin
  308. 41 Viola
  309. 42 Cello
  310. 43 Contrabass
  311. 44 Tremolo Strings
  312. 45 Pizzicato Strings
  313. 46 Orchestral Strings
  314. 47 Timpani
  315. 48 String Ensemble 1
  316. 49 String Ensemble 2
  317. 50 SynthStrings 1
  318. 51 SynthStrings 2
  319. 52 Choir Aahs
  320. 53 Voice Oohs
  321. 54 Synth Voice
  322. 55 Orchestra Hit
  323. 56 Trumpet
  324. 57 Trombone
  325. 58 Tuba
  326. 59 Muted Trumpet
  327. 60 French Horn
  328. 61 Brass Section
  329. 62 SynthBrass 1
  330. 63 SynthBrass 2
  331. 64 Soprano Sax
  332. 65 Alto Sax
  333. 66 Tenor Sax
  334. 67 Baritone Sax
  335. 68 Oboe
  336. 69 English Horn
  337. 70 Bassoon
  338. 71 Clarinet
  339. 72 Piccolo
  340. 73 Flute
  341. 74 Recorder
  342. 75 Pan Flute
  343. 76 Blown Bottle
  344. 77 Shakuhachi
  345. 78 Whistle
  346. 79 Ocarina
  347. 80 Lead 1 (square)
  348. 81 Lead 2 (sawtooth)
  349. 82 Lead 3 (calliope)
  350. 83 Lead 4 (chiff)
  351. 84 Lead 5 (charang)
  352. 85 Lead 6 (voice)
  353. 86 Lead 7 (fifths)
  354. 87 Lead 8 (bass + lead)
  355. 88 Pad 1 (new age)
  356. 89 Pad 2 (warm)
  357. 90 Pad 3 (polysynth)
  358. 91 Pad 4 (choir)
  359. 92 Pad 5 (bowed)
  360. 93 Pad 6 (metallic)
  361. 94 Pad 7 (halo)
  362. 95 Pad 8 (sweep)
  363. 96 FX 1 (rain)
  364. 97 FX 2 (soundtrack)
  365. 98 FX 3 (crystal)
  366. 99 FX 4 (atmosphere)
  367. 100 FX 5 (brightness)
  368. 101 FX 6 (goblins)
  369. 102 FX 7 (echoes)
  370. 103 FX 8 (sci-fi)
  371. 104 Sitar
  372. 105 Banjo
  373. 106 Shamisen
  374. 107 Koto
  375. 108 Kalimba
  376. 109 Bagpipe
  377. 110 Fiddle
  378. 111 Shanai
  379. 112 Tinkle Bell
  380. 113 Agogo
  381. 114 Steel Drums
  382. 115 Woodblock
  383. 116 Taiko Drum
  384. 117 Melodic Tom
  385. 118 Synth Drum
  386. 119 Reverse Cymbal
  387. 120 Guitar Fret Noise
  388. 121 Breath Noise
  389. 122 Seashore
  390. 123 Bird Tweet
  391. 124 Telephone Ring
  392. 125 Helicopter
  393. 126 Applause
  394. 127 Gunshot
  395. */
  396. return getid3_lib::EmbeddedLookup($instrumentid, $begin, __LINE__, __FILE__, 'GeneralMIDIinstrument');
  397. }
  398. function GeneralMIDIpercussionLookup($instrumentid) {
  399. $begin = __LINE__;
  400. /** This is not a comment!
  401. 35 Acoustic Bass Drum
  402. 36 Bass Drum 1
  403. 37 Side Stick
  404. 38 Acoustic Snare
  405. 39 Hand Clap
  406. 40 Electric Snare
  407. 41 Low Floor Tom
  408. 42 Closed Hi-Hat
  409. 43 High Floor Tom
  410. 44 Pedal Hi-Hat
  411. 45 Low Tom
  412. 46 Open Hi-Hat
  413. 47 Low-Mid Tom
  414. 48 Hi-Mid Tom
  415. 49 Crash Cymbal 1
  416. 50 High Tom
  417. 51 Ride Cymbal 1
  418. 52 Chinese Cymbal
  419. 53 Ride Bell
  420. 54 Tambourine
  421. 55 Splash Cymbal
  422. 56 Cowbell
  423. 57 Crash Cymbal 2
  424. 59 Ride Cymbal 2
  425. 60 Hi Bongo
  426. 61 Low Bongo
  427. 62 Mute Hi Conga
  428. 63 Open Hi Conga
  429. 64 Low Conga
  430. 65 High Timbale
  431. 66 Low Timbale
  432. 67 High Agogo
  433. 68 Low Agogo
  434. 69 Cabasa
  435. 70 Maracas
  436. 71 Short Whistle
  437. 72 Long Whistle
  438. 73 Short Guiro
  439. 74 Long Guiro
  440. 75 Claves
  441. 76 Hi Wood Block
  442. 77 Low Wood Block
  443. 78 Mute Cuica
  444. 79 Open Cuica
  445. 80 Mute Triangle
  446. 81 Open Triangle
  447. */
  448. return getid3_lib::EmbeddedLookup($instrumentid, $begin, __LINE__, __FILE__, 'GeneralMIDIpercussion');
  449. }
  450. }
  451. ?>