17define(
'GETID3_MIDI_MAGIC_MTHD', 
'MThd'); 
 
   18define(
'GETID3_MIDI_MAGIC_MTRK', 
'MTrk'); 
 
   25                $info = &$this->getid3->info;
 
   28                $info[
'midi'][
'raw'] = array();
 
   29                $thisfile_midi               = &
$info[
'midi'];
 
   30                $thisfile_midi_raw           = &$thisfile_midi[
'raw'];
 
   32                $info[
'fileformat']          = 
'midi';
 
   33                $info[
'audio'][
'dataformat'] = 
'midi';
 
   36                $MIDIdata = $this->
fread($this->getid3->fread_buffer_size());
 
   38                $MIDIheaderID = substr($MIDIdata, $offset, 4); 
 
   41                        unset(
$info[
'fileformat']);
 
   54                for (
$i = 0; 
$i < $thisfile_midi_raw[
'tracks']; 
$i++) {
 
   55                        while ((strlen($MIDIdata) - $offset) < 8) {
 
   56                                if ($buffer = $this->
fread($this->getid3->fread_buffer_size())) {
 
   59                                        $this->
warning(
'only processed '.(
$i - 1).
' of '.$thisfile_midi_raw[
'tracks'].
' tracks');
 
   60                                        $this->
error(
'Unabled to read more file data at '.$this->
ftell().
' (trying to seek to : '.$offset.
'), was expecting at least 8 more bytes');
 
   64                        $trackID = substr($MIDIdata, $offset, 4);
 
   70                                $trackdataarray[
$i] = substr($MIDIdata, $offset, $tracksize);
 
   71                                $offset += $tracksize;
 
   78                if (!isset($trackdataarray) || !is_array($trackdataarray)) {
 
   79                        $this->
error(
'Cannot find MIDI track information');
 
   80                        unset($thisfile_midi);
 
   81                        unset(
$info[
'fileformat']);
 
   85                if ($this->scanwholefile) { 
 
   86                        $thisfile_midi[
'totalticks']      = 0;
 
   87                        $info[
'playtime_seconds'] = 0;
 
   88                        $CurrentMicroSecondsPerBeat       = 500000; 
 
   89                        $CurrentBeatsPerMinute            = 120;    
 
   90                        $MicroSecondsPerQuarterNoteAfter  = array ();
 
   92                        foreach ($trackdataarray as $tracknumber => $trackdata) {
 
   95                                $LastIssuedMIDIcommand      = 0;
 
   96                                $LastIssuedMIDIchannel      = 0;
 
   97                                $CumulativeDeltaTime        = 0;
 
   98                                $TicksAtCurrentBPM = 0;
 
   99                                while ($eventsoffset < strlen($trackdata)) {
 
  101                                        if (isset($MIDIevents[$tracknumber]) && is_array($MIDIevents[$tracknumber])) {
 
  102                                                $eventid = count($MIDIevents[$tracknumber]);
 
  105                                        for (
$i = 0; 
$i < 4; 
$i++) {
 
  106                                                $deltatimebyte = ord(substr($trackdata, $eventsoffset++, 1));
 
  107                                                $deltatime = ($deltatime << 7) + ($deltatimebyte & 0x7F);
 
  108                                                if ($deltatimebyte & 0x80) {
 
  114                                        $CumulativeDeltaTime += $deltatime;
 
  115                                        $TicksAtCurrentBPM   += $deltatime;
 
  116                                        $MIDIevents[$tracknumber][$eventid][
'deltatime'] = $deltatime;
 
  117                                        $MIDI_event_channel                                  = ord(substr($trackdata, $eventsoffset++, 1));
 
  118                                        if ($MIDI_event_channel & 0x80) {
 
  120                                                $LastIssuedMIDIcommand = $MIDI_event_channel >> 4;
 
  121                                                $LastIssuedMIDIchannel = $MIDI_event_channel & 0x0F;
 
  126                                        $MIDIevents[$tracknumber][$eventid][
'eventid']   = $LastIssuedMIDIcommand;
 
  127                                        $MIDIevents[$tracknumber][$eventid][
'channel']   = $LastIssuedMIDIchannel;
 
  128                                        if ($MIDIevents[$tracknumber][$eventid][
'eventid'] == 0x08) { 
 
  130                                                $notenumber = ord(substr($trackdata, $eventsoffset++, 1));
 
  131                                                $velocity   = ord(substr($trackdata, $eventsoffset++, 1));
 
  133                                        } elseif ($MIDIevents[$tracknumber][$eventid][
'eventid'] == 0x09) { 
 
  135                                                $notenumber = ord(substr($trackdata, $eventsoffset++, 1));
 
  136                                                $velocity   = ord(substr($trackdata, $eventsoffset++, 1));
 
  138                                        } elseif ($MIDIevents[$tracknumber][$eventid][
'eventid'] == 0x0A) { 
 
  140                                                $notenumber = ord(substr($trackdata, $eventsoffset++, 1));
 
  141                                                $velocity   = ord(substr($trackdata, $eventsoffset++, 1));
 
  143                                        } elseif ($MIDIevents[$tracknumber][$eventid][
'eventid'] == 0x0B) { 
 
  145                                                $controllernum = ord(substr($trackdata, $eventsoffset++, 1));
 
  146                                                $newvalue      = ord(substr($trackdata, $eventsoffset++, 1));
 
  148                                        } elseif ($MIDIevents[$tracknumber][$eventid][
'eventid'] == 0x0C) { 
 
  150                                                $newprogramnum = ord(substr($trackdata, $eventsoffset++, 1));
 
  152                                                $thisfile_midi_raw[
'track'][$tracknumber][
'instrumentid'] = $newprogramnum;
 
  153                                                if ($tracknumber == 10) {
 
  159                                        } elseif ($MIDIevents[$tracknumber][$eventid][
'eventid'] == 0x0D) { 
 
  161                                                $channelnumber = ord(substr($trackdata, $eventsoffset++, 1));
 
  163                                        } elseif ($MIDIevents[$tracknumber][$eventid][
'eventid'] == 0x0E) { 
 
  165                                                $changeLSB = ord(substr($trackdata, $eventsoffset++, 1));
 
  166                                                $changeMSB = ord(substr($trackdata, $eventsoffset++, 1));
 
  167                                                $pitchwheelchange = (($changeMSB & 0x7F) << 7) & ($changeLSB & 0x7F);
 
  169                                        } elseif (($MIDIevents[$tracknumber][$eventid][
'eventid'] == 0x0F) && ($MIDIevents[$tracknumber][$eventid][
'channel'] == 0x0F)) {
 
  171                                                $METAeventCommand = ord(substr($trackdata, $eventsoffset++, 1));
 
  172                                                $METAeventLength  = ord(substr($trackdata, $eventsoffset++, 1));
 
  173                                                $METAeventData    = substr($trackdata, $eventsoffset, $METAeventLength);
 
  174                                                $eventsoffset += $METAeventLength;
 
  175                                                switch ($METAeventCommand) {
 
  182                                                                $text_generic = substr($METAeventData, 0, $METAeventLength);
 
  184                                                                $thisfile_midi[
'comments'][
'comment'][] = $text_generic;
 
  188                                                                $text_copyright = substr($METAeventData, 0, $METAeventLength);
 
  190                                                                $thisfile_midi[
'comments'][
'copyright'][] = $text_copyright;
 
  194                                                                $text_trackname = substr($METAeventData, 0, $METAeventLength);
 
  195                                                                $thisfile_midi_raw[
'track'][$tracknumber][
'name'] = $text_trackname;
 
  199                                                                $text_instrument = substr($METAeventData, 0, $METAeventLength);
 
  204                                                                $text_lyrics  = substr($METAeventData, 0, $METAeventLength);
 
  206                                                                if (!isset($thisfile_midi[
'lyrics'])) {
 
  207                                                                        $thisfile_midi[
'lyrics'] = 
'';
 
  209                                                                $thisfile_midi[
'lyrics'] .= $text_lyrics.
"\n";
 
  213                                                                $text_marker = substr($METAeventData, 0, $METAeventLength);
 
  218                                                                $text_cuepoint = substr($METAeventData, 0, $METAeventLength);
 
  228                                                                if ($CurrentMicroSecondsPerBeat == 0) {
 
  229                                                                        $this->
error(
'Corrupt MIDI file: CurrentMicroSecondsPerBeat == zero');
 
  232                                                                $thisfile_midi_raw[
'events'][$tracknumber][$CumulativeDeltaTime][
'us_qnote'] = $CurrentMicroSecondsPerBeat;
 
  233                                                                $CurrentBeatsPerMinute = (1000000 / $CurrentMicroSecondsPerBeat) * 60;
 
  234                                                                $MicroSecondsPerQuarterNoteAfter[$CumulativeDeltaTime] = $CurrentMicroSecondsPerBeat;
 
  235                                                                $TicksAtCurrentBPM = 0;
 
  246                                                                $thisfile_midi[
'timesignature'][] = $timesig_numerator.
'/'.$timesig_denominator;
 
  251                                                                if ($keysig_sharpsflats & 0x80) {
 
  253                                                                        $keysig_sharpsflats -= 256;
 
  257                                                                $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#');
 
  264                                                                $thisfile_midi[
'keysignature'][] = $keysigs[$keysig_sharpsflats].
' '.((bool) $keysig_majorminor ? 
'minor' : 
'major');
 
  268                                                                $custom_data = substr($METAeventData, 0, $METAeventLength);
 
  272                                                                $this->
warning(
'Unhandled META Event Command: '.$METAeventCommand);
 
  278                                                $this->
warning(
'Unhandled MIDI Event ID: '.$MIDIevents[$tracknumber][$eventid][
'eventid'].
' + Channel ID: '.$MIDIevents[$tracknumber][$eventid][
'channel']);
 
  282                                if (($tracknumber > 0) || (count($trackdataarray) == 1)) {
 
  283                                        $thisfile_midi[
'totalticks'] = max($thisfile_midi[
'totalticks'], $CumulativeDeltaTime);
 
  286                        $previoustickoffset = 
null;
 
  288                        ksort($MicroSecondsPerQuarterNoteAfter);
 
  289                        foreach ($MicroSecondsPerQuarterNoteAfter as $tickoffset => $microsecondsperbeat) {
 
  290                                if (is_null($previoustickoffset)) {
 
  291                                        $prevmicrosecondsperbeat = $microsecondsperbeat;
 
  292                                        $previoustickoffset = $tickoffset;
 
  295                                if ($thisfile_midi[
'totalticks'] > $tickoffset) {
 
  297                                        if ($thisfile_midi_raw[
'ticksperqnote'] == 0) {
 
  298                                                $this->
error(
'Corrupt MIDI file: ticksperqnote == zero');
 
  302                                        $info[
'playtime_seconds'] += (($tickoffset - $previoustickoffset) / $thisfile_midi_raw[
'ticksperqnote']) * ($prevmicrosecondsperbeat / 1000000);
 
  304                                        $prevmicrosecondsperbeat = $microsecondsperbeat;
 
  305                                        $previoustickoffset = $tickoffset;
 
  308                        if ($thisfile_midi[
'totalticks'] > $previoustickoffset) {
 
  310                                if ($thisfile_midi_raw[
'ticksperqnote'] == 0) {
 
  311                                        $this->
error(
'Corrupt MIDI file: ticksperqnote == zero');
 
  315                                $info[
'playtime_seconds'] += (($thisfile_midi[
'totalticks'] - $previoustickoffset) / $thisfile_midi_raw[
'ticksperqnote']) * ($microsecondsperbeat / 1000000);
 
  321                if (!empty(
$info[
'playtime_seconds'])) {
 
  322                        $info[
'bitrate'] = ((
$info[
'avdataend'] - 
$info[
'avdataoffset']) * 8) / 
$info[
'playtime_seconds'];
 
  325                if (!empty($thisfile_midi[
'lyrics'])) {
 
  326                        $thisfile_midi[
'comments'][
'lyrics'][] = $thisfile_midi[
'lyrics'];
 
An exception for terminatinating execution or to throw for unit testing.
fseek($bytes, $whence=SEEK_SET)
static PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8')
static EmbeddedLookup($key, $begin, $end, $file, $name)
static BigEndian2Int($byteword, $synchsafe=false, $signed=false)
GeneralMIDIinstrumentLookup($instrumentid)
GeneralMIDIpercussionLookup($instrumentid)
const GETID3_MIDI_MAGIC_MTHD
getID3() by James Heinrich info@getid3.org //
const GETID3_MIDI_MAGIC_MTRK