Esempio n. 1
0
File: MFi.php Progetto: yoya/IO_MFi
 function parse($mfidata)
 {
     $reader = new IO_Bit();
     $reader->input($mfidata);
     // Header Part
     $identifier = $reader->getData(4);
     if ($identifier != 'melo') {
         throw new Exception('Identifer($identifier) is not melo');
     }
     $this->headers['Identifier'] = $identifier;
     $fileLength = $reader->getUI32BE();
     $realFileLength = strlen($mfidata);
     if ($fileLength != $realFileLength - 8) {
         throw new Exception("FileLength({$fileLength}) is not real FileLength({$realFileLength}) - 8");
     }
     $this->headers['FileLength'] = $fileLength;
     $offsetToTrack = $reader->getUI16BE();
     $this->headers['OffsetToTrack'] = $offsetToTrack;
     $this->headers['DataTypeMajor'] = $reader->getUI8();
     $this->headers['DataTypeMinor'] = $reader->getUI8();
     $this->headers['NumberOfTrack'] = $reader->getUI8();
     // Data Information Part
     $reader_di = new IO_Bit();
     $reader_di->input($reader->getData($offsetToTrack - 3));
     $note_message_length_info = 0;
     while ($reader_di->hasNextData(6)) {
         $info = array();
         $identifer = $reader_di->getData(4);
         $length = $reader_di->getUI16BE();
         $info['Identifer'] = $identifer;
         $info['Length'] = $length;
         switch ($identifer) {
             case 'titl':
             case 'copy':
             case 'prot':
             case 'date':
                 $data = $reader_di->getData($length);
                 break;
             case 'sorc':
                 $data = $reader_di->getUI8($length);
                 break;
             case 'note':
             case 'exst':
                 $data = $reader_di->getUI16BE($length);
                 if ($identifer == 'note') {
                     $note_message_length_info = $data;
                 }
                 break;
             case 'vers':
                 $data = $reader_di->getUI32BE($length);
                 break;
         }
         $info['Data'] = $data;
         $this->datainfos[] = $info;
     }
     // Track Part
     while ($reader->hasNextData(8)) {
         $track = array();
         $track['Identifer'] = $reader->getData(4);
         $length = $reader->getUI32BE();
         $track['Length'] = $length;
         $reader_ev = new IO_Bit();
         $reader_ev->input($reader->getData($length));
         $track['Events'] = array();
         while ($reader_ev->hasNextData(3)) {
             $event = array();
             $event['DeltaTime'] = $reader_ev->getUI8();
             $statusInfo = $reader_ev->getUI8();
             $event['StatusInfo'] = $statusInfo;
             switch ($statusInfo) {
                 default:
                     $event['Data'] = $reader_ev->getUI8();
                     if ($note_message_length_info == 1) {
                         // MFi2
                         $event['Data2'] = $reader_ev->getUI8();
                     }
                     break;
                 case 0xff:
                     $statusInfo2 = $reader_ev->getUI8();
                     $event['StatusInfo2'] = $statusInfo2;
                     switch ($statusInfo2) {
                         default:
                             $event['Data'] = $reader_ev->getUI8();
                             break;
                         case 0xf0:
                         case 0xf1:
                         case 0xff:
                             $length = $reader_ev->getUI16BE();
                             $event['Length'] = $length;
                             $event['Data'] = $reader_ev->getData($length);
                             break;
                     }
             }
             $track['Events'][] = $event;
         }
         $this->tracks[] = $track;
     }
 }
