module.audio.midi.php 19 KB

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