34 {
35 $info = &$this->getid3->info;
36
37
38
39 $info[
'riff'] = array(
'raw'=>array());
40
41
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'];
49
50 $Original[
'avdataoffset'] =
$info[
'avdataoffset'];
51 $Original[
'avdataend'] =
$info[
'avdataend'];
52
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);
59
60 switch ($RIFFtype) {
61
62 case 'FORM':
63
64 $this->container = 'aiff';
66 $thisfile_riff[$RIFFsubtype] = $this->
ParseRIFF($offset, ($offset + $thisfile_riff[
'header_size'] - 4));
67 break;
68
69 case 'RIFF':
70 case 'SDSS':
71 case 'RMP3':
72
73 $this->container = 'riff';
75 if ($RIFFsubtype == 'RMP3') {
76
77 $RIFFsubtype = 'WAVE';
78 }
79 if ($RIFFsubtype != 'AMV ') {
80
81
82 $thisfile_riff[$RIFFsubtype] = $this->
ParseRIFF($offset, ($offset + $thisfile_riff[
'header_size'] - 4));
83 }
84 if ((
$info[
'avdataend'] -
$info[
'filesize']) == 1) {
85
86
87
89 }
90
91 $nextRIFFoffset = $Original['avdataoffset'] + 8 + $thisfile_riff['header_size'];
92 while ($nextRIFFoffset < min(
$info[
'filesize'],
$info[
'avdataend'])) {
93 try {
94 $this->
fseek($nextRIFFoffset);
96 if ($e->getCode() == 10) {
97
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');
100 break;
101 } else {
102 throw $e;
103 }
104 }
105 $nextRIFFheader = $this->
fread(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
120 switch ($nextRIFFheaderID) {
121 case 'RIFF':
122 $chunkdata[
'chunks'] = $this->
ParseRIFF($chunkdata[
'offset'] + 4, $nextRIFFoffset);
123 if (!isset($thisfile_riff[$nextRIFFtype])) {
124 $thisfile_riff[$nextRIFFtype] = array();
125 }
126 $thisfile_riff[$nextRIFFtype][] = $chunkdata;
127 break;
128
129 case 'AMV ':
130 unset(
$info[
'riff']);
132 break;
133
134 case 'JUNK':
135
136 $thisfile_riff[$nextRIFFheaderID][] = $chunkdata;
137 break;
138
139 case 'IDVX':
141 break;
142
143 default:
144 if (
$info[
'filesize'] == ($chunkdata[
'offset'] - 8 + 128)) {
145 $DIVXTAG = $nextRIFFheader.$this->fread(128 - 12);
146 if (substr($DIVXTAG, -7) == 'DIVXTAG') {
147
148 $this->
warning(
'Found wrongly-structured DIVXTAG at offset '.($this->
ftell() - 128).
', parsing anyway');
150 break 2;
151 }
152 }
153 $this->
warning(
'Expecting "RIFF|JUNK|IDVX" at '.$nextRIFFoffset.
', found "'.$nextRIFFheaderID.
'" ('.
getid3_lib::PrintHexBytes($nextRIFFheaderID).
') - skipping rest of file');
154 break 2;
155
156 }
157
158 }
159 if ($RIFFsubtype == 'WAVE') {
160 $thisfile_riff_WAVE = &$thisfile_riff['WAVE'];
161 }
162 break;
163
164 default:
165 $this->
error(
'Cannot parse RIFF (this is maybe not a RIFF / WAV / AVI file?) - expecting "FORM|RIFF|SDSS|RMP3" found "'.$RIFFsubtype.
'" instead');
166
167 return false;
168 }
169
170 $streamindex = 0;
171 switch ($RIFFsubtype) {
172
173
174 case 'WAVE':
175 $info[
'fileformat'] =
'wav';
176
177 if (empty($thisfile_audio['bitrate_mode'])) {
178 $thisfile_audio['bitrate_mode'] = 'cbr';
179 }
180 if (empty($thisfile_audio_dataformat)) {
181 $thisfile_audio_dataformat = 'wav';
182 }
183
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'];
187 }
188 if (isset($thisfile_riff_WAVE['fmt '][0]['data'])) {
189
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');
194 return false;
195 }
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];
199
201 if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') {
202 $this->
warning(
'Audio codec = '.$thisfile_audio[
'codec']);
203 }
204 $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
205
206 if (empty(
$info[
'playtime_seconds'])) {
207 $info[
'playtime_seconds'] = (float) (((
$info[
'avdataend'] -
$info[
'avdataoffset']) * 8) / $thisfile_audio[
'bitrate']);
208 }
209
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']) {
213
214 case 0x0001:
215 $thisfile_audio['lossless'] = true;
216 break;
217
218 case 0x2000:
219 $thisfile_audio_dataformat = 'ac3';
220 break;
221
222 default:
223
224 break;
225
226 }
227 }
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;
232 }
233
234 if (isset($thisfile_riff_WAVE['rgad'][0]['data'])) {
235
236
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'];
242
244 $thisfile_riff_raw_rgad[
'nRadioRgAdjust'] = $this->
EitherEndian2Int(substr($rgadData, 4, 2));
245 $thisfile_riff_raw_rgad[
'nAudiophileRgAdjust'] = $this->
EitherEndian2Int(substr($rgadData, 6, 2));
246
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));
257
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']);
263 }
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']);
268 }
269 }
270
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));
273
274
275
276
277
278
279
280
281 }
282 if (!empty($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'])) {
283 $thisfile_audio[
'bitrate'] =
getid3_lib::CastAsInt($thisfile_riff_raw[
'fmt '][
'nAvgBytesPerSec'] * 8);
284 }
285
286 if (isset($thisfile_riff_WAVE['bext'][0]['data'])) {
287
288 $thisfile_riff_WAVE_bext_0 = &$thisfile_riff_WAVE['bext'][0];
289
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']);
304 } else {
305 $this->
warning(
'RIFF.WAVE.BEXT.origin_time is invalid');
306 }
307 } else {
308 $this->
warning(
'RIFF.WAVE.BEXT.origin_date is invalid');
309 }
310 $thisfile_riff['comments']['author'][] = $thisfile_riff_WAVE_bext_0['author'];
311 $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_bext_0['title'];
312 }
313
314 if (isset($thisfile_riff_WAVE['MEXT'][0]['data'])) {
315
316 $thisfile_riff_WAVE_MEXT_0 = &$thisfile_riff_WAVE['MEXT'][0];
317
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);
324
326 }
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);
332 }
333
334 if (isset($thisfile_riff_WAVE['cart'][0]['data'])) {
335
336 $thisfile_riff_WAVE_cart_0 = &$thisfile_riff_WAVE['cart'][0];
337
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));
357 }
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)));
360
361 $thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist'];
362 $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_cart_0['title'];
363 }
364
365 if (isset($thisfile_riff_WAVE['SNDM'][0]['data'])) {
366
367
368
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'];
373
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;
386
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).
')');
389 break;
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).
')');
392 break;
393 }
394 $SNDM_startoffset += $SNDM_thisTagSize;
395
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;
399 } else {
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).
')');
401 }
402 }
403
404 $tagmapping = array(
405 'tracktitle'=>'title',
406 'category' =>'genre',
407 'cdtitle' =>'album',
408 'tracktitle'=>'title',
409 );
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];
413 }
414 }
415 }
416
417 if (isset($thisfile_riff_WAVE['iXML'][0]['data'])) {
418
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);
424 }
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);
428 }
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);
440 }
441 unset($parsedXML);
442 }
443 }
444
445
446
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']);
450 }
451
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'];
456
457
458 $info[
'avdataend'] = $Original[
'avdataend'];
459 $thisfile_audio[
'bitrate'] = ((
$info[
'avdataend'] -
$info[
'avdataoffset']) * 8) /
$info[
'playtime_seconds'];
460
462 $RIFFdata = $this->
fread(44);
465
466 if ($OrignalRIFFheaderSize > $OrignalRIFFdataSize) {
467 $info[
'avdataend'] -= ($OrignalRIFFheaderSize - $OrignalRIFFdataSize);
469 $RIFFdata .= $this->
fread($OrignalRIFFheaderSize - $OrignalRIFFdataSize);
470 }
471
472
473
474
475 $RIFFdata = substr($RIFFdata, 0, 36).substr($RIFFdata, 44).substr($RIFFdata, 36, 8);
477 $getid3_riff->ParseRIFFdata($RIFFdata);
478 unset($getid3_riff);
479 }
480
481 if (isset($thisfile_riff_raw['fmt ']['wFormatTag'])) {
482 switch ($thisfile_riff_raw['fmt ']['wFormatTag']) {
483 case 0x0001:
484 if (!empty(
$info[
'ac3'])) {
485
486 $thisfile_audio['wformattag'] = 0x2000;
488 $thisfile_audio['lossless'] = false;
489 $thisfile_audio[
'bitrate'] =
$info[
'ac3'][
'bitrate'];
490 $thisfile_audio[
'sample_rate'] =
$info[
'ac3'][
'sample_rate'];
491 }
492 if (!empty(
$info[
'dts'])) {
493
494 $thisfile_audio['wformattag'] = 0x2001;
496 $thisfile_audio['lossless'] = false;
497 $thisfile_audio[
'bitrate'] =
$info[
'dts'][
'bitrate'];
498 $thisfile_audio[
'sample_rate'] =
$info[
'dts'][
'sample_rate'];
499 }
500 break;
501 case 0x08AE:
502 $thisfile_audio['bitrate_mode'] = 'vbr';
503 $thisfile_audio_dataformat = 'litewave';
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522 $thisfile_riff['litewave']['raw'] = array();
523 $riff_litewave = &$thisfile_riff['litewave'];
524 $riff_litewave_raw = &$riff_litewave['raw'];
525
526 $flags = array(
527 'compression_method' => 1,
528 'compression_flags' => 1,
529 'm_dwScale' => 4,
530 'm_dwBlockSize' => 4,
531 'm_wQuality' => 2,
532 'm_wMarkDistance' => 2,
533 'm_wReserved' => 2,
534 'm_dwOrgSize' => 4,
535 'm_bFactExists' => 2,
536 'm_dwRiffChunkSize' => 4,
537 );
538 $litewave_offset = 18;
539 foreach ($flags as $flag => $length) {
541 $litewave_offset += $length;
542 }
543
544
545 $riff_litewave['quality_factor'] = $riff_litewave_raw['m_wQuality'];
546
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);
550
551 $thisfile_audio['lossless'] = (($riff_litewave_raw['m_wQuality'] == 100) ? true : false);
552 $thisfile_audio['encoder_options'] = '-q'.$riff_litewave['quality_factor'];
553 break;
554
555 default:
556 break;
557 }
558 }
560 switch (!empty($thisfile_audio_dataformat) ? $thisfile_audio_dataformat : '') {
561 case 'wavpack':
562 case 'lpac':
563 case 'ofr':
564 case 'ofs':
565
566 break;
567
568 case 'litewave':
569 if ((
$info[
'avdataend'] -
$info[
'filesize']) == 1) {
570
571
572
573 } else {
574
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)');
577 }
578 break;
579
580 default:
581 if (((
$info[
'avdataend'] -
$info[
'filesize']) == 1) && (($thisfile_riff[$RIFFsubtype][
'data'][0][
'size'] % 2) == 0) && (((
$info[
'filesize'] -
$info[
'avdataoffset']) % 2) == 1)) {
582
583
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)');
586 } else {
587
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)');
590 }
591 break;
592 }
593 }
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');
598 }
599 }
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'];
604 }
605 }
606 break;
607
608
609 case 'AVI ':
610 $info[
'fileformat'] =
'avi';
611 $info[
'mime_type'] =
'video/avi';
612
613 $thisfile_video['bitrate_mode'] = 'vbr';
614 $thisfile_video['dataformat'] = 'avi';
615
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'];
620 } else {
621 $info[
'avdataend'] = $thisfile_riff[
'AVI '][
'movi'][
'offset'] + $thisfile_riff[
'AVI '][
'movi'][
'size'];
622 }
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)');
626 }
627 }
628
629 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['indx'])) {
630
631
632
633
634
635
636
637
638
639
640 foreach ($thisfile_riff['AVI ']['hdrl']['strl']['indx'] as $streamnumber => $steamdataarray) {
641 $ahsisd = &$thisfile_riff['AVI ']['hdrl']['strl']['indx'][$streamnumber]['data'];
642
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));
649
650
651
652
653 unset($ahsisd);
654 }
655 }
656 if (isset($thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'])) {
657 $avihData = $thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'];
658
659
660 $thisfile_riff_raw['avih'] = array();
661 $thisfile_riff_raw_avih = &$thisfile_riff_raw['avih'];
662
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');
666 return false;
667 }
668
669 $flags = array(
670 'dwMaxBytesPerSec',
671 'dwPaddingGranularity',
672 'dwFlags',
673 'dwTotalFrames',
674 'dwInitialFrames',
675 'dwStreams',
676 'dwSuggestedBufferSize',
677 'dwWidth',
678 'dwHeight',
679 'dwScale',
680 'dwRate',
681 'dwStart',
682 'dwLength',
683 );
684 $avih_offset = 4;
685 foreach ($flags as $flag) {
686 $thisfile_riff_raw_avih[$flag] = $this->
EitherEndian2Int(substr($avihData, $avih_offset, 4));
687 $avih_offset += 4;
688 }
689
690 $flags = array(
691 'hasindex' => 0x00000010,
692 'mustuseindex' => 0x00000020,
693 'interleaved' => 0x00000100,
694 'trustcktype' => 0x00000800,
695 'capturedfile' => 0x00010000,
696 'copyrighted' => 0x00020010,
697 );
698 foreach ($flags as $flag => $value) {
699 $thisfile_riff_raw_avih['flags'][$flag] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & $value);
700 }
701
702
703 $thisfile_riff_video[$streamindex] = array();
704 $thisfile_riff_video_current = &$thisfile_riff_video[$streamindex];
705
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'];
709 }
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'];
713 }
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'];
717 }
718
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'];
721 }
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);
728
729 if (isset($thisfile_riff[
'AVI '][
'hdrl'][
'strl'][
'strf'][
$i][
'data'])) {
730 $strfData = $thisfile_riff[
'AVI '][
'hdrl'][
'strl'][
'strf'][
$i][
'data'];
731
732
733 $thisfile_riff_raw_strf_strhfccType_streamindex = &$thisfile_riff_raw['strf'][$strhfccType][$streamindex];
734
735 switch ($strhfccType) {
736 case 'auds':
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);
741 }
742
744 $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
745
746
747 $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
748 $thisfile_audio_streams_currentstream = &$thisfile_audio['streams'][$streamindex];
749
750 if ($thisfile_audio_streams_currentstream['bits_per_sample'] == 0) {
751 unset($thisfile_audio_streams_currentstream['bits_per_sample']);
752 }
753 $thisfile_audio_streams_currentstream['wformattag'] = $thisfile_audio_streams_currentstream['raw']['wFormatTag'];
754 unset($thisfile_audio_streams_currentstream['raw']);
755
756
757 $thisfile_riff_raw['strf'][$strhfccType][$streamindex] = $thisfile_riff_audio[$streamindex]['raw'];
758
759 unset($thisfile_riff_audio[$streamindex]['raw']);
761
762 $thisfile_audio['lossless'] = false;
763 switch ($thisfile_riff_raw_strf_strhfccType_streamindex['wFormatTag']) {
764 case 0x0001:
765 $thisfile_audio_dataformat = 'wav';
766 $thisfile_audio['lossless'] = true;
767 break;
768
769 case 0x0050:
770 $thisfile_audio_dataformat = 'mp2';
771 break;
772
773 case 0x0055:
774 $thisfile_audio_dataformat = 'mp3';
775 break;
776
777 case 0x00FF:
778 $thisfile_audio_dataformat = 'aac';
779 break;
780
781 case 0x0161:
782 case 0x0162:
783 case 0x0163:
784 $thisfile_audio_dataformat = 'wma';
785 break;
786
787 case 0x2000:
788 $thisfile_audio_dataformat = 'ac3';
789 break;
790
791 case 0x2001:
792 $thisfile_audio_dataformat = 'dts';
793 break;
794
795 default:
796 $thisfile_audio_dataformat = 'wav';
797 break;
798 }
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'];
802 break;
803
804
805 case 'iavs':
806 case 'vids':
807
808 $thisfile_riff_raw[
'strh'][
$i] = array();
809 $thisfile_riff_raw_strh_current = &$thisfile_riff_raw[
'strh'][
$i];
810
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));
825
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'];
831 }
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']) {
835 case 'HFYU':
836 case 'IRAW':
837 case 'YUY2':
838 $thisfile_video['lossless'] = true;
839 break;
840
841 default:
842 $thisfile_video['lossless'] = false;
843 break;
844 }
845
846 switch ($strhfccType) {
847 case 'vids':
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'];
850
851 if ($thisfile_riff_video_current['codec'] == 'DV') {
852 $thisfile_riff_video_current['dv_type'] = 2;
853 }
854 break;
855
856 case 'iavs':
857 $thisfile_riff_video_current['dv_type'] = 1;
858 break;
859 }
860 break;
861
862 default:
863 $this->
warning(
'Unhandled fccType for stream ('.$i.
'): "'.$strhfccType.
'"');
864 break;
865
866 }
867 }
868 }
869
870 if (isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
871
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'];
876 }
877
878 switch ($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) {
879 case 'HFYU':
880 case 'IRAW':
881 case 'YUY2':
882 $thisfile_video['lossless'] = true;
883
884 break;
885
886 default:
887 $thisfile_video['lossless'] = false;
888
889 break;
890 }
891
892 }
893 }
894 }
895 }
896 break;
897
898
899 case 'AMV ':
900 $info[
'fileformat'] =
'amv';
901 $info[
'mime_type'] =
'video/amv';
902
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;
908
909 $thisfile_audio['dataformat'] = 'adpcm';
910 $thisfile_audio['lossless'] = false;
911 break;
912
913
914
915 case 'CDDA':
916 $info[
'fileformat'] =
'cda';
917 unset(
$info[
'mime_type']);
918
919 $thisfile_audio_dataformat = 'cda';
920
921 $info[
'avdataoffset'] = 44;
922
923 if (isset($thisfile_riff['CDDA']['fmt '][0]['data'])) {
924
925 $thisfile_riff_CDDA_fmt_0 = &$thisfile_riff['CDDA']['fmt '][0];
926
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));
934
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'];
939
940
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';
947 }
948 break;
949
950
951 case 'AIFF':
952 case 'AIFC':
953 $info[
'fileformat'] =
'aiff';
954 $info[
'mime_type'] =
'audio/x-aiff';
955
956 $thisfile_audio['bitrate_mode'] = 'cbr';
957 $thisfile_audio_dataformat = 'aiff';
958 $thisfile_audio['lossless'] = true;
959
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)) {
965
966
967 } else {
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');
969 }
971 }
972 }
973
974 if (isset($thisfile_riff[$RIFFsubtype]['COMM'][0]['data'])) {
975
976
977 $thisfile_riff_RIFFsubtype_COMM_0_data = &$thisfile_riff[$RIFFsubtype]['COMM'][0]['data'];
978
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);
983
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']) {
989 case 'NONE':
990 $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)';
991 $thisfile_audio['lossless'] = true;
992 break;
993
994 case '':
995 switch ($thisfile_riff_audio['codec_fourcc']) {
996
997 case 'sowt':
998 $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Little-Endian PCM';
999 $thisfile_audio['lossless'] = true;
1000 break;
1001
1002 case 'twos':
1003 $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Big-Endian PCM';
1004 $thisfile_audio['lossless'] = true;
1005 break;
1006
1007 default:
1008 break;
1009 }
1010 break;
1011
1012 default:
1013 $thisfile_audio['codec'] = $thisfile_riff_audio['codec_name'];
1014 $thisfile_audio['lossless'] = false;
1015 break;
1016 }
1017 }
1018
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'];
1022 }
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');
1026 return false;
1027 }
1028 $info[
'playtime_seconds'] = $thisfile_riff_audio[
'total_samples'] / $thisfile_audio[
'sample_rate'];
1029 }
1030
1031 if (isset($thisfile_riff[$RIFFsubtype]['COMT'])) {
1032 $offset = 0;
1034 $offset += 2;
1035 for (
$i = 0;
$i < $CommentCount;
$i++) {
1037 $offset += 4;
1039 $offset += 2;
1041 $offset += 2;
1042 $info[
'comments_raw'][
$i][
'comment'] = substr($thisfile_riff[$RIFFsubtype][
'COMT'][0][
'data'], $offset, $CommentLength);
1043 $offset += $CommentLength;
1044
1046 $thisfile_riff[
'comments'][
'comment'][] =
$info[
'comments_raw'][
$i][
'comment'];
1047 }
1048 }
1049
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'];
1054 }
1055 }
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069 break;
1070
1071
1072 case '8SVX':
1073 $info[
'fileformat'] =
'8svx';
1074 $info[
'mime_type'] =
'audio/8svx';
1075
1076 $thisfile_audio['bitrate_mode'] = 'cbr';
1077 $thisfile_audio_dataformat = '8svx';
1078 $thisfile_audio['bits_per_sample'] = 8;
1079 $thisfile_audio['channels'] = 1;
1080
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');
1086 }
1087 }
1088
1089 if (isset($thisfile_riff[$RIFFsubtype]['VHDR'][0]['offset'])) {
1090
1091 $thisfile_riff_RIFFsubtype_VHDR_0 = &$thisfile_riff[$RIFFsubtype]['VHDR'][0];
1092
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));
1100
1101 $thisfile_audio['sample_rate'] = $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec'];
1102
1103 switch ($thisfile_riff_RIFFsubtype_VHDR_0['sCompression']) {
1104 case 0:
1105 $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)';
1106 $thisfile_audio['lossless'] = true;
1107 $ActualBitsPerSample = 8;
1108 break;
1109
1110 case 1:
1111 $thisfile_audio['codec'] = 'Fibonacci-delta encoding';
1112 $thisfile_audio['lossless'] = false;
1113 $ActualBitsPerSample = 4;
1114 break;
1115
1116 default:
1117 $this->
warning(
'Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.sCompression.
'"');
1118 break;
1119 }
1120 }
1121
1122 if (isset($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'])) {
1124 switch ($ChannelsIndex) {
1125 case 6:
1126 $thisfile_audio['channels'] = 2;
1127 break;
1128
1129 case 2:
1130 case 4:
1131 $thisfile_audio['channels'] = 1;
1132 break;
1133
1134 default:
1135 $this->
warning(
'Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "'.$ChannelsIndex.
'"');
1136 break;
1137 }
1138
1139 }
1140
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'];
1145 }
1146 }
1147
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);
1151 }
1152 break;
1153
1154 case 'CDXA':
1155 $info[
'fileformat'] =
'vcd';
1156 $info[
'mime_type'] =
'video/mpeg';
1157
1158 if (!empty($thisfile_riff['CDXA']['data'][0]['size'])) {
1160
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'];
1170 }
1171 unset($getid3_temp, $getid3_mpeg);
1172 }
1173 break;
1174
1175 case 'WEBP':
1176
1177 $info[
'fileformat'] =
'webp';
1178 $info[
'mime_type'] =
'image/webp';
1179
1180$this->
error(
'WebP image parsing not supported in this version of getID3()');
1181 break;
1182
1183 default:
1184 $this->
error(
'Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA|WEBP), found "'.$RIFFsubtype.
'" instead');
1185
1186 }
1187
1188 switch ($RIFFsubtype) {
1189 case 'WAVE':
1190 case 'AIFF':
1191 case 'AIFC':
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.
'"');
1198 }
1199 }
1200
1201 if (isset($thisfile_riff[$RIFFsubtype]['id3 '])) {
1203
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'];
1210 }
1211 unset($getid3_temp, $getid3_id3v2);
1212 }
1213 break;
1214 }
1215
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));
1218 }
1219 if (isset($thisfile_riff_WAVE['INFO']) && is_array($thisfile_riff_WAVE['INFO'])) {
1221 }
1222 if (isset($thisfile_riff['AVI ']['INFO']) && is_array($thisfile_riff['AVI ']['INFO'])) {
1224 }
1225
1226 if (empty($thisfile_audio[
'encoder']) && !empty(
$info[
'mpeg'][
'audio'][
'LAME'][
'short_version'])) {
1227 $thisfile_audio[
'encoder'] =
$info[
'mpeg'][
'audio'][
'LAME'][
'short_version'];
1228 }
1229
1230 if (!isset(
$info[
'playtime_seconds'])) {
1231 $info[
'playtime_seconds'] = 0;
1232 }
1233 if (isset($thisfile_riff_raw['strh'][0]['dwLength']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) {
1234
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);
1238 }
1239
1240 if (
$info[
'playtime_seconds'] > 0) {
1241 if (isset($thisfile_riff_audio) && isset($thisfile_riff_video)) {
1242
1243 if (!isset(
$info[
'bitrate'])) {
1244 $info[
'bitrate'] = (((
$info[
'avdataend'] -
$info[
'avdataoffset']) /
$info[
'playtime_seconds']) * 8);
1245 }
1246
1247 } elseif (isset($thisfile_riff_audio) && !isset($thisfile_riff_video)) {
1248
1249 if (!isset($thisfile_audio['bitrate'])) {
1250 $thisfile_audio[
'bitrate'] = (((
$info[
'avdataend'] -
$info[
'avdataoffset']) /
$info[
'playtime_seconds']) * 8);
1251 }
1252
1253 } elseif (!isset($thisfile_riff_audio) && isset($thisfile_riff_video)) {
1254
1255 if (!isset($thisfile_video['bitrate'])) {
1256 $thisfile_video[
'bitrate'] = (((
$info[
'avdataend'] -
$info[
'avdataoffset']) /
$info[
'playtime_seconds']) * 8);
1257 }
1258
1259 }
1260 }
1261
1262
1263 if (isset($thisfile_riff_video) && isset($thisfile_audio[
'bitrate']) && ($thisfile_audio[
'bitrate'] > 0) && (
$info[
'playtime_seconds'] > 0)) {
1264
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'];
1271 }
1272 if ($thisfile_video['bitrate'] <= 0) {
1273 unset($thisfile_video['bitrate']);
1274 }
1275 if ($thisfile_audio['bitrate'] <= 0) {
1276 unset($thisfile_audio['bitrate']);
1277 }
1278 }
1279
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'];
1288 }
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'];
1297 }
1298 }
1299 }
1301 $thisfile_audio['encoder_options'] = $getid3_mp3->GuessEncoderOptions();
1302 unset($getid3_mp3);
1303 }
1304
1305
1306 if (!empty($thisfile_riff_raw['fmt ']['wBitsPerSample']) && ($thisfile_riff_raw['fmt ']['wBitsPerSample'] > 0)) {
1307 switch ($thisfile_audio_dataformat) {
1308 case 'ac3':
1309
1310 break;
1311
1312 default:
1313 $thisfile_audio['bits_per_sample'] = $thisfile_riff_raw['fmt ']['wBitsPerSample'];
1314 break;
1315 }
1316 }
1317
1318
1319 if (empty($thisfile_riff_raw)) {
1320 unset($thisfile_riff['raw']);
1321 }
1322 if (empty($thisfile_riff_audio)) {
1323 unset($thisfile_riff['audio']);
1324 }
1325 if (empty($thisfile_riff_video)) {
1326 unset($thisfile_riff['video']);
1327 }
1328
1329 return true;
1330 }
fseek($bytes, $whence=SEEK_SET)
static RGADadjustmentLookup($rawadjustment, $signbit)
static XML2array($XMLstring)
static PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8')
static LittleEndian2Int($byteword, $signed=false)
static FixedPoint16_16($rawdata)
static RGADoriginatorLookup($originatorcode)
static LittleEndian2Float($byteword)
static Bin2Dec($binstring, $signed=false)
static DateMac2Unix($macdate)
static IncludeDependency($filename, $sourcefile, $DieOnFailure=false)
static array_merge_noclobber($array1, $array2)
static RGADnameLookup($namecode)
static BigEndian2Float($byteword)
static CastAsInt($floatnum)
static BigEndian2Int($byteword, $synchsafe=false, $signed=false)
static parseComments(&$RIFFinfoArray, &$CommentsTargetArray)
static parseWAVEFORMATex($WaveFormatExData)
EitherEndian2Int($byteword, $signed=false)
ParseRIFF($startoffset, $maxoffset)
static wFormatTagLookup($wFormatTag)
static ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true)
static fourccLookup($fourcc)
static ParseDIVXTAG($DIVXTAG, $raw=false)
ParseRIFFAMV($startoffset, $maxoffset)