Esempio n. 2
0
 function parseDataChunks(&$reader)
 {
     $chunks = array();
     while ($reader->hasNextData(8)) {
         $chunk = array();
         $chunkID = $reader->getData(4);
         $size = $reader->getUI32BE();
         $chunk['ID'] = $chunkID;
         $chunkID_3byte = substr($chunkID, 0, 3);
         $chunkID_4th_value = ord($chunkID[3]);
         switch ($chunkID_3byte) {
             case 'Dch':
                 $chunk['ID'] = $chunkID_3byte;
                 $chunk['CodeType'] = $chunkID_4th_value;
                 break;
             case 'MTR':
             case 'ATR':
             case 'GTR':
                 $chunk['ID'] = $chunkID_3byte;
                 $chunk['TrackNumber'] = $chunkID_4th_value;
                 break;
         }
         $chunk['Size'] = $size;
         switch (substr($chunkID, 0, 3)) {
             case 'CNT':
                 // CNTI: Contents Information Chunk
                 $chunk['Contents Class'] = $reader->getUI8();
                 $chunk['Contents Type'] = $reader->getUI8();
                 $chunk['Contents Code Type'] = $reader->getUI8();
                 $chunk['Copy Status'] = $reader->getUI8();
                 $chunk['Copy Counts'] = $reader->getUI8();
                 if ($size > 5) {
                     $chunk['Option'] = $reader->getData($size - 5);
                 }
                 break;
             case 'MTR':
                 // MTR*: Score Track Chunk
                 $chunk['Format Type'] = $reader->getUI8();
                 $chunk['Sequence Type'] = $reader->getUI8();
                 $chunk['Timebase D'] = $reader->getUI8();
                 $chunk['Timebase G'] = $reader->getUI8();
                 $chunk['Channnel Status'] = $reader->getUI16BE();
                 $data = $reader->getData($size - 6);
                 $reader_chunkdata = new IO_Bit();
                 $reader_chunkdata->input($data);
                 $this->seekToAlphabet($reader_chunkdata);
                 $chunk[$structure_type] = $this->parseDataChunks($reader_chunkdata);
                 break;
             case 'Mts':
                 // Mtsu, Mtsq, Mts
                 $data = $reader->getData($size);
                 $reader_tracks = new IO_Bit();
                 $reader_tracks->input($data);
                 switch ($chunkID) {
                     case 'Mtsu':
                         // Score Track Setup Data
                     // Score Track Setup Data
                     case 'Mtsq':
                         // Score Track Sequence Data
                         $tracks = array();
                         while ($reader_tracks->hasNextData(4)) {
                             $end_check = $reader_tracks->getUI32BE();
                             if ($end_check == 0) {
                                 break;
                             }
                             $reader_tracks->incrementOffset(-4, 0);
                             $track = array();
                             // Duration
                             if ($chunkID != 'Mtsu') {
                                 // Mtsu は Duration 無し
                                 $duration = $reader_tracks->getUI8();
                                 if ($duration & 0x80) {
                                     $duration = ($duration & 0x7f) << 8;
                                     $duration |= $reader_tracks->getUI8();
                                 }
                                 $track['Duration'] = $duration;
                             }
                             // Event
                             $event = $reader_tracks->getUI8();
                             $eventData = array();
                             if ($event != 0) {
                                 $eventData['Type'] = 'Note Message';
                                 $eventData['GetTime'] = $reader_tracks->getUI8();
                                 // Option ???
                             } else {
                                 $data1 = $reader_tracks->getUI8();
                                 $eventData['Channel'] = $data1 >> 6;
                                 if (($data1 & 0xf) == 0) {
                                     $eventData['Type'] = 'Program change';
                                 } elseif (($data1 & 0xf) == 1) {
                                     $eventData['Type'] = 'Bank Select';
                                 } else {
                                     $msg = sprintf("Unknow Event Data#1=0x%02x", $data1);
                                     //                                throw new Exception($msg);
                                     printf($msg . "\n");
                                     break 2;
                                 }
                                 $eventData['Value'] = $reader_tracks->getUI8();
                             }
                             $track['event'] = $tracks[] = $track;
                         }
                         $chunk['Tracks'] = $tracks;
                         break 2;
                 }
             default:
                 $data = $reader->getData($size);
                 if ($structure_type = $this->nestedChunkIDSize($chunkID)) {
                     $reader_chunkdata = new IO_Bit();
                     $reader_chunkdata->input($data);
                     $method = 'parseData' . $structure_type;
                     $chunk[$structure_type] = $this->{$method}($reader_chunkdata);
                 } else {
                     $chunk['Data'] = $data;
                 }
                 break;
         }
         //            var_dump($chunk);
         $chunks[] = $chunk;
     }
     return $chunks;
 }