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