function getMP3headerFilepointer(&$fd, &$ThisFileInfo) { getOnlyMPEGaudioInfo($fd, $ThisFileInfo, $ThisFileInfo['avdataoffset']); if (isset($ThisFileInfo['mpeg']['audio']['bitratemode'])) { $ThisFileInfo['audio']['bitrate_mode'] = strtolower($ThisFileInfo['mpeg']['audio']['bitratemode']); } if (isset($ThisFileInfo['id3v2']) && $ThisFileInfo['avdataoffset'] > $ThisFileInfo['id3v2']['headerlength'] || !isset($ThisFileInfo['id3v2']) && $ThisFileInfo['avdataoffset'] > 0) { $ThisFileInfo['warning'] .= "\n" . 'Unknown data before synch '; if (isset($ThisFileInfo['id3v2']['headerlength'])) { $ThisFileInfo['warning'] .= '(ID3v2 header ends at ' . $ThisFileInfo['id3v2']['headerlength'] . ', '; } else { $ThisFileInfo['warning'] .= '(should be at beginning of file, '; } $ThisFileInfo['warning'] .= 'synch detected at ' . $ThisFileInfo['avdataoffset'] . ')'; if ($ThisFileInfo['audio']['bitrate_mode'] == 'cbr' && $ThisFileInfo['avdataoffset'] == $ThisFileInfo['mpeg']['audio']['framelength']) { $ThisFileInfo['warning'] .= ' This is a known problem with some versions of LAME (3.91, 3.92) DLL in CBR mode.'; $ThisFileInfo['audio']['codec'] = 'LAME'; } } if (isset($ThisFileInfo['mpeg']['audio']['layer']) && $ThisFileInfo['mpeg']['audio']['layer'] == 'II') { $ThisFileInfo['fileformat'] = 'mp2'; $ThisFileInfo['audio']['dataformat'] = 'mp2'; } elseif (isset($ThisFileInfo['mpeg']['audio']['layer']) && $ThisFileInfo['mpeg']['audio']['layer'] == 'I') { $ThisFileInfo['fileformat'] = 'mp1'; $ThisFileInfo['audio']['dataformat'] = 'mp1'; } if (empty($ThisFileInfo['fileformat'])) { $ThisFileInfo['error'] .= "\n" . 'Synch not found'; unset($ThisFileInfo['fileformat']); unset($ThisFileInfo['audio']['bitrate_mode']); unset($ThisFileInfo['avdataoffset']); unset($ThisFileInfo['avdataend']); return false; } $ThisFileInfo['mime_type'] = 'audio/mpeg'; // Calculate playtime from audiobytes etc if (!isset($ThisFileInfo['playtime_seconds']) && isset($ThisFileInfo['audio']['bitrate']) && $ThisFileInfo['audio']['bitrate'] > 0) { $ThisFileInfo['playtime_seconds'] = ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8 / $ThisFileInfo['audio']['bitrate']; } if (isset($ThisFileInfo['mpeg']['audio']['LAME'])) { $ThisFileInfo['audio']['codec'] = 'LAME'; if (!empty($ThisFileInfo['mpeg']['audio']['LAME']['short_version'])) { $ThisFileInfo['audio']['encoder'] = trim($ThisFileInfo['mpeg']['audio']['LAME']['short_version']); } } return true; }
function getMP3headerFilepointer(&$fd, &$ThisFileInfo) { getOnlyMPEGaudioInfo($fd, $ThisFileInfo, $ThisFileInfo['avdataoffset']); if (isset($ThisFileInfo['mpeg']['audio']['bitrate_mode'])) { $ThisFileInfo['audio']['bitrate_mode'] = strtolower($ThisFileInfo['mpeg']['audio']['bitrate_mode']); } if (isset($ThisFileInfo['id3v2']) && $ThisFileInfo['avdataoffset'] > $ThisFileInfo['id3v2']['headerlength'] || !isset($ThisFileInfo['id3v2']) && $ThisFileInfo['avdataoffset'] > 0) { $ThisFileInfo['warning'] .= "\n" . 'Unknown data before synch '; if (isset($ThisFileInfo['id3v2']['headerlength'])) { $ThisFileInfo['warning'] .= '(ID3v2 header ends at ' . $ThisFileInfo['id3v2']['headerlength'] . ', then ' . ($ThisFileInfo['avdataoffset'] - $ThisFileInfo['id3v2']['headerlength']) . ' bytes garbage, '; } else { $ThisFileInfo['warning'] .= '(should be at beginning of file, '; } $ThisFileInfo['warning'] .= 'synch detected at ' . $ThisFileInfo['avdataoffset'] . ')'; if ($ThisFileInfo['audio']['bitrate_mode'] == 'cbr') { if (!empty($ThisFileInfo['id3v2']['headerlength']) && $ThisFileInfo['avdataoffset'] - $ThisFileInfo['id3v2']['headerlength'] == $ThisFileInfo['mpeg']['audio']['framelength']) { $ThisFileInfo['warning'] .= '. This is a known problem with some versions of LAME (3.91, 3.92) DLL in CBR mode.'; $ThisFileInfo['audio']['codec'] = 'LAME'; } elseif (empty($ThisFileInfo['id3v2']['headerlength']) && $ThisFileInfo['avdataoffset'] == $ThisFileInfo['mpeg']['audio']['framelength']) { $ThisFileInfo['warning'] .= '. This is a known problem with some versions of LAME (3.91, 3.92) DLL in CBR mode.'; $ThisFileInfo['audio']['codec'] = 'LAME'; } } } if (isset($ThisFileInfo['mpeg']['audio']['layer']) && $ThisFileInfo['mpeg']['audio']['layer'] == 'II') { $ThisFileInfo['audio']['dataformat'] = 'mp2'; } elseif (isset($ThisFileInfo['mpeg']['audio']['layer']) && $ThisFileInfo['mpeg']['audio']['layer'] == 'I') { $ThisFileInfo['audio']['dataformat'] = 'mp1'; } if ($ThisFileInfo['fileformat'] == 'mp3') { switch ($ThisFileInfo['audio']['dataformat']) { case 'mp1': case 'mp2': case 'mp3': $ThisFileInfo['fileformat'] = $ThisFileInfo['audio']['dataformat']; break; default: $ThisFileInfo['warning'] .= "\n" . 'Expecting [audio][dataformat] to be mp1/mp2/mp3 when fileformat == mp3, [audio][dataformat] actually "' . $ThisFileInfo['audio']['dataformat'] . '"'; break; } } if (empty($ThisFileInfo['fileformat'])) { $ThisFileInfo['error'] .= "\n" . 'Synch not found'; unset($ThisFileInfo['fileformat']); unset($ThisFileInfo['audio']['bitrate_mode']); unset($ThisFileInfo['avdataoffset']); unset($ThisFileInfo['avdataend']); return false; } $ThisFileInfo['mime_type'] = 'audio/mpeg'; $ThisFileInfo['audio']['lossless'] = false; // Calculate playtime if (!isset($ThisFileInfo['playtime_seconds']) && isset($ThisFileInfo['audio']['bitrate']) && $ThisFileInfo['audio']['bitrate'] > 0) { $ThisFileInfo['playtime_seconds'] = ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8 / $ThisFileInfo['audio']['bitrate']; } if (isset($ThisFileInfo['mpeg']['audio']['LAME'])) { $ThisFileInfo['audio']['codec'] = 'LAME'; if (!empty($ThisFileInfo['mpeg']['audio']['LAME']['long_version'])) { $ThisFileInfo['audio']['encoder'] = trim($ThisFileInfo['mpeg']['audio']['LAME']['long_version']); } } return true; }
function getQuicktimeHeaderFilepointer(&$fd, &$ThisFileInfo) { $ThisFileInfo['fileformat'] = 'quicktime'; $ThisFileInfo['audio']['dataformat'] = 'quicktime'; $ThisFileInfo['video']['dataformat'] = 'quicktime'; fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET); $offset = 0; $atomcounter = 0; while ($offset < $ThisFileInfo['avdataend']) { fseek($fd, $offset, SEEK_SET); $AtomHeader = fread($fd, 8); $atomsize = BigEndian2Int(substr($AtomHeader, 0, 4)); $atomname = substr($AtomHeader, 4, 4); $ThisFileInfo['quicktime']["{$atomname}"]['name'] = $atomname; $ThisFileInfo['quicktime']["{$atomname}"]['size'] = $atomsize; $ThisFileInfo['quicktime']["{$atomname}"]['offset'] = $offset; if ($offset + $atomsize > $ThisFileInfo['avdataend']) { $ThisFileInfo['error'] .= "\n" . 'Atom at offset ' . $offset . ' claims to go beyond end-of-file (length: ' . $atomsize . ' bytes)'; return false; } switch ($atomname) { case 'mdat': // Media DATa atom // 'mdat' contains the actual data for the audio/video if (!isset($ThisFileInfo['avdataend_tmp']) || $ThisFileInfo['quicktime']["{$atomname}"]['size'] > $ThisFileInfo['avdataend_tmp'] - $ThisFileInfo['avdataoffset']) { $ThisFileInfo['avdataoffset'] = $ThisFileInfo['quicktime']["{$atomname}"]['offset'] + 8; $OldAVDataEnd = $ThisFileInfo['avdataend']; $ThisFileInfo['avdataend'] = $ThisFileInfo['quicktime']["{$atomname}"]['offset'] + $ThisFileInfo['quicktime']["{$atomname}"]['size']; require_once GETID3_INCLUDEPATH . 'getid3.mp3.php'; if (MPEGaudioHeaderValid(MPEGaudioHeaderDecode(fread($fd, 4)))) { getOnlyMPEGaudioInfo($fd, $ThisFileInfo, $ThisFileInfo['avdataoffset'], false); if (isset($ThisFileInfo['mpeg']['audio'])) { $ThisFileInfo['audio']['dataformat'] = 'mp3'; $ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['mpeg']['audio']['sample_rate']; $ThisFileInfo['audio']['channels'] = $ThisFileInfo['mpeg']['audio']['channels']; $ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['mpeg']['audio']['bitrate'] * 1000; $ThisFileInfo['audio']['bitrate_mode'] = strtolower($ThisFileInfo['mpeg']['audio']['bitratemode']); $ThisFileInfo['bitrate'] = $ThisFileInfo['audio']['bitrate']; } } $ThisFileInfo['avdataend'] = $OldAVDataEnd; unset($OldAVDataEnd); } break; case 'free': // FREE space atom // FREE space atom case 'skip': // SKIP atom // SKIP atom case 'wide': // 64-bit expansion placeholder atom // 'free', 'skip' and 'wide' are just padding, contains no useful data at all break; default: $atomHierarchy = array(); $ThisFileInfo['quicktime']["{$atomname}"] = QuicktimeParseAtom($atomname, $atomsize, fread($fd, $atomsize), $ThisFileInfo, $offset, $atomHierarchy); break; } $offset += $atomsize; $atomcounter++; } if (!empty($ThisFileInfo['avdataend_tmp'])) { // this value is assigned to a temp value and then erased because // otherwise any atoms beyond the 'mdat' atom would not get parsed $ThisFileInfo['avdataend'] = $ThisFileInfo['avdataend_tmp']; unset($ThisFileInfo['avdataend_tmp']); } // Quicktime tags have highest priority if (isset($ThisFileInfo['quicktime']['comments'])) { CopyFormatCommentsToRootComments($ThisFileInfo['quicktime']['comments'], $ThisFileInfo, true, true, true); // add tag to array of tags $ThisFileInfo['tags'][] = 'quicktime'; } if (!isset($ThisFileInfo['bitrate']) && isset($ThisFileInfo['playtime_seconds'])) { $ThisFileInfo['bitrate'] = ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8 / $ThisFileInfo['playtime_seconds']; } if (isset($ThisFileInfo['bitrate']) && !isset($ThisFileInfo['audio']['bitrate']) && !isset($ThisFileInfo['quicktime']['video'])) { $ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['bitrate']; } return true; }
function getMP3headerFilepointer(&$fd, &$MP3fileInfo) { // get all information about an MP3 file - ID3v1, ID3v2, Lyrics3, MPEG-audio $MP3fileInfo['fileformat'] = ''; if (!$fd) { $MP3fileInfo['error'] .= "\n" . 'Could not open file'; return FALSE; } else { fseek($fd, -128 - 9 - 6, SEEK_END); $lyrics3_id3v1 = fread($fd, 128 + 9 + 6); $lyrics3lsz = substr($lyrics3_id3v1, 0, 6); $lyrics3end = substr($lyrics3_id3v1, 6, 9); // LYRICSEND or LYRICS200 $id3v1tag = substr($lyrics3_id3v1, 15, 128); if ($lyrics3end == 'LYRICSEND') { // Lyrics3 v1 and ID3v1 $lyrics3size = 5100; include_once GETID3_INCLUDEPATH . 'getid3.lyrics3.php'; getLyrics3Filepointer($MP3fileInfo, $fd, -128 - $lyrics3size, 1, $lyrics3size); } else { if ($lyrics3end == 'LYRICS200') { // Lyrics3 v2 and ID3v1 $lyrics3size = $lyrics3lsz + 6 + strlen('LYRICS200'); // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200' include_once GETID3_INCLUDEPATH . 'getid3.lyrics3.php'; getLyrics3Filepointer($MP3fileInfo, $fd, -128 - $lyrics3size, 2, $lyrics3size); } else { if (substr($lyrics3_id3v1, strlen($lyrics3_id3v1) - 1 - 9, 9) == 'LYRICSEND') { // Lyrics3 v1, no ID3v1 (I think according to Lyrics3 specs there MUST be ID3v1, but just in case :) $lyrics3size = 5100; include_once GETID3_INCLUDEPATH . 'getid3.lyrics3.php'; getLyrics3Filepointer($MP3fileInfo, $fd, 0 - $lyrics3size, 1, $lyrics3size); } else { if (substr($lyrics3_id3v1, strlen($lyrics3_id3v1) - 1 - 9, 9) == 'LYRICS200') { // Lyrics3 v2, no ID3v1 (I think according to Lyrics3 specs there MUST be ID3v1, but just in case :) $lyrics3size = $lyrics3lsz + 6 + strlen('LYRICS200'); // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200' include_once GETID3_INCLUDEPATH . 'getid3.lyrics3.php'; getLyrics3Filepointer($MP3fileInfo, $fd, 0 - $lyrics3size, 2, $lyrics3size); } } } } if (substr($id3v1tag, 0, 3) == 'TAG') { include_once GETID3_INCLUDEPATH . 'getid3.id3v1.php'; $MP3fileInfo['id3']['id3v1'] = getID3v1Filepointer($fd); $MP3fileInfo['fileformat'] = 'id3'; } include_once GETID3_INCLUDEPATH . 'getid3.id3v2.php'; getID3v2Filepointer($fd, $MP3fileInfo); if (isset($MP3fileInfo['id3']['id3v2']['header'])) { $MP3fileInfo['fileformat'] = 'id3'; $audiodataoffset = $MP3fileInfo['id3']['id3v2']['headerlength']; if (isset($MP3fileInfo['id3']['id3v2']['footer'])) { $audiodataoffset += 10; } } else { // no ID3v2 header if (isset($MP3fileInfo['id3']['id3v2'])) { unset($MP3fileInfo['id3']['id3v2']); } $audiodataoffset = 0; } if ($audiodataoffset < $MP3fileInfo['filesize']) { getOnlyMPEGaudioInfo($fd, $MP3fileInfo, $audiodataoffset); } if (isset($MP3fileInfo['audiodataoffset']) && (isset($MP3fileInfo['id3']['id3v2']) && $MP3fileInfo['audiodataoffset'] > $MP3fileInfo['id3']['id3v2']['headerlength'] || !isset($MP3fileInfo['id3']['id3v2']) && $MP3fileInfo['audiodataoffset'] > 0)) { $MP3fileInfo['error'] .= "\n" . 'Unknown data before synch '; if (isset($MP3fileInfo['id3']['id3v2']['headerlength'])) { $MP3fileInfo['error'] .= '(ID3v2 header ends at ' . $MP3fileInfo['id3']['id3v2']['headerlength'] . ', '; } else { $MP3fileInfo['error'] .= '(should be at beginning of file, '; } $MP3fileInfo['error'] .= 'synch detected at ' . $MP3fileInfo['audiodataoffset'] . ')'; } if (!$MP3fileInfo['fileformat']) { $MP3fileInfo['error'] .= "\n" . 'Synch not found'; unset($MP3fileInfo['audiodataoffset']); unset($MP3fileInfo['fileformat']); } } // if ($fd) if (isset($MP3fileInfo['id3']) && !isset($MP3fileInfo['id3']['id3v2']) && !isset($MP3fileInfo['id3']['id3v1'])) { unset($MP3fileInfo['id3']); } return TRUE; }
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); $chunksize = EitherEndian2Int($ThisFileInfo, fread($fd, 4)); 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 ': // skip over $RIFFchunk["{$listname}"]['offset'] = ftell($fd) - 4; $RIFFchunk["{$listname}"]['size'] = $chunksize; fseek($fd, $chunksize - 4, SEEK_CUR); break; default: if (!isset($RIFFchunk["{$listname}"])) { $RIFFchunk["{$listname}"] = array(); } $RIFFchunk["{$listname}"] = array_merge_recursive($RIFFchunk["{$listname}"], ParseRIFF($fd, ftell($fd), ftell($fd) + $chunksize - 4, $ThisFileInfo)); 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': $RIFFdataChunkContentsTest = fread($fd, 8); if (strlen($RIFFdataChunkContentsTest) > 0 && $RIFFdataChunkContentsTest[0] == chr(0xff)) { // Probably (but not guaranteed) that this is MP3 data require_once GETID3_INCLUDEPATH . 'getid3.mp3.php'; if (MPEGaudioHeaderBytesValid(substr($RIFFdataChunkContentsTest, 0, 4))) { $WhereWeWere = ftell($fd); getOnlyMPEGaudioInfo($fd, $ThisFileInfo, $RIFFchunk["{$chunkname}"][$thisindex]['offset'], false); fseek($fd, $WhereWeWere, SEEK_SET); if (isset($ThisFileInfo['mpeg']['audio'])) { $ThisFileInfo['audio']['dataformat'] = 'mp' . strlen($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'] * 1000; $ThisFileInfo['bitrate'] = $ThisFileInfo['audio']['bitrate']; $ThisFileInfo['audio']['bitrate_mode'] = strtolower($ThisFileInfo['mpeg']['audio']['bitrate_mode']); } fseek($fd, $chunksize - 8, SEEK_CUR); } } else { if (substr($RIFFdataChunkContentsTest, 0, 4) == 'wvpk') { // This is WavPack data $ThisFileInfo['wavpack']['offset'] = ftell($fd) - 8; $ThisFileInfo['wavpack']['size'] = LittleEndian2Int(substr($RIFFdataChunkContentsTest, 4, 4)); $WavPackData = fread($fd, $ThisFileInfo['wavpack']['size']); RIFFparseWavPackHeader($WavPackData, $ThisFileInfo); fseek($fd, $chunksize - 8 - $ThisFileInfo['wavpack']['size'], SEEK_CUR); } else { // This is some other kind of data (quite possibly just PCM) // do nothing special, just skip it fseek($fd, $chunksize - 8, SEEK_CUR); } } break; case 'bext': case 'cart': case 'fmt ': case 'MEXT': case 'DISP': // always read data in $RIFFchunk["{$chunkname}"][$thisindex]['data'] = fread($fd, $chunksize); break; default: // read data in if smaller than 2kB if ($chunksize < 2048) { $RIFFchunk["{$chunkname}"][$thisindex]['data'] = fread($fd, $chunksize); } else { fseek($fd, $chunksize, SEEK_CUR); } break; } break; } } return $RIFFchunk; }
function getRIFFHeaderFilepointer(&$fd, &$ThisFileInfo) { fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET); $RIFFheader = fread($fd, 12); switch (substr($RIFFheader, 0, 4)) { case 'RIFF': case 'SDSS': // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com) $ThisFileInfo['fileformat'] = 'riff'; $ThisFileInfo['RIFF'][substr($RIFFheader, 8, 4)] = ParseRIFF($fd, $ThisFileInfo['avdataoffset'] + 12, $ThisFileInfo['avdataoffset'] + LittleEndian2Int(substr($RIFFheader, 4, 4)), $ThisFileInfo); break; default: $ThisFileInfo['error'] .= "\n" . 'Cannot parse RIFF (this is maybe not a RIFF / WAV / AVI file?)'; unset($ThisFileInfo['fileformat']); return false; break; } $streamindex = 0; $arraykeys = array_keys($ThisFileInfo['RIFF']); switch ($arraykeys[0]) { case 'WAVE': $ThisFileInfo['audio']['bitrate_mode'] = 'cbr'; $ThisFileInfo['audio']['dataformat'] = 'wav'; if (isset($ThisFileInfo['RIFF']['WAVE']['fmt '][0]['data'])) { $ThisFileInfo['RIFF']['audio'][$streamindex] = RIFFparseWAVEFORMATex($ThisFileInfo['RIFF']['WAVE']['fmt '][0]['data']); if ($ThisFileInfo['RIFF']['audio'][$streamindex] == 0) { $ThisFileInfo['error'] .= 'Corrupt RIFF file: bitrate_audio == zero'; return false; } $ThisFileInfo['RIFF']['raw']['fmt '] = $ThisFileInfo['RIFF']['audio'][$streamindex]['raw']; unset($ThisFileInfo['RIFF']['audio'][$streamindex]['raw']); $ThisFileInfo['audio'] = array_merge_noclobber($ThisFileInfo['audio'], $ThisFileInfo['RIFF']['audio'][$streamindex]); $ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['RIFF']['audio'][$streamindex]['bitrate']; $ThisFileInfo['playtime_seconds'] = (double) (($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8 / $ThisFileInfo['audio']['bitrate']); if (isset($ThisFileInfo['RIFF']['WAVE']['data'][0]['offset']) && isset($ThisFileInfo['RIFF']['raw']['fmt ']['wFormatTag'])) { switch ($ThisFileInfo['RIFF']['raw']['fmt ']['wFormatTag']) { case 85: // LAME ACM require_once GETID3_INCLUDEPATH . 'getid3.mp3.php'; getOnlyMPEGaudioInfo($fd, $ThisFileInfo, $ThisFileInfo['RIFF']['WAVE']['data'][0]['offset'], false); $ThisFileInfo['audio']['dataformat'] = 'mp3'; if (isset($ThisFileInfo['mpeg']['audio'])) { $ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['mpeg']['audio']['sample_rate']; $ThisFileInfo['audio']['channels'] = $ThisFileInfo['mpeg']['audio']['channels']; $ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['mpeg']['audio']['bitrate'] * 1000; $ThisFileInfo['bitrate'] = $ThisFileInfo['audio']['bitrate']; $ThisFileInfo['audio']['bitrate_mode'] = strtolower($ThisFileInfo['mpeg']['audio']['bitratemode']); } break; default: // do nothing break; } } } if (isset($ThisFileInfo['RIFF']['WAVE']['rgad'][0]['data'])) { require_once GETID3_INCLUDEPATH . 'getid3.rgad.php'; $rgadData = $ThisFileInfo['RIFF']['WAVE']['rgad'][0]['data']; $ThisFileInfo['RIFF']['raw']['rgad']['fPeakAmplitude'] = LittleEndian2Float(substr($rgadData, 0, 4)); $ThisFileInfo['RIFF']['raw']['rgad']['nRadioRgAdjust'] = LittleEndian2Int(substr($rgadData, 4, 2)); $ThisFileInfo['RIFF']['raw']['rgad']['nAudiophileRgAdjust'] = LittleEndian2Int(substr($rgadData, 6, 2)); $nRadioRgAdjustBitstring = str_pad(Dec2Bin($ThisFileInfo['RIFF']['raw']['rgad']['nRadioRgAdjust']), 16, '0', STR_PAD_LEFT); $nAudiophileRgAdjustBitstring = str_pad(Dec2Bin($ThisFileInfo['RIFF']['raw']['rgad']['nAudiophileRgAdjust']), 16, '0', STR_PAD_LEFT); $ThisFileInfo['RIFF']['raw']['rgad']['radio']['name'] = Bin2Dec(substr($nRadioRgAdjustBitstring, 0, 3)); $ThisFileInfo['RIFF']['raw']['rgad']['radio']['originator'] = Bin2Dec(substr($nRadioRgAdjustBitstring, 3, 3)); $ThisFileInfo['RIFF']['raw']['rgad']['radio']['signbit'] = Bin2Dec(substr($nRadioRgAdjustBitstring, 6, 1)); $ThisFileInfo['RIFF']['raw']['rgad']['radio']['adjustment'] = Bin2Dec(substr($nRadioRgAdjustBitstring, 7, 9)); $ThisFileInfo['RIFF']['raw']['rgad']['audiophile']['name'] = Bin2Dec(substr($nAudiophileRgAdjustBitstring, 0, 3)); $ThisFileInfo['RIFF']['raw']['rgad']['audiophile']['originator'] = Bin2Dec(substr($nAudiophileRgAdjustBitstring, 3, 3)); $ThisFileInfo['RIFF']['raw']['rgad']['audiophile']['signbit'] = Bin2Dec(substr($nAudiophileRgAdjustBitstring, 6, 1)); $ThisFileInfo['RIFF']['raw']['rgad']['audiophile']['adjustment'] = Bin2Dec(substr($nAudiophileRgAdjustBitstring, 7, 9)); $ThisFileInfo['RIFF']['rgad']['peakamplitude'] = $ThisFileInfo['RIFF']['raw']['rgad']['fPeakAmplitude']; if ($ThisFileInfo['RIFF']['raw']['rgad']['radio']['name'] != 0 && $ThisFileInfo['RIFF']['raw']['rgad']['radio']['originator'] != 0) { $ThisFileInfo['RIFF']['rgad']['radio']['name'] = RGADnameLookup($ThisFileInfo['RIFF']['raw']['rgad']['radio']['name']); $ThisFileInfo['RIFF']['rgad']['radio']['originator'] = RGADoriginatorLookup($ThisFileInfo['RIFF']['raw']['rgad']['radio']['originator']); $ThisFileInfo['RIFF']['rgad']['radio']['adjustment'] = RGADadjustmentLookup($ThisFileInfo['RIFF']['raw']['rgad']['radio']['adjustment'], $ThisFileInfo['RIFF']['raw']['rgad']['radio']['signbit']); } if ($ThisFileInfo['RIFF']['raw']['rgad']['audiophile']['name'] != 0 && $ThisFileInfo['RIFF']['raw']['rgad']['audiophile']['originator'] != 0) { $ThisFileInfo['RIFF']['rgad']['audiophile']['name'] = RGADnameLookup($ThisFileInfo['RIFF']['raw']['rgad']['audiophile']['name']); $ThisFileInfo['RIFF']['rgad']['audiophile']['originator'] = RGADoriginatorLookup($ThisFileInfo['RIFF']['raw']['rgad']['audiophile']['originator']); $ThisFileInfo['RIFF']['rgad']['audiophile']['adjustment'] = RGADadjustmentLookup($ThisFileInfo['RIFF']['raw']['rgad']['audiophile']['adjustment'], $ThisFileInfo['RIFF']['raw']['rgad']['audiophile']['signbit']); } } if (isset($ThisFileInfo['RIFF']['WAVE']['fact'][0]['data'])) { $ThisFileInfo['RIFF']['raw']['fact']['NumberOfSamples'] = LittleEndian2Int(substr($ThisFileInfo['RIFF']['WAVE']['fact'][0]['data'], 0, 4)); if (isset($ThisFileInfo['RIFF']['raw']['fmt ']['nSamplesPerSec']) && $ThisFileInfo['RIFF']['raw']['fmt ']['nSamplesPerSec'] > 0) { $ThisFileInfo['playtime_seconds'] = (double) $ThisFileInfo['RIFF']['raw']['fact']['NumberOfSamples'] / $ThisFileInfo['RIFF']['raw']['fmt ']['nSamplesPerSec']; } if (isset($ThisFileInfo['RIFF']['raw']['fmt ']['nAvgBytesPerSec']) && $ThisFileInfo['RIFF']['raw']['fmt ']['nAvgBytesPerSec']) { $ThisFileInfo['audio']['bitrate'] = CastAsInt($ThisFileInfo['RIFF']['raw']['fmt ']['nAvgBytesPerSec'] * 8); } } if (!isset($ThisFileInfo['audio']['bitrate']) && isset($ThisFileInfo['RIFF']['audio'][$streamindex]['bitrate'])) { $ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['RIFF']['audio'][$streamindex]['bitrate']; $ThisFileInfo['playtime_seconds'] = (double) (($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8 / $ThisFileInfo['audio']['bitrate']); } break; case 'AVI ': $ThisFileInfo['video']['bitrate_mode'] = 'cbr'; $ThisFileInfo['video']['dataformat'] = 'avi'; $ThisFileInfo['mime_type'] = 'video/avi'; if (isset($ThisFileInfo['RIFF']['AVI ']['hdrl']['avih'][$streamindex]['data'])) { $avihData = $ThisFileInfo['RIFF']['AVI ']['hdrl']['avih'][$streamindex]['data']; $ThisFileInfo['RIFF']['raw']['avih']['dwMicroSecPerFrame'] = LittleEndian2Int(substr($avihData, 0, 4)); // frame display rate (or 0L) if ($ThisFileInfo['RIFF']['raw']['avih']['dwMicroSecPerFrame'] == 0) { $ThisFileInfo['error'] .= 'Corrupt RIFF file: avih.dwMicroSecPerFrame == zero'; return false; } $ThisFileInfo['RIFF']['raw']['avih']['dwMaxBytesPerSec'] = LittleEndian2Int(substr($avihData, 4, 4)); // max. transfer rate $ThisFileInfo['RIFF']['raw']['avih']['dwPaddingGranularity'] = LittleEndian2Int(substr($avihData, 8, 4)); // pad to multiples of this size; normally 2K. $ThisFileInfo['RIFF']['raw']['avih']['dwFlags'] = LittleEndian2Int(substr($avihData, 12, 4)); // the ever-present flags $ThisFileInfo['RIFF']['raw']['avih']['dwTotalFrames'] = LittleEndian2Int(substr($avihData, 16, 4)); // # frames in file $ThisFileInfo['RIFF']['raw']['avih']['dwInitialFrames'] = LittleEndian2Int(substr($avihData, 20, 4)); $ThisFileInfo['RIFF']['raw']['avih']['dwStreams'] = LittleEndian2Int(substr($avihData, 24, 4)); $ThisFileInfo['RIFF']['raw']['avih']['dwSuggestedBufferSize'] = LittleEndian2Int(substr($avihData, 28, 4)); $ThisFileInfo['RIFF']['raw']['avih']['dwWidth'] = LittleEndian2Int(substr($avihData, 32, 4)); $ThisFileInfo['RIFF']['raw']['avih']['dwHeight'] = LittleEndian2Int(substr($avihData, 36, 4)); $ThisFileInfo['RIFF']['raw']['avih']['dwScale'] = LittleEndian2Int(substr($avihData, 40, 4)); $ThisFileInfo['RIFF']['raw']['avih']['dwRate'] = LittleEndian2Int(substr($avihData, 44, 4)); $ThisFileInfo['RIFF']['raw']['avih']['dwStart'] = LittleEndian2Int(substr($avihData, 48, 4)); $ThisFileInfo['RIFF']['raw']['avih']['dwLength'] = LittleEndian2Int(substr($avihData, 52, 4)); $ThisFileInfo['RIFF']['raw']['avih']['flags']['hasindex'] = (bool) ($ThisFileInfo['RIFF']['raw']['avih']['dwFlags'] & 0x10); $ThisFileInfo['RIFF']['raw']['avih']['flags']['mustuseindex'] = (bool) ($ThisFileInfo['RIFF']['raw']['avih']['dwFlags'] & 0x20); $ThisFileInfo['RIFF']['raw']['avih']['flags']['interleaved'] = (bool) ($ThisFileInfo['RIFF']['raw']['avih']['dwFlags'] & 0x100); $ThisFileInfo['RIFF']['raw']['avih']['flags']['trustcktype'] = (bool) ($ThisFileInfo['RIFF']['raw']['avih']['dwFlags'] & 0x800); $ThisFileInfo['RIFF']['raw']['avih']['flags']['capturedfile'] = (bool) ($ThisFileInfo['RIFF']['raw']['avih']['dwFlags'] & 0x10000); $ThisFileInfo['RIFF']['raw']['avih']['flags']['copyrighted'] = (bool) ($ThisFileInfo['RIFF']['raw']['avih']['dwFlags'] & 0x20010); $ThisFileInfo['RIFF']['video'][$streamindex]['frame_width'] = $ThisFileInfo['RIFF']['raw']['avih']['dwWidth']; $ThisFileInfo['RIFF']['video'][$streamindex]['frame_height'] = $ThisFileInfo['RIFF']['raw']['avih']['dwHeight']; $ThisFileInfo['RIFF']['video'][$streamindex]['frame_rate'] = round(1000000 / $ThisFileInfo['RIFF']['raw']['avih']['dwMicroSecPerFrame'], 3); if (!isset($ThisFileInfo['video']['resolution_x'])) { $ThisFileInfo['video']['resolution_x'] = $ThisFileInfo['RIFF']['video'][$streamindex]['frame_width']; } if (!isset($ThisFileInfo['video']['resolution_y'])) { $ThisFileInfo['video']['resolution_y'] = $ThisFileInfo['RIFF']['video'][$streamindex]['frame_height']; } $ThisFileInfo['video']['frame_rate'] = $ThisFileInfo['RIFF']['video'][$streamindex]['frame_rate']; } if (isset($ThisFileInfo['RIFF']['AVI ']['hdrl']['strl']['strh'][0]['data'])) { if (is_array($ThisFileInfo['RIFF']['AVI ']['hdrl']['strl']['strh'])) { for ($i = 0; $i < count($ThisFileInfo['RIFF']['AVI ']['hdrl']['strl']['strh']); $i++) { if (isset($ThisFileInfo['RIFF']['AVI ']['hdrl']['strl']['strh'][$i]['data'])) { $strhData = $ThisFileInfo['RIFF']['AVI ']['hdrl']['strl']['strh'][$i]['data']; $strhfccType = substr($strhData, 0, 4); if (isset($ThisFileInfo['RIFF']['AVI ']['hdrl']['strl']['strf'][$i]['data'])) { $strfData = $ThisFileInfo['RIFF']['AVI ']['hdrl']['strl']['strf'][$i]['data']; switch ($strhfccType) { case 'auds': $ThisFileInfo['audio']['bitrate_mode'] = 'cbr'; $ThisFileInfo['audio']['dataformat'] = 'wav'; if (isset($ThisFileInfo['RIFF']['audio']) && is_array($ThisFileInfo['RIFF']['audio'])) { $streamindex = count($ThisFileInfo['RIFF']['audio']); } $ThisFileInfo['RIFF']['audio'][$streamindex] = RIFFparseWAVEFORMATex($strfData); $ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex] = $ThisFileInfo['RIFF']['audio'][$streamindex]['raw']; unset($ThisFileInfo['RIFF']['audio'][$streamindex]['raw']); $ThisFileInfo['audio'] = array_merge_noclobber($ThisFileInfo['audio'], $ThisFileInfo['RIFF']['audio'][$streamindex]); switch ($ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['wFormatTag']) { case 85: $ThisFileInfo['audio']['dataformat'] = 'mp3'; break; case 8192: $ThisFileInfo['audio']['dataformat'] = 'ac3'; break; default: $ThisFileInfo['audio']['dataformat'] = 'wav'; break; } break; case 'iavs': case 'vids': $ThisFileInfo['RIFF']['raw']['strh'][$i]['fccType'] = substr($strhData, 0, 4); // same as $strhfccType; $ThisFileInfo['RIFF']['raw']['strh'][$i]['fccHandler'] = substr($strhData, 4, 4); $ThisFileInfo['RIFF']['raw']['strh'][$i]['dwFlags'] = LittleEndian2Int(substr($strhData, 8, 4)); // Contains AVITF_* flags $ThisFileInfo['RIFF']['raw']['strh'][$i]['wPriority'] = LittleEndian2Int(substr($strhData, 12, 2)); $ThisFileInfo['RIFF']['raw']['strh'][$i]['wLanguage'] = LittleEndian2Int(substr($strhData, 14, 2)); $ThisFileInfo['RIFF']['raw']['strh'][$i]['dwInitialFrames'] = LittleEndian2Int(substr($strhData, 16, 4)); $ThisFileInfo['RIFF']['raw']['strh'][$i]['dwScale'] = LittleEndian2Int(substr($strhData, 20, 4)); $ThisFileInfo['RIFF']['raw']['strh'][$i]['dwRate'] = LittleEndian2Int(substr($strhData, 24, 4)); $ThisFileInfo['RIFF']['raw']['strh'][$i]['dwStart'] = LittleEndian2Int(substr($strhData, 28, 4)); $ThisFileInfo['RIFF']['raw']['strh'][$i]['dwLength'] = LittleEndian2Int(substr($strhData, 32, 4)); $ThisFileInfo['RIFF']['raw']['strh'][$i]['dwSuggestedBufferSize'] = LittleEndian2Int(substr($strhData, 36, 4)); $ThisFileInfo['RIFF']['raw']['strh'][$i]['dwQuality'] = LittleEndian2Int(substr($strhData, 40, 4)); $ThisFileInfo['RIFF']['raw']['strh'][$i]['dwSampleSize'] = LittleEndian2Int(substr($strhData, 44, 4)); $ThisFileInfo['RIFF']['raw']['strh'][$i]['rcFrame'] = LittleEndian2Int(substr($strhData, 48, 4)); $ThisFileInfo['RIFF']['video'][$streamindex]['codec'] = RIFFfourccLookup($ThisFileInfo['RIFF']['raw']['strh'][$i]['fccHandler']); if (!$ThisFileInfo['RIFF']['video'][$streamindex]['codec'] && isset($ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['fourcc']) && RIFFfourccLookup($ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['fourcc'])) { $ThisFileInfo['RIFF']['video'][$streamindex]['codec'] = RIFFfourccLookup($ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['fourcc']); } $ThisFileInfo['video']['codec'] = $ThisFileInfo['RIFF']['video'][$streamindex]['codec']; switch ($strhfccType) { case 'vids': $ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['biSize'] = LittleEndian2Int(substr($strfData, 0, 4)); // number of bytes required by the BITMAPINFOHEADER structure $ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['biWidth'] = LittleEndian2Int(substr($strfData, 4, 4)); // width of the bitmap in pixels $ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['biHeight'] = LittleEndian2Int(substr($strfData, 8, 4)); // height of the bitmap in pixels. If biHeight is positive, the bitmap is a 'bottom-up' DIB and its origin is the lower left corner. If biHeight is negative, the bitmap is a 'top-down' DIB and its origin is the upper left corner $ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['biPlanes'] = LittleEndian2Int(substr($strfData, 12, 2)); // number of color planes on the target device. In most cases this value must be set to 1 $ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['biBitCount'] = LittleEndian2Int(substr($strfData, 14, 2)); // Specifies the number of bits per pixels $ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['fourcc'] = substr($strfData, 16, 4); // $ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['biSizeImage'] = LittleEndian2Int(substr($strfData, 20, 4)); // size of the bitmap data section of the image (the actual pixel data, excluding BITMAPINFOHEADER and RGBQUAD structures) $ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['biXPelsPerMeter'] = LittleEndian2Int(substr($strfData, 24, 4)); // horizontal resolution, in pixels per metre, of the target device $ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['biYPelsPerMeter'] = LittleEndian2Int(substr($strfData, 28, 4)); // vertical resolution, in pixels per metre, of the target device $ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['biClrUsed'] = LittleEndian2Int(substr($strfData, 32, 4)); // actual number of color indices in the color table used by the bitmap. If this value is zero, the bitmap uses the maximum number of colors corresponding to the value of the biBitCount member for the compression mode specified by biCompression $ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['biClrImportant'] = LittleEndian2Int(substr($strfData, 36, 4)); // number of color indices that are considered important for displaying the bitmap. If this value is zero, all colors are important if ($ThisFileInfo['RIFF']['video'][$streamindex]['codec'] == 'DV') { $ThisFileInfo['RIFF']['video'][$streamindex]['dv_type'] = 2; } break; case 'iavs': $ThisFileInfo['RIFF']['video'][$streamindex]['dv_type'] = 1; break; } break; default: $ThisFileInfo['warning'] .= "\n" . 'Unhandled fccType for stream (' . $i . '): "' . $strhfccType . '"'; break; } } } if (isset($ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['fourcc']) && RIFFfourccLookup($ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['fourcc'])) { $ThisFileInfo['RIFF']['video'][$streamindex]['codec'] = RIFFfourccLookup($ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['fourcc']); $ThisFileInfo['video']['codec'] = $ThisFileInfo['RIFF']['video'][$streamindex]['codec']; } } } } break; case 'CDDA': $ThisFileInfo['audio']['bitrate_mode'] = 'cbr'; $ThisFileInfo['audio']['dataformat'] = 'cda'; unset($ThisFileInfo['mime_type']); if (isset($ThisFileInfo['RIFF']['CDDA']['fmt '][0]['data'])) { $fmtData = $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['data']; $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['unknown1'] = LittleEndian2Int(substr($fmtData, 0, 2)); $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['track_num'] = LittleEndian2Int(substr($fmtData, 2, 2)); $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['disc_id'] = LittleEndian2Int(substr($fmtData, 4, 4)); $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['start_offset_frame'] = LittleEndian2Int(substr($fmtData, 8, 4)); $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['playtime_frames'] = LittleEndian2Int(substr($fmtData, 12, 4)); $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['unknown6'] = LittleEndian2Int(substr($fmtData, 16, 4)); $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['unknown7'] = LittleEndian2Int(substr($fmtData, 20, 4)); $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['start_offset_seconds'] = (double) $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['start_offset_frame'] / 75; $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['playtime_seconds'] = (double) $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['playtime_frames'] / 75; $ThisFileInfo['comments']['track'] = $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['track_num']; $ThisFileInfo['playtime_seconds'] = $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['playtime_seconds']; // hardcoded data for CD-audio $ThisFileInfo['audio']['sample_rate'] = 44100; $ThisFileInfo['audio']['channels'] = 2; $ThisFileInfo['audio']['bits_per_sample'] = 16; $ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['audio']['sample_rate'] * $ThisFileInfo['audio']['channels'] * $ThisFileInfo['audio']['bits_per_sample']; $ThisFileInfo['audio']['bitrate_mode'] = 'cbr'; } break; default: unset($ThisFileInfo['fileformat']); break; } if (isset($ThisFileInfo['RIFF']['WAVE']['DISP']) && is_array($ThisFileInfo['RIFF']['WAVE']['DISP'])) { $ThisFileInfo['tags'][] = 'riff'; $ThisFileInfo['RIFF']['comments']['title'][] = trim(substr($ThisFileInfo['RIFF']['WAVE']['DISP'][count($ThisFileInfo['RIFF']['WAVE']['DISP']) - 1]['data'], 4)); } if (isset($ThisFileInfo['RIFF']['WAVE']['INFO']) && is_array($ThisFileInfo['RIFF']['WAVE']['INFO'])) { $ThisFileInfo['tags'][] = 'riff'; $RIFFinfoKeyLookup = array('IART' => 'artist', 'IGNR' => 'genre', 'ICMT' => 'comment', 'ICOP' => 'copyright', 'IENG' => 'engineers', 'IKEY' => 'keywords', 'IMED' => 'orignalmedium', 'INAM' => 'name', 'ISRC' => 'sourcesupplier', 'ITCH' => 'digitizer', 'ISBJ' => 'subject', 'ISRF' => 'digitizationsource'); foreach ($RIFFinfoKeyLookup as $key => $value) { foreach ($ThisFileInfo['RIFF']['WAVE']['INFO']["{$key}"] as $commentid => $commentdata) { if (trim($commentdata['data']) != '') { $ThisFileInfo['RIFF']['comments']["{$value}"][] = trim($commentdata['data']); } } } } if (!empty($ThisFileInfo['RIFF']['comments'])) { CopyFormatCommentsToRootComments($ThisFileInfo['RIFF']['comments'], $ThisFileInfo, true, true, true); } if (!isset($ThisFileInfo['playtime_seconds'])) { $ThisFileInfo['playtime_seconds'] = 0; } if (isset($ThisFileInfo['RIFF']['raw']['avih']['dwTotalFrames']) && isset($ThisFileInfo['RIFF']['raw']['avih']['dwMicroSecPerFrame'])) { $ThisFileInfo['playtime_seconds'] = $ThisFileInfo['RIFF']['raw']['avih']['dwTotalFrames'] * ($ThisFileInfo['RIFF']['raw']['avih']['dwMicroSecPerFrame'] / 1000000); } if ($ThisFileInfo['playtime_seconds'] > 0) { if (isset($ThisFileInfo['RIFF']['audio']) && isset($ThisFileInfo['RIFF']['video'])) { if (!isset($ThisFileInfo['bitrate'])) { $ThisFileInfo['bitrate'] = ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) / $ThisFileInfo['playtime_seconds'] * 8; } } elseif (isset($ThisFileInfo['RIFF']['audio']) && !isset($ThisFileInfo['RIFF']['video'])) { if (!isset($ThisFileInfo['audio']['bitrate'])) { $ThisFileInfo['audio']['bitrate'] = ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) / $ThisFileInfo['playtime_seconds'] * 8; } } elseif (!isset($ThisFileInfo['RIFF']['audio']) && isset($ThisFileInfo['RIFF']['video'])) { if (!isset($ThisFileInfo['video']['bitrate'])) { $ThisFileInfo['video']['bitrate'] = ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) / $ThisFileInfo['playtime_seconds'] * 8; } } } if (isset($ThisFileInfo['RIFF']['video']) && isset($ThisFileInfo['audio']['bitrate']) && $ThisFileInfo['audio']['bitrate'] > 0 && $ThisFileInfo['playtime_seconds'] > 0) { $ThisFileInfo['audio']['bitrate'] = 0; $ThisFileInfo['video']['bitrate'] = ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) / $ThisFileInfo['playtime_seconds'] * 8; foreach ($ThisFileInfo['RIFF']['audio'] as $channelnumber => $audioinfoarray) { $ThisFileInfo['video']['bitrate'] -= $audioinfoarray['bitrate']; $ThisFileInfo['audio']['bitrate'] += $audioinfoarray['bitrate']; } if ($ThisFileInfo['video']['bitrate'] <= 0) { unset($ThisFileInfo['video']['bitrate']); } if ($ThisFileInfo['audio']['bitrate'] <= 0) { unset($ThisFileInfo['audio']['bitrate']); } } if (!empty($ThisFileInfo['RIFF']['raw']['fmt ']['nBitsPerSample'])) { $ThisFileInfo['audio']['bits_per_sample'] = $ThisFileInfo['RIFF']['raw']['fmt ']['nBitsPerSample']; } // Skip RIFF header $ThisFileInfo['avdataoffset'] += 44; return true; }