50 {
51 $info = &$this->getid3->info;
52
53
54
55 $info[
'riff'] = array(
'raw'=>array());
56
57
58 $thisfile_riff = &
$info[
'riff'];
59 $thisfile_riff_raw = &$thisfile_riff['raw'];
60 $thisfile_audio = &
$info[
'audio'];
61 $thisfile_video = &
$info[
'video'];
62 $thisfile_audio_dataformat = &$thisfile_audio['dataformat'];
63 $thisfile_riff_audio = &$thisfile_riff['audio'];
64 $thisfile_riff_video = &$thisfile_riff['video'];
65
66
67 $Original[
'avdataoffset'] =
$info[
'avdataoffset'];
68 $Original[
'avdataend'] =
$info[
'avdataend'];
69
70 fseek($this->getid3->fp,
$info[
'avdataoffset'], SEEK_SET);
71 $RIFFheader =
fread($this->getid3->fp, 12);
72 $RIFFsubtype = substr($RIFFheader, 8, 4);
73 switch (substr($RIFFheader, 0, 4)) {
74 case 'FORM':
75 $info[
'fileformat'] =
'aiff';
76 $thisfile_riff[
'header_size'] = $this->
EitherEndian2Int(substr($RIFFheader, 4, 4));
77 $thisfile_riff[$RIFFsubtype] = $this->
ParseRIFF(
$info[
'avdataoffset'] + 12,
$info[
'avdataoffset'] + $thisfile_riff[
'header_size']);
78 break;
79
80 case 'RIFF':
81 case 'SDSS':
82 case 'RMP3':
83 $info[
'fileformat'] =
'riff';
84 $thisfile_riff[
'header_size'] = $this->
EitherEndian2Int(substr($RIFFheader, 4, 4));
85 if ($RIFFsubtype == 'RMP3') {
86
87 $RIFFsubtype = 'WAVE';
88 }
89 $thisfile_riff[$RIFFsubtype] = $this->
ParseRIFF(
$info[
'avdataoffset'] + 12,
$info[
'avdataoffset'] + $thisfile_riff[
'header_size']);
90 if ((
$info[
'avdataend'] -
$info[
'filesize']) == 1) {
91
92
93
95 }
96
97 $nextRIFFoffset = $Original['avdataoffset'] + 8 + $thisfile_riff['header_size'];
98 while ($nextRIFFoffset < min(
$info[
'filesize'],
$info[
'avdataend'])) {
100 $info[
'error'][] =
'AVI extends beyond '.round(PHP_INT_MAX / 1073741824).
'GB and PHP filesystem functions cannot read that far, playtime is probably wrong';
101 $info[
'warning'][] =
'[avdataend] value may be incorrect, multiple AVIX chunks may be present';
102 break;
103 } else {
104 fseek($this->getid3->fp, $nextRIFFoffset, SEEK_SET);
105 $nextRIFFheader =
fread($this->getid3->fp, 12);
106 if ($nextRIFFoffset == (
$info[
'avdataend'] - 1)) {
107 if (substr($nextRIFFheader, 0, 1) == "\x00") {
108
109 break;
110 }
111 }
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'];
119 switch ($nextRIFFheaderID) {
120 case 'RIFF':
121 $info[
'avdataend'] = $nextRIFFoffset;
123 $info[
'error'][] =
'AVI extends beyond '.round(PHP_INT_MAX / 1073741824).
'GB and PHP filesystem functions cannot read that far, playtime is probably wrong';
124 $info[
'warning'][] =
'[avdataend] value may be incorrect, multiple AVIX chunks may be present';
125 }
126 $chunkdata[
'chunks'] = $this->
ParseRIFF($chunkdata[
'offset'] + 4, $chunkdata[
'offset'] + $chunkdata[
'size']);
127
128 if (!isset($thisfile_riff[$nextRIFFtype])) {
129 $thisfile_riff[$nextRIFFtype] = array();
130 }
131 $thisfile_riff[$nextRIFFtype][] = $chunkdata;
132 break;
133 case 'JUNK':
134
135 $thisfile_riff[$nextRIFFheaderID][] = $chunkdata;
136 break;
137 default:
138 if (
$info[
'filesize'] == ($chunkdata[
'offset'] - 8 + 128)) {
139 $DIVXTAG = $nextRIFFheader.fread($this->getid3->fp, 128 - 12);
140 if (substr($DIVXTAG, -7) == 'DIVXTAG') {
141
142 $info[
'warning'][] =
'Found wrongly-structured DIVXTAG at offset '.(ftell($this->getid3->fp) - 128 + 12).
', parsing anyway';
143 $thisfile_riff[
'DIVXTAG'] = $this->
ParseDIVXTAG($DIVXTAG);
144 foreach ($thisfile_riff['DIVXTAG'] as $key => $value) {
145 if ($value && !preg_match('#_id$#', $key)) {
146 $thisfile_riff['comments'][$key][] = $value;
147 }
148 }
149 break 2;
150 }
151 }
152 $info[
'warning'][] =
'expecting "RIFF" or "JUNK" at '.$nextRIFFoffset.
', found '.
Helper::PrintHexBytes(substr($nextRIFFheader, 0, 4)).
' - skipping rest of file';
153 break 2;
154 }
155 }
156 }
157 if ($RIFFsubtype == 'WAVE') {
158 $thisfile_riff_WAVE = &$thisfile_riff['WAVE'];
159 }
160 break;
161
162 default:
163 $info[
'error'][] =
'Cannot parse RIFF (this is maybe not a RIFF / WAV / AVI file?) - expecting "FORM|RIFF|SDSS|RMP3" found "'.$RIFFsubtype.
'" instead';
164 unset(
$info[
'fileformat']);
165
166 return false;
167 break;
168 }
169
170 $streamindex = 0;
171 switch ($RIFFsubtype) {
172 case 'WAVE':
173 if (empty($thisfile_audio['bitrate_mode'])) {
174 $thisfile_audio['bitrate_mode'] = 'cbr';
175 }
176 if (empty($thisfile_audio_dataformat)) {
177 $thisfile_audio_dataformat = 'wav';
178 }
179
180 if (isset($thisfile_riff_WAVE['data'][0]['offset'])) {
181 $info[
'avdataoffset'] = $thisfile_riff_WAVE[
'data'][0][
'offset'] + 8;
182 $info[
'avdataend'] =
$info[
'avdataoffset'] + $thisfile_riff_WAVE[
'data'][0][
'size'];
183 }
184 if (isset($thisfile_riff_WAVE['fmt '][0]['data'])) {
185
187 $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
188 if (!isset($thisfile_riff_audio[$streamindex]['bitrate']) || ($thisfile_riff_audio[$streamindex]['bitrate'] == 0)) {
189 $info[
'error'][] =
'Corrupt RIFF file: bitrate_audio == zero';
190
191 return false;
192 }
193 $thisfile_riff_raw['fmt '] = $thisfile_riff_audio[$streamindex]['raw'];
194 unset($thisfile_riff_audio[$streamindex]['raw']);
195 $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
196
198 if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') {
199 $info[
'warning'][] =
'Audio codec = '.$thisfile_audio[
'codec'];
200 }
201 $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
202
203 $info[
'playtime_seconds'] = (float) (((
$info[
'avdataend'] -
$info[
'avdataoffset']) * 8) / $thisfile_audio[
'bitrate']);
204
205 $thisfile_audio['lossless'] = false;
206 if (isset($thisfile_riff_WAVE['data'][0]['offset']) && isset($thisfile_riff_raw['fmt ']['wFormatTag'])) {
207 switch ($thisfile_riff_raw['fmt ']['wFormatTag']) {
208
209 case 0x0001:
210 $thisfile_audio['lossless'] = true;
211 break;
212
213 case 0x2000:
214 $thisfile_audio_dataformat = 'ac3';
215 break;
216
217 default:
218
219 break;
220
221 }
222 }
223 $thisfile_audio['streams'][$streamindex]['wformattag'] = $thisfile_audio['wformattag'];
224 $thisfile_audio['streams'][$streamindex]['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
225 $thisfile_audio['streams'][$streamindex]['lossless'] = $thisfile_audio['lossless'];
226 $thisfile_audio['streams'][$streamindex]['dataformat'] = $thisfile_audio_dataformat;
227 }
228
229 if (isset($thisfile_riff_WAVE['rgad'][0]['data'])) {
230
231
232 $rgadData = &$thisfile_riff_WAVE['rgad'][0]['data'];
233 $thisfile_riff_raw['rgad'] = array('track'=>array(), 'album'=>array());
234 $thisfile_riff_raw_rgad = &$thisfile_riff_raw['rgad'];
235 $thisfile_riff_raw_rgad_track = &$thisfile_riff_raw_rgad['track'];
236 $thisfile_riff_raw_rgad_album = &$thisfile_riff_raw_rgad['album'];
237
239 $thisfile_riff_raw_rgad[
'nRadioRgAdjust'] = $this->
EitherEndian2Int(substr($rgadData, 4, 2));
240 $thisfile_riff_raw_rgad[
'nAudiophileRgAdjust'] = $this->
EitherEndian2Int(substr($rgadData, 6, 2));
241
242 $nRadioRgAdjustBitstring = str_pad(
Helper::Dec2Bin($thisfile_riff_raw_rgad[
'nRadioRgAdjust']), 16,
'0', STR_PAD_LEFT);
243 $nAudiophileRgAdjustBitstring = str_pad(
Helper::Dec2Bin($thisfile_riff_raw_rgad[
'nAudiophileRgAdjust']), 16,
'0', STR_PAD_LEFT);
244 $thisfile_riff_raw_rgad_track[
'name'] =
Helper::Bin2Dec(substr($nRadioRgAdjustBitstring, 0, 3));
245 $thisfile_riff_raw_rgad_track[
'originator'] =
Helper::Bin2Dec(substr($nRadioRgAdjustBitstring, 3, 3));
246 $thisfile_riff_raw_rgad_track[
'signbit'] =
Helper::Bin2Dec(substr($nRadioRgAdjustBitstring, 6, 1));
247 $thisfile_riff_raw_rgad_track[
'adjustment'] =
Helper::Bin2Dec(substr($nRadioRgAdjustBitstring, 7, 9));
248 $thisfile_riff_raw_rgad_album[
'name'] =
Helper::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 0, 3));
249 $thisfile_riff_raw_rgad_album[
'originator'] =
Helper::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 3, 3));
250 $thisfile_riff_raw_rgad_album[
'signbit'] =
Helper::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 6, 1));
251 $thisfile_riff_raw_rgad_album[
'adjustment'] =
Helper::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 7, 9));
252
253 $thisfile_riff['rgad']['peakamplitude'] = $thisfile_riff_raw_rgad['fPeakAmplitude'];
254 if (($thisfile_riff_raw_rgad_track['name'] != 0) && ($thisfile_riff_raw_rgad_track['originator'] != 0)) {
257 $thisfile_riff[
'rgad'][
'track'][
'adjustment'] =
Helper::RGADadjustmentLookup($thisfile_riff_raw_rgad_track[
'adjustment'], $thisfile_riff_raw_rgad_track[
'signbit']);
258 }
259 if (($thisfile_riff_raw_rgad_album['name'] != 0) && ($thisfile_riff_raw_rgad_album['originator'] != 0)) {
262 $thisfile_riff[
'rgad'][
'album'][
'adjustment'] =
Helper::RGADadjustmentLookup($thisfile_riff_raw_rgad_album[
'adjustment'], $thisfile_riff_raw_rgad_album[
'signbit']);
263 }
264 }
265
266 if (isset($thisfile_riff_WAVE['fact'][0]['data'])) {
267 $thisfile_riff_raw[
'fact'][
'NumberOfSamples'] = $this->
EitherEndian2Int(substr($thisfile_riff_WAVE[
'fact'][0][
'data'], 0, 4));
268
269
270
271
272
273
274
275
276 }
277 if (!empty($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'])) {
278 $thisfile_audio[
'bitrate'] =
Helper::CastAsInt($thisfile_riff_raw[
'fmt '][
'nAvgBytesPerSec'] * 8);
279 }
280
281 if (isset($thisfile_riff_WAVE['bext'][0]['data'])) {
282
283 $thisfile_riff_WAVE_bext_0 = &$thisfile_riff_WAVE['bext'][0];
284
285 $thisfile_riff_WAVE_bext_0['title'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 0, 256));
286 $thisfile_riff_WAVE_bext_0['author'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 256, 32));
287 $thisfile_riff_WAVE_bext_0['reference'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 288, 32));
288 $thisfile_riff_WAVE_bext_0['origin_date'] = substr($thisfile_riff_WAVE_bext_0['data'], 320, 10);
289 $thisfile_riff_WAVE_bext_0['origin_time'] = substr($thisfile_riff_WAVE_bext_0['data'], 330, 8);
290 $thisfile_riff_WAVE_bext_0[
'time_reference'] =
Helper::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0[
'data'], 338, 8));
291 $thisfile_riff_WAVE_bext_0[
'bwf_version'] =
Helper::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0[
'data'], 346, 1));
292 $thisfile_riff_WAVE_bext_0['reserved'] = substr($thisfile_riff_WAVE_bext_0['data'], 347, 254);
293 $thisfile_riff_WAVE_bext_0['coding_history'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_bext_0['data'], 601)));
294 if (preg_match('#^([0-9]{4}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_date'], $matches_bext_date)) {
295 if (preg_match('#^([0-9]{2}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_time'], $matches_bext_time)) {
296 list($dummy, $bext_timestamp['year'], $bext_timestamp['month'], $bext_timestamp['day']) = $matches_bext_date;
297 list($dummy, $bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second']) = $matches_bext_time;
298 $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']);
299 } else {
300 $info[
'warning'][] =
'RIFF.WAVE.BEXT.origin_time is invalid';
301 }
302 } else {
303 $info[
'warning'][] =
'RIFF.WAVE.BEXT.origin_date is invalid';
304 }
305 $thisfile_riff['comments']['author'][] = $thisfile_riff_WAVE_bext_0['author'];
306 $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_bext_0['title'];
307 }
308
309 if (isset($thisfile_riff_WAVE['MEXT'][0]['data'])) {
310
311 $thisfile_riff_WAVE_MEXT_0 = &$thisfile_riff_WAVE['MEXT'][0];
312
313 $thisfile_riff_WAVE_MEXT_0[
'raw'][
'sound_information'] =
Helper::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0[
'data'], 0, 2));
314 $thisfile_riff_WAVE_MEXT_0['flags']['homogenous'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0001);
315 if ($thisfile_riff_WAVE_MEXT_0['flags']['homogenous']) {
316 $thisfile_riff_WAVE_MEXT_0['flags']['padding'] = ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0002) ? false : true;
317 $thisfile_riff_WAVE_MEXT_0['flags']['22_or_44'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0004);
318 $thisfile_riff_WAVE_MEXT_0['flags']['free_format'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0008);
319
320 $thisfile_riff_WAVE_MEXT_0[
'nominal_frame_size'] =
Helper::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0[
'data'], 2, 2));
321 }
322 $thisfile_riff_WAVE_MEXT_0[
'anciliary_data_length'] =
Helper::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0[
'data'], 6, 2));
323 $thisfile_riff_WAVE_MEXT_0[
'raw'][
'anciliary_data_def'] =
Helper::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0[
'data'], 8, 2));
324 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_left'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0001);
325 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_free'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0002);
326 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_right'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0004);
327 }
328
329 if (isset($thisfile_riff_WAVE['cart'][0]['data'])) {
330
331 $thisfile_riff_WAVE_cart_0 = &$thisfile_riff_WAVE['cart'][0];
332
333 $thisfile_riff_WAVE_cart_0['version'] = substr($thisfile_riff_WAVE_cart_0['data'], 0, 4);
334 $thisfile_riff_WAVE_cart_0['title'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 4, 64));
335 $thisfile_riff_WAVE_cart_0['artist'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 68, 64));
336 $thisfile_riff_WAVE_cart_0['cut_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 132, 64));
337 $thisfile_riff_WAVE_cart_0['client_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 196, 64));
338 $thisfile_riff_WAVE_cart_0['category'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 260, 64));
339 $thisfile_riff_WAVE_cart_0['classification'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 324, 64));
340 $thisfile_riff_WAVE_cart_0['out_cue'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 388, 64));
341 $thisfile_riff_WAVE_cart_0['start_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 452, 10));
342 $thisfile_riff_WAVE_cart_0['start_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 462, 8));
343 $thisfile_riff_WAVE_cart_0['end_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 470, 10));
344 $thisfile_riff_WAVE_cart_0['end_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 480, 8));
345 $thisfile_riff_WAVE_cart_0['producer_app_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 488, 64));
346 $thisfile_riff_WAVE_cart_0['producer_app_version'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 552, 64));
347 $thisfile_riff_WAVE_cart_0['user_defined_text'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 616, 64));
348 $thisfile_riff_WAVE_cart_0[
'zero_db_reference'] =
Helper::LittleEndian2Int(substr($thisfile_riff_WAVE_cart_0[
'data'], 680, 4),
true);
349 for ($i = 0; $i < 8; $i++) {
350 $thisfile_riff_WAVE_cart_0['post_time'][$i]['usage_fourcc'] = substr($thisfile_riff_WAVE_cart_0['data'], 684 + ($i * 8), 4);
351 $thisfile_riff_WAVE_cart_0[
'post_time'][$i][
'timer_value'] =
Helper::LittleEndian2Int(substr($thisfile_riff_WAVE_cart_0[
'data'], 684 + ($i * 8) + 4, 4));
352 }
353 $thisfile_riff_WAVE_cart_0['url'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 748, 1024));
354 $thisfile_riff_WAVE_cart_0['tag_text'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_cart_0['data'], 1772)));
355
356 $thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist'];
357 $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_cart_0['title'];
358 }
359
360 if (isset($thisfile_riff_WAVE['SNDM'][0]['data'])) {
361
362
363
364 $thisfile_riff_WAVE_SNDM_0 = &$thisfile_riff_WAVE['SNDM'][0];
365 $thisfile_riff_WAVE_SNDM_0_data = &$thisfile_riff_WAVE_SNDM_0['data'];
366 $SNDM_startoffset = 0;
367 $SNDM_endoffset = $thisfile_riff_WAVE_SNDM_0['size'];
368
369 while ($SNDM_startoffset < $SNDM_endoffset) {
370 $SNDM_thisTagOffset = 0;
371 $SNDM_thisTagSize =
Helper::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4));
372 $SNDM_thisTagOffset += 4;
373 $SNDM_thisTagKey = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4);
374 $SNDM_thisTagOffset += 4;
375 $SNDM_thisTagDataSize =
Helper::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2));
376 $SNDM_thisTagOffset += 2;
377 $SNDM_thisTagDataFlags =
Helper::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2));
378 $SNDM_thisTagOffset += 2;
379 $SNDM_thisTagDataText = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, $SNDM_thisTagDataSize);
380 $SNDM_thisTagOffset += $SNDM_thisTagDataSize;
381
382 if ($SNDM_thisTagSize != (4 + 4 + 2 + 2 + $SNDM_thisTagDataSize)) {
383 $info[
'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).
')';
384 break;
385 } elseif ($SNDM_thisTagSize <= 0) {
386 $info[
'warning'][] =
'RIFF.WAVE.SNDM.data contains zero-size tag at offset '.$SNDM_startoffset.
' (file offset '.($thisfile_riff_WAVE_SNDM_0[
'offset'] + $SNDM_startoffset).
')';
387 break;
388 }
389 $SNDM_startoffset += $SNDM_thisTagSize;
390
391 $thisfile_riff_WAVE_SNDM_0['parsed_raw'][$SNDM_thisTagKey] = $SNDM_thisTagDataText;
393 $thisfile_riff_WAVE_SNDM_0['parsed'][$parsedkey] = $SNDM_thisTagDataText;
394 } else {
395 $info[
'warning'][] =
'RIFF.WAVE.SNDM contains unknown tag "'.$SNDM_thisTagKey.
'" at offset '.$SNDM_startoffset.
' (file offset '.($thisfile_riff_WAVE_SNDM_0[
'offset'] + $SNDM_startoffset).
')';
396 }
397 }
398
399 $tagmapping = array(
400 'tracktitle'=>'title',
401 'category' =>'genre',
402 'cdtitle' =>'album',
403 'tracktitle'=>'title',
404 );
405 foreach ($tagmapping as $fromkey => $tokey) {
406 if (isset($thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey])) {
407 $thisfile_riff['comments'][$tokey][] = $thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey];
408 }
409 }
410 }
411
412 if (isset($thisfile_riff_WAVE['iXML'][0]['data'])) {
413
415 $thisfile_riff_WAVE['iXML'][0]['parsed'] = $parsedXML;
416 if (isset($parsedXML['SPEED']['MASTER_SPEED'])) {
417 @list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['MASTER_SPEED']);
418 $thisfile_riff_WAVE['iXML'][0]['master_speed'] = $numerator / ($denominator ? $denominator : 1000);
419 }
420 if (isset($parsedXML['SPEED']['TIMECODE_RATE'])) {
421 @list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['TIMECODE_RATE']);
422 $thisfile_riff_WAVE['iXML'][0]['timecode_rate'] = $numerator / ($denominator ? $denominator : 1000);
423 }
424 if (isset($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO']) && !empty($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) && !empty($thisfile_riff_WAVE['iXML'][0]['timecode_rate'])) {
425 $samples_since_midnight = floatval(ltrim($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_HI'].$parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO'], '0'));
426 $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] = $samples_since_midnight / $parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE'];
427 $h = floor( $thisfile_riff_WAVE[
'iXML'][0][
'timecode_seconds'] / 3600);
428 $m = floor(($thisfile_riff_WAVE[
'iXML'][0][
'timecode_seconds'] - (
$h * 3600)) / 60);
429 $s = floor( $thisfile_riff_WAVE[
'iXML'][0][
'timecode_seconds'] - (
$h * 3600) - ($m * 60));
430 $f = ($thisfile_riff_WAVE[
'iXML'][0][
'timecode_seconds'] - (
$h * 3600) - ($m * 60) - $s) * $thisfile_riff_WAVE[
'iXML'][0][
'timecode_rate'];
431 $thisfile_riff_WAVE[
'iXML'][0][
'timecode_string'] =
sprintf(
'%02d:%02d:%02d:%05.2f',
$h, $m, $s, $f);
432 $thisfile_riff_WAVE[
'iXML'][0][
'timecode_string_round'] =
sprintf(
'%02d:%02d:%02d:%02d',
$h, $m, $s, round($f));
433 }
434 unset($parsedXML);
435 }
436 }
437
438 if (!isset($thisfile_audio['bitrate']) && isset($thisfile_riff_audio[$streamindex]['bitrate'])) {
439 $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
440 $info[
'playtime_seconds'] = (float) (((
$info[
'avdataend'] -
$info[
'avdataoffset']) * 8) / $thisfile_audio[
'bitrate']);
441 }
442
443 if (!empty(
$info[
'wavpack'])) {
444 $thisfile_audio_dataformat = 'wavpack';
445 $thisfile_audio['bitrate_mode'] = 'vbr';
446 $thisfile_audio['encoder'] = 'WavPack v'.$info['wavpack']['version'];
447
448
449 $info[
'avdataend'] = $Original[
'avdataend'];
450 $thisfile_audio[
'bitrate'] = ((
$info[
'avdataend'] -
$info[
'avdataoffset']) * 8) /
$info[
'playtime_seconds'];
451
452 fseek($this->getid3->fp,
$info[
'avdataoffset'] - 44, SEEK_SET);
453 $RIFFdata =
fread($this->getid3->fp, 44);
456
457 if ($OrignalRIFFheaderSize > $OrignalRIFFdataSize) {
458 $info[
'avdataend'] -= ($OrignalRIFFheaderSize - $OrignalRIFFdataSize);
459 fseek($this->getid3->fp,
$info[
'avdataend'], SEEK_SET);
460 $RIFFdata .=
fread($this->getid3->fp, $OrignalRIFFheaderSize - $OrignalRIFFdataSize);
461 }
462
463
464
465
466 $RIFFdata = substr($RIFFdata, 0, 36).substr($RIFFdata, 44).substr($RIFFdata, 36, 8);
468 $getid3_riff->ParseRIFFdata($RIFFdata);
469 unset($getid3_riff);
470 }
471
472 if (isset($thisfile_riff_raw['fmt ']['wFormatTag'])) {
473 switch ($thisfile_riff_raw['fmt ']['wFormatTag']) {
474 case 0x0001:
475 if (!empty(
$info[
'ac3'])) {
476
477 $thisfile_audio['wformattag'] = 0x2000;
479 $thisfile_audio['lossless'] = false;
480 $thisfile_audio[
'bitrate'] =
$info[
'ac3'][
'bitrate'];
481 $thisfile_audio[
'sample_rate'] =
$info[
'ac3'][
'sample_rate'];
482 }
483 break;
484 case 0x08AE:
485 $thisfile_audio['bitrate_mode'] = 'vbr';
486 $thisfile_audio_dataformat = 'litewave';
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505 $thisfile_riff['litewave']['raw'] = array();
506 $thisfile_riff_litewave = &$thisfile_riff['litewave'];
507 $thisfile_riff_litewave_raw = &$thisfile_riff_litewave['raw'];
508
509 $thisfile_riff_litewave_raw[
'compression_method'] =
Helper::LittleEndian2Int(substr($thisfile_riff_WAVE[
'fmt '][0][
'data'], 18, 1));
510 $thisfile_riff_litewave_raw[
'compression_flags'] =
Helper::LittleEndian2Int(substr($thisfile_riff_WAVE[
'fmt '][0][
'data'], 19, 1));
511 $thisfile_riff_litewave_raw[
'm_dwScale'] =
Helper::LittleEndian2Int(substr($thisfile_riff_WAVE[
'fmt '][0][
'data'], 20, 4));
512 $thisfile_riff_litewave_raw[
'm_dwBlockSize'] =
Helper::LittleEndian2Int(substr($thisfile_riff_WAVE[
'fmt '][0][
'data'], 24, 4));
513 $thisfile_riff_litewave_raw[
'm_wQuality'] =
Helper::LittleEndian2Int(substr($thisfile_riff_WAVE[
'fmt '][0][
'data'], 28, 2));
514 $thisfile_riff_litewave_raw[
'm_wMarkDistance'] =
Helper::LittleEndian2Int(substr($thisfile_riff_WAVE[
'fmt '][0][
'data'], 30, 2));
515 $thisfile_riff_litewave_raw[
'm_wReserved'] =
Helper::LittleEndian2Int(substr($thisfile_riff_WAVE[
'fmt '][0][
'data'], 32, 2));
516 $thisfile_riff_litewave_raw[
'm_dwOrgSize'] =
Helper::LittleEndian2Int(substr($thisfile_riff_WAVE[
'fmt '][0][
'data'], 34, 4));
517 $thisfile_riff_litewave_raw[
'm_bFactExists'] =
Helper::LittleEndian2Int(substr($thisfile_riff_WAVE[
'fmt '][0][
'data'], 38, 2));
518 $thisfile_riff_litewave_raw[
'm_dwRiffChunkSize'] =
Helper::LittleEndian2Int(substr($thisfile_riff_WAVE[
'fmt '][0][
'data'], 40, 4));
519
520
521 $thisfile_riff_litewave['quality_factor'] = $thisfile_riff_litewave_raw['m_wQuality'];
522
523 $thisfile_riff_litewave['flags']['raw_source'] = ($thisfile_riff_litewave_raw['compression_flags'] & 0x01) ? false : true;
524 $thisfile_riff_litewave['flags']['vbr_blocksize'] = ($thisfile_riff_litewave_raw['compression_flags'] & 0x02) ? false : true;
525 $thisfile_riff_litewave['flags']['seekpoints'] = (bool) ($thisfile_riff_litewave_raw['compression_flags'] & 0x04);
526
527 $thisfile_audio['lossless'] = (($thisfile_riff_litewave_raw['m_wQuality'] == 100) ? true : false);
528 $thisfile_audio['encoder_options'] = '-q'.$thisfile_riff_litewave['quality_factor'];
529 break;
530
531 default:
532 break;
533 }
534 }
536 switch (!empty($thisfile_audio_dataformat) ? $thisfile_audio_dataformat : '') {
537 case 'wavpack':
538 case 'lpac':
539 case 'ofr':
540 case 'ofs':
541
542 break;
543
544 case 'litewave':
545 if ((
$info[
'avdataend'] -
$info[
'filesize']) == 1) {
546
547
548
549 } else {
550
551 $info[
'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)';
553 }
554 break;
555
556 default:
557 if (((
$info[
'avdataend'] -
$info[
'filesize']) == 1) && (($thisfile_riff[$RIFFsubtype][
'data'][0][
'size'] % 2) == 0) && (((
$info[
'filesize'] -
$info[
'avdataoffset']) % 2) == 1)) {
558
559
560 $info[
'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)';
562 } else {
563
564 $info[
'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)';
566 }
567 break;
568 }
569 }
570 if (!empty(
$info[
'mpeg'][
'audio'][
'LAME'][
'audio_bytes'])) {
571 if (((
$info[
'avdataend'] -
$info[
'avdataoffset']) -
$info[
'mpeg'][
'audio'][
'LAME'][
'audio_bytes']) == 1) {
572 $info[
'avdataend']--;
573 $info[
'warning'][] =
'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored';
574 }
575 }
576 if (isset($thisfile_audio_dataformat) && ($thisfile_audio_dataformat == 'ac3')) {
577 unset($thisfile_audio['bits_per_sample']);
578 if (!empty(
$info[
'ac3'][
'bitrate']) && (
$info[
'ac3'][
'bitrate'] != $thisfile_audio[
'bitrate'])) {
579 $thisfile_audio[
'bitrate'] =
$info[
'ac3'][
'bitrate'];
580 }
581 }
582 break;
583
584 case 'AVI ':
585 $thisfile_video['bitrate_mode'] = 'vbr';
586 $thisfile_video['dataformat'] = 'avi';
587 $info[
'mime_type'] =
'video/avi';
588
589 if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) {
590 $info[
'avdataoffset'] = $thisfile_riff[$RIFFsubtype][
'movi'][
'offset'] + 8;
591 if (isset($thisfile_riff['AVIX'])) {
592 $info[
'avdataend'] = $thisfile_riff[
'AVIX'][(count($thisfile_riff[
'AVIX']) - 1)][
'chunks'][
'movi'][
'offset'] + $thisfile_riff[
'AVIX'][(count($thisfile_riff[
'AVIX']) - 1)][
'chunks'][
'movi'][
'size'];
593 } else {
594 $info[
'avdataend'] = $thisfile_riff[
'AVI '][
'movi'][
'offset'] + $thisfile_riff[
'AVI '][
'movi'][
'size'];
595 }
597 $info[
'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)';
599 }
600 }
601
602 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['indx'])) {
603
604
605
606
607
608
609
610
611
612
613 foreach ($thisfile_riff['AVI ']['hdrl']['strl']['indx'] as $streamnumber => $steamdataarray) {
614 $thisfile_riff_avi_hdrl_strl_indx_stream_data = &$thisfile_riff['AVI ']['hdrl']['strl']['indx'][$streamnumber]['data'];
615
616 $thisfile_riff_raw[
'indx'][$streamnumber][
'wLongsPerEntry'] = $this->
EitherEndian2Int(substr($thisfile_riff_avi_hdrl_strl_indx_stream_data, 0, 2));
617 $thisfile_riff_raw[
'indx'][$streamnumber][
'bIndexSubType'] = $this->
EitherEndian2Int(substr($thisfile_riff_avi_hdrl_strl_indx_stream_data, 2, 1));
618 $thisfile_riff_raw[
'indx'][$streamnumber][
'bIndexType'] = $this->
EitherEndian2Int(substr($thisfile_riff_avi_hdrl_strl_indx_stream_data, 3, 1));
619 $thisfile_riff_raw[
'indx'][$streamnumber][
'nEntriesInUse'] = $this->
EitherEndian2Int(substr($thisfile_riff_avi_hdrl_strl_indx_stream_data, 4, 4));
620 $thisfile_riff_raw['indx'][$streamnumber]['dwChunkId'] = substr($thisfile_riff_avi_hdrl_strl_indx_stream_data, 8, 4);
621 $thisfile_riff_raw[
'indx'][$streamnumber][
'dwReserved'] = $this->
EitherEndian2Int(substr($thisfile_riff_avi_hdrl_strl_indx_stream_data, 12, 4));
622
623
624
625
626 unset($thisfile_riff_avi_hdrl_strl_indx_stream_data);
627 }
628 }
629 if (isset($thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'])) {
630 $avihData = $thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'];
631
632
633 $thisfile_riff_raw['avih'] = array();
634 $thisfile_riff_raw_avih = &$thisfile_riff_raw['avih'];
635
636 $thisfile_riff_raw_avih[
'dwMicroSecPerFrame'] = $this->
EitherEndian2Int(substr($avihData, 0, 4));
637 if ($thisfile_riff_raw_avih['dwMicroSecPerFrame'] == 0) {
638 $info[
'error'][] =
'Corrupt RIFF file: avih.dwMicroSecPerFrame == zero';
639
640 return false;
641 }
642 $thisfile_riff_raw_avih[
'dwMaxBytesPerSec'] = $this->
EitherEndian2Int(substr($avihData, 4, 4));
643 $thisfile_riff_raw_avih[
'dwPaddingGranularity'] = $this->
EitherEndian2Int(substr($avihData, 8, 4));
644 $thisfile_riff_raw_avih[
'dwFlags'] = $this->
EitherEndian2Int(substr($avihData, 12, 4));
645 $thisfile_riff_raw_avih[
'dwTotalFrames'] = $this->
EitherEndian2Int(substr($avihData, 16, 4));
646 $thisfile_riff_raw_avih[
'dwInitialFrames'] = $this->
EitherEndian2Int(substr($avihData, 20, 4));
647 $thisfile_riff_raw_avih[
'dwStreams'] = $this->
EitherEndian2Int(substr($avihData, 24, 4));
648 $thisfile_riff_raw_avih[
'dwSuggestedBufferSize'] = $this->
EitherEndian2Int(substr($avihData, 28, 4));
649 $thisfile_riff_raw_avih[
'dwWidth'] = $this->
EitherEndian2Int(substr($avihData, 32, 4));
650 $thisfile_riff_raw_avih[
'dwHeight'] = $this->
EitherEndian2Int(substr($avihData, 36, 4));
651 $thisfile_riff_raw_avih[
'dwScale'] = $this->
EitherEndian2Int(substr($avihData, 40, 4));
652 $thisfile_riff_raw_avih[
'dwRate'] = $this->
EitherEndian2Int(substr($avihData, 44, 4));
653 $thisfile_riff_raw_avih[
'dwStart'] = $this->
EitherEndian2Int(substr($avihData, 48, 4));
654 $thisfile_riff_raw_avih[
'dwLength'] = $this->
EitherEndian2Int(substr($avihData, 52, 4));
655
656 $thisfile_riff_raw_avih['flags']['hasindex'] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & 0x00000010);
657 $thisfile_riff_raw_avih['flags']['mustuseindex'] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & 0x00000020);
658 $thisfile_riff_raw_avih['flags']['interleaved'] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & 0x00000100);
659 $thisfile_riff_raw_avih['flags']['trustcktype'] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & 0x00000800);
660 $thisfile_riff_raw_avih['flags']['capturedfile'] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & 0x00010000);
661 $thisfile_riff_raw_avih['flags']['copyrighted'] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & 0x00020010);
662
663
664 $thisfile_riff_video[$streamindex] = array();
665 $thisfile_riff_video_current = &$thisfile_riff_video[$streamindex];
666
667 if ($thisfile_riff_raw_avih['dwWidth'] > 0) {
668 $thisfile_riff_video_current['frame_width'] = $thisfile_riff_raw_avih['dwWidth'];
669 $thisfile_video['resolution_x'] = $thisfile_riff_video_current['frame_width'];
670 }
671 if ($thisfile_riff_raw_avih['dwHeight'] > 0) {
672 $thisfile_riff_video_current['frame_height'] = $thisfile_riff_raw_avih['dwHeight'];
673 $thisfile_video['resolution_y'] = $thisfile_riff_video_current['frame_height'];
674 }
675 if ($thisfile_riff_raw_avih['dwTotalFrames'] > 0) {
676 $thisfile_riff_video_current['total_frames'] = $thisfile_riff_raw_avih['dwTotalFrames'];
677 $thisfile_video['total_frames'] = $thisfile_riff_video_current['total_frames'];
678 }
679
680 $thisfile_riff_video_current['frame_rate'] = round(1000000 / $thisfile_riff_raw_avih['dwMicroSecPerFrame'], 3);
681 $thisfile_video['frame_rate'] = $thisfile_riff_video_current['frame_rate'];
682 }
683 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][0]['data'])) {
684 if (is_array($thisfile_riff['AVI ']['hdrl']['strl']['strh'])) {
685 for ($i = 0; $i < count($thisfile_riff['AVI ']['hdrl']['strl']['strh']); $i++) {
686 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'])) {
687 $strhData = $thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'];
688 $strhfccType = substr($strhData, 0, 4);
689
690 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'])) {
691 $strfData = $thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'];
692
693
694 $thisfile_riff_raw_strf_strhfccType_streamindex = &$thisfile_riff_raw['strf'][$strhfccType][$streamindex];
695
696 switch ($strhfccType) {
697 case 'auds':
698 $thisfile_audio['bitrate_mode'] = 'cbr';
699 $thisfile_audio_dataformat = 'wav';
700 if (isset($thisfile_riff_audio) && is_array($thisfile_riff_audio)) {
701 $streamindex = count($thisfile_riff_audio);
702 }
703
705 $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
706
707
708 $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
709 $thisfile_audio_streams_currentstream = &$thisfile_audio['streams'][$streamindex];
710
711 if ($thisfile_audio_streams_currentstream['bits_per_sample'] == 0) {
712 unset($thisfile_audio_streams_currentstream['bits_per_sample']);
713 }
714 $thisfile_audio_streams_currentstream['wformattag'] = $thisfile_audio_streams_currentstream['raw']['wFormatTag'];
715 unset($thisfile_audio_streams_currentstream['raw']);
716
717
718 $thisfile_riff_raw['strf'][$strhfccType][$streamindex] = $thisfile_riff_audio[$streamindex]['raw'];
719
720 unset($thisfile_riff_audio[$streamindex]['raw']);
722
723 $thisfile_audio['lossless'] = false;
724 switch ($thisfile_riff_raw_strf_strhfccType_streamindex['wFormatTag']) {
725 case 0x0001:
726 $thisfile_audio_dataformat = 'wav';
727 $thisfile_audio['lossless'] = true;
728 break;
729
730 case 0x0050:
731 $thisfile_audio_dataformat = 'mp2';
732 break;
733
734 case 0x0055:
735 $thisfile_audio_dataformat = 'mp3';
736 break;
737
738 case 0x00FF:
739 $thisfile_audio_dataformat = 'aac';
740 break;
741
742 case 0x0161:
743 case 0x0162:
744 case 0x0163:
745 $thisfile_audio_dataformat = 'wma';
746 break;
747
748 case 0x2000:
749 $thisfile_audio_dataformat = 'ac3';
750 break;
751
752 case 0x2001:
753 $thisfile_audio_dataformat = 'dts';
754 break;
755
756 default:
757 $thisfile_audio_dataformat = 'wav';
758 break;
759 }
760 $thisfile_audio_streams_currentstream['dataformat'] = $thisfile_audio_dataformat;
761 $thisfile_audio_streams_currentstream['lossless'] = $thisfile_audio['lossless'];
762 $thisfile_audio_streams_currentstream['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
763 break;
764
765 case 'iavs':
766 case 'vids':
767
768 $thisfile_riff_raw['strh'][$i] = array();
769 $thisfile_riff_raw_strh_current = &$thisfile_riff_raw['strh'][$i];
770
771 $thisfile_riff_raw_strh_current['fccType'] = substr($strhData, 0, 4);
772 $thisfile_riff_raw_strh_current['fccHandler'] = substr($strhData, 4, 4);
773 $thisfile_riff_raw_strh_current[
'dwFlags'] = $this->
EitherEndian2Int(substr($strhData, 8, 4));
774 $thisfile_riff_raw_strh_current[
'wPriority'] = $this->
EitherEndian2Int(substr($strhData, 12, 2));
775 $thisfile_riff_raw_strh_current[
'wLanguage'] = $this->
EitherEndian2Int(substr($strhData, 14, 2));
776 $thisfile_riff_raw_strh_current[
'dwInitialFrames'] = $this->
EitherEndian2Int(substr($strhData, 16, 4));
777 $thisfile_riff_raw_strh_current[
'dwScale'] = $this->
EitherEndian2Int(substr($strhData, 20, 4));
778 $thisfile_riff_raw_strh_current[
'dwRate'] = $this->
EitherEndian2Int(substr($strhData, 24, 4));
779 $thisfile_riff_raw_strh_current[
'dwStart'] = $this->
EitherEndian2Int(substr($strhData, 28, 4));
780 $thisfile_riff_raw_strh_current[
'dwLength'] = $this->
EitherEndian2Int(substr($strhData, 32, 4));
781 $thisfile_riff_raw_strh_current[
'dwSuggestedBufferSize'] = $this->
EitherEndian2Int(substr($strhData, 36, 4));
782 $thisfile_riff_raw_strh_current[
'dwQuality'] = $this->
EitherEndian2Int(substr($strhData, 40, 4));
783 $thisfile_riff_raw_strh_current[
'dwSampleSize'] = $this->
EitherEndian2Int(substr($strhData, 44, 4));
784 $thisfile_riff_raw_strh_current[
'rcFrame'] = $this->
EitherEndian2Int(substr($strhData, 48, 4));
785
786 $thisfile_riff_video_current[
'codec'] =
self::RIFFfourccLookup($thisfile_riff_raw_strh_current[
'fccHandler']);
787 $thisfile_video['fourcc'] = $thisfile_riff_raw_strh_current['fccHandler'];
788 if (!$thisfile_riff_video_current['codec'] && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) && self::RIFFfourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
789 $thisfile_riff_video_current[
'codec'] =
self::RIFFfourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex[
'fourcc']);
790 $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
791 }
792 $thisfile_video['codec'] = $thisfile_riff_video_current['codec'];
793 $thisfile_video['pixel_aspect_ratio'] = (float) 1;
794 switch ($thisfile_riff_raw_strh_current['fccHandler']) {
795 case 'HFYU':
796 case 'IRAW':
797 case 'YUY2':
798 $thisfile_video['lossless'] = true;
799 break;
800
801 default:
802 $thisfile_video['lossless'] = false;
803 break;
804 }
805
806 switch ($strhfccType) {
807 case 'vids':
809
810 $thisfile_video['bits_per_sample'] = $thisfile_riff_raw_strf_strhfccType_streamindex['biBitCount'];
811
812 if ($thisfile_riff_video_current['codec'] == 'DV') {
813 $thisfile_riff_video_current['dv_type'] = 2;
814 }
815 break;
816
817 case 'iavs':
818 $thisfile_riff_video_current['dv_type'] = 1;
819 break;
820 }
821 break;
822
823 default:
824 $info[
'warning'][] =
'Unhandled fccType for stream ('.$i.
'): "'.$strhfccType.
'"';
825 break;
826
827 }
828 }
829 }
830
831 if (isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
832
833 $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
834 if (self::RIFFfourccLookup($thisfile_video['fourcc'])) {
836 $thisfile_video['codec'] = $thisfile_riff_video_current['codec'];
837 }
838
839 switch ($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) {
840 case 'HFYU':
841 case 'IRAW':
842 case 'YUY2':
843 $thisfile_video['lossless'] = true;
844
845 break;
846
847 default:
848 $thisfile_video['lossless'] = false;
849
850 break;
851 }
852
853 }
854 }
855 }
856 }
857 break;
858
859 case 'CDDA':
860 $thisfile_audio['bitrate_mode'] = 'cbr';
861 $thisfile_audio_dataformat = 'cda';
862 $thisfile_audio['lossless'] = true;
863 unset(
$info[
'mime_type']);
864
865 $info[
'avdataoffset'] = 44;
866
867 if (isset($thisfile_riff['CDDA']['fmt '][0]['data'])) {
868
869 $thisfile_riff_CDDA_fmt_0 = &$thisfile_riff['CDDA']['fmt '][0];
870
871 $thisfile_riff_CDDA_fmt_0[
'unknown1'] = $this->
EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0[
'data'], 0, 2));
872 $thisfile_riff_CDDA_fmt_0[
'track_num'] = $this->
EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0[
'data'], 2, 2));
873 $thisfile_riff_CDDA_fmt_0[
'disc_id'] = $this->
EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0[
'data'], 4, 4));
874 $thisfile_riff_CDDA_fmt_0[
'start_offset_frame'] = $this->
EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0[
'data'], 8, 4));
875 $thisfile_riff_CDDA_fmt_0[
'playtime_frames'] = $this->
EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0[
'data'], 12, 4));
876 $thisfile_riff_CDDA_fmt_0[
'unknown6'] = $this->
EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0[
'data'], 16, 4));
877 $thisfile_riff_CDDA_fmt_0[
'unknown7'] = $this->
EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0[
'data'], 20, 4));
878
879 $thisfile_riff_CDDA_fmt_0['start_offset_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['start_offset_frame'] / 75;
880 $thisfile_riff_CDDA_fmt_0['playtime_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['playtime_frames'] / 75;
881 $info[
'comments'][
'track'] = $thisfile_riff_CDDA_fmt_0[
'track_num'];
882 $info[
'playtime_seconds'] = $thisfile_riff_CDDA_fmt_0[
'playtime_seconds'];
883
884
885 $thisfile_audio['sample_rate'] = 44100;
886 $thisfile_audio['channels'] = 2;
887 $thisfile_audio['bits_per_sample'] = 16;
888 $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $thisfile_audio['channels'] * $thisfile_audio['bits_per_sample'];
889 $thisfile_audio['bitrate_mode'] = 'cbr';
890 }
891 break;
892
893 case 'AIFF':
894 case 'AIFC':
895 $thisfile_audio['bitrate_mode'] = 'cbr';
896 $thisfile_audio_dataformat = 'aiff';
897 $thisfile_audio['lossless'] = true;
898 $info[
'mime_type'] =
'audio/x-aiff';
899
900 if (isset($thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'])) {
901 $info[
'avdataoffset'] = $thisfile_riff[$RIFFsubtype][
'SSND'][0][
'offset'] + 8;
902 $info[
'avdataend'] =
$info[
'avdataoffset'] + $thisfile_riff[$RIFFsubtype][
'SSND'][0][
'size'];
904 if ((
$info[
'avdataend'] == (
$info[
'filesize'] + 1)) && ((
$info[
'filesize'] % 2) == 1)) {
905
906
907 } else {
908 $info[
'warning'][] =
'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype][
'SSND'][0][
'size'].
' bytes of audio data, only '.(
$info[
'filesize'] -
$info[
'avdataoffset']).
' bytes found';
909 }
911 }
912 }
913
914 if (isset($thisfile_riff[$RIFFsubtype]['COMM'][0]['data'])) {
915
916
917 $thisfile_riff_RIFFsubtype_COMM_0_data = &$thisfile_riff[$RIFFsubtype]['COMM'][0]['data'];
918
919 $thisfile_riff_audio[
'channels'] =
Helper::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 0, 2),
true);
920 $thisfile_riff_audio[
'total_samples'] =
Helper::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 2, 4),
false);
921 $thisfile_riff_audio[
'bits_per_sample'] =
Helper::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 6, 2),
true);
922 $thisfile_riff_audio[
'sample_rate'] = (int)
Helper::BigEndian2Float(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 8, 10));
923
924 if ($thisfile_riff[$RIFFsubtype]['COMM'][0]['size'] > 18) {
925 $thisfile_riff_audio['codec_fourcc'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 18, 4);
926 $CodecNameSize =
Helper::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 22, 1),
false);
927 $thisfile_riff_audio['codec_name'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 23, $CodecNameSize);
928 switch ($thisfile_riff_audio['codec_name']) {
929 case 'NONE':
930 $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)';
931 $thisfile_audio['lossless'] = true;
932 break;
933
934 case '':
935 switch ($thisfile_riff_audio['codec_fourcc']) {
936
937 case 'sowt':
938 $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Little-Endian PCM';
939 $thisfile_audio['lossless'] = true;
940 break;
941
942 case 'twos':
943 $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Big-Endian PCM';
944 $thisfile_audio['lossless'] = true;
945 break;
946
947 default:
948 break;
949 }
950 break;
951
952 default:
953 $thisfile_audio['codec'] = $thisfile_riff_audio['codec_name'];
954 $thisfile_audio['lossless'] = false;
955 break;
956 }
957 }
958
959 $thisfile_audio['channels'] = $thisfile_riff_audio['channels'];
960 if ($thisfile_riff_audio['bits_per_sample'] > 0) {
961 $thisfile_audio['bits_per_sample'] = $thisfile_riff_audio['bits_per_sample'];
962 }
963 $thisfile_audio['sample_rate'] = $thisfile_riff_audio['sample_rate'];
964 if ($thisfile_audio['sample_rate'] == 0) {
965 $info[
'error'][] =
'Corrupted AIFF file: sample_rate == zero';
966
967 return false;
968 }
969 $info[
'playtime_seconds'] = $thisfile_riff_audio[
'total_samples'] / $thisfile_audio[
'sample_rate'];
970 }
971
972 if (isset($thisfile_riff[$RIFFsubtype]['COMT'])) {
973 $offset = 0;
974 $CommentCount =
Helper::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype][
'COMT'][0][
'data'], $offset, 2),
false);
975 $offset += 2;
976 for ($i = 0; $i < $CommentCount; $i++) {
977 $info[
'comments_raw'][$i][
'timestamp'] =
Helper::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype][
'COMT'][0][
'data'], $offset, 4),
false);
978 $offset += 4;
979 $info[
'comments_raw'][$i][
'marker_id'] =
Helper::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype][
'COMT'][0][
'data'], $offset, 2),
true);
980 $offset += 2;
981 $CommentLength =
Helper::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype][
'COMT'][0][
'data'], $offset, 2),
false);
982 $offset += 2;
983 $info[
'comments_raw'][$i][
'comment'] = substr($thisfile_riff[$RIFFsubtype][
'COMT'][0][
'data'], $offset, $CommentLength);
984 $offset += $CommentLength;
985
987 $thisfile_riff[
'comments'][
'comment'][] =
$info[
'comments_raw'][$i][
'comment'];
988 }
989 }
990
991 $CommentsChunkNames = array('NAME'=>'title', 'author'=>'artist', '(c) '=>'copyright', 'ANNO'=>'comment');
992 foreach ($CommentsChunkNames as $key => $value) {
993 if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) {
994 $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data'];
995 }
996 }
997
998 break;
999
1000 case '8SVX':
1001 $thisfile_audio['bitrate_mode'] = 'cbr';
1002 $thisfile_audio_dataformat = '8svx';
1003 $thisfile_audio['bits_per_sample'] = 8;
1004 $thisfile_audio['channels'] = 1;
1005 $info[
'mime_type'] =
'audio/x-aiff';
1006
1007 if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) {
1008 $info[
'avdataoffset'] = $thisfile_riff[$RIFFsubtype][
'BODY'][0][
'offset'] + 8;
1009 $info[
'avdataend'] =
$info[
'avdataoffset'] + $thisfile_riff[$RIFFsubtype][
'BODY'][0][
'size'];
1010 if (
$info[
'avdataend'] >
$info[
'filesize']) {
1011 $info[
'warning'][] =
'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype][
'BODY'][0][
'size'].
' bytes of audio data, only '.(
$info[
'filesize'] -
$info[
'avdataoffset']).
' bytes found';
1012 }
1013 }
1014
1015 if (isset($thisfile_riff[$RIFFsubtype]['VHDR'][0]['offset'])) {
1016
1017 $thisfile_riff_RIFFsubtype_VHDR_0 = &$thisfile_riff[$RIFFsubtype]['VHDR'][0];
1018
1019 $thisfile_riff_RIFFsubtype_VHDR_0[
'oneShotHiSamples'] =
Helper::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0[
'data'], 0, 4));
1020 $thisfile_riff_RIFFsubtype_VHDR_0[
'repeatHiSamples'] =
Helper::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0[
'data'], 4, 4));
1021 $thisfile_riff_RIFFsubtype_VHDR_0[
'samplesPerHiCycle'] =
Helper::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0[
'data'], 8, 4));
1022 $thisfile_riff_RIFFsubtype_VHDR_0[
'samplesPerSec'] =
Helper::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0[
'data'], 12, 2));
1023 $thisfile_riff_RIFFsubtype_VHDR_0[
'ctOctave'] =
Helper::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0[
'data'], 14, 1));
1024 $thisfile_riff_RIFFsubtype_VHDR_0[
'sCompression'] =
Helper::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0[
'data'], 15, 1));
1025 $thisfile_riff_RIFFsubtype_VHDR_0[
'Volume'] =
Helper::FixedPoint16_16(substr($thisfile_riff_RIFFsubtype_VHDR_0[
'data'], 16, 4));
1026
1027 $thisfile_audio['sample_rate'] = $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec'];
1028
1029 switch ($thisfile_riff_RIFFsubtype_VHDR_0['sCompression']) {
1030 case 0:
1031 $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)';
1032 $thisfile_audio['lossless'] = true;
1033 $ActualBitsPerSample = 8;
1034 break;
1035
1036 case 1:
1037 $thisfile_audio['codec'] = 'Fibonacci-delta encoding';
1038 $thisfile_audio['lossless'] = false;
1039 $ActualBitsPerSample = 4;
1040 break;
1041
1042 default:
1043 $info[
'warning'][] =
'Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.sCompression.
'"';
1044 break;
1045 }
1046 }
1047
1048 if (isset($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'])) {
1049 $ChannelsIndex =
Helper::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype][
'CHAN'][0][
'data'], 0, 4));
1050 switch ($ChannelsIndex) {
1051 case 6:
1052 $thisfile_audio['channels'] = 2;
1053 break;
1054
1055 case 2:
1056 case 4:
1057 $thisfile_audio['channels'] = 1;
1058 break;
1059
1060 default:
1061 $info[
'warning'][] =
'Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "'.$ChannelsIndex.
'"';
1062 break;
1063 }
1064
1065 }
1066
1067 $CommentsChunkNames = array('NAME'=>'title', 'author'=>'artist', '(c) '=>'copyright', 'ANNO'=>'comment');
1068 foreach ($CommentsChunkNames as $key => $value) {
1069 if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) {
1070 $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data'];
1071 }
1072 }
1073
1074 $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $ActualBitsPerSample * $thisfile_audio['channels'];
1075 if (!empty($thisfile_audio['bitrate'])) {
1076 $info[
'playtime_seconds'] = (
$info[
'avdataend'] -
$info[
'avdataoffset']) / ($thisfile_audio[
'bitrate'] / 8);
1077 }
1078 break;
1079
1080 case 'CDXA':
1081 $info[
'mime_type'] =
'video/mpeg';
1082 if (!empty($thisfile_riff['CDXA']['data'][0]['size'])) {
1083 if (class_exists('GetId3\Module\AudioVideo\Mpeg')) {
1084 $getid3_temp = new GetId3Core();
1085 $getid3_temp->openfile($this->getid3->filename);
1086 $getid3_mpeg = new Mpeg($getid3_temp);
1087 $getid3_mpeg->analyze();
1088 if (empty($getid3_temp->info['error'])) {
1089 $info[
'audio'] = $getid3_temp->info[
'audio'];
1090 $info[
'video'] = $getid3_temp->info[
'video'];
1091 $info[
'mpeg'] = $getid3_temp->info[
'mpeg'];
1092 $info[
'warning'] = $getid3_temp->info[
'warning'];
1093 }
1094 unset($getid3_temp, $getid3_mpeg);
1095 }
1096 }
1097 break;
1098
1099 default:
1100 $info[
'error'][] =
'Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA), found "'.$RIFFsubtype.
'" instead';
1101 unset(
$info[
'fileformat']);
1102 break;
1103 }
1104
1105 switch ($RIFFsubtype) {
1106 case 'WAVE':
1107 case 'AIFF':
1108 case 'AIFC':
1109 if (isset($thisfile_riff[$RIFFsubtype]['ID3 ']) && !array_key_exists('id3 ', $thisfile_riff[$RIFFsubtype])) {
1110 $info[
'warning'][] =
'mapping "ID3 " chunk to "id3 "';
1111 }
1112 if (isset($thisfile_riff[$RIFFsubtype]['tag ']) && !array_key_exists('id3 ', $thisfile_riff[$RIFFsubtype])) {
1113 $info[
'warning'][] =
'mapping "tag " chunk to "id3 "';
1114 }
1115 if (isset($thisfile_riff[$RIFFsubtype]['id3 '])) {
1116
1117 $getid3_temp = new GetId3Core();
1118 $getid3_temp->openfile($this->getid3->filename);
1119 $getid3_id3v2 = new Id3v2($getid3_temp);
1120 $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['id3 '][0]['offset'] + 8;
1121 if ($thisfile_riff[$RIFFsubtype]['id3 '][0]['valid'] = $getid3_id3v2->analyze()) {
1122 $info[
'id3v2'] = $getid3_temp->info[
'id3v2'];
1123 }
1124 unset($getid3_temp, $getid3_id3v2);
1125 }
1126 break;
1127 }
1128
1129 if (isset($thisfile_riff_raw['fmt ']['wFormatTag']) && ($thisfile_riff_raw['fmt ']['wFormatTag'] == 1)) {
1130
1131 fseek($this->getid3->fp,
$info[
'avdataoffset'], SEEK_SET);
1132 $FirstFourBytes =
fread($this->getid3->fp, 4);
1133 if (preg_match('/^\xFF\x1F\x00\xE8/s', $FirstFourBytes)) {
1134
1135 $thisfile_audio_dataformat = 'dts';
1136 } elseif (preg_match('/^\x7F\xFF\x80\x01/s', $FirstFourBytes)) {
1137
1138 $thisfile_audio_dataformat = 'dts';
1139 }
1140 }
1141
1142
1143 if (isset($thisfile_riff_WAVE['DISP']) && is_array($thisfile_riff_WAVE['DISP'])) {
1144 $thisfile_riff['comments']['title'][] = trim(substr($thisfile_riff_WAVE['DISP'][count($thisfile_riff_WAVE['DISP']) - 1]['data'], 4));
1145 }
1146 if (isset($thisfile_riff_WAVE['INFO']) && is_array($thisfile_riff_WAVE['INFO'])) {
1147 $this->
RIFFcommentsParse($thisfile_riff_WAVE[
'INFO'], $thisfile_riff[
'comments']);
1148 }
1149 if (isset($thisfile_riff['AVI ']['INFO']) && is_array($thisfile_riff['AVI ']['INFO'])) {
1150 $this->
RIFFcommentsParse($thisfile_riff[
'AVI '][
'INFO'], $thisfile_riff[
'comments']);
1151 }
1152
1153 if (empty($thisfile_audio[
'encoder']) && !empty(
$info[
'mpeg'][
'audio'][
'LAME'][
'short_version'])) {
1154 $thisfile_audio[
'encoder'] =
$info[
'mpeg'][
'audio'][
'LAME'][
'short_version'];
1155 }
1156
1157 if (!isset(
$info[
'playtime_seconds'])) {
1158 $info[
'playtime_seconds'] = 0;
1159 }
1160 if (isset($thisfile_riff_raw['strh'][0]['dwLength']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) {
1161
1162 $info[
'playtime_seconds'] = $thisfile_riff_raw[
'strh'][0][
'dwLength'] * ($thisfile_riff_raw[
'avih'][
'dwMicroSecPerFrame'] / 1000000);
1163 } elseif (isset($thisfile_riff_raw['avih']['dwTotalFrames']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) {
1164 $info[
'playtime_seconds'] = $thisfile_riff_raw[
'avih'][
'dwTotalFrames'] * ($thisfile_riff_raw[
'avih'][
'dwMicroSecPerFrame'] / 1000000);
1165 }
1166
1167 if (
$info[
'playtime_seconds'] > 0) {
1168 if (isset($thisfile_riff_audio) && isset($thisfile_riff_video)) {
1169
1170 if (!isset(
$info[
'bitrate'])) {
1171 $info[
'bitrate'] = (((
$info[
'avdataend'] -
$info[
'avdataoffset']) /
$info[
'playtime_seconds']) * 8);
1172 }
1173
1174 } elseif (isset($thisfile_riff_audio) && !isset($thisfile_riff_video)) {
1175
1176 if (!isset($thisfile_audio['bitrate'])) {
1177 $thisfile_audio[
'bitrate'] = (((
$info[
'avdataend'] -
$info[
'avdataoffset']) /
$info[
'playtime_seconds']) * 8);
1178 }
1179
1180 } elseif (!isset($thisfile_riff_audio) && isset($thisfile_riff_video)) {
1181
1182 if (!isset($thisfile_video['bitrate'])) {
1183 $thisfile_video[
'bitrate'] = (((
$info[
'avdataend'] -
$info[
'avdataoffset']) /
$info[
'playtime_seconds']) * 8);
1184 }
1185
1186 }
1187 }
1188
1189
1190 if (isset($thisfile_riff_video) && isset($thisfile_audio[
'bitrate']) && ($thisfile_audio[
'bitrate'] > 0) && (
$info[
'playtime_seconds'] > 0)) {
1191
1192 $info[
'bitrate'] = (((
$info[
'avdataend'] -
$info[
'avdataoffset']) /
$info[
'playtime_seconds']) * 8);
1193 $thisfile_audio['bitrate'] = 0;
1194 $thisfile_video[
'bitrate'] =
$info[
'bitrate'];
1195 foreach ($thisfile_riff_audio as $channelnumber => $audioinfoarray) {
1196 $thisfile_video['bitrate'] -= $audioinfoarray['bitrate'];
1197 $thisfile_audio['bitrate'] += $audioinfoarray['bitrate'];
1198 }
1199 if ($thisfile_video['bitrate'] <= 0) {
1200 unset($thisfile_video['bitrate']);
1201 }
1202 if ($thisfile_audio['bitrate'] <= 0) {
1203 unset($thisfile_audio['bitrate']);
1204 }
1205 }
1206
1207 if (isset(
$info[
'mpeg'][
'audio'])) {
1208 $thisfile_audio_dataformat = 'mp'.$info['mpeg']['audio']['layer'];
1209 $thisfile_audio[
'sample_rate'] =
$info[
'mpeg'][
'audio'][
'sample_rate'];
1210 $thisfile_audio[
'channels'] =
$info[
'mpeg'][
'audio'][
'channels'];
1211 $thisfile_audio[
'bitrate'] =
$info[
'mpeg'][
'audio'][
'bitrate'];
1212 $thisfile_audio[
'bitrate_mode'] = strtolower(
$info[
'mpeg'][
'audio'][
'bitrate_mode']);
1213 if (!empty(
$info[
'mpeg'][
'audio'][
'codec'])) {
1214 $thisfile_audio[
'codec'] =
$info[
'mpeg'][
'audio'][
'codec'].
' '.$thisfile_audio[
'codec'];
1215 }
1216 if (!empty($thisfile_audio['streams'])) {
1217 foreach ($thisfile_audio['streams'] as $streamnumber => $streamdata) {
1218 if ($streamdata['dataformat'] == $thisfile_audio_dataformat) {
1219 $thisfile_audio['streams'][$streamnumber]['sample_rate'] = $thisfile_audio['sample_rate'];
1220 $thisfile_audio['streams'][$streamnumber]['channels'] = $thisfile_audio['channels'];
1221 $thisfile_audio['streams'][$streamnumber]['bitrate'] = $thisfile_audio['bitrate'];
1222 $thisfile_audio['streams'][$streamnumber]['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
1223 $thisfile_audio['streams'][$streamnumber]['codec'] = $thisfile_audio['codec'];
1224 }
1225 }
1226 }
1227 $getid3_mp3 = new Mp3($this->getid3);
1228 $thisfile_audio['encoder_options'] = $getid3_mp3->GuessEncoderOptions();
1229 unset($getid3_mp3);
1230 }
1231
1232
1233 if (!empty($thisfile_riff_raw['fmt ']['wBitsPerSample']) && ($thisfile_riff_raw['fmt ']['wBitsPerSample'] > 0)) {
1234 switch ($thisfile_audio_dataformat) {
1235 case 'ac3':
1236
1237 break;
1238
1239 default:
1240 $thisfile_audio['bits_per_sample'] = $thisfile_riff_raw['fmt ']['wBitsPerSample'];
1241 break;
1242 }
1243 }
1244
1245
1246 if (empty($thisfile_riff_raw)) {
1247 unset($thisfile_riff['raw']);
1248 }
1249 if (empty($thisfile_riff_audio)) {
1250 unset($thisfile_riff['audio']);
1251 }
1252 if (empty($thisfile_riff_video)) {
1253 unset($thisfile_riff['video']);
1254 }
1255
1256 return true;
1257 }
sprintf('%.4f', $callTime)
fseek($bytes, $whence=SEEK_SET)
static Bin2Dec($binstring, $signed=false)
static BigEndian2Int($byteword, $synchsafe=false, $signed=false)
static FixedPoint16_16($rawdata)
static RGADoriginatorLookup($originatorcode)
@staticvar array $RGADoriginator
static LittleEndian2Float($byteword)
static intValueSupported($num)
@staticvar null $hasINT64
static XML2array($XMLstring)
static array_merge_noclobber($array1, $array2)
static BigEndian2Float($byteword)
ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic.
static LittleEndian2Int($byteword, $signed=false)
static PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8')
static RGADadjustmentLookup($rawadjustment, $signbit)
static CastAsInt($floatnum)
static RGADnameLookup($namecode)
@staticvar array $RGADname
static DateMac2Unix($macdate)
static RIFFfourccLookup($fourcc)
ParseRIFF($startoffset, $maxoffset)
static ParseDIVXTAG($DIVXTAG)
@staticvar array $DIVXTAGgenre @staticvar array $DIVXTAGrating
static ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true)
EitherEndian2Int($byteword, $signed=false)
static RIFFwaveSNDMtagLookup($tagshortname)
static RIFFcommentsParse(&$RIFFinfoArray, &$CommentsTargetArray)
static RIFFparseWAVEFORMATex($WaveFormatExData)
static RIFFwFormatTagLookup($wFormatTag)