35 $info = &$this->getid3->info;
39 $info[
'riff'] = array(
'raw'=>array());
42 $thisfile_riff = &
$info[
'riff'];
43 $thisfile_riff_raw = &$thisfile_riff[
'raw'];
44 $thisfile_audio = &
$info[
'audio'];
45 $thisfile_video = &
$info[
'video'];
46 $thisfile_audio_dataformat = &$thisfile_audio[
'dataformat'];
47 $thisfile_riff_audio = &$thisfile_riff[
'audio'];
48 $thisfile_riff_video = &$thisfile_riff[
'video'];
50 $Original[
'avdataoffset'] =
$info[
'avdataoffset'];
51 $Original[
'avdataend'] =
$info[
'avdataend'];
54 $RIFFheader = $this->
fread(12);
55 $offset = $this->
ftell();
56 $RIFFtype = substr($RIFFheader, 0, 4);
57 $RIFFsize = substr($RIFFheader, 4, 4);
58 $RIFFsubtype = substr($RIFFheader, 8, 4);
64 $this->container =
'aiff';
66 $thisfile_riff[$RIFFsubtype] = $this->
ParseRIFF($offset, ($offset + $thisfile_riff[
'header_size'] - 4));
73 $this->container =
'riff';
75 if ($RIFFsubtype ==
'RMP3') {
77 $RIFFsubtype =
'WAVE';
79 if ($RIFFsubtype !=
'AMV ') {
82 $thisfile_riff[$RIFFsubtype] = $this->
ParseRIFF($offset, ($offset + $thisfile_riff[
'header_size'] - 4));
84 if ((
$info[
'avdataend'] -
$info[
'filesize']) == 1) {
91 $nextRIFFoffset = $Original[
'avdataoffset'] + 8 + $thisfile_riff[
'header_size'];
92 while ($nextRIFFoffset < min(
$info[
'filesize'],
$info[
'avdataend'])) {
94 $this->
fseek($nextRIFFoffset);
96 if ($e->getCode() == 10) {
98 $this->
error(
'AVI extends beyond '.round(PHP_INT_MAX / 1073741824).
'GB and PHP filesystem functions cannot read that far, playtime may be wrong');
99 $this->
warning(
'[avdataend] value may be incorrect, multiple AVIX chunks may be present');
105 $nextRIFFheader = $this->
fread(12);
106 if ($nextRIFFoffset == (
$info[
'avdataend'] - 1)) {
107 if (substr($nextRIFFheader, 0, 1) ==
"\x00") {
112 $nextRIFFheaderID = substr($nextRIFFheader, 0, 4);
114 $nextRIFFtype = substr($nextRIFFheader, 8, 4);
115 $chunkdata = array();
116 $chunkdata[
'offset'] = $nextRIFFoffset + 8;
117 $chunkdata[
'size'] = $nextRIFFsize;
118 $nextRIFFoffset = $chunkdata[
'offset'] + $chunkdata[
'size'];
120 switch ($nextRIFFheaderID) {
122 $chunkdata[
'chunks'] = $this->
ParseRIFF($chunkdata[
'offset'] + 4, $nextRIFFoffset);
123 if (!isset($thisfile_riff[$nextRIFFtype])) {
124 $thisfile_riff[$nextRIFFtype] = array();
126 $thisfile_riff[$nextRIFFtype][] = $chunkdata;
130 unset(
$info[
'riff']);
136 $thisfile_riff[$nextRIFFheaderID][] = $chunkdata;
140 $info[
'divxtag'][
'comments'] = self::ParseDIVXTAG($this->
fread($chunkdata[
'size']));
144 if (
$info[
'filesize'] == ($chunkdata[
'offset'] - 8 + 128)) {
145 $DIVXTAG = $nextRIFFheader.$this->fread(128 - 12);
146 if (substr($DIVXTAG, -7) ==
'DIVXTAG') {
148 $this->
warning(
'Found wrongly-structured DIVXTAG at offset '.($this->
ftell() - 128).
', parsing anyway');
149 $info[
'divxtag'][
'comments'] = self::ParseDIVXTAG($DIVXTAG);
153 $this->
warning(
'Expecting "RIFF|JUNK|IDVX" at '.$nextRIFFoffset.
', found "'.$nextRIFFheaderID.
'" ('.
getid3_lib::PrintHexBytes($nextRIFFheaderID).
') - skipping rest of file');
159 if ($RIFFsubtype ==
'WAVE') {
160 $thisfile_riff_WAVE = &$thisfile_riff[
'WAVE'];
165 $this->
error(
'Cannot parse RIFF (this is maybe not a RIFF / WAV / AVI file?) - expecting "FORM|RIFF|SDSS|RMP3" found "'.$RIFFsubtype.
'" instead');
171 switch ($RIFFsubtype) {
175 $info[
'fileformat'] =
'wav';
177 if (empty($thisfile_audio[
'bitrate_mode'])) {
178 $thisfile_audio[
'bitrate_mode'] =
'cbr';
180 if (empty($thisfile_audio_dataformat)) {
181 $thisfile_audio_dataformat =
'wav';
184 if (isset($thisfile_riff_WAVE[
'data'][0][
'offset'])) {
185 $info[
'avdataoffset'] = $thisfile_riff_WAVE[
'data'][0][
'offset'] + 8;
186 $info[
'avdataend'] =
$info[
'avdataoffset'] + $thisfile_riff_WAVE[
'data'][0][
'size'];
188 if (isset($thisfile_riff_WAVE[
'fmt '][0][
'data'])) {
190 $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($thisfile_riff_WAVE[
'fmt '][0][
'data']);
191 $thisfile_audio[
'wformattag'] = $thisfile_riff_audio[$streamindex][
'raw'][
'wFormatTag'];
192 if (!isset($thisfile_riff_audio[$streamindex][
'bitrate']) || ($thisfile_riff_audio[$streamindex][
'bitrate'] == 0)) {
193 $this->
error(
'Corrupt RIFF file: bitrate_audio == zero');
196 $thisfile_riff_raw[
'fmt '] = $thisfile_riff_audio[$streamindex][
'raw'];
197 unset($thisfile_riff_audio[$streamindex][
'raw']);
198 $thisfile_audio[
'streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
201 if (substr($thisfile_audio[
'codec'], 0, strlen(
'unknown: 0x')) ==
'unknown: 0x') {
202 $this->
warning(
'Audio codec = '.$thisfile_audio[
'codec']);
204 $thisfile_audio[
'bitrate'] = $thisfile_riff_audio[$streamindex][
'bitrate'];
206 if (empty(
$info[
'playtime_seconds'])) {
207 $info[
'playtime_seconds'] = (float) (((
$info[
'avdataend'] -
$info[
'avdataoffset']) * 8) / $thisfile_audio[
'bitrate']);
210 $thisfile_audio[
'lossless'] =
false;
211 if (isset($thisfile_riff_WAVE[
'data'][0][
'offset']) && isset($thisfile_riff_raw[
'fmt '][
'wFormatTag'])) {
212 switch ($thisfile_riff_raw[
'fmt '][
'wFormatTag']) {
215 $thisfile_audio[
'lossless'] =
true;
219 $thisfile_audio_dataformat =
'ac3';
228 $thisfile_audio[
'streams'][$streamindex][
'wformattag'] = $thisfile_audio[
'wformattag'];
229 $thisfile_audio[
'streams'][$streamindex][
'bitrate_mode'] = $thisfile_audio[
'bitrate_mode'];
230 $thisfile_audio[
'streams'][$streamindex][
'lossless'] = $thisfile_audio[
'lossless'];
231 $thisfile_audio[
'streams'][$streamindex][
'dataformat'] = $thisfile_audio_dataformat;
234 if (isset($thisfile_riff_WAVE[
'rgad'][0][
'data'])) {
237 $rgadData = &$thisfile_riff_WAVE[
'rgad'][0][
'data'];
238 $thisfile_riff_raw[
'rgad'] = array(
'track'=>array(),
'album'=>array());
239 $thisfile_riff_raw_rgad = &$thisfile_riff_raw[
'rgad'];
240 $thisfile_riff_raw_rgad_track = &$thisfile_riff_raw_rgad[
'track'];
241 $thisfile_riff_raw_rgad_album = &$thisfile_riff_raw_rgad[
'album'];
244 $thisfile_riff_raw_rgad[
'nRadioRgAdjust'] = $this->
EitherEndian2Int(substr($rgadData, 4, 2));
245 $thisfile_riff_raw_rgad[
'nAudiophileRgAdjust'] = $this->
EitherEndian2Int(substr($rgadData, 6, 2));
247 $nRadioRgAdjustBitstring = str_pad(
getid3_lib::Dec2Bin($thisfile_riff_raw_rgad[
'nRadioRgAdjust']), 16,
'0', STR_PAD_LEFT);
248 $nAudiophileRgAdjustBitstring = str_pad(
getid3_lib::Dec2Bin($thisfile_riff_raw_rgad[
'nAudiophileRgAdjust']), 16,
'0', STR_PAD_LEFT);
249 $thisfile_riff_raw_rgad_track[
'name'] =
getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 0, 3));
250 $thisfile_riff_raw_rgad_track[
'originator'] =
getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 3, 3));
251 $thisfile_riff_raw_rgad_track[
'signbit'] =
getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 6, 1));
252 $thisfile_riff_raw_rgad_track[
'adjustment'] =
getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 7, 9));
253 $thisfile_riff_raw_rgad_album[
'name'] =
getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 0, 3));
254 $thisfile_riff_raw_rgad_album[
'originator'] =
getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 3, 3));
255 $thisfile_riff_raw_rgad_album[
'signbit'] =
getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 6, 1));
256 $thisfile_riff_raw_rgad_album[
'adjustment'] =
getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 7, 9));
258 $thisfile_riff[
'rgad'][
'peakamplitude'] = $thisfile_riff_raw_rgad[
'fPeakAmplitude'];
259 if (($thisfile_riff_raw_rgad_track[
'name'] != 0) && ($thisfile_riff_raw_rgad_track[
'originator'] != 0)) {
262 $thisfile_riff[
'rgad'][
'track'][
'adjustment'] =
getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_track[
'adjustment'], $thisfile_riff_raw_rgad_track[
'signbit']);
264 if (($thisfile_riff_raw_rgad_album[
'name'] != 0) && ($thisfile_riff_raw_rgad_album[
'originator'] != 0)) {
267 $thisfile_riff[
'rgad'][
'album'][
'adjustment'] =
getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_album[
'adjustment'], $thisfile_riff_raw_rgad_album[
'signbit']);
271 if (isset($thisfile_riff_WAVE[
'fact'][0][
'data'])) {
272 $thisfile_riff_raw[
'fact'][
'NumberOfSamples'] = $this->
EitherEndian2Int(substr($thisfile_riff_WAVE[
'fact'][0][
'data'], 0, 4));
282 if (!empty($thisfile_riff_raw[
'fmt '][
'nAvgBytesPerSec'])) {
283 $thisfile_audio[
'bitrate'] =
getid3_lib::CastAsInt($thisfile_riff_raw[
'fmt '][
'nAvgBytesPerSec'] * 8);
286 if (isset($thisfile_riff_WAVE[
'bext'][0][
'data'])) {
288 $thisfile_riff_WAVE_bext_0 = &$thisfile_riff_WAVE[
'bext'][0];
290 $thisfile_riff_WAVE_bext_0[
'title'] = trim(substr($thisfile_riff_WAVE_bext_0[
'data'], 0, 256));
291 $thisfile_riff_WAVE_bext_0[
'author'] = trim(substr($thisfile_riff_WAVE_bext_0[
'data'], 256, 32));
292 $thisfile_riff_WAVE_bext_0[
'reference'] = trim(substr($thisfile_riff_WAVE_bext_0[
'data'], 288, 32));
293 $thisfile_riff_WAVE_bext_0[
'origin_date'] = substr($thisfile_riff_WAVE_bext_0[
'data'], 320, 10);
294 $thisfile_riff_WAVE_bext_0[
'origin_time'] = substr($thisfile_riff_WAVE_bext_0[
'data'], 330, 8);
297 $thisfile_riff_WAVE_bext_0[
'reserved'] = substr($thisfile_riff_WAVE_bext_0[
'data'], 347, 254);
298 $thisfile_riff_WAVE_bext_0[
'coding_history'] = explode(
"\r\n", trim(substr($thisfile_riff_WAVE_bext_0[
'data'], 601)));
299 if (preg_match(
'#^([0-9]{4}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0[
'origin_date'], $matches_bext_date)) {
300 if (preg_match(
'#^([0-9]{2}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0[
'origin_time'], $matches_bext_time)) {
301 list($dummy, $bext_timestamp[
'year'], $bext_timestamp[
'month'], $bext_timestamp[
'day']) = $matches_bext_date;
302 list($dummy, $bext_timestamp[
'hour'], $bext_timestamp[
'minute'], $bext_timestamp[
'second']) = $matches_bext_time;
303 $thisfile_riff_WAVE_bext_0[
'origin_date_unix'] = gmmktime($bext_timestamp[
'hour'], $bext_timestamp[
'minute'], $bext_timestamp[
'second'], $bext_timestamp[
'month'], $bext_timestamp[
'day'], $bext_timestamp[
'year']);
305 $this->
warning(
'RIFF.WAVE.BEXT.origin_time is invalid');
308 $this->
warning(
'RIFF.WAVE.BEXT.origin_date is invalid');
310 $thisfile_riff[
'comments'][
'author'][] = $thisfile_riff_WAVE_bext_0[
'author'];
311 $thisfile_riff[
'comments'][
'title'][] = $thisfile_riff_WAVE_bext_0[
'title'];
314 if (isset($thisfile_riff_WAVE[
'MEXT'][0][
'data'])) {
316 $thisfile_riff_WAVE_MEXT_0 = &$thisfile_riff_WAVE[
'MEXT'][0];
318 $thisfile_riff_WAVE_MEXT_0[
'raw'][
'sound_information'] =
getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0[
'data'], 0, 2));
319 $thisfile_riff_WAVE_MEXT_0[
'flags'][
'homogenous'] = (bool) ($thisfile_riff_WAVE_MEXT_0[
'raw'][
'sound_information'] & 0x0001);
320 if ($thisfile_riff_WAVE_MEXT_0[
'flags'][
'homogenous']) {
321 $thisfile_riff_WAVE_MEXT_0[
'flags'][
'padding'] = ($thisfile_riff_WAVE_MEXT_0[
'raw'][
'sound_information'] & 0x0002) ?
false :
true;
322 $thisfile_riff_WAVE_MEXT_0[
'flags'][
'22_or_44'] = (bool) ($thisfile_riff_WAVE_MEXT_0[
'raw'][
'sound_information'] & 0x0004);
323 $thisfile_riff_WAVE_MEXT_0[
'flags'][
'free_format'] = (bool) ($thisfile_riff_WAVE_MEXT_0[
'raw'][
'sound_information'] & 0x0008);
328 $thisfile_riff_WAVE_MEXT_0[
'raw'][
'anciliary_data_def'] =
getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0[
'data'], 8, 2));
329 $thisfile_riff_WAVE_MEXT_0[
'flags'][
'anciliary_data_left'] = (bool) ($thisfile_riff_WAVE_MEXT_0[
'raw'][
'anciliary_data_def'] & 0x0001);
330 $thisfile_riff_WAVE_MEXT_0[
'flags'][
'anciliary_data_free'] = (bool) ($thisfile_riff_WAVE_MEXT_0[
'raw'][
'anciliary_data_def'] & 0x0002);
331 $thisfile_riff_WAVE_MEXT_0[
'flags'][
'anciliary_data_right'] = (bool) ($thisfile_riff_WAVE_MEXT_0[
'raw'][
'anciliary_data_def'] & 0x0004);
334 if (isset($thisfile_riff_WAVE[
'cart'][0][
'data'])) {
336 $thisfile_riff_WAVE_cart_0 = &$thisfile_riff_WAVE[
'cart'][0];
338 $thisfile_riff_WAVE_cart_0[
'version'] = substr($thisfile_riff_WAVE_cart_0[
'data'], 0, 4);
339 $thisfile_riff_WAVE_cart_0[
'title'] = trim(substr($thisfile_riff_WAVE_cart_0[
'data'], 4, 64));
340 $thisfile_riff_WAVE_cart_0[
'artist'] = trim(substr($thisfile_riff_WAVE_cart_0[
'data'], 68, 64));
341 $thisfile_riff_WAVE_cart_0[
'cut_id'] = trim(substr($thisfile_riff_WAVE_cart_0[
'data'], 132, 64));
342 $thisfile_riff_WAVE_cart_0[
'client_id'] = trim(substr($thisfile_riff_WAVE_cart_0[
'data'], 196, 64));
343 $thisfile_riff_WAVE_cart_0[
'category'] = trim(substr($thisfile_riff_WAVE_cart_0[
'data'], 260, 64));
344 $thisfile_riff_WAVE_cart_0[
'classification'] = trim(substr($thisfile_riff_WAVE_cart_0[
'data'], 324, 64));
345 $thisfile_riff_WAVE_cart_0[
'out_cue'] = trim(substr($thisfile_riff_WAVE_cart_0[
'data'], 388, 64));
346 $thisfile_riff_WAVE_cart_0[
'start_date'] = trim(substr($thisfile_riff_WAVE_cart_0[
'data'], 452, 10));
347 $thisfile_riff_WAVE_cart_0[
'start_time'] = trim(substr($thisfile_riff_WAVE_cart_0[
'data'], 462, 8));
348 $thisfile_riff_WAVE_cart_0[
'end_date'] = trim(substr($thisfile_riff_WAVE_cart_0[
'data'], 470, 10));
349 $thisfile_riff_WAVE_cart_0[
'end_time'] = trim(substr($thisfile_riff_WAVE_cart_0[
'data'], 480, 8));
350 $thisfile_riff_WAVE_cart_0[
'producer_app_id'] = trim(substr($thisfile_riff_WAVE_cart_0[
'data'], 488, 64));
351 $thisfile_riff_WAVE_cart_0[
'producer_app_version'] = trim(substr($thisfile_riff_WAVE_cart_0[
'data'], 552, 64));
352 $thisfile_riff_WAVE_cart_0[
'user_defined_text'] = trim(substr($thisfile_riff_WAVE_cart_0[
'data'], 616, 64));
353 $thisfile_riff_WAVE_cart_0[
'zero_db_reference'] =
getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_cart_0[
'data'], 680, 4),
true);
354 for (
$i = 0;
$i < 8;
$i++) {
355 $thisfile_riff_WAVE_cart_0[
'post_time'][
$i][
'usage_fourcc'] = substr($thisfile_riff_WAVE_cart_0[
'data'], 684 + (
$i * 8), 4);
356 $thisfile_riff_WAVE_cart_0[
'post_time'][
$i][
'timer_value'] =
getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_cart_0[
'data'], 684 + (
$i * 8) + 4, 4));
358 $thisfile_riff_WAVE_cart_0[
'url'] = trim(substr($thisfile_riff_WAVE_cart_0[
'data'], 748, 1024));
359 $thisfile_riff_WAVE_cart_0[
'tag_text'] = explode(
"\r\n", trim(substr($thisfile_riff_WAVE_cart_0[
'data'], 1772)));
361 $thisfile_riff[
'comments'][
'artist'][] = $thisfile_riff_WAVE_cart_0[
'artist'];
362 $thisfile_riff[
'comments'][
'title'][] = $thisfile_riff_WAVE_cart_0[
'title'];
365 if (isset($thisfile_riff_WAVE[
'SNDM'][0][
'data'])) {
369 $thisfile_riff_WAVE_SNDM_0 = &$thisfile_riff_WAVE[
'SNDM'][0];
370 $thisfile_riff_WAVE_SNDM_0_data = &$thisfile_riff_WAVE_SNDM_0[
'data'];
371 $SNDM_startoffset = 0;
372 $SNDM_endoffset = $thisfile_riff_WAVE_SNDM_0[
'size'];
374 while ($SNDM_startoffset < $SNDM_endoffset) {
375 $SNDM_thisTagOffset = 0;
376 $SNDM_thisTagSize =
getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4));
377 $SNDM_thisTagOffset += 4;
378 $SNDM_thisTagKey = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4);
379 $SNDM_thisTagOffset += 4;
380 $SNDM_thisTagDataSize =
getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2));
381 $SNDM_thisTagOffset += 2;
382 $SNDM_thisTagDataFlags =
getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2));
383 $SNDM_thisTagOffset += 2;
384 $SNDM_thisTagDataText = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, $SNDM_thisTagDataSize);
385 $SNDM_thisTagOffset += $SNDM_thisTagDataSize;
387 if ($SNDM_thisTagSize != (4 + 4 + 2 + 2 + $SNDM_thisTagDataSize)) {
388 $this->
warning(
'RIFF.WAVE.SNDM.data contains tag not expected length (expected: '.$SNDM_thisTagSize.
', found: '.(4 + 4 + 2 + 2 + $SNDM_thisTagDataSize).
') at offset '.$SNDM_startoffset.
' (file offset '.($thisfile_riff_WAVE_SNDM_0[
'offset'] + $SNDM_startoffset).
')');
390 } elseif ($SNDM_thisTagSize <= 0) {
391 $this->
warning(
'RIFF.WAVE.SNDM.data contains zero-size tag at offset '.$SNDM_startoffset.
' (file offset '.($thisfile_riff_WAVE_SNDM_0[
'offset'] + $SNDM_startoffset).
')');
394 $SNDM_startoffset += $SNDM_thisTagSize;
396 $thisfile_riff_WAVE_SNDM_0[
'parsed_raw'][$SNDM_thisTagKey] = $SNDM_thisTagDataText;
397 if ($parsedkey = self::waveSNDMtagLookup($SNDM_thisTagKey)) {
398 $thisfile_riff_WAVE_SNDM_0[
'parsed'][$parsedkey] = $SNDM_thisTagDataText;
400 $this->
warning(
'RIFF.WAVE.SNDM contains unknown tag "'.$SNDM_thisTagKey.
'" at offset '.$SNDM_startoffset.
' (file offset '.($thisfile_riff_WAVE_SNDM_0[
'offset'] + $SNDM_startoffset).
')');
405 'tracktitle'=>
'title',
406 'category' =>
'genre',
408 'tracktitle'=>
'title',
410 foreach ($tagmapping as $fromkey => $tokey) {
411 if (isset($thisfile_riff_WAVE_SNDM_0[
'parsed'][$fromkey])) {
412 $thisfile_riff[
'comments'][$tokey][] = $thisfile_riff_WAVE_SNDM_0[
'parsed'][$fromkey];
417 if (isset($thisfile_riff_WAVE[
'iXML'][0][
'data'])) {
420 $thisfile_riff_WAVE[
'iXML'][0][
'parsed'] = $parsedXML;
421 if (isset($parsedXML[
'SPEED'][
'MASTER_SPEED'])) {
422 @list($numerator, $denominator) = explode(
'/', $parsedXML[
'SPEED'][
'MASTER_SPEED']);
423 $thisfile_riff_WAVE[
'iXML'][0][
'master_speed'] = $numerator / ($denominator ? $denominator : 1000);
425 if (isset($parsedXML[
'SPEED'][
'TIMECODE_RATE'])) {
426 @list($numerator, $denominator) = explode(
'/', $parsedXML[
'SPEED'][
'TIMECODE_RATE']);
427 $thisfile_riff_WAVE[
'iXML'][0][
'timecode_rate'] = $numerator / ($denominator ? $denominator : 1000);
429 if (isset($parsedXML[
'SPEED'][
'TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO']) && !empty($parsedXML[
'SPEED'][
'TIMESTAMP_SAMPLE_RATE']) && !empty($thisfile_riff_WAVE[
'iXML'][0][
'timecode_rate'])) {
430 $samples_since_midnight = floatval(ltrim($parsedXML[
'SPEED'][
'TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_HI'].$parsedXML[
'SPEED'][
'TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO'],
'0'));
431 $timestamp_sample_rate = (is_array($parsedXML[
'SPEED'][
'TIMESTAMP_SAMPLE_RATE']) ? max($parsedXML[
'SPEED'][
'TIMESTAMP_SAMPLE_RATE']) : $parsedXML[
'SPEED'][
'TIMESTAMP_SAMPLE_RATE']);
432 $thisfile_riff_WAVE[
'iXML'][0][
'timecode_seconds'] = $samples_since_midnight / $timestamp_sample_rate;
433 $h = floor( $thisfile_riff_WAVE[
'iXML'][0][
'timecode_seconds'] / 3600);
434 $m = floor(($thisfile_riff_WAVE[
'iXML'][0][
'timecode_seconds'] - (
$h * 3600)) / 60);
435 $s = floor( $thisfile_riff_WAVE[
'iXML'][0][
'timecode_seconds'] - (
$h * 3600) - (
$m * 60));
436 $f = ($thisfile_riff_WAVE[
'iXML'][0][
'timecode_seconds'] - (
$h * 3600) - (
$m * 60) -
$s) * $thisfile_riff_WAVE[
'iXML'][0][
'timecode_rate'];
437 $thisfile_riff_WAVE[
'iXML'][0][
'timecode_string'] = sprintf(
'%02d:%02d:%02d:%05.2f',
$h,
$m,
$s,
$f);
438 $thisfile_riff_WAVE[
'iXML'][0][
'timecode_string_round'] = sprintf(
'%02d:%02d:%02d:%02d',
$h,
$m,
$s, round(
$f));
439 unset($samples_since_midnight, $timestamp_sample_rate,
$h,
$m,
$s,
$f);
447 if (!isset($thisfile_audio[
'bitrate']) && isset($thisfile_riff_audio[$streamindex][
'bitrate'])) {
448 $thisfile_audio[
'bitrate'] = $thisfile_riff_audio[$streamindex][
'bitrate'];
449 $info[
'playtime_seconds'] = (float) (((
$info[
'avdataend'] -
$info[
'avdataoffset']) * 8) / $thisfile_audio[
'bitrate']);
452 if (!empty(
$info[
'wavpack'])) {
453 $thisfile_audio_dataformat =
'wavpack';
454 $thisfile_audio[
'bitrate_mode'] =
'vbr';
455 $thisfile_audio[
'encoder'] =
'WavPack v'.$info[
'wavpack'][
'version'];
458 $info[
'avdataend'] = $Original[
'avdataend'];
459 $thisfile_audio[
'bitrate'] = ((
$info[
'avdataend'] -
$info[
'avdataoffset']) * 8) /
$info[
'playtime_seconds'];
462 $RIFFdata = $this->
fread(44);
466 if ($OrignalRIFFheaderSize > $OrignalRIFFdataSize) {
467 $info[
'avdataend'] -= ($OrignalRIFFheaderSize - $OrignalRIFFdataSize);
469 $RIFFdata .= $this->
fread($OrignalRIFFheaderSize - $OrignalRIFFdataSize);
475 $RIFFdata = substr($RIFFdata, 0, 36).substr($RIFFdata, 44).substr($RIFFdata, 36, 8);
477 $getid3_riff->ParseRIFFdata($RIFFdata);
481 if (isset($thisfile_riff_raw[
'fmt '][
'wFormatTag'])) {
482 switch ($thisfile_riff_raw[
'fmt '][
'wFormatTag']) {
484 if (!empty(
$info[
'ac3'])) {
486 $thisfile_audio[
'wformattag'] = 0x2000;
487 $thisfile_audio[
'codec'] = self::wFormatTagLookup($thisfile_audio[
'wformattag']);
488 $thisfile_audio[
'lossless'] =
false;
489 $thisfile_audio[
'bitrate'] =
$info[
'ac3'][
'bitrate'];
490 $thisfile_audio[
'sample_rate'] =
$info[
'ac3'][
'sample_rate'];
492 if (!empty(
$info[
'dts'])) {
494 $thisfile_audio[
'wformattag'] = 0x2001;
495 $thisfile_audio[
'codec'] = self::wFormatTagLookup($thisfile_audio[
'wformattag']);
496 $thisfile_audio[
'lossless'] =
false;
497 $thisfile_audio[
'bitrate'] =
$info[
'dts'][
'bitrate'];
498 $thisfile_audio[
'sample_rate'] =
$info[
'dts'][
'sample_rate'];
502 $thisfile_audio[
'bitrate_mode'] =
'vbr';
503 $thisfile_audio_dataformat =
'litewave';
522 $thisfile_riff[
'litewave'][
'raw'] = array();
523 $riff_litewave = &$thisfile_riff[
'litewave'];
524 $riff_litewave_raw = &$riff_litewave[
'raw'];
527 'compression_method' => 1,
528 'compression_flags' => 1,
530 'm_dwBlockSize' => 4,
532 'm_wMarkDistance' => 2,
535 'm_bFactExists' => 2,
536 'm_dwRiffChunkSize' => 4,
538 $litewave_offset = 18;
539 foreach ($flags as $flag => $length) {
541 $litewave_offset += $length;
545 $riff_litewave[
'quality_factor'] = $riff_litewave_raw[
'm_wQuality'];
547 $riff_litewave[
'flags'][
'raw_source'] = ($riff_litewave_raw[
'compression_flags'] & 0x01) ?
false :
true;
548 $riff_litewave[
'flags'][
'vbr_blocksize'] = ($riff_litewave_raw[
'compression_flags'] & 0x02) ?
false :
true;
549 $riff_litewave[
'flags'][
'seekpoints'] = (bool) ($riff_litewave_raw[
'compression_flags'] & 0x04);
551 $thisfile_audio[
'lossless'] = (($riff_litewave_raw[
'm_wQuality'] == 100) ?
true :
false);
552 $thisfile_audio[
'encoder_options'] =
'-q'.$riff_litewave[
'quality_factor'];
560 switch (!empty($thisfile_audio_dataformat) ? $thisfile_audio_dataformat :
'') {
569 if ((
$info[
'avdataend'] -
$info[
'filesize']) == 1) {
575 $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)');
581 if (((
$info[
'avdataend'] -
$info[
'filesize']) == 1) && (($thisfile_riff[$RIFFsubtype][
'data'][0][
'size'] % 2) == 0) && (((
$info[
'filesize'] -
$info[
'avdataoffset']) % 2) == 1)) {
584 $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)');
588 $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)');
594 if (!empty(
$info[
'mpeg'][
'audio'][
'LAME'][
'audio_bytes'])) {
595 if (((
$info[
'avdataend'] -
$info[
'avdataoffset']) -
$info[
'mpeg'][
'audio'][
'LAME'][
'audio_bytes']) == 1) {
596 $info[
'avdataend']--;
597 $this->
warning(
'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored');
600 if (isset($thisfile_audio_dataformat) && ($thisfile_audio_dataformat ==
'ac3')) {
601 unset($thisfile_audio[
'bits_per_sample']);
602 if (!empty(
$info[
'ac3'][
'bitrate']) && (
$info[
'ac3'][
'bitrate'] != $thisfile_audio[
'bitrate'])) {
603 $thisfile_audio[
'bitrate'] =
$info[
'ac3'][
'bitrate'];
610 $info[
'fileformat'] =
'avi';
611 $info[
'mime_type'] =
'video/avi';
613 $thisfile_video[
'bitrate_mode'] =
'vbr';
614 $thisfile_video[
'dataformat'] =
'avi';
616 if (isset($thisfile_riff[$RIFFsubtype][
'movi'][
'offset'])) {
617 $info[
'avdataoffset'] = $thisfile_riff[$RIFFsubtype][
'movi'][
'offset'] + 8;
618 if (isset($thisfile_riff[
'AVIX'])) {
619 $info[
'avdataend'] = $thisfile_riff[
'AVIX'][(count($thisfile_riff[
'AVIX']) - 1)][
'chunks'][
'movi'][
'offset'] + $thisfile_riff[
'AVIX'][(count($thisfile_riff[
'AVIX']) - 1)][
'chunks'][
'movi'][
'size'];
621 $info[
'avdataend'] = $thisfile_riff[
'AVI '][
'movi'][
'offset'] + $thisfile_riff[
'AVI '][
'movi'][
'size'];
624 $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)');
629 if (isset($thisfile_riff[
'AVI '][
'hdrl'][
'strl'][
'indx'])) {
640 foreach ($thisfile_riff[
'AVI '][
'hdrl'][
'strl'][
'indx'] as $streamnumber => $steamdataarray) {
641 $ahsisd = &$thisfile_riff[
'AVI '][
'hdrl'][
'strl'][
'indx'][$streamnumber][
'data'];
643 $thisfile_riff_raw[
'indx'][$streamnumber][
'wLongsPerEntry'] = $this->
EitherEndian2Int(substr($ahsisd, 0, 2));
644 $thisfile_riff_raw[
'indx'][$streamnumber][
'bIndexSubType'] = $this->
EitherEndian2Int(substr($ahsisd, 2, 1));
645 $thisfile_riff_raw[
'indx'][$streamnumber][
'bIndexType'] = $this->
EitherEndian2Int(substr($ahsisd, 3, 1));
646 $thisfile_riff_raw[
'indx'][$streamnumber][
'nEntriesInUse'] = $this->
EitherEndian2Int(substr($ahsisd, 4, 4));
647 $thisfile_riff_raw[
'indx'][$streamnumber][
'dwChunkId'] = substr($ahsisd, 8, 4);
648 $thisfile_riff_raw[
'indx'][$streamnumber][
'dwReserved'] = $this->
EitherEndian2Int(substr($ahsisd, 12, 4));
656 if (isset($thisfile_riff[
'AVI '][
'hdrl'][
'avih'][$streamindex][
'data'])) {
657 $avihData = $thisfile_riff[
'AVI '][
'hdrl'][
'avih'][$streamindex][
'data'];
660 $thisfile_riff_raw[
'avih'] = array();
661 $thisfile_riff_raw_avih = &$thisfile_riff_raw[
'avih'];
663 $thisfile_riff_raw_avih[
'dwMicroSecPerFrame'] = $this->
EitherEndian2Int(substr($avihData, 0, 4));
664 if ($thisfile_riff_raw_avih[
'dwMicroSecPerFrame'] == 0) {
665 $this->
error(
'Corrupt RIFF file: avih.dwMicroSecPerFrame == zero');
671 'dwPaddingGranularity',
676 'dwSuggestedBufferSize',
685 foreach ($flags as $flag) {
686 $thisfile_riff_raw_avih[$flag] = $this->
EitherEndian2Int(substr($avihData, $avih_offset, 4));
691 'hasindex' => 0x00000010,
692 'mustuseindex' => 0x00000020,
693 'interleaved' => 0x00000100,
694 'trustcktype' => 0x00000800,
695 'capturedfile' => 0x00010000,
696 'copyrighted' => 0x00020010,
698 foreach ($flags as $flag => $value) {
699 $thisfile_riff_raw_avih[
'flags'][$flag] = (bool) ($thisfile_riff_raw_avih[
'dwFlags'] & $value);
703 $thisfile_riff_video[$streamindex] = array();
704 $thisfile_riff_video_current = &$thisfile_riff_video[$streamindex];
706 if ($thisfile_riff_raw_avih[
'dwWidth'] > 0) {
707 $thisfile_riff_video_current[
'frame_width'] = $thisfile_riff_raw_avih[
'dwWidth'];
708 $thisfile_video[
'resolution_x'] = $thisfile_riff_video_current[
'frame_width'];
710 if ($thisfile_riff_raw_avih[
'dwHeight'] > 0) {
711 $thisfile_riff_video_current[
'frame_height'] = $thisfile_riff_raw_avih[
'dwHeight'];
712 $thisfile_video[
'resolution_y'] = $thisfile_riff_video_current[
'frame_height'];
714 if ($thisfile_riff_raw_avih[
'dwTotalFrames'] > 0) {
715 $thisfile_riff_video_current[
'total_frames'] = $thisfile_riff_raw_avih[
'dwTotalFrames'];
716 $thisfile_video[
'total_frames'] = $thisfile_riff_video_current[
'total_frames'];
719 $thisfile_riff_video_current[
'frame_rate'] = round(1000000 / $thisfile_riff_raw_avih[
'dwMicroSecPerFrame'], 3);
720 $thisfile_video[
'frame_rate'] = $thisfile_riff_video_current[
'frame_rate'];
722 if (isset($thisfile_riff[
'AVI '][
'hdrl'][
'strl'][
'strh'][0][
'data'])) {
723 if (is_array($thisfile_riff[
'AVI '][
'hdrl'][
'strl'][
'strh'])) {
724 for (
$i = 0;
$i < count($thisfile_riff[
'AVI '][
'hdrl'][
'strl'][
'strh']);
$i++) {
725 if (isset($thisfile_riff[
'AVI '][
'hdrl'][
'strl'][
'strh'][
$i][
'data'])) {
726 $strhData = $thisfile_riff[
'AVI '][
'hdrl'][
'strl'][
'strh'][
$i][
'data'];
727 $strhfccType = substr($strhData, 0, 4);
729 if (isset($thisfile_riff[
'AVI '][
'hdrl'][
'strl'][
'strf'][$i][
'data'])) {
730 $strfData = $thisfile_riff[
'AVI '][
'hdrl'][
'strl'][
'strf'][
$i][
'data'];
733 $thisfile_riff_raw_strf_strhfccType_streamindex = &$thisfile_riff_raw[
'strf'][$strhfccType][$streamindex];
735 switch ($strhfccType) {
737 $thisfile_audio[
'bitrate_mode'] =
'cbr';
738 $thisfile_audio_dataformat =
'wav';
739 if (isset($thisfile_riff_audio) && is_array($thisfile_riff_audio)) {
740 $streamindex = count($thisfile_riff_audio);
743 $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($strfData);
744 $thisfile_audio[
'wformattag'] = $thisfile_riff_audio[$streamindex][
'raw'][
'wFormatTag'];
747 $thisfile_audio[
'streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
748 $thisfile_audio_streams_currentstream = &$thisfile_audio[
'streams'][$streamindex];
750 if ($thisfile_audio_streams_currentstream[
'bits_per_sample'] == 0) {
751 unset($thisfile_audio_streams_currentstream[
'bits_per_sample']);
753 $thisfile_audio_streams_currentstream[
'wformattag'] = $thisfile_audio_streams_currentstream[
'raw'][
'wFormatTag'];
754 unset($thisfile_audio_streams_currentstream[
'raw']);
757 $thisfile_riff_raw[
'strf'][$strhfccType][$streamindex] = $thisfile_riff_audio[$streamindex][
'raw'];
759 unset($thisfile_riff_audio[$streamindex][
'raw']);
762 $thisfile_audio[
'lossless'] =
false;
763 switch ($thisfile_riff_raw_strf_strhfccType_streamindex[
'wFormatTag']) {
765 $thisfile_audio_dataformat =
'wav';
766 $thisfile_audio[
'lossless'] =
true;
770 $thisfile_audio_dataformat =
'mp2';
774 $thisfile_audio_dataformat =
'mp3';
778 $thisfile_audio_dataformat =
'aac';
784 $thisfile_audio_dataformat =
'wma';
788 $thisfile_audio_dataformat =
'ac3';
792 $thisfile_audio_dataformat =
'dts';
796 $thisfile_audio_dataformat =
'wav';
799 $thisfile_audio_streams_currentstream[
'dataformat'] = $thisfile_audio_dataformat;
800 $thisfile_audio_streams_currentstream[
'lossless'] = $thisfile_audio[
'lossless'];
801 $thisfile_audio_streams_currentstream[
'bitrate_mode'] = $thisfile_audio[
'bitrate_mode'];
808 $thisfile_riff_raw[
'strh'][
$i] = array();
809 $thisfile_riff_raw_strh_current = &$thisfile_riff_raw[
'strh'][
$i];
811 $thisfile_riff_raw_strh_current[
'fccType'] = substr($strhData, 0, 4);
812 $thisfile_riff_raw_strh_current[
'fccHandler'] = substr($strhData, 4, 4);
813 $thisfile_riff_raw_strh_current[
'dwFlags'] = $this->
EitherEndian2Int(substr($strhData, 8, 4));
814 $thisfile_riff_raw_strh_current[
'wPriority'] = $this->
EitherEndian2Int(substr($strhData, 12, 2));
815 $thisfile_riff_raw_strh_current[
'wLanguage'] = $this->
EitherEndian2Int(substr($strhData, 14, 2));
816 $thisfile_riff_raw_strh_current[
'dwInitialFrames'] = $this->
EitherEndian2Int(substr($strhData, 16, 4));
817 $thisfile_riff_raw_strh_current[
'dwScale'] = $this->
EitherEndian2Int(substr($strhData, 20, 4));
818 $thisfile_riff_raw_strh_current[
'dwRate'] = $this->
EitherEndian2Int(substr($strhData, 24, 4));
819 $thisfile_riff_raw_strh_current[
'dwStart'] = $this->
EitherEndian2Int(substr($strhData, 28, 4));
820 $thisfile_riff_raw_strh_current[
'dwLength'] = $this->
EitherEndian2Int(substr($strhData, 32, 4));
821 $thisfile_riff_raw_strh_current[
'dwSuggestedBufferSize'] = $this->
EitherEndian2Int(substr($strhData, 36, 4));
822 $thisfile_riff_raw_strh_current[
'dwQuality'] = $this->
EitherEndian2Int(substr($strhData, 40, 4));
823 $thisfile_riff_raw_strh_current[
'dwSampleSize'] = $this->
EitherEndian2Int(substr($strhData, 44, 4));
824 $thisfile_riff_raw_strh_current[
'rcFrame'] = $this->
EitherEndian2Int(substr($strhData, 48, 4));
826 $thisfile_riff_video_current[
'codec'] = self::fourccLookup($thisfile_riff_raw_strh_current[
'fccHandler']);
827 $thisfile_video[
'fourcc'] = $thisfile_riff_raw_strh_current[
'fccHandler'];
828 if (!$thisfile_riff_video_current[
'codec'] && isset($thisfile_riff_raw_strf_strhfccType_streamindex[
'fourcc']) && self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex[
'fourcc'])) {
829 $thisfile_riff_video_current[
'codec'] = self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex[
'fourcc']);
830 $thisfile_video[
'fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex[
'fourcc'];
832 $thisfile_video[
'codec'] = $thisfile_riff_video_current[
'codec'];
833 $thisfile_video[
'pixel_aspect_ratio'] = (float) 1;
834 switch ($thisfile_riff_raw_strh_current[
'fccHandler']) {
838 $thisfile_video[
'lossless'] =
true;
842 $thisfile_video[
'lossless'] =
false;
846 switch ($strhfccType) {
848 $thisfile_riff_raw_strf_strhfccType_streamindex = self::ParseBITMAPINFOHEADER(substr($strfData, 0, 40), ($this->container ==
'riff'));
849 $thisfile_video[
'bits_per_sample'] = $thisfile_riff_raw_strf_strhfccType_streamindex[
'biBitCount'];
851 if ($thisfile_riff_video_current[
'codec'] ==
'DV') {
852 $thisfile_riff_video_current[
'dv_type'] = 2;
857 $thisfile_riff_video_current[
'dv_type'] = 1;
863 $this->
warning(
'Unhandled fccType for stream ('.$i.
'): "'.$strhfccType.
'"');
870 if (isset($thisfile_riff_raw_strf_strhfccType_streamindex[
'fourcc'])) {
872 $thisfile_video[
'fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex[
'fourcc'];
873 if (self::fourccLookup($thisfile_video[
'fourcc'])) {
874 $thisfile_riff_video_current[
'codec'] = self::fourccLookup($thisfile_video[
'fourcc']);
875 $thisfile_video[
'codec'] = $thisfile_riff_video_current[
'codec'];
878 switch ($thisfile_riff_raw_strf_strhfccType_streamindex[
'fourcc']) {
882 $thisfile_video[
'lossless'] =
true;
887 $thisfile_video[
'lossless'] =
false;
900 $info[
'fileformat'] =
'amv';
901 $info[
'mime_type'] =
'video/amv';
903 $thisfile_video[
'bitrate_mode'] =
'vbr';
904 $thisfile_video[
'dataformat'] =
'mjpeg';
905 $thisfile_video[
'codec'] =
'mjpeg';
906 $thisfile_video[
'lossless'] =
false;
907 $thisfile_video[
'bits_per_sample'] = 24;
909 $thisfile_audio[
'dataformat'] =
'adpcm';
910 $thisfile_audio[
'lossless'] =
false;
916 $info[
'fileformat'] =
'cda';
917 unset(
$info[
'mime_type']);
919 $thisfile_audio_dataformat =
'cda';
921 $info[
'avdataoffset'] = 44;
923 if (isset($thisfile_riff[
'CDDA'][
'fmt '][0][
'data'])) {
925 $thisfile_riff_CDDA_fmt_0 = &$thisfile_riff[
'CDDA'][
'fmt '][0];
927 $thisfile_riff_CDDA_fmt_0[
'unknown1'] = $this->
EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0[
'data'], 0, 2));
928 $thisfile_riff_CDDA_fmt_0[
'track_num'] = $this->
EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0[
'data'], 2, 2));
929 $thisfile_riff_CDDA_fmt_0[
'disc_id'] = $this->
EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0[
'data'], 4, 4));
930 $thisfile_riff_CDDA_fmt_0[
'start_offset_frame'] = $this->
EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0[
'data'], 8, 4));
931 $thisfile_riff_CDDA_fmt_0[
'playtime_frames'] = $this->
EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0[
'data'], 12, 4));
932 $thisfile_riff_CDDA_fmt_0[
'unknown6'] = $this->
EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0[
'data'], 16, 4));
933 $thisfile_riff_CDDA_fmt_0[
'unknown7'] = $this->
EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0[
'data'], 20, 4));
935 $thisfile_riff_CDDA_fmt_0[
'start_offset_seconds'] = (float) $thisfile_riff_CDDA_fmt_0[
'start_offset_frame'] / 75;
936 $thisfile_riff_CDDA_fmt_0[
'playtime_seconds'] = (float) $thisfile_riff_CDDA_fmt_0[
'playtime_frames'] / 75;
937 $info[
'comments'][
'track'] = $thisfile_riff_CDDA_fmt_0[
'track_num'];
938 $info[
'playtime_seconds'] = $thisfile_riff_CDDA_fmt_0[
'playtime_seconds'];
941 $thisfile_audio[
'lossless'] =
true;
942 $thisfile_audio[
'sample_rate'] = 44100;
943 $thisfile_audio[
'channels'] = 2;
944 $thisfile_audio[
'bits_per_sample'] = 16;
945 $thisfile_audio[
'bitrate'] = $thisfile_audio[
'sample_rate'] * $thisfile_audio[
'channels'] * $thisfile_audio[
'bits_per_sample'];
946 $thisfile_audio[
'bitrate_mode'] =
'cbr';
953 $info[
'fileformat'] =
'aiff';
954 $info[
'mime_type'] =
'audio/x-aiff';
956 $thisfile_audio[
'bitrate_mode'] =
'cbr';
957 $thisfile_audio_dataformat =
'aiff';
958 $thisfile_audio[
'lossless'] =
true;
960 if (isset($thisfile_riff[$RIFFsubtype][
'SSND'][0][
'offset'])) {
961 $info[
'avdataoffset'] = $thisfile_riff[$RIFFsubtype][
'SSND'][0][
'offset'] + 8;
962 $info[
'avdataend'] =
$info[
'avdataoffset'] + $thisfile_riff[$RIFFsubtype][
'SSND'][0][
'size'];
964 if ((
$info[
'avdataend'] == (
$info[
'filesize'] + 1)) && ((
$info[
'filesize'] % 2) == 1)) {
968 $this->
warning(
'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype][
'SSND'][0][
'size'].
' bytes of audio data, only '.(
$info[
'filesize'] -
$info[
'avdataoffset']).
' bytes found');
974 if (isset($thisfile_riff[$RIFFsubtype][
'COMM'][0][
'data'])) {
977 $thisfile_riff_RIFFsubtype_COMM_0_data = &$thisfile_riff[$RIFFsubtype][
'COMM'][0][
'data'];
979 $thisfile_riff_audio[
'channels'] =
getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 0, 2),
true);
980 $thisfile_riff_audio[
'total_samples'] =
getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 2, 4),
false);
981 $thisfile_riff_audio[
'bits_per_sample'] =
getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 6, 2),
true);
984 if ($thisfile_riff[$RIFFsubtype][
'COMM'][0][
'size'] > 18) {
985 $thisfile_riff_audio[
'codec_fourcc'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 18, 4);
987 $thisfile_riff_audio[
'codec_name'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 23, $CodecNameSize);
988 switch ($thisfile_riff_audio[
'codec_name']) {
990 $thisfile_audio[
'codec'] =
'Pulse Code Modulation (PCM)';
991 $thisfile_audio[
'lossless'] =
true;
995 switch ($thisfile_riff_audio[
'codec_fourcc']) {
998 $thisfile_riff_audio[
'codec_name'] =
'Two\'s Compliment Little-Endian PCM';
999 $thisfile_audio[
'lossless'] =
true;
1003 $thisfile_riff_audio[
'codec_name'] =
'Two\'s Compliment Big-Endian PCM';
1004 $thisfile_audio[
'lossless'] =
true;
1013 $thisfile_audio[
'codec'] = $thisfile_riff_audio[
'codec_name'];
1014 $thisfile_audio[
'lossless'] =
false;
1019 $thisfile_audio[
'channels'] = $thisfile_riff_audio[
'channels'];
1020 if ($thisfile_riff_audio[
'bits_per_sample'] > 0) {
1021 $thisfile_audio[
'bits_per_sample'] = $thisfile_riff_audio[
'bits_per_sample'];
1023 $thisfile_audio[
'sample_rate'] = $thisfile_riff_audio[
'sample_rate'];
1024 if ($thisfile_audio[
'sample_rate'] == 0) {
1025 $this->
error(
'Corrupted AIFF file: sample_rate == zero');
1028 $info[
'playtime_seconds'] = $thisfile_riff_audio[
'total_samples'] / $thisfile_audio[
'sample_rate'];
1031 if (isset($thisfile_riff[$RIFFsubtype][
'COMT'])) {
1035 for (
$i = 0;
$i < $CommentCount;
$i++) {
1042 $info[
'comments_raw'][
$i][
'comment'] = substr($thisfile_riff[$RIFFsubtype][
'COMT'][0][
'data'], $offset, $CommentLength);
1043 $offset += $CommentLength;
1046 $thisfile_riff[
'comments'][
'comment'][] =
$info[
'comments_raw'][
$i][
'comment'];
1050 $CommentsChunkNames = array(
'NAME'=>
'title',
'author'=>
'artist',
'(c) '=>
'copyright',
'ANNO'=>
'comment');
1051 foreach ($CommentsChunkNames as
$key => $value) {
1052 if (isset($thisfile_riff[$RIFFsubtype][
$key][0][
'data'])) {
1053 $thisfile_riff[
'comments'][$value][] = $thisfile_riff[$RIFFsubtype][
$key][0][
'data'];
1073 $info[
'fileformat'] =
'8svx';
1074 $info[
'mime_type'] =
'audio/8svx';
1076 $thisfile_audio[
'bitrate_mode'] =
'cbr';
1077 $thisfile_audio_dataformat =
'8svx';
1078 $thisfile_audio[
'bits_per_sample'] = 8;
1079 $thisfile_audio[
'channels'] = 1;
1081 if (isset($thisfile_riff[$RIFFsubtype][
'BODY'][0][
'offset'])) {
1082 $info[
'avdataoffset'] = $thisfile_riff[$RIFFsubtype][
'BODY'][0][
'offset'] + 8;
1083 $info[
'avdataend'] =
$info[
'avdataoffset'] + $thisfile_riff[$RIFFsubtype][
'BODY'][0][
'size'];
1084 if (
$info[
'avdataend'] >
$info[
'filesize']) {
1085 $this->
warning(
'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype][
'BODY'][0][
'size'].
' bytes of audio data, only '.(
$info[
'filesize'] -
$info[
'avdataoffset']).
' bytes found');
1089 if (isset($thisfile_riff[$RIFFsubtype][
'VHDR'][0][
'offset'])) {
1091 $thisfile_riff_RIFFsubtype_VHDR_0 = &$thisfile_riff[$RIFFsubtype][
'VHDR'][0];
1093 $thisfile_riff_RIFFsubtype_VHDR_0[
'oneShotHiSamples'] =
getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0[
'data'], 0, 4));
1094 $thisfile_riff_RIFFsubtype_VHDR_0[
'repeatHiSamples'] =
getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0[
'data'], 4, 4));
1095 $thisfile_riff_RIFFsubtype_VHDR_0[
'samplesPerHiCycle'] =
getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0[
'data'], 8, 4));
1096 $thisfile_riff_RIFFsubtype_VHDR_0[
'samplesPerSec'] =
getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0[
'data'], 12, 2));
1097 $thisfile_riff_RIFFsubtype_VHDR_0[
'ctOctave'] =
getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0[
'data'], 14, 1));
1098 $thisfile_riff_RIFFsubtype_VHDR_0[
'sCompression'] =
getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0[
'data'], 15, 1));
1099 $thisfile_riff_RIFFsubtype_VHDR_0[
'Volume'] =
getid3_lib::FixedPoint16_16(substr($thisfile_riff_RIFFsubtype_VHDR_0[
'data'], 16, 4));
1101 $thisfile_audio[
'sample_rate'] = $thisfile_riff_RIFFsubtype_VHDR_0[
'samplesPerSec'];
1103 switch ($thisfile_riff_RIFFsubtype_VHDR_0[
'sCompression']) {
1105 $thisfile_audio[
'codec'] =
'Pulse Code Modulation (PCM)';
1106 $thisfile_audio[
'lossless'] =
true;
1107 $ActualBitsPerSample = 8;
1111 $thisfile_audio[
'codec'] =
'Fibonacci-delta encoding';
1112 $thisfile_audio[
'lossless'] =
false;
1113 $ActualBitsPerSample = 4;
1117 $this->
warning(
'Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.sCompression.
'"');
1122 if (isset($thisfile_riff[$RIFFsubtype][
'CHAN'][0][
'data'])) {
1124 switch ($ChannelsIndex) {
1126 $thisfile_audio[
'channels'] = 2;
1131 $thisfile_audio[
'channels'] = 1;
1135 $this->
warning(
'Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "'.$ChannelsIndex.
'"');
1141 $CommentsChunkNames = array(
'NAME'=>
'title',
'author'=>
'artist',
'(c) '=>
'copyright',
'ANNO'=>
'comment');
1142 foreach ($CommentsChunkNames as
$key => $value) {
1143 if (isset($thisfile_riff[$RIFFsubtype][
$key][0][
'data'])) {
1144 $thisfile_riff[
'comments'][$value][] = $thisfile_riff[$RIFFsubtype][
$key][0][
'data'];
1148 $thisfile_audio[
'bitrate'] = $thisfile_audio[
'sample_rate'] * $ActualBitsPerSample * $thisfile_audio[
'channels'];
1149 if (!empty($thisfile_audio[
'bitrate'])) {
1150 $info[
'playtime_seconds'] = (
$info[
'avdataend'] -
$info[
'avdataoffset']) / ($thisfile_audio[
'bitrate'] / 8);
1155 $info[
'fileformat'] =
'vcd';
1156 $info[
'mime_type'] =
'video/mpeg';
1158 if (!empty($thisfile_riff[
'CDXA'][
'data'][0][
'size'])) {
1161 $getid3_temp =
new getID3();
1162 $getid3_temp->openfile($this->getid3->filename);
1164 $getid3_mpeg->Analyze();
1165 if (empty($getid3_temp->info[
'error'])) {
1166 $info[
'audio'] = $getid3_temp->info[
'audio'];
1167 $info[
'video'] = $getid3_temp->info[
'video'];
1168 $info[
'mpeg'] = $getid3_temp->info[
'mpeg'];
1169 $info[
'warning'] = $getid3_temp->info[
'warning'];
1171 unset($getid3_temp, $getid3_mpeg);
1177 $info[
'fileformat'] =
'webp';
1178 $info[
'mime_type'] =
'image/webp';
1180 $this->
error(
'WebP image parsing not supported in this version of getID3()');
1184 $this->
error(
'Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA|WEBP), found "'.$RIFFsubtype.
'" instead');
1188 switch ($RIFFsubtype) {
1192 $ID3v2_key_good =
'id3 ';
1193 $ID3v2_keys_bad = array(
'ID3 ',
'tag ');
1194 foreach ($ID3v2_keys_bad as $ID3v2_key_bad) {
1195 if (isset($thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]) && !array_key_exists($ID3v2_key_good, $thisfile_riff[$RIFFsubtype])) {
1196 $thisfile_riff[$RIFFsubtype][$ID3v2_key_good] = $thisfile_riff[$RIFFsubtype][$ID3v2_key_bad];
1197 $this->
warning(
'mapping "'.$ID3v2_key_bad.
'" chunk to "'.$ID3v2_key_good.
'"');
1201 if (isset($thisfile_riff[$RIFFsubtype][
'id3 '])) {
1204 $getid3_temp =
new getID3();
1205 $getid3_temp->openfile($this->getid3->filename);
1207 $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype][
'id3 '][0][
'offset'] + 8;
1208 if ($thisfile_riff[$RIFFsubtype][
'id3 '][0][
'valid'] = $getid3_id3v2->Analyze()) {
1209 $info[
'id3v2'] = $getid3_temp->info[
'id3v2'];
1211 unset($getid3_temp, $getid3_id3v2);
1216 if (isset($thisfile_riff_WAVE[
'DISP']) && is_array($thisfile_riff_WAVE[
'DISP'])) {
1217 $thisfile_riff[
'comments'][
'title'][] = trim(substr($thisfile_riff_WAVE[
'DISP'][count($thisfile_riff_WAVE[
'DISP']) - 1][
'data'], 4));
1219 if (isset($thisfile_riff_WAVE[
'INFO']) && is_array($thisfile_riff_WAVE[
'INFO'])) {
1220 self::parseComments($thisfile_riff_WAVE[
'INFO'], $thisfile_riff[
'comments']);
1222 if (isset($thisfile_riff[
'AVI '][
'INFO']) && is_array($thisfile_riff[
'AVI '][
'INFO'])) {
1223 self::parseComments($thisfile_riff[
'AVI '][
'INFO'], $thisfile_riff[
'comments']);
1226 if (empty($thisfile_audio[
'encoder']) && !empty(
$info[
'mpeg'][
'audio'][
'LAME'][
'short_version'])) {
1227 $thisfile_audio[
'encoder'] =
$info[
'mpeg'][
'audio'][
'LAME'][
'short_version'];
1230 if (!isset(
$info[
'playtime_seconds'])) {
1231 $info[
'playtime_seconds'] = 0;
1233 if (isset($thisfile_riff_raw[
'strh'][0][
'dwLength']) && isset($thisfile_riff_raw[
'avih'][
'dwMicroSecPerFrame'])) {
1235 $info[
'playtime_seconds'] = $thisfile_riff_raw[
'strh'][0][
'dwLength'] * ($thisfile_riff_raw[
'avih'][
'dwMicroSecPerFrame'] / 1000000);
1236 } elseif (isset($thisfile_riff_raw[
'avih'][
'dwTotalFrames']) && isset($thisfile_riff_raw[
'avih'][
'dwMicroSecPerFrame'])) {
1237 $info[
'playtime_seconds'] = $thisfile_riff_raw[
'avih'][
'dwTotalFrames'] * ($thisfile_riff_raw[
'avih'][
'dwMicroSecPerFrame'] / 1000000);
1240 if (
$info[
'playtime_seconds'] > 0) {
1241 if (isset($thisfile_riff_audio) && isset($thisfile_riff_video)) {
1243 if (!isset(
$info[
'bitrate'])) {
1244 $info[
'bitrate'] = (((
$info[
'avdataend'] -
$info[
'avdataoffset']) /
$info[
'playtime_seconds']) * 8);
1247 } elseif (isset($thisfile_riff_audio) && !isset($thisfile_riff_video)) {
1249 if (!isset($thisfile_audio[
'bitrate'])) {
1250 $thisfile_audio[
'bitrate'] = (((
$info[
'avdataend'] -
$info[
'avdataoffset']) /
$info[
'playtime_seconds']) * 8);
1253 } elseif (!isset($thisfile_riff_audio) && isset($thisfile_riff_video)) {
1255 if (!isset($thisfile_video[
'bitrate'])) {
1256 $thisfile_video[
'bitrate'] = (((
$info[
'avdataend'] -
$info[
'avdataoffset']) /
$info[
'playtime_seconds']) * 8);
1263 if (isset($thisfile_riff_video) && isset($thisfile_audio[
'bitrate']) && ($thisfile_audio[
'bitrate'] > 0) && (
$info[
'playtime_seconds'] > 0)) {
1265 $info[
'bitrate'] = (((
$info[
'avdataend'] -
$info[
'avdataoffset']) /
$info[
'playtime_seconds']) * 8);
1266 $thisfile_audio[
'bitrate'] = 0;
1267 $thisfile_video[
'bitrate'] =
$info[
'bitrate'];
1268 foreach ($thisfile_riff_audio as $channelnumber => $audioinfoarray) {
1269 $thisfile_video[
'bitrate'] -= $audioinfoarray[
'bitrate'];
1270 $thisfile_audio[
'bitrate'] += $audioinfoarray[
'bitrate'];
1272 if ($thisfile_video[
'bitrate'] <= 0) {
1273 unset($thisfile_video[
'bitrate']);
1275 if ($thisfile_audio[
'bitrate'] <= 0) {
1276 unset($thisfile_audio[
'bitrate']);
1280 if (isset(
$info[
'mpeg'][
'audio'])) {
1281 $thisfile_audio_dataformat =
'mp'.$info[
'mpeg'][
'audio'][
'layer'];
1282 $thisfile_audio[
'sample_rate'] =
$info[
'mpeg'][
'audio'][
'sample_rate'];
1283 $thisfile_audio[
'channels'] =
$info[
'mpeg'][
'audio'][
'channels'];
1284 $thisfile_audio[
'bitrate'] =
$info[
'mpeg'][
'audio'][
'bitrate'];
1285 $thisfile_audio[
'bitrate_mode'] = strtolower(
$info[
'mpeg'][
'audio'][
'bitrate_mode']);
1286 if (!empty(
$info[
'mpeg'][
'audio'][
'codec'])) {
1287 $thisfile_audio[
'codec'] =
$info[
'mpeg'][
'audio'][
'codec'].
' '.$thisfile_audio[
'codec'];
1289 if (!empty($thisfile_audio[
'streams'])) {
1290 foreach ($thisfile_audio[
'streams'] as $streamnumber => $streamdata) {
1291 if ($streamdata[
'dataformat'] == $thisfile_audio_dataformat) {
1292 $thisfile_audio[
'streams'][$streamnumber][
'sample_rate'] = $thisfile_audio[
'sample_rate'];
1293 $thisfile_audio[
'streams'][$streamnumber][
'channels'] = $thisfile_audio[
'channels'];
1294 $thisfile_audio[
'streams'][$streamnumber][
'bitrate'] = $thisfile_audio[
'bitrate'];
1295 $thisfile_audio[
'streams'][$streamnumber][
'bitrate_mode'] = $thisfile_audio[
'bitrate_mode'];
1296 $thisfile_audio[
'streams'][$streamnumber][
'codec'] = $thisfile_audio[
'codec'];
1301 $thisfile_audio[
'encoder_options'] = $getid3_mp3->GuessEncoderOptions();
1306 if (!empty($thisfile_riff_raw[
'fmt '][
'wBitsPerSample']) && ($thisfile_riff_raw[
'fmt '][
'wBitsPerSample'] > 0)) {
1307 switch ($thisfile_audio_dataformat) {
1313 $thisfile_audio[
'bits_per_sample'] = $thisfile_riff_raw[
'fmt '][
'wBitsPerSample'];
1319 if (empty($thisfile_riff_raw)) {
1320 unset($thisfile_riff[
'raw']);
1322 if (empty($thisfile_riff_audio)) {
1323 unset($thisfile_riff[
'audio']);
1325 if (empty($thisfile_riff_video)) {
1326 unset($thisfile_riff[
'video']);
1351 $info = &$this->getid3->info;
1356 $this->
fseek($startoffset);
1357 $maxoffset = min($maxoffset,
$info[
'avdataend']);
1358 $AMVheader = $this->
fread(284);
1359 if (substr($AMVheader, 0, 8) !=
'hdrlamvh') {
1360 throw new Exception(
'expecting "hdrlamv" at offset '.($startoffset + 0).
', found "'.substr($AMVheader, 0, 8).
'"');
1362 if (substr($AMVheader, 8, 4) !=
"\x38\x00\x00\x00") {
1365 $RIFFchunk = array();
1367 $RIFFchunk[
'amvh'][
'reserved28'] = substr($AMVheader, 16, 28);
1377 $info[
'video'][
'frame_rate'] = 1000000 / $RIFFchunk[
'amvh'][
'us_per_frame'];
1378 $info[
'video'][
'resolution_x'] = $RIFFchunk[
'amvh'][
'resolution_x'];
1379 $info[
'video'][
'resolution_y'] = $RIFFchunk[
'amvh'][
'resolution_y'];
1380 $info[
'playtime_seconds'] = ($RIFFchunk[
'amvh'][
'runtime_hrs'] * 3600) + ($RIFFchunk[
'amvh'][
'runtime_min'] * 60) + $RIFFchunk[
'amvh'][
'runtime_sec'];
1384 if (substr($AMVheader, 68, 20) !=
'LIST'.
"\x00\x00\x00\x00".
'strlstrh'.
"\x38\x00\x00\x00") {
1385 throw new Exception(
'expecting "LIST<0x00000000>strlstrh<0x38000000>" at offset '.($startoffset + 68).
', found "'.
getid3_lib::PrintHexBytes(substr($AMVheader, 68, 20)).
'"');
1388 if (substr($AMVheader, 144, 8) !=
'strf'.
"\x24\x00\x00\x00") {
1393 if (substr($AMVheader, 188, 20) !=
'LIST'.
"\x00\x00\x00\x00".
'strlstrh'.
"\x30\x00\x00\x00") {
1394 throw new Exception(
'expecting "LIST<0x00000000>strlstrh<0x30000000>" at offset '.($startoffset + 188).
', found "'.
getid3_lib::PrintHexBytes(substr($AMVheader, 188, 20)).
'"');
1397 if (substr($AMVheader, 256, 8) !=
'strf'.
"\x14\x00\x00\x00") {
1421 $info[
'audio'][
'lossless'] =
false;
1422 $info[
'audio'][
'sample_rate'] = $RIFFchunk[
'strf'][
'nsamplespersec'];
1423 $info[
'audio'][
'channels'] = $RIFFchunk[
'strf'][
'nchannels'];
1424 $info[
'audio'][
'bits_per_sample'] = $RIFFchunk[
'strf'][
'wbitspersample'];
1425 $info[
'audio'][
'bitrate'] =
$info[
'audio'][
'sample_rate'] *
$info[
'audio'][
'channels'] *
$info[
'audio'][
'bits_per_sample'];
1426 $info[
'audio'][
'bitrate_mode'] =
'cbr';
1430 if ($e->getCode() == 10) {
1431 $this->
warning(
'RIFFAMV parser: '.$e->getMessage());
1442 $info = &$this->getid3->info;
1445 $FoundAllChunksWeNeed =
false;
1448 $this->
fseek($startoffset);
1449 $maxoffset = min($maxoffset,
$info[
'avdataend']);
1450 while ($this->
ftell() < $maxoffset) {
1451 $chunknamesize = $this->
fread(8);
1453 $chunkname = str_replace(
"\x00",
'_', substr($chunknamesize, 0, 4));
1456 if (strlen($chunkname) < 4) {
1457 $this->
error(
'Expecting chunk name at offset '.($this->
ftell() - 8).
' but found nothing. Aborting RIFF parsing.');
1460 if (($chunksize == 0) && ($chunkname !=
'JUNK')) {
1461 $this->
warning(
'Chunk ('.$chunkname.
') size at offset '.($this->ftell() - 4).
' is zero. Aborting RIFF parsing.');
1464 if (($chunksize % 2) != 0) {
1469 switch ($chunkname) {
1471 $listname = $this->
fread(4);
1472 if (preg_match(
'#^(movi|rec )$#i', $listname)) {
1473 $RIFFchunk[$listname][
'offset'] = $this->
ftell() - 4;
1474 $RIFFchunk[$listname][
'size'] = $chunksize;
1476 if (!$FoundAllChunksWeNeed) {
1477 $WhereWeWere = $this->
ftell();
1478 $AudioChunkHeader = $this->
fread(12);
1479 $AudioChunkStreamNum = substr($AudioChunkHeader, 0, 2);
1480 $AudioChunkStreamType = substr($AudioChunkHeader, 2, 2);
1483 if ($AudioChunkStreamType ==
'wb') {
1484 $FirstFourBytes = substr($AudioChunkHeader, 8, 4);
1485 if (preg_match(
'/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', $FirstFourBytes)) {
1488 $getid3_temp =
new getID3();
1489 $getid3_temp->openfile($this->getid3->filename);
1490 $getid3_temp->info[
'avdataoffset'] = $this->
ftell() - 4;
1491 $getid3_temp->info[
'avdataend'] = $this->
ftell() + $AudioChunkSize;
1492 $getid3_mp3 =
new getid3_mp3($getid3_temp, __CLASS__);
1493 $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info[
'avdataoffset'],
false);
1494 if (isset($getid3_temp->info[
'mpeg'][
'audio'])) {
1495 $info[
'mpeg'][
'audio'] = $getid3_temp->info[
'mpeg'][
'audio'];
1496 $info[
'audio'] = $getid3_temp->info[
'audio'];
1497 $info[
'audio'][
'dataformat'] =
'mp'.$info[
'mpeg'][
'audio'][
'layer'];
1498 $info[
'audio'][
'sample_rate'] =
$info[
'mpeg'][
'audio'][
'sample_rate'];
1499 $info[
'audio'][
'channels'] =
$info[
'mpeg'][
'audio'][
'channels'];
1500 $info[
'audio'][
'bitrate'] =
$info[
'mpeg'][
'audio'][
'bitrate'];
1501 $info[
'audio'][
'bitrate_mode'] = strtolower(
$info[
'mpeg'][
'audio'][
'bitrate_mode']);
1504 unset($getid3_temp, $getid3_mp3);
1510 $getid3_temp =
new getID3();
1511 $getid3_temp->openfile($this->getid3->filename);
1512 $getid3_temp->info[
'avdataoffset'] = $this->
ftell() - 4;
1513 $getid3_temp->info[
'avdataend'] = $this->
ftell() + $AudioChunkSize;
1515 $getid3_ac3->Analyze();
1516 if (empty($getid3_temp->info[
'error'])) {
1517 $info[
'audio'] = $getid3_temp->info[
'audio'];
1518 $info[
'ac3'] = $getid3_temp->info[
'ac3'];
1519 if (!empty($getid3_temp->info[
'warning'])) {
1520 foreach ($getid3_temp->info[
'warning'] as
$key => $value) {
1525 unset($getid3_temp, $getid3_ac3);
1528 $FoundAllChunksWeNeed =
true;
1529 $this->
fseek($WhereWeWere);
1531 $this->
fseek($chunksize - 4, SEEK_CUR);
1535 if (!isset($RIFFchunk[$listname])) {
1536 $RIFFchunk[$listname] = array();
1538 $LISTchunkParent = $listname;
1539 $LISTchunkMaxOffset = $this->
ftell() - 4 + $chunksize;
1540 if ($parsedChunk = $this->
ParseRIFF($this->
ftell(), $LISTchunkMaxOffset)) {
1541 $RIFFchunk[$listname] = array_merge_recursive($RIFFchunk[$listname], $parsedChunk);
1548 if (preg_match(
'#^[0-9]{2}(wb|pc|dc|db)$#', $chunkname)) {
1549 $this->
fseek($chunksize, SEEK_CUR);
1553 if (isset($RIFFchunk[$chunkname]) && is_array($RIFFchunk[$chunkname])) {
1554 $thisindex = count($RIFFchunk[$chunkname]);
1556 $RIFFchunk[$chunkname][$thisindex][
'offset'] = $this->
ftell() - 8;
1557 $RIFFchunk[$chunkname][$thisindex][
'size'] = $chunksize;
1558 switch ($chunkname) {
1561 $info[
'avdataend'] =
$info[
'avdataoffset'] + $chunksize;
1563 $testData = $this->
fread(36);
1564 if ($testData ===
'') {
1567 if (preg_match(
'/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', substr($testData, 0, 4))) {
1571 $getid3_temp =
new getID3();
1572 $getid3_temp->openfile($this->getid3->filename);
1573 $getid3_temp->info[
'avdataoffset'] =
$info[
'avdataoffset'];
1574 $getid3_temp->info[
'avdataend'] =
$info[
'avdataend'];
1575 $getid3_mp3 =
new getid3_mp3($getid3_temp, __CLASS__);
1576 $getid3_mp3->getOnlyMPEGaudioInfo(
$info[
'avdataoffset'],
false);
1577 if (empty($getid3_temp->info[
'error'])) {
1578 $info[
'audio'] = $getid3_temp->info[
'audio'];
1579 $info[
'mpeg'] = $getid3_temp->info[
'mpeg'];
1581 unset($getid3_temp, $getid3_mp3);
1587 $getid3_temp =
new getID3();
1588 if ($isRegularAC3) {
1589 $getid3_temp->openfile($this->getid3->filename);
1590 $getid3_temp->info[
'avdataoffset'] =
$info[
'avdataoffset'];
1591 $getid3_temp->info[
'avdataend'] =
$info[
'avdataend'];
1594 if ($isRegularAC3) {
1595 $getid3_ac3->Analyze();
1601 for (
$i = 0;
$i < 28;
$i += 2) {
1602 $ac3_data .= substr($testData, 8 +
$i + 1, 1);
1603 $ac3_data .= substr($testData, 8 +
$i + 0, 1);
1605 $getid3_ac3->AnalyzeString($ac3_data);
1608 if (empty($getid3_temp->info[
'error'])) {
1609 $info[
'audio'] = $getid3_temp->info[
'audio'];
1610 $info[
'ac3'] = $getid3_temp->info[
'ac3'];
1611 if (!empty($getid3_temp->info[
'warning'])) {
1612 foreach ($getid3_temp->info[
'warning'] as $newerror) {
1613 $this->
warning(
'getid3_ac3() says: ['.$newerror.
']');
1617 unset($getid3_temp, $getid3_ac3);
1619 } elseif (preg_match(
'/^('.implode(
'|', array_map(
'preg_quote',
getid3_dts::$syncwords)).
')/', $testData)) {
1622 $getid3_temp =
new getID3();
1623 $getid3_temp->openfile($this->getid3->filename);
1624 $getid3_temp->info[
'avdataoffset'] =
$info[
'avdataoffset'];
1626 $getid3_dts->Analyze();
1627 if (empty($getid3_temp->info[
'error'])) {
1628 $info[
'audio'] = $getid3_temp->info[
'audio'];
1629 $info[
'dts'] = $getid3_temp->info[
'dts'];
1630 $info[
'playtime_seconds'] = $getid3_temp->info[
'playtime_seconds'];
1631 if (!empty($getid3_temp->info[
'warning'])) {
1632 foreach ($getid3_temp->info[
'warning'] as $newerror) {
1633 $this->
warning(
'getid3_dts() says: ['.$newerror.
']');
1638 unset($getid3_temp, $getid3_dts);
1640 } elseif (substr($testData, 0, 4) ==
'wvpk') {
1643 $info[
'wavpack'][
'offset'] =
$info[
'avdataoffset'];
1651 $nextoffset =
$info[
'avdataend'];
1652 $this->
fseek($nextoffset);
1668 if ($chunksize < 1048576) {
1669 if ($chunksize > 0) {
1670 $RIFFchunk[$chunkname][$thisindex][
'data'] = $this->
fread($chunksize);
1671 if ($chunkname ==
'JUNK') {
1672 if (preg_match(
'#^([\\x20-\\x7F]+)#', $RIFFchunk[$chunkname][$thisindex][
'data'], $matches)) {
1674 $info[
'riff'][
'comments'][
'junk'][] = trim($matches[1]);
1678 unset($RIFFchunk[$chunkname][$thisindex][
'data']);
1682 $this->
warning(
'Chunk "'.$chunkname.
'" at offset '.$this->ftell().
' is unexpectedly larger than 1MB (claims to be '.number_format($chunksize).
' bytes), skipping data');
1683 $this->
fseek($chunksize, SEEK_CUR);
1692 if (!empty($LISTchunkParent) && (($RIFFchunk[$chunkname][$thisindex][
'offset'] + $RIFFchunk[$chunkname][$thisindex][
'size']) <= $LISTchunkMaxOffset)) {
1693 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex][
'offset'] = $RIFFchunk[$chunkname][$thisindex][
'offset'];
1694 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex][
'size'] = $RIFFchunk[$chunkname][$thisindex][
'size'];
1695 unset($RIFFchunk[$chunkname][$thisindex][
'offset']);
1696 unset($RIFFchunk[$chunkname][$thisindex][
'size']);
1697 if (isset($RIFFchunk[$chunkname][$thisindex]) && empty($RIFFchunk[$chunkname][$thisindex])) {
1698 unset($RIFFchunk[$chunkname][$thisindex]);
1700 if (isset($RIFFchunk[$chunkname]) && empty($RIFFchunk[$chunkname])) {
1701 unset($RIFFchunk[$chunkname]);
1703 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex][
'data'] = $this->
fread($chunksize);
1704 } elseif ($chunksize < 2048) {
1706 $RIFFchunk[$chunkname][$thisindex][
'data'] = $this->
fread($chunksize);
1708 $this->
fseek($chunksize, SEEK_CUR);
1717 if ($e->getCode() == 10) {
1718 $this->
warning(
'RIFF parser: '.$e->getMessage());
1728 $info = &$this->getid3->info;
1730 $tempfile = tempnam(GETID3_TEMP_DIR,
'getID3');
1731 $fp_temp =
fopen($tempfile,
'wb');
1732 $RIFFdataLength = strlen($RIFFdata);
1734 for (
$i = 0;
$i < 4;
$i++) {
1735 $RIFFdata[(
$i + 4)] = $NewLengthString[
$i];
1737 fwrite($fp_temp, $RIFFdata);
1740 $getid3_temp =
new getID3();
1741 $getid3_temp->openfile($tempfile);
1742 $getid3_temp->info[
'filesize'] = $RIFFdataLength;
1743 $getid3_temp->info[
'filenamepath'] =
$info[
'filenamepath'];
1744 $getid3_temp->info[
'tags'] =
$info[
'tags'];
1745 $getid3_temp->info[
'warning'] =
$info[
'warning'];
1746 $getid3_temp->info[
'error'] =
$info[
'error'];
1747 $getid3_temp->info[
'comments'] =
$info[
'comments'];
1748 $getid3_temp->info[
'audio'] = (isset(
$info[
'audio']) ?
$info[
'audio'] : array());
1749 $getid3_temp->info[
'video'] = (isset(
$info[
'video']) ?
$info[
'video'] : array());
1751 $getid3_riff->Analyze();
1753 $info[
'riff'] = $getid3_temp->info[
'riff'];
1754 $info[
'warning'] = $getid3_temp->info[
'warning'];
1755 $info[
'error'] = $getid3_temp->info[
'error'];
1756 $info[
'tags'] = $getid3_temp->info[
'tags'];
1757 $info[
'comments'] = $getid3_temp->info[
'comments'];
1758 unset($getid3_riff, $getid3_temp);
1765 $RIFFinfoKeyLookup = array(
1766 'IARL'=>
'archivallocation',
1768 'ICDS'=>
'costumedesigner',
1769 'ICMS'=>
'commissionedby',
1772 'ICOP'=>
'copyright',
1773 'ICRD'=>
'creationdate',
1774 'IDIM'=>
'dimensions',
1775 'IDIT'=>
'digitizationdate',
1776 'IDPI'=>
'resolution',
1777 'IDST'=>
'distributor',
1779 'IENG'=>
'engineers',
1780 'IFRM'=>
'accountofparts',
1783 'ILGT'=>
'lightness',
1785 'IMED'=>
'orignalmedium',
1788 'IPDS'=>
'productiondesigner',
1796 'ISGN'=>
'secondarygenre',
1797 'ISHP'=>
'sharpness',
1798 'ISRC'=>
'sourcesupplier',
1799 'ISRF'=>
'digitizationsource',
1800 'ISTD'=>
'productionstudio',
1802 'ITCH'=>
'encoded_by',
1807 foreach ($RIFFinfoKeyLookup as
$key => $value) {
1808 if (isset($RIFFinfoArray[
$key])) {
1809 foreach ($RIFFinfoArray[$key] as $commentid => $commentdata) {
1810 if (trim($commentdata[
'data']) !=
'') {
1811 if (isset($CommentsTargetArray[$value])) {
1812 $CommentsTargetArray[$value][] = trim($commentdata[
'data']);
1814 $CommentsTargetArray[$value] = array(trim($commentdata[
'data']));
1825 $WaveFormatEx[
'raw'] = array();
1826 $WaveFormatEx_raw = &$WaveFormatEx[
'raw'];
1828 $WaveFormatEx_raw[
'wFormatTag'] = substr($WaveFormatExData, 0, 2);
1829 $WaveFormatEx_raw[
'nChannels'] = substr($WaveFormatExData, 2, 2);
1830 $WaveFormatEx_raw[
'nSamplesPerSec'] = substr($WaveFormatExData, 4, 4);
1831 $WaveFormatEx_raw[
'nAvgBytesPerSec'] = substr($WaveFormatExData, 8, 4);
1832 $WaveFormatEx_raw[
'nBlockAlign'] = substr($WaveFormatExData, 12, 2);
1833 $WaveFormatEx_raw[
'wBitsPerSample'] = substr($WaveFormatExData, 14, 2);
1834 if (strlen($WaveFormatExData) > 16) {
1835 $WaveFormatEx_raw[
'cbSize'] = substr($WaveFormatExData, 16, 2);
1837 $WaveFormatEx_raw = array_map(
'getid3_lib::LittleEndian2Int', $WaveFormatEx_raw);
1839 $WaveFormatEx[
'codec'] = self::wFormatTagLookup($WaveFormatEx_raw[
'wFormatTag']);
1840 $WaveFormatEx[
'channels'] = $WaveFormatEx_raw[
'nChannels'];
1841 $WaveFormatEx[
'sample_rate'] = $WaveFormatEx_raw[
'nSamplesPerSec'];
1842 $WaveFormatEx[
'bitrate'] = $WaveFormatEx_raw[
'nAvgBytesPerSec'] * 8;
1843 $WaveFormatEx[
'bits_per_sample'] = $WaveFormatEx_raw[
'wBitsPerSample'];
1845 return $WaveFormatEx;
1860 $info = &$this->getid3->info;
1861 $info[
'wavpack'] = array();
1862 $thisfile_wavpack = &
$info[
'wavpack'];
1865 if ($thisfile_wavpack[
'version'] >= 2) {
1868 if ($thisfile_wavpack[
'version'] >= 3) {
1874 $thisfile_wavpack[
'extension'] = substr($WavPackChunkData, 20, 4);
1876 for (
$i = 0;
$i <= 2;
$i++) {
1881 $thisfile_wavpack[
'flags'] = array();
1882 $thisfile_wavpack_flags = &$thisfile_wavpack[
'flags'];
1884 $thisfile_wavpack_flags[
'mono'] = (bool) ($thisfile_wavpack[
'flags_raw'] & 0x000001);
1885 $thisfile_wavpack_flags[
'fast_mode'] = (bool) ($thisfile_wavpack[
'flags_raw'] & 0x000002);
1886 $thisfile_wavpack_flags[
'raw_mode'] = (bool) ($thisfile_wavpack[
'flags_raw'] & 0x000004);
1887 $thisfile_wavpack_flags[
'calc_noise'] = (bool) ($thisfile_wavpack[
'flags_raw'] & 0x000008);
1888 $thisfile_wavpack_flags[
'high_quality'] = (bool) ($thisfile_wavpack[
'flags_raw'] & 0x000010);
1889 $thisfile_wavpack_flags[
'3_byte_samples'] = (bool) ($thisfile_wavpack[
'flags_raw'] & 0x000020);
1890 $thisfile_wavpack_flags[
'over_20_bits'] = (bool) ($thisfile_wavpack[
'flags_raw'] & 0x000040);
1891 $thisfile_wavpack_flags[
'use_wvc'] = (bool) ($thisfile_wavpack[
'flags_raw'] & 0x000080);
1892 $thisfile_wavpack_flags[
'noiseshaping'] = (bool) ($thisfile_wavpack[
'flags_raw'] & 0x000100);
1893 $thisfile_wavpack_flags[
'very_fast_mode'] = (bool) ($thisfile_wavpack[
'flags_raw'] & 0x000200);
1894 $thisfile_wavpack_flags[
'new_high_quality'] = (bool) ($thisfile_wavpack[
'flags_raw'] & 0x000400);
1895 $thisfile_wavpack_flags[
'cancel_extreme'] = (bool) ($thisfile_wavpack[
'flags_raw'] & 0x000800);
1896 $thisfile_wavpack_flags[
'cross_decorrelation'] = (bool) ($thisfile_wavpack[
'flags_raw'] & 0x001000);
1897 $thisfile_wavpack_flags[
'new_decorrelation'] = (bool) ($thisfile_wavpack[
'flags_raw'] & 0x002000);
1898 $thisfile_wavpack_flags[
'joint_stereo'] = (bool) ($thisfile_wavpack[
'flags_raw'] & 0x004000);
1899 $thisfile_wavpack_flags[
'extra_decorrelation'] = (bool) ($thisfile_wavpack[
'flags_raw'] & 0x008000);
1900 $thisfile_wavpack_flags[
'override_noiseshape'] = (bool) ($thisfile_wavpack[
'flags_raw'] & 0x010000);
1901 $thisfile_wavpack_flags[
'override_jointstereo'] = (bool) ($thisfile_wavpack[
'flags_raw'] & 0x020000);
1902 $thisfile_wavpack_flags[
'copy_source_filetime'] = (bool) ($thisfile_wavpack[
'flags_raw'] & 0x040000);
1903 $thisfile_wavpack_flags[
'create_exe'] = (bool) ($thisfile_wavpack[
'flags_raw'] & 0x080000);
1911 $parsed[
'biSize'] = substr($BITMAPINFOHEADER, 0, 4);
1912 $parsed[
'biWidth'] = substr($BITMAPINFOHEADER, 4, 4);
1913 $parsed[
'biHeight'] = substr($BITMAPINFOHEADER, 8, 4);
1914 $parsed[
'biPlanes'] = substr($BITMAPINFOHEADER, 12, 2);
1915 $parsed[
'biBitCount'] = substr($BITMAPINFOHEADER, 14, 2);
1916 $parsed[
'biSizeImage'] = substr($BITMAPINFOHEADER, 20, 4);
1917 $parsed[
'biXPelsPerMeter'] = substr($BITMAPINFOHEADER, 24, 4);
1918 $parsed[
'biYPelsPerMeter'] = substr($BITMAPINFOHEADER, 28, 4);
1919 $parsed[
'biClrUsed'] = substr($BITMAPINFOHEADER, 32, 4);
1920 $parsed[
'biClrImportant'] = substr($BITMAPINFOHEADER, 36, 4);
1921 $parsed = array_map(
'getid3_lib::'.($littleEndian ?
'Little' :
'Big').
'Endian2Int', $parsed);
1923 $parsed[
'fourcc'] = substr($BITMAPINFOHEADER, 16, 4);
1941 static $DIVXTAGgenre = array(
1943 1 =>
'Action/Adventure',
1955 13 =>
'Infomercial',
1956 14 =>
'Interactive',
1958 16 =>
'Music Video',
1965 $DIVXTAGrating = array(
1974 $parsed[
'title'] = trim(substr($DIVXTAG, 0, 32));
1975 $parsed[
'artist'] = trim(substr($DIVXTAG, 32, 28));
1976 $parsed[
'year'] = intval(trim(substr($DIVXTAG, 60, 4)));
1977 $parsed[
'comment'] = trim(substr($DIVXTAG, 64, 48));
1978 $parsed[
'genre_id'] = intval(trim(substr($DIVXTAG, 112, 3)));
1979 $parsed[
'rating_id'] = ord(substr($DIVXTAG, 115, 1));
1983 $parsed[
'genre'] = (isset($DIVXTAGgenre[$parsed[
'genre_id']]) ? $DIVXTAGgenre[$parsed[
'genre_id']] : $parsed[
'genre_id']);
1984 $parsed[
'rating'] = (isset($DIVXTAGrating[$parsed[
'rating_id']]) ? $DIVXTAGrating[$parsed[
'rating_id']] : $parsed[
'rating_id']);
1987 unset($parsed[
'genre_id'], $parsed[
'rating_id']);
1988 foreach ($parsed as
$key => $value) {
1989 if (!$value ===
'') {
1990 unset($parsed[
'key']);
1995 foreach ($parsed as
$tag => $value) {
1996 $parsed[
$tag] = array($value);
2191 return getid3_lib::EmbeddedLookup(
'0x'.str_pad(strtoupper(dechex($wFormatTag)), 4,
'0', STR_PAD_LEFT), $begin, __LINE__, __FILE__,
'riff-wFormatTag');
2589 if ($this->container ==
'riff') {
static $syncwords
Possible syncwords indicating bitstream encoding.
ParseRIFFAMV($startoffset, $maxoffset)
ParseRIFF($startoffset, $maxoffset)
static ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true)
ParseRIFFdata(&$RIFFdata)
static EmbeddedLookup($key, $begin, $end, $file, $name)
static RGADnameLookup($namecode)
static waveSNDMtagLookup($tagshortname)
static RGADoriginatorLookup($originatorcode)
static MPEGaudioHeaderBytesValid($head4, $allowBitrate15=false)
static Bin2Dec($binstring, $signed=false)
static parseWAVEFORMATex($WaveFormatExData)
static LittleEndian2Int($byteword, $signed=false)
static IncludeDependency($filename, $sourcefile, $DieOnFailure=false)
static fourccLookup($fourcc)
static BigEndian2Float($byteword)
static RGADadjustmentLookup($rawadjustment, $signbit)
static XML2array($XMLstring)
EitherEndian2Int($byteword, $signed=false)
parseWavPackHeader($WavPackChunkData)
static DateMac2Unix($macdate)
static CastAsInt($floatnum)
static PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8')
static ParseDIVXTAG($DIVXTAG, $raw=false)
static LittleEndian2Float($byteword)
static parseComments(&$RIFFinfoArray, &$CommentsTargetArray)
static wFormatTagLookup($wFormatTag)
fseek($bytes, $whence=SEEK_SET)
static LittleEndian2String($number, $minbytes=1, $synchsafe=false)
static BigEndian2Int($byteword, $synchsafe=false, $signed=false)
if(function_exists('posix_getuid') &&posix_getuid()===0) if(!array_key_exists('t', $options)) $tag
getID3() by James Heinrich info@getid3.org //
getID3() by James Heinrich info@getid3.org //
static FixedPoint16_16($rawdata)
static array_merge_noclobber($array1, $array2)