: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
case 'Filter HP': // High-pass filter frequency in kHz
case 'Filter LP': // Low-pass filter frequency in kHz
case 'Humidity': // Relative humidity as a percentage
case 'Length': // Recording length in seconds
case 'Loc Accuracy': // Estimated Position Error in meters
case 'Temperature Ext': // External temperature in degrees Celsius outside the recorder's housing
case 'Temperature Int': // Internal temperature in degrees Celsius inside the recorder's housing
$thisfile_riff['guano'][$key] = (float) $value;
case 'Samplerate': // Recording sample rate, Hz
case 'TE': // Time-expansion factor. If not specified, then 1 (no time-expansion a.k.a. direct-recording) is assumed.
$thisfile_riff['guano'][$key] = (int) $value;
$this->warning('RIFF.guan data not in expected format');
if (!isset($thisfile_audio['bitrate']) && isset($thisfile_riff_audio[$streamindex]['bitrate'])) {
$thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
$info['playtime_seconds'] = (float)getid3_lib::SafeDiv((($info['avdataend'] - $info['avdataoffset']) * 8), $thisfile_audio['bitrate']);
if (!empty($info['wavpack'])) {
$thisfile_audio_dataformat = 'wavpack';
$thisfile_audio['bitrate_mode'] = 'vbr';
$thisfile_audio['encoder'] = 'WavPack v'.$info['wavpack']['version'];
// Reset to the way it was - RIFF parsing will have messed this up
$info['avdataend'] = $Original['avdataend'];
$thisfile_audio['bitrate'] = getid3_lib::SafeDiv(($info['avdataend'] - $info['avdataoffset']) * 8, $info['playtime_seconds']);
$this->fseek($info['avdataoffset'] - 44);
$RIFFdata = $this->fread(44);
$OrignalRIFFheaderSize = getid3_lib::LittleEndian2Int(substr($RIFFdata, 4, 4)) + 8;
$OrignalRIFFdataSize = getid3_lib::LittleEndian2Int(substr($RIFFdata, 40, 4)) + 44;
if ($OrignalRIFFheaderSize > $OrignalRIFFdataSize) {
$info['avdataend'] -= ($OrignalRIFFheaderSize - $OrignalRIFFdataSize);
$this->fseek($info['avdataend']);
$RIFFdata .= $this->fread($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);
$getid3_riff = new getid3_riff($this->getid3);
$getid3_riff->ParseRIFFdata($RIFFdata);
if (isset($thisfile_riff_raw['fmt ']['wFormatTag'])) {
switch ($thisfile_riff_raw['fmt ']['wFormatTag']) {
if (!empty($info['ac3'])) {
// Dolby Digital WAV files masquerade as PCM-WAV, but they're not
$thisfile_audio['wformattag'] = 0x2000;
$thisfile_audio['codec'] = self::wFormatTagLookup($thisfile_audio['wformattag']);
$thisfile_audio['lossless'] = false;
$thisfile_audio['bitrate'] = $info['ac3']['bitrate'];
$thisfile_audio['sample_rate'] = $info['ac3']['sample_rate'];
if (!empty($info['dts'])) {
// Dolby DTS files masquerade as PCM-WAV, but they're not
$thisfile_audio['wformattag'] = 0x2001;
$thisfile_audio['codec'] = self::wFormatTagLookup($thisfile_audio['wformattag']);
$thisfile_audio['lossless'] = false;
$thisfile_audio['bitrate'] = $info['dts']['bitrate'];
$thisfile_audio['sample_rate'] = $info['dts']['sample_rate'];
case 0x08AE: // ClearJump LiteWave
$thisfile_audio['bitrate_mode'] = 'vbr';
$thisfile_audio_dataformat = 'litewave';
//typedef struct tagSLwFormat {
// WORD m_wCompFormat; // low byte defines compression method, high byte is compression flags
// DWORD m_dwScale; // scale factor for lossy compression
// DWORD m_dwBlockSize; // number of samples in encoded blocks
// WORD m_wQuality; // alias for the scale factor
// WORD m_wMarkDistance; // distance between marks in bytes
// //following paramters are ignored if CF_FILESRC is not set
// DWORD m_dwOrgSize; // original file size in bytes
// WORD m_bFactExists; // indicates if 'fact' chunk exists in the original file
// DWORD m_dwRiffChunkSize; // riff chunk size in the original file
// PCMWAVEFORMAT m_OrgWf; // original wave format
// }SLwFormat, *PSLwFormat;
$thisfile_riff['litewave']['raw'] = array();
$riff_litewave = &$thisfile_riff['litewave'];
$riff_litewave_raw = &$riff_litewave['raw'];
'compression_method' => 1,
'compression_flags' => 1,
'm_dwRiffChunkSize' => 4,
foreach ($flags as $flag => $length) {
$riff_litewave_raw[$flag] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE['fmt '][0]['data'], $litewave_offset, $length));
$litewave_offset += $length;
//$riff_litewave['quality_factor'] = intval(round((2000 - $riff_litewave_raw['m_dwScale']) / 20));
$riff_litewave['quality_factor'] = $riff_litewave_raw['m_wQuality'];
$riff_litewave['flags']['raw_source'] = ($riff_litewave_raw['compression_flags'] & 0x01) ? false : true;
$riff_litewave['flags']['vbr_blocksize'] = ($riff_litewave_raw['compression_flags'] & 0x02) ? false : true;
$riff_litewave['flags']['seekpoints'] = (bool) ($riff_litewave_raw['compression_flags'] & 0x04);
$thisfile_audio['lossless'] = (($riff_litewave_raw['m_wQuality'] == 100) ? true : false);
$thisfile_audio['encoder_options'] = '-q'.$riff_litewave['quality_factor'];
if ($info['avdataend'] > $info['filesize']) {
switch ($thisfile_audio_dataformat) {
case 'wavpack': // WavPack
case 'ofs': // OptimFROG DualStream
// lossless compressed audio formats that keep original RIFF headers - skip warning
if (($info['avdataend'] - $info['filesize']) == 1) {
// LiteWave appears to incorrectly *not* pad actual output file
// to nearest WORD boundary so may appear to be short by one
// byte, in which case - skip warning
// Short by more than one byte, throw warning
$this->warning('Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)');
$info['avdataend'] = $info['filesize'];
if ((($info['avdataend'] - $info['filesize']) == 1) && (($thisfile_riff[$RIFFsubtype]['data'][0]['size'] % 2) == 0) && ((($info['filesize'] - $info['avdataoffset']) % 2) == 1)) {
// output file appears to be incorrectly *not* padded to nearest WORD boundary
// Output less severe warning
$this->warning('File should probably be padded to nearest WORD boundary, but it is not (expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' therefore short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)');
$info['avdataend'] = $info['filesize'];
// Short by more than one byte, throw warning
$this->warning('Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)');
$info['avdataend'] = $info['filesize'];
if (!empty($info['mpeg']['audio']['LAME']['audio_bytes'])) {
if ((($info['avdataend'] - $info['avdataoffset']) - $info['mpeg']['audio']['LAME']['audio_bytes']) == 1) {
$this->warning('Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored');
if ($thisfile_audio_dataformat == 'ac3') {
unset($thisfile_audio['bits_per_sample']);
if (!empty($info['ac3']['bitrate']) && ($info['ac3']['bitrate'] != $thisfile_audio['bitrate'])) {
$thisfile_audio['bitrate'] = $info['ac3']['bitrate'];
// http://en.wikipedia.org/wiki/Audio_Video_Interleave
$info['fileformat'] = 'avi';
$info['mime_type'] = 'video/avi';
$thisfile_video['bitrate_mode'] = 'vbr'; // maybe not, but probably
$thisfile_video['dataformat'] = 'avi';
$thisfile_riff_video_current = array();
if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) {
$info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['movi']['offset'] + 8;
if (isset($thisfile_riff['AVIX'])) {
$info['avdataend'] = $thisfile_riff['AVIX'][(count($thisfile_riff['AVIX']) - 1)]['chunks']['movi']['offset'] + $thisfile_riff['AVIX'][(count($thisfile_riff['AVIX']) - 1)]['chunks']['movi']['size'];
$info['avdataend'] = $thisfile_riff['AVI ']['movi']['offset'] + $thisfile_riff['AVI ']['movi']['size'];
if ($info['avdataend'] > $info['filesize']) {
$this->warning('Probably truncated file - expecting '.($info['avdataend'] - $info['avdataoffset']).' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($info['avdataend'] - $info['filesize']).' bytes)');
$info['avdataend'] = $info['filesize'];
if (isset($thisfile_riff['AVI ']['hdrl']['strl']['indx'])) {
// 0x00 => 'AVI_INDEX_OF_INDEXES',
// 0x01 => 'AVI_INDEX_OF_CHUNKS',
// 0x80 => 'AVI_INDEX_IS_DATA',
//$bIndexSubtype = array(
// 0x01 => 'AVI_INDEX_2FIELD',
foreach ($thisfile_riff['AVI ']['hdrl']['strl']['indx'] as $streamnumber => $steamdataarray) {
$ahsisd = &$thisfile_riff['AVI ']['hdrl']['strl']['indx'][$streamnumber]['data'];
$thisfile_riff_raw['indx'][$streamnumber]['wLongsPerEntry'] = $this->EitherEndian2Int(substr($ahsisd, 0, 2));
$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType'] = $this->EitherEndian2Int(substr($ahsisd, 2, 1));
$thisfile_riff_raw['indx'][$streamnumber]['bIndexType'] = $this->EitherEndian2Int(substr($ahsisd, 3, 1));
$thisfile_riff_raw['indx'][$streamnumber]['nEntriesInUse'] = $this->EitherEndian2Int(substr($ahsisd, 4, 4));
$thisfile_riff_raw['indx'][$streamnumber]['dwChunkId'] = substr($ahsisd, 8, 4);
$thisfile_riff_raw['indx'][$streamnumber]['dwReserved'] = $this->EitherEndian2Int(substr($ahsisd, 12, 4));
//$thisfile_riff_raw['indx'][$streamnumber]['bIndexType_name'] = $bIndexType[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']];
//$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType_name'] = $bIndexSubtype[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']][$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType']];
if (isset($thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'])) {
$avihData = $thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'];
$thisfile_riff_raw['avih'] = array();
$thisfile_riff_raw_avih = &$thisfile_riff_raw['avih'];
$thisfile_riff_raw_avih['dwMicroSecPerFrame'] = $this->EitherEndian2Int(substr($avihData, 0, 4)); // frame display rate (or 0L)
if ($thisfile_riff_raw_avih['dwMicroSecPerFrame'] == 0) {
$this->error('Corrupt RIFF file: avih.dwMicroSecPerFrame == zero');
'dwMaxBytesPerSec', // max. transfer rate
'dwPaddingGranularity', // pad to multiples of this size; normally 2K.
'dwFlags', // the ever-present flags
'dwTotalFrames', // # frames in file
'dwSuggestedBufferSize', //
foreach ($flags as $flag) {
$thisfile_riff_raw_avih[$flag] = $this->EitherEndian2Int(substr($avihData, $avih_offset, 4));
'hasindex' => 0x00000010,
'mustuseindex' => 0x00000020,
'interleaved' => 0x00000100,
'trustcktype' => 0x00000800,
'capturedfile' => 0x00010000,
'copyrighted' => 0x00020010,
foreach ($flags as $flag => $value) {
$thisfile_riff_raw_avih['flags'][$flag] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & $value);
$thisfile_riff_video[$streamindex] = array();
/** @var array $thisfile_riff_video_current */
$thisfile_riff_video_current = &$thisfile_riff_video[$streamindex];
if ($thisfile_riff_raw_avih['dwWidth'] > 0) { // @phpstan-ignore-line
$thisfile_riff_video_current['frame_width'] = $thisfile_riff_raw_avih['dwWidth'];
$thisfile_video['resolution_x'] = $thisfile_riff_video_current['frame_width'];
if ($thisfile_riff_raw_avih['dwHeight'] > 0) { // @phpstan-ignore-line
$thisfile_riff_video_current['frame_height'] = $thisfile_riff_raw_avih['dwHeight'];
$thisfile_video['resolution_y'] = $thisfile_riff_video_current['frame_height'];
if ($thisfile_riff_raw_avih['dwTotalFrames'] > 0) { // @phpstan-ignore-line
$thisfile_riff_video_current['total_frames'] = $thisfile_riff_raw_avih['dwTotalFrames'];
$thisfile_video['total_frames'] = $thisfile_riff_video_current['total_frames'];
$thisfile_riff_video_current['frame_rate'] = round(1000000 / $thisfile_riff_raw_avih['dwMicroSecPerFrame'], 3);
$thisfile_video['frame_rate'] = $thisfile_riff_video_current['frame_rate'];
if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][0]['data'])) {
if (is_array($thisfile_riff['AVI ']['hdrl']['strl']['strh'])) {
$thisfile_riff_raw_strf_strhfccType_streamindex = null;
for ($i = 0; $i < count($thisfile_riff['AVI ']['hdrl']['strl']['strh']); $i++) {
if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'])) {
$strhData = $thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'];
$strhfccType = substr($strhData, 0, 4);
if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'])) {
$strfData = $thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'];
if (!isset($thisfile_riff_raw['strf'][$strhfccType][$streamindex])) {
$thisfile_riff_raw['strf'][$strhfccType][$streamindex] = null;
$thisfile_riff_raw_strf_strhfccType_streamindex = &$thisfile_riff_raw['strf'][$strhfccType][$streamindex];
$thisfile_audio['bitrate_mode'] = 'cbr';
$thisfile_audio_dataformat = 'wav';
if (isset($thisfile_riff_audio) && is_array($thisfile_riff_audio)) {
$streamindex = count($thisfile_riff_audio);
$thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($strfData);
$thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
$thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
$thisfile_audio_streams_currentstream = &$thisfile_audio['streams'][$streamindex];
if ($thisfile_audio_streams_currentstream['bits_per_sample'] == 0) {
unset($thisfile_audio_streams_currentstream['bits_per_sample']);
$thisfile_audio_streams_currentstream['wformattag'] = $thisfile_audio_streams_currentstream['raw']['wFormatTag'];
unset($thisfile_audio_streams_currentstream['raw']);
$thisfile_riff_raw['strf'][$strhfccType][$streamindex] = $thisfile_riff_audio[$streamindex]['raw'];
unset($thisfile_riff_audio[$streamindex]['raw']);
$thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
$thisfile_audio['lossless'] = false;
switch ($thisfile_riff_raw_strf_strhfccType_streamindex['wFormatTag']) {
$thisfile_audio_dataformat = 'wav';
$thisfile_audio['lossless'] = true;
case 0x0050: // MPEG Layer 2 or Layer 1
$thisfile_audio_dataformat = 'mp2'; // Assume Layer-2
case 0x0055: // MPEG Layer 3
$thisfile_audio_dataformat = 'mp3';
$thisfile_audio_dataformat = 'aac';
case 0x0161: // Windows Media v7 / v8 / v9
case 0x0162: // Windows Media Professional v9
case 0x0163: // Windows Media Lossess v9
$thisfile_audio_dataformat = 'wma';
$thisfile_audio_dataformat = 'ac3';
$thisfile_audio_dataformat = 'dts';
$thisfile_audio_dataformat = 'wav';
$thisfile_audio_streams_currentstream['dataformat'] = $thisfile_audio_dataformat;
$thisfile_audio_streams_currentstream['lossless'] = $thisfile_audio['lossless'];
$thisfile_audio_streams_currentstream['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
$thisfile_riff_raw['strh'][$i] = array();
$thisfile_riff_raw_strh_current = &$thisfile_riff_raw['strh'][$i];
$thisfile_riff_raw_strh_current['fccType'] = substr($strhData, 0, 4); // same as $strhfccType;
$thisfile_riff_raw_strh_current['fccHandler'] = substr($strhData, 4, 4);
$thisfile_riff_raw_strh_current['dwFlags'] = $this->EitherEndian2Int(substr($strhData, 8, 4)); // Contains AVITF_* flags
$thisfile_riff_raw_strh_current['wPriority'] = $this->EitherEndian2Int(substr($strhData, 12, 2));
$thisfile_riff_raw_strh_current['wLanguage'] = $this->EitherEndian2Int(substr($strhData, 14, 2));
$thisfile_riff_raw_strh_current['dwInitialFrames'] = $this->EitherEndian2Int(substr($strhData, 16, 4));
$thisfile_riff_raw_strh_current['dwScale'] = $this->EitherEndian2Int(substr($strhData, 20, 4));
$thisfile_riff_raw_strh_current['dwRate'] = $this->EitherEndian2Int(substr($strhData, 24, 4));
$thisfile_riff_raw_strh_current['dwStart'] = $this->EitherEndian2Int(substr($strhData, 28, 4));
$thisfile_riff_raw_strh_current['dwLength'] = $this->EitherEndian2Int(substr($strhData, 32, 4));
$thisfile_riff_raw_strh_current['dwSuggestedBufferSize'] = $this->EitherEndian2Int(substr($strhData, 36, 4));
$thisfile_riff_raw_strh_current['dwQuality'] = $this->EitherEndian2Int(substr($strhData, 40, 4));
$thisfile_riff_raw_strh_current['dwSampleSize'] = $this->EitherEndian2Int(substr($strhData, 44, 4));
$thisfile_riff_raw_strh_current['rcFrame'] = $this->EitherEndian2Int(substr($strhData, 48, 4));
$thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strh_current['fccHandler']);
$thisfile_video['fourcc'] = $thisfile_riff_raw_strh_current['fccHandler'];
if (!$thisfile_riff_video_current['codec'] && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) && self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
$thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']);
$thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
$thisfile_video['codec'] = $thisfile_riff_video_current['codec'];
$thisfile_video['pixel_aspect_ratio'] = (float) 1;
switch ($thisfile_riff_raw_strh_current['fccHandler']) {
case 'HFYU': // Huffman Lossless Codec
case 'IRAW': // Intel YUV Uncompressed
case 'YUY2': // Uncompressed YUV 4:2:2
$thisfile_video['lossless'] = true;
$thisfile_video['lossless'] = false;
$thisfile_riff_raw_strf_strhfccType_streamindex = self::ParseBITMAPINFOHEADER(substr($strfData, 0, 40), ($this->container == 'riff'));
$thisfile_video['bits_per_sample'] = $thisfile_riff_raw_strf_strhfccType_streamindex['biBitCount'];
if ($thisfile_riff_video_current['codec'] == 'DV') {
$thisfile_riff_video_current['dv_type'] = 2;
$thisfile_riff_video_current['dv_type'] = 1;
$this->warning('Unhandled fccType for stream ('.$i.'): "'.$strhfccType.'"');
if (isset($thisfile_riff_raw_strf_strhfccType_streamindex) && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
$thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
if (self::fourccLookup($thisfile_video['fourcc'])) {
$thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_video['fourcc']);
$thisfile_video['codec'] = $thisfile_riff_video_current['codec'];
switch ($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) {
case 'HFYU': // Huffman Lossless Codec
case 'IRAW': // Intel YUV Uncompressed
case 'YUY2': // Uncompressed YUV 4:2:2
$thisfile_video['lossless'] = true;
//$thisfile_video['bits_per_sample'] = 24;
$thisfile_video['lossless'] = false;
//$thisfile_video['bits_per_sample'] = 24;
$info['fileformat'] = 'amv';
$info['mime_type'] = 'video/amv';
$thisfile_video['bitrate_mode'] = 'vbr'; // it's MJPEG, presumably contant-quality encoding, thereby VBR
$thisfile_video['dataformat'] = 'mjpeg';
$thisfile_video['codec'] = 'mjpeg';
$thisfile_video['lossless'] = false;
$thisfile_video['bits_per_sample'] = 24;
$thisfile_audio['dataformat'] = 'adpcm';
$thisfile_audio['lossless'] = false;
// http://en.wikipedia.org/wiki/CD-DA
$info['fileformat'] = 'cda';
unset($info['mime_type']);