2 /////////////////////////////////////////////////////////////////
3 /// getID3() by James Heinrich <info@getid3.org> //
4 // available at http://getid3.sourceforge.net //
5 // or http://www.getid3.org //
6 /////////////////////////////////////////////////////////////////
7 // See readme.txt for more details //
8 /////////////////////////////////////////////////////////////////
10 // module.audio-video.riff.php //
11 // module for analyzing RIFF files //
12 // multiple formats supported by this module: //
13 // Wave, AVI, AIFF/AIFC, (MP3,AC3)/RIFF, Wavpack v3, 8SVX //
14 // dependencies: module.audio.mp3.php //
15 // module.audio.ac3.php //
16 // module.audio.dts.php //
18 /////////////////////////////////////////////////////////////////
21 * @todo Parse AC-3/DTS audio inside WAVE correctly
22 * @todo Rewrite RIFF parser totally
25 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true);
26 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ac3.php', __FILE__, true);
27 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.dts.php', __FILE__, true);
29 class getid3_riff extends getid3_handler
32 public function Analyze() {
33 $info = &$this->getid3->info;
35 // initialize these values to an empty array, otherwise they default to NULL
36 // and you can't append array values to a NULL value
37 $info['riff'] = array('raw'=>array());
40 $thisfile_riff = &$info['riff'];
41 $thisfile_riff_raw = &$thisfile_riff['raw'];
42 $thisfile_audio = &$info['audio'];
43 $thisfile_video = &$info['video'];
44 $thisfile_audio_dataformat = &$thisfile_audio['dataformat'];
45 $thisfile_riff_audio = &$thisfile_riff['audio'];
46 $thisfile_riff_video = &$thisfile_riff['video'];
48 $Original['avdataoffset'] = $info['avdataoffset'];
49 $Original['avdataend'] = $info['avdataend'];
51 $this->fseek($info['avdataoffset']);
52 $RIFFheader = $this->fread(12);
53 $offset = $this->ftell();
54 $RIFFtype = substr($RIFFheader, 0, 4);
55 $RIFFsize = substr($RIFFheader, 4, 4);
56 $RIFFsubtype = substr($RIFFheader, 8, 4);
60 case 'FORM': // AIFF, AIFC
61 $info['fileformat'] = 'aiff';
62 $thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize);
63 $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, ($offset + $thisfile_riff['header_size'] - 4));
66 case 'RIFF': // AVI, WAV, etc
67 case 'SDSS': // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com)
68 case 'RMP3': // RMP3 is identical to RIFF, just renamed. Used by [unknown program] when creating RIFF-MP3s
69 $info['fileformat'] = 'riff';
70 $thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize);
71 if ($RIFFsubtype == 'RMP3') {
72 // RMP3 is identical to WAVE, just renamed. Used by [unknown program] when creating RIFF-MP3s
73 $RIFFsubtype = 'WAVE';
75 $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, ($offset + $thisfile_riff['header_size'] - 4));
76 if (($info['avdataend'] - $info['filesize']) == 1) {
77 // LiteWave appears to incorrectly *not* pad actual output file
78 // to nearest WORD boundary so may appear to be short by one
79 // byte, in which case - skip warning
80 $info['avdataend'] = $info['filesize'];
83 $nextRIFFoffset = $Original['avdataoffset'] + 8 + $thisfile_riff['header_size']; // 8 = "RIFF" + 32-bit offset
84 while ($nextRIFFoffset < min($info['filesize'], $info['avdataend'])) {
86 $this->fseek($nextRIFFoffset);
87 } catch (getid3_exception $e) {
88 if ($e->getCode() == 10) {
89 //$this->warning('RIFF parser: '.$e->getMessage());
90 $this->error('AVI extends beyond '.round(PHP_INT_MAX / 1073741824).'GB and PHP filesystem functions cannot read that far, playtime may be wrong');
91 $this->warning('[avdataend] value may be incorrect, multiple AVIX chunks may be present');
97 $nextRIFFheader = $this->fread(12);
98 if ($nextRIFFoffset == ($info['avdataend'] - 1)) {
99 if (substr($nextRIFFheader, 0, 1) == "\x00") {
100 // RIFF padded to WORD boundary, we're actually already at the end
104 $nextRIFFheaderID = substr($nextRIFFheader, 0, 4);
105 $nextRIFFsize = $this->EitherEndian2Int(substr($nextRIFFheader, 4, 4));
106 $nextRIFFtype = substr($nextRIFFheader, 8, 4);
107 $chunkdata = array();
108 $chunkdata['offset'] = $nextRIFFoffset + 8;
109 $chunkdata['size'] = $nextRIFFsize;
110 $nextRIFFoffset = $chunkdata['offset'] + $chunkdata['size'];
112 switch ($nextRIFFheaderID) {
115 $chunkdata['chunks'] = $this->ParseRIFF($chunkdata['offset'] + 4, $nextRIFFoffset);
117 if (!isset($thisfile_riff[$nextRIFFtype])) {
118 $thisfile_riff[$nextRIFFtype] = array();
120 $thisfile_riff[$nextRIFFtype][] = $chunkdata;
125 $thisfile_riff[$nextRIFFheaderID][] = $chunkdata;
129 $info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunkdata['size']));
133 if ($info['filesize'] == ($chunkdata['offset'] - 8 + 128)) {
134 $DIVXTAG = $nextRIFFheader.$this->fread(128 - 12);
135 if (substr($DIVXTAG, -7) == 'DIVXTAG') {
136 // DIVXTAG is supposed to be inside an IDVX chunk in a LIST chunk, but some bad encoders just slap it on the end of a file
137 $this->warning('Found wrongly-structured DIVXTAG at offset '.($this->ftell() - 128).', parsing anyway');
138 $info['divxtag']['comments'] = self::ParseDIVXTAG($DIVXTAG);
142 $this->warning('Expecting "RIFF|JUNK|IDVX" at '.$nextRIFFoffset.', found "'.$nextRIFFheaderID.'" ('.getid3_lib::PrintHexBytes($nextRIFFheaderID).') - skipping rest of file');
148 if ($RIFFsubtype == 'WAVE') {
149 $thisfile_riff_WAVE = &$thisfile_riff['WAVE'];
154 $this->error('Cannot parse RIFF (this is maybe not a RIFF / WAV / AVI file?) - expecting "FORM|RIFF|SDSS|RMP3" found "'.$RIFFsubtype.'" instead');
155 unset($info['fileformat']);
160 switch ($RIFFsubtype) {
162 if (empty($thisfile_audio['bitrate_mode'])) {
163 $thisfile_audio['bitrate_mode'] = 'cbr';
165 if (empty($thisfile_audio_dataformat)) {
166 $thisfile_audio_dataformat = 'wav';
169 if (isset($thisfile_riff_WAVE['data'][0]['offset'])) {
170 $info['avdataoffset'] = $thisfile_riff_WAVE['data'][0]['offset'] + 8;
171 $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff_WAVE['data'][0]['size'];
173 if (isset($thisfile_riff_WAVE['fmt '][0]['data'])) {
175 $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($thisfile_riff_WAVE['fmt '][0]['data']);
176 $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
177 if (!isset($thisfile_riff_audio[$streamindex]['bitrate']) || ($thisfile_riff_audio[$streamindex]['bitrate'] == 0)) {
178 $info['error'][] = 'Corrupt RIFF file: bitrate_audio == zero';
181 $thisfile_riff_raw['fmt '] = $thisfile_riff_audio[$streamindex]['raw'];
182 unset($thisfile_riff_audio[$streamindex]['raw']);
183 $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
185 $thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
186 if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') {
187 $info['warning'][] = 'Audio codec = '.$thisfile_audio['codec'];
189 $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
191 if (empty($info['playtime_seconds'])) { // may already be set (e.g. DTS-WAV)
192 $info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $thisfile_audio['bitrate']);
195 $thisfile_audio['lossless'] = false;
196 if (isset($thisfile_riff_WAVE['data'][0]['offset']) && isset($thisfile_riff_raw['fmt ']['wFormatTag'])) {
197 switch ($thisfile_riff_raw['fmt ']['wFormatTag']) {
200 $thisfile_audio['lossless'] = true;
204 $thisfile_audio_dataformat = 'ac3';
213 $thisfile_audio['streams'][$streamindex]['wformattag'] = $thisfile_audio['wformattag'];
214 $thisfile_audio['streams'][$streamindex]['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
215 $thisfile_audio['streams'][$streamindex]['lossless'] = $thisfile_audio['lossless'];
216 $thisfile_audio['streams'][$streamindex]['dataformat'] = $thisfile_audio_dataformat;
219 if (isset($thisfile_riff_WAVE['rgad'][0]['data'])) {
222 $rgadData = &$thisfile_riff_WAVE['rgad'][0]['data'];
223 $thisfile_riff_raw['rgad'] = array('track'=>array(), 'album'=>array());
224 $thisfile_riff_raw_rgad = &$thisfile_riff_raw['rgad'];
225 $thisfile_riff_raw_rgad_track = &$thisfile_riff_raw_rgad['track'];
226 $thisfile_riff_raw_rgad_album = &$thisfile_riff_raw_rgad['album'];
228 $thisfile_riff_raw_rgad['fPeakAmplitude'] = getid3_lib::LittleEndian2Float(substr($rgadData, 0, 4));
229 $thisfile_riff_raw_rgad['nRadioRgAdjust'] = $this->EitherEndian2Int(substr($rgadData, 4, 2));
230 $thisfile_riff_raw_rgad['nAudiophileRgAdjust'] = $this->EitherEndian2Int(substr($rgadData, 6, 2));
232 $nRadioRgAdjustBitstring = str_pad(getid3_lib::Dec2Bin($thisfile_riff_raw_rgad['nRadioRgAdjust']), 16, '0', STR_PAD_LEFT);
233 $nAudiophileRgAdjustBitstring = str_pad(getid3_lib::Dec2Bin($thisfile_riff_raw_rgad['nAudiophileRgAdjust']), 16, '0', STR_PAD_LEFT);
234 $thisfile_riff_raw_rgad_track['name'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 0, 3));
235 $thisfile_riff_raw_rgad_track['originator'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 3, 3));
236 $thisfile_riff_raw_rgad_track['signbit'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 6, 1));
237 $thisfile_riff_raw_rgad_track['adjustment'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 7, 9));
238 $thisfile_riff_raw_rgad_album['name'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 0, 3));
239 $thisfile_riff_raw_rgad_album['originator'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 3, 3));
240 $thisfile_riff_raw_rgad_album['signbit'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 6, 1));
241 $thisfile_riff_raw_rgad_album['adjustment'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 7, 9));
243 $thisfile_riff['rgad']['peakamplitude'] = $thisfile_riff_raw_rgad['fPeakAmplitude'];
244 if (($thisfile_riff_raw_rgad_track['name'] != 0) && ($thisfile_riff_raw_rgad_track['originator'] != 0)) {
245 $thisfile_riff['rgad']['track']['name'] = getid3_lib::RGADnameLookup($thisfile_riff_raw_rgad_track['name']);
246 $thisfile_riff['rgad']['track']['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_riff_raw_rgad_track['originator']);
247 $thisfile_riff['rgad']['track']['adjustment'] = getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_track['adjustment'], $thisfile_riff_raw_rgad_track['signbit']);
249 if (($thisfile_riff_raw_rgad_album['name'] != 0) && ($thisfile_riff_raw_rgad_album['originator'] != 0)) {
250 $thisfile_riff['rgad']['album']['name'] = getid3_lib::RGADnameLookup($thisfile_riff_raw_rgad_album['name']);
251 $thisfile_riff['rgad']['album']['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_riff_raw_rgad_album['originator']);
252 $thisfile_riff['rgad']['album']['adjustment'] = getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_album['adjustment'], $thisfile_riff_raw_rgad_album['signbit']);
256 if (isset($thisfile_riff_WAVE['fact'][0]['data'])) {
257 $thisfile_riff_raw['fact']['NumberOfSamples'] = $this->EitherEndian2Int(substr($thisfile_riff_WAVE['fact'][0]['data'], 0, 4));
259 // This should be a good way of calculating exact playtime,
260 // but some sample files have had incorrect number of samples,
261 // so cannot use this method
263 // if (!empty($thisfile_riff_raw['fmt ']['nSamplesPerSec'])) {
264 // $info['playtime_seconds'] = (float) $thisfile_riff_raw['fact']['NumberOfSamples'] / $thisfile_riff_raw['fmt ']['nSamplesPerSec'];
267 if (!empty($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'])) {
268 $thisfile_audio['bitrate'] = getid3_lib::CastAsInt($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'] * 8);
271 if (isset($thisfile_riff_WAVE['bext'][0]['data'])) {
273 $thisfile_riff_WAVE_bext_0 = &$thisfile_riff_WAVE['bext'][0];
275 $thisfile_riff_WAVE_bext_0['title'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 0, 256));
276 $thisfile_riff_WAVE_bext_0['author'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 256, 32));
277 $thisfile_riff_WAVE_bext_0['reference'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 288, 32));
278 $thisfile_riff_WAVE_bext_0['origin_date'] = substr($thisfile_riff_WAVE_bext_0['data'], 320, 10);
279 $thisfile_riff_WAVE_bext_0['origin_time'] = substr($thisfile_riff_WAVE_bext_0['data'], 330, 8);
280 $thisfile_riff_WAVE_bext_0['time_reference'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 338, 8));
281 $thisfile_riff_WAVE_bext_0['bwf_version'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 346, 1));
282 $thisfile_riff_WAVE_bext_0['reserved'] = substr($thisfile_riff_WAVE_bext_0['data'], 347, 254);
283 $thisfile_riff_WAVE_bext_0['coding_history'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_bext_0['data'], 601)));
284 if (preg_match('#^([0-9]{4}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_date'], $matches_bext_date)) {
285 if (preg_match('#^([0-9]{2}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_time'], $matches_bext_time)) {
286 list($dummy, $bext_timestamp['year'], $bext_timestamp['month'], $bext_timestamp['day']) = $matches_bext_date;
287 list($dummy, $bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second']) = $matches_bext_time;
288 $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']);
290 $info['warning'][] = 'RIFF.WAVE.BEXT.origin_time is invalid';
293 $info['warning'][] = 'RIFF.WAVE.BEXT.origin_date is invalid';
295 $thisfile_riff['comments']['author'][] = $thisfile_riff_WAVE_bext_0['author'];
296 $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_bext_0['title'];
299 if (isset($thisfile_riff_WAVE['MEXT'][0]['data'])) {
301 $thisfile_riff_WAVE_MEXT_0 = &$thisfile_riff_WAVE['MEXT'][0];
303 $thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 0, 2));
304 $thisfile_riff_WAVE_MEXT_0['flags']['homogenous'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0001);
305 if ($thisfile_riff_WAVE_MEXT_0['flags']['homogenous']) {
306 $thisfile_riff_WAVE_MEXT_0['flags']['padding'] = ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0002) ? false : true;
307 $thisfile_riff_WAVE_MEXT_0['flags']['22_or_44'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0004);
308 $thisfile_riff_WAVE_MEXT_0['flags']['free_format'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0008);
310 $thisfile_riff_WAVE_MEXT_0['nominal_frame_size'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 2, 2));
312 $thisfile_riff_WAVE_MEXT_0['anciliary_data_length'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 6, 2));
313 $thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 8, 2));
314 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_left'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0001);
315 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_free'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0002);
316 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_right'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0004);
319 if (isset($thisfile_riff_WAVE['cart'][0]['data'])) {
321 $thisfile_riff_WAVE_cart_0 = &$thisfile_riff_WAVE['cart'][0];
323 $thisfile_riff_WAVE_cart_0['version'] = substr($thisfile_riff_WAVE_cart_0['data'], 0, 4);
324 $thisfile_riff_WAVE_cart_0['title'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 4, 64));
325 $thisfile_riff_WAVE_cart_0['artist'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 68, 64));
326 $thisfile_riff_WAVE_cart_0['cut_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 132, 64));
327 $thisfile_riff_WAVE_cart_0['client_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 196, 64));
328 $thisfile_riff_WAVE_cart_0['category'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 260, 64));
329 $thisfile_riff_WAVE_cart_0['classification'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 324, 64));
330 $thisfile_riff_WAVE_cart_0['out_cue'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 388, 64));
331 $thisfile_riff_WAVE_cart_0['start_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 452, 10));
332 $thisfile_riff_WAVE_cart_0['start_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 462, 8));
333 $thisfile_riff_WAVE_cart_0['end_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 470, 10));
334 $thisfile_riff_WAVE_cart_0['end_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 480, 8));
335 $thisfile_riff_WAVE_cart_0['producer_app_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 488, 64));
336 $thisfile_riff_WAVE_cart_0['producer_app_version'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 552, 64));
337 $thisfile_riff_WAVE_cart_0['user_defined_text'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 616, 64));
338 $thisfile_riff_WAVE_cart_0['zero_db_reference'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_cart_0['data'], 680, 4), true);
339 for ($i = 0; $i < 8; $i++) {
340 $thisfile_riff_WAVE_cart_0['post_time'][$i]['usage_fourcc'] = substr($thisfile_riff_WAVE_cart_0['data'], 684 + ($i * 8), 4);
341 $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));
343 $thisfile_riff_WAVE_cart_0['url'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 748, 1024));
344 $thisfile_riff_WAVE_cart_0['tag_text'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_cart_0['data'], 1772)));
346 $thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist'];
347 $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_cart_0['title'];
350 if (isset($thisfile_riff_WAVE['SNDM'][0]['data'])) {
351 // SoundMiner metadata
354 $thisfile_riff_WAVE_SNDM_0 = &$thisfile_riff_WAVE['SNDM'][0];
355 $thisfile_riff_WAVE_SNDM_0_data = &$thisfile_riff_WAVE_SNDM_0['data'];
356 $SNDM_startoffset = 0;
357 $SNDM_endoffset = $thisfile_riff_WAVE_SNDM_0['size'];
359 while ($SNDM_startoffset < $SNDM_endoffset) {
360 $SNDM_thisTagOffset = 0;
361 $SNDM_thisTagSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4));
362 $SNDM_thisTagOffset += 4;
363 $SNDM_thisTagKey = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4);
364 $SNDM_thisTagOffset += 4;
365 $SNDM_thisTagDataSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2));
366 $SNDM_thisTagOffset += 2;
367 $SNDM_thisTagDataFlags = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2));
368 $SNDM_thisTagOffset += 2;
369 $SNDM_thisTagDataText = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, $SNDM_thisTagDataSize);
370 $SNDM_thisTagOffset += $SNDM_thisTagDataSize;
372 if ($SNDM_thisTagSize != (4 + 4 + 2 + 2 + $SNDM_thisTagDataSize)) {
373 $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).')';
375 } elseif ($SNDM_thisTagSize <= 0) {
376 $info['warning'][] = 'RIFF.WAVE.SNDM.data contains zero-size tag at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')';
379 $SNDM_startoffset += $SNDM_thisTagSize;
381 $thisfile_riff_WAVE_SNDM_0['parsed_raw'][$SNDM_thisTagKey] = $SNDM_thisTagDataText;
382 if ($parsedkey = self::waveSNDMtagLookup($SNDM_thisTagKey)) {
383 $thisfile_riff_WAVE_SNDM_0['parsed'][$parsedkey] = $SNDM_thisTagDataText;
385 $info['warning'][] = 'RIFF.WAVE.SNDM contains unknown tag "'.$SNDM_thisTagKey.'" at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')';
390 'tracktitle'=>'title',
391 'category' =>'genre',
393 'tracktitle'=>'title',
395 foreach ($tagmapping as $fromkey => $tokey) {
396 if (isset($thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey])) {
397 $thisfile_riff['comments'][$tokey][] = $thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey];
402 if (isset($thisfile_riff_WAVE['iXML'][0]['data'])) {
403 // requires functions simplexml_load_string and get_object_vars
404 if ($parsedXML = getid3_lib::XML2array($thisfile_riff_WAVE['iXML'][0]['data'])) {
405 $thisfile_riff_WAVE['iXML'][0]['parsed'] = $parsedXML;
406 if (isset($parsedXML['SPEED']['MASTER_SPEED'])) {
407 @list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['MASTER_SPEED']);
408 $thisfile_riff_WAVE['iXML'][0]['master_speed'] = $numerator / ($denominator ? $denominator : 1000);
410 if (isset($parsedXML['SPEED']['TIMECODE_RATE'])) {
411 @list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['TIMECODE_RATE']);
412 $thisfile_riff_WAVE['iXML'][0]['timecode_rate'] = $numerator / ($denominator ? $denominator : 1000);
414 if (isset($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO']) && !empty($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) && !empty($thisfile_riff_WAVE['iXML'][0]['timecode_rate'])) {
415 $samples_since_midnight = floatval(ltrim($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_HI'].$parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO'], '0'));
416 $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] = $samples_since_midnight / $parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE'];
417 $h = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] / 3600);
418 $m = floor(($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600)) / 60);
419 $s = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60));
420 $f = ($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60) - $s) * $thisfile_riff_WAVE['iXML'][0]['timecode_rate'];
421 $thisfile_riff_WAVE['iXML'][0]['timecode_string'] = sprintf('%02d:%02d:%02d:%05.2f', $h, $m, $s, $f);
422 $thisfile_riff_WAVE['iXML'][0]['timecode_string_round'] = sprintf('%02d:%02d:%02d:%02d', $h, $m, $s, round($f));
430 if (!isset($thisfile_audio['bitrate']) && isset($thisfile_riff_audio[$streamindex]['bitrate'])) {
431 $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
432 $info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $thisfile_audio['bitrate']);
435 if (!empty($info['wavpack'])) {
436 $thisfile_audio_dataformat = 'wavpack';
437 $thisfile_audio['bitrate_mode'] = 'vbr';
438 $thisfile_audio['encoder'] = 'WavPack v'.$info['wavpack']['version'];
440 // Reset to the way it was - RIFF parsing will have messed this up
441 $info['avdataend'] = $Original['avdataend'];
442 $thisfile_audio['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
444 $this->fseek($info['avdataoffset'] - 44);
445 $RIFFdata = $this->fread(44);
446 $OrignalRIFFheaderSize = getid3_lib::LittleEndian2Int(substr($RIFFdata, 4, 4)) + 8;
447 $OrignalRIFFdataSize = getid3_lib::LittleEndian2Int(substr($RIFFdata, 40, 4)) + 44;
449 if ($OrignalRIFFheaderSize > $OrignalRIFFdataSize) {
450 $info['avdataend'] -= ($OrignalRIFFheaderSize - $OrignalRIFFdataSize);
451 $this->fseek($info['avdataend']);
452 $RIFFdata .= $this->fread($OrignalRIFFheaderSize - $OrignalRIFFdataSize);
455 // move the data chunk after all other chunks (if any)
456 // so that the RIFF parser doesn't see EOF when trying
457 // to skip over the data chunk
458 $RIFFdata = substr($RIFFdata, 0, 36).substr($RIFFdata, 44).substr($RIFFdata, 36, 8);
459 $getid3_riff = new getid3_riff($this->getid3);
460 $getid3_riff->ParseRIFFdata($RIFFdata);
464 if (isset($thisfile_riff_raw['fmt ']['wFormatTag'])) {
465 switch ($thisfile_riff_raw['fmt ']['wFormatTag']) {
467 if (!empty($info['ac3'])) {
468 // Dolby Digital WAV files masquerade as PCM-WAV, but they're not
469 $thisfile_audio['wformattag'] = 0x2000;
470 $thisfile_audio['codec'] = self::wFormatTagLookup($thisfile_audio['wformattag']);
471 $thisfile_audio['lossless'] = false;
472 $thisfile_audio['bitrate'] = $info['ac3']['bitrate'];
473 $thisfile_audio['sample_rate'] = $info['ac3']['sample_rate'];
475 if (!empty($info['dts'])) {
476 // Dolby DTS files masquerade as PCM-WAV, but they're not
477 $thisfile_audio['wformattag'] = 0x2001;
478 $thisfile_audio['codec'] = self::wFormatTagLookup($thisfile_audio['wformattag']);
479 $thisfile_audio['lossless'] = false;
480 $thisfile_audio['bitrate'] = $info['dts']['bitrate'];
481 $thisfile_audio['sample_rate'] = $info['dts']['sample_rate'];
484 case 0x08AE: // ClearJump LiteWave
485 $thisfile_audio['bitrate_mode'] = 'vbr';
486 $thisfile_audio_dataformat = 'litewave';
488 //typedef struct tagSLwFormat {
489 // WORD m_wCompFormat; // low byte defines compression method, high byte is compression flags
490 // DWORD m_dwScale; // scale factor for lossy compression
491 // DWORD m_dwBlockSize; // number of samples in encoded blocks
492 // WORD m_wQuality; // alias for the scale factor
493 // WORD m_wMarkDistance; // distance between marks in bytes
496 // //following paramters are ignored if CF_FILESRC is not set
497 // DWORD m_dwOrgSize; // original file size in bytes
498 // WORD m_bFactExists; // indicates if 'fact' chunk exists in the original file
499 // DWORD m_dwRiffChunkSize; // riff chunk size in the original file
501 // PCMWAVEFORMAT m_OrgWf; // original wave format
502 // }SLwFormat, *PSLwFormat;
505 $thisfile_riff['litewave']['raw'] = array();
506 $riff_litewave = &$thisfile_riff['litewave'];
507 $riff_litewave_raw = &$riff_litewave['raw'];
510 'compression_method' => 1,
511 'compression_flags' => 1,
513 'm_dwBlockSize' => 4,
515 'm_wMarkDistance' => 2,
518 'm_bFactExists' => 2,
519 'm_dwRiffChunkSize' => 4,
521 $litewave_offset = 18;
522 foreach ($flags as $flag => $length) {
523 $riff_litewave_raw[$flag] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE['fmt '][0]['data'], $litewave_offset, $length));
524 $litewave_offset += $length;
527 //$riff_litewave['quality_factor'] = intval(round((2000 - $riff_litewave_raw['m_dwScale']) / 20));
528 $riff_litewave['quality_factor'] = $riff_litewave_raw['m_wQuality'];
530 $riff_litewave['flags']['raw_source'] = ($riff_litewave_raw['compression_flags'] & 0x01) ? false : true;
531 $riff_litewave['flags']['vbr_blocksize'] = ($riff_litewave_raw['compression_flags'] & 0x02) ? false : true;
532 $riff_litewave['flags']['seekpoints'] = (bool) ($riff_litewave_raw['compression_flags'] & 0x04);
534 $thisfile_audio['lossless'] = (($riff_litewave_raw['m_wQuality'] == 100) ? true : false);
535 $thisfile_audio['encoder_options'] = '-q'.$riff_litewave['quality_factor'];
542 if ($info['avdataend'] > $info['filesize']) {
543 switch (!empty($thisfile_audio_dataformat) ? $thisfile_audio_dataformat : '') {
544 case 'wavpack': // WavPack
546 case 'ofr': // OptimFROG
547 case 'ofs': // OptimFROG DualStream
548 // lossless compressed audio formats that keep original RIFF headers - skip warning
552 if (($info['avdataend'] - $info['filesize']) == 1) {
553 // LiteWave appears to incorrectly *not* pad actual output file
554 // to nearest WORD boundary so may appear to be short by one
555 // byte, in which case - skip warning
557 // Short by more than one byte, throw warning
558 $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)';
559 $info['avdataend'] = $info['filesize'];
564 if ((($info['avdataend'] - $info['filesize']) == 1) && (($thisfile_riff[$RIFFsubtype]['data'][0]['size'] % 2) == 0) && ((($info['filesize'] - $info['avdataoffset']) % 2) == 1)) {
565 // output file appears to be incorrectly *not* padded to nearest WORD boundary
566 // Output less severe warning
567 $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)';
568 $info['avdataend'] = $info['filesize'];
570 // Short by more than one byte, throw warning
571 $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)';
572 $info['avdataend'] = $info['filesize'];
577 if (!empty($info['mpeg']['audio']['LAME']['audio_bytes'])) {
578 if ((($info['avdataend'] - $info['avdataoffset']) - $info['mpeg']['audio']['LAME']['audio_bytes']) == 1) {
579 $info['avdataend']--;
580 $info['warning'][] = 'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored';
583 if (isset($thisfile_audio_dataformat) && ($thisfile_audio_dataformat == 'ac3')) {
584 unset($thisfile_audio['bits_per_sample']);
585 if (!empty($info['ac3']['bitrate']) && ($info['ac3']['bitrate'] != $thisfile_audio['bitrate'])) {
586 $thisfile_audio['bitrate'] = $info['ac3']['bitrate'];
592 $thisfile_video['bitrate_mode'] = 'vbr'; // maybe not, but probably
593 $thisfile_video['dataformat'] = 'avi';
594 $info['mime_type'] = 'video/avi';
596 if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) {
597 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['movi']['offset'] + 8;
598 if (isset($thisfile_riff['AVIX'])) {
599 $info['avdataend'] = $thisfile_riff['AVIX'][(count($thisfile_riff['AVIX']) - 1)]['chunks']['movi']['offset'] + $thisfile_riff['AVIX'][(count($thisfile_riff['AVIX']) - 1)]['chunks']['movi']['size'];
601 $info['avdataend'] = $thisfile_riff['AVI ']['movi']['offset'] + $thisfile_riff['AVI ']['movi']['size'];
603 if ($info['avdataend'] > $info['filesize']) {
604 $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)';
605 $info['avdataend'] = $info['filesize'];
609 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['indx'])) {
610 //$bIndexType = array(
611 // 0x00 => 'AVI_INDEX_OF_INDEXES',
612 // 0x01 => 'AVI_INDEX_OF_CHUNKS',
613 // 0x80 => 'AVI_INDEX_IS_DATA',
615 //$bIndexSubtype = array(
617 // 0x01 => 'AVI_INDEX_2FIELD',
620 foreach ($thisfile_riff['AVI ']['hdrl']['strl']['indx'] as $streamnumber => $steamdataarray) {
621 $ahsisd = &$thisfile_riff['AVI ']['hdrl']['strl']['indx'][$streamnumber]['data'];
623 $thisfile_riff_raw['indx'][$streamnumber]['wLongsPerEntry'] = $this->EitherEndian2Int(substr($ahsisd, 0, 2));
624 $thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType'] = $this->EitherEndian2Int(substr($ahsisd, 2, 1));
625 $thisfile_riff_raw['indx'][$streamnumber]['bIndexType'] = $this->EitherEndian2Int(substr($ahsisd, 3, 1));
626 $thisfile_riff_raw['indx'][$streamnumber]['nEntriesInUse'] = $this->EitherEndian2Int(substr($ahsisd, 4, 4));
627 $thisfile_riff_raw['indx'][$streamnumber]['dwChunkId'] = substr($ahsisd, 8, 4);
628 $thisfile_riff_raw['indx'][$streamnumber]['dwReserved'] = $this->EitherEndian2Int(substr($ahsisd, 12, 4));
630 //$thisfile_riff_raw['indx'][$streamnumber]['bIndexType_name'] = $bIndexType[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']];
631 //$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType_name'] = $bIndexSubtype[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']][$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType']];
636 if (isset($thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'])) {
637 $avihData = $thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'];
640 $thisfile_riff_raw['avih'] = array();
641 $thisfile_riff_raw_avih = &$thisfile_riff_raw['avih'];
643 $thisfile_riff_raw_avih['dwMicroSecPerFrame'] = $this->EitherEndian2Int(substr($avihData, 0, 4)); // frame display rate (or 0L)
644 if ($thisfile_riff_raw_avih['dwMicroSecPerFrame'] == 0) {
645 $info['error'][] = 'Corrupt RIFF file: avih.dwMicroSecPerFrame == zero';
650 'dwMaxBytesPerSec', // max. transfer rate
651 'dwPaddingGranularity', // pad to multiples of this size; normally 2K.
652 'dwFlags', // the ever-present flags
653 'dwTotalFrames', // # frames in file
654 'dwInitialFrames', //
656 'dwSuggestedBufferSize', //
665 foreach ($flags as $flag) {
666 $thisfile_riff_raw_avih[$flag] = $this->EitherEndian2Int(substr($avihData, $avih_offset, 4));
671 'hasindex' => 0x00000010,
672 'mustuseindex' => 0x00000020,
673 'interleaved' => 0x00000100,
674 'trustcktype' => 0x00000800,
675 'capturedfile' => 0x00010000,
676 'copyrighted' => 0x00020010,
678 foreach ($flags as $flag => $value) {
679 $thisfile_riff_raw_avih['flags'][$flag] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & $value);
683 $thisfile_riff_video[$streamindex] = array();
684 $thisfile_riff_video_current = &$thisfile_riff_video[$streamindex];
686 if ($thisfile_riff_raw_avih['dwWidth'] > 0) {
687 $thisfile_riff_video_current['frame_width'] = $thisfile_riff_raw_avih['dwWidth'];
688 $thisfile_video['resolution_x'] = $thisfile_riff_video_current['frame_width'];
690 if ($thisfile_riff_raw_avih['dwHeight'] > 0) {
691 $thisfile_riff_video_current['frame_height'] = $thisfile_riff_raw_avih['dwHeight'];
692 $thisfile_video['resolution_y'] = $thisfile_riff_video_current['frame_height'];
694 if ($thisfile_riff_raw_avih['dwTotalFrames'] > 0) {
695 $thisfile_riff_video_current['total_frames'] = $thisfile_riff_raw_avih['dwTotalFrames'];
696 $thisfile_video['total_frames'] = $thisfile_riff_video_current['total_frames'];
699 $thisfile_riff_video_current['frame_rate'] = round(1000000 / $thisfile_riff_raw_avih['dwMicroSecPerFrame'], 3);
700 $thisfile_video['frame_rate'] = $thisfile_riff_video_current['frame_rate'];
702 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][0]['data'])) {
703 if (is_array($thisfile_riff['AVI ']['hdrl']['strl']['strh'])) {
704 for ($i = 0; $i < count($thisfile_riff['AVI ']['hdrl']['strl']['strh']); $i++) {
705 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'])) {
706 $strhData = $thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'];
707 $strhfccType = substr($strhData, 0, 4);
709 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'])) {
710 $strfData = $thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'];
713 $thisfile_riff_raw_strf_strhfccType_streamindex = &$thisfile_riff_raw['strf'][$strhfccType][$streamindex];
715 switch ($strhfccType) {
717 $thisfile_audio['bitrate_mode'] = 'cbr';
718 $thisfile_audio_dataformat = 'wav';
719 if (isset($thisfile_riff_audio) && is_array($thisfile_riff_audio)) {
720 $streamindex = count($thisfile_riff_audio);
723 $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($strfData);
724 $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
727 $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
728 $thisfile_audio_streams_currentstream = &$thisfile_audio['streams'][$streamindex];
730 if ($thisfile_audio_streams_currentstream['bits_per_sample'] == 0) {
731 unset($thisfile_audio_streams_currentstream['bits_per_sample']);
733 $thisfile_audio_streams_currentstream['wformattag'] = $thisfile_audio_streams_currentstream['raw']['wFormatTag'];
734 unset($thisfile_audio_streams_currentstream['raw']);
737 $thisfile_riff_raw['strf'][$strhfccType][$streamindex] = $thisfile_riff_audio[$streamindex]['raw'];
739 unset($thisfile_riff_audio[$streamindex]['raw']);
740 $thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
742 $thisfile_audio['lossless'] = false;
743 switch ($thisfile_riff_raw_strf_strhfccType_streamindex['wFormatTag']) {
745 $thisfile_audio_dataformat = 'wav';
746 $thisfile_audio['lossless'] = true;
749 case 0x0050: // MPEG Layer 2 or Layer 1
750 $thisfile_audio_dataformat = 'mp2'; // Assume Layer-2
753 case 0x0055: // MPEG Layer 3
754 $thisfile_audio_dataformat = 'mp3';
758 $thisfile_audio_dataformat = 'aac';
761 case 0x0161: // Windows Media v7 / v8 / v9
762 case 0x0162: // Windows Media Professional v9
763 case 0x0163: // Windows Media Lossess v9
764 $thisfile_audio_dataformat = 'wma';
768 $thisfile_audio_dataformat = 'ac3';
772 $thisfile_audio_dataformat = 'dts';
776 $thisfile_audio_dataformat = 'wav';
779 $thisfile_audio_streams_currentstream['dataformat'] = $thisfile_audio_dataformat;
780 $thisfile_audio_streams_currentstream['lossless'] = $thisfile_audio['lossless'];
781 $thisfile_audio_streams_currentstream['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
788 $thisfile_riff_raw['strh'][$i] = array();
789 $thisfile_riff_raw_strh_current = &$thisfile_riff_raw['strh'][$i];
791 $thisfile_riff_raw_strh_current['fccType'] = substr($strhData, 0, 4); // same as $strhfccType;
792 $thisfile_riff_raw_strh_current['fccHandler'] = substr($strhData, 4, 4);
793 $thisfile_riff_raw_strh_current['dwFlags'] = $this->EitherEndian2Int(substr($strhData, 8, 4)); // Contains AVITF_* flags
794 $thisfile_riff_raw_strh_current['wPriority'] = $this->EitherEndian2Int(substr($strhData, 12, 2));
795 $thisfile_riff_raw_strh_current['wLanguage'] = $this->EitherEndian2Int(substr($strhData, 14, 2));
796 $thisfile_riff_raw_strh_current['dwInitialFrames'] = $this->EitherEndian2Int(substr($strhData, 16, 4));
797 $thisfile_riff_raw_strh_current['dwScale'] = $this->EitherEndian2Int(substr($strhData, 20, 4));
798 $thisfile_riff_raw_strh_current['dwRate'] = $this->EitherEndian2Int(substr($strhData, 24, 4));
799 $thisfile_riff_raw_strh_current['dwStart'] = $this->EitherEndian2Int(substr($strhData, 28, 4));
800 $thisfile_riff_raw_strh_current['dwLength'] = $this->EitherEndian2Int(substr($strhData, 32, 4));
801 $thisfile_riff_raw_strh_current['dwSuggestedBufferSize'] = $this->EitherEndian2Int(substr($strhData, 36, 4));
802 $thisfile_riff_raw_strh_current['dwQuality'] = $this->EitherEndian2Int(substr($strhData, 40, 4));
803 $thisfile_riff_raw_strh_current['dwSampleSize'] = $this->EitherEndian2Int(substr($strhData, 44, 4));
804 $thisfile_riff_raw_strh_current['rcFrame'] = $this->EitherEndian2Int(substr($strhData, 48, 4));
806 $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strh_current['fccHandler']);
807 $thisfile_video['fourcc'] = $thisfile_riff_raw_strh_current['fccHandler'];
808 if (!$thisfile_riff_video_current['codec'] && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) && self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
809 $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']);
810 $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
812 $thisfile_video['codec'] = $thisfile_riff_video_current['codec'];
813 $thisfile_video['pixel_aspect_ratio'] = (float) 1;
814 switch ($thisfile_riff_raw_strh_current['fccHandler']) {
815 case 'HFYU': // Huffman Lossless Codec
816 case 'IRAW': // Intel YUV Uncompressed
817 case 'YUY2': // Uncompressed YUV 4:2:2
818 $thisfile_video['lossless'] = true;
822 $thisfile_video['lossless'] = false;
826 switch ($strhfccType) {
828 $thisfile_riff_raw_strf_strhfccType_streamindex = self::ParseBITMAPINFOHEADER(substr($strfData, 0, 40), ($info['fileformat'] == 'riff'));
829 $thisfile_video['bits_per_sample'] = $thisfile_riff_raw_strf_strhfccType_streamindex['biBitCount'];
831 if ($thisfile_riff_video_current['codec'] == 'DV') {
832 $thisfile_riff_video_current['dv_type'] = 2;
837 $thisfile_riff_video_current['dv_type'] = 1;
843 $info['warning'][] = 'Unhandled fccType for stream ('.$i.'): "'.$strhfccType.'"';
850 if (isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
852 $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
853 if (self::fourccLookup($thisfile_video['fourcc'])) {
854 $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_video['fourcc']);
855 $thisfile_video['codec'] = $thisfile_riff_video_current['codec'];
858 switch ($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) {
859 case 'HFYU': // Huffman Lossless Codec
860 case 'IRAW': // Intel YUV Uncompressed
861 case 'YUY2': // Uncompressed YUV 4:2:2
862 $thisfile_video['lossless'] = true;
863 //$thisfile_video['bits_per_sample'] = 24;
867 $thisfile_video['lossless'] = false;
868 //$thisfile_video['bits_per_sample'] = 24;
879 $thisfile_audio['bitrate_mode'] = 'cbr';
880 $thisfile_audio_dataformat = 'cda';
881 $thisfile_audio['lossless'] = true;
882 unset($info['mime_type']);
884 $info['avdataoffset'] = 44;
886 if (isset($thisfile_riff['CDDA']['fmt '][0]['data'])) {
888 $thisfile_riff_CDDA_fmt_0 = &$thisfile_riff['CDDA']['fmt '][0];
890 $thisfile_riff_CDDA_fmt_0['unknown1'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 0, 2));
891 $thisfile_riff_CDDA_fmt_0['track_num'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 2, 2));
892 $thisfile_riff_CDDA_fmt_0['disc_id'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 4, 4));
893 $thisfile_riff_CDDA_fmt_0['start_offset_frame'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 8, 4));
894 $thisfile_riff_CDDA_fmt_0['playtime_frames'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 12, 4));
895 $thisfile_riff_CDDA_fmt_0['unknown6'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 16, 4));
896 $thisfile_riff_CDDA_fmt_0['unknown7'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 20, 4));
898 $thisfile_riff_CDDA_fmt_0['start_offset_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['start_offset_frame'] / 75;
899 $thisfile_riff_CDDA_fmt_0['playtime_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['playtime_frames'] / 75;
900 $info['comments']['track'] = $thisfile_riff_CDDA_fmt_0['track_num'];
901 $info['playtime_seconds'] = $thisfile_riff_CDDA_fmt_0['playtime_seconds'];
903 // hardcoded data for CD-audio
904 $thisfile_audio['sample_rate'] = 44100;
905 $thisfile_audio['channels'] = 2;
906 $thisfile_audio['bits_per_sample'] = 16;
907 $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $thisfile_audio['channels'] * $thisfile_audio['bits_per_sample'];
908 $thisfile_audio['bitrate_mode'] = 'cbr';
915 $thisfile_audio['bitrate_mode'] = 'cbr';
916 $thisfile_audio_dataformat = 'aiff';
917 $thisfile_audio['lossless'] = true;
918 $info['mime_type'] = 'audio/x-aiff';
920 if (isset($thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'])) {
921 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'] + 8;
922 $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['SSND'][0]['size'];
923 if ($info['avdataend'] > $info['filesize']) {
924 if (($info['avdataend'] == ($info['filesize'] + 1)) && (($info['filesize'] % 2) == 1)) {
925 // structures rounded to 2-byte boundary, but dumb encoders
926 // forget to pad end of file to make this actually work
928 $info['warning'][] = 'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['SSND'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found';
930 $info['avdataend'] = $info['filesize'];
934 if (isset($thisfile_riff[$RIFFsubtype]['COMM'][0]['data'])) {
937 $thisfile_riff_RIFFsubtype_COMM_0_data = &$thisfile_riff[$RIFFsubtype]['COMM'][0]['data'];
939 $thisfile_riff_audio['channels'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 0, 2), true);
940 $thisfile_riff_audio['total_samples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 2, 4), false);
941 $thisfile_riff_audio['bits_per_sample'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 6, 2), true);
942 $thisfile_riff_audio['sample_rate'] = (int) getid3_lib::BigEndian2Float(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 8, 10));
944 if ($thisfile_riff[$RIFFsubtype]['COMM'][0]['size'] > 18) {
945 $thisfile_riff_audio['codec_fourcc'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 18, 4);
946 $CodecNameSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 22, 1), false);
947 $thisfile_riff_audio['codec_name'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 23, $CodecNameSize);
948 switch ($thisfile_riff_audio['codec_name']) {
950 $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)';
951 $thisfile_audio['lossless'] = true;
955 switch ($thisfile_riff_audio['codec_fourcc']) {
956 // http://developer.apple.com/qa/snd/snd07.html
958 $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Little-Endian PCM';
959 $thisfile_audio['lossless'] = true;
963 $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Big-Endian PCM';
964 $thisfile_audio['lossless'] = true;
973 $thisfile_audio['codec'] = $thisfile_riff_audio['codec_name'];
974 $thisfile_audio['lossless'] = false;
979 $thisfile_audio['channels'] = $thisfile_riff_audio['channels'];
980 if ($thisfile_riff_audio['bits_per_sample'] > 0) {
981 $thisfile_audio['bits_per_sample'] = $thisfile_riff_audio['bits_per_sample'];
983 $thisfile_audio['sample_rate'] = $thisfile_riff_audio['sample_rate'];
984 if ($thisfile_audio['sample_rate'] == 0) {
985 $info['error'][] = 'Corrupted AIFF file: sample_rate == zero';
988 $info['playtime_seconds'] = $thisfile_riff_audio['total_samples'] / $thisfile_audio['sample_rate'];
991 if (isset($thisfile_riff[$RIFFsubtype]['COMT'])) {
993 $CommentCount = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false);
995 for ($i = 0; $i < $CommentCount; $i++) {
996 $info['comments_raw'][$i]['timestamp'] = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 4), false);
998 $info['comments_raw'][$i]['marker_id'] = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), true);
1000 $CommentLength = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false);
1002 $info['comments_raw'][$i]['comment'] = substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, $CommentLength);
1003 $offset += $CommentLength;
1005 $info['comments_raw'][$i]['timestamp_unix'] = getid3_lib::DateMac2Unix($info['comments_raw'][$i]['timestamp']);
1006 $thisfile_riff['comments']['comment'][] = $info['comments_raw'][$i]['comment'];
1010 $CommentsChunkNames = array('NAME'=>'title', 'author'=>'artist', '(c) '=>'copyright', 'ANNO'=>'comment');
1011 foreach ($CommentsChunkNames as $key => $value) {
1012 if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) {
1013 $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data'];
1017 if (isset($thisfile_riff[$RIFFsubtype]['ID3 '])) {
1018 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
1019 $getid3_temp = new getID3();
1020 $getid3_temp->openfile($this->getid3->filename);
1021 $getid3_id3v2 = new getid3_id3v2($getid3_temp);
1022 $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['ID3 '][0]['offset'] + 8;
1023 if ($thisfile_riff[$RIFFsubtype]['ID3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
1024 $info['id3v2'] = $getid3_temp->info['id3v2'];
1026 unset($getid3_temp, $getid3_id3v2);
1032 $thisfile_audio['bitrate_mode'] = 'cbr';
1033 $thisfile_audio_dataformat = '8svx';
1034 $thisfile_audio['bits_per_sample'] = 8;
1035 $thisfile_audio['channels'] = 1; // overridden below, if need be
1036 $info['mime_type'] = 'audio/x-aiff';
1038 if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) {
1039 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8;
1040 $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['BODY'][0]['size'];
1041 if ($info['avdataend'] > $info['filesize']) {
1042 $info['warning'][] = 'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['BODY'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found';
1046 if (isset($thisfile_riff[$RIFFsubtype]['VHDR'][0]['offset'])) {
1048 $thisfile_riff_RIFFsubtype_VHDR_0 = &$thisfile_riff[$RIFFsubtype]['VHDR'][0];
1050 $thisfile_riff_RIFFsubtype_VHDR_0['oneShotHiSamples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 0, 4));
1051 $thisfile_riff_RIFFsubtype_VHDR_0['repeatHiSamples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 4, 4));
1052 $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerHiCycle'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 8, 4));
1053 $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 12, 2));
1054 $thisfile_riff_RIFFsubtype_VHDR_0['ctOctave'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 14, 1));
1055 $thisfile_riff_RIFFsubtype_VHDR_0['sCompression'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 15, 1));
1056 $thisfile_riff_RIFFsubtype_VHDR_0['Volume'] = getid3_lib::FixedPoint16_16(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 16, 4));
1058 $thisfile_audio['sample_rate'] = $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec'];
1060 switch ($thisfile_riff_RIFFsubtype_VHDR_0['sCompression']) {
1062 $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)';
1063 $thisfile_audio['lossless'] = true;
1064 $ActualBitsPerSample = 8;
1068 $thisfile_audio['codec'] = 'Fibonacci-delta encoding';
1069 $thisfile_audio['lossless'] = false;
1070 $ActualBitsPerSample = 4;
1074 $info['warning'][] = 'Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.sCompression.'"';
1079 if (isset($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'])) {
1080 $ChannelsIndex = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'], 0, 4));
1081 switch ($ChannelsIndex) {
1083 $thisfile_audio['channels'] = 2;
1086 case 2: // Left channel only
1087 case 4: // Right channel only
1088 $thisfile_audio['channels'] = 1;
1092 $info['warning'][] = 'Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "'.$ChannelsIndex.'"';
1098 $CommentsChunkNames = array('NAME'=>'title', 'author'=>'artist', '(c) '=>'copyright', 'ANNO'=>'comment');
1099 foreach ($CommentsChunkNames as $key => $value) {
1100 if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) {
1101 $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data'];
1105 $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $ActualBitsPerSample * $thisfile_audio['channels'];
1106 if (!empty($thisfile_audio['bitrate'])) {
1107 $info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset']) / ($thisfile_audio['bitrate'] / 8);
1113 $info['mime_type'] = 'video/mpeg';
1114 if (!empty($thisfile_riff['CDXA']['data'][0]['size'])) {
1115 if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.mpeg.php', __FILE__, false)) {
1116 $getid3_temp = new getID3();
1117 $getid3_temp->openfile($this->getid3->filename);
1118 $getid3_mpeg = new getid3_mpeg($getid3_temp);
1119 $getid3_mpeg->Analyze();
1120 if (empty($getid3_temp->info['error'])) {
1121 $info['audio'] = $getid3_temp->info['audio'];
1122 $info['video'] = $getid3_temp->info['video'];
1123 $info['mpeg'] = $getid3_temp->info['mpeg'];
1124 $info['warning'] = $getid3_temp->info['warning'];
1126 unset($getid3_temp, $getid3_mpeg);
1133 $info['error'][] = 'Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA), found "'.$RIFFsubtype.'" instead';
1134 unset($info['fileformat']);
1138 switch ($RIFFsubtype) {
1142 $ID3v2_key_good = 'id3 ';
1143 $ID3v2_keys_bad = array('ID3 ', 'tag ');
1144 foreach ($ID3v2_keys_bad as $ID3v2_key_bad) {
1145 if (isset($thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]) && !array_key_exists($ID3v2_key_good, $thisfile_riff[$RIFFsubtype])) {
1146 $thisfile_riff[$RIFFsubtype][$ID3v2_key_good] = $thisfile_riff[$RIFFsubtype][$ID3v2_key_bad];
1147 $info['warning'][] = 'mapping "'.$ID3v2_key_bad.'" chunk to "'.$ID3v2_key_good.'"';
1151 if (isset($thisfile_riff[$RIFFsubtype]['id3 '])) {
1152 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
1153 $getid3_temp = new getID3();
1154 $getid3_temp->openfile($this->getid3->filename);
1155 $getid3_id3v2 = new getid3_id3v2($getid3_temp);
1156 $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['id3 '][0]['offset'] + 8;
1157 if ($thisfile_riff[$RIFFsubtype]['id3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
1158 $info['id3v2'] = $getid3_temp->info['id3v2'];
1160 unset($getid3_temp, $getid3_id3v2);
1165 if (isset($thisfile_riff_WAVE['DISP']) && is_array($thisfile_riff_WAVE['DISP'])) {
1166 $thisfile_riff['comments']['title'][] = trim(substr($thisfile_riff_WAVE['DISP'][count($thisfile_riff_WAVE['DISP']) - 1]['data'], 4));
1168 if (isset($thisfile_riff_WAVE['INFO']) && is_array($thisfile_riff_WAVE['INFO'])) {
1169 self::parseComments($thisfile_riff_WAVE['INFO'], $thisfile_riff['comments']);
1171 if (isset($thisfile_riff['AVI ']['INFO']) && is_array($thisfile_riff['AVI ']['INFO'])) {
1172 self::parseComments($thisfile_riff['AVI ']['INFO'], $thisfile_riff['comments']);
1175 if (empty($thisfile_audio['encoder']) && !empty($info['mpeg']['audio']['LAME']['short_version'])) {
1176 $thisfile_audio['encoder'] = $info['mpeg']['audio']['LAME']['short_version'];
1179 if (!isset($info['playtime_seconds'])) {
1180 $info['playtime_seconds'] = 0;
1182 if (isset($thisfile_riff_raw['strh'][0]['dwLength']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) {
1183 // needed for >2GB AVIs where 'avih' chunk only lists number of frames in that chunk, not entire movie
1184 $info['playtime_seconds'] = $thisfile_riff_raw['strh'][0]['dwLength'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000);
1185 } elseif (isset($thisfile_riff_raw['avih']['dwTotalFrames']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) {
1186 $info['playtime_seconds'] = $thisfile_riff_raw['avih']['dwTotalFrames'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000);
1189 if ($info['playtime_seconds'] > 0) {
1190 if (isset($thisfile_riff_audio) && isset($thisfile_riff_video)) {
1192 if (!isset($info['bitrate'])) {
1193 $info['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8);
1196 } elseif (isset($thisfile_riff_audio) && !isset($thisfile_riff_video)) {
1198 if (!isset($thisfile_audio['bitrate'])) {
1199 $thisfile_audio['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8);
1202 } elseif (!isset($thisfile_riff_audio) && isset($thisfile_riff_video)) {
1204 if (!isset($thisfile_video['bitrate'])) {
1205 $thisfile_video['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8);
1212 if (isset($thisfile_riff_video) && isset($thisfile_audio['bitrate']) && ($thisfile_audio['bitrate'] > 0) && ($info['playtime_seconds'] > 0)) {
1214 $info['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8);
1215 $thisfile_audio['bitrate'] = 0;
1216 $thisfile_video['bitrate'] = $info['bitrate'];
1217 foreach ($thisfile_riff_audio as $channelnumber => $audioinfoarray) {
1218 $thisfile_video['bitrate'] -= $audioinfoarray['bitrate'];
1219 $thisfile_audio['bitrate'] += $audioinfoarray['bitrate'];
1221 if ($thisfile_video['bitrate'] <= 0) {
1222 unset($thisfile_video['bitrate']);
1224 if ($thisfile_audio['bitrate'] <= 0) {
1225 unset($thisfile_audio['bitrate']);
1229 if (isset($info['mpeg']['audio'])) {
1230 $thisfile_audio_dataformat = 'mp'.$info['mpeg']['audio']['layer'];
1231 $thisfile_audio['sample_rate'] = $info['mpeg']['audio']['sample_rate'];
1232 $thisfile_audio['channels'] = $info['mpeg']['audio']['channels'];
1233 $thisfile_audio['bitrate'] = $info['mpeg']['audio']['bitrate'];
1234 $thisfile_audio['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
1235 if (!empty($info['mpeg']['audio']['codec'])) {
1236 $thisfile_audio['codec'] = $info['mpeg']['audio']['codec'].' '.$thisfile_audio['codec'];
1238 if (!empty($thisfile_audio['streams'])) {
1239 foreach ($thisfile_audio['streams'] as $streamnumber => $streamdata) {
1240 if ($streamdata['dataformat'] == $thisfile_audio_dataformat) {
1241 $thisfile_audio['streams'][$streamnumber]['sample_rate'] = $thisfile_audio['sample_rate'];
1242 $thisfile_audio['streams'][$streamnumber]['channels'] = $thisfile_audio['channels'];
1243 $thisfile_audio['streams'][$streamnumber]['bitrate'] = $thisfile_audio['bitrate'];
1244 $thisfile_audio['streams'][$streamnumber]['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
1245 $thisfile_audio['streams'][$streamnumber]['codec'] = $thisfile_audio['codec'];
1249 $getid3_mp3 = new getid3_mp3($this->getid3);
1250 $thisfile_audio['encoder_options'] = $getid3_mp3->GuessEncoderOptions();
1255 if (!empty($thisfile_riff_raw['fmt ']['wBitsPerSample']) && ($thisfile_riff_raw['fmt ']['wBitsPerSample'] > 0)) {
1256 switch ($thisfile_audio_dataformat) {
1258 // ignore bits_per_sample
1262 $thisfile_audio['bits_per_sample'] = $thisfile_riff_raw['fmt ']['wBitsPerSample'];
1268 if (empty($thisfile_riff_raw)) {
1269 unset($thisfile_riff['raw']);
1271 if (empty($thisfile_riff_audio)) {
1272 unset($thisfile_riff['audio']);
1274 if (empty($thisfile_riff_video)) {
1275 unset($thisfile_riff['video']);
1281 public function ParseRIFF($startoffset, $maxoffset) {
1282 $info = &$this->getid3->info;
1285 $FoundAllChunksWeNeed = false;
1288 $this->fseek($startoffset);
1289 $maxoffset = min($maxoffset, $info['avdataend']);
1290 while ($this->ftell() < $maxoffset) {
1291 $chunknamesize = $this->fread(8);
1292 //$chunkname = substr($chunknamesize, 0, 4);
1293 $chunkname = str_replace("\x00", '_', substr($chunknamesize, 0, 4)); // note: chunk names of 4 null bytes do appear to be legal (has been observed inside INFO and PRMI chunks, for example), but makes traversing array keys more difficult
1294 $chunksize = $this->EitherEndian2Int(substr($chunknamesize, 4, 4));
1295 //if (strlen(trim($chunkname, "\x00")) < 4) {
1296 if (strlen($chunkname) < 4) {
1297 $this->error('Expecting chunk name at offset '.($this->ftell() - 8).' but found nothing. Aborting RIFF parsing.');
1300 if (($chunksize == 0) && ($chunkname != 'JUNK')) {
1301 $this->warning('Chunk ('.$chunkname.') size at offset '.($this->ftell() - 4).' is zero. Aborting RIFF parsing.');
1304 if (($chunksize % 2) != 0) {
1305 // all structures are packed on word boundaries
1309 switch ($chunkname) {
1311 $listname = $this->fread(4);
1312 if (preg_match('#^(movi|rec )$#i', $listname)) {
1313 $RIFFchunk[$listname]['offset'] = $this->ftell() - 4;
1314 $RIFFchunk[$listname]['size'] = $chunksize;
1316 if (!$FoundAllChunksWeNeed) {
1317 $WhereWeWere = $this->ftell();
1318 $AudioChunkHeader = $this->fread(12);
1319 $AudioChunkStreamNum = substr($AudioChunkHeader, 0, 2);
1320 $AudioChunkStreamType = substr($AudioChunkHeader, 2, 2);
1321 $AudioChunkSize = getid3_lib::LittleEndian2Int(substr($AudioChunkHeader, 4, 4));
1323 if ($AudioChunkStreamType == 'wb') {
1324 $FirstFourBytes = substr($AudioChunkHeader, 8, 4);
1325 if (preg_match('/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', $FirstFourBytes)) {
1327 if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) {
1328 $getid3_temp = new getID3();
1329 $getid3_temp->openfile($this->getid3->filename);
1330 $getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
1331 $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize;
1332 $getid3_mp3 = new getid3_mp3($getid3_temp);
1333 $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false);
1334 if (isset($getid3_temp->info['mpeg']['audio'])) {
1335 $info['mpeg']['audio'] = $getid3_temp->info['mpeg']['audio'];
1336 $info['audio'] = $getid3_temp->info['audio'];
1337 $info['audio']['dataformat'] = 'mp'.$info['mpeg']['audio']['layer'];
1338 $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate'];
1339 $info['audio']['channels'] = $info['mpeg']['audio']['channels'];
1340 $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate'];
1341 $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
1342 //$info['bitrate'] = $info['audio']['bitrate'];
1344 unset($getid3_temp, $getid3_mp3);
1347 } elseif (strpos($FirstFourBytes, getid3_ac3::syncword) === 0) {
1350 $getid3_temp = new getID3();
1351 $getid3_temp->openfile($this->getid3->filename);
1352 $getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
1353 $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize;
1354 $getid3_ac3 = new getid3_ac3($getid3_temp);
1355 $getid3_ac3->Analyze();
1356 if (empty($getid3_temp->info['error'])) {
1357 $info['audio'] = $getid3_temp->info['audio'];
1358 $info['ac3'] = $getid3_temp->info['ac3'];
1359 if (!empty($getid3_temp->info['warning'])) {
1360 foreach ($getid3_temp->info['warning'] as $key => $value) {
1361 $info['warning'][] = $value;
1365 unset($getid3_temp, $getid3_ac3);
1368 $FoundAllChunksWeNeed = true;
1369 $this->fseek($WhereWeWere);
1371 $this->fseek($chunksize - 4, SEEK_CUR);
1375 if (!isset($RIFFchunk[$listname])) {
1376 $RIFFchunk[$listname] = array();
1378 $LISTchunkParent = $listname;
1379 $LISTchunkMaxOffset = $this->ftell() - 4 + $chunksize;
1380 if ($parsedChunk = $this->ParseRIFF($this->ftell(), $LISTchunkMaxOffset)) {
1381 $RIFFchunk[$listname] = array_merge_recursive($RIFFchunk[$listname], $parsedChunk);
1388 if (preg_match('#^[0-9]{2}(wb|pc|dc|db)$#', $chunkname)) {
1389 $this->fseek($chunksize, SEEK_CUR);
1393 if (isset($RIFFchunk[$chunkname]) && is_array($RIFFchunk[$chunkname])) {
1394 $thisindex = count($RIFFchunk[$chunkname]);
1396 $RIFFchunk[$chunkname][$thisindex]['offset'] = $this->ftell() - 8;
1397 $RIFFchunk[$chunkname][$thisindex]['size'] = $chunksize;
1398 switch ($chunkname) {
1400 $info['avdataoffset'] = $this->ftell();
1401 $info['avdataend'] = $info['avdataoffset'] + $chunksize;
1403 $testData = $this->fread(36);
1404 if ($testData === '') {
1407 if (preg_match('/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', substr($testData, 0, 4))) {
1409 // Probably is MP3 data
1410 if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($testData, 0, 4))) {
1411 $getid3_temp = new getID3();
1412 $getid3_temp->openfile($this->getid3->filename);
1413 $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
1414 $getid3_temp->info['avdataend'] = $info['avdataend'];
1415 $getid3_mp3 = new getid3_mp3($getid3_temp);
1416 $getid3_mp3->getOnlyMPEGaudioInfo($info['avdataoffset'], false);
1417 if (empty($getid3_temp->info['error'])) {
1418 $info['audio'] = $getid3_temp->info['audio'];
1419 $info['mpeg'] = $getid3_temp->info['mpeg'];
1421 unset($getid3_temp, $getid3_mp3);
1424 } elseif (($isRegularAC3 = (substr($testData, 0, 2) == getid3_ac3::syncword)) || substr($testData, 8, 2) == strrev(getid3_ac3::syncword)) {
1426 // This is probably AC-3 data
1427 $getid3_temp = new getID3();
1428 if ($isRegularAC3) {
1429 $getid3_temp->openfile($this->getid3->filename);
1430 $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
1431 $getid3_temp->info['avdataend'] = $info['avdataend'];
1433 $getid3_ac3 = new getid3_ac3($getid3_temp);
1434 if ($isRegularAC3) {
1435 $getid3_ac3->Analyze();
1437 // Dolby Digital WAV
1438 // AC-3 content, but not encoded in same format as normal AC-3 file
1439 // For one thing, byte order is swapped
1441 for ($i = 0; $i < 28; $i += 2) {
1442 $ac3_data .= substr($testData, 8 + $i + 1, 1);
1443 $ac3_data .= substr($testData, 8 + $i + 0, 1);
1445 $getid3_ac3->AnalyzeString($ac3_data);
1448 if (empty($getid3_temp->info['error'])) {
1449 $info['audio'] = $getid3_temp->info['audio'];
1450 $info['ac3'] = $getid3_temp->info['ac3'];
1451 if (!empty($getid3_temp->info['warning'])) {
1452 foreach ($getid3_temp->info['warning'] as $newerror) {
1453 $this->warning('getid3_ac3() says: ['.$newerror.']');
1457 unset($getid3_temp, $getid3_ac3);
1459 } elseif (preg_match('/^('.implode('|', array_map('preg_quote', getid3_dts::$syncwords)).')/', $testData)) {
1461 // This is probably DTS data
1462 $getid3_temp = new getID3();
1463 $getid3_temp->openfile($this->getid3->filename);
1464 $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
1465 $getid3_dts = new getid3_dts($getid3_temp);
1466 $getid3_dts->Analyze();
1467 if (empty($getid3_temp->info['error'])) {
1468 $info['audio'] = $getid3_temp->info['audio'];
1469 $info['dts'] = $getid3_temp->info['dts'];
1470 $info['playtime_seconds'] = $getid3_temp->info['playtime_seconds']; // may not match RIFF calculations since DTS-WAV often used 14/16 bit-word packing
1471 if (!empty($getid3_temp->info['warning'])) {
1472 foreach ($getid3_temp->info['warning'] as $newerror) {
1473 $this->warning('getid3_dts() says: ['.$newerror.']');
1478 unset($getid3_temp, $getid3_dts);
1480 } elseif (substr($testData, 0, 4) == 'wvpk') {
1482 // This is WavPack data
1483 $info['wavpack']['offset'] = $info['avdataoffset'];
1484 $info['wavpack']['size'] = getid3_lib::LittleEndian2Int(substr($testData, 4, 4));
1485 $this->parseWavPackHeader(substr($testData, 8, 28));
1488 // This is some other kind of data (quite possibly just PCM)
1489 // do nothing special, just skip it
1491 $nextoffset = $info['avdataend'];
1492 $this->fseek($nextoffset);
1504 // always read data in
1506 // should be: never read data in
1507 // but some programs write their version strings in a JUNK chunk (e.g. VirtualDub, AVIdemux, etc)
1508 if ($chunksize < 1048576) {
1509 if ($chunksize > 0) {
1510 $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize);
1511 if ($chunkname == 'JUNK') {
1512 if (preg_match('#^([\\x20-\\x7F]+)#', $RIFFchunk[$chunkname][$thisindex]['data'], $matches)) {
1513 // only keep text characters [chr(32)-chr(127)]
1514 $info['riff']['comments']['junk'][] = trim($matches[1]);
1516 // but if nothing there, ignore
1517 // remove the key in either case
1518 unset($RIFFchunk[$chunkname][$thisindex]['data']);
1522 $this->warning('Chunk "'.$chunkname.'" at offset '.$this->ftell().' is unexpectedly larger than 1MB (claims to be '.number_format($chunksize).' bytes), skipping data');
1523 $this->fseek($chunksize, SEEK_CUR);
1528 // $info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunksize));
1532 if (!empty($LISTchunkParent) && (($RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) {
1533 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
1534 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size'] = $RIFFchunk[$chunkname][$thisindex]['size'];
1535 unset($RIFFchunk[$chunkname][$thisindex]['offset']);
1536 unset($RIFFchunk[$chunkname][$thisindex]['size']);
1537 if (isset($RIFFchunk[$chunkname][$thisindex]) && empty($RIFFchunk[$chunkname][$thisindex])) {
1538 unset($RIFFchunk[$chunkname][$thisindex]);
1540 if (isset($RIFFchunk[$chunkname]) && empty($RIFFchunk[$chunkname])) {
1541 unset($RIFFchunk[$chunkname]);
1543 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['data'] = $this->fread($chunksize);
1544 } elseif ($chunksize < 2048) {
1545 // only read data in if smaller than 2kB
1546 $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize);
1548 $this->fseek($chunksize, SEEK_CUR);
1556 } catch (getid3_exception $e) {
1557 if ($e->getCode() == 10) {
1558 $this->warning('RIFF parser: '.$e->getMessage());
1567 public function ParseRIFFdata(&$RIFFdata) {
1568 $info = &$this->getid3->info;
1570 $tempfile = tempnam(GETID3_TEMP_DIR, 'getID3');
1571 $fp_temp = fopen($tempfile, 'wb');
1572 $RIFFdataLength = strlen($RIFFdata);
1573 $NewLengthString = getid3_lib::LittleEndian2String($RIFFdataLength, 4);
1574 for ($i = 0; $i < 4; $i++) {
1575 $RIFFdata[($i + 4)] = $NewLengthString[$i];
1577 fwrite($fp_temp, $RIFFdata);
1580 $getid3_temp = new getID3();
1581 $getid3_temp->openfile($tempfile);
1582 $getid3_temp->info['filesize'] = $RIFFdataLength;
1583 $getid3_temp->info['filenamepath'] = $info['filenamepath'];
1584 $getid3_temp->info['tags'] = $info['tags'];
1585 $getid3_temp->info['warning'] = $info['warning'];
1586 $getid3_temp->info['error'] = $info['error'];
1587 $getid3_temp->info['comments'] = $info['comments'];
1588 $getid3_temp->info['audio'] = (isset($info['audio']) ? $info['audio'] : array());
1589 $getid3_temp->info['video'] = (isset($info['video']) ? $info['video'] : array());
1590 $getid3_riff = new getid3_riff($getid3_temp);
1591 $getid3_riff->Analyze();
1593 $info['riff'] = $getid3_temp->info['riff'];
1594 $info['warning'] = $getid3_temp->info['warning'];
1595 $info['error'] = $getid3_temp->info['error'];
1596 $info['tags'] = $getid3_temp->info['tags'];
1597 $info['comments'] = $getid3_temp->info['comments'];
1598 unset($getid3_riff, $getid3_temp);
1604 public static function parseComments(&$RIFFinfoArray, &$CommentsTargetArray) {
1605 $RIFFinfoKeyLookup = array(
1606 'IARL'=>'archivallocation',
1608 'ICDS'=>'costumedesigner',
1609 'ICMS'=>'commissionedby',
1612 'ICOP'=>'copyright',
1613 'ICRD'=>'creationdate',
1614 'IDIM'=>'dimensions',
1615 'IDIT'=>'digitizationdate',
1616 'IDPI'=>'resolution',
1617 'IDST'=>'distributor',
1619 'IENG'=>'engineers',
1620 'IFRM'=>'accountofparts',
1623 'ILGT'=>'lightness',
1625 'IMED'=>'orignalmedium',
1628 'IPDS'=>'productiondesigner',
1636 'ISGN'=>'secondarygenre',
1637 'ISHP'=>'sharpness',
1638 'ISRC'=>'sourcesupplier',
1639 'ISRF'=>'digitizationsource',
1640 'ISTD'=>'productionstudio',
1642 'ITCH'=>'encoded_by',
1647 foreach ($RIFFinfoKeyLookup as $key => $value) {
1648 if (isset($RIFFinfoArray[$key])) {
1649 foreach ($RIFFinfoArray[$key] as $commentid => $commentdata) {
1650 if (trim($commentdata['data']) != '') {
1651 if (isset($CommentsTargetArray[$value])) {
1652 $CommentsTargetArray[$value][] = trim($commentdata['data']);
1654 $CommentsTargetArray[$value] = array(trim($commentdata['data']));
1663 public static function parseWAVEFORMATex($WaveFormatExData) {
1665 $WaveFormatEx['raw'] = array();
1666 $WaveFormatEx_raw = &$WaveFormatEx['raw'];
1668 $WaveFormatEx_raw['wFormatTag'] = substr($WaveFormatExData, 0, 2);
1669 $WaveFormatEx_raw['nChannels'] = substr($WaveFormatExData, 2, 2);
1670 $WaveFormatEx_raw['nSamplesPerSec'] = substr($WaveFormatExData, 4, 4);
1671 $WaveFormatEx_raw['nAvgBytesPerSec'] = substr($WaveFormatExData, 8, 4);
1672 $WaveFormatEx_raw['nBlockAlign'] = substr($WaveFormatExData, 12, 2);
1673 $WaveFormatEx_raw['wBitsPerSample'] = substr($WaveFormatExData, 14, 2);
1674 if (strlen($WaveFormatExData) > 16) {
1675 $WaveFormatEx_raw['cbSize'] = substr($WaveFormatExData, 16, 2);
1677 $WaveFormatEx_raw = array_map('getid3_lib::LittleEndian2Int', $WaveFormatEx_raw);
1679 $WaveFormatEx['codec'] = self::wFormatTagLookup($WaveFormatEx_raw['wFormatTag']);
1680 $WaveFormatEx['channels'] = $WaveFormatEx_raw['nChannels'];
1681 $WaveFormatEx['sample_rate'] = $WaveFormatEx_raw['nSamplesPerSec'];
1682 $WaveFormatEx['bitrate'] = $WaveFormatEx_raw['nAvgBytesPerSec'] * 8;
1683 $WaveFormatEx['bits_per_sample'] = $WaveFormatEx_raw['wBitsPerSample'];
1685 return $WaveFormatEx;
1688 public function parseWavPackHeader($WavPackChunkData) {
1693 // short bits; // added for version 2.00
1694 // short flags, shift; // added for version 3.00
1695 // long total_samples, crc, crc2;
1696 // char extension [4], extra_bc, extras [3];
1700 $info = &$this->getid3->info;
1701 $info['wavpack'] = array();
1702 $thisfile_wavpack = &$info['wavpack'];
1704 $thisfile_wavpack['version'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 0, 2));
1705 if ($thisfile_wavpack['version'] >= 2) {
1706 $thisfile_wavpack['bits'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 2, 2));
1708 if ($thisfile_wavpack['version'] >= 3) {
1709 $thisfile_wavpack['flags_raw'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 4, 2));
1710 $thisfile_wavpack['shift'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 6, 2));
1711 $thisfile_wavpack['total_samples'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 8, 4));
1712 $thisfile_wavpack['crc1'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 12, 4));
1713 $thisfile_wavpack['crc2'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 16, 4));
1714 $thisfile_wavpack['extension'] = substr($WavPackChunkData, 20, 4);
1715 $thisfile_wavpack['extra_bc'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 24, 1));
1716 for ($i = 0; $i <= 2; $i++) {
1717 $thisfile_wavpack['extras'][] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 25 + $i, 1));
1721 $thisfile_wavpack['flags'] = array();
1722 $thisfile_wavpack_flags = &$thisfile_wavpack['flags'];
1724 $thisfile_wavpack_flags['mono'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000001);
1725 $thisfile_wavpack_flags['fast_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000002);
1726 $thisfile_wavpack_flags['raw_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000004);
1727 $thisfile_wavpack_flags['calc_noise'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000008);
1728 $thisfile_wavpack_flags['high_quality'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000010);
1729 $thisfile_wavpack_flags['3_byte_samples'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000020);
1730 $thisfile_wavpack_flags['over_20_bits'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000040);
1731 $thisfile_wavpack_flags['use_wvc'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000080);
1732 $thisfile_wavpack_flags['noiseshaping'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000100);
1733 $thisfile_wavpack_flags['very_fast_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000200);
1734 $thisfile_wavpack_flags['new_high_quality'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000400);
1735 $thisfile_wavpack_flags['cancel_extreme'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000800);
1736 $thisfile_wavpack_flags['cross_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x001000);
1737 $thisfile_wavpack_flags['new_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x002000);
1738 $thisfile_wavpack_flags['joint_stereo'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x004000);
1739 $thisfile_wavpack_flags['extra_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x008000);
1740 $thisfile_wavpack_flags['override_noiseshape'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x010000);
1741 $thisfile_wavpack_flags['override_jointstereo'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x020000);
1742 $thisfile_wavpack_flags['copy_source_filetime'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x040000);
1743 $thisfile_wavpack_flags['create_exe'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x080000);
1749 public static function ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true) {
1751 $parsed['biSize'] = substr($BITMAPINFOHEADER, 0, 4); // number of bytes required by the BITMAPINFOHEADER structure
1752 $parsed['biWidth'] = substr($BITMAPINFOHEADER, 4, 4); // width of the bitmap in pixels
1753 $parsed['biHeight'] = substr($BITMAPINFOHEADER, 8, 4); // height of the bitmap in pixels. If biHeight is positive, the bitmap is a 'bottom-up' DIB and its origin is the lower left corner. If biHeight is negative, the bitmap is a 'top-down' DIB and its origin is the upper left corner
1754 $parsed['biPlanes'] = substr($BITMAPINFOHEADER, 12, 2); // number of color planes on the target device. In most cases this value must be set to 1
1755 $parsed['biBitCount'] = substr($BITMAPINFOHEADER, 14, 2); // Specifies the number of bits per pixels
1756 $parsed['biSizeImage'] = substr($BITMAPINFOHEADER, 20, 4); // size of the bitmap data section of the image (the actual pixel data, excluding BITMAPINFOHEADER and RGBQUAD structures)
1757 $parsed['biXPelsPerMeter'] = substr($BITMAPINFOHEADER, 24, 4); // horizontal resolution, in pixels per metre, of the target device
1758 $parsed['biYPelsPerMeter'] = substr($BITMAPINFOHEADER, 28, 4); // vertical resolution, in pixels per metre, of the target device
1759 $parsed['biClrUsed'] = substr($BITMAPINFOHEADER, 32, 4); // actual number of color indices in the color table used by the bitmap. If this value is zero, the bitmap uses the maximum number of colors corresponding to the value of the biBitCount member for the compression mode specified by biCompression
1760 $parsed['biClrImportant'] = substr($BITMAPINFOHEADER, 36, 4); // number of color indices that are considered important for displaying the bitmap. If this value is zero, all colors are important
1761 $parsed = array_map('getid3_lib::'.($littleEndian ? 'Little' : 'Big').'Endian2Int', $parsed);
1763 $parsed['fourcc'] = substr($BITMAPINFOHEADER, 16, 4); // compression identifier
1768 public static function ParseDIVXTAG($DIVXTAG, $raw=false) {
1769 // structure from "IDivX" source, Form1.frm, by "Greg Frazier of Daemonic Software Group", email: gfrazier@icestorm.net, web: http://dsg.cjb.net/
1770 // source available at http://files.divx-digest.com/download/c663efe7ef8ad2e90bf4af4d3ea6188a/on0SWN2r/edit/IDivX.zip
1771 // 'Byte Layout: '1111111111111111
1772 // '32 for Movie - 1 '1111111111111111
1773 // '28 for Author - 6 '6666666666666666
1774 // '4 for year - 2 '6666666666662222
1775 // '3 for genre - 3 '7777777777777777
1776 // '48 for Comments - 7 '7777777777777777
1777 // '1 for Rating - 4 '7777777777777777
1778 // '5 for Future Additions - 0 '333400000DIVXTAG
1781 static $DIVXTAGgenre = array(
1783 1 => 'Action/Adventure',
1795 13 => 'Infomercial',
1796 14 => 'Interactive',
1798 16 => 'Music Video',
1805 $DIVXTAGrating = array(
1814 $parsed['title'] = trim(substr($DIVXTAG, 0, 32));
1815 $parsed['artist'] = trim(substr($DIVXTAG, 32, 28));
1816 $parsed['year'] = intval(trim(substr($DIVXTAG, 60, 4)));
1817 $parsed['comment'] = trim(substr($DIVXTAG, 64, 48));
1818 $parsed['genre_id'] = intval(trim(substr($DIVXTAG, 112, 3)));
1819 $parsed['rating_id'] = ord(substr($DIVXTAG, 115, 1));
1820 //$parsed['padding'] = substr($DIVXTAG, 116, 5); // 5-byte null
1821 //$parsed['magic'] = substr($DIVXTAG, 121, 7); // "DIVXTAG"
1823 $parsed['genre'] = (isset($DIVXTAGgenre[$parsed['genre_id']]) ? $DIVXTAGgenre[$parsed['genre_id']] : $parsed['genre_id']);
1824 $parsed['rating'] = (isset($DIVXTAGrating[$parsed['rating_id']]) ? $DIVXTAGrating[$parsed['rating_id']] : $parsed['rating_id']);
1827 unset($parsed['genre_id'], $parsed['rating_id']);
1828 foreach ($parsed as $key => $value) {
1829 if (!$value === '') {
1830 unset($parsed['key']);
1835 foreach ($parsed as $tag => $value) {
1836 $parsed[$tag] = array($value);
1842 public static function waveSNDMtagLookup($tagshortname) {
1845 /** This is not a comment!
1852 ©fin featuredinstrument
1862 return getid3_lib::EmbeddedLookup($tagshortname, $begin, __LINE__, __FILE__, 'riff-sndm');
1865 public static function wFormatTagLookup($wFormatTag) {
1869 /** This is not a comment!
1871 0x0000 Microsoft Unknown Wave Format
1872 0x0001 Pulse Code Modulation (PCM)
1873 0x0002 Microsoft ADPCM
1875 0x0004 Compaq Computer VSELP
1877 0x0006 Microsoft A-Law
1878 0x0007 Microsoft mu-Law
1879 0x0008 Microsoft DTS
1881 0x0011 Intel DVI/IMA ADPCM
1882 0x0012 Videologic MediaSpace ADPCM
1883 0x0013 Sierra Semiconductor ADPCM
1884 0x0014 Antex Electronics G.723 ADPCM
1885 0x0015 DSP Solutions DigiSTD
1886 0x0016 DSP Solutions DigiFIX
1887 0x0017 Dialogic OKI ADPCM
1888 0x0018 MediaVision ADPCM
1889 0x0019 Hewlett-Packard CU
1891 0x0021 Speech Compression Sonarc
1892 0x0022 DSP Group TrueSpeech
1893 0x0023 Echo Speech EchoSC1
1894 0x0024 Audiofile AF36
1895 0x0025 Audio Processing Technology APTX
1896 0x0026 AudioFile AF10
1900 0x0031 Microsoft GSM 6.10
1902 0x0033 Antex Electronics ADPCME
1903 0x0034 Control Resources VQLPC
1904 0x0035 DSP Solutions DigiREAL
1905 0x0036 DSP Solutions DigiADPCM
1906 0x0037 Control Resources CR10
1907 0x0038 Natural MicroSystems VBXADPCM
1908 0x0039 Crystal Semiconductor IMA ADPCM
1910 0x003B Rockwell ADPCM
1911 0x003C Rockwell Digit LK
1913 0x0040 Antex Electronics G.721 ADPCM
1916 0x0050 MPEG Layer-2 or Layer-1
1924 0x0063 Canopus Atrac
1929 0x0069 Voxware Byte Aligned
1934 0x0074 Voxware MetaVoice
1935 0x0075 Voxware MetaSound
1936 0x0076 Voxware RT29HW
1950 0x0092 Dolby AC3 SPDIF
1951 0x0093 MediaSonic G.723
1952 0x0094 Aculab PLC Prosody 8kbps
1954 0x0098 Philips LPCBB
1957 0x0100 Rhetorex ADPCM
1960 0x0103 IBM AVC Adaptive Differential Pulse Code Modulation (ADPCM)
1963 0x0123 Digital G.723
1964 0x0125 Sanyo LD ADPCM
1965 0x0130 Sipro Lab Telecom ACELP NET
1966 0x0131 Sipro Lab Telecom ACELP 4800
1967 0x0132 Sipro Lab Telecom ACELP 8V3
1968 0x0133 Sipro Lab Telecom G.729
1969 0x0134 Sipro Lab Telecom G.729A
1970 0x0135 Sipro Lab Telecom Kelvin
1971 0x0140 Windows Media Video V8
1972 0x0150 Qualcomm PureVoice
1973 0x0151 Qualcomm HalfRate
1974 0x0155 Ring Zero Systems TUB GSM
1975 0x0160 Microsoft Audio 1
1976 0x0161 Windows Media Audio V7 / V8 / V9
1977 0x0162 Windows Media Audio Professional V9
1978 0x0163 Windows Media Audio Lossless V9
1979 0x0200 Creative Labs ADPCM
1980 0x0202 Creative Labs Fastspeech8
1981 0x0203 Creative Labs Fastspeech10
1982 0x0210 UHER Informatic GmbH ADPCM
1984 0x0230 I-link Worldwide VC
1985 0x0240 Aureal RAW Sport
1986 0x0250 Interactive Products HSX
1987 0x0251 Interactive Products RPELP
1988 0x0260 Consistent Software CS2
1990 0x0300 Fujitsu FM Towns Snd
1992 0x0401 Intel Music Coder
1993 0x0450 QDesign Music
1995 0x0681 AT&T Labs TPC
1996 0x08AE ClearJump LiteWave
1998 0x1001 Olivetti ADPCM
1999 0x1002 Olivetti CELP
2002 0x1100 Lernout & Hauspie Codec (0x1100)
2003 0x1101 Lernout & Hauspie CELP Codec (0x1101)
2004 0x1102 Lernout & Hauspie SBC Codec (0x1102)
2005 0x1103 Lernout & Hauspie SBC Codec (0x1103)
2006 0x1104 Lernout & Hauspie SBC Codec (0x1104)
2008 0x1401 AT&T ISIAudio
2009 0x1500 Soundspace Music Compression
2010 0x181C VoxWare RT24 Speech
2011 0x1FC4 NCT Soft ALF2CD (www.nctsoft.com)
2014 0x2002 WAVE_FORMAT_14_4
2015 0x2003 WAVE_FORMAT_28_8
2016 0x2004 WAVE_FORMAT_COOK
2017 0x2005 WAVE_FORMAT_DNET
2021 0x676F Ogg Vorbis 1+
2022 0x6770 Ogg Vorbis 2+
2023 0x6771 Ogg Vorbis 3+
2024 0x7A21 GSM-AMR (CBR, no SID)
2025 0x7A22 GSM-AMR (VBR, including SID)
2026 0xFFFE WAVE_FORMAT_EXTENSIBLE
2027 0xFFFF WAVE_FORMAT_DEVELOPMENT
2031 return getid3_lib::EmbeddedLookup('0x'.str_pad(strtoupper(dechex($wFormatTag)), 4, '0', STR_PAD_LEFT), $begin, __LINE__, __FILE__, 'riff-wFormatTag');
2034 public static function fourccLookup($fourcc) {
2038 /** This is not a comment!
2040 swot http://developer.apple.com/qa/snd/snd07.html
2041 ____ No Codec (____)
2042 _BIT BI_BITFIELDS (Raw RGB)
2043 _JPG JPEG compressed
2044 _PNG PNG compressed W3C/ISO/IEC (RFC-2083)
2045 _RAW Full Frames (Uncompressed)
2052 AASC Autodesk Animator
2053 ABYR Kensington ?ABYR?
2054 AEMI Array Microsystems VideoONE MPEG1-I Capture
2055 AFLC Autodesk Animator FLC
2056 AFLI Autodesk Animator FLI
2057 AMPG Array Microsystems VideoONE MPEG
2058 ANIM Intel RDX (ANIM)
2059 AP41 AngelPotion Definitive
2062 ASVX Asus Video 2.0 (audio)
2063 AUR2 AuraVision Aura 2 Codec - YUV 4:2:2
2064 AURA AuraVision Aura 1 Codec - YUV 4:1:1
2065 AVDJ Independent JPEG Group\'s codec (AVDJ)
2066 AVRN Independent JPEG Group\'s codec (AVRN)
2067 AYUV 4:4:4 YUV (AYUV)
2068 AZPR Quicktime Apple Video (AZPR)
2070 BLZ0 Blizzard DivX MPEG-4
2071 BTVC Conexant Composite Video
2072 BINK RAD Game Tools Bink Video
2073 BT20 Conexant Prosumer Video
2074 BTCV Conexant Composite Video Codec
2075 BW10 Data Translation Broadway MPEG Capture
2078 CFCC Digital Processing Systems DPS Perception
2079 CGDI Microsoft Office 97 Camcorder Video
2080 CHAM Winnov Caviara Champagne
2081 CJPG Creative WebCam JPEG
2082 CLJR Cirrus Logic YUV 4:1:1
2083 CMYK Common Data Format in Printing (Colorgraph)
2084 CPLA Weitek 4:2:0 YUV Planar
2085 CRAM Microsoft Video 1 (CRAM)
2088 CWLT Microsoft Color WLT DIB
2089 CYUV Creative Labs YUV
2093 DIB Device Independent Bitmap
2094 DIV1 FFmpeg OpenDivX
2095 DIV2 Microsoft MPEG-4 v1/v2
2096 DIV3 DivX ;-) MPEG-4 v3.x Low-Motion
2097 DIV4 DivX ;-) MPEG-4 v3.x Fast-Motion
2098 DIV5 DivX MPEG-4 v5.x
2099 DIV6 DivX ;-) (MS MPEG-4 v3.x)
2100 DIVX DivX MPEG-4 v4 (OpenDivX / Project Mayo)
2102 DMB1 Matrox Rainbow Runner hardware MJPEG
2105 DUCK Duck TrueMotion 1.0
2106 DPS0 DPS/Leitch Reality Motion JPEG
2107 DPSC DPS/Leitch PAR Motion JPEG
2108 DV25 Matrox DVCPRO codec
2109 DV50 Matrox DVCPRO50 codec
2110 DVC IEC 61834 and SMPTE 314M (DVC/DV Video)
2111 DVCP IEC 61834 and SMPTE 314M (DVC/DV Video)
2112 DVHD IEC Standard DV 1125 lines @ 30fps / 1250 lines @ 25fps
2113 DVMA Darim Vision DVMPEG (dummy for MPEG compressor) (www.darvision.com)
2114 DVSL IEC Standard DV compressed in SD (SDL)
2116 DVE2 InSoft DVE-2 Videoconferencing
2117 dvsd IEC 61834 and SMPTE 314M DVC/DV Video
2118 DVSD IEC 61834 and SMPTE 314M DVC/DV Video
2119 DVX1 Lucent DVX1000SP Video Decoder
2120 DVX2 Lucent DVX2000S Video Decoder
2121 DVX3 Lucent DVX3000S Video Decoder
2123 DXT1 Microsoft DirectX Compressed Texture (DXT1)
2124 DXT2 Microsoft DirectX Compressed Texture (DXT2)
2125 DXT3 Microsoft DirectX Compressed Texture (DXT3)
2126 DXT4 Microsoft DirectX Compressed Texture (DXT4)
2127 DXT5 Microsoft DirectX Compressed Texture (DXT5)
2128 DXTC Microsoft DirectX Compressed Texture (DXTC)
2129 DXTn Microsoft DirectX Compressed Texture (DXTn)
2130 EM2V Etymonix MPEG-2 I-frame (www.etymonix.com)
2134 ETV1 eTreppid Video ETV1
2135 ETV2 eTreppid Video ETV2
2136 ETVC eTreppid Video ETVC
2137 FLIC Autodesk FLI/FLC Animation
2139 FLV4 On2 TrueMotion VP6
2140 FRWT Darim Vision Forward Motion JPEG (www.darvision.com)
2141 FRWU Darim Vision Forward Uncompressed (www.darvision.com)
2142 FLJP D-Vision Field Encoded Motion JPEG
2144 FRWA SoftLab-Nsk Forward Motion JPEG w/ alpha channel
2145 FRWD SoftLab-Nsk Forward Motion JPEG
2146 FVF1 Iterated Systems Fractal Video Frame
2147 GLZW Motion LZW (gabest@freemail.hu)
2148 GPEG Motion JPEG (gabest@freemail.hu)
2149 GWLT Microsoft Greyscale WLT DIB
2150 H260 Intel ITU H.260 Videoconferencing
2151 H261 Intel ITU H.261 Videoconferencing
2152 H262 Intel ITU H.262 Videoconferencing
2153 H263 Intel ITU H.263 Videoconferencing
2154 H264 Intel ITU H.264 Videoconferencing
2155 H265 Intel ITU H.265 Videoconferencing
2156 H266 Intel ITU H.266 Videoconferencing
2157 H267 Intel ITU H.267 Videoconferencing
2158 H268 Intel ITU H.268 Videoconferencing
2159 H269 Intel ITU H.269 Videoconferencing
2160 HFYU Huffman Lossless Codec
2161 HMCR Rendition Motion Compensation Format (HMCR)
2162 HMRR Rendition Motion Compensation Format (HMRR)
2163 I263 FFmpeg I263 decoder
2164 IF09 Indeo YVU9 ("YVU9 with additional delta-frame info after the U plane")
2165 IUYV Interlaced version of UYVY (www.leadtools.com)
2166 IY41 Interlaced version of Y41P (www.leadtools.com)
2167 IYU1 12 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec IEEE standard
2168 IYU2 24 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec IEEE standard
2169 IYUV Planar YUV format (8-bpp Y plane, followed by 8-bpp 2×2 U and V planes)
2170 i263 Intel ITU H.263 Videoconferencing (i263)
2172 IAN Intel Indeo 4 (RDX)
2173 ICLB InSoft CellB Videoconferencing
2175 IJPG Intergraph JPEG
2176 ILVC Intel Layered Video
2178 IPDV I-O Data Device Giga AVI DV Codec
2179 IR21 Intel Indeo 2.1
2180 IRAW Intel YUV Uncompressed
2181 IV30 Intel Indeo 3.0
2182 IV31 Intel Indeo 3.1
2183 IV32 Ligos Indeo 3.2
2184 IV33 Ligos Indeo 3.3
2185 IV34 Ligos Indeo 3.4
2186 IV35 Ligos Indeo 3.5
2187 IV36 Ligos Indeo 3.6
2188 IV37 Ligos Indeo 3.7
2189 IV38 Ligos Indeo 3.8
2190 IV39 Ligos Indeo 3.9
2191 IV40 Ligos Indeo Interactive 4.0
2192 IV41 Ligos Indeo Interactive 4.1
2193 IV42 Ligos Indeo Interactive 4.2
2194 IV43 Ligos Indeo Interactive 4.3
2195 IV44 Ligos Indeo Interactive 4.4
2196 IV45 Ligos Indeo Interactive 4.5
2197 IV46 Ligos Indeo Interactive 4.6
2198 IV47 Ligos Indeo Interactive 4.7
2199 IV48 Ligos Indeo Interactive 4.8
2200 IV49 Ligos Indeo Interactive 4.9
2201 IV50 Ligos Indeo Interactive 5.0
2202 JBYR Kensington ?JBYR?
2203 JPEG Still Image JPEG DIB
2204 JPGL Pegasus Lossless Motion JPEG
2205 KMVC Team17 Software Karl Morton\'s Video Codec
2206 LSVM Vianet Lighting Strike Vmail (Streaming) (www.vianet.com)
2207 LEAD LEAD Video Codec
2208 Ljpg LEAD MJPEG Codec
2209 MDVD Alex MicroDVD Video (hacked MS MPEG-4) (www.tiasoft.de)
2210 MJPA Morgan Motion JPEG (MJPA) (www.morgan-multimedia.com)
2211 MJPB Morgan Motion JPEG (MJPB) (www.morgan-multimedia.com)
2212 MMES Matrox MPEG-2 I-frame
2213 MP2v Microsoft S-Mpeg 4 version 1 (MP2v)
2214 MP42 Microsoft S-Mpeg 4 version 2 (MP42)
2215 MP43 Microsoft S-Mpeg 4 version 3 (MP43)
2216 MP4S Microsoft S-Mpeg 4 version 3 (MP4S)
2218 MPG1 FFmpeg MPEG 1/2
2219 MPG2 FFmpeg MPEG 1/2
2220 MPG3 FFmpeg DivX ;-) (MS MPEG-4 v3)
2221 MPG4 Microsoft MPEG-4
2222 MPGI Sigma Designs MPEG
2223 MPNG PNG images decoder
2224 MSS1 Microsoft Windows Screen Video
2225 MSZH LCL (Lossless Codec Library) (www.geocities.co.jp/Playtown-Denei/2837/LRC.htm)
2226 M261 Microsoft H.261
2227 M263 Microsoft H.263
2228 M4S2 Microsoft Fully Compliant MPEG-4 v2 simple profile (M4S2)
2229 m4s2 Microsoft Fully Compliant MPEG-4 v2 simple profile (m4s2)
2230 MC12 ATI Motion Compensation Format (MC12)
2231 MCAM ATI Motion Compensation Format (MCAM)
2232 MJ2C Morgan Multimedia Motion JPEG2000
2233 mJPG IBM Motion JPEG w/ Huffman Tables
2234 MJPG Microsoft Motion JPEG DIB
2235 MP42 Microsoft MPEG-4 (low-motion)
2236 MP43 Microsoft MPEG-4 (fast-motion)
2237 MP4S Microsoft MPEG-4 (MP4S)
2238 mp4s Microsoft MPEG-4 (mp4s)
2239 MPEG Chromatic Research MPEG-1 Video I-Frame
2240 MPG4 Microsoft MPEG-4 Video High Speed Compressor
2241 MPGI Sigma Designs MPEG
2242 MRCA FAST Multimedia Martin Regen Codec
2243 MRLE Microsoft Run Length Encoding
2244 MSVC Microsoft Video 1
2254 MV12 Motion Pixels Codec (old)
2255 MWV1 Aware Motion Wavelets
2256 nAVI SMR Codec (hack of Microsoft MPEG-4) (IRC #shadowrealm)
2257 NT00 NewTek LightWave HDTV YUV w/ Alpha (www.newtek.com)
2259 NTN1 Nogatech Video Compression 1
2260 NVS0 nVidia GeForce Texture (NVS0)
2261 NVS1 nVidia GeForce Texture (NVS1)
2262 NVS2 nVidia GeForce Texture (NVS2)
2263 NVS3 nVidia GeForce Texture (NVS3)
2264 NVS4 nVidia GeForce Texture (NVS4)
2265 NVS5 nVidia GeForce Texture (NVS5)
2266 NVT0 nVidia GeForce Texture (NVT0)
2267 NVT1 nVidia GeForce Texture (NVT1)
2268 NVT2 nVidia GeForce Texture (NVT2)
2269 NVT3 nVidia GeForce Texture (NVT3)
2270 NVT4 nVidia GeForce Texture (NVT4)
2271 NVT5 nVidia GeForce Texture (NVT5)
2272 PIXL MiroXL, Pinnacle PCTV
2273 PDVC I-O Data Device Digital Video Capture DV codec
2274 PGVV Radius Video Vision
2275 PHMO IBM Photomotion
2276 PIM1 MPEG Realtime (Pinnacle Cards)
2277 PIM2 Pegasus Imaging ?PIM2?
2278 PIMJ Pegasus Imaging Lossless JPEG
2279 PVEZ Horizons Technology PowerEZ
2280 PVMM PacketVideo Corporation MPEG-4
2281 PVW2 Pegasus Imaging Wavelet Compression
2282 Q1.0 Q-Team\'s QPEG 1.0 (www.q-team.de)
2283 Q1.1 Q-Team\'s QPEG 1.1 (www.q-team.de)
2284 QPEG Q-Team QPEG 1.0
2285 qpeq Q-Team QPEG 1.1
2287 RGBA Raw RGB w/ Alpha
2288 RMP4 REALmagic MPEG-4 (unauthorized XVID copy) (www.sigmadesigns.com)
2289 ROQV Id RoQ File Video Decoder
2290 RPZA Quicktime Apple Video (RPZA)
2291 RUD0 Rududu video codec (http://rududu.ifrance.com/rududu/)
2292 RV10 RealVideo 1.0 (aka RealVideo 5.0)
2293 RV13 RealVideo 1.0 (RV13)
2297 RGBT Raw RGB w/ Transparency
2298 RLE Microsoft Run Length Encoder
2299 RLE4 Run Length Encoded (4bpp, 16-color)
2300 RLE8 Run Length Encoded (8bpp, 256-color)
2301 RT21 Intel Indeo RealTime Video 2.1
2304 RVX Intel RDX (RVX )
2305 SMC Apple Graphics (SMC )
2306 SP54 Logitech Sunplus Sp54 Codec for Mustek GSmart Mini 2
2308 SVQ3 Sorenson Video 3 (Apple Quicktime 5)
2309 s422 Tekram VideoCap C210 YUV 4:2:2
2310 SDCC Sun Communication Digital Camera Codec
2311 SFMC CrystalNet Surface Fitting Method
2314 smsv WorldConnect Wavelet Video
2316 SPLC Splash Studios ACM Audio Codec (www.splashstudios.net)
2317 SQZ2 Microsoft VXTreme Video Codec V2
2318 STVA ST Microelectronics CMOS Imager Data (Bayer)
2319 STVB ST Microelectronics CMOS Imager Data (Nudged Bayer)
2320 STVC ST Microelectronics CMOS Imager Data (Bunched)
2321 STVX ST Microelectronics CMOS Imager Data (Extended CODEC Data Format)
2322 STVY ST Microelectronics CMOS Imager Data (Extended CODEC Data Format with Correction Data)
2323 SV10 Sorenson Video R1
2325 T420 Toshiba YUV 4:2:0
2326 TM2A Duck TrueMotion Archiver 2.0 (www.duck.com)
2327 TVJP Pinnacle/Truevision Targa 2000 board (TVJP)
2328 TVMJ Pinnacle/Truevision Targa 2000 board (TVMJ)
2329 TY0N Tecomac Low-Bit Rate Codec (www.tecomac.com)
2330 TY2C Trident Decompression Driver
2331 TLMS TeraLogic Motion Intraframe Codec (TLMS)
2332 TLST TeraLogic Motion Intraframe Codec (TLST)
2333 TM20 Duck TrueMotion 2.0
2334 TM2X Duck TrueMotion 2X
2335 TMIC TeraLogic Motion Intraframe Codec (TMIC)
2336 TMOT Horizons Technology TrueMotion S
2337 tmot Horizons TrueMotion Video Compression
2338 TR20 Duck TrueMotion RealTime 2.0
2339 TSCC TechSmith Screen Capture Codec
2340 TV10 Tecomac Low-Bit Rate Codec
2342 U263 UB Video H.263/H.263+/H.263++ Decoder
2343 UMP4 UB Video MPEG 4 (www.ubvideo.com)
2344 UYNV Nvidia UYVY packed 4:2:2
2345 UYVP Evans & Sutherland YCbCr 4:2:2 extended precision
2346 UCOD eMajix.com ClearVideo
2348 UYVY UYVY packed 4:2:2
2350 VIFP VFAPI Reader Codec (www.yks.ne.jp/~hori/)
2351 VIV1 FFmpeg H263+ decoder
2353 VQC2 Vector-quantised codec 2 (research) http://eprints.ecs.soton.ac.uk/archive/00001310/01/VTC97-js.pdf)
2354 VTLP Alaris VideoGramPiX
2358 V422 Vitec Multimedia 24-bit YUV 4:2:2 Format
2359 V655 Vitec Multimedia 16-bit YUV 4:2:2 Format
2360 VCR1 ATI Video Codec 1
2361 VCR2 ATI Video Codec 2
2369 VDCT Vitec Multimedia Video Maker Pro DIB
2371 VDOW VDOnet VDOLive (H.263)
2372 VDTZ Darim Vison VideoTizer YUV
2373 VGPX Alaris VideoGramPiX
2374 VIDS Vitec Multimedia YUV 4:2:2 CCIR 601 for V422
2375 VIVO Vivo H.263 v2.00
2377 VIXL Miro/Pinnacle Video XL
2378 VLV1 VideoLogic/PURE Digital Videologic Capture
2381 VP6F On2 TrueMotion VP6
2382 VX1K Lucent VX1000S Video Codec
2383 VX2K Lucent VX2000S Video Codec
2384 VXSP Lucent VX1000SP Video Codec
2386 WHAM Microsoft Video 1 (WHAM)
2387 WINX Winnov Software Compression
2388 WJPG AverMedia Winbond JPEG
2389 WMV1 Windows Media Video V7
2390 WMV2 Windows Media Video V8
2391 WMV3 Windows Media Video V9
2392 WNV1 Winnov Hardware Compression
2393 XYZP Extended PAL format XYZ palette (www.riff.org)
2395 XLV0 NetXL Video Decoder
2396 XMPG Xing MPEG (I-Frame only)
2397 XVID XviD MPEG-4 (www.xvid.org)
2399 YU92 Intel YUV (YU92)
2400 YUNV Nvidia Uncompressed YUV 4:2:2
2401 YUVP Extended PAL format YUV palette (www.riff.org)
2402 Y211 YUV 2:1:1 Packed
2403 Y411 YUV 4:1:1 Packed
2404 Y41B Weitek YUV 4:1:1 Planar
2405 Y41P Brooktree PC1 YUV 4:1:1 Packed
2406 Y41T Brooktree PC1 YUV 4:1:1 with transparency
2407 Y42B Weitek YUV 4:2:2 Planar
2408 Y42T Brooktree UYUV 4:2:2 with transparency
2409 Y422 ADS Technologies Copy of UYVY used in Pyro WebCam firewire camera
2410 Y800 Simple, single Y plane for monochrome images
2412 YC12 Intel YUV 12 codec
2413 YUV8 Winnov Caviar YUV8
2415 YUY2 Uncompressed YUV 4:2:2
2418 YVU9 Intel YVU9 Planar (8-bpp Y plane, followed by 8-bpp 4x4 U and V planes)
2419 YVYU YVYU 4:2:2 Packed
2420 ZLIB Lossless Codec Library zlib compression (www.geocities.co.jp/Playtown-Denei/2837/LRC.htm)
2421 ZPEG Metheus Video Zipper
2425 return getid3_lib::EmbeddedLookup($fourcc, $begin, __LINE__, __FILE__, 'riff-fourcc');
2428 private function EitherEndian2Int($byteword, $signed=false) {
2429 if ($this->getid3->info['fileformat'] == 'riff') {
2430 return getid3_lib::LittleEndian2Int($byteword, $signed);
2432 return getid3_lib::BigEndian2Int($byteword, false, $signed);