function ParseRIFF(&$fd, $startoffset, $maxoffset, &$ThisFileInfo)
 {
     $maxoffset = min($maxoffset, $ThisFileInfo['avdataend']);
     $RIFFchunk = false;
     fseek($fd, $startoffset, SEEK_SET);
     while (ftell($fd) < $maxoffset) {
         $chunkname = fread($fd, 4);
         if (strlen($chunkname) < 4) {
             $ThisFileInfo['error'][] = 'Expecting chunk name at offset ' . (ftell($fd) - 4) . ' but found nothing. Aborting RIFF parsing.';
             break;
         }
         $chunksize = getid3_riff::EitherEndian2Int($ThisFileInfo, fread($fd, 4));
         if ($chunksize == 0) {
             $ThisFileInfo['error'][] = 'Chunk size at offset ' . (ftell($fd) - 4) . ' is zero. Aborting RIFF parsing.';
             break;
         }
         if ($chunksize % 2 != 0) {
             // all structures are packed on word boundaries
             $chunksize++;
         }
         switch ($chunkname) {
             case 'LIST':
                 $listname = fread($fd, 4);
                 switch ($listname) {
                     case 'movi':
                     case 'rec ':
                         $RIFFchunk[$listname]['offset'] = ftell($fd) - 4;
                         $RIFFchunk[$listname]['size'] = $chunksize;
                         static $ParsedAudioStream = false;
                         if ($ParsedAudioStream) {
                             // skip over
                         } else {
                             $WhereWeWere = ftell($fd);
                             $AudioChunkHeader = fread($fd, 12);
                             $AudioChunkStreamNum = substr($AudioChunkHeader, 0, 2);
                             $AudioChunkStreamType = substr($AudioChunkHeader, 2, 2);
                             $AudioChunkSize = getid3_lib::LittleEndian2Int(substr($AudioChunkHeader, 4, 4));
                             if ($AudioChunkStreamType == 'wb') {
                                 $FirstFourBytes = substr($AudioChunkHeader, 8, 4);
                                 if (preg_match('/^\\xFF[\\xE2-\\xE7\\xF2-\\xF7\\xFA-\\xFF][\\x00-\\xEB]/s', $FirstFourBytes)) {
                                     // MP3
                                     if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) {
                                         $dummy = $ThisFileInfo;
                                         $dummy['avdataoffset'] = ftell($fd) - 4;
                                         $dummy['avdataend'] = ftell($fd) + $AudioChunkSize;
                                         getid3_mp3::getOnlyMPEGaudioInfo($fd, $dummy, $dummy['avdataoffset'], false);
                                         if (isset($dummy['mpeg']['audio'])) {
                                             $ThisFileInfo = $dummy;
                                             $ThisFileInfo['audio']['dataformat'] = 'mp' . $ThisFileInfo['mpeg']['audio']['layer'];
                                             $ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['mpeg']['audio']['sample_rate'];
                                             $ThisFileInfo['audio']['channels'] = $ThisFileInfo['mpeg']['audio']['channels'];
                                             $ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['mpeg']['audio']['bitrate'];
                                             $ThisFileInfo['bitrate'] = $ThisFileInfo['audio']['bitrate'];
                                             $ThisFileInfo['audio']['bitrate_mode'] = strtolower($ThisFileInfo['mpeg']['audio']['bitrate_mode']);
                                         }
                                     }
                                 } elseif (preg_match('/^\\x0B\\x77/s', $FirstFourBytes)) {
                                     // AC3
                                     $GETID3_ERRORARRAY =& $ThisFileInfo['warning'];
                                     if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.ac3.php', __FILE__, false)) {
                                         $dummy = $ThisFileInfo;
                                         $dummy['avdataoffset'] = ftell($fd) - 4;
                                         $dummy['avdataend'] = ftell($fd) + $AudioChunkSize;
                                         $dummy['error'] = array();
                                         $ac3_tag = new getid3_ac3($fd, $dummy);
                                         if (empty($dummy['error'])) {
                                             $ThisFileInfo['audio'] = $dummy['audio'];
                                             $ThisFileInfo['ac3'] = $dummy['ac3'];
                                             $ThisFileInfo['warning'] = $dummy['warning'];
                                         }
                                     }
                                 }
                             }
                             $ParsedAudioStream = true;
                             fseek($fd, $WhereWeWere, SEEK_SET);
                         }
                         fseek($fd, $chunksize - 4, SEEK_CUR);
                         break;
                     default:
                         if (!isset($RIFFchunk[$listname])) {
                             $RIFFchunk[$listname] = array();
                         }
                         $LISTchunkParent = $listname;
                         $LISTchunkMaxOffset = ftell($fd) - 4 + $chunksize;
                         if ($parsedChunk = getid3_riff::ParseRIFF($fd, ftell($fd), ftell($fd) + $chunksize - 4, $ThisFileInfo)) {
                             $RIFFchunk[$listname] = array_merge_recursive($RIFFchunk[$listname], $parsedChunk);
                         }
                         break;
                 }
                 break;
             default:
                 $thisindex = 0;
                 if (isset($RIFFchunk[$chunkname]) && is_array($RIFFchunk[$chunkname])) {
                     $thisindex = count($RIFFchunk[$chunkname]);
                 }
                 $RIFFchunk[$chunkname][$thisindex]['offset'] = ftell($fd) - 8;
                 $RIFFchunk[$chunkname][$thisindex]['size'] = $chunksize;
                 switch ($chunkname) {
                     case 'data':
                         $ThisFileInfo['avdataoffset'] = ftell($fd);
                         $ThisFileInfo['avdataend'] = $ThisFileInfo['avdataoffset'] + $chunksize;
                         $RIFFdataChunkContentsTest = fread($fd, 36);
                         if (strlen($RIFFdataChunkContentsTest) > 0 && preg_match('/^\\xFF[\\xE2-\\xE7\\xF2-\\xF7\\xFA-\\xFF][\\x00-\\xEB]/s', substr($RIFFdataChunkContentsTest, 0, 4))) {
                             // Probably is MP3 data
                             if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($RIFFdataChunkContentsTest, 0, 4))) {
                                 getid3_mp3::getOnlyMPEGaudioInfo($fd, $ThisFileInfo, $RIFFchunk[$chunkname][$thisindex]['offset'], false);
                             }
                         } elseif (strlen($RIFFdataChunkContentsTest) > 0 && substr($RIFFdataChunkContentsTest, 0, 2) == "\vw") {
                             // This is probably AC-3 data
                             $GETID3_ERRORARRAY =& $ThisFileInfo['warning'];
                             if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.ac3.php', __FILE__, false)) {
                                 $dummy = $ThisFileInfo;
                                 $dummy['avdataoffset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
                                 $dummy['avdataend'] = $dummy['avdataoffset'] + $RIFFchunk[$chunkname][$thisindex]['size'];
                                 $dummy['error'] = array();
                                 $ac3_tag = new getid3_ac3($fd, $dummy);
                                 if (empty($dummy['error'])) {
                                     $ThisFileInfo['audio'] = $dummy['audio'];
                                     $ThisFileInfo['ac3'] = $dummy['ac3'];
                                     $ThisFileInfo['warning'] = $dummy['warning'];
                                 }
                             }
                         } elseif (strlen($RIFFdataChunkContentsTest) > 0 && substr($RIFFdataChunkContentsTest, 8, 2) == "w\v") {
                             // Dolby Digital WAV
                             // AC-3 content, but not encoded in same format as normal AC-3 file
                             // For one thing, byte order is swapped
                             $GETID3_ERRORARRAY =& $ThisFileInfo['warning'];
                             if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.ac3.php', __FILE__, false)) {
                                 // ok to use tmpfile here - only 56 bytes
                                 if ($fd_temp = tmpfile()) {
                                     for ($i = 0; $i < 28; $i += 2) {
                                         // swap byte order
                                         fwrite($fd_temp, substr($RIFFdataChunkContentsTest, 8 + $i + 1, 1));
                                         fwrite($fd_temp, substr($RIFFdataChunkContentsTest, 8 + $i + 0, 1));
                                     }
                                     $dummy = $ThisFileInfo;
                                     $dummy['avdataoffset'] = 0;
                                     $dummy['avdataend'] = 20;
                                     $dummy['error'] = array();
                                     $ac3_tag = new getid3_ac3($fd_temp, $dummy);
                                     fclose($fd_temp);
                                     if (empty($dummy['error'])) {
                                         $ThisFileInfo['audio'] = $dummy['audio'];
                                         $ThisFileInfo['ac3'] = $dummy['ac3'];
                                         $ThisFileInfo['warning'] = $dummy['warning'];
                                     } else {
                                         $ThisFileInfo['error'][] = 'Errors parsing DolbyDigital WAV: ' . explode(';', $dummy['error']);
                                     }
                                 } else {
                                     $ThisFileInfo['error'][] = 'Could not create temporary file to analyze DolbyDigital WAV';
                                 }
                             }
                         } elseif (strlen($RIFFdataChunkContentsTest) > 0 && substr($RIFFdataChunkContentsTest, 0, 4) == 'wvpk') {
                             // This is WavPack data
                             $ThisFileInfo['wavpack']['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
                             $ThisFileInfo['wavpack']['size'] = getid3_lib::LittleEndian2Int(substr($RIFFdataChunkContentsTest, 4, 4));
                             getid3_riff::RIFFparseWavPackHeader(substr($RIFFdataChunkContentsTest, 8, 28), $ThisFileInfo);
                         } else {
                             // This is some other kind of data (quite possibly just PCM)
                             // do nothing special, just skip it
                         }
                         fseek($fd, $RIFFchunk[$chunkname][$thisindex]['offset'] + 8 + $chunksize, SEEK_SET);
                         break;
                     case 'bext':
                     case 'cart':
                     case 'fmt ':
                     case 'MEXT':
                     case 'DISP':
                         // always read data in
                         $RIFFchunk[$chunkname][$thisindex]['data'] = fread($fd, $chunksize);
                         break;
                     default:
                         if (!empty($LISTchunkParent) && $RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size'] <= $LISTchunkMaxOffset) {
                             $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
                             $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size'] = $RIFFchunk[$chunkname][$thisindex]['size'];
                             unset($RIFFchunk[$chunkname][$thisindex]['offset']);
                             unset($RIFFchunk[$chunkname][$thisindex]['size']);
                             if (isset($RIFFchunk[$chunkname][$thisindex]) && empty($RIFFchunk[$chunkname][$thisindex])) {
                                 unset($RIFFchunk[$chunkname][$thisindex]);
                             }
                             if (isset($RIFFchunk[$chunkname]) && empty($RIFFchunk[$chunkname])) {
                                 unset($RIFFchunk[$chunkname]);
                             }
                             $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['data'] = fread($fd, $chunksize);
                         } elseif ($chunksize < 2048) {
                             // only read data in if smaller than 2kB
                             $RIFFchunk[$chunkname][$thisindex]['data'] = fread($fd, $chunksize);
                         } else {
                             fseek($fd, $chunksize, SEEK_CUR);
                         }
                         break;
                 }
                 break;
         }
     }
     return $RIFFchunk;
 }
 public function ParseRIFF($startoffset, $maxoffset)
 {
     $info =& $this->getid3->info;
     $RIFFchunk = false;
     $FoundAllChunksWeNeed = false;
     try {
         $this->fseek($startoffset);
         $maxoffset = min($maxoffset, $info['avdataend']);
         while ($this->ftell() < $maxoffset) {
             $chunknamesize = $this->fread(8);
             //$chunkname =                          substr($chunknamesize, 0, 4);
             $chunkname = str_replace("", '_', substr($chunknamesize, 0, 4));
             // note: chunk names of 4 null bytes do appear to be legal (has been observed inside INFO and PRMI chunks, for example), but makes traversing array keys more difficult
             $chunksize = $this->EitherEndian2Int(substr($chunknamesize, 4, 4));
             //if (strlen(trim($chunkname, "\x00")) < 4) {
             if (strlen($chunkname) < 4) {
                 $this->error('Expecting chunk name at offset ' . ($this->ftell() - 8) . ' but found nothing. Aborting RIFF parsing.');
                 break;
             }
             if ($chunksize == 0 && $chunkname != 'JUNK') {
                 $this->warning('Chunk (' . $chunkname . ') size at offset ' . ($this->ftell() - 4) . ' is zero. Aborting RIFF parsing.');
                 break;
             }
             if ($chunksize % 2 != 0) {
                 // all structures are packed on word boundaries
                 $chunksize++;
             }
             switch ($chunkname) {
                 case 'LIST':
                     $listname = $this->fread(4);
                     if (preg_match('#^(movi|rec )$#i', $listname)) {
                         $RIFFchunk[$listname]['offset'] = $this->ftell() - 4;
                         $RIFFchunk[$listname]['size'] = $chunksize;
                         if (!$FoundAllChunksWeNeed) {
                             $WhereWeWere = $this->ftell();
                             $AudioChunkHeader = $this->fread(12);
                             $AudioChunkStreamNum = substr($AudioChunkHeader, 0, 2);
                             $AudioChunkStreamType = substr($AudioChunkHeader, 2, 2);
                             $AudioChunkSize = getid3_lib::LittleEndian2Int(substr($AudioChunkHeader, 4, 4));
                             if ($AudioChunkStreamType == 'wb') {
                                 $FirstFourBytes = substr($AudioChunkHeader, 8, 4);
                                 if (preg_match('/^\\xFF[\\xE2-\\xE7\\xF2-\\xF7\\xFA-\\xFF][\\x00-\\xEB]/s', $FirstFourBytes)) {
                                     // MP3
                                     if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) {
                                         $getid3_temp = new getID3();
                                         $getid3_temp->openfile($this->getid3->filename);
                                         $getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
                                         $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize;
                                         $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__);
                                         $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false);
                                         if (isset($getid3_temp->info['mpeg']['audio'])) {
                                             $info['mpeg']['audio'] = $getid3_temp->info['mpeg']['audio'];
                                             $info['audio'] = $getid3_temp->info['audio'];
                                             $info['audio']['dataformat'] = 'mp' . $info['mpeg']['audio']['layer'];
                                             $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate'];
                                             $info['audio']['channels'] = $info['mpeg']['audio']['channels'];
                                             $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate'];
                                             $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
                                             //$info['bitrate']               = $info['audio']['bitrate'];
                                         }
                                         unset($getid3_temp, $getid3_mp3);
                                     }
                                 } elseif (strpos($FirstFourBytes, getid3_ac3::syncword) === 0) {
                                     // AC3
                                     $getid3_temp = new getID3();
                                     $getid3_temp->openfile($this->getid3->filename);
                                     $getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
                                     $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize;
                                     $getid3_ac3 = new getid3_ac3($getid3_temp);
                                     $getid3_ac3->Analyze();
                                     if (empty($getid3_temp->info['error'])) {
                                         $info['audio'] = $getid3_temp->info['audio'];
                                         $info['ac3'] = $getid3_temp->info['ac3'];
                                         if (!empty($getid3_temp->info['warning'])) {
                                             foreach ($getid3_temp->info['warning'] as $key => $value) {
                                                 $info['warning'][] = $value;
                                             }
                                         }
                                     }
                                     unset($getid3_temp, $getid3_ac3);
                                 }
                             }
                             $FoundAllChunksWeNeed = true;
                             $this->fseek($WhereWeWere);
                         }
                         $this->fseek($chunksize - 4, SEEK_CUR);
                     } else {
                         if (!isset($RIFFchunk[$listname])) {
                             $RIFFchunk[$listname] = array();
                         }
                         $LISTchunkParent = $listname;
                         $LISTchunkMaxOffset = $this->ftell() - 4 + $chunksize;
                         if ($parsedChunk = $this->ParseRIFF($this->ftell(), $LISTchunkMaxOffset)) {
                             $RIFFchunk[$listname] = array_merge_recursive($RIFFchunk[$listname], $parsedChunk);
                         }
                     }
                     break;
                 default:
                     if (preg_match('#^[0-9]{2}(wb|pc|dc|db)$#', $chunkname)) {
                         $this->fseek($chunksize, SEEK_CUR);
                         break;
                     }
                     $thisindex = 0;
                     if (isset($RIFFchunk[$chunkname]) && is_array($RIFFchunk[$chunkname])) {
                         $thisindex = count($RIFFchunk[$chunkname]);
                     }
                     $RIFFchunk[$chunkname][$thisindex]['offset'] = $this->ftell() - 8;
                     $RIFFchunk[$chunkname][$thisindex]['size'] = $chunksize;
                     switch ($chunkname) {
                         case 'data':
                             $info['avdataoffset'] = $this->ftell();
                             $info['avdataend'] = $info['avdataoffset'] + $chunksize;
                             $testData = $this->fread(36);
                             if ($testData === '') {
                                 break;
                             }
                             if (preg_match('/^\\xFF[\\xE2-\\xE7\\xF2-\\xF7\\xFA-\\xFF][\\x00-\\xEB]/s', substr($testData, 0, 4))) {
                                 // Probably is MP3 data
                                 if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($testData, 0, 4))) {
                                     $getid3_temp = new getID3();
                                     $getid3_temp->openfile($this->getid3->filename);
                                     $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
                                     $getid3_temp->info['avdataend'] = $info['avdataend'];
                                     $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__);
                                     $getid3_mp3->getOnlyMPEGaudioInfo($info['avdataoffset'], false);
                                     if (empty($getid3_temp->info['error'])) {
                                         $info['audio'] = $getid3_temp->info['audio'];
                                         $info['mpeg'] = $getid3_temp->info['mpeg'];
                                     }
                                     unset($getid3_temp, $getid3_mp3);
                                 }
                             } elseif (($isRegularAC3 = substr($testData, 0, 2) == getid3_ac3::syncword) || substr($testData, 8, 2) == strrev(getid3_ac3::syncword)) {
                                 // This is probably AC-3 data
                                 $getid3_temp = new getID3();
                                 if ($isRegularAC3) {
                                     $getid3_temp->openfile($this->getid3->filename);
                                     $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
                                     $getid3_temp->info['avdataend'] = $info['avdataend'];
                                 }
                                 $getid3_ac3 = new getid3_ac3($getid3_temp);
                                 if ($isRegularAC3) {
                                     $getid3_ac3->Analyze();
                                 } else {
                                     // Dolby Digital WAV
                                     // AC-3 content, but not encoded in same format as normal AC-3 file
                                     // For one thing, byte order is swapped
                                     $ac3_data = '';
                                     for ($i = 0; $i < 28; $i += 2) {
                                         $ac3_data .= substr($testData, 8 + $i + 1, 1);
                                         $ac3_data .= substr($testData, 8 + $i + 0, 1);
                                     }
                                     $getid3_ac3->AnalyzeString($ac3_data);
                                 }
                                 if (empty($getid3_temp->info['error'])) {
                                     $info['audio'] = $getid3_temp->info['audio'];
                                     $info['ac3'] = $getid3_temp->info['ac3'];
                                     if (!empty($getid3_temp->info['warning'])) {
                                         foreach ($getid3_temp->info['warning'] as $newerror) {
                                             $this->warning('getid3_ac3() says: [' . $newerror . ']');
                                         }
                                     }
                                 }
                                 unset($getid3_temp, $getid3_ac3);
                             } elseif (preg_match('/^(' . implode('|', array_map('preg_quote', getid3_dts::$syncwords)) . ')/', $testData)) {
                                 // This is probably DTS data
                                 $getid3_temp = new getID3();
                                 $getid3_temp->openfile($this->getid3->filename);
                                 $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
                                 $getid3_dts = new getid3_dts($getid3_temp);
                                 $getid3_dts->Analyze();
                                 if (empty($getid3_temp->info['error'])) {
                                     $info['audio'] = $getid3_temp->info['audio'];
                                     $info['dts'] = $getid3_temp->info['dts'];
                                     $info['playtime_seconds'] = $getid3_temp->info['playtime_seconds'];
                                     // may not match RIFF calculations since DTS-WAV often used 14/16 bit-word packing
                                     if (!empty($getid3_temp->info['warning'])) {
                                         foreach ($getid3_temp->info['warning'] as $newerror) {
                                             $this->warning('getid3_dts() says: [' . $newerror . ']');
                                         }
                                     }
                                 }
                                 unset($getid3_temp, $getid3_dts);
                             } elseif (substr($testData, 0, 4) == 'wvpk') {
                                 // This is WavPack data
                                 $info['wavpack']['offset'] = $info['avdataoffset'];
                                 $info['wavpack']['size'] = getid3_lib::LittleEndian2Int(substr($testData, 4, 4));
                                 $this->parseWavPackHeader(substr($testData, 8, 28));
                             } else {
                                 // This is some other kind of data (quite possibly just PCM)
                                 // do nothing special, just skip it
                             }
                             $nextoffset = $info['avdataend'];
                             $this->fseek($nextoffset);
                             break;
                         case 'iXML':
                         case 'bext':
                         case 'cart':
                         case 'fmt ':
                         case 'strh':
                         case 'strf':
                         case 'indx':
                         case 'MEXT':
                         case 'DISP':
                             // always read data in
                         // always read data in
                         case 'JUNK':
                             // should be: never read data in
                             // but some programs write their version strings in a JUNK chunk (e.g. VirtualDub, AVIdemux, etc)
                             if ($chunksize < 1048576) {
                                 if ($chunksize > 0) {
                                     $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize);
                                     if ($chunkname == 'JUNK') {
                                         if (preg_match('#^([\\x20-\\x7F]+)#', $RIFFchunk[$chunkname][$thisindex]['data'], $matches)) {
                                             // only keep text characters [chr(32)-chr(127)]
                                             $info['riff']['comments']['junk'][] = trim($matches[1]);
                                         }
                                         // but if nothing there, ignore
                                         // remove the key in either case
                                         unset($RIFFchunk[$chunkname][$thisindex]['data']);
                                     }
                                 }
                             } else {
                                 $this->warning('Chunk "' . $chunkname . '" at offset ' . $this->ftell() . ' is unexpectedly larger than 1MB (claims to be ' . number_format($chunksize) . ' bytes), skipping data');
                                 $this->fseek($chunksize, SEEK_CUR);
                             }
                             break;
                             //case 'IDVX':
                             //	$info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunksize));
                             //	break;
                         //case 'IDVX':
                         //	$info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunksize));
                         //	break;
                         default:
                             if (!empty($LISTchunkParent) && $RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size'] <= $LISTchunkMaxOffset) {
                                 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
                                 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size'] = $RIFFchunk[$chunkname][$thisindex]['size'];
                                 unset($RIFFchunk[$chunkname][$thisindex]['offset']);
                                 unset($RIFFchunk[$chunkname][$thisindex]['size']);
                                 if (isset($RIFFchunk[$chunkname][$thisindex]) && empty($RIFFchunk[$chunkname][$thisindex])) {
                                     unset($RIFFchunk[$chunkname][$thisindex]);
                                 }
                                 if (isset($RIFFchunk[$chunkname]) && empty($RIFFchunk[$chunkname])) {
                                     unset($RIFFchunk[$chunkname]);
                                 }
                                 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['data'] = $this->fread($chunksize);
                             } elseif ($chunksize < 2048) {
                                 // only read data in if smaller than 2kB
                                 $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize);
                             } else {
                                 $this->fseek($chunksize, SEEK_CUR);
                             }
                             break;
                     }
                     break;
             }
         }
     } catch (getid3_exception $e) {
         if ($e->getCode() == 10) {
             $this->warning('RIFF parser: ' . $e->getMessage());
         } else {
             throw $e;
         }
     }
     return $RIFFchunk;
 }
 public function ParseRIFF($start_offset, $max_offset)
 {
     $getid3 = $this->getid3;
     $info =& $getid3->info;
     $endian_function = $this->endian_function;
     $max_offset = min($max_offset, $info['avdataend']);
     $riff_chunk = false;
     $this->fseek($start_offset, SEEK_SET);
     while ($this->ftell() < $max_offset) {
         $chunk_name = $this->fread(4);
         if (strlen($chunk_name) < 4) {
             throw new getid3_exception('Expecting chunk name at offset ' . ($this->ftell() - 4) . ' but found nothing. Aborting RIFF parsing.');
         }
         $chunk_size = getid3_lib::$endian_function($this->fread(4));
         if ($chunk_size == 0) {
             continue;
             throw new getid3_exception('Chunk size at offset ' . ($this->ftell() - 4) . ' is zero. Aborting RIFF parsing.');
         }
         if ($chunk_size % 2 != 0) {
             // all structures are packed on word boundaries
             $chunk_size++;
         }
         switch ($chunk_name) {
             case 'LIST':
                 $list_name = $this->fread(4);
                 switch ($list_name) {
                     case 'movi':
                     case 'rec ':
                         $riff_chunk[$list_name]['offset'] = $this->ftell() - 4;
                         $riff_chunk[$list_name]['size'] = $chunk_size;
                         static $parsed_audio_stream = false;
                         if (!$parsed_audio_stream) {
                             $where_we_were = $this->ftell();
                             $audio_chunk_header = $this->fread(12);
                             $audio_chunk_stream_num = substr($audio_chunk_header, 0, 2);
                             $audio_chunk_stream_type = substr($audio_chunk_header, 2, 2);
                             $audio_chunk_size = getid3_lib::LittleEndian2Int(substr($audio_chunk_header, 4, 4));
                             if ($audio_chunk_stream_type == 'wb') {
                                 $first_four_bytes = substr($audio_chunk_header, 8, 4);
                                 //// MPEG
                                 if (preg_match('/^\\xFF[\\xE2-\\xE7\\xF2-\\xF7\\xFA-\\xFF][\\x00-\\xEB]/s', $first_four_bytes)) {
                                     if (!$getid3->include_module_optional('audio.mp3')) {
                                         $getid3->warning('MP3 skipped because mp3 module is missing.');
                                     } elseif (getid3_mp3::MPEGaudioHeaderBytesValid($first_four_bytes)) {
                                         // Clone getid3 - messing with offsets - better safe than sorry
                                         $clone = clone $getid3;
                                         $clone->info['avdataoffset'] = $this->ftell() - 4;
                                         $clone->info['avdataend'] = $this->ftell() + $audio_chunk_size;
                                         $mp3 = new getid3_mp3($clone);
                                         $mp3->AnalyzeMPEGaudioInfo();
                                         // Import from clone and destroy
                                         if (isset($clone->info['mpeg']['audio'])) {
                                             $info['mpeg']['audio'] = $clone->info['mpeg']['audio'];
                                             $info['audio']['dataformat'] = 'mp' . $info['mpeg']['audio']['layer'];
                                             $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate'];
                                             $info['audio']['channels'] = $info['mpeg']['audio']['channels'];
                                             $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate'];
                                             $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
                                             $info['bitrate'] = $info['audio']['bitrate'];
                                             $getid3->warning($clone->warnings());
                                             unset($clone);
                                         }
                                     }
                                 } elseif (preg_match('/^\\x0B\\x77/s', $first_four_bytes)) {
                                     if (!$getid3->include_module_optional('audio.ac3')) {
                                         $getid3->warning('AC3 skipped because ac3 module is missing.');
                                     } else {
                                         // Clone getid3 - messing with offsets - better safe than sorry
                                         $clone = clone $getid3;
                                         $clone->info['avdataoffset'] = $this->ftell() - 4;
                                         $clone->info['avdataend'] = $this->ftell() + $audio_chunk_size;
                                         // Analyze clone by fp
                                         $ac3 = new getid3_ac3($clone);
                                         $ac3->Analyze();
                                         // Import from clone and destroy
                                         $info['audio'] = $clone->info['audio'];
                                         $info['ac3'] = $clone->info['ac3'];
                                         $getid3->warning($clone->warnings());
                                         unset($clone);
                                     }
                                 }
                             }
                             $parsed_audio_stream = true;
                             $this->fseek($where_we_were, SEEK_SET);
                         }
                         $this->fseek($chunk_size - 4, SEEK_CUR);
                         break;
                     default:
                         if (!isset($riff_chunk[$list_name])) {
                             $riff_chunk[$list_name] = array();
                         }
                         $list_chunk_parent = $list_name;
                         $list_chunk_max_offset = $this->ftell() - 4 + $chunk_size;
                         if ($parsed_chunk = $this->ParseRIFF($this->ftell(), $this->ftell() + $chunk_size - 4)) {
                             $riff_chunk[$list_name] = array_merge_recursive($riff_chunk[$list_name], $parsed_chunk);
                         }
                         break;
                 }
                 break;
             default:
                 $this_index = 0;
                 if (isset($riff_chunk[$chunk_name]) && is_array($riff_chunk[$chunk_name])) {
                     $this_index = count($riff_chunk[$chunk_name]);
                 }
                 $riff_chunk[$chunk_name][$this_index]['offset'] = $this->ftell() - 8;
                 $riff_chunk[$chunk_name][$this_index]['size'] = $chunk_size;
                 switch ($chunk_name) {
                     case 'data':
                         $info['avdataoffset'] = $this->ftell();
                         $info['avdataend'] = $info['avdataoffset'] + $chunk_size;
                         $riff_data_chunk_contents_test = $this->fread(36);
                         //// This is probably MP3 data
                         if (strlen($riff_data_chunk_contents_test) > 0 && preg_match('/^\\xFF[\\xE2-\\xE7\\xF2-\\xF7\\xFA-\\xFF][\\x00-\\xEB]/s', substr($riff_data_chunk_contents_test, 0, 4))) {
                             try {
                                 if (!$getid3->include_module_optional('audio.mp3')) {
                                     $getid3->warning('MP3 skipped because mp3 module is missing.');
                                 }
                                 // Clone getid3 - messing with offsets - better safe than sorry
                                 $clone = clone $getid3;
                                 if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($riff_data_chunk_contents_test, 0, 4))) {
                                     $mp3 = new getid3_mp3($clone);
                                     $mp3->AnalyzeMPEGaudioInfo();
                                     // Import from clone and destroy
                                     if (isset($clone->info['mpeg']['audio'])) {
                                         $info['mpeg']['audio'] = $clone->info['mpeg']['audio'];
                                         $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate'];
                                         $info['audio']['channels'] = $info['mpeg']['audio']['channels'];
                                         $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate'];
                                         $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
                                         $info['bitrate'] = $info['audio']['bitrate'];
                                         $getid3->warning($clone->warnings());
                                         unset($clone);
                                     }
                                 }
                             } catch (Exception $e) {
                                 // do nothing - not MP3 data
                             }
                         } elseif (strlen($riff_data_chunk_contents_test) > 0 && substr($riff_data_chunk_contents_test, 0, 2) == "\vw") {
                             if (!$getid3->include_module_optional('audio.ac3')) {
                                 $getid3->warning('AC3 skipped because ac3 module is missing.');
                             } else {
                                 // Clone getid3 - messing with offsets - better safe than sorry
                                 $clone = clone $getid3;
                                 $clone->info['avdataoffset'] = $riff_chunk[$chunk_name][$this_index]['offset'];
                                 $clone->info['avdataend'] = $clone->info['avdataoffset'] + $riff_chunk[$chunk_name][$this_index]['size'];
                                 // Analyze clone by fp
                                 $ac3 = new getid3_ac3($clone);
                                 $ac3->Analyze();
                                 // Import from clone and destroy
                                 $info['audio'] = $clone->info['audio'];
                                 $info['ac3'] = $clone->info['ac3'];
                                 $getid3->warning($clone->warnings());
                                 unset($clone);
                             }
                         } elseif (strlen($riff_data_chunk_contents_test) > 0 && substr($riff_data_chunk_contents_test, 8, 2) == "w\v") {
                             if (!$getid3->include_module_optional('audio.ac3')) {
                                 $getid3->warning('AC3 skipped because ac3 module is missing.');
                             } else {
                                 // Extract ac3 data to string
                                 $ac3_data = '';
                                 for ($i = 0; $i < 28; $i += 2) {
                                     // swap byte order
                                     $ac3_data .= substr($riff_data_chunk_contents_test, 8 + $i + 1, 1);
                                     $ac3_data .= substr($riff_data_chunk_contents_test, 8 + $i + 0, 1);
                                 }
                                 // Clone getid3 - messing with offsets - better safe than sorry
                                 $clone = clone $getid3;
                                 $clone->info['avdataoffset'] = 0;
                                 $clone->info['avdataend'] = 20;
                                 // Analyse clone by string
                                 $ac3 = new getid3_ac3($clone);
                                 $ac3->AnalyzeString($ac3_data);
                                 // Import from clone and destroy
                                 $info['audio'] = $clone->info['audio'];
                                 $info['ac3'] = $clone->info['ac3'];
                                 $getid3->warning($clone->warnings());
                                 unset($clone);
                             }
                         }
                         if (strlen($riff_data_chunk_contents_test) > 0 && substr($riff_data_chunk_contents_test, 0, 4) == 'wvpk') {
                             // This is WavPack data
                             $info['wavpack']['offset'] = $riff_chunk[$chunk_name][$this_index]['offset'];
                             $info['wavpack']['size'] = getid3_lib::LittleEndian2Int(substr($riff_data_chunk_contents_test, 4, 4));
                             $this->RIFFparseWavPackHeader(substr($riff_data_chunk_contents_test, 8, 28));
                         } else {
                             // This is some other kind of data (quite possibly just PCM)
                             // do nothing special, just skip it
                         }
                         $this->fseek($riff_chunk[$chunk_name][$this_index]['offset'] + 8 + $chunk_size, SEEK_SET);
                         break;
                     case 'bext':
                     case 'cart':
                     case 'fmt ':
                     case 'MEXT':
                     case 'DISP':
                         // always read data in
                         $riff_chunk[$chunk_name][$this_index]['data'] = $this->fread($chunk_size);
                         break;
                     default:
                         if (!empty($list_chunk_parent) && $riff_chunk[$chunk_name][$this_index]['offset'] + $riff_chunk[$chunk_name][$this_index]['size'] <= $list_chunk_max_offset) {
                             $riff_chunk[$list_chunk_parent][$chunk_name][$this_index]['offset'] = $riff_chunk[$chunk_name][$this_index]['offset'];
                             $riff_chunk[$list_chunk_parent][$chunk_name][$this_index]['size'] = $riff_chunk[$chunk_name][$this_index]['size'];
                             unset($riff_chunk[$chunk_name][$this_index]['offset']);
                             unset($riff_chunk[$chunk_name][$this_index]['size']);
                             if (isset($riff_chunk[$chunk_name][$this_index]) && empty($riff_chunk[$chunk_name][$this_index])) {
                                 unset($riff_chunk[$chunk_name][$this_index]);
                             }
                             if (isset($riff_chunk[$chunk_name]) && empty($riff_chunk[$chunk_name])) {
                                 unset($riff_chunk[$chunk_name]);
                             }
                             $riff_chunk[$list_chunk_parent][$chunk_name][$this_index]['data'] = $this->fread($chunk_size);
                         } elseif ($chunk_size < 2048) {
                             // only read data in if smaller than 2kB
                             $riff_chunk[$chunk_name][$this_index]['data'] = $this->fread($chunk_size);
                         } else {
                             $this->fseek($chunk_size, SEEK_CUR);
                         }
                         break;
                 }
                 break;
         }
     }
     return $riff_chunk;
 }
 function ParseRIFF($startoffset, $maxoffset)
 {
     $info =& $this->getid3->info;
     $maxoffset = min($maxoffset, $info['avdataend']);
     $RIFFchunk = false;
     $FoundAllChunksWeNeed = false;
     if ($startoffset < 0 || !getid3_lib::intValueSupported($startoffset)) {
         $info['warning'][] = 'Unable to ParseRIFF() at ' . $startoffset . ' because beyond ' . round(PHP_INT_MAX / 1073741824) . 'GB limit of PHP filesystem functions';
         return false;
     }
     $max_usable_offset = min(PHP_INT_MAX - 1024, $maxoffset);
     if ($maxoffset > $max_usable_offset) {
         $info['warning'][] = 'ParseRIFF() may return incomplete data for chunk starting at ' . $startoffset . ' because beyond it extends to ' . $maxoffset . ', which is beyond the ' . round(PHP_INT_MAX / 1073741824) . 'GB limit of PHP filesystem functions';
     }
     fseek($this->getid3->fp, $startoffset, SEEK_SET);
     while (ftell($this->getid3->fp) < $max_usable_offset) {
         $chunknamesize = fread($this->getid3->fp, 8);
         $chunkname = substr($chunknamesize, 0, 4);
         $chunksize = $this->EitherEndian2Int(substr($chunknamesize, 4, 4));
         if (strlen($chunkname) < 4) {
             $info['error'][] = 'Expecting chunk name at offset ' . (ftell($this->getid3->fp) - 4) . ' but found nothing. Aborting RIFF parsing.';
             break;
         }
         if ($chunksize == 0) {
             if ($chunkname == 'JUNK') {
                 // we'll allow zero-size JUNK frames
             } else {
                 $info['warning'][] = 'Chunk size at offset ' . (ftell($this->getid3->fp) - 4) . ' is zero. Aborting RIFF parsing.';
                 break;
             }
         }
         if ($chunksize % 2 != 0) {
             // all structures are packed on word boundaries
             $chunksize++;
         }
         switch ($chunkname) {
             case 'LIST':
                 $listname = fread($this->getid3->fp, 4);
                 if (preg_match('#^(movi|rec )$#i', $listname)) {
                     $RIFFchunk[$listname]['offset'] = ftell($this->getid3->fp) - 4;
                     $RIFFchunk[$listname]['size'] = $chunksize;
                     if ($FoundAllChunksWeNeed) {
                         // skip over
                     } else {
                         $WhereWeWere = ftell($this->getid3->fp);
                         $AudioChunkHeader = fread($this->getid3->fp, 12);
                         $AudioChunkStreamNum = substr($AudioChunkHeader, 0, 2);
                         $AudioChunkStreamType = substr($AudioChunkHeader, 2, 2);
                         $AudioChunkSize = getid3_lib::LittleEndian2Int(substr($AudioChunkHeader, 4, 4));
                         if ($AudioChunkStreamType == 'wb') {
                             $FirstFourBytes = substr($AudioChunkHeader, 8, 4);
                             if (preg_match('/^\\xFF[\\xE2-\\xE7\\xF2-\\xF7\\xFA-\\xFF][\\x00-\\xEB]/s', $FirstFourBytes)) {
                                 // MP3
                                 if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) {
                                     $getid3_temp = new getID3();
                                     $getid3_temp->openfile($this->getid3->filename);
                                     $getid3_temp->info['avdataoffset'] = ftell($this->getid3->fp) - 4;
                                     $getid3_temp->info['avdataend'] = ftell($this->getid3->fp) + $AudioChunkSize;
                                     $getid3_mp3 = new getid3_mp3($getid3_temp);
                                     $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false);
                                     if (isset($getid3_temp->info['mpeg']['audio'])) {
                                         $info['mpeg']['audio'] = $getid3_temp->info['mpeg']['audio'];
                                         $info['audio'] = $getid3_temp->info['audio'];
                                         $info['audio']['dataformat'] = 'mp' . $info['mpeg']['audio']['layer'];
                                         $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate'];
                                         $info['audio']['channels'] = $info['mpeg']['audio']['channels'];
                                         $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate'];
                                         $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
                                         //$info['bitrate']               = $info['audio']['bitrate'];
                                     }
                                     unset($getid3_temp, $getid3_mp3);
                                 }
                             } elseif (preg_match('/^\\x0B\\x77/s', $FirstFourBytes)) {
                                 // AC3
                                 if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.ac3.php', __FILE__, false)) {
                                     $getid3_temp = new getID3();
                                     $getid3_temp->openfile($this->getid3->filename);
                                     $getid3_temp->info['avdataoffset'] = ftell($this->getid3->fp) - 4;
                                     $getid3_temp->info['avdataend'] = ftell($this->getid3->fp) + $AudioChunkSize;
                                     $getid3_ac3 = new getid3_ac3($getid3_temp);
                                     $getid3_ac3->Analyze();
                                     if (empty($getid3_temp->info['error'])) {
                                         $info['audio'] = $getid3_temp->info['audio'];
                                         $info['ac3'] = $getid3_temp->info['ac3'];
                                         if (!empty($getid3_temp->info['warning'])) {
                                             foreach ($getid3_temp->info['warning'] as $key => $value) {
                                                 $info['warning'][] = $value;
                                             }
                                         }
                                     }
                                     unset($getid3_temp, $getid3_ac3);
                                 }
                             }
                         }
                         $FoundAllChunksWeNeed = true;
                         fseek($this->getid3->fp, $WhereWeWere, SEEK_SET);
                     }
                     fseek($this->getid3->fp, $chunksize - 4, SEEK_CUR);
                     //} elseif (preg_match('#^[0-9]{2}(wb|pc|dc|db)$#i', $listname)) {
                     //
                     //	// data chunk, ignore
                     //
                 } else {
                     if (!isset($RIFFchunk[$listname])) {
                         $RIFFchunk[$listname] = array();
                     }
                     $LISTchunkParent = $listname;
                     $LISTchunkMaxOffset = ftell($this->getid3->fp) - 4 + $chunksize;
                     if ($parsedChunk = $this->ParseRIFF(ftell($this->getid3->fp), ftell($this->getid3->fp) + $chunksize - 4)) {
                         $RIFFchunk[$listname] = array_merge_recursive($RIFFchunk[$listname], $parsedChunk);
                     }
                 }
                 break;
             default:
                 if (preg_match('#^[0-9]{2}(wb|pc|dc|db)$#', $chunkname)) {
                     $nextoffset = ftell($this->getid3->fp) + $chunksize;
                     if ($nextoffset < 0 || !getid3_lib::intValueSupported($nextoffset)) {
                         $info['warning'][] = 'Unable to parse chunk at offset ' . $nextoffset . ' because beyond ' . round(PHP_INT_MAX / 1073741824) . 'GB limit of PHP filesystem functions';
                         break 2;
                     }
                     fseek($this->getid3->fp, $nextoffset, SEEK_SET);
                     break;
                 }
                 $thisindex = 0;
                 if (isset($RIFFchunk[$chunkname]) && is_array($RIFFchunk[$chunkname])) {
                     $thisindex = count($RIFFchunk[$chunkname]);
                 }
                 $RIFFchunk[$chunkname][$thisindex]['offset'] = ftell($this->getid3->fp) - 8;
                 $RIFFchunk[$chunkname][$thisindex]['size'] = $chunksize;
                 switch ($chunkname) {
                     case 'data':
                         $info['avdataoffset'] = ftell($this->getid3->fp);
                         $info['avdataend'] = $info['avdataoffset'] + $chunksize;
                         $RIFFdataChunkContentsTest = fread($this->getid3->fp, 36);
                         if (strlen($RIFFdataChunkContentsTest) > 0 && preg_match('/^\\xFF[\\xE2-\\xE7\\xF2-\\xF7\\xFA-\\xFF][\\x00-\\xEB]/s', substr($RIFFdataChunkContentsTest, 0, 4))) {
                             // Probably is MP3 data
                             if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($RIFFdataChunkContentsTest, 0, 4))) {
                                 $getid3_temp = new getID3();
                                 $getid3_temp->openfile($this->getid3->filename);
                                 $getid3_temp->info['avdataoffset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
                                 $getid3_temp->info['avdataend'] = $RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size'];
                                 $getid3_mp3 = new getid3_mp3($getid3_temp);
                                 $getid3_mp3->getOnlyMPEGaudioInfo($RIFFchunk[$chunkname][$thisindex]['offset'], false);
                                 if (empty($getid3_temp->info['error'])) {
                                     $info['mpeg'] = $getid3_temp->info['mpeg'];
                                     $info['audio'] = $getid3_temp->info['audio'];
                                 }
                                 unset($getid3_temp, $getid3_mp3);
                             }
                         } elseif (strlen($RIFFdataChunkContentsTest) > 0 && substr($RIFFdataChunkContentsTest, 0, 2) == "\vw") {
                             // This is probably AC-3 data
                             if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.ac3.php', __FILE__, false)) {
                                 $getid3_temp = new getID3();
                                 $getid3_temp->openfile($this->getid3->filename);
                                 $getid3_temp->info['avdataoffset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
                                 $getid3_temp->info['avdataend'] = $RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size'];
                                 $getid3_ac3 = new getid3_ac3($getid3_temp);
                                 $getid3_ac3->Analyze();
                                 if (empty($getid3_temp->info['error'])) {
                                     $info['audio'] = $getid3_temp->info['audio'];
                                     $info['ac3'] = $getid3_temp->info['ac3'];
                                     $info['warning'] = $getid3_temp->info['warning'];
                                 }
                                 unset($getid3_temp, $getid3_ac3);
                             }
                         } elseif (strlen($RIFFdataChunkContentsTest) > 0 && substr($RIFFdataChunkContentsTest, 8, 2) == "w\v") {
                             // Dolby Digital WAV
                             // AC-3 content, but not encoded in same format as normal AC-3 file
                             // For one thing, byte order is swapped
                             if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.ac3.php', __FILE__, false)) {
                                 // ok to use tmpfile here - only 56 bytes
                                 if ($RIFFtempfilename = tempnam(GETID3_TEMP_DIR, 'id3')) {
                                     if ($fd_temp = fopen($RIFFtempfilename, 'wb')) {
                                         for ($i = 0; $i < 28; $i += 2) {
                                             // swap byte order
                                             fwrite($fd_temp, substr($RIFFdataChunkContentsTest, 8 + $i + 1, 1));
                                             fwrite($fd_temp, substr($RIFFdataChunkContentsTest, 8 + $i + 0, 1));
                                         }
                                         fclose($fd_temp);
                                         $getid3_temp = new getID3();
                                         $getid3_temp->openfile($RIFFtempfilename);
                                         $getid3_temp->info['avdataend'] = 20;
                                         $getid3_ac3 = new getid3_ac3($getid3_temp);
                                         $getid3_ac3->Analyze();
                                         if (empty($getid3_temp->info['error'])) {
                                             $info['audio'] = $getid3_temp->info['audio'];
                                             $info['ac3'] = $getid3_temp->info['ac3'];
                                             $info['warning'] = $getid3_temp->info['warning'];
                                         } else {
                                             $info['error'][] = 'Error parsing Dolby Digital WAV (AC3-in-RIFF): ' . implode(';', $getid3_temp->info['error']);
                                         }
                                         unset($getid3_ac3, $getid3_temp);
                                     } else {
                                         $info['error'][] = 'Error parsing Dolby Digital WAV (AC3-in-RIFF): failed to write temp file';
                                     }
                                     unlink($RIFFtempfilename);
                                 } else {
                                     $info['error'][] = 'Error parsing Dolby Digital WAV (AC3-in-RIFF): failed to write temp file';
                                 }
                             }
                         } elseif (strlen($RIFFdataChunkContentsTest) > 0 && substr($RIFFdataChunkContentsTest, 0, 4) == 'wvpk') {
                             // This is WavPack data
                             $info['wavpack']['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
                             $info['wavpack']['size'] = getid3_lib::LittleEndian2Int(substr($RIFFdataChunkContentsTest, 4, 4));
                             $this->RIFFparseWavPackHeader(substr($RIFFdataChunkContentsTest, 8, 28));
                         } else {
                             // This is some other kind of data (quite possibly just PCM)
                             // do nothing special, just skip it
                         }
                         $nextoffset = $RIFFchunk[$chunkname][$thisindex]['offset'] + 8 + $chunksize;
                         if ($nextoffset < 0 || !getid3_lib::intValueSupported($nextoffset)) {
                             $info['warning'][] = 'Unable to parse chunk at offset ' . $nextoffset . ' because beyond ' . round(PHP_INT_MAX / 1073741824) . 'GB limit of PHP filesystem functions';
                             break 3;
                         }
                         fseek($this->getid3->fp, $RIFFchunk[$chunkname][$thisindex]['offset'] + 8 + $chunksize, SEEK_SET);
                         break;
                     case 'iXML':
                     case 'bext':
                     case 'cart':
                     case 'fmt ':
                     case 'strh':
                     case 'strf':
                     case 'indx':
                     case 'MEXT':
                     case 'DISP':
                         // always read data in
                     // always read data in
                     case 'JUNK':
                         // should be: never read data in
                         // but some programs write their version strings in a JUNK chunk (e.g. VirtualDub, AVIdemux, etc)
                         if ($chunksize < 1048576) {
                             if ($chunksize > 0) {
                                 $RIFFchunk[$chunkname][$thisindex]['data'] = fread($this->getid3->fp, $chunksize);
                                 if ($chunkname == 'JUNK') {
                                     if (preg_match('#^([\\x20-\\x7F]+)#', $RIFFchunk[$chunkname][$thisindex]['data'], $matches)) {
                                         // only keep text characters [chr(32)-chr(127)]
                                         $info['riff']['comments']['junk'][] = trim($matches[1]);
                                     }
                                     // but if nothing there, ignore
                                     // remove the key in either case
                                     unset($RIFFchunk[$chunkname][$thisindex]['data']);
                                 }
                             }
                         } else {
                             $info['warning'][] = 'chunk "' . $chunkname . '" at offset ' . ftell($this->getid3->fp) . ' is unexpectedly larger than 1MB (claims to be ' . number_format($chunksize) . ' bytes), skipping data';
                             $nextoffset = ftell($this->getid3->fp) + $chunksize;
                             if ($nextoffset < 0 || !getid3_lib::intValueSupported($nextoffset)) {
                                 $info['warning'][] = 'Unable to parse chunk at offset ' . $nextoffset . ' because beyond ' . round(PHP_INT_MAX / 1073741824) . 'GB limit of PHP filesystem functions';
                                 break 3;
                             }
                             fseek($this->getid3->fp, $nextoffset, SEEK_SET);
                         }
                         break;
                     default:
                         if (!preg_match('#^[0-9]{2}(wb|pc|dc|db)$#', $chunkname) && !empty($LISTchunkParent) && $RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size'] <= $LISTchunkMaxOffset) {
                             $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
                             $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size'] = $RIFFchunk[$chunkname][$thisindex]['size'];
                             unset($RIFFchunk[$chunkname][$thisindex]['offset']);
                             unset($RIFFchunk[$chunkname][$thisindex]['size']);
                             if (isset($RIFFchunk[$chunkname][$thisindex]) && empty($RIFFchunk[$chunkname][$thisindex])) {
                                 unset($RIFFchunk[$chunkname][$thisindex]);
                             }
                             if (isset($RIFFchunk[$chunkname]) && empty($RIFFchunk[$chunkname])) {
                                 unset($RIFFchunk[$chunkname]);
                             }
                             $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['data'] = fread($this->getid3->fp, $chunksize);
                             //} elseif (in_array($chunkname, array('ID3 ')) || (($chunksize > 0) && ($chunksize < 2048))) {
                         } elseif ($chunksize > 0 && $chunksize < 2048) {
                             // only read data in if smaller than 2kB
                             $RIFFchunk[$chunkname][$thisindex]['data'] = fread($this->getid3->fp, $chunksize);
                         } else {
                             $nextoffset = ftell($this->getid3->fp) + $chunksize;
                             if ($nextoffset < 0 || !getid3_lib::intValueSupported($nextoffset)) {
                                 $info['warning'][] = 'Unable to parse chunk at offset ' . $nextoffset . ' because beyond ' . round(PHP_INT_MAX / 1073741824) . 'GB limit of PHP filesystem functions';
                                 break 3;
                             }
                             fseek($this->getid3->fp, $nextoffset, SEEK_SET);
                         }
                         break;
                 }
                 break;
         }
     }
     return $RIFFchunk;
 }
 static function ParseRIFF(&$fd, $startoffset, $maxoffset, &$ThisFileInfo)
 {
     $maxoffset = min($maxoffset, $ThisFileInfo['avdataend']);
     $RIFFchunk = false;
     $FoundAllChunksWeNeed = false;
     if ($startoffset < 0 || !getid3_lib::intValueSupported($startoffset)) {
         $ThisFileInfo['warning'][] = 'Unable to ParseRIFF() at ' . $startoffset . ' because beyond ' . round(PHP_INT_MAX / 1073741824) . 'GB limit of PHP filesystem functions';
         return false;
     }
     $max_usable_offset = min(PHP_INT_MAX - 1024, $maxoffset);
     if ($maxoffset > $max_usable_offset) {
         $ThisFileInfo['warning'][] = 'ParseRIFF() may return incomplete data for chunk starting at ' . $startoffset . ' because beyond it extends to ' . $maxoffset . ', which is beyond the ' . round(PHP_INT_MAX / 1073741824) . 'GB limit of PHP filesystem functions';
     }
     fseek($fd, $startoffset, SEEK_SET);
     while (ftell($fd) < $max_usable_offset) {
         $chunknamesize = fread($fd, 8);
         $chunkname = substr($chunknamesize, 0, 4);
         $chunksize = getid3_riff::EitherEndian2Int($ThisFileInfo, substr($chunknamesize, 4, 4));
         if (strlen($chunkname) < 4) {
             $ThisFileInfo['error'][] = 'Expecting chunk name at offset ' . (ftell($fd) - 4) . ' but found nothing. Aborting RIFF parsing.';
             break;
         }
         if ($chunksize == 0) {
             if ($chunkname == 'JUNK') {
                 // we'll allow zero-size JUNK frames
             } else {
                 $ThisFileInfo['warning'][] = 'Chunk size at offset ' . (ftell($fd) - 4) . ' is zero. Aborting RIFF parsing.';
                 break;
             }
         }
         if ($chunksize % 2 != 0) {
             // all structures are packed on word boundaries
             $chunksize++;
         }
         switch ($chunkname) {
             case 'LIST':
                 $listname = fread($fd, 4);
                 if (preg_match('#^(movi|rec )$#i', $listname)) {
                     $RIFFchunk[$listname]['offset'] = ftell($fd) - 4;
                     $RIFFchunk[$listname]['size'] = $chunksize;
                     if ($FoundAllChunksWeNeed) {
                         // skip over
                     } else {
                         $WhereWeWere = ftell($fd);
                         $AudioChunkHeader = fread($fd, 12);
                         $AudioChunkStreamNum = substr($AudioChunkHeader, 0, 2);
                         $AudioChunkStreamType = substr($AudioChunkHeader, 2, 2);
                         $AudioChunkSize = getid3_lib::LittleEndian2Int(substr($AudioChunkHeader, 4, 4));
                         if ($AudioChunkStreamType == 'wb') {
                             $FirstFourBytes = substr($AudioChunkHeader, 8, 4);
                             if (preg_match('/^\\xFF[\\xE2-\\xE7\\xF2-\\xF7\\xFA-\\xFF][\\x00-\\xEB]/s', $FirstFourBytes)) {
                                 // MP3
                                 if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) {
                                     $dummy = $ThisFileInfo;
                                     $dummy['avdataoffset'] = ftell($fd) - 4;
                                     $dummy['avdataend'] = ftell($fd) + $AudioChunkSize;
                                     getid3_mp3::getOnlyMPEGaudioInfo($fd, $dummy, $dummy['avdataoffset'], false);
                                     if (isset($dummy['mpeg']['audio'])) {
                                         $ThisFileInfo = $dummy;
                                         $ThisFileInfo['audio']['dataformat'] = 'mp' . $ThisFileInfo['mpeg']['audio']['layer'];
                                         $ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['mpeg']['audio']['sample_rate'];
                                         $ThisFileInfo['audio']['channels'] = $ThisFileInfo['mpeg']['audio']['channels'];
                                         $ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['mpeg']['audio']['bitrate'];
                                         $ThisFileInfo['bitrate'] = $ThisFileInfo['audio']['bitrate'];
                                         $ThisFileInfo['audio']['bitrate_mode'] = strtolower($ThisFileInfo['mpeg']['audio']['bitrate_mode']);
                                     }
                                     unset($dummy);
                                 }
                             } elseif (preg_match('/^\\x0B\\x77/s', $FirstFourBytes)) {
                                 // AC3
                                 $GETID3_ERRORARRAY =& $ThisFileInfo['warning'];
                                 if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.ac3.php', __FILE__, false)) {
                                     $dummy = $ThisFileInfo;
                                     $dummy['avdataoffset'] = ftell($fd) - 4;
                                     $dummy['avdataend'] = ftell($fd) + $AudioChunkSize;
                                     $dummy['error'] = array();
                                     $ac3_tag = new getid3_ac3($fd, $dummy);
                                     if (empty($dummy['error'])) {
                                         $ThisFileInfo['audio'] = $dummy['audio'];
                                         $ThisFileInfo['ac3'] = $dummy['ac3'];
                                         $ThisFileInfo['warning'] = $dummy['warning'];
                                     }
                                     unset($ac3_tag);
                                 }
                             }
                         }
                         $FoundAllChunksWeNeed = true;
                         fseek($fd, $WhereWeWere, SEEK_SET);
                     }
                     fseek($fd, $chunksize - 4, SEEK_CUR);
                     //} elseif (preg_match('#^[0-9]{2}(wb|pc|dc|db)$#i', $listname)) {
                     //
                     //	// data chunk, ignore
                     //
                 } else {
                     if (!isset($RIFFchunk[$listname])) {
                         $RIFFchunk[$listname] = array();
                     }
                     $LISTchunkParent = $listname;
                     $LISTchunkMaxOffset = ftell($fd) - 4 + $chunksize;
                     if ($parsedChunk = getid3_riff::ParseRIFF($fd, ftell($fd), ftell($fd) + $chunksize - 4, $ThisFileInfo)) {
                         $RIFFchunk[$listname] = array_merge_recursive($RIFFchunk[$listname], $parsedChunk);
                     }
                 }
                 break;
             default:
                 if (preg_match('#^[0-9]{2}(wb|pc|dc|db)$#', $chunkname)) {
                     $nextoffset = ftell($fd) + $chunksize;
                     if ($nextoffset < 0 || !getid3_lib::intValueSupported($nextoffset)) {
                         $ThisFileInfo['warning'][] = 'Unable to parse chunk at offset ' . $nextoffset . ' because beyond ' . round(PHP_INT_MAX / 1073741824) . 'GB limit of PHP filesystem functions';
                         break 2;
                     }
                     fseek($fd, $nextoffset, SEEK_SET);
                     break;
                 }
                 $thisindex = 0;
                 if (isset($RIFFchunk[$chunkname]) && is_array($RIFFchunk[$chunkname])) {
                     $thisindex = count($RIFFchunk[$chunkname]);
                 }
                 $RIFFchunk[$chunkname][$thisindex]['offset'] = ftell($fd) - 8;
                 $RIFFchunk[$chunkname][$thisindex]['size'] = $chunksize;
                 switch ($chunkname) {
                     case 'data':
                         $ThisFileInfo['avdataoffset'] = ftell($fd);
                         $ThisFileInfo['avdataend'] = $ThisFileInfo['avdataoffset'] + $chunksize;
                         $RIFFdataChunkContentsTest = fread($fd, 36);
                         if (strlen($RIFFdataChunkContentsTest) > 0 && preg_match('/^\\xFF[\\xE2-\\xE7\\xF2-\\xF7\\xFA-\\xFF][\\x00-\\xEB]/s', substr($RIFFdataChunkContentsTest, 0, 4))) {
                             // Probably is MP3 data
                             if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($RIFFdataChunkContentsTest, 0, 4))) {
                                 $dummy = $ThisFileInfo;
                                 // copy info array, only use if there's no error
                                 $getid3_mp3 = new getid3_mp3($fd, $dummy);
                                 $dummy = $ThisFileInfo;
                                 // copy info array, only use if there's no error
                                 $getid3_mp3->getOnlyMPEGaudioInfo($fd, $dummy, $RIFFchunk[$chunkname][$thisindex]['offset'], false);
                                 // use dummy array unless error
                                 if (empty($dummy['error'])) {
                                     $ThisFileInfo = $dummy;
                                 }
                             }
                         } elseif (strlen($RIFFdataChunkContentsTest) > 0 && substr($RIFFdataChunkContentsTest, 0, 2) == "\vw") {
                             // This is probably AC-3 data
                             $GETID3_ERRORARRAY =& $ThisFileInfo['warning'];
                             if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.ac3.php', __FILE__, false)) {
                                 $dummy = $ThisFileInfo;
                                 $dummy['avdataoffset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
                                 $dummy['avdataend'] = $dummy['avdataoffset'] + $RIFFchunk[$chunkname][$thisindex]['size'];
                                 $dummy['error'] = array();
                                 $ac3_tag = new getid3_ac3($fd, $dummy);
                                 if (empty($dummy['error'])) {
                                     $ThisFileInfo['audio'] = $dummy['audio'];
                                     $ThisFileInfo['ac3'] = $dummy['ac3'];
                                     $ThisFileInfo['warning'] = $dummy['warning'];
                                 }
                                 unset($ac3_tag);
                             }
                         } elseif (strlen($RIFFdataChunkContentsTest) > 0 && substr($RIFFdataChunkContentsTest, 8, 2) == "w\v") {
                             // Dolby Digital WAV
                             // AC-3 content, but not encoded in same format as normal AC-3 file
                             // For one thing, byte order is swapped
                             $GETID3_ERRORARRAY =& $ThisFileInfo['warning'];
                             if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.ac3.php', __FILE__, false)) {
                                 // ok to use tmpfile here - only 56 bytes
                                 if ($fd_temp = tmpfile()) {
                                     for ($i = 0; $i < 28; $i += 2) {
                                         // swap byte order
                                         fwrite($fd_temp, substr($RIFFdataChunkContentsTest, 8 + $i + 1, 1));
                                         fwrite($fd_temp, substr($RIFFdataChunkContentsTest, 8 + $i + 0, 1));
                                     }
                                     $dummy = $ThisFileInfo;
                                     $dummy['avdataoffset'] = 0;
                                     $dummy['avdataend'] = 20;
                                     $dummy['error'] = array();
                                     $ac3_tag = new getid3_ac3($fd_temp, $dummy);
                                     fclose($fd_temp);
                                     if (empty($dummy['error'])) {
                                         $ThisFileInfo['audio'] = $dummy['audio'];
                                         $ThisFileInfo['ac3'] = $dummy['ac3'];
                                         $ThisFileInfo['warning'] = $dummy['warning'];
                                     } else {
                                         $ThisFileInfo['error'][] = 'Errors parsing DolbyDigital WAV: ' . explode(';', $dummy['error']);
                                     }
                                     unset($ac3_tag);
                                 } else {
                                     $ThisFileInfo['error'][] = 'Could not create temporary file to analyze DolbyDigital WAV';
                                 }
                             }
                         } elseif (strlen($RIFFdataChunkContentsTest) > 0 && substr($RIFFdataChunkContentsTest, 0, 4) == 'wvpk') {
                             // This is WavPack data
                             $ThisFileInfo['wavpack']['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
                             $ThisFileInfo['wavpack']['size'] = getid3_lib::LittleEndian2Int(substr($RIFFdataChunkContentsTest, 4, 4));
                             getid3_riff::RIFFparseWavPackHeader(substr($RIFFdataChunkContentsTest, 8, 28), $ThisFileInfo);
                         } else {
                             // This is some other kind of data (quite possibly just PCM)
                             // do nothing special, just skip it
                         }
                         $nextoffset = $RIFFchunk[$chunkname][$thisindex]['offset'] + 8 + $chunksize;
                         if ($nextoffset < 0 || !getid3_lib::intValueSupported($nextoffset)) {
                             $ThisFileInfo['warning'][] = 'Unable to parse chunk at offset ' . $nextoffset . ' because beyond ' . round(PHP_INT_MAX / 1073741824) . 'GB limit of PHP filesystem functions';
                             break 3;
                         }
                         fseek($fd, $RIFFchunk[$chunkname][$thisindex]['offset'] + 8 + $chunksize, SEEK_SET);
                         break;
                     case 'bext':
                     case 'cart':
                     case 'fmt ':
                     case 'strh':
                     case 'strf':
                     case 'indx':
                     case 'MEXT':
                     case 'DISP':
                         // always read data in
                         $RIFFchunk[$chunkname][$thisindex]['data'] = fread($fd, $chunksize);
                         break;
                     case 'JUNK':
                         // never read data in
                         $nextoffset = ftell($fd) + $chunksize;
                         if ($nextoffset < 0 || !getid3_lib::intValueSupported($nextoffset)) {
                             $ThisFileInfo['warning'][] = 'Unable to parse chunk at offset ' . $nextoffset . ' because beyond ' . round(PHP_INT_MAX / 1073741824) . 'GB limit of PHP filesystem functions';
                             break 3;
                         }
                         fseek($fd, $nextoffset, SEEK_SET);
                         break;
                     default:
                         if (!preg_match('#^[0-9]{2}(wb|pc|dc|db)$#', $chunkname) && !empty($LISTchunkParent) && $RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size'] <= $LISTchunkMaxOffset) {
                             $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
                             $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size'] = $RIFFchunk[$chunkname][$thisindex]['size'];
                             unset($RIFFchunk[$chunkname][$thisindex]['offset']);
                             unset($RIFFchunk[$chunkname][$thisindex]['size']);
                             if (isset($RIFFchunk[$chunkname][$thisindex]) && empty($RIFFchunk[$chunkname][$thisindex])) {
                                 unset($RIFFchunk[$chunkname][$thisindex]);
                             }
                             if (isset($RIFFchunk[$chunkname]) && empty($RIFFchunk[$chunkname])) {
                                 unset($RIFFchunk[$chunkname]);
                             }
                             $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['data'] = fread($fd, $chunksize);
                         } elseif ($chunksize > 0 && $chunksize < 2048) {
                             // only read data in if smaller than 2kB
                             $RIFFchunk[$chunkname][$thisindex]['data'] = fread($fd, $chunksize);
                         } else {
                             $nextoffset = ftell($fd) + $chunksize;
                             if ($nextoffset < 0 || !getid3_lib::intValueSupported($nextoffset)) {
                                 $ThisFileInfo['warning'][] = 'Unable to parse chunk at offset ' . $nextoffset . ' because beyond ' . round(PHP_INT_MAX / 1073741824) . 'GB limit of PHP filesystem functions';
                                 break 3;
                             }
                             fseek($fd, $nextoffset, SEEK_SET);
                         }
                         break;
                 }
                 break;
         }
     }
     return $RIFFchunk;
 }
 public function ParseRIFF($startoffset, $maxoffset)
 {
     $info =& $this->getid3->info;
     $RIFFchunk = false;
     $FoundAllChunksWeNeed = false;
     try {
         $this->fseek($startoffset);
         $maxoffset = min($maxoffset, $info['avdataend']);
         while ($this->ftell() < $maxoffset) {
             $chunknamesize = $this->fread(8);
             $chunkname = substr($chunknamesize, 0, 4);
             $chunksize = $this->EitherEndian2Int(substr($chunknamesize, 4, 4));
             if (strlen(trim($chunkname, "")) < 4) {
                 $this->error('Expecting chunk name at offset ' . ($this->ftell() - 8) . ' but found nothing. Aborting RIFF parsing.');
                 break;
             }
             if ($chunksize == 0 && $chunkname != 'JUNK') {
                 $this->warning('Chunk (' . $chunkname . ') size at offset ' . ($this->ftell() - 4) . ' is zero. Aborting RIFF parsing.');
                 break;
             }
             if ($chunksize % 2 != 0) {
                 // all structures are packed on word boundaries
                 $chunksize++;
             }
             switch ($chunkname) {
                 case 'LIST':
                     $listname = $this->fread(4);
                     if (preg_match('#^(movi|rec )$#i', $listname)) {
                         $RIFFchunk[$listname]['offset'] = $this->ftell() - 4;
                         $RIFFchunk[$listname]['size'] = $chunksize;
                         if (!$FoundAllChunksWeNeed) {
                             $WhereWeWere = $this->ftell();
                             $AudioChunkHeader = $this->fread(12);
                             $AudioChunkStreamNum = substr($AudioChunkHeader, 0, 2);
                             $AudioChunkStreamType = substr($AudioChunkHeader, 2, 2);
                             $AudioChunkSize = getid3_lib::LittleEndian2Int(substr($AudioChunkHeader, 4, 4));
                             if ($AudioChunkStreamType == 'wb') {
                                 $FirstFourBytes = substr($AudioChunkHeader, 8, 4);
                                 if (preg_match('/^\\xFF[\\xE2-\\xE7\\xF2-\\xF7\\xFA-\\xFF][\\x00-\\xEB]/s', $FirstFourBytes)) {
                                     // MP3
                                     if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) {
                                         $getid3_temp = new getID3();
                                         $getid3_temp->openfile($this->getid3->filename);
                                         $getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
                                         $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize;
                                         $getid3_mp3 = new getid3_mp3($getid3_temp);
                                         $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false);
                                         if (isset($getid3_temp->info['mpeg']['audio'])) {
                                             $info['mpeg']['audio'] = $getid3_temp->info['mpeg']['audio'];
                                             $info['audio'] = $getid3_temp->info['audio'];
                                             $info['audio']['dataformat'] = 'mp' . $info['mpeg']['audio']['layer'];
                                             $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate'];
                                             $info['audio']['channels'] = $info['mpeg']['audio']['channels'];
                                             $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate'];
                                             $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
                                             //$info['bitrate']               = $info['audio']['bitrate'];
                                         }
                                         unset($getid3_temp, $getid3_mp3);
                                     }
                                 } elseif (strpos($FirstFourBytes, getid3_ac3::syncword) === 0) {
                                     // AC3
                                     $getid3_temp = new getID3();
                                     $getid3_temp->openfile($this->getid3->filename);
                                     $getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
                                     $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize;
                                     $getid3_ac3 = new getid3_ac3($getid3_temp);
                                     $getid3_ac3->Analyze();
                                     if (empty($getid3_temp->info['error'])) {
                                         $info['audio'] = $getid3_temp->info['audio'];
                                         $info['ac3'] = $getid3_temp->info['ac3'];
                                         if (!empty($getid3_temp->info['warning'])) {
                                             foreach ($getid3_temp->info['warning'] as $key => $value) {
                                                 $info['warning'][] = $value;
                                             }
                                         }
                                     }
                                     unset($getid3_temp, $getid3_ac3);
                                 }
                             }
                             $FoundAllChunksWeNeed = true;
                             $this->fseek($WhereWeWere);
                         }
                         $this->fseek($chunksize - 4, SEEK_CUR);
                     } else {
                         if (!isset($RIFFchunk[$listname])) {
                             $RIFFchunk[$listname] = array();
                         }
                         $LISTchunkParent = $listname;
                         $LISTchunkMaxOffset = $this->ftell() - 4 + $chunksize;
                         if ($parsedChunk = $this->ParseRIFF($this->ftell(), $LISTchunkMaxOffset)) {
                             $RIFFchunk[$listname] = array_merge_recursive($RIFFchunk[$listname], $parsedChunk);
                         }
                     }
                     break;
                 default:
                     if (preg_match('#^[0-9]{2}(wb|pc|dc|db)$#', $chunkname)) {
                         $this->fseek($chunksize, SEEK_CUR);
                         break;
                     }
                     $thisindex = 0;
                     if (isset($RIFFchunk[$chunkname]) && is_array($RIFFchunk[$chunkname])) {
                         $thisindex = count($RIFFchunk[$chunkname]);
                     }
                     $RIFFchunk[$chunkname][$thisindex]['offset'] = $this->ftell() - 8;
                     $RIFFchunk[$chunkname][$thisindex]['size'] = $chunksize;
                     switch ($chunkname) {
                         case 'data':
                             $info['avdataoffset'] = $this->ftell();
                             $info['avdataend'] = $info['avdataoffset'] + $chunksize;
                             $RIFFdataChunkContentsTest = $this->fread(36);
                             if (strlen($RIFFdataChunkContentsTest) > 0 && preg_match('/^\\xFF[\\xE2-\\xE7\\xF2-\\xF7\\xFA-\\xFF][\\x00-\\xEB]/s', substr($RIFFdataChunkContentsTest, 0, 4))) {
                                 // Probably is MP3 data
                                 if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($RIFFdataChunkContentsTest, 0, 4))) {
                                     $getid3_temp = new getID3();
                                     $getid3_temp->openfile($this->getid3->filename);
                                     $getid3_temp->info['avdataoffset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
                                     $getid3_temp->info['avdataend'] = $RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size'];
                                     $getid3_mp3 = new getid3_mp3($getid3_temp);
                                     $getid3_mp3->getOnlyMPEGaudioInfo($RIFFchunk[$chunkname][$thisindex]['offset'], false);
                                     if (empty($getid3_temp->info['error'])) {
                                         $info['mpeg'] = $getid3_temp->info['mpeg'];
                                         $info['audio'] = $getid3_temp->info['audio'];
                                     }
                                     unset($getid3_temp, $getid3_mp3);
                                 }
                             } elseif (strlen($RIFFdataChunkContentsTest) > 0 && substr($RIFFdataChunkContentsTest, 0, 2) == getid3_ac3::syncword) {
                                 // This is probably AC-3 data
                                 $getid3_temp = new getID3();
                                 $getid3_temp->openfile($this->getid3->filename);
                                 $getid3_temp->info['avdataoffset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
                                 $getid3_temp->info['avdataend'] = $RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size'];
                                 $getid3_ac3 = new getid3_ac3($getid3_temp);
                                 $getid3_ac3->Analyze();
                                 if (empty($getid3_temp->info['error'])) {
                                     $info['audio'] = $getid3_temp->info['audio'];
                                     $info['ac3'] = $getid3_temp->info['ac3'];
                                     $info['warning'] = $getid3_temp->info['warning'];
                                 }
                                 unset($getid3_temp, $getid3_ac3);
                             } elseif (strlen($RIFFdataChunkContentsTest) > 0 && substr($RIFFdataChunkContentsTest, 8, 2) == getid3_ac3::syncword) {
                                 // Dolby Digital WAV
                                 // AC-3 content, but not encoded in same format as normal AC-3 file
                                 // For one thing, byte order is swapped
                                 if ($RIFFtempfilename = tempnam(GETID3_TEMP_DIR, 'id3')) {
                                     // ok to use tmpfile here - only 56 bytes
                                     if ($fd_temp = fopen($RIFFtempfilename, 'wb')) {
                                         for ($i = 0; $i < 28; $i += 2) {
                                             // swap byte order
                                             fwrite($fd_temp, substr($RIFFdataChunkContentsTest, 8 + $i + 1, 1));
                                             fwrite($fd_temp, substr($RIFFdataChunkContentsTest, 8 + $i + 0, 1));
                                         }
                                         fclose($fd_temp);
                                         $getid3_temp = new getID3();
                                         $getid3_temp->openfile($RIFFtempfilename);
                                         $getid3_temp->info['avdataend'] = 20;
                                         $getid3_ac3 = new getid3_ac3($getid3_temp);
                                         $getid3_ac3->Analyze();
                                         if (empty($getid3_temp->info['error'])) {
                                             $info['audio'] = $getid3_temp->info['audio'];
                                             $info['ac3'] = $getid3_temp->info['ac3'];
                                             $info['warning'] = $getid3_temp->info['warning'];
                                         } else {
                                             $info['error'][] = 'Error parsing Dolby Digital WAV (AC3-in-RIFF): ' . implode(';', $getid3_temp->info['error']);
                                         }
                                         unset($getid3_ac3, $getid3_temp);
                                     } else {
                                         $info['error'][] = 'Error parsing Dolby Digital WAV (AC3-in-RIFF): failed to write temp file';
                                     }
                                     unlink($RIFFtempfilename);
                                 } else {
                                     $info['error'][] = 'Error parsing Dolby Digital WAV (AC3-in-RIFF): failed to write temp file';
                                 }
                             } elseif (strlen($RIFFdataChunkContentsTest) > 0 && substr($RIFFdataChunkContentsTest, 0, 4) == 'wvpk') {
                                 // This is WavPack data
                                 $info['wavpack']['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
                                 $info['wavpack']['size'] = getid3_lib::LittleEndian2Int(substr($RIFFdataChunkContentsTest, 4, 4));
                                 self::parseWavPackHeader(substr($RIFFdataChunkContentsTest, 8, 28));
                             } else {
                                 // This is some other kind of data (quite possibly just PCM)
                                 // do nothing special, just skip it
                             }
                             $nextoffset = $RIFFchunk[$chunkname][$thisindex]['offset'] + 8 + $chunksize;
                             $this->fseek($nextoffset);
                             break;
                         case 'iXML':
                         case 'bext':
                         case 'cart':
                         case 'fmt ':
                         case 'strh':
                         case 'strf':
                         case 'indx':
                         case 'MEXT':
                         case 'DISP':
                             // always read data in
                         // always read data in
                         case 'JUNK':
                             // should be: never read data in
                             // but some programs write their version strings in a JUNK chunk (e.g. VirtualDub, AVIdemux, etc)
                             if ($chunksize < 1048576) {
                                 if ($chunksize > 0) {
                                     $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize);
                                     if ($chunkname == 'JUNK') {
                                         if (preg_match('#^([\\x20-\\x7F]+)#', $RIFFchunk[$chunkname][$thisindex]['data'], $matches)) {
                                             // only keep text characters [chr(32)-chr(127)]
                                             $info['riff']['comments']['junk'][] = trim($matches[1]);
                                         }
                                         // but if nothing there, ignore
                                         // remove the key in either case
                                         unset($RIFFchunk[$chunkname][$thisindex]['data']);
                                     }
                                 }
                             } else {
                                 $this->warning('Chunk "' . $chunkname . '" at offset ' . $this->ftell() . ' is unexpectedly larger than 1MB (claims to be ' . number_format($chunksize) . ' bytes), skipping data');
                                 $this->fseek($chunksize, SEEK_CUR);
                             }
                             break;
                             //case 'IDVX':
                             //	$info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunksize));
                             //	break;
                         //case 'IDVX':
                         //	$info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunksize));
                         //	break;
                         default:
                             if (!empty($LISTchunkParent) && $RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size'] <= $LISTchunkMaxOffset) {
                                 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
                                 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size'] = $RIFFchunk[$chunkname][$thisindex]['size'];
                                 unset($RIFFchunk[$chunkname][$thisindex]['offset']);
                                 unset($RIFFchunk[$chunkname][$thisindex]['size']);
                                 if (isset($RIFFchunk[$chunkname][$thisindex]) && empty($RIFFchunk[$chunkname][$thisindex])) {
                                     unset($RIFFchunk[$chunkname][$thisindex]);
                                 }
                                 if (isset($RIFFchunk[$chunkname]) && empty($RIFFchunk[$chunkname])) {
                                     unset($RIFFchunk[$chunkname]);
                                 }
                                 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['data'] = $this->fread($chunksize);
                             } elseif ($chunksize < 2048) {
                                 // only read data in if smaller than 2kB
                                 $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize);
                             } else {
                                 $this->fseek($chunksize, SEEK_CUR);
                             }
                             break;
                     }
                     break;
             }
         }
     } catch (getid3_exception $e) {
         if ($e->getCode() == 10) {
             $this->warning('RIFF parser: ' . $e->getMessage());
         } else {
             throw $e;
         }
     }
     return $RIFFchunk;
 }