function _parseTrack($binStr, $tn)
 {
     //$trackLen2 =  ((( (( (ord($binStr[0]) << 8) | ord($binStr[1]))<<8) | ord($binStr[2]) ) << 8 ) |  ord($binStr[3]) );
     //$trackLen2 += 4;
     $trackLen = strlen($binStr);
     // MM: ToDo: Warn if trackLen and trackLen2 are different!!!
     // if ($trackLen != $trackLen2) { echo "Warning: TrackLength is corrupt ($trackLen != $trackLen2)! \n"; }
     $p = 4;
     $time = 0;
     $track = array();
     while ($p < $trackLen) {
         // timedelta
         $dt = _readVarLen($binStr, $p);
         $time += $dt;
         $byte = ord($binStr[$p]);
         $high = $byte >> 4;
         $low = $byte - $high * 16;
         switch ($high) {
             case 0xc:
                 //PrCh = ProgramChange
                 $chan = $low + 1;
                 $prog = ord($binStr[$p + 1]);
                 $last = 'PrCh';
                 $track[] = "{$time} PrCh ch={$chan} p={$prog}";
                 $p += 2;
                 break;
             case 0x9:
                 //On
                 $chan = $low + 1;
                 $note = ord($binStr[$p + 1]);
                 $vel = ord($binStr[$p + 2]);
                 $last = 'On';
                 $track[] = "{$time} On ch={$chan} n={$note} v={$vel}";
                 $p += 3;
                 break;
             case 0x8:
                 //Off
                 $chan = $low + 1;
                 $note = ord($binStr[$p + 1]);
                 $vel = ord($binStr[$p + 2]);
                 $last = 'Off';
                 $track[] = "{$time} Off ch={$chan} n={$note} v={$vel}";
                 $p += 3;
                 break;
             case 0xa:
                 //PoPr = PolyPressure
                 $chan = $low + 1;
                 $note = ord($binStr[$p + 1]);
                 $val = ord($binStr[$p + 2]);
                 $last = 'PoPr';
                 $track[] = "{$time} PoPr ch={$chan} n={$note} v={$val}";
                 $p += 3;
                 break;
             case 0xb:
                 //Par = ControllerChange
                 $chan = $low + 1;
                 $c = ord($binStr[$p + 1]);
                 $val = ord($binStr[$p + 2]);
                 $last = 'Par';
                 $track[] = "{$time} Par ch={$chan} c={$c} v={$val}";
                 $p += 3;
                 break;
             case 0xd:
                 //ChPr = ChannelPressure
                 $chan = $low + 1;
                 $val = ord($binStr[$p + 1]);
                 $last = 'ChPr';
                 $track[] = "{$time} ChPr ch={$chan} v={$val}";
                 $p += 2;
                 break;
             case 0xe:
                 //Pb = PitchBend
                 $chan = $low + 1;
                 $val = ord($binStr[$p + 1]) & 0x7f | (ord($binStr[$p + 2]) & 0x7f) << 7;
                 $last = 'Pb';
                 $track[] = "{$time} Pb ch={$chan} v={$val}";
                 $p += 3;
                 break;
             default:
                 switch ($byte) {
                     case 0xff:
                         // Meta
                         $meta = ord($binStr[$p + 1]);
                         switch ($meta) {
                             case 0x0:
                                 // sequence_number
                                 $tmp = ord($binStr[$p + 2]);
                                 if ($tmp == 0x0) {
                                     $num = $tn;
                                     $p += 3;
                                 } else {
                                     $num = 1;
                                     $p += 5;
                                 }
                                 $track[] = "{$time} Seqnr {$num}";
                                 break;
                             case 0x1:
                                 // Meta Text
                             // Meta Text
                             case 0x2:
                                 // Meta Copyright
                             // Meta Copyright
                             case 0x3:
                                 // Meta TrackName ???sequence_name???
                             // Meta TrackName ???sequence_name???
                             case 0x4:
                                 // Meta InstrumentName
                             // Meta InstrumentName
                             case 0x5:
                                 // Meta Lyrics
                             // Meta Lyrics
                             case 0x6:
                                 // Meta Marker
                             // Meta Marker
                             case 0x7:
                                 // Meta Cue
                                 $texttypes = array('Text', 'Copyright', 'TrkName', 'InstrName', 'Lyric', 'Marker', 'Cue');
                                 $type = $texttypes[$meta - 1];
                                 $p += 2;
                                 $len = _readVarLen($binStr, $p);
                                 if ($len + $p > $trackLen) {
                                     _err("Meta {$type} has corrupt variable length field ({$len}) [track: {$tn} dt: {$dt}]");
                                 }
                                 $txt = substr($binStr, $p, $len);
                                 $track[] = "{$time} Meta {$type} \"{$txt}\"";
                                 $p += $len;
                                 break;
                             case 0x20:
                                 // ChannelPrefix
                                 $chan = ord($binStr[$p + 3]);
                                 if ($chan < 10) {
                                     $chan = '0' . $chan;
                                 }
                                 //???
                                 $track[] = "{$time} Meta 0x20 {$chan}";
                                 $p += 4;
                                 break;
                             case 0x21:
                                 // ChannelPrefixOrPort
                                 $chan = ord($binStr[$p + 3]);
                                 if ($chan < 10) {
                                     $chan = '0' . $chan;
                                 }
                                 //???
                                 $track[] = "{$time} Meta 0x21 {$chan}";
                                 $p += 4;
                                 break;
                             case 0x2f:
                                 // Meta TrkEnd
                                 $track[] = "{$time} Meta TrkEnd";
                                 return $track;
                                 //ignore rest
                                 break;
                             case 0x51:
                                 // Tempo
                                 $tempo = ord($binStr[$p + 3]) * 256 * 256 + ord($binStr[$p + 4]) * 256 + ord($binStr[$p + 5]);
                                 $track[] = "{$time} Tempo {$tempo}";
                                 if ($tn == 0 && $time == 0) {
                                     $this->tempo = $tempo;
                                     // ???
                                     $this->tempoMsgNum = count($track) - 1;
                                 }
                                 $p += 6;
                                 break;
                             case 0x54:
                                 // SMPTE offset
                                 $h = ord($binStr[$p + 3]);
                                 $m = ord($binStr[$p + 4]);
                                 $s = ord($binStr[$p + 5]);
                                 $f = ord($binStr[$p + 6]);
                                 $fh = ord($binStr[$p + 7]);
                                 $track[] = "{$time} SMPTE {$h} {$m} {$s} {$f} {$fh}";
                                 $p += 8;
                                 break;
                             case 0x58:
                                 // TimeSig
                                 $z = ord($binStr[$p + 3]);
                                 $t = pow(2, ord($binStr[$p + 4]));
                                 $mc = ord($binStr[$p + 5]);
                                 $c = ord($binStr[$p + 6]);
                                 $track[] = "{$time} TimeSig {$z}/{$t} {$mc} {$c}";
                                 $p += 7;
                                 break;
                             case 0x59:
                                 // KeySig
                                 $vz = ord($binStr[$p + 3]);
                                 $g = ord($binStr[$p + 4]) == 0 ? 'major' : 'minor';
                                 $track[] = "{$time} KeySig {$vz} {$g}";
                                 $p += 5;
                                 break;
                             case 0x7f:
                                 // Sequencer specific data (string or hexString???)
                                 $p += 2;
                                 $len = _readVarLen($binStr, $p);
                                 if ($len + $p > $trackLen) {
                                     _err("SeqSpec has corrupt variable length field ({$len}) [track: {$tn} dt: {$dt}]");
                                 }
                                 $p -= 3;
                                 $data = '';
                                 for ($i = 0; $i < $len; $i++) {
                                     $data .= ' ' . sprintf("%02x", ord($binStr[$p + 3 + $i]));
                                 }
                                 $track[] = "{$time} SeqSpec{$data}";
                                 $p += $len + 3;
                                 break;
                             default:
                                 // MM added: accept "unknown" Meta-Events
                                 $metacode = sprintf("%02x", ord($binStr[$p + 1]));
                                 $p += 2;
                                 $len = _readVarLen($binStr, $p);
                                 if ($len + $p > $trackLen) {
                                     _err("Meta {$metacode} has corrupt variable length field ({$len}) [track: {$tn} dt: {$dt}]");
                                 }
                                 $p -= 3;
                                 $data = '';
                                 for ($i = 0; $i < $len; $i++) {
                                     $data .= ' ' . sprintf("%02x", ord($binStr[$p + 3 + $i]));
                                 }
                                 $track[] = "{$time} Meta 0x{$metacode} {$data}";
                                 $p += $len + 3;
                                 break;
                         }
                         // switch ($meta)
                         break;
                         // Ende Meta
                     // Ende Meta
                     case 0xf0:
                         // SysEx
                         $p += 1;
                         $len = _readVarLen($binStr, $p);
                         if ($len + $p > $trackLen) {
                             _err("SysEx has corrupt variable length field ({$len}) [track: {$tn} dt: {$dt} p: {$p}]");
                         }
                         $str = 'f0';
                         for ($i = 0; $i < $len; $i++) {
                             $str .= ' ' . sprintf("%02x", ord($binStr[$p + $i]));
                         }
                         # FIXED
                         $track[] = "{$time} SysEx {$str}";
                         $p += $len;
                         break;
                     default:
                         // Repetition of last event?
                         switch ($last) {
                             case 'On':
                             case 'Off':
                                 $note = ord($binStr[$p]);
                                 $vel = ord($binStr[$p + 1]);
                                 $track[] = "{$time} {$last} ch={$chan} n={$note} v={$vel}";
                                 $p += 2;
                                 break;
                             case 'PrCh':
                                 $prog = ord($binStr[$p]);
                                 $track[] = "{$time} PrCh ch={$chan} p={$prog}";
                                 $p += 1;
                                 break;
                             case 'PoPr':
                                 $note = ord($binStr[$p + 1]);
                                 $val = ord($binStr[$p + 2]);
                                 $track[] = "{$time} PoPr ch={$chan} n={$note} v={$val}";
                                 $p += 2;
                                 break;
                             case 'ChPr':
                                 $val = ord($binStr[$p]);
                                 $track[] = "{$time} ChPr ch={$chan} v={$val}";
                                 $p += 1;
                                 break;
                             case 'Par':
                                 $c = ord($binStr[$p]);
                                 $val = ord($binStr[$p + 1]);
                                 $track[] = "{$time} Par ch={$chan} c={$c} v={$val}";
                                 $p += 2;
                                 break;
                             case 'Pb':
                                 $val = ord($binStr[$p]) & 0x7f | (ord($binStr[$p + 1]) & 0x7f) << 7;
                                 $track[] = "{$time} Pb ch={$chan} v={$val}";
                                 $p += 2;
                                 break;
                             default:
                                 // MM: ToDo: Repetition of SysEx and META-events? with <last>?? \n";
                                 _err("unknown repetition: {$last}");
                         }
                         // switch ($last)
                 }
                 // switch ($byte)
         }
         // switch ($high)
     }
     // while
     return $track;
 }
Example #2
0
 function _parseTrack($binStr, $tn)
 {
     $trackLen = strlen($binStr);
     $p = 4;
     $time = 0;
     $track = array();
     while ($p < $trackLen) {
         // timedelta
         $dt = _readVarLen($binStr, $p);
         $time += $dt;
         $byte = ord($binStr[$p]);
         $high = $byte >> 4;
         $low = $byte - $high * 16;
         switch ($high) {
             case 0xc:
                 //PrCh = ProgramChange
                 $chan = $low + 1;
                 $prog = ord($binStr[$p + 1]);
                 $track[] = "{$time} PrCh ch={$chan} p={$prog}";
                 $p += 2;
                 break;
             case 0x9:
                 //On
                 $chan = $low + 1;
                 $note = ord($binStr[$p + 1]);
                 $vel = ord($binStr[$p + 2]);
                 $last = 'On';
                 $track[] = "{$time} On ch={$chan} n={$note} v={$vel}";
                 $p += 3;
                 break;
             case 0x8:
                 //Off
                 $chan = $low + 1;
                 $note = ord($binStr[$p + 1]);
                 $vel = ord($binStr[$p + 2]);
                 $last = 'Off';
                 $track[] = "{$time} Off ch={$chan} n={$note} v={$vel}";
                 $p += 3;
                 break;
             case 0xa:
                 //PoPr = PolyPressure
                 $chan = $low + 1;
                 $note = ord($binStr[$p + 1]);
                 $val = ord($binStr[$p + 2]);
                 $last = 'PoPr';
                 $track[] = "{$time} PoPr ch={$chan} n={$note} v={$val}";
                 $p += 3;
                 break;
             case 0xb:
                 //Par = ControllerChange
                 $chan = $low + 1;
                 $c = ord($binStr[$p + 1]);
                 $val = ord($binStr[$p + 2]);
                 $last = 'Par';
                 $track[] = "{$time} Par ch={$chan} c={$c} v={$val}";
                 $p += 3;
                 break;
             case 0xd:
                 //ChPr = ChannelPressure
                 $chan = $low + 1;
                 $val = ord($binStr[$p + 1]);
                 $last = 'ChPr';
                 $track[] = "{$time} ChPr ch={$chan} v={$val}";
                 $p += 2;
                 break;
             case 0xe:
                 //Pb = PitchBend
                 $chan = $low + 1;
                 $val = ord($binStr[$p + 1]) + (ord($binStr[$p + 2]) - 64) * 128;
                 $last = 'Pb';
                 $track[] = "{$time} Pb ch={$chan} v={$val}";
                 $p += 3;
                 break;
             default:
                 switch ($byte) {
                     case 0xff:
                         // Meta
                         $meta = ord($binStr[$p + 1]);
                         switch ($meta) {
                             case 0x0:
                                 // sequence_number
                                 $num = ord($binStr[$p + 2]);
                                 $track[] = "{$time} Seqnr {$num}";
                                 $p += 2;
                                 break;
                             case 0x1:
                                 // Meta Text
                             // Meta Text
                             case 0x2:
                                 // Meta Copyright
                             // Meta Copyright
                             case 0x3:
                                 // Meta TrackName ???sequence_name???
                             // Meta TrackName ???sequence_name???
                             case 0x4:
                                 // Meta InstrumentName
                             // Meta InstrumentName
                             case 0x5:
                                 // Meta Lyrics
                             // Meta Lyrics
                             case 0x6:
                                 // Meta Marker
                             // Meta Marker
                             case 0x7:
                                 // Meta Cue
                                 $texttypes = array('Text', 'Copyright', 'TrkName', 'InstrName', 'Lyric', 'Marker', 'Cue');
                                 $type = $texttypes[$meta - 1];
                                 $len = ord($binStr[$p + 2]);
                                 $txt = substr($binStr, $p + 3, $len);
                                 $track[] = "{$time} Meta {$type} \"{$txt}\"";
                                 $p += $len + 3;
                                 break;
                             case 0x20:
                                 // ChannelPrefix
                                 $chan = ord($binStr[$p + 3]);
                                 if ($chan < 10) {
                                     $chan = '0' . $chan;
                                 }
                                 //???
                                 $track[] = "{$time} Meta 0x20 {$chan}";
                                 $p += 4;
                                 break;
                             case 0x21:
                                 // ChannelPrefixOrPort
                                 $chan = ord($binStr[$p + 3]);
                                 if ($chan < 10) {
                                     $chan = '0' . $chan;
                                 }
                                 //???
                                 $track[] = "{$time} Meta 0x21 {$chan}";
                                 $p += 4;
                                 break;
                             case 0x2f:
                                 // Meta TrkEnd
                                 $track[] = "{$time} Meta TrkEnd";
                                 $p += 3;
                                 break;
                             case 0x51:
                                 // Tempo
                                 $tempo = ord($binStr[$p + 3]) * 256 * 256 + ord($binStr[$p + 4]) * 256 + ord($binStr[$p + 5]);
                                 $track[] = "{$time} Tempo {$tempo}";
                                 if ($tn == 0 && $time == 0) {
                                     $this->tempo = $tempo;
                                     // ???
                                     $this->tempoMsgNum = count($track) - 1;
                                 }
                                 $p += 6;
                                 break;
                             case 0x54:
                                 // SMPTE offset
                                 $h = ord($binStr[$p + 3]);
                                 $m = ord($binStr[$p + 4]);
                                 $s = ord($binStr[$p + 5]);
                                 $f = ord($binStr[$p + 6]);
                                 $fh = ord($binStr[$p + 7]);
                                 $track[] = "{$time} SMPTE {$h} {$m} {$s} {$f} {$fh}";
                                 $p += 8;
                                 break;
                             case 0x58:
                                 // TimeSig
                                 $z = ord($binStr[$p + 3]);
                                 $t = pow(2, ord($binStr[$p + 4]));
                                 $mc = ord($binStr[$p + 5]);
                                 $c = ord($binStr[$p + 6]);
                                 $track[] = "{$time} TimeSig {$z}/{$t} {$mc} {$c}";
                                 $p += 7;
                                 break;
                             case 0x59:
                                 // KeySig
                                 $vz = ord($binStr[$p + 3]);
                                 $g = ord($binStr[$p + 4]) == 0 ? 'major' : 'minor';
                                 $track[] = "{$time} KeySig {$vz} {$g}";
                                 $p += 5;
                                 break;
                             case 0x7f:
                                 // Sequencer specific data (string or hexString???)
                                 $len = ord($binStr[$p + 2]);
                                 $data = substr($binStr, $p + 3, $len);
                                 $track[] = "{$time} SeqSpec \"{$data}\"";
                                 $p += $len + 3;
                                 break;
                             default:
                                 _err(">>> unknown meta event: {$time} {$byte} {$meta}");
                         }
                         break;
                         // Ende Meta
                     // Ende Meta
                     case 0xf0:
                         // SysEx
                         $len = ord($binStr[$p + 1]);
                         $str = 'f0';
                         for ($i = 0; $i < $len; $i++) {
                             $str .= ' ' . sprintf("%02x", ord($binStr[$p + 2 + $i]));
                         }
                         $track[] = "{$time} SysEx {$str}";
                         $p += $len + 2;
                         break;
                     default:
                         //Repetition of last event?
                         switch ($last) {
                             case 'On':
                             case 'Off':
                                 $note = ord($binStr[$p]);
                                 $vel = ord($binStr[$p + 1]);
                                 $track[] = "{$time} {$last} ch={$chan} n={$note} v={$vel}";
                                 $p += 2;
                                 break;
                             case 'PoPr':
                                 $note = ord($binStr[$p + 1]);
                                 $val = ord($binStr[$p + 2]);
                                 $track[] = "{$time} PoPr ch={$chan} n={$note} v={$val}";
                                 $p += 2;
                                 break;
                             case 'ChPr':
                                 $val = ord($binStr[$p]);
                                 $track[] = "{$time} ChPr ch={$chan} v={$val}";
                                 $p += 1;
                                 break;
                             case 'Par':
                                 $c = ord($binStr[$p]);
                                 $val = ord($binStr[$p + 1]);
                                 $track[] = "{$time} Par ch={$chan} c={$c} v={$val}";
                                 $p += 2;
                                 break;
                             case 'Pb':
                                 $val = ord($binStr[$p]) + ord($binStr[$p + 1]) * 128;
                                 $track[] = "{$time} Pb ch={$chan} v={$val}";
                                 $p += 2;
                                 break;
                             default:
                                 _err(">>> unknown repetition: {$last}");
                         }
                 }
         }
     }
     return $track;
 }