Mercurial > judyates
view e2gallerypro/e2upload/Backend/Assets/getid3/module.audio.midi.php @ 20:1038db2374ec judyates
change address
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sun, 08 Sep 2013 00:47:09 -0400 |
parents | 3f6b44aa6b35 |
children |
line wrap: on
line source
1 <?php2 // +----------------------------------------------------------------------+3 // | PHP version 5 |4 // +----------------------------------------------------------------------+5 // | Copyright (c) 2002-2006 James Heinrich, Allan Hansen |6 // +----------------------------------------------------------------------+7 // | This source file is subject to version 2 of the GPL license, |8 // | that is bundled with this package in the file license.txt and is |9 // | available through the world-wide-web at the following url: |10 // | http://www.gnu.org/copyleft/gpl.html |11 // +----------------------------------------------------------------------+12 // | getID3() - http://getid3.sourceforge.net or http://www.getid3.org |13 // +----------------------------------------------------------------------+14 // | Authors: James Heinrich <infoØgetid3*org> |15 // | Allan Hansen <ahØartemis*dk> |16 // +----------------------------------------------------------------------+17 // | module.audio.midi.php |18 // | Module for analyzing midi audio files |19 // | dependencies: NONE |20 // +----------------------------------------------------------------------+21 //22 // $Id: module.audio.midi.php,v 1.5 2006/11/02 10:48:01 ah Exp $26 class getid3_midi extends getid3_handler27 {29 public function Analyze() {31 $getid3 = $this->getid3;33 $getid3->info['midi']['raw'] = array ();34 $info_midi = &$getid3->info['midi'];35 $info_midi_raw = &$info_midi['raw'];37 $getid3->info['fileformat'] = 'midi';38 $getid3->info['audio']['dataformat'] = 'midi';40 fseek($getid3->fp, $getid3->info['avdataoffset'], SEEK_SET);41 $midi_data = fread($getid3->fp, getid3::FREAD_BUFFER_SIZE);43 // Magic bytes: 'MThd'45 getid3_lib::ReadSequence('BigEndian2Int', $info_midi_raw, $midi_data, 4,46 array (47 'headersize' => 4,48 'fileformat' => 2,49 'tracks' => 2,50 'ticksperqnote' => 251 )52 );54 $offset = 14;56 for ($i = 0; $i < $info_midi_raw['tracks']; $i++) {58 if ((strlen($midi_data) - $offset) < 8) {59 $midi_data .= fread($getid3->fp, getid3::FREAD_BUFFER_SIZE);60 }62 $track_id = substr($midi_data, $offset, 4);63 $offset += 4;65 if ($track_id != 'MTrk') {66 throw new getid3_exception('Expecting "MTrk" at '.$offset.', found '.$track_id.' instead');67 }69 $track_size = getid3_lib::BigEndian2Int(substr($midi_data, $offset, 4));70 $offset += 4;72 $track_data_array[$i] = substr($midi_data, $offset, $track_size);73 $offset += $track_size;74 }76 if (!isset($track_data_array) || !is_array($track_data_array)) {77 throw new getid3_exception('Cannot find MIDI track information');78 }81 $info_midi['totalticks'] = 0;82 $getid3->info['playtime_seconds'] = 0;83 $current_ms_per_beat = 500000; // 120 beats per minute; 60,000,000 microseconds per minute -> 500,000 microseconds per beat84 $current_beats_per_min = 120; // 120 beats per minute; 60,000,000 microseconds per minute -> 500,000 microseconds per beat85 $ms_per_quarter_note_after = array ();87 foreach ($track_data_array as $track_number => $track_data) {89 $events_offset = $last_issued_midi_command = $last_issued_midi_channel = $cumulative_delta_time = $ticks_at_current_bpm = 0;91 while ($events_offset < strlen($track_data)) {93 $event_id = 0;94 if (isset($midi_events[$track_number]) && is_array($midi_events[$track_number])) {95 $event_id = count($midi_events[$track_number]);96 }97 $delta_time = 0;98 for ($i = 0; $i < 4; $i++) {99 $delta_time_byte = ord($track_data{$events_offset++});100 $delta_time = ($delta_time << 7) + ($delta_time_byte & 0x7F);101 if ($delta_time_byte & 0x80) {102 // another byte follows103 } else {104 break;105 }106 }108 $cumulative_delta_time += $delta_time;109 $ticks_at_current_bpm += $delta_time;111 $midi_events[$track_number][$event_id]['deltatime'] = $delta_time;113 $midi_event_channel = ord($track_data{$events_offset++});115 // OK, normal event - MIDI command has MSB set116 if ($midi_event_channel & 0x80) {117 $last_issued_midi_command = $midi_event_channel >> 4;118 $last_issued_midi_channel = $midi_event_channel & 0x0F;119 }121 // Running event - assume last command122 else {123 $events_offset--;124 }126 $midi_events[$track_number][$event_id]['eventid'] = $last_issued_midi_command;127 $midi_events[$track_number][$event_id]['channel'] = $last_issued_midi_channel;129 switch ($midi_events[$track_number][$event_id]['eventid']) {131 case 0x8: // Note off (key is released)132 case 0x9: // Note on (key is pressed)133 case 0xA: // Key after-touch135 //$notenumber = ord($track_data{$events_offset++});136 //$velocity = ord($track_data{$events_offset++});137 $events_offset += 2;138 break;141 case 0xB: // Control Change143 //$controllernum = ord($track_data{$events_offset++});144 //$newvalue = ord($track_data{$events_offset++});145 $events_offset += 2;146 break;149 case 0xC: // Program (patch) change151 $new_program_num = ord($track_data{$events_offset++});153 $info_midi_raw['track'][$track_number]['instrumentid'] = $new_program_num;154 $info_midi_raw['track'][$track_number]['instrument'] = $track_number == 10 ? getid3_midi::GeneralMIDIpercussionLookup($new_program_num) : getid3_midi::GeneralMIDIinstrumentLookup($new_program_num);155 break;158 case 0xD: // Channel after-touch160 //$channelnumber = ord($track_data{$events_offset++});161 break;164 case 0xE: // Pitch wheel change (2000H is normal or no change)166 //$changeLSB = ord($track_data{$events_offset++});167 //$changeMSB = ord($track_data{$events_offset++});168 //$pitchwheelchange = (($changeMSB & 0x7F) << 7) & ($changeLSB & 0x7F);169 $events_offset += 2;170 break;173 case 0xF:175 if ($midi_events[$track_number][$event_id]['channel'] == 0xF) {177 $meta_event_command = ord($track_data{$events_offset++});178 $meta_event_length = ord($track_data{$events_offset++});179 $meta_event_data = substr($track_data, $events_offset, $meta_event_length);180 $events_offset += $meta_event_length;182 switch ($meta_event_command) {184 case 0x00: // Set track sequence number186 //$track_sequence_number = getid3_lib::BigEndian2Int(substr($meta_event_data, 0, $meta_event_length));187 //$info_midi_raw['events'][$track_number][$event_id]['seqno'] = $track_sequence_number;188 break;191 case 0x01: // Text: generic193 $text_generic = substr($meta_event_data, 0, $meta_event_length);194 //$info_midi_raw['events'][$track_number][$event_id]['text'] = $text_generic;195 $info_midi['comments']['comment'][] = $text_generic;196 break;199 case 0x02: // Text: copyright201 $text_copyright = substr($meta_event_data, 0, $meta_event_length);202 //$info_midi_raw['events'][$track_number][$event_id]['copyright'] = $text_copyright;203 $info_midi['comments']['copyright'][] = $text_copyright;204 break;207 case 0x03: // Text: track name209 $text_trackname = substr($meta_event_data, 0, $meta_event_length);210 $info_midi_raw['track'][$track_number]['name'] = $text_trackname;211 break;214 case 0x04: // Text: track instrument name216 //$text_instrument = substr($meta_event_data, 0, $meta_event_length);217 //$info_midi_raw['events'][$track_number][$event_id]['instrument'] = $text_instrument;218 break;221 case 0x05: // Text: lyrics223 $text_lyrics = substr($meta_event_data, 0, $meta_event_length);224 //$info_midi_raw['events'][$track_number][$event_id]['lyrics'] = $text_lyrics;225 if (!isset($info_midi['lyrics'])) {226 $info_midi['lyrics'] = '';227 }228 $info_midi['lyrics'] .= $text_lyrics . "\n";229 break;232 case 0x06: // Text: marker234 //$text_marker = substr($meta_event_data, 0, $meta_event_length);235 //$info_midi_raw['events'][$track_number][$event_id]['marker'] = $text_marker;236 break;239 case 0x07: // Text: cue point241 //$text_cuepoint = substr($meta_event_data, 0, $meta_event_length);242 //$info_midi_raw['events'][$track_number][$event_id]['cuepoint'] = $text_cuepoint;243 break;246 case 0x2F: // End Of Track248 //$info_midi_raw['events'][$track_number][$event_id]['EOT'] = $cumulative_delta_time;249 break;252 case 0x51: // Tempo: microseconds / quarter note254 $current_ms_per_beat = getid3_lib::BigEndian2Int(substr($meta_event_data, 0, $meta_event_length));255 $info_midi_raw['events'][$track_number][$cumulative_delta_time]['us_qnote'] = $current_ms_per_beat;256 $current_beats_per_min = (1000000 / $current_ms_per_beat) * 60;257 $ms_per_quarter_note_after[$cumulative_delta_time] = $current_ms_per_beat;258 $ticks_at_current_bpm = 0;259 break;262 case 0x58: // Time signature263 $timesig_numerator = getid3_lib::BigEndian2Int($meta_event_data[0]);264 $timesig_denominator = pow(2, getid3_lib::BigEndian2Int($meta_event_data[1])); // $02 -> x/4, $03 -> x/8, etc265 //$timesig_32inqnote = getid3_lib::BigEndian2Int($meta_event_data[2]); // number of 32nd notes to the quarter note266 //$info_midi_raw['events'][$track_number][$event_id]['timesig_32inqnote'] = $timesig_32inqnote;267 //$info_midi_raw['events'][$track_number][$event_id]['timesig_numerator'] = $timesig_numerator;268 //$info_midi_raw['events'][$track_number][$event_id]['timesig_denominator'] = $timesig_denominator;269 //$info_midi_raw['events'][$track_number][$event_id]['timesig_text'] = $timesig_numerator.'/'.$timesig_denominator;270 $info_midi['timesignature'][] = $timesig_numerator.'/'.$timesig_denominator;271 break;274 case 0x59: // Keysignature276 $keysig_sharpsflats = getid3_lib::BigEndian2Int($meta_event_data{0});277 if ($keysig_sharpsflats & 0x80) {278 // (-7 -> 7 flats, 0 ->key of C, 7 -> 7 sharps)279 $keysig_sharpsflats -= 256;280 }282 $keysig_majorminor = getid3_lib::BigEndian2Int($meta_event_data{1}); // 0 -> major, 1 -> minor283 $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#');284 //$info_midi_raw['events'][$track_number][$event_id]['keysig_sharps'] = (($keysig_sharpsflats > 0) ? abs($keysig_sharpsflats) : 0);285 //$info_midi_raw['events'][$track_number][$event_id]['keysig_flats'] = (($keysig_sharpsflats < 0) ? abs($keysig_sharpsflats) : 0);286 //$info_midi_raw['events'][$track_number][$event_id]['keysig_minor'] = (bool)$keysig_majorminor;287 //$info_midi_raw['events'][$track_number][$event_id]['keysig_text'] = $keysigs[$keysig_sharpsflats].' '.($info_midi_raw['events'][$track_number][$event_id]['keysig_minor'] ? 'minor' : 'major');289 // $keysigs[$keysig_sharpsflats] gets an int key (correct) - $keysigs["$keysig_sharpsflats"] gets a string key (incorrect)290 $info_midi['keysignature'][] = $keysigs[$keysig_sharpsflats].' '.((bool)$keysig_majorminor ? 'minor' : 'major');291 break;294 case 0x7F: // Sequencer specific information296 $custom_data = substr($meta_event_data, 0, $meta_event_length);297 break;300 default:302 $getid3->warning('Unhandled META Event Command: '.$meta_event_command);303 }304 }305 break;308 default:309 $getid3->warning('Unhandled MIDI Event ID: '.$midi_events[$track_number][$event_id]['eventid']);310 }311 }313 if (($track_number > 0) || (count($track_data_array) == 1)) {314 $info_midi['totalticks'] = max($info_midi['totalticks'], $cumulative_delta_time);315 }316 }318 $previous_tick_offset = null;320 ksort($ms_per_quarter_note_after);321 foreach ($ms_per_quarter_note_after as $tick_offset => $ms_per_beat) {323 if (is_null($previous_tick_offset)) {324 $prev_ms_per_beat = $ms_per_beat;325 $previous_tick_offset = $tick_offset;326 continue;327 }329 if ($info_midi['totalticks'] > $tick_offset) {330 $getid3->info['playtime_seconds'] += (($tick_offset - $previous_tick_offset) / $info_midi_raw['ticksperqnote']) * ($prev_ms_per_beat / 1000000);332 $prev_ms_per_beat = $ms_per_beat;333 $previous_tick_offset = $tick_offset;334 }335 }337 if ($info_midi['totalticks'] > $previous_tick_offset) {338 $getid3->info['playtime_seconds'] += (($info_midi['totalticks'] - $previous_tick_offset) / $info_midi_raw['ticksperqnote']) * ($ms_per_beat / 1000000);339 }341 if (@$getid3->info['playtime_seconds'] > 0) {342 $getid3->info['bitrate'] = (($getid3->info['avdataend'] - $getid3->info['avdataoffset']) * 8) / $getid3->info['playtime_seconds'];343 }345 if (!empty($info_midi['lyrics'])) {346 $info_midi['comments']['lyrics'][] = $info_midi['lyrics'];347 }349 return true;350 }354 public static function GeneralMIDIinstrumentLookup($instrument_id) {356 static $lookup = array (358 0 => 'Acoustic Grand',359 1 => 'Bright Acoustic',360 2 => 'Electric Grand',361 3 => 'Honky-Tonk',362 4 => 'Electric Piano 1',363 5 => 'Electric Piano 2',364 6 => 'Harpsichord',365 7 => 'Clavier',366 8 => 'Celesta',367 9 => 'Glockenspiel',368 10 => 'Music Box',369 11 => 'Vibraphone',370 12 => 'Marimba',371 13 => 'Xylophone',372 14 => 'Tubular Bells',373 15 => 'Dulcimer',374 16 => 'Drawbar Organ',375 17 => 'Percussive Organ',376 18 => 'Rock Organ',377 19 => 'Church Organ',378 20 => 'Reed Organ',379 21 => 'Accordian',380 22 => 'Harmonica',381 23 => 'Tango Accordian',382 24 => 'Acoustic Guitar (nylon)',383 25 => 'Acoustic Guitar (steel)',384 26 => 'Electric Guitar (jazz)',385 27 => 'Electric Guitar (clean)',386 28 => 'Electric Guitar (muted)',387 29 => 'Overdriven Guitar',388 30 => 'Distortion Guitar',389 31 => 'Guitar Harmonics',390 32 => 'Acoustic Bass',391 33 => 'Electric Bass (finger)',392 34 => 'Electric Bass (pick)',393 35 => 'Fretless Bass',394 36 => 'Slap Bass 1',395 37 => 'Slap Bass 2',396 38 => 'Synth Bass 1',397 39 => 'Synth Bass 2',398 40 => 'Violin',399 41 => 'Viola',400 42 => 'Cello',401 43 => 'Contrabass',402 44 => 'Tremolo Strings',403 45 => 'Pizzicato Strings',404 46 => 'Orchestral Strings',405 47 => 'Timpani',406 48 => 'String Ensemble 1',407 49 => 'String Ensemble 2',408 50 => 'SynthStrings 1',409 51 => 'SynthStrings 2',410 52 => 'Choir Aahs',411 53 => 'Voice Oohs',412 54 => 'Synth Voice',413 55 => 'Orchestra Hit',414 56 => 'Trumpet',415 57 => 'Trombone',416 58 => 'Tuba',417 59 => 'Muted Trumpet',418 60 => 'French Horn',419 61 => 'Brass Section',420 62 => 'SynthBrass 1',421 63 => 'SynthBrass 2',422 64 => 'Soprano Sax',423 65 => 'Alto Sax',424 66 => 'Tenor Sax',425 67 => 'Baritone Sax',426 68 => 'Oboe',427 69 => 'English Horn',428 70 => 'Bassoon',429 71 => 'Clarinet',430 72 => 'Piccolo',431 73 => 'Flute',432 74 => 'Recorder',433 75 => 'Pan Flute',434 76 => 'Blown Bottle',435 77 => 'Shakuhachi',436 78 => 'Whistle',437 79 => 'Ocarina',438 80 => 'Lead 1 (square)',439 81 => 'Lead 2 (sawtooth)',440 82 => 'Lead 3 (calliope)',441 83 => 'Lead 4 (chiff)',442 84 => 'Lead 5 (charang)',443 85 => 'Lead 6 (voice)',444 86 => 'Lead 7 (fifths)',445 87 => 'Lead 8 (bass + lead)',446 88 => 'Pad 1 (new age)',447 89 => 'Pad 2 (warm)',448 90 => 'Pad 3 (polysynth)',449 91 => 'Pad 4 (choir)',450 92 => 'Pad 5 (bowed)',451 93 => 'Pad 6 (metallic)',452 94 => 'Pad 7 (halo)',453 95 => 'Pad 8 (sweep)',454 96 => 'FX 1 (rain)',455 97 => 'FX 2 (soundtrack)',456 98 => 'FX 3 (crystal)',457 99 => 'FX 4 (atmosphere)',458 100 => 'FX 5 (brightness)',459 101 => 'FX 6 (goblins)',460 102 => 'FX 7 (echoes)',461 103 => 'FX 8 (sci-fi)',462 104 => 'Sitar',463 105 => 'Banjo',464 106 => 'Shamisen',465 107 => 'Koto',466 108 => 'Kalimba',467 109 => 'Bagpipe',468 110 => 'Fiddle',469 111 => 'Shanai',470 112 => 'Tinkle Bell',471 113 => 'Agogo',472 114 => 'Steel Drums',473 115 => 'Woodblock',474 116 => 'Taiko Drum',475 117 => 'Melodic Tom',476 118 => 'Synth Drum',477 119 => 'Reverse Cymbal',478 120 => 'Guitar Fret Noise',479 121 => 'Breath Noise',480 122 => 'Seashore',481 123 => 'Bird Tweet',482 124 => 'Telephone Ring',483 125 => 'Helicopter',484 126 => 'Applause',485 127 => 'Gunshot'486 );488 return @$lookup[$instrument_id];489 }493 public static function GeneralMIDIpercussionLookup($instrument_id) {495 static $lookup = array (497 35 => 'Acoustic Bass Drum',498 36 => 'Bass Drum 1',499 37 => 'Side Stick',500 38 => 'Acoustic Snare',501 39 => 'Hand Clap',502 40 => 'Electric Snare',503 41 => 'Low Floor Tom',504 42 => 'Closed Hi-Hat',505 43 => 'High Floor Tom',506 44 => 'Pedal Hi-Hat',507 45 => 'Low Tom',508 46 => 'Open Hi-Hat',509 47 => 'Low-Mid Tom',510 48 => 'Hi-Mid Tom',511 49 => 'Crash Cymbal 1',512 50 => 'High Tom',513 51 => 'Ride Cymbal 1',514 52 => 'Chinese Cymbal',515 53 => 'Ride Bell',516 54 => 'Tambourine',517 55 => 'Splash Cymbal',518 56 => 'Cowbell',519 57 => 'Crash Cymbal 2',520 59 => 'Ride Cymbal 2',521 60 => 'Hi Bongo',522 61 => 'Low Bongo',523 62 => 'Mute Hi Conga',524 63 => 'Open Hi Conga',525 64 => 'Low Conga',526 65 => 'High Timbale',527 66 => 'Low Timbale',528 67 => 'High Agogo',529 68 => 'Low Agogo',530 69 => 'Cabasa',531 70 => 'Maracas',532 71 => 'Short Whistle',533 72 => 'Long Whistle',534 73 => 'Short Guiro',535 74 => 'Long Guiro',536 75 => 'Claves',537 76 => 'Hi Wood Block',538 77 => 'Low Wood Block',539 78 => 'Mute Cuica',540 79 => 'Open Cuica',541 80 => 'Mute Triangle',542 81 => 'Open Triangle'543 );545 return @$lookup[$instrument_id];546 }549 }552 ?>