function getRIFFHeaderFilepointer(&$fd, &$MP3fileInfo) { $offset = 0; rewind($fd); $MP3fileInfo['RIFF'] = ParseRIFF($fd, $offset, $MP3fileInfo['filesize']); $streamindex = 0; if (!is_array($MP3fileInfo['RIFF'])) { $MP3fileInfo['error'] .= "\n" . 'Cannot parse RIFF (this is maybe not a RIFF / WAV / AVI file?)'; unset($MP3fileInfo['RIFF']); unset($MP3fileInfo['fileformat']); return FALSE; } $arraykeys = array_keys($MP3fileInfo['RIFF']); switch ($arraykeys[0]) { case 'WAVE': $MP3fileInfo['fileformat'] = 'wav'; if (isset($MP3fileInfo['RIFF']['WAVE']['fmt '][0]['data'])) { $fmtData = $MP3fileInfo['RIFF']['WAVE']['fmt '][0]['data']; $MP3fileInfo['RIFF']['raw']['fmt ']['wFormatTag'] = LittleEndian2Int(substr($fmtData, 0, 2)); $MP3fileInfo['RIFF']['raw']['fmt ']['nChannels'] = LittleEndian2Int(substr($fmtData, 2, 2)); $MP3fileInfo['RIFF']['raw']['fmt ']['nSamplesPerSec'] = LittleEndian2Int(substr($fmtData, 4, 4)); $MP3fileInfo['RIFF']['raw']['fmt ']['nAvgBytesPerSec'] = LittleEndian2Int(substr($fmtData, 8, 4)); $MP3fileInfo['RIFF']['raw']['fmt ']['nBlockAlign'] = LittleEndian2Int(substr($fmtData, 12, 2)); $MP3fileInfo['RIFF']['raw']['fmt ']['nBitsPerSample'] = LittleEndian2Int(substr($fmtData, 14, 2)); $MP3fileInfo['RIFF']['audio']["{$streamindex}"]['format'] = RIFFwFormatTagLookup($MP3fileInfo['RIFF']['raw']['fmt ']['wFormatTag']); $MP3fileInfo['RIFF']['audio']["{$streamindex}"]['channels'] = $MP3fileInfo['RIFF']['raw']['fmt ']['nChannels']; $MP3fileInfo['RIFF']['audio']["{$streamindex}"]['channelmode'] = $MP3fileInfo['RIFF']['audio']["{$streamindex}"]['channels'] == 1 ? 'mono' : 'stereo'; $MP3fileInfo['RIFF']['audio']["{$streamindex}"]['frequency'] = $MP3fileInfo['RIFF']['raw']['fmt ']['nSamplesPerSec']; $MP3fileInfo['RIFF']['audio']["{$streamindex}"]['bitrate'] = $MP3fileInfo['RIFF']['raw']['fmt ']['nAvgBytesPerSec'] * 8; $MP3fileInfo['RIFF']['audio']["{$streamindex}"]['bitspersample'] = $MP3fileInfo['RIFF']['raw']['fmt ']['nBitsPerSample']; } if (isset($MP3fileInfo['RIFF']['WAVE']['rgad'][0]['data'])) { $rgadData = $MP3fileInfo['RIFF']['WAVE']['rgad'][0]['data']; $MP3fileInfo['RIFF']['raw']['rgad']['fPeakAmplitude'] = LittleEndian2Float(substr($rgadData, 0, 4)); $MP3fileInfo['RIFF']['raw']['rgad']['nRadioRgAdjust'] = LittleEndian2Int(substr($rgadData, 4, 2)); $MP3fileInfo['RIFF']['raw']['rgad']['nAudiophileRgAdjust'] = LittleEndian2Int(substr($rgadData, 6, 2)); $nRadioRgAdjustBitstring = str_pad(Dec2Bin($MP3fileInfo['RIFF']['raw']['rgad']['nRadioRgAdjust']), 16, '0', STR_PAD_LEFT); $nAudiophileRgAdjustBitstring = str_pad(Dec2Bin($MP3fileInfo['RIFF']['raw']['rgad']['nAudiophileRgAdjust']), 16, '0', STR_PAD_LEFT); $MP3fileInfo['RIFF']['raw']['rgad']['radio']['name'] = Bin2Dec(substr($nRadioRgAdjustBitstring, 0, 3)); $MP3fileInfo['RIFF']['raw']['rgad']['radio']['originator'] = Bin2Dec(substr($nRadioRgAdjustBitstring, 3, 3)); $MP3fileInfo['RIFF']['raw']['rgad']['radio']['signbit'] = Bin2Dec(substr($nRadioRgAdjustBitstring, 6, 1)); $MP3fileInfo['RIFF']['raw']['rgad']['radio']['adjustment'] = Bin2Dec(substr($nRadioRgAdjustBitstring, 7, 9)); $MP3fileInfo['RIFF']['raw']['rgad']['audiophile']['name'] = Bin2Dec(substr($nAudiophileRgAdjustBitstring, 0, 3)); $MP3fileInfo['RIFF']['raw']['rgad']['audiophile']['originator'] = Bin2Dec(substr($nAudiophileRgAdjustBitstring, 3, 3)); $MP3fileInfo['RIFF']['raw']['rgad']['audiophile']['signbit'] = Bin2Dec(substr($nAudiophileRgAdjustBitstring, 6, 1)); $MP3fileInfo['RIFF']['raw']['rgad']['audiophile']['adjustment'] = Bin2Dec(substr($nAudiophileRgAdjustBitstring, 7, 9)); $MP3fileInfo['RIFF']['rgad']['peakamplitude'] = $MP3fileInfo['RIFF']['raw']['rgad']['fPeakAmplitude']; if ($MP3fileInfo['RIFF']['raw']['rgad']['radio']['name'] != 0 && $MP3fileInfo['RIFF']['raw']['rgad']['radio']['originator'] != 0) { $MP3fileInfo['RIFF']['rgad']['radio']['name'] = RGADnameLookup($MP3fileInfo['RIFF']['raw']['rgad']['radio']['name']); $MP3fileInfo['RIFF']['rgad']['radio']['originator'] = RGADoriginatorLookup($MP3fileInfo['RIFF']['raw']['rgad']['radio']['originator']); $MP3fileInfo['RIFF']['rgad']['radio']['adjustment'] = RGADadjustmentLookup($MP3fileInfo['RIFF']['raw']['rgad']['radio']['adjustment'], $MP3fileInfo['RIFF']['raw']['rgad']['radio']['signbit']); } if ($MP3fileInfo['RIFF']['raw']['rgad']['audiophile']['name'] != 0 && $MP3fileInfo['RIFF']['raw']['rgad']['audiophile']['originator'] != 0) { $MP3fileInfo['RIFF']['rgad']['audiophile']['name'] = RGADnameLookup($MP3fileInfo['RIFF']['raw']['rgad']['audiophile']['name']); $MP3fileInfo['RIFF']['rgad']['audiophile']['originator'] = RGADoriginatorLookup($MP3fileInfo['RIFF']['raw']['rgad']['audiophile']['originator']); $MP3fileInfo['RIFF']['rgad']['audiophile']['adjustment'] = RGADadjustmentLookup($MP3fileInfo['RIFF']['raw']['rgad']['audiophile']['adjustment'], $MP3fileInfo['RIFF']['raw']['rgad']['audiophile']['signbit']); } } if (isset($MP3fileInfo['RIFF']['WAVE']['fact'][0]['data'])) { $MP3fileInfo['RIFF']['raw']['fact']['NumberOfSamples'] = LittleEndian2Int(substr($MP3fileInfo['RIFF']['WAVE']['fact'][0]['data'], 0, 4)); if (isset($MP3fileInfo['RIFF']['raw']['fmt ']['nSamplesPerSec']) && $MP3fileInfo['RIFF']['raw']['fmt ']['nSamplesPerSec']) { $MP3fileInfo['playtime_seconds'] = (double) $MP3fileInfo['RIFF']['raw']['fact']['NumberOfSamples'] / $MP3fileInfo['RIFF']['raw']['fmt ']['nSamplesPerSec']; } if (isset($MP3fileInfo['RIFF']['raw']['fmt ']['nAvgBytesPerSec']) && $MP3fileInfo['RIFF']['raw']['fmt ']['nAvgBytesPerSec']) { $MP3fileInfo['audiobytes'] = CastAsInt(round($MP3fileInfo['playtime_seconds'] * $MP3fileInfo['RIFF']['raw']['fmt ']['nAvgBytesPerSec'])); $MP3fileInfo['bitrate'] = CastAsInt($MP3fileInfo['RIFF']['raw']['fmt ']['nAvgBytesPerSec'] * 8); } } if (!isset($MP3fileInfo['audiobytes']) && isset($MP3fileInfo['RIFF']['WAVE']['data'][0]['size'])) { $MP3fileInfo['audiobytes'] = $MP3fileInfo['RIFF']['WAVE']['data'][0]['size']; } if (!isset($MP3fileInfo['bitrate']) && isset($MP3fileInfo['RIFF']['audio']["{$streamindex}"]['bitrate']) && isset($MP3fileInfo['audiobytes'])) { $MP3fileInfo['bitrate'] = $MP3fileInfo['RIFF']['audio']["{$streamindex}"]['bitrate']; $MP3fileInfo['playtime_seconds'] = (double) ($MP3fileInfo['audiobytes'] * 8 / $MP3fileInfo['bitrate']); } break; case 'AVI ': $MP3fileInfo['fileformat'] = 'avi'; if (isset($MP3fileInfo['RIFF']['AVI ']['hdrl']['avih']["{$streamindex}"]['data'])) { $avihData = $MP3fileInfo['RIFF']['AVI ']['hdrl']['avih']["{$streamindex}"]['data']; $MP3fileInfo['RIFF']['raw']['avih']['dwMicroSecPerFrame'] = LittleEndian2Int(substr($avihData, 0, 4)); // frame display rate (or 0L) $MP3fileInfo['RIFF']['raw']['avih']['dwMaxBytesPerSec'] = LittleEndian2Int(substr($avihData, 4, 4)); // max. transfer rate $MP3fileInfo['RIFF']['raw']['avih']['dwPaddingGranularity'] = LittleEndian2Int(substr($avihData, 8, 4)); // pad to multiples of this size; normally 2K. $MP3fileInfo['RIFF']['raw']['avih']['dwFlags'] = LittleEndian2Int(substr($avihData, 12, 4)); // the ever-present flags $MP3fileInfo['RIFF']['raw']['avih']['dwTotalFrames'] = LittleEndian2Int(substr($avihData, 16, 4)); // # frames in file $MP3fileInfo['RIFF']['raw']['avih']['dwInitialFrames'] = LittleEndian2Int(substr($avihData, 20, 4)); $MP3fileInfo['RIFF']['raw']['avih']['dwStreams'] = LittleEndian2Int(substr($avihData, 24, 4)); $MP3fileInfo['RIFF']['raw']['avih']['dwSuggestedBufferSize'] = LittleEndian2Int(substr($avihData, 28, 4)); $MP3fileInfo['RIFF']['raw']['avih']['dwWidth'] = LittleEndian2Int(substr($avihData, 32, 4)); $MP3fileInfo['RIFF']['raw']['avih']['dwHeight'] = LittleEndian2Int(substr($avihData, 36, 4)); $MP3fileInfo['RIFF']['raw']['avih']['dwScale'] = LittleEndian2Int(substr($avihData, 40, 4)); $MP3fileInfo['RIFF']['raw']['avih']['dwRate'] = LittleEndian2Int(substr($avihData, 44, 4)); $MP3fileInfo['RIFF']['raw']['avih']['dwStart'] = LittleEndian2Int(substr($avihData, 48, 4)); $MP3fileInfo['RIFF']['raw']['avih']['dwLength'] = LittleEndian2Int(substr($avihData, 52, 4)); $MP3fileInfo['RIFF']['raw']['avih']['flags']['hasindex'] = (bool) ($MP3fileInfo['RIFF']['raw']['avih']['dwFlags'] & 0x10); $MP3fileInfo['RIFF']['raw']['avih']['flags']['mustuseindex'] = (bool) ($MP3fileInfo['RIFF']['raw']['avih']['dwFlags'] & 0x20); $MP3fileInfo['RIFF']['raw']['avih']['flags']['interleaved'] = (bool) ($MP3fileInfo['RIFF']['raw']['avih']['dwFlags'] & 0x100); $MP3fileInfo['RIFF']['raw']['avih']['flags']['trustcktype'] = (bool) ($MP3fileInfo['RIFF']['raw']['avih']['dwFlags'] & 0x800); $MP3fileInfo['RIFF']['raw']['avih']['flags']['capturedfile'] = (bool) ($MP3fileInfo['RIFF']['raw']['avih']['dwFlags'] & 0x10000); $MP3fileInfo['RIFF']['raw']['avih']['flags']['copyrighted'] = (bool) ($MP3fileInfo['RIFF']['raw']['avih']['dwFlags'] & 0x20010); $MP3fileInfo['RIFF']['video']["{$streamindex}"]['frame_width'] = $MP3fileInfo['RIFF']['raw']['avih']['dwWidth']; $MP3fileInfo['RIFF']['video']["{$streamindex}"]['frame_height'] = $MP3fileInfo['RIFF']['raw']['avih']['dwHeight']; $MP3fileInfo['RIFF']['video']["{$streamindex}"]['frame_rate'] = round(1000000 / $MP3fileInfo['RIFF']['raw']['avih']['dwMicroSecPerFrame'], 3); $MP3fileInfo['playtime_seconds'] = $MP3fileInfo['RIFF']['raw']['avih']['dwTotalFrames'] * ($MP3fileInfo['RIFF']['raw']['avih']['dwMicroSecPerFrame'] / 1000000); $MP3fileInfo['bitrate'] = $MP3fileInfo['filesize'] / $MP3fileInfo['playtime_seconds'] * 8; } if (isset($MP3fileInfo['RIFF']['AVI ']['hdrl']['strl']['strh'][0]['data'])) { if (is_array($MP3fileInfo['RIFF']['AVI ']['hdrl']['strl']['strh'])) { for ($i = 0; $i < count($MP3fileInfo['RIFF']['AVI ']['hdrl']['strl']['strh']); $i++) { if (isset($MP3fileInfo['RIFF']['AVI ']['hdrl']['strl']['strh']["{$i}"]['data'])) { $strhData = $MP3fileInfo['RIFF']['AVI ']['hdrl']['strl']['strh']["{$i}"]['data']; $MP3fileInfo['RIFF']['raw']['strh']["{$i}"]['fccType'] = substr($strhData, 0, 4); $MP3fileInfo['RIFF']['raw']['strh']["{$i}"]['fccHandler'] = substr($strhData, 4, 4); $MP3fileInfo['RIFF']['raw']['strh']["{$i}"]['dwFlags'] = LittleEndian2Int(substr($strhData, 8, 4)); // Contains AVITF_* flags $MP3fileInfo['RIFF']['raw']['strh']["{$i}"]['wPriority'] = LittleEndian2Int(substr($strhData, 12, 2)); $MP3fileInfo['RIFF']['raw']['strh']["{$i}"]['wLanguage'] = LittleEndian2Int(substr($strhData, 14, 2)); $MP3fileInfo['RIFF']['raw']['strh']["{$i}"]['dwInitialFrames'] = LittleEndian2Int(substr($strhData, 16, 4)); $MP3fileInfo['RIFF']['raw']['strh']["{$i}"]['dwScale'] = LittleEndian2Int(substr($strhData, 20, 4)); $MP3fileInfo['RIFF']['raw']['strh']["{$i}"]['dwRate'] = LittleEndian2Int(substr($strhData, 24, 4)); $MP3fileInfo['RIFF']['raw']['strh']["{$i}"]['dwStart'] = LittleEndian2Int(substr($strhData, 28, 4)); $MP3fileInfo['RIFF']['raw']['strh']["{$i}"]['dwLength'] = LittleEndian2Int(substr($strhData, 32, 4)); $MP3fileInfo['RIFF']['raw']['strh']["{$i}"]['dwSuggestedBufferSize'] = LittleEndian2Int(substr($strhData, 36, 4)); $MP3fileInfo['RIFF']['raw']['strh']["{$i}"]['dwQuality'] = LittleEndian2Int(substr($strhData, 40, 4)); $MP3fileInfo['RIFF']['raw']['strh']["{$i}"]['dwSampleSize'] = LittleEndian2Int(substr($strhData, 44, 4)); $MP3fileInfo['RIFF']['raw']['strh']["{$i}"]['rcFrame'] = LittleEndian2Int(substr($strhData, 48, 4)); if (isset($MP3fileInfo['RIFF']['AVI ']['hdrl']['strl']['strf']["{$i}"]['data'])) { $strfData = $MP3fileInfo['RIFF']['AVI ']['hdrl']['strl']['strf']["{$i}"]['data']; switch ($MP3fileInfo['RIFF']['raw']['strh']["{$i}"]['fccType']) { case 'auds': if (isset($MP3fileInfo['RIFF']['audio']) && is_array($MP3fileInfo['RIFF']['audio'])) { $streamindex = count($MP3fileInfo['RIFF']['audio']); } $MP3fileInfo['RIFF']['raw']['strf']['auds']["{$streamindex}"]['wFormatTag'] = LittleEndian2Int(substr($strfData, 0, 2)); $MP3fileInfo['RIFF']['raw']['strf']['auds']["{$streamindex}"]['nChannels'] = LittleEndian2Int(substr($strfData, 2, 2)); $MP3fileInfo['RIFF']['raw']['strf']['auds']["{$streamindex}"]['nSamplesPerSec'] = LittleEndian2Int(substr($strfData, 4, 4)); $MP3fileInfo['RIFF']['raw']['strf']['auds']["{$streamindex}"]['nAvgBytesPerSec'] = LittleEndian2Int(substr($strfData, 8, 4)); $MP3fileInfo['RIFF']['raw']['strf']['auds']["{$streamindex}"]['nBlockAlign'] = LittleEndian2Int(substr($strfData, 12, 2)); $MP3fileInfo['RIFF']['raw']['strf']['auds']["{$streamindex}"]['nBitsPerSample'] = LittleEndian2Int(substr($strfData, 14, 2)); $MP3fileInfo['RIFF']['audio']["{$streamindex}"]['format'] = RIFFwFormatTagLookup($MP3fileInfo['RIFF']['raw']['strf']['auds']["{$streamindex}"]['wFormatTag']); $MP3fileInfo['RIFF']['audio']["{$streamindex}"]['channels'] = $MP3fileInfo['RIFF']['raw']['strf']['auds']["{$streamindex}"]['nChannels']; $MP3fileInfo['RIFF']['audio']["{$streamindex}"]['channelmode'] = $MP3fileInfo['RIFF']['audio']["{$streamindex}"]['channels'] == 1 ? 'mono' : 'stereo'; $MP3fileInfo['RIFF']['audio']["{$streamindex}"]['frequency'] = $MP3fileInfo['RIFF']['raw']['strf']['auds']["{$streamindex}"]['nSamplesPerSec']; $MP3fileInfo['RIFF']['audio']["{$streamindex}"]['bitrate'] = $MP3fileInfo['RIFF']['raw']['strf']['auds']["{$streamindex}"]['nAvgBytesPerSec'] * 8; $MP3fileInfo['RIFF']['audio']["{$streamindex}"]['bitspersample'] = $MP3fileInfo['RIFF']['raw']['strf']['auds']["{$streamindex}"]['nBitsPerSample']; break; case 'vids': $MP3fileInfo['RIFF']['raw']['strf']['vids']["{$streamindex}"]['biSize'] = LittleEndian2Int(substr($strfData, 0, 4)); // number of bytes required by the BITMAPINFOHEADER structure $MP3fileInfo['RIFF']['raw']['strf']['vids']["{$streamindex}"]['biWidth'] = LittleEndian2Int(substr($strfData, 4, 4)); // width of the bitmap in pixels $MP3fileInfo['RIFF']['raw']['strf']['vids']["{$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 $MP3fileInfo['RIFF']['raw']['strf']['vids']["{$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 $MP3fileInfo['RIFF']['raw']['strf']['vids']["{$streamindex}"]['biBitCount'] = LittleEndian2Int(substr($strfData, 14, 2)); // Specifies the number of bits per pixels $MP3fileInfo['RIFF']['raw']['strf']['vids']["{$streamindex}"]['fourcc'] = substr($strfData, 16, 4); // $MP3fileInfo['RIFF']['raw']['strf']['vids']["{$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) $MP3fileInfo['RIFF']['raw']['strf']['vids']["{$streamindex}"]['biXPelsPerMeter'] = LittleEndian2Int(substr($strfData, 24, 4)); // horizontal resolution, in pixels per metre, of the target device $MP3fileInfo['RIFF']['raw']['strf']['vids']["{$streamindex}"]['biYPelsPerMeter'] = LittleEndian2Int(substr($strfData, 28, 4)); // vertical resolution, in pixels per metre, of the target device $MP3fileInfo['RIFF']['raw']['strf']['vids']["{$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 $MP3fileInfo['RIFF']['raw']['strf']['vids']["{$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 $MP3fileInfo['RIFF']['video']["{$streamindex}"]['codec'] = RIFFfourccLookup($MP3fileInfo['RIFF']['raw']['strh']["{$i}"]['fccHandler']); if (!$MP3fileInfo['RIFF']['video']["{$streamindex}"]['codec'] && RIFFfourccLookup($MP3fileInfo['RIFF']['raw']['strf']['vids']["{$streamindex}"]['fourcc'])) { RIFFfourccLookup($MP3fileInfo['RIFF']['raw']['strf']['vids']["{$streamindex}"]['fourcc']); } break; } } } } } } break; default: unset($MP3fileInfo['fileformat']); break; } if (isset($MP3fileInfo['RIFF']['WAVE']['INFO']) && is_array($MP3fileInfo['RIFF']['WAVE']['INFO'])) { $MP3fileInfo['RIFF']['title'] = trim(substr($MP3fileInfo['RIFF']['WAVE']['INFO']['DISP'][count($MP3fileInfo['RIFF']['WAVE']['INFO']['DISP']) - 1]['data'], 4)); $MP3fileInfo['RIFF']['artist'] = trim($MP3fileInfo['RIFF']['WAVE']['INFO']['IART'][count($MP3fileInfo['RIFF']['WAVE']['INFO']['IART']) - 1]['data']); $MP3fileInfo['RIFF']['genre'] = trim($MP3fileInfo['RIFF']['WAVE']['INFO']['IGNR'][count($MP3fileInfo['RIFF']['WAVE']['INFO']['IGNR']) - 1]['data']); $MP3fileInfo['RIFF']['comment'] = trim($MP3fileInfo['RIFF']['WAVE']['INFO']['ICMT'][count($MP3fileInfo['RIFF']['WAVE']['INFO']['ICMT']) - 1]['data']); $MP3fileInfo['RIFF']['copyright'] = trim($MP3fileInfo['RIFF']['WAVE']['INFO']['ICOP'][count($MP3fileInfo['RIFF']['WAVE']['INFO']['ICOP']) - 1]['data']); $MP3fileInfo['RIFF']['engineers'] = trim($MP3fileInfo['RIFF']['WAVE']['INFO']['IENG'][count($MP3fileInfo['RIFF']['WAVE']['INFO']['IENG']) - 1]['data']); $MP3fileInfo['RIFF']['keywords'] = trim($MP3fileInfo['RIFF']['WAVE']['INFO']['IKEY'][count($MP3fileInfo['RIFF']['WAVE']['INFO']['IKEY']) - 1]['data']); $MP3fileInfo['RIFF']['originalmedium'] = trim($MP3fileInfo['RIFF']['WAVE']['INFO']['IMED'][count($MP3fileInfo['RIFF']['WAVE']['INFO']['IMED']) - 1]['data']); $MP3fileInfo['RIFF']['name'] = trim($MP3fileInfo['RIFF']['WAVE']['INFO']['INAM'][count($MP3fileInfo['RIFF']['WAVE']['INFO']['INAM']) - 1]['data']); $MP3fileInfo['RIFF']['sourcesupplier'] = trim($MP3fileInfo['RIFF']['WAVE']['INFO']['ISRC'][count($MP3fileInfo['RIFF']['WAVE']['INFO']['ISRC']) - 1]['data']); $MP3fileInfo['RIFF']['digitizer'] = trim($MP3fileInfo['RIFF']['WAVE']['INFO']['ITCH'][count($MP3fileInfo['RIFF']['WAVE']['INFO']['ITCH']) - 1]['data']); $MP3fileInfo['RIFF']['subject'] = trim($MP3fileInfo['RIFF']['WAVE']['INFO']['ISBJ'][count($MP3fileInfo['RIFF']['WAVE']['INFO']['ISBJ']) - 1]['data']); $MP3fileInfo['RIFF']['digitizationsource'] = trim($MP3fileInfo['RIFF']['WAVE']['INFO']['ISRF'][count($MP3fileInfo['RIFF']['WAVE']['INFO']['ISRF']) - 1]['data']); } foreach ($MP3fileInfo['RIFF'] as $key => $value) { if (!is_array($value) && !$value) { unset($MP3fileInfo['RIFF']["{$key}"]); } } return TRUE; }
function getRIFFHeaderFilepointer(&$fd, &$ThisFileInfo) { $Original['avdataoffset'] = $ThisFileInfo['avdataoffset']; $Original['avdataend'] = $ThisFileInfo['avdataend']; fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET); $RIFFheader = fread($fd, 12); switch (substr($RIFFheader, 0, 4)) { case 'FORM': $ThisFileInfo['fileformat'] = 'aiff'; $RIFFheaderSize = EitherEndian2Int($ThisFileInfo, substr($RIFFheader, 4, 4)); $ThisFileInfo['RIFF'][substr($RIFFheader, 8, 4)] = ParseRIFF($fd, $ThisFileInfo['avdataoffset'] + 12, $ThisFileInfo['avdataoffset'] + $RIFFheaderSize, $ThisFileInfo); $ThisFileInfo['RIFF']['header_size'] = $RIFFheaderSize; break; case 'RIFF': case 'SDSS': // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com) // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com) case 'RMP3': // RMP3 is identical to RIFF, just renamed. Used by [unknown program] when creating RIFF-MP3s $RIFFtype = substr($RIFFheader, 8, 4); if ($RIFFtype == 'RMP3') { $RIFFtype == 'WAVE'; } $ThisFileInfo['fileformat'] = 'riff'; $RIFFheaderSize = EitherEndian2Int($ThisFileInfo, substr($RIFFheader, 4, 4)); $ThisFileInfo['RIFF']["{$RIFFtype}"] = ParseRIFF($fd, $ThisFileInfo['avdataoffset'] + 12, $ThisFileInfo['avdataoffset'] + $RIFFheaderSize, $ThisFileInfo); $ThisFileInfo['RIFF']['header_size'] = $RIFFheaderSize; 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': case 'RMP3': // RMP3 is identical to WAVE, just renamed. Used by [unknown program] when creating RIFF-MP3s if (empty($ThisFileInfo['audio']['bitrate_mode'])) { $ThisFileInfo['audio']['bitrate_mode'] = 'cbr'; } if (empty($ThisFileInfo['audio']['dataformat'])) { $ThisFileInfo['audio']['dataformat'] = 'wav'; } if (isset($ThisFileInfo['RIFF'][$arraykeys[0]]['data'][0]['offset'])) { $ThisFileInfo['avdataoffset'] = $ThisFileInfo['RIFF'][$arraykeys[0]]['data'][0]['offset'] + 8; $ThisFileInfo['avdataend'] = $ThisFileInfo['avdataoffset'] + $ThisFileInfo['RIFF'][$arraykeys[0]]['data'][0]['size']; } 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]); if (substr($ThisFileInfo['audio']['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') { $ThisFileInfo['warning'] .= "\n" . 'Audio codec = ' . $ThisFileInfo['audio']['codec']; } $ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['RIFF']['audio'][$streamindex]['bitrate']; if ($ThisFileInfo['audio']['bits_per_sample'] == 0) { unset($ThisFileInfo['audio']['bits_per_sample']); } $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'])) { $ThisFileInfo['audio']['lossless'] = false; switch ($ThisFileInfo['RIFF']['raw']['fmt ']['wFormatTag']) { case 1: // PCM $ThisFileInfo['audio']['lossless'] = true; 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'] = EitherEndian2Int($ThisFileInfo, substr($rgadData, 4, 2)); $ThisFileInfo['RIFF']['raw']['rgad']['nAudiophileRgAdjust'] = EitherEndian2Int($ThisFileInfo, 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'] = EitherEndian2Int($ThisFileInfo, 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['RIFF']['WAVE']['bext'][0]['data'])) { $ThisFileInfo['RIFF']['WAVE']['bext'][0]['title'] = trim(substr($ThisFileInfo['RIFF']['WAVE']['bext'][0]['data'], 0, 256)); $ThisFileInfo['RIFF']['WAVE']['bext'][0]['author'] = trim(substr($ThisFileInfo['RIFF']['WAVE']['bext'][0]['data'], 256, 32)); $ThisFileInfo['RIFF']['WAVE']['bext'][0]['reference'] = trim(substr($ThisFileInfo['RIFF']['WAVE']['bext'][0]['data'], 288, 32)); $ThisFileInfo['RIFF']['WAVE']['bext'][0]['origin_date'] = substr($ThisFileInfo['RIFF']['WAVE']['bext'][0]['data'], 320, 10); $ThisFileInfo['RIFF']['WAVE']['bext'][0]['origin_time'] = substr($ThisFileInfo['RIFF']['WAVE']['bext'][0]['data'], 330, 8); $ThisFileInfo['RIFF']['WAVE']['bext'][0]['time_reference'] = LittleEndian2Int(substr($ThisFileInfo['RIFF']['WAVE']['bext'][0]['data'], 338, 8)); $ThisFileInfo['RIFF']['WAVE']['bext'][0]['bwf_version'] = LittleEndian2Int(substr($ThisFileInfo['RIFF']['WAVE']['bext'][0]['data'], 346, 1)); $ThisFileInfo['RIFF']['WAVE']['bext'][0]['reserved'] = LittleEndian2Int(substr($ThisFileInfo['RIFF']['WAVE']['bext'][0]['data'], 347, 254)); $ThisFileInfo['RIFF']['WAVE']['bext'][0]['coding_history'] = explode("\r\n", trim(substr($ThisFileInfo['RIFF']['WAVE']['bext'][0]['data'], 601))); $ThisFileInfo['RIFF']['WAVE']['bext'][0]['origin_date_unix'] = mktime(substr($ThisFileInfo['RIFF']['WAVE']['bext'][0]['origin_time'], 0, 2), substr($ThisFileInfo['RIFF']['WAVE']['bext'][0]['origin_time'], 3, 2), substr($ThisFileInfo['RIFF']['WAVE']['bext'][0]['origin_time'], 6, 2), substr($ThisFileInfo['RIFF']['WAVE']['bext'][0]['origin_date'], 5, 2), substr($ThisFileInfo['RIFF']['WAVE']['bext'][0]['origin_date'], 8, 2), substr($ThisFileInfo['RIFF']['WAVE']['bext'][0]['origin_date'], 0, 4)); $ThisFileInfo['RIFF']['comments']['author'][] = $ThisFileInfo['RIFF']['WAVE']['bext'][0]['author']; $ThisFileInfo['RIFF']['comments']['title'][] = $ThisFileInfo['RIFF']['WAVE']['bext'][0]['title']; } if (isset($ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['data'])) { $ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['raw']['sound_information'] = LittleEndian2Int(substr($ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['data'], 0, 2)); $ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['flags']['homogenous'] = (bool) ($ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['raw']['sound_information'] & 0x1); if ($ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['flags']['homogenous']) { $ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['flags']['padding'] = InverseBoolean($ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['raw']['sound_information'] & 0x2); $ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['flags']['22_or_44'] = (bool) ($ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['raw']['sound_information'] & 0x4); $ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['flags']['free_format'] = (bool) ($ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['raw']['sound_information'] & 0x8); $ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['nominal_frame_size'] = LittleEndian2Int(substr($ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['data'], 2, 2)); } $ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['anciliary_data_length'] = LittleEndian2Int(substr($ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['data'], 6, 2)); $ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['raw']['anciliary_data_def'] = LittleEndian2Int(substr($ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['data'], 8, 2)); $ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['flags']['anciliary_data_left'] = (bool) ($ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['raw']['anciliary_data_def'] & 0x1); $ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['flags']['anciliary_data_free'] = (bool) ($ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['raw']['anciliary_data_def'] & 0x2); $ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['flags']['anciliary_data_right'] = (bool) ($ThisFileInfo['RIFF']['WAVE']['MEXT'][0]['raw']['anciliary_data_def'] & 0x4); } if (isset($ThisFileInfo['RIFF']['WAVE']['cart'][0]['data'])) { $ThisFileInfo['RIFF']['WAVE']['cart'][0]['version'] = substr($ThisFileInfo['RIFF']['WAVE']['cart'][0]['data'], 0, 4); $ThisFileInfo['RIFF']['WAVE']['cart'][0]['title'] = trim(substr($ThisFileInfo['RIFF']['WAVE']['cart'][0]['data'], 4, 64)); $ThisFileInfo['RIFF']['WAVE']['cart'][0]['artist'] = trim(substr($ThisFileInfo['RIFF']['WAVE']['cart'][0]['data'], 68, 64)); $ThisFileInfo['RIFF']['WAVE']['cart'][0]['cut_id'] = trim(substr($ThisFileInfo['RIFF']['WAVE']['cart'][0]['data'], 132, 64)); $ThisFileInfo['RIFF']['WAVE']['cart'][0]['client_id'] = trim(substr($ThisFileInfo['RIFF']['WAVE']['cart'][0]['data'], 196, 64)); $ThisFileInfo['RIFF']['WAVE']['cart'][0]['category'] = trim(substr($ThisFileInfo['RIFF']['WAVE']['cart'][0]['data'], 260, 64)); $ThisFileInfo['RIFF']['WAVE']['cart'][0]['classification'] = trim(substr($ThisFileInfo['RIFF']['WAVE']['cart'][0]['data'], 324, 64)); $ThisFileInfo['RIFF']['WAVE']['cart'][0]['out_cue'] = trim(substr($ThisFileInfo['RIFF']['WAVE']['cart'][0]['data'], 388, 64)); $ThisFileInfo['RIFF']['WAVE']['cart'][0]['start_date'] = trim(substr($ThisFileInfo['RIFF']['WAVE']['cart'][0]['data'], 452, 10)); $ThisFileInfo['RIFF']['WAVE']['cart'][0]['start_time'] = trim(substr($ThisFileInfo['RIFF']['WAVE']['cart'][0]['data'], 462, 8)); $ThisFileInfo['RIFF']['WAVE']['cart'][0]['end_date'] = trim(substr($ThisFileInfo['RIFF']['WAVE']['cart'][0]['data'], 470, 10)); $ThisFileInfo['RIFF']['WAVE']['cart'][0]['end_time'] = trim(substr($ThisFileInfo['RIFF']['WAVE']['cart'][0]['data'], 480, 8)); $ThisFileInfo['RIFF']['WAVE']['cart'][0]['producer_app_id'] = trim(substr($ThisFileInfo['RIFF']['WAVE']['cart'][0]['data'], 488, 64)); $ThisFileInfo['RIFF']['WAVE']['cart'][0]['producer_app_version'] = trim(substr($ThisFileInfo['RIFF']['WAVE']['cart'][0]['data'], 552, 64)); $ThisFileInfo['RIFF']['WAVE']['cart'][0]['user_defined_text'] = trim(substr($ThisFileInfo['RIFF']['WAVE']['cart'][0]['data'], 616, 64)); $ThisFileInfo['RIFF']['WAVE']['cart'][0]['zero_db_reference'] = LittleEndian2Int(substr($ThisFileInfo['RIFF']['WAVE']['cart'][0]['data'], 680, 4), true); for ($i = 0; $i < 8; $i++) { $ThisFileInfo['RIFF']['WAVE']['cart'][0]['post_time'][$i]['usage_fourcc'] = substr($ThisFileInfo['RIFF']['WAVE']['cart'][0]['data'], 684 + $i * 8, 4); $ThisFileInfo['RIFF']['WAVE']['cart'][0]['post_time'][$i]['timer_value'] = LittleEndian2Int(substr($ThisFileInfo['RIFF']['WAVE']['cart'][0]['data'], 684 + $i * 8 + 4, 4)); } $ThisFileInfo['RIFF']['WAVE']['cart'][0]['url'] = trim(substr($ThisFileInfo['RIFF']['WAVE']['cart'][0]['data'], 748, 1024)); $ThisFileInfo['RIFF']['WAVE']['cart'][0]['tag_text'] = explode("\r\n", trim(substr($ThisFileInfo['RIFF']['WAVE']['cart'][0]['data'], 1772))); $ThisFileInfo['RIFF']['comments']['artist'][] = $ThisFileInfo['RIFF']['WAVE']['cart'][0]['artist']; $ThisFileInfo['RIFF']['comments']['title'][] = $ThisFileInfo['RIFF']['WAVE']['cart'][0]['title']; } 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']); } if (!empty($ThisFileInfo['wavpack'])) { $ThisFileInfo['audio']['dataformat'] = 'wavpack'; $ThisFileInfo['audio']['bitrate_mode'] = 'vbr'; $ThisFileInfo['audio']['encoder'] = 'WavPack v' . $ThisFileInfo['wavpack']['version']; // Reset to the way it was - RIFF parsing will have messed this up $ThisFileInfo['avdataend'] = $Original['avdataend']; $ThisFileInfo['audio']['bitrate'] = ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8 / $ThisFileInfo['playtime_seconds']; fseek($fd, $ThisFileInfo['avdataoffset'] - 44, SEEK_SET); $RIFFdata = fread($fd, 44); $OrignalRIFFheaderSize = LittleEndian2Int(substr($RIFFdata, 4, 4)) + 8; $OrignalRIFFdataSize = LittleEndian2Int(substr($RIFFdata, 40, 4)) + 44; if ($OrignalRIFFheaderSize > $OrignalRIFFdataSize) { $ThisFileInfo['avdataend'] -= $OrignalRIFFheaderSize - $OrignalRIFFdataSize; fseek($fd, $ThisFileInfo['avdataend'], SEEK_SET); $RIFFdata .= fread($fd, $OrignalRIFFheaderSize - $OrignalRIFFdataSize); } // move the data chunk after all other chunks (if any) // so that the RIFF parser doesn't see EOF when trying // to skip over the data chunk $RIFFdata = substr($RIFFdata, 0, 36) . substr($RIFFdata, 44) . substr($RIFFdata, 36, 8); ParseRIFFdata($RIFFdata, $ThisFileInfo); } break; case 'AVI ': $ThisFileInfo['video']['bitrate_mode'] = 'cbr'; $ThisFileInfo['video']['dataformat'] = 'avi'; $ThisFileInfo['mime_type'] = 'video/avi'; if (isset($ThisFileInfo['RIFF'][$arraykeys[0]]['movi']['offset'])) { $ThisFileInfo['avdataoffset'] = $ThisFileInfo['RIFF'][$arraykeys[0]]['movi']['offset'] + 8; $ThisFileInfo['avdataend'] = $ThisFileInfo['avdataoffset'] + $ThisFileInfo['RIFF'][$arraykeys[0]]['movi']['size']; } if (isset($ThisFileInfo['RIFF']['AVI ']['hdrl']['avih'][$streamindex]['data'])) { $avihData = $ThisFileInfo['RIFF']['AVI ']['hdrl']['avih'][$streamindex]['data']; $ThisFileInfo['RIFF']['raw']['avih']['dwMicroSecPerFrame'] = EitherEndian2Int($ThisFileInfo, 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'] = EitherEndian2Int($ThisFileInfo, substr($avihData, 4, 4)); // max. transfer rate $ThisFileInfo['RIFF']['raw']['avih']['dwPaddingGranularity'] = EitherEndian2Int($ThisFileInfo, substr($avihData, 8, 4)); // pad to multiples of this size; normally 2K. $ThisFileInfo['RIFF']['raw']['avih']['dwFlags'] = EitherEndian2Int($ThisFileInfo, substr($avihData, 12, 4)); // the ever-present flags $ThisFileInfo['RIFF']['raw']['avih']['dwTotalFrames'] = EitherEndian2Int($ThisFileInfo, substr($avihData, 16, 4)); // # frames in file $ThisFileInfo['RIFF']['raw']['avih']['dwInitialFrames'] = EitherEndian2Int($ThisFileInfo, substr($avihData, 20, 4)); $ThisFileInfo['RIFF']['raw']['avih']['dwStreams'] = EitherEndian2Int($ThisFileInfo, substr($avihData, 24, 4)); $ThisFileInfo['RIFF']['raw']['avih']['dwSuggestedBufferSize'] = EitherEndian2Int($ThisFileInfo, substr($avihData, 28, 4)); $ThisFileInfo['RIFF']['raw']['avih']['dwWidth'] = EitherEndian2Int($ThisFileInfo, substr($avihData, 32, 4)); $ThisFileInfo['RIFF']['raw']['avih']['dwHeight'] = EitherEndian2Int($ThisFileInfo, substr($avihData, 36, 4)); $ThisFileInfo['RIFF']['raw']['avih']['dwScale'] = EitherEndian2Int($ThisFileInfo, substr($avihData, 40, 4)); $ThisFileInfo['RIFF']['raw']['avih']['dwRate'] = EitherEndian2Int($ThisFileInfo, substr($avihData, 44, 4)); $ThisFileInfo['RIFF']['raw']['avih']['dwStart'] = EitherEndian2Int($ThisFileInfo, substr($avihData, 48, 4)); $ThisFileInfo['RIFF']['raw']['avih']['dwLength'] = EitherEndian2Int($ThisFileInfo, 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); if ($ThisFileInfo['RIFF']['raw']['avih']['dwWidth'] > 0) { $ThisFileInfo['RIFF']['video'][$streamindex]['frame_width'] = $ThisFileInfo['RIFF']['raw']['avih']['dwWidth']; $ThisFileInfo['video']['resolution_x'] = $ThisFileInfo['RIFF']['video'][$streamindex]['frame_width']; } if ($ThisFileInfo['RIFF']['raw']['avih']['dwHeight'] > 0) { $ThisFileInfo['RIFF']['video'][$streamindex]['frame_height'] = $ThisFileInfo['RIFF']['raw']['avih']['dwHeight']; $ThisFileInfo['video']['resolution_y'] = $ThisFileInfo['RIFF']['video'][$streamindex]['frame_height']; } $ThisFileInfo['RIFF']['video'][$streamindex]['frame_rate'] = round(1000000 / $ThisFileInfo['RIFF']['raw']['avih']['dwMicroSecPerFrame'], 3); $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]); $ThisFileInfo['audio']['lossless'] = false; switch ($ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['wFormatTag']) { case 1: // PCM $ThisFileInfo['audio']['lossless'] = true; break; case 85: // MPEG Layer 3 $ThisFileInfo['audio']['dataformat'] = 'mp3'; break; case 8192: // AC-3 $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'] = EitherEndian2Int($ThisFileInfo, substr($strhData, 8, 4)); // Contains AVITF_* flags $ThisFileInfo['RIFF']['raw']['strh'][$i]['wPriority'] = EitherEndian2Int($ThisFileInfo, substr($strhData, 12, 2)); $ThisFileInfo['RIFF']['raw']['strh'][$i]['wLanguage'] = EitherEndian2Int($ThisFileInfo, substr($strhData, 14, 2)); $ThisFileInfo['RIFF']['raw']['strh'][$i]['dwInitialFrames'] = EitherEndian2Int($ThisFileInfo, substr($strhData, 16, 4)); $ThisFileInfo['RIFF']['raw']['strh'][$i]['dwScale'] = EitherEndian2Int($ThisFileInfo, substr($strhData, 20, 4)); $ThisFileInfo['RIFF']['raw']['strh'][$i]['dwRate'] = EitherEndian2Int($ThisFileInfo, substr($strhData, 24, 4)); $ThisFileInfo['RIFF']['raw']['strh'][$i]['dwStart'] = EitherEndian2Int($ThisFileInfo, substr($strhData, 28, 4)); $ThisFileInfo['RIFF']['raw']['strh'][$i]['dwLength'] = EitherEndian2Int($ThisFileInfo, substr($strhData, 32, 4)); $ThisFileInfo['RIFF']['raw']['strh'][$i]['dwSuggestedBufferSize'] = EitherEndian2Int($ThisFileInfo, substr($strhData, 36, 4)); $ThisFileInfo['RIFF']['raw']['strh'][$i]['dwQuality'] = EitherEndian2Int($ThisFileInfo, substr($strhData, 40, 4)); $ThisFileInfo['RIFF']['raw']['strh'][$i]['dwSampleSize'] = EitherEndian2Int($ThisFileInfo, substr($strhData, 44, 4)); $ThisFileInfo['RIFF']['raw']['strh'][$i]['rcFrame'] = EitherEndian2Int($ThisFileInfo, 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 ($ThisFileInfo['RIFF']['raw']['strh'][$i]['fccHandler']) { case 'HFYU': // Huffman Lossless Codec // Huffman Lossless Codec case 'IRAW': // Intel YUV Uncompressed // Intel YUV Uncompressed case 'YUY2': // Uncompressed YUV 4:2:2 $ThisFileInfo['video']['lossless'] = true; break; default: $ThisFileInfo['video']['lossless'] = false; break; } switch ($strhfccType) { case 'vids': $ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['biSize'] = EitherEndian2Int($ThisFileInfo, substr($strfData, 0, 4)); // number of bytes required by the BITMAPINFOHEADER structure $ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['biWidth'] = EitherEndian2Int($ThisFileInfo, substr($strfData, 4, 4)); // width of the bitmap in pixels $ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['biHeight'] = EitherEndian2Int($ThisFileInfo, 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'] = EitherEndian2Int($ThisFileInfo, 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'] = EitherEndian2Int($ThisFileInfo, 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'] = EitherEndian2Int($ThisFileInfo, 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'] = EitherEndian2Int($ThisFileInfo, substr($strfData, 24, 4)); // horizontal resolution, in pixels per metre, of the target device $ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['biYPelsPerMeter'] = EitherEndian2Int($ThisFileInfo, substr($strfData, 28, 4)); // vertical resolution, in pixels per metre, of the target device $ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['biClrUsed'] = EitherEndian2Int($ThisFileInfo, 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'] = EitherEndian2Int($ThisFileInfo, 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 $ThisFileInfo['video']['bits_per_sample'] = $ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['biBitCount']; 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']; switch ($ThisFileInfo['RIFF']['raw']['strf']["{$strhfccType}"][$streamindex]['fourcc']) { case 'HFYU': // Huffman Lossless Codec // Huffman Lossless Codec case 'IRAW': // Intel YUV Uncompressed // Intel YUV Uncompressed case 'YUY2': // Uncompressed YUV 4:2:2 $ThisFileInfo['video']['lossless'] = true; $ThisFileInfo['video']['bits_per_sample'] = 24; break; default: $ThisFileInfo['video']['lossless'] = false; $ThisFileInfo['video']['bits_per_sample'] = 24; break; } } } } } break; case 'CDDA': $ThisFileInfo['audio']['bitrate_mode'] = 'cbr'; $ThisFileInfo['audio']['dataformat'] = 'cda'; $ThisFileInfo['audio']['lossless'] = true; unset($ThisFileInfo['mime_type']); $ThisFileInfo['avdataoffset'] = 44; if (isset($ThisFileInfo['RIFF']['CDDA']['fmt '][0]['data'])) { $fmtData = $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['data']; $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['unknown1'] = EitherEndian2Int($ThisFileInfo, substr($fmtData, 0, 2)); $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['track_num'] = EitherEndian2Int($ThisFileInfo, substr($fmtData, 2, 2)); $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['disc_id'] = EitherEndian2Int($ThisFileInfo, substr($fmtData, 4, 4)); $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['start_offset_frame'] = EitherEndian2Int($ThisFileInfo, substr($fmtData, 8, 4)); $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['playtime_frames'] = EitherEndian2Int($ThisFileInfo, substr($fmtData, 12, 4)); $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['unknown6'] = EitherEndian2Int($ThisFileInfo, substr($fmtData, 16, 4)); $ThisFileInfo['RIFF']['CDDA']['fmt '][0]['unknown7'] = EitherEndian2Int($ThisFileInfo, 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; case 'AIFF': case 'AIFC': $ThisFileInfo['audio']['bitrate_mode'] = 'cbr'; $ThisFileInfo['audio']['dataformat'] = 'aiff'; $ThisFileInfo['audio']['lossless'] = true; $ThisFileInfo['mime_type'] = 'audio/x-aiff'; if (isset($ThisFileInfo['RIFF'][$arraykeys[0]]['SSND'][0]['offset'])) { $ThisFileInfo['avdataoffset'] = $ThisFileInfo['RIFF'][$arraykeys[0]]['SSND'][0]['offset'] + 8; $ThisFileInfo['avdataend'] = $ThisFileInfo['avdataoffset'] + $ThisFileInfo['RIFF'][$arraykeys[0]]['SSND'][0]['size']; if ($ThisFileInfo['avdataend'] > $ThisFileInfo['filesize']) { if ($ThisFileInfo['avdataend'] == $ThisFileInfo['filesize'] + 1 && $ThisFileInfo['filesize'] % 2 == 1) { // structures rounded to 2-byte boundary, but dumb encoders // forget to pad end of file to make this actually work } else { $ThisFileInfo['warning'] .= "\n" . 'Probable truncated AIFF file: expecting ' . $ThisFileInfo['RIFF'][$arraykeys[0]]['SSND'][0]['size'] . ' bytes of audio data, only ' . ($ThisFileInfo['filesize'] - $ThisFileInfo['avdataoffset']) . ' bytes found'; } $ThisFileInfo['avdataend'] = $ThisFileInfo['filesize']; } } if (isset($ThisFileInfo['RIFF'][$arraykeys[0]]['COMM'][0]['data'])) { $ThisFileInfo['RIFF']['audio']['channels'] = BigEndian2Int(substr($ThisFileInfo['RIFF'][$arraykeys[0]]['COMM'][0]['data'], 0, 2), true); $ThisFileInfo['RIFF']['audio']['total_samples'] = BigEndian2Int(substr($ThisFileInfo['RIFF'][$arraykeys[0]]['COMM'][0]['data'], 2, 4), false); $ThisFileInfo['RIFF']['audio']['bits_per_sample'] = BigEndian2Int(substr($ThisFileInfo['RIFF'][$arraykeys[0]]['COMM'][0]['data'], 6, 2), true); $ThisFileInfo['RIFF']['audio']['sample_rate'] = (int) BigEndian2Float(substr($ThisFileInfo['RIFF'][$arraykeys[0]]['COMM'][0]['data'], 8, 10)); if ($ThisFileInfo['RIFF'][$arraykeys[0]]['COMM'][0]['size'] > 18) { $ThisFileInfo['RIFF']['audio']['codec_fourcc'] = substr($ThisFileInfo['RIFF'][$arraykeys[0]]['COMM'][0]['data'], 18, 4); $CodecNameSize = BigEndian2Int(substr($ThisFileInfo['RIFF'][$arraykeys[0]]['COMM'][0]['data'], 22, 1), false); $ThisFileInfo['RIFF']['audio']['codec_name'] = substr($ThisFileInfo['RIFF'][$arraykeys[0]]['COMM'][0]['data'], 23, $CodecNameSize); if ($ThisFileInfo['RIFF']['audio']['codec_name'] == 'NONE') { $ThisFileInfo['audio']['codec'] = 'Pulse Code Modulation (PCM)'; $ThisFileInfo['audio']['lossless'] = true; } else { $ThisFileInfo['audio']['codec'] = $ThisFileInfo['RIFF']['audio']['codec_name']; $ThisFileInfo['audio']['lossless'] = false; } } $ThisFileInfo['audio']['channels'] = $ThisFileInfo['RIFF']['audio']['channels']; if ($ThisFileInfo['RIFF']['audio']['bits_per_sample'] > 0) { $ThisFileInfo['audio']['bits_per_sample'] = $ThisFileInfo['RIFF']['audio']['bits_per_sample']; } $ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['RIFF']['audio']['sample_rate']; if ($ThisFileInfo['audio']['sample_rate'] == 0) { $ThisFileInfo['error'] .= "\n" . 'Corrupted AIFF file: sample_rate == zero'; return false; } $ThisFileInfo['playtime_seconds'] = $ThisFileInfo['RIFF']['audio']['total_samples'] / $ThisFileInfo['audio']['sample_rate']; } if (isset($ThisFileInfo['RIFF'][$arraykeys[0]]['COMT'])) { $offset = 0; $CommentCount = BigEndian2Int(substr($ThisFileInfo['RIFF'][$arraykeys[0]]['COMT'][0]['data'], $offset, 2), false); $offset += 2; for ($i = 0; $i < $CommentCount; $i++) { $ThisFileInfo['comments_raw'][$i]['timestamp'] = BigEndian2Int(substr($ThisFileInfo['RIFF'][$arraykeys[0]]['COMT'][0]['data'], $offset, 4), false); $offset += 4; $ThisFileInfo['comments_raw'][$i]['marker_id'] = BigEndian2Int(substr($ThisFileInfo['RIFF'][$arraykeys[0]]['COMT'][0]['data'], $offset, 2), true); $offset += 2; $CommentLength = BigEndian2Int(substr($ThisFileInfo['RIFF'][$arraykeys[0]]['COMT'][0]['data'], $offset, 2), false); $offset += 2; $ThisFileInfo['comments_raw'][$i]['comment'] = substr($ThisFileInfo['RIFF'][$arraykeys[0]]['COMT'][0]['data'], $offset, $CommentLength); $offset += $CommentLength; $ThisFileInfo['comments_raw'][$i]['timestamp_unix'] = DateMac2Unix($ThisFileInfo['comments_raw'][$i]['timestamp']); $ThisFileInfo['RIFF']['comments']['comment'][] = $ThisFileInfo['comments_raw'][$i]['comment']; } } $CommentsChunkNames = array('NAME' => 'title', 'author' => 'artist', '(c) ' => 'copyright', 'ANNO' => 'comment'); foreach ($CommentsChunkNames as $key => $value) { if (isset($ThisFileInfo['RIFF'][$arraykeys[0]][$key][0]['data'])) { $ThisFileInfo['RIFF']['comments'][$value][] = $ThisFileInfo['RIFF'][$arraykeys[0]][$key][0]['data']; } } if (isset($ThisFileInfo['RIFF']['comments'])) { CopyFormatCommentsToRootComments($ThisFileInfo['RIFF']['comments'], $ThisFileInfo, true, true, true); } break; case '8SVX': $ThisFileInfo['audio']['bitrate_mode'] = 'cbr'; $ThisFileInfo['audio']['dataformat'] = '8svx'; $ThisFileInfo['audio']['bits_per_sample'] = 8; $ThisFileInfo['audio']['channels'] = 1; // overridden below, if need be $ThisFileInfo['mime_type'] = 'audio/x-aiff'; if (isset($ThisFileInfo['RIFF'][$arraykeys[0]]['BODY'][0]['offset'])) { $ThisFileInfo['avdataoffset'] = $ThisFileInfo['RIFF'][$arraykeys[0]]['BODY'][0]['offset'] + 8; $ThisFileInfo['avdataend'] = $ThisFileInfo['avdataoffset'] + $ThisFileInfo['RIFF'][$arraykeys[0]]['BODY'][0]['size']; if ($ThisFileInfo['avdataend'] > $ThisFileInfo['filesize']) { $ThisFileInfo['warning'] .= "\n" . 'Probable truncated AIFF file: expecting ' . $ThisFileInfo['RIFF'][$arraykeys[0]]['BODY'][0]['size'] . ' bytes of audio data, only ' . ($ThisFileInfo['filesize'] - $ThisFileInfo['avdataoffset']) . ' bytes found'; } } if (isset($ThisFileInfo['RIFF'][$arraykeys[0]]['VHDR'][0]['offset'])) { $ThisFileInfo['RIFF'][$arraykeys[0]]['VHDR'][0]['oneShotHiSamples'] = BigEndian2Int(substr($ThisFileInfo['RIFF'][$arraykeys[0]]['VHDR'][0]['data'], 0, 4)); $ThisFileInfo['RIFF'][$arraykeys[0]]['VHDR'][0]['repeatHiSamples'] = BigEndian2Int(substr($ThisFileInfo['RIFF'][$arraykeys[0]]['VHDR'][0]['data'], 4, 4)); $ThisFileInfo['RIFF'][$arraykeys[0]]['VHDR'][0]['samplesPerHiCycle'] = BigEndian2Int(substr($ThisFileInfo['RIFF'][$arraykeys[0]]['VHDR'][0]['data'], 8, 4)); $ThisFileInfo['RIFF'][$arraykeys[0]]['VHDR'][0]['samplesPerSec'] = BigEndian2Int(substr($ThisFileInfo['RIFF'][$arraykeys[0]]['VHDR'][0]['data'], 12, 2)); $ThisFileInfo['RIFF'][$arraykeys[0]]['VHDR'][0]['ctOctave'] = BigEndian2Int(substr($ThisFileInfo['RIFF'][$arraykeys[0]]['VHDR'][0]['data'], 14, 1)); $ThisFileInfo['RIFF'][$arraykeys[0]]['VHDR'][0]['sCompression'] = BigEndian2Int(substr($ThisFileInfo['RIFF'][$arraykeys[0]]['VHDR'][0]['data'], 15, 1)); $ThisFileInfo['RIFF'][$arraykeys[0]]['VHDR'][0]['Volume'] = FixedPoint16_16(substr($ThisFileInfo['RIFF'][$arraykeys[0]]['VHDR'][0]['data'], 16, 4)); $ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['RIFF'][$arraykeys[0]]['VHDR'][0]['samplesPerSec']; switch ($ThisFileInfo['RIFF'][$arraykeys[0]]['VHDR'][0]['sCompression']) { case 0: $ThisFileInfo['audio']['codec'] = 'Pulse Code Modulation (PCM)'; $ThisFileInfo['audio']['lossless'] = true; $ActualBitsPerSample = 8; break; case 1: $ThisFileInfo['audio']['codec'] = 'Fibonacci-delta encoding'; $ThisFileInfo['audio']['lossless'] = false; $ActualBitsPerSample = 4; break; default: $ThisFileInfo['warning'] .= "\n" . 'Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "' . sCompression . '"'; break; } } if (isset($ThisFileInfo['RIFF'][$arraykeys[0]]['CHAN'][0]['data'])) { $ChannelsIndex = BigEndian2Int(substr($ThisFileInfo['RIFF'][$arraykeys[0]]['CHAN'][0]['data'], 0, 4)); switch ($ChannelsIndex) { case 6: // Stereo $ThisFileInfo['audio']['channels'] = 2; break; case 2: // Left channel only // Left channel only case 4: // Right channel only $ThisFileInfo['audio']['channels'] = 1; break; default: $ThisFileInfo['warning'] .= "\n" . 'Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "' . $ChannelsIndex . '"'; break; } } $CommentsChunkNames = array('NAME' => 'title', 'author' => 'artist', '(c) ' => 'copyright', 'ANNO' => 'comment'); foreach ($CommentsChunkNames as $key => $value) { if (isset($ThisFileInfo['RIFF'][$arraykeys[0]][$key][0]['data'])) { $ThisFileInfo['RIFF']['comments'][$value][] = $ThisFileInfo['RIFF'][$arraykeys[0]][$key][0]['data']; } } if (isset($ThisFileInfo['RIFF']['comments'])) { CopyFormatCommentsToRootComments($ThisFileInfo['RIFF']['comments'], $ThisFileInfo, true, true, true); } $ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['audio']['sample_rate'] * $ActualBitsPerSample * $ThisFileInfo['audio']['channels']; if (!empty($ThisFileInfo['audio']['bitrate'])) { $ThisFileInfo['playtime_seconds'] = ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) / ($ThisFileInfo['audio']['bitrate'] / 8); } break; default: $ThisFileInfo['error'] .= "\n" . 'Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|), found "' . $arraykeys[0] . '" instead'; 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', 'ISFT' => 'encoded_by'); foreach ($RIFFinfoKeyLookup as $key => $value) { if (isset($ThisFileInfo['RIFF']['WAVE']['INFO']["{$key}"])) { 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, false, true); } if (empty($ThisFileInfo['audio']['encoder']) && !empty($ThisFileInfo['mpeg']['audio']['LAME']['short_version'])) { $ThisFileInfo['audio']['encoder'] = $ThisFileInfo['mpeg']['audio']['LAME']['short_version']; } 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['RIFF']['raw']['fmt ']['nBitsPerSample'] > 0) { $ThisFileInfo['audio']['bits_per_sample'] = $ThisFileInfo['RIFF']['raw']['fmt ']['nBitsPerSample']; } return true; }
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; }