// // available at http://getid3.sourceforge.net /// ///////////////////////////////////////////////////////////////// // // // getid3.midi.php - part of getID3() // // See getid3.readme.txt for more details // // // ///////////////////////////////////////////////////////////////// function getMIDIHeaderFilepointer(&$fd, &$ThisFileInfo, $scanwholefile=true) { $ThisFileInfo['fileformat'] = 'midi'; $ThisFileInfo['audio']['dataformat'] = 'midi'; fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET); $MIDIdata = fread($fd, FREAD_BUFFER_SIZE); $offset = 0; $MIDIheaderID = substr($MIDIdata, $offset, 4); // 'MThd' $offset += 4; $ThisFileInfo['midi']['raw']['headersize'] = BigEndian2Int(substr($MIDIdata, $offset, 4)); $offset += 4; $ThisFileInfo['midi']['raw']['fileformat'] = BigEndian2Int(substr($MIDIdata, $offset, 2)); $offset += 2; $ThisFileInfo['midi']['raw']['tracks'] = BigEndian2Int(substr($MIDIdata, $offset, 2)); $offset += 2; $ThisFileInfo['midi']['raw']['ticksperqnote'] = BigEndian2Int(substr($MIDIdata, $offset, 2)); $offset += 2; for ($i = 0; $i < $ThisFileInfo['midi']['raw']['tracks']; $i++) { if ((strlen($MIDIdata) - $offset) < 8) { $MIDIdata .= fread($fd, FREAD_BUFFER_SIZE); } $trackID = substr($MIDIdata, $offset, 4); $offset += 4; if ($trackID == 'MTrk') { $tracksize = BigEndian2Int(substr($MIDIdata, $offset, 4)); $offset += 4; // $ThisFileInfo['midi']['tracks'][$i]['size'] = $tracksize; $trackdataarray[$i] = substr($MIDIdata, $offset, $tracksize); $offset += $tracksize; } else { $ThisFileInfo['error'] .= "\n".'Expecting "MTrk" at '.$offset.', found '.$trackID.' instead'; return false; } } if (!isset($trackdataarray) || !is_array($trackdataarray)) { $ThisFileInfo['error'] .= "\n".'Cannot find MIDI track information'; unset($ThisFileInfo['midi']); unset($ThisFileInfo['fileformat']); return false; } if ($scanwholefile) { // this can take quite a long time, so have the option to bypass it if speed is very important $ThisFileInfo['midi']['totalticks'] = 0; $ThisFileInfo['playtime_seconds'] = 0; $CurrentMicroSecondsPerBeat = 500000; // 120 beats per minute; 60,000,000 microseconds per minute -> 500,000 microseconds per beat $CurrentBeatsPerMinute = 120; // 120 beats per minute; 60,000,000 microseconds per minute -> 500,000 microseconds per beat foreach ($trackdataarray as $tracknumber => $trackdata) { $eventsoffset = 0; $LastIssuedMIDIcommand = 0; $LastIssuedMIDIchannel = 0; $CumulativeDeltaTime = 0; $TicksAtCurrentBPM = 0; while ($eventsoffset < strlen($trackdata)) { $eventid = 0; if (isset($MIDIevents[$tracknumber]) && is_array($MIDIevents[$tracknumber])) { $eventid = count($MIDIevents[$tracknumber]); } $deltatime = 0; for ($i=0;$i<4;$i++) { $deltatimebyte = ord(substr($trackdata, $eventsoffset++, 1)); $deltatime = ($deltatime << 7) + ($deltatimebyte & 0x7F); if ($deltatimebyte & 0x80) { // another byte follows } else { break; } } $CumulativeDeltaTime += $deltatime; $TicksAtCurrentBPM += $deltatime; $MIDIevents[$tracknumber][$eventid]['deltatime'] = $deltatime; $MIDI_event_channel = ord(substr($trackdata, $eventsoffset++, 1)); if ($MIDI_event_channel & 0x80) { // OK, normal event - MIDI command has MSB set $LastIssuedMIDIcommand = $MIDI_event_channel >> 4; $LastIssuedMIDIchannel = $MIDI_event_channel & 0x0F; } else { // running event - assume last command $eventsoffset--; } $MIDIevents[$tracknumber][$eventid]['eventid'] = $LastIssuedMIDIcommand; $MIDIevents[$tracknumber][$eventid]['channel'] = $LastIssuedMIDIchannel; if ($MIDIevents[$tracknumber][$eventid]['eventid'] == 0x8) { // Note off (key is released) $notenumber = ord(substr($trackdata, $eventsoffset++, 1)); $velocity = ord(substr($trackdata, $eventsoffset++, 1)); } elseif ($MIDIevents[$tracknumber][$eventid]['eventid'] == 0x9) { // Note on (key is pressed) $notenumber = ord(substr($trackdata, $eventsoffset++, 1)); $velocity = ord(substr($trackdata, $eventsoffset++, 1)); } elseif ($MIDIevents[$tracknumber][$eventid]['eventid'] == 0xA) { // Key after-touch $notenumber = ord(substr($trackdata, $eventsoffset++, 1)); $velocity = ord(substr($trackdata, $eventsoffset++, 1)); } elseif ($MIDIevents[$tracknumber][$eventid]['eventid'] == 0xB) { // Control Change $controllernum = ord(substr($trackdata, $eventsoffset++, 1)); $newvalue = ord(substr($trackdata, $eventsoffset++, 1)); } elseif ($MIDIevents[$tracknumber][$eventid]['eventid'] == 0xC) { // Program (patch) change $newprogramnum = ord(substr($trackdata, $eventsoffset++, 1)); $ThisFileInfo['midi']['raw']['track'][$tracknumber]['instrumentid'] = $newprogramnum; if ($tracknumber == 10) { $ThisFileInfo['midi']['raw']['track'][$tracknumber]['instrument'] = GeneralMIDIpercussionLookup($newprogramnum); } else { $ThisFileInfo['midi']['raw']['track'][$tracknumber]['instrument'] = GeneralMIDIinstrumentLookup($newprogramnum); } } elseif ($MIDIevents[$tracknumber][$eventid]['eventid'] == 0xD) { // Channel after-touch $channelnumber = ord(substr($trackdata, $eventsoffset++, 1)); } elseif ($MIDIevents[$tracknumber][$eventid]['eventid'] == 0xE) { // Pitch wheel change (2000H is normal or no change) $changeLSB = ord(substr($trackdata, $eventsoffset++, 1)); $changeMSB = ord(substr($trackdata, $eventsoffset++, 1)); $pitchwheelchange = (($changeMSB & 0x7F) << 7) & ($changeLSB & 0x7F); } elseif (($MIDIevents[$tracknumber][$eventid]['eventid'] == 0xF) && ($MIDIevents[$tracknumber][$eventid]['channel'] == 0xF)) { $METAeventCommand = ord(substr($trackdata, $eventsoffset++, 1)); $METAeventLength = ord(substr($trackdata, $eventsoffset++, 1)); $METAeventData = substr($trackdata, $eventsoffset, $METAeventLength); $eventsoffset += $METAeventLength; switch ($METAeventCommand) { case 0x00: // Set track sequence number $track_sequence_number = BigEndian2Int(substr($METAeventData, 0, $METAeventLength)); //$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['seqno'] = $track_sequence_number; break; case 0x01: // Text: generic $text_generic = substr($METAeventData, 0, $METAeventLength); //$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['text'] = $text_generic; if (empty($ThisFileInfo['midi']['comments']['comment'])) { $ThisFileInfo['midi']['comments']['comment'] = ''; } $ThisFileInfo['midi']['comments']['comment'] .= $text_generic."\n"; break; case 0x02: // Text: copyright $text_copyright = substr($METAeventData, 0, $METAeventLength); //$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['copyright'] = $text_copyright; if (empty($ThisFileInfo['midi']['comments']['copyright'])) { $ThisFileInfo['midi']['comments']['copyright'] = ''; } $ThisFileInfo['midi']['comments']['copyright'] = $text_copyright."\n"; break; case 0x03: // Text: track name $text_trackname = substr($METAeventData, 0, $METAeventLength); $ThisFileInfo['midi']['raw']['track'][$tracknumber]['name'] = $text_trackname; break; case 0x04: // Text: track instrument name $text_instrument = substr($METAeventData, 0, $METAeventLength); //$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['instrument'] = $text_instrument; break; case 0x05: // Text: lyric $text_lyric = substr($METAeventData, 0, $METAeventLength); //$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['lyric'] = $text_lyric; if (!isset($ThisFileInfo['midi']['lyric'])) { $ThisFileInfo['midi']['lyric'] = ''; } $ThisFileInfo['midi']['lyric'] .= $text_lyric."\n"; break; case 0x06: // Text: marker $text_marker = substr($METAeventData, 0, $METAeventLength); //$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['marker'] = $text_marker; break; case 0x07: // Text: cue point $text_cuepoint = substr($METAeventData, 0, $METAeventLength); //$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['cuepoint'] = $text_cuepoint; break; case 0x2F: // End Of Track //$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['EOT'] = $CumulativeDeltaTime; break; case 0x51: // Tempo: microseconds / quarter note $CurrentMicroSecondsPerBeat = BigEndian2Int(substr($METAeventData, 0, $METAeventLength)); if ($CurrentMicroSecondsPerBeat == 0) { $ThisFileInfo['error'] .= "\n".'Corrupt MIDI file: CurrentMicroSecondsPerBeat == zero'; return false; } $ThisFileInfo['midi']['raw']['events'][$tracknumber][$CumulativeDeltaTime]['us_qnote'] = $CurrentMicroSecondsPerBeat; $CurrentBeatsPerMinute = (1000000 / $CurrentMicroSecondsPerBeat) * 60; $MicroSecondsPerQuarterNoteAfter[$CumulativeDeltaTime] = $CurrentMicroSecondsPerBeat; $TicksAtCurrentBPM = 0; break; case 0x58: // Time signature $timesig_numerator = BigEndian2Int($METAeventData{0}); $timesig_denominator = pow(2, BigEndian2Int($METAeventData{1})); // $02 -> x/4, $03 -> x/8, etc $timesig_32inqnote = BigEndian2Int($METAeventData{2}); // number of 32nd notes to the quarter note //$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['timesig_32inqnote'] = $timesig_32inqnote; //$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['timesig_numerator'] = $timesig_numerator; //$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['timesig_denominator'] = $timesig_denominator; //$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['timesig_text'] = $timesig_numerator.'/'.$timesig_denominator; $ThisFileInfo['midi']['timesignature'][] = $timesig_numerator.'/'.$timesig_denominator; break; case 0x59: // Keysignature $keysig_sharpsflats = BigEndian2Int($METAeventData{0}); if ($keysig_sharpsflats & 0x80) { // (-7 -> 7 flats, 0 ->key of C, 7 -> 7 sharps) $keysig_sharpsflats -= 256; } $keysig_majorminor = BigEndian2Int($METAeventData{1}); // 0 -> major, 1 -> minor $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#'); //$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['keysig_sharps'] = (($keysig_sharpsflats > 0) ? abs($keysig_sharpsflats) : 0); //$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['keysig_flats'] = (($keysig_sharpsflats < 0) ? abs($keysig_sharpsflats) : 0); //$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['keysig_minor'] = (bool) $keysig_majorminor; //$ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['keysig_text'] = $keysigs[$keysig_sharpsflats].' '.($ThisFileInfo['midi']['raw']['events'][$tracknumber][$eventid]['keysig_minor'] ? 'minor' : 'major'); // $keysigs[$keysig_sharpsflats] gets an int key (correct) - $keysigs["$keysig_sharpsflats"] gets a string key (incorrect) $ThisFileInfo['midi']['keysignature'][] = $keysigs[$keysig_sharpsflats].' '.((bool) $keysig_majorminor ? 'minor' : 'major'); break; case 0x7F: // Sequencer specific information $custom_data = substr($METAeventData, 0, $METAeventLength); break; default: $ThisFileInfo['warning'] .= "\n".'Unhandled META Event Command: '.$METAeventCommand; break; } } else { $ThisFileInfo['warning'] .= "\n".'Unhandled MIDI Event ID: '.$MIDIevents[$tracknumber][$eventid]['eventid']; } } if ($tracknumber > 0) { $ThisFileInfo['midi']['totalticks'] = max($ThisFileInfo['midi']['totalticks'], $CumulativeDeltaTime); } } $previoustickoffset = 0; foreach ($MicroSecondsPerQuarterNoteAfter as $tickoffset => $microsecondsperbeat) { if ($ThisFileInfo['midi']['totalticks'] > $tickoffset) { if ($ThisFileInfo['midi']['raw']['ticksperqnote'] == 0) { $ThisFileInfo['error'] .= "\n".'Corrupt MIDI file: ticksperqnote == zero'; return false; } $ThisFileInfo['playtime_seconds'] += (($tickoffset - $previoustickoffset) / $ThisFileInfo['midi']['raw']['ticksperqnote']) * ($microsecondsperbeat / 1000000); $previoustickoffset = $tickoffset; } } if ($ThisFileInfo['midi']['totalticks'] > $previoustickoffset) { if ($ThisFileInfo['midi']['raw']['ticksperqnote'] == 0) { $ThisFileInfo['error'] .= "\n".'Corrupt MIDI file: ticksperqnote == zero'; return false; } $ThisFileInfo['playtime_seconds'] += (($ThisFileInfo['midi']['totalticks'] - $previoustickoffset) / $ThisFileInfo['midi']['raw']['ticksperqnote']) * ($microsecondsperbeat / 1000000); } } // MIDI tags have highest priority if (!empty($ThisFileInfo['midi']['comments'])) { CopyFormatCommentsToRootComments($ThisFileInfo['midi']['comments'], $ThisFileInfo, true, true, true); // add tag to array of tags $ThisFileInfo['tags'][] = 'midi'; } return true; } function GeneralMIDIinstrumentLookup($instrumentid) { static $GeneralMIDIinstrumentLookup = array(); if (empty($GeneralMIDIinstrumentLookup)) { $GeneralMIDIinstrumentLookup[0] = 'Acoustic Grand'; $GeneralMIDIinstrumentLookup[1] = 'Bright Acoustic'; $GeneralMIDIinstrumentLookup[2] = 'Electric Grand'; $GeneralMIDIinstrumentLookup[3] = 'Honky-Tonk'; $GeneralMIDIinstrumentLookup[4] = 'Electric Piano 1'; $GeneralMIDIinstrumentLookup[5] = 'Electric Piano 2'; $GeneralMIDIinstrumentLookup[6] = 'Harpsichord'; $GeneralMIDIinstrumentLookup[7] = 'Clav'; $GeneralMIDIinstrumentLookup[8] = 'Celesta'; $GeneralMIDIinstrumentLookup[9] = 'Glockenspiel'; $GeneralMIDIinstrumentLookup[10] = 'Music Box'; $GeneralMIDIinstrumentLookup[11] = 'Vibraphone'; $GeneralMIDIinstrumentLookup[12] = 'Marimba'; $GeneralMIDIinstrumentLookup[13] = 'Xylophone'; $GeneralMIDIinstrumentLookup[14] = 'Tubular Bells'; $GeneralMIDIinstrumentLookup[15] = 'Dulcimer'; $GeneralMIDIinstrumentLookup[16] = 'Drawbar Organ'; $GeneralMIDIinstrumentLookup[17] = 'Percussive Organ'; $GeneralMIDIinstrumentLookup[18] = 'Rock Organ'; $GeneralMIDIinstrumentLookup[19] = 'Church Organ'; $GeneralMIDIinstrumentLookup[20] = 'Reed Organ'; $GeneralMIDIinstrumentLookup[21] = 'Accordian'; $GeneralMIDIinstrumentLookup[22] = 'Harmonica'; $GeneralMIDIinstrumentLookup[23] = 'Tango Accordian'; $GeneralMIDIinstrumentLookup[24] = 'Acoustic Guitar (nylon)'; $GeneralMIDIinstrumentLookup[25] = 'Acoustic Guitar (steel)'; $GeneralMIDIinstrumentLookup[26] = 'Electric Guitar (jazz)'; $GeneralMIDIinstrumentLookup[27] = 'Electric Guitar (clean)'; $GeneralMIDIinstrumentLookup[28] = 'Electric Guitar (muted)'; $GeneralMIDIinstrumentLookup[29] = 'Overdriven Guitar'; $GeneralMIDIinstrumentLookup[30] = 'Distortion Guitar'; $GeneralMIDIinstrumentLookup[31] = 'Guitar Harmonics'; $GeneralMIDIinstrumentLookup[32] = 'Acoustic Bass'; $GeneralMIDIinstrumentLookup[33] = 'Electric Bass (finger)'; $GeneralMIDIinstrumentLookup[34] = 'Electric Bass (pick)'; $GeneralMIDIinstrumentLookup[35] = 'Fretless Bass'; $GeneralMIDIinstrumentLookup[36] = 'Slap Bass 1'; $GeneralMIDIinstrumentLookup[37] = 'Slap Bass 2'; $GeneralMIDIinstrumentLookup[38] = 'Synth Bass 1'; $GeneralMIDIinstrumentLookup[39] = 'Synth Bass 2'; $GeneralMIDIinstrumentLookup[40] = 'Violin'; $GeneralMIDIinstrumentLookup[41] = 'Viola'; $GeneralMIDIinstrumentLookup[42] = 'Cello'; $GeneralMIDIinstrumentLookup[43] = 'Contrabass'; $GeneralMIDIinstrumentLookup[44] = 'Tremolo Strings'; $GeneralMIDIinstrumentLookup[45] = 'Pizzicato Strings'; $GeneralMIDIinstrumentLookup[46] = 'Orchestral Strings'; $GeneralMIDIinstrumentLookup[47] = 'Timpani'; $GeneralMIDIinstrumentLookup[48] = 'String Ensemble 1'; $GeneralMIDIinstrumentLookup[49] = 'String Ensemble 2'; $GeneralMIDIinstrumentLookup[50] = 'SynthStrings 1'; $GeneralMIDIinstrumentLookup[51] = 'SynthStrings 2'; $GeneralMIDIinstrumentLookup[52] = 'Choir Aahs'; $GeneralMIDIinstrumentLookup[53] = 'Voice Oohs'; $GeneralMIDIinstrumentLookup[54] = 'Synth Voice'; $GeneralMIDIinstrumentLookup[55] = 'Orchestra Hit'; $GeneralMIDIinstrumentLookup[56] = 'Trumpet'; $GeneralMIDIinstrumentLookup[57] = 'Trombone'; $GeneralMIDIinstrumentLookup[58] = 'Tuba'; $GeneralMIDIinstrumentLookup[59] = 'Muted Trumpet'; $GeneralMIDIinstrumentLookup[60] = 'French Horn'; $GeneralMIDIinstrumentLookup[61] = 'Brass Section'; $GeneralMIDIinstrumentLookup[62] = 'SynthBrass 1'; $GeneralMIDIinstrumentLookup[63] = 'SynthBrass 2'; $GeneralMIDIinstrumentLookup[64] = 'Soprano Sax'; $GeneralMIDIinstrumentLookup[65] = 'Alto Sax'; $GeneralMIDIinstrumentLookup[66] = 'Tenor Sax'; $GeneralMIDIinstrumentLookup[67] = 'Baritone Sax'; $GeneralMIDIinstrumentLookup[68] = 'Oboe'; $GeneralMIDIinstrumentLookup[69] = 'English Horn'; $GeneralMIDIinstrumentLookup[70] = 'Bassoon'; $GeneralMIDIinstrumentLookup[71] = 'Clarinet'; $GeneralMIDIinstrumentLookup[72] = 'Piccolo'; $GeneralMIDIinstrumentLookup[73] = 'Flute'; $GeneralMIDIinstrumentLookup[74] = 'Recorder'; $GeneralMIDIinstrumentLookup[75] = 'Pan Flute'; $GeneralMIDIinstrumentLookup[76] = 'Blown Bottle'; $GeneralMIDIinstrumentLookup[77] = 'Shakuhachi'; $GeneralMIDIinstrumentLookup[78] = 'Whistle'; $GeneralMIDIinstrumentLookup[79] = 'Ocarina'; $GeneralMIDIinstrumentLookup[80] = 'Lead 1 (square)'; $GeneralMIDIinstrumentLookup[81] = 'Lead 2 (sawtooth)'; $GeneralMIDIinstrumentLookup[82] = 'Lead 3 (calliope)'; $GeneralMIDIinstrumentLookup[83] = 'Lead 4 (chiff)'; $GeneralMIDIinstrumentLookup[84] = 'Lead 5 (charang)'; $GeneralMIDIinstrumentLookup[85] = 'Lead 6 (voice)'; $GeneralMIDIinstrumentLookup[86] = 'Lead 7 (fifths)'; $GeneralMIDIinstrumentLookup[87] = 'Lead 8 (bass + lead)'; $GeneralMIDIinstrumentLookup[88] = 'Pad 1 (new age)'; $GeneralMIDIinstrumentLookup[89] = 'Pad 2 (warm)'; $GeneralMIDIinstrumentLookup[90] = 'Pad 3 (polysynth)'; $GeneralMIDIinstrumentLookup[91] = 'Pad 4 (choir)'; $GeneralMIDIinstrumentLookup[92] = 'Pad 5 (bowed)'; $GeneralMIDIinstrumentLookup[93] = 'Pad 6 (metallic)'; $GeneralMIDIinstrumentLookup[94] = 'Pad 7 (halo)'; $GeneralMIDIinstrumentLookup[95] = 'Pad 8 (sweep)'; $GeneralMIDIinstrumentLookup[96] = 'FX 1 (rain)'; $GeneralMIDIinstrumentLookup[97] = 'FX 2 (soundtrack)'; $GeneralMIDIinstrumentLookup[98] = 'FX 3 (crystal)'; $GeneralMIDIinstrumentLookup[99] = 'FX 4 (atmosphere)'; $GeneralMIDIinstrumentLookup[100] = 'FX 5 (brightness)'; $GeneralMIDIinstrumentLookup[101] = 'FX 6 (goblins)'; $GeneralMIDIinstrumentLookup[102] = 'FX 7 (echoes)'; $GeneralMIDIinstrumentLookup[103] = 'FX 8 (sci-fi)'; $GeneralMIDIinstrumentLookup[104] = 'Sitar'; $GeneralMIDIinstrumentLookup[105] = 'Banjo'; $GeneralMIDIinstrumentLookup[106] = 'Shamisen'; $GeneralMIDIinstrumentLookup[107] = 'Koto'; $GeneralMIDIinstrumentLookup[108] = 'Kalimba'; $GeneralMIDIinstrumentLookup[109] = 'Bagpipe'; $GeneralMIDIinstrumentLookup[110] = 'Fiddle'; $GeneralMIDIinstrumentLookup[111] = 'Shanai'; $GeneralMIDIinstrumentLookup[112] = 'Tinkle Bell'; $GeneralMIDIinstrumentLookup[113] = 'Agogo'; $GeneralMIDIinstrumentLookup[114] = 'Steel Drums'; $GeneralMIDIinstrumentLookup[115] = 'Woodblock'; $GeneralMIDIinstrumentLookup[116] = 'Taiko Drum'; $GeneralMIDIinstrumentLookup[117] = 'Melodic Tom'; $GeneralMIDIinstrumentLookup[118] = 'Synth Drum'; $GeneralMIDIinstrumentLookup[119] = 'Reverse Cymbal'; $GeneralMIDIinstrumentLookup[120] = 'Guitar Fret Noise'; $GeneralMIDIinstrumentLookup[121] = 'Breath Noise'; $GeneralMIDIinstrumentLookup[122] = 'Seashore'; $GeneralMIDIinstrumentLookup[123] = 'Bird Tweet'; $GeneralMIDIinstrumentLookup[124] = 'Telephone Ring'; $GeneralMIDIinstrumentLookup[125] = 'Helicopter'; $GeneralMIDIinstrumentLookup[126] = 'Applause'; $GeneralMIDIinstrumentLookup[127] = 'Gunshot'; } return (isset($GeneralMIDIinstrumentLookup[$instrumentid]) ? $GeneralMIDIinstrumentLookup[$instrumentid] : ''); } function GeneralMIDIpercussionLookup($instrumentid) { static $GeneralMIDIpercussionLookup = array(); if (empty($GeneralMIDIpercussionLookup)) { $GeneralMIDIpercussionLookup[35] = 'Acoustic Bass Drum'; $GeneralMIDIpercussionLookup[36] = 'Bass Drum 1'; $GeneralMIDIpercussionLookup[37] = 'Side Stick'; $GeneralMIDIpercussionLookup[38] = 'Acoustic Snare'; $GeneralMIDIpercussionLookup[39] = 'Hand Clap'; $GeneralMIDIpercussionLookup[40] = 'Electric Snare'; $GeneralMIDIpercussionLookup[41] = 'Low Floor Tom'; $GeneralMIDIpercussionLookup[42] = 'Closed Hi-Hat'; $GeneralMIDIpercussionLookup[43] = 'High Floor Tom'; $GeneralMIDIpercussionLookup[44] = 'Pedal Hi-Hat'; $GeneralMIDIpercussionLookup[45] = 'Low Tom'; $GeneralMIDIpercussionLookup[46] = 'Open Hi-Hat'; $GeneralMIDIpercussionLookup[47] = 'Low-Mid Tom'; $GeneralMIDIpercussionLookup[48] = 'Hi-Mid Tom'; $GeneralMIDIpercussionLookup[49] = 'Crash Cymbal 1'; $GeneralMIDIpercussionLookup[50] = 'High Tom'; $GeneralMIDIpercussionLookup[51] = 'Ride Cymbal 1'; $GeneralMIDIpercussionLookup[52] = 'Chinese Cymbal'; $GeneralMIDIpercussionLookup[53] = 'Ride Bell'; $GeneralMIDIpercussionLookup[54] = 'Tambourine'; $GeneralMIDIpercussionLookup[55] = 'Splash Cymbal'; $GeneralMIDIpercussionLookup[56] = 'Cowbell'; $GeneralMIDIpercussionLookup[57] = 'Crash Cymbal 2'; $GeneralMIDIpercussionLookup[59] = 'Ride Cymbal 2'; $GeneralMIDIpercussionLookup[60] = 'Hi Bongo'; $GeneralMIDIpercussionLookup[61] = 'Low Bongo'; $GeneralMIDIpercussionLookup[62] = 'Mute Hi Conga'; $GeneralMIDIpercussionLookup[63] = 'Open Hi Conga'; $GeneralMIDIpercussionLookup[64] = 'Low Conga'; $GeneralMIDIpercussionLookup[65] = 'High Timbale'; $GeneralMIDIpercussionLookup[66] = 'Low Timbale'; $GeneralMIDIpercussionLookup[67] = 'High Agogo'; $GeneralMIDIpercussionLookup[68] = 'Low Agogo'; $GeneralMIDIpercussionLookup[69] = 'Cabasa'; $GeneralMIDIpercussionLookup[70] = 'Maracas'; $GeneralMIDIpercussionLookup[71] = 'Short Whistle'; $GeneralMIDIpercussionLookup[72] = 'Long Whistle'; $GeneralMIDIpercussionLookup[73] = 'Short Guiro'; $GeneralMIDIpercussionLookup[74] = 'Long Guiro'; $GeneralMIDIpercussionLookup[75] = 'Claves'; $GeneralMIDIpercussionLookup[76] = 'Hi Wood Block'; $GeneralMIDIpercussionLookup[77] = 'Low Wood Block'; $GeneralMIDIpercussionLookup[78] = 'Mute Cuica'; $GeneralMIDIpercussionLookup[79] = 'Open Cuica'; $GeneralMIDIpercussionLookup[80] = 'Mute Triangle'; $GeneralMIDIpercussionLookup[81] = 'Open Triangle'; } return (isset($GeneralMIDIpercussionLookup[$instrumentid]) ? $GeneralMIDIpercussionLookup[$instrumentid] : ''); } ?>