cdf553386bc34c96dce88fe49d42fdd39b3808a0
3 /////////////////////////////////////////////////////////////////
4 /// getID3() by James Heinrich <info@getid3.org> //
5 // available at https://github.com/JamesHeinrich/getID3 //
6 // or https://www.getid3.org //
7 // or http://getid3.sourceforge.net //
8 // see readme.txt for more details //
9 /////////////////////////////////////////////////////////////////
11 // module.audio-video.riff.php //
12 // module for analyzing RIFF files //
13 // multiple formats supported by this module: //
14 // Wave, AVI, AIFF/AIFC, (MP3,AC3)/RIFF, Wavpack v3, 8SVX //
15 // dependencies: module.audio.mp3.php //
16 // module.audio.ac3.php //
17 // module.audio.dts.php //
19 /////////////////////////////////////////////////////////////////
22 * @todo Parse AC-3/DTS audio inside WAVE correctly
23 * @todo Rewrite RIFF parser totally
26 if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
29 getid3_lib
::IncludeDependency(GETID3_INCLUDEPATH
.'module.audio.mp3.php', __FILE__
, true);
30 getid3_lib
::IncludeDependency(GETID3_INCLUDEPATH
.'module.audio.ac3.php', __FILE__
, true);
31 getid3_lib
::IncludeDependency(GETID3_INCLUDEPATH
.'module.audio.dts.php', __FILE__
, true);
33 class getid3_riff
extends getid3_handler
35 protected $container = 'riff'; // default
40 * @throws getid3_exception
42 public function Analyze() {
43 $info = &$this->getid3
->info
;
45 // initialize these values to an empty array, otherwise they default to NULL
46 // and you can't append array values to a NULL value
47 $info['riff'] = array('raw'=>array());
50 $thisfile_riff = &$info['riff'];
51 $thisfile_riff_raw = &$thisfile_riff['raw'];
52 $thisfile_audio = &$info['audio'];
53 $thisfile_video = &$info['video'];
54 $thisfile_audio_dataformat = &$thisfile_audio['dataformat'];
55 $thisfile_riff_audio = &$thisfile_riff['audio'];
56 $thisfile_riff_video = &$thisfile_riff['video'];
57 $thisfile_riff_WAVE = array();
59 $Original['avdataoffset'] = $info['avdataoffset'];
60 $Original['avdataend'] = $info['avdataend'];
62 $this->fseek($info['avdataoffset']);
63 $RIFFheader = $this->fread(12);
64 $offset = $this->ftell();
65 $RIFFtype = substr($RIFFheader, 0, 4);
66 $RIFFsize = substr($RIFFheader, 4, 4);
67 $RIFFsubtype = substr($RIFFheader, 8, 4);
71 case 'FORM': // AIFF, AIFC
72 //$info['fileformat'] = 'aiff';
73 $this->container
= 'aiff';
74 $thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize);
75 $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, ($offset +
$thisfile_riff['header_size'] - 4));
78 case 'RIFF': // AVI, WAV, etc
79 case 'SDSS': // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com)
80 case 'RMP3': // RMP3 is identical to RIFF, just renamed. Used by [unknown program] when creating RIFF-MP3s
81 //$info['fileformat'] = 'riff';
82 $this->container
= 'riff';
83 $thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize);
84 if ($RIFFsubtype == 'RMP3') {
85 // RMP3 is identical to WAVE, just renamed. Used by [unknown program] when creating RIFF-MP3s
86 $RIFFsubtype = 'WAVE';
88 if ($RIFFsubtype != 'AMV ') {
89 // AMV files are RIFF-AVI files with parts of the spec deliberately broken, such as chunk size fields hardcoded to zero (because players known in hardware that these fields are always a certain size
90 // Handled separately in ParseRIFFAMV()
91 $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, ($offset +
$thisfile_riff['header_size'] - 4));
93 if (($info['avdataend'] - $info['filesize']) == 1) {
94 // LiteWave appears to incorrectly *not* pad actual output file
95 // to nearest WORD boundary so may appear to be short by one
96 // byte, in which case - skip warning
97 $info['avdataend'] = $info['filesize'];
100 $nextRIFFoffset = $Original['avdataoffset'] +
8 +
$thisfile_riff['header_size']; // 8 = "RIFF" + 32-bit offset
101 while ($nextRIFFoffset < min($info['filesize'], $info['avdataend'])) {
103 $this->fseek($nextRIFFoffset);
104 } catch (getid3_exception
$e) {
105 if ($e->getCode() == 10) {
106 //$this->warning('RIFF parser: '.$e->getMessage());
107 $this->error('AVI extends beyond '.round(PHP_INT_MAX
/ 1073741824).'GB and PHP filesystem functions cannot read that far, playtime may be wrong');
108 $this->warning('[avdataend] value may be incorrect, multiple AVIX chunks may be present');
114 $nextRIFFheader = $this->fread(12);
115 if ($nextRIFFoffset == ($info['avdataend'] - 1)) {
116 if (substr($nextRIFFheader, 0, 1) == "\x00") {
117 // RIFF padded to WORD boundary, we're actually already at the end
121 $nextRIFFheaderID = substr($nextRIFFheader, 0, 4);
122 $nextRIFFsize = $this->EitherEndian2Int(substr($nextRIFFheader, 4, 4));
123 $nextRIFFtype = substr($nextRIFFheader, 8, 4);
124 $chunkdata = array();
125 $chunkdata['offset'] = $nextRIFFoffset +
8;
126 $chunkdata['size'] = $nextRIFFsize;
127 $nextRIFFoffset = $chunkdata['offset'] +
$chunkdata['size'];
129 switch ($nextRIFFheaderID) {
131 $chunkdata['chunks'] = $this->ParseRIFF($chunkdata['offset'] +
4, $nextRIFFoffset);
132 if (!isset($thisfile_riff[$nextRIFFtype])) {
133 $thisfile_riff[$nextRIFFtype] = array();
135 $thisfile_riff[$nextRIFFtype][] = $chunkdata;
139 unset($info['riff']);
140 $info['amv'] = $this->ParseRIFFAMV($chunkdata['offset'] +
4, $nextRIFFoffset);
145 $thisfile_riff[$nextRIFFheaderID][] = $chunkdata;
149 $info['divxtag']['comments'] = self
::ParseDIVXTAG($this->fread($chunkdata['size']));
153 if ($info['filesize'] == ($chunkdata['offset'] - 8 +
128)) {
154 $DIVXTAG = $nextRIFFheader.$this->fread(128 - 12);
155 if (substr($DIVXTAG, -7) == 'DIVXTAG') {
156 // 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
157 $this->warning('Found wrongly-structured DIVXTAG at offset '.($this->ftell() - 128).', parsing anyway');
158 $info['divxtag']['comments'] = self
::ParseDIVXTAG($DIVXTAG);
162 $this->warning('Expecting "RIFF|JUNK|IDVX" at '.$nextRIFFoffset.', found "'.$nextRIFFheaderID.'" ('.getid3_lib
::PrintHexBytes($nextRIFFheaderID).') - skipping rest of file');
168 if ($RIFFsubtype == 'WAVE') {
169 $thisfile_riff_WAVE = &$thisfile_riff['WAVE'];
174 $this->error('Cannot parse RIFF (this is maybe not a RIFF / WAV / AVI file?) - expecting "FORM|RIFF|SDSS|RMP3" found "'.$RIFFsubtype.'" instead');
175 //unset($info['fileformat']);
180 switch ($RIFFsubtype) {
182 // http://en.wikipedia.org/wiki/Wav
184 $info['fileformat'] = 'wav';
186 if (empty($thisfile_audio['bitrate_mode'])) {
187 $thisfile_audio['bitrate_mode'] = 'cbr';
189 if (empty($thisfile_audio_dataformat)) {
190 $thisfile_audio_dataformat = 'wav';
193 if (isset($thisfile_riff_WAVE['data'][0]['offset'])) {
194 $info['avdataoffset'] = $thisfile_riff_WAVE['data'][0]['offset'] +
8;
195 $info['avdataend'] = $info['avdataoffset'] +
$thisfile_riff_WAVE['data'][0]['size'];
197 if (isset($thisfile_riff_WAVE['fmt '][0]['data'])) {
199 $thisfile_riff_audio[$streamindex] = self
::parseWAVEFORMATex($thisfile_riff_WAVE['fmt '][0]['data']);
200 $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
201 if (!isset($thisfile_riff_audio[$streamindex]['bitrate']) ||
($thisfile_riff_audio[$streamindex]['bitrate'] == 0)) {
202 $this->error('Corrupt RIFF file: bitrate_audio == zero');
205 $thisfile_riff_raw['fmt '] = $thisfile_riff_audio[$streamindex]['raw'];
206 unset($thisfile_riff_audio[$streamindex]['raw']);
207 $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
209 $thisfile_audio = (array) getid3_lib
::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
210 if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') {
211 $this->warning('Audio codec = '.$thisfile_audio['codec']);
213 $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
215 if (empty($info['playtime_seconds'])) { // may already be set (e.g. DTS-WAV)
216 $info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $thisfile_audio['bitrate']);
219 $thisfile_audio['lossless'] = false;
220 if (isset($thisfile_riff_WAVE['data'][0]['offset']) && isset($thisfile_riff_raw['fmt ']['wFormatTag'])) {
221 switch ($thisfile_riff_raw['fmt ']['wFormatTag']) {
224 $thisfile_audio['lossless'] = true;
228 $thisfile_audio_dataformat = 'ac3';
237 $thisfile_audio['streams'][$streamindex]['wformattag'] = $thisfile_audio['wformattag'];
238 $thisfile_audio['streams'][$streamindex]['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
239 $thisfile_audio['streams'][$streamindex]['lossless'] = $thisfile_audio['lossless'];
240 $thisfile_audio['streams'][$streamindex]['dataformat'] = $thisfile_audio_dataformat;
243 if (isset($thisfile_riff_WAVE['rgad'][0]['data'])) {
246 $rgadData = &$thisfile_riff_WAVE['rgad'][0]['data'];
247 $thisfile_riff_raw['rgad'] = array('track'=>array(), 'album'=>array());
248 $thisfile_riff_raw_rgad = &$thisfile_riff_raw['rgad'];
249 $thisfile_riff_raw_rgad_track = &$thisfile_riff_raw_rgad['track'];
250 $thisfile_riff_raw_rgad_album = &$thisfile_riff_raw_rgad['album'];
252 $thisfile_riff_raw_rgad['fPeakAmplitude'] = getid3_lib
::LittleEndian2Float(substr($rgadData, 0, 4));
253 $thisfile_riff_raw_rgad['nRadioRgAdjust'] = $this->EitherEndian2Int(substr($rgadData, 4, 2));
254 $thisfile_riff_raw_rgad['nAudiophileRgAdjust'] = $this->EitherEndian2Int(substr($rgadData, 6, 2));
256 $nRadioRgAdjustBitstring = str_pad(getid3_lib
::Dec2Bin($thisfile_riff_raw_rgad['nRadioRgAdjust']), 16, '0', STR_PAD_LEFT
);
257 $nAudiophileRgAdjustBitstring = str_pad(getid3_lib
::Dec2Bin($thisfile_riff_raw_rgad['nAudiophileRgAdjust']), 16, '0', STR_PAD_LEFT
);
258 $thisfile_riff_raw_rgad_track['name'] = getid3_lib
::Bin2Dec(substr($nRadioRgAdjustBitstring, 0, 3));
259 $thisfile_riff_raw_rgad_track['originator'] = getid3_lib
::Bin2Dec(substr($nRadioRgAdjustBitstring, 3, 3));
260 $thisfile_riff_raw_rgad_track['signbit'] = getid3_lib
::Bin2Dec(substr($nRadioRgAdjustBitstring, 6, 1));
261 $thisfile_riff_raw_rgad_track['adjustment'] = getid3_lib
::Bin2Dec(substr($nRadioRgAdjustBitstring, 7, 9));
262 $thisfile_riff_raw_rgad_album['name'] = getid3_lib
::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 0, 3));
263 $thisfile_riff_raw_rgad_album['originator'] = getid3_lib
::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 3, 3));
264 $thisfile_riff_raw_rgad_album['signbit'] = getid3_lib
::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 6, 1));
265 $thisfile_riff_raw_rgad_album['adjustment'] = getid3_lib
::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 7, 9));
267 $thisfile_riff['rgad']['peakamplitude'] = $thisfile_riff_raw_rgad['fPeakAmplitude'];
268 if (($thisfile_riff_raw_rgad_track['name'] != 0) && ($thisfile_riff_raw_rgad_track['originator'] != 0)) {
269 $thisfile_riff['rgad']['track']['name'] = getid3_lib
::RGADnameLookup($thisfile_riff_raw_rgad_track['name']);
270 $thisfile_riff['rgad']['track']['originator'] = getid3_lib
::RGADoriginatorLookup($thisfile_riff_raw_rgad_track['originator']);
271 $thisfile_riff['rgad']['track']['adjustment'] = getid3_lib
::RGADadjustmentLookup($thisfile_riff_raw_rgad_track['adjustment'], $thisfile_riff_raw_rgad_track['signbit']);
273 if (($thisfile_riff_raw_rgad_album['name'] != 0) && ($thisfile_riff_raw_rgad_album['originator'] != 0)) {
274 $thisfile_riff['rgad']['album']['name'] = getid3_lib
::RGADnameLookup($thisfile_riff_raw_rgad_album['name']);
275 $thisfile_riff['rgad']['album']['originator'] = getid3_lib
::RGADoriginatorLookup($thisfile_riff_raw_rgad_album['originator']);
276 $thisfile_riff['rgad']['album']['adjustment'] = getid3_lib
::RGADadjustmentLookup($thisfile_riff_raw_rgad_album['adjustment'], $thisfile_riff_raw_rgad_album['signbit']);
280 if (isset($thisfile_riff_WAVE['fact'][0]['data'])) {
281 $thisfile_riff_raw['fact']['NumberOfSamples'] = $this->EitherEndian2Int(substr($thisfile_riff_WAVE['fact'][0]['data'], 0, 4));
283 // This should be a good way of calculating exact playtime,
284 // but some sample files have had incorrect number of samples,
285 // so cannot use this method
287 // if (!empty($thisfile_riff_raw['fmt ']['nSamplesPerSec'])) {
288 // $info['playtime_seconds'] = (float) $thisfile_riff_raw['fact']['NumberOfSamples'] / $thisfile_riff_raw['fmt ']['nSamplesPerSec'];
291 if (!empty($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'])) {
292 $thisfile_audio['bitrate'] = getid3_lib
::CastAsInt($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'] * 8);
295 if (isset($thisfile_riff_WAVE['bext'][0]['data'])) {
297 $thisfile_riff_WAVE_bext_0 = &$thisfile_riff_WAVE['bext'][0];
299 $thisfile_riff_WAVE_bext_0['title'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 0, 256));
300 $thisfile_riff_WAVE_bext_0['author'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 256, 32));
301 $thisfile_riff_WAVE_bext_0['reference'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 288, 32));
302 $thisfile_riff_WAVE_bext_0['origin_date'] = substr($thisfile_riff_WAVE_bext_0['data'], 320, 10);
303 $thisfile_riff_WAVE_bext_0['origin_time'] = substr($thisfile_riff_WAVE_bext_0['data'], 330, 8);
304 $thisfile_riff_WAVE_bext_0['time_reference'] = getid3_lib
::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 338, 8));
305 $thisfile_riff_WAVE_bext_0['bwf_version'] = getid3_lib
::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 346, 1));
306 $thisfile_riff_WAVE_bext_0['reserved'] = substr($thisfile_riff_WAVE_bext_0['data'], 347, 254);
307 $thisfile_riff_WAVE_bext_0['coding_history'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_bext_0['data'], 601)));
308 if (preg_match('#^([0-9]{4}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_date'], $matches_bext_date)) {
309 if (preg_match('#^([0-9]{2}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_time'], $matches_bext_time)) {
310 list($dummy, $bext_timestamp['year'], $bext_timestamp['month'], $bext_timestamp['day']) = $matches_bext_date;
311 list($dummy, $bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second']) = $matches_bext_time;
312 $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']);
314 $this->warning('RIFF.WAVE.BEXT.origin_time is invalid');
317 $this->warning('RIFF.WAVE.BEXT.origin_date is invalid');
319 $thisfile_riff['comments']['author'][] = $thisfile_riff_WAVE_bext_0['author'];
320 $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_bext_0['title'];
323 if (isset($thisfile_riff_WAVE['MEXT'][0]['data'])) {
325 $thisfile_riff_WAVE_MEXT_0 = &$thisfile_riff_WAVE['MEXT'][0];
327 $thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] = getid3_lib
::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 0, 2));
328 $thisfile_riff_WAVE_MEXT_0['flags']['homogenous'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0001);
329 if ($thisfile_riff_WAVE_MEXT_0['flags']['homogenous']) {
330 $thisfile_riff_WAVE_MEXT_0['flags']['padding'] = ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0002) ?
false : true;
331 $thisfile_riff_WAVE_MEXT_0['flags']['22_or_44'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0004);
332 $thisfile_riff_WAVE_MEXT_0['flags']['free_format'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0008);
334 $thisfile_riff_WAVE_MEXT_0['nominal_frame_size'] = getid3_lib
::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 2, 2));
336 $thisfile_riff_WAVE_MEXT_0['anciliary_data_length'] = getid3_lib
::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 6, 2));
337 $thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] = getid3_lib
::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 8, 2));
338 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_left'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0001);
339 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_free'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0002);
340 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_right'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0004);
343 if (isset($thisfile_riff_WAVE['cart'][0]['data'])) {
345 $thisfile_riff_WAVE_cart_0 = &$thisfile_riff_WAVE['cart'][0];
347 $thisfile_riff_WAVE_cart_0['version'] = substr($thisfile_riff_WAVE_cart_0['data'], 0, 4);
348 $thisfile_riff_WAVE_cart_0['title'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 4, 64));
349 $thisfile_riff_WAVE_cart_0['artist'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 68, 64));
350 $thisfile_riff_WAVE_cart_0['cut_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 132, 64));
351 $thisfile_riff_WAVE_cart_0['client_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 196, 64));
352 $thisfile_riff_WAVE_cart_0['category'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 260, 64));
353 $thisfile_riff_WAVE_cart_0['classification'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 324, 64));
354 $thisfile_riff_WAVE_cart_0['out_cue'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 388, 64));
355 $thisfile_riff_WAVE_cart_0['start_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 452, 10));
356 $thisfile_riff_WAVE_cart_0['start_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 462, 8));
357 $thisfile_riff_WAVE_cart_0['end_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 470, 10));
358 $thisfile_riff_WAVE_cart_0['end_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 480, 8));
359 $thisfile_riff_WAVE_cart_0['producer_app_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 488, 64));
360 $thisfile_riff_WAVE_cart_0['producer_app_version'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 552, 64));
361 $thisfile_riff_WAVE_cart_0['user_defined_text'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 616, 64));
362 $thisfile_riff_WAVE_cart_0['zero_db_reference'] = getid3_lib
::LittleEndian2Int(substr($thisfile_riff_WAVE_cart_0['data'], 680, 4), true);
363 for ($i = 0; $i < 8; $i++
) {
364 $thisfile_riff_WAVE_cart_0['post_time'][$i]['usage_fourcc'] = substr($thisfile_riff_WAVE_cart_0['data'], 684 +
($i * 8), 4);
365 $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));
367 $thisfile_riff_WAVE_cart_0['url'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 748, 1024));
368 $thisfile_riff_WAVE_cart_0['tag_text'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_cart_0['data'], 1772)));
369 $thisfile_riff['comments']['tag_text'][] = substr($thisfile_riff_WAVE_cart_0['data'], 1772);
371 $thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist'];
372 $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_cart_0['title'];
375 if (isset($thisfile_riff_WAVE['SNDM'][0]['data'])) {
376 // SoundMiner metadata
379 $thisfile_riff_WAVE_SNDM_0 = &$thisfile_riff_WAVE['SNDM'][0];
380 $thisfile_riff_WAVE_SNDM_0_data = &$thisfile_riff_WAVE_SNDM_0['data'];
381 $SNDM_startoffset = 0;
382 $SNDM_endoffset = $thisfile_riff_WAVE_SNDM_0['size'];
384 while ($SNDM_startoffset < $SNDM_endoffset) {
385 $SNDM_thisTagOffset = 0;
386 $SNDM_thisTagSize = getid3_lib
::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset +
$SNDM_thisTagOffset, 4));
387 $SNDM_thisTagOffset +
= 4;
388 $SNDM_thisTagKey = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset +
$SNDM_thisTagOffset, 4);
389 $SNDM_thisTagOffset +
= 4;
390 $SNDM_thisTagDataSize = getid3_lib
::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset +
$SNDM_thisTagOffset, 2));
391 $SNDM_thisTagOffset +
= 2;
392 $SNDM_thisTagDataFlags = getid3_lib
::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset +
$SNDM_thisTagOffset, 2));
393 $SNDM_thisTagOffset +
= 2;
394 $SNDM_thisTagDataText = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset +
$SNDM_thisTagOffset, $SNDM_thisTagDataSize);
395 $SNDM_thisTagOffset +
= $SNDM_thisTagDataSize;
397 if ($SNDM_thisTagSize != (4 +
4 +
2 +
2 +
$SNDM_thisTagDataSize)) {
398 $this->warning('RIFF.WAVE.SNDM.data contains tag not expected length (expected: '.$SNDM_thisTagSize.', found: '.(4 +
4 +
2 +
2 +
$SNDM_thisTagDataSize).') at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] +
$SNDM_startoffset).')');
400 } elseif ($SNDM_thisTagSize <= 0) {
401 $this->warning('RIFF.WAVE.SNDM.data contains zero-size tag at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] +
$SNDM_startoffset).')');
404 $SNDM_startoffset +
= $SNDM_thisTagSize;
406 $thisfile_riff_WAVE_SNDM_0['parsed_raw'][$SNDM_thisTagKey] = $SNDM_thisTagDataText;
407 if ($parsedkey = self
::waveSNDMtagLookup($SNDM_thisTagKey)) {
408 $thisfile_riff_WAVE_SNDM_0['parsed'][$parsedkey] = $SNDM_thisTagDataText;
410 $this->warning('RIFF.WAVE.SNDM contains unknown tag "'.$SNDM_thisTagKey.'" at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] +
$SNDM_startoffset).')');
415 'tracktitle'=>'title',
416 'category' =>'genre',
419 foreach ($tagmapping as $fromkey => $tokey) {
420 if (isset($thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey])) {
421 $thisfile_riff['comments'][$tokey][] = $thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey];
426 if (isset($thisfile_riff_WAVE['iXML'][0]['data'])) {
427 // requires functions simplexml_load_string and get_object_vars
428 if ($parsedXML = getid3_lib
::XML2array($thisfile_riff_WAVE['iXML'][0]['data'])) {
429 $thisfile_riff_WAVE['iXML'][0]['parsed'] = $parsedXML;
430 if (isset($parsedXML['SPEED']['MASTER_SPEED'])) {
431 @list
($numerator, $denominator) = explode('/', $parsedXML['SPEED']['MASTER_SPEED']);
432 $thisfile_riff_WAVE['iXML'][0]['master_speed'] = $numerator / ($denominator ?
$denominator : 1000);
434 if (isset($parsedXML['SPEED']['TIMECODE_RATE'])) {
435 @list
($numerator, $denominator) = explode('/', $parsedXML['SPEED']['TIMECODE_RATE']);
436 $thisfile_riff_WAVE['iXML'][0]['timecode_rate'] = $numerator / ($denominator ?
$denominator : 1000);
438 if (isset($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO']) && !empty($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) && !empty($thisfile_riff_WAVE['iXML'][0]['timecode_rate'])) {
439 $samples_since_midnight = floatval(ltrim($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_HI'].$parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO'], '0'));
440 $timestamp_sample_rate = (is_array($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) ?
max($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) : $parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']); // XML could possibly contain more than one TIMESTAMP_SAMPLE_RATE tag, returning as array instead of integer [why? does it make sense? perhaps doesn't matter but getID3 needs to deal with it] - see https://github.com/JamesHeinrich/getID3/issues/105
441 $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] = $samples_since_midnight / $timestamp_sample_rate;
442 $h = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] / 3600);
443 $m = floor(($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600)) / 60);
444 $s = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60));
445 $f = ($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60) - $s) * $thisfile_riff_WAVE['iXML'][0]['timecode_rate'];
446 $thisfile_riff_WAVE['iXML'][0]['timecode_string'] = sprintf('%02d:%02d:%02d:%05.2f', $h, $m, $s, $f);
447 $thisfile_riff_WAVE['iXML'][0]['timecode_string_round'] = sprintf('%02d:%02d:%02d:%02d', $h, $m, $s, round($f));
448 unset($samples_since_midnight, $timestamp_sample_rate, $h, $m, $s, $f);
456 if (!isset($thisfile_audio['bitrate']) && isset($thisfile_riff_audio[$streamindex]['bitrate'])) {
457 $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
458 $info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $thisfile_audio['bitrate']);
461 if (!empty($info['wavpack'])) {
462 $thisfile_audio_dataformat = 'wavpack';
463 $thisfile_audio['bitrate_mode'] = 'vbr';
464 $thisfile_audio['encoder'] = 'WavPack v'.$info['wavpack']['version'];
466 // Reset to the way it was - RIFF parsing will have messed this up
467 $info['avdataend'] = $Original['avdataend'];
468 $thisfile_audio['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
470 $this->fseek($info['avdataoffset'] - 44);
471 $RIFFdata = $this->fread(44);
472 $OrignalRIFFheaderSize = getid3_lib
::LittleEndian2Int(substr($RIFFdata, 4, 4)) +
8;
473 $OrignalRIFFdataSize = getid3_lib
::LittleEndian2Int(substr($RIFFdata, 40, 4)) +
44;
475 if ($OrignalRIFFheaderSize > $OrignalRIFFdataSize) {
476 $info['avdataend'] -= ($OrignalRIFFheaderSize - $OrignalRIFFdataSize);
477 $this->fseek($info['avdataend']);
478 $RIFFdata .= $this->fread($OrignalRIFFheaderSize - $OrignalRIFFdataSize);
481 // move the data chunk after all other chunks (if any)
482 // so that the RIFF parser doesn't see EOF when trying
483 // to skip over the data chunk
484 $RIFFdata = substr($RIFFdata, 0, 36).substr($RIFFdata, 44).substr($RIFFdata, 36, 8);
485 $getid3_riff = new getid3_riff($this->getid3
);
486 $getid3_riff->ParseRIFFdata($RIFFdata);
490 if (isset($thisfile_riff_raw['fmt ']['wFormatTag'])) {
491 switch ($thisfile_riff_raw['fmt ']['wFormatTag']) {
493 if (!empty($info['ac3'])) {
494 // Dolby Digital WAV files masquerade as PCM-WAV, but they're not
495 $thisfile_audio['wformattag'] = 0x2000;
496 $thisfile_audio['codec'] = self
::wFormatTagLookup($thisfile_audio['wformattag']);
497 $thisfile_audio['lossless'] = false;
498 $thisfile_audio['bitrate'] = $info['ac3']['bitrate'];
499 $thisfile_audio['sample_rate'] = $info['ac3']['sample_rate'];
501 if (!empty($info['dts'])) {
502 // Dolby DTS files masquerade as PCM-WAV, but they're not
503 $thisfile_audio['wformattag'] = 0x2001;
504 $thisfile_audio['codec'] = self
::wFormatTagLookup($thisfile_audio['wformattag']);
505 $thisfile_audio['lossless'] = false;
506 $thisfile_audio['bitrate'] = $info['dts']['bitrate'];
507 $thisfile_audio['sample_rate'] = $info['dts']['sample_rate'];
510 case 0x08AE: // ClearJump LiteWave
511 $thisfile_audio['bitrate_mode'] = 'vbr';
512 $thisfile_audio_dataformat = 'litewave';
514 //typedef struct tagSLwFormat {
515 // WORD m_wCompFormat; // low byte defines compression method, high byte is compression flags
516 // DWORD m_dwScale; // scale factor for lossy compression
517 // DWORD m_dwBlockSize; // number of samples in encoded blocks
518 // WORD m_wQuality; // alias for the scale factor
519 // WORD m_wMarkDistance; // distance between marks in bytes
522 // //following paramters are ignored if CF_FILESRC is not set
523 // DWORD m_dwOrgSize; // original file size in bytes
524 // WORD m_bFactExists; // indicates if 'fact' chunk exists in the original file
525 // DWORD m_dwRiffChunkSize; // riff chunk size in the original file
527 // PCMWAVEFORMAT m_OrgWf; // original wave format
528 // }SLwFormat, *PSLwFormat;
531 $thisfile_riff['litewave']['raw'] = array();
532 $riff_litewave = &$thisfile_riff['litewave'];
533 $riff_litewave_raw = &$riff_litewave['raw'];
536 'compression_method' => 1,
537 'compression_flags' => 1,
539 'm_dwBlockSize' => 4,
541 'm_wMarkDistance' => 2,
544 'm_bFactExists' => 2,
545 'm_dwRiffChunkSize' => 4,
547 $litewave_offset = 18;
548 foreach ($flags as $flag => $length) {
549 $riff_litewave_raw[$flag] = getid3_lib
::LittleEndian2Int(substr($thisfile_riff_WAVE['fmt '][0]['data'], $litewave_offset, $length));
550 $litewave_offset +
= $length;
553 //$riff_litewave['quality_factor'] = intval(round((2000 - $riff_litewave_raw['m_dwScale']) / 20));
554 $riff_litewave['quality_factor'] = $riff_litewave_raw['m_wQuality'];
556 $riff_litewave['flags']['raw_source'] = ($riff_litewave_raw['compression_flags'] & 0x01) ?
false : true;
557 $riff_litewave['flags']['vbr_blocksize'] = ($riff_litewave_raw['compression_flags'] & 0x02) ?
false : true;
558 $riff_litewave['flags']['seekpoints'] = (bool) ($riff_litewave_raw['compression_flags'] & 0x04);
560 $thisfile_audio['lossless'] = (($riff_litewave_raw['m_wQuality'] == 100) ?
true : false);
561 $thisfile_audio['encoder_options'] = '-q'.$riff_litewave['quality_factor'];
568 if ($info['avdataend'] > $info['filesize']) {
569 switch (!empty($thisfile_audio_dataformat) ?
$thisfile_audio_dataformat : '') {
570 case 'wavpack': // WavPack
572 case 'ofr': // OptimFROG
573 case 'ofs': // OptimFROG DualStream
574 // lossless compressed audio formats that keep original RIFF headers - skip warning
578 if (($info['avdataend'] - $info['filesize']) == 1) {
579 // LiteWave appears to incorrectly *not* pad actual output file
580 // to nearest WORD boundary so may appear to be short by one
581 // byte, in which case - skip warning
583 // Short by more than one byte, throw warning
584 $this->warning('Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)');
585 $info['avdataend'] = $info['filesize'];
590 if ((($info['avdataend'] - $info['filesize']) == 1) && (($thisfile_riff[$RIFFsubtype]['data'][0]['size'] %
2) == 0) && ((($info['filesize'] - $info['avdataoffset']) %
2) == 1)) {
591 // output file appears to be incorrectly *not* padded to nearest WORD boundary
592 // Output less severe warning
593 $this->warning('File should probably be padded to nearest WORD boundary, but it is not (expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' therefore short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)');
594 $info['avdataend'] = $info['filesize'];
596 // Short by more than one byte, throw warning
597 $this->warning('Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)');
598 $info['avdataend'] = $info['filesize'];
603 if (!empty($info['mpeg']['audio']['LAME']['audio_bytes'])) {
604 if ((($info['avdataend'] - $info['avdataoffset']) - $info['mpeg']['audio']['LAME']['audio_bytes']) == 1) {
605 $info['avdataend']--;
606 $this->warning('Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored');
609 if (isset($thisfile_audio_dataformat) && ($thisfile_audio_dataformat == 'ac3')) {
610 unset($thisfile_audio['bits_per_sample']);
611 if (!empty($info['ac3']['bitrate']) && ($info['ac3']['bitrate'] != $thisfile_audio['bitrate'])) {
612 $thisfile_audio['bitrate'] = $info['ac3']['bitrate'];
617 // http://en.wikipedia.org/wiki/Audio_Video_Interleave
619 $info['fileformat'] = 'avi';
620 $info['mime_type'] = 'video/avi';
622 $thisfile_video['bitrate_mode'] = 'vbr'; // maybe not, but probably
623 $thisfile_video['dataformat'] = 'avi';
625 $thisfile_riff_video_current = array();
627 if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) {
628 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['movi']['offset'] +
8;
629 if (isset($thisfile_riff['AVIX'])) {
630 $info['avdataend'] = $thisfile_riff['AVIX'][(count($thisfile_riff['AVIX']) - 1)]['chunks']['movi']['offset'] +
$thisfile_riff['AVIX'][(count($thisfile_riff['AVIX']) - 1)]['chunks']['movi']['size'];
632 $info['avdataend'] = $thisfile_riff['AVI ']['movi']['offset'] +
$thisfile_riff['AVI ']['movi']['size'];
634 if ($info['avdataend'] > $info['filesize']) {
635 $this->warning('Probably truncated file - expecting '.($info['avdataend'] - $info['avdataoffset']).' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($info['avdataend'] - $info['filesize']).' bytes)');
636 $info['avdataend'] = $info['filesize'];
640 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['indx'])) {
641 //$bIndexType = array(
642 // 0x00 => 'AVI_INDEX_OF_INDEXES',
643 // 0x01 => 'AVI_INDEX_OF_CHUNKS',
644 // 0x80 => 'AVI_INDEX_IS_DATA',
646 //$bIndexSubtype = array(
648 // 0x01 => 'AVI_INDEX_2FIELD',
651 foreach ($thisfile_riff['AVI ']['hdrl']['strl']['indx'] as $streamnumber => $steamdataarray) {
652 $ahsisd = &$thisfile_riff['AVI ']['hdrl']['strl']['indx'][$streamnumber]['data'];
654 $thisfile_riff_raw['indx'][$streamnumber]['wLongsPerEntry'] = $this->EitherEndian2Int(substr($ahsisd, 0, 2));
655 $thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType'] = $this->EitherEndian2Int(substr($ahsisd, 2, 1));
656 $thisfile_riff_raw['indx'][$streamnumber]['bIndexType'] = $this->EitherEndian2Int(substr($ahsisd, 3, 1));
657 $thisfile_riff_raw['indx'][$streamnumber]['nEntriesInUse'] = $this->EitherEndian2Int(substr($ahsisd, 4, 4));
658 $thisfile_riff_raw['indx'][$streamnumber]['dwChunkId'] = substr($ahsisd, 8, 4);
659 $thisfile_riff_raw['indx'][$streamnumber]['dwReserved'] = $this->EitherEndian2Int(substr($ahsisd, 12, 4));
661 //$thisfile_riff_raw['indx'][$streamnumber]['bIndexType_name'] = $bIndexType[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']];
662 //$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType_name'] = $bIndexSubtype[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']][$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType']];
667 if (isset($thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'])) {
668 $avihData = $thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'];
671 $thisfile_riff_raw['avih'] = array();
672 $thisfile_riff_raw_avih = &$thisfile_riff_raw['avih'];
674 $thisfile_riff_raw_avih['dwMicroSecPerFrame'] = $this->EitherEndian2Int(substr($avihData, 0, 4)); // frame display rate (or 0L)
675 if ($thisfile_riff_raw_avih['dwMicroSecPerFrame'] == 0) {
676 $this->error('Corrupt RIFF file: avih.dwMicroSecPerFrame == zero');
681 'dwMaxBytesPerSec', // max. transfer rate
682 'dwPaddingGranularity', // pad to multiples of this size; normally 2K.
683 'dwFlags', // the ever-present flags
684 'dwTotalFrames', // # frames in file
685 'dwInitialFrames', //
687 'dwSuggestedBufferSize', //
696 foreach ($flags as $flag) {
697 $thisfile_riff_raw_avih[$flag] = $this->EitherEndian2Int(substr($avihData, $avih_offset, 4));
702 'hasindex' => 0x00000010,
703 'mustuseindex' => 0x00000020,
704 'interleaved' => 0x00000100,
705 'trustcktype' => 0x00000800,
706 'capturedfile' => 0x00010000,
707 'copyrighted' => 0x00020010,
709 foreach ($flags as $flag => $value) {
710 $thisfile_riff_raw_avih['flags'][$flag] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & $value);
714 $thisfile_riff_video[$streamindex] = array();
715 /** @var array $thisfile_riff_video_current */
716 $thisfile_riff_video_current = &$thisfile_riff_video[$streamindex];
718 if ($thisfile_riff_raw_avih['dwWidth'] > 0) {
719 $thisfile_riff_video_current['frame_width'] = $thisfile_riff_raw_avih['dwWidth'];
720 $thisfile_video['resolution_x'] = $thisfile_riff_video_current['frame_width'];
722 if ($thisfile_riff_raw_avih['dwHeight'] > 0) {
723 $thisfile_riff_video_current['frame_height'] = $thisfile_riff_raw_avih['dwHeight'];
724 $thisfile_video['resolution_y'] = $thisfile_riff_video_current['frame_height'];
726 if ($thisfile_riff_raw_avih['dwTotalFrames'] > 0) {
727 $thisfile_riff_video_current['total_frames'] = $thisfile_riff_raw_avih['dwTotalFrames'];
728 $thisfile_video['total_frames'] = $thisfile_riff_video_current['total_frames'];
731 $thisfile_riff_video_current['frame_rate'] = round(1000000 / $thisfile_riff_raw_avih['dwMicroSecPerFrame'], 3);
732 $thisfile_video['frame_rate'] = $thisfile_riff_video_current['frame_rate'];
734 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][0]['data'])) {
735 if (is_array($thisfile_riff['AVI ']['hdrl']['strl']['strh'])) {
736 for ($i = 0; $i < count($thisfile_riff['AVI ']['hdrl']['strl']['strh']); $i++
) {
737 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'])) {
738 $strhData = $thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'];
739 $strhfccType = substr($strhData, 0, 4);
741 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'])) {
742 $strfData = $thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'];
745 $thisfile_riff_raw_strf_strhfccType_streamindex = &$thisfile_riff_raw['strf'][$strhfccType][$streamindex];
747 switch ($strhfccType) {
749 $thisfile_audio['bitrate_mode'] = 'cbr';
750 $thisfile_audio_dataformat = 'wav';
751 if (isset($thisfile_riff_audio) && is_array($thisfile_riff_audio)) {
752 $streamindex = count($thisfile_riff_audio);
755 $thisfile_riff_audio[$streamindex] = self
::parseWAVEFORMATex($strfData);
756 $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
759 $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
760 $thisfile_audio_streams_currentstream = &$thisfile_audio['streams'][$streamindex];
762 if ($thisfile_audio_streams_currentstream['bits_per_sample'] == 0) {
763 unset($thisfile_audio_streams_currentstream['bits_per_sample']);
765 $thisfile_audio_streams_currentstream['wformattag'] = $thisfile_audio_streams_currentstream['raw']['wFormatTag'];
766 unset($thisfile_audio_streams_currentstream['raw']);
769 $thisfile_riff_raw['strf'][$strhfccType][$streamindex] = $thisfile_riff_audio[$streamindex]['raw'];
771 unset($thisfile_riff_audio[$streamindex]['raw']);
772 $thisfile_audio = getid3_lib
::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
774 $thisfile_audio['lossless'] = false;
775 switch ($thisfile_riff_raw_strf_strhfccType_streamindex['wFormatTag']) {
777 $thisfile_audio_dataformat = 'wav';
778 $thisfile_audio['lossless'] = true;
781 case 0x0050: // MPEG Layer 2 or Layer 1
782 $thisfile_audio_dataformat = 'mp2'; // Assume Layer-2
785 case 0x0055: // MPEG Layer 3
786 $thisfile_audio_dataformat = 'mp3';
790 $thisfile_audio_dataformat = 'aac';
793 case 0x0161: // Windows Media v7 / v8 / v9
794 case 0x0162: // Windows Media Professional v9
795 case 0x0163: // Windows Media Lossess v9
796 $thisfile_audio_dataformat = 'wma';
800 $thisfile_audio_dataformat = 'ac3';
804 $thisfile_audio_dataformat = 'dts';
808 $thisfile_audio_dataformat = 'wav';
811 $thisfile_audio_streams_currentstream['dataformat'] = $thisfile_audio_dataformat;
812 $thisfile_audio_streams_currentstream['lossless'] = $thisfile_audio['lossless'];
813 $thisfile_audio_streams_currentstream['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
820 $thisfile_riff_raw['strh'][$i] = array();
821 $thisfile_riff_raw_strh_current = &$thisfile_riff_raw['strh'][$i];
823 $thisfile_riff_raw_strh_current['fccType'] = substr($strhData, 0, 4); // same as $strhfccType;
824 $thisfile_riff_raw_strh_current['fccHandler'] = substr($strhData, 4, 4);
825 $thisfile_riff_raw_strh_current['dwFlags'] = $this->EitherEndian2Int(substr($strhData, 8, 4)); // Contains AVITF_* flags
826 $thisfile_riff_raw_strh_current['wPriority'] = $this->EitherEndian2Int(substr($strhData, 12, 2));
827 $thisfile_riff_raw_strh_current['wLanguage'] = $this->EitherEndian2Int(substr($strhData, 14, 2));
828 $thisfile_riff_raw_strh_current['dwInitialFrames'] = $this->EitherEndian2Int(substr($strhData, 16, 4));
829 $thisfile_riff_raw_strh_current['dwScale'] = $this->EitherEndian2Int(substr($strhData, 20, 4));
830 $thisfile_riff_raw_strh_current['dwRate'] = $this->EitherEndian2Int(substr($strhData, 24, 4));
831 $thisfile_riff_raw_strh_current['dwStart'] = $this->EitherEndian2Int(substr($strhData, 28, 4));
832 $thisfile_riff_raw_strh_current['dwLength'] = $this->EitherEndian2Int(substr($strhData, 32, 4));
833 $thisfile_riff_raw_strh_current['dwSuggestedBufferSize'] = $this->EitherEndian2Int(substr($strhData, 36, 4));
834 $thisfile_riff_raw_strh_current['dwQuality'] = $this->EitherEndian2Int(substr($strhData, 40, 4));
835 $thisfile_riff_raw_strh_current['dwSampleSize'] = $this->EitherEndian2Int(substr($strhData, 44, 4));
836 $thisfile_riff_raw_strh_current['rcFrame'] = $this->EitherEndian2Int(substr($strhData, 48, 4));
838 $thisfile_riff_video_current['codec'] = self
::fourccLookup($thisfile_riff_raw_strh_current['fccHandler']);
839 $thisfile_video['fourcc'] = $thisfile_riff_raw_strh_current['fccHandler'];
840 if (!$thisfile_riff_video_current['codec'] && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) && self
::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
841 $thisfile_riff_video_current['codec'] = self
::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']);
842 $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
844 $thisfile_video['codec'] = $thisfile_riff_video_current['codec'];
845 $thisfile_video['pixel_aspect_ratio'] = (float) 1;
846 switch ($thisfile_riff_raw_strh_current['fccHandler']) {
847 case 'HFYU': // Huffman Lossless Codec
848 case 'IRAW': // Intel YUV Uncompressed
849 case 'YUY2': // Uncompressed YUV 4:2:2
850 $thisfile_video['lossless'] = true;
854 $thisfile_video['lossless'] = false;
858 switch ($strhfccType) {
860 $thisfile_riff_raw_strf_strhfccType_streamindex = self
::ParseBITMAPINFOHEADER(substr($strfData, 0, 40), ($this->container
== 'riff'));
861 $thisfile_video['bits_per_sample'] = $thisfile_riff_raw_strf_strhfccType_streamindex['biBitCount'];
863 if ($thisfile_riff_video_current['codec'] == 'DV') {
864 $thisfile_riff_video_current['dv_type'] = 2;
869 $thisfile_riff_video_current['dv_type'] = 1;
875 $this->warning('Unhandled fccType for stream ('.$i.'): "'.$strhfccType.'"');
882 if (isset($thisfile_riff_raw_strf_strhfccType_streamindex) && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
884 $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
885 if (self
::fourccLookup($thisfile_video['fourcc'])) {
886 $thisfile_riff_video_current['codec'] = self
::fourccLookup($thisfile_video['fourcc']);
887 $thisfile_video['codec'] = $thisfile_riff_video_current['codec'];
890 switch ($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) {
891 case 'HFYU': // Huffman Lossless Codec
892 case 'IRAW': // Intel YUV Uncompressed
893 case 'YUY2': // Uncompressed YUV 4:2:2
894 $thisfile_video['lossless'] = true;
895 //$thisfile_video['bits_per_sample'] = 24;
899 $thisfile_video['lossless'] = false;
900 //$thisfile_video['bits_per_sample'] = 24;
912 $info['fileformat'] = 'amv';
913 $info['mime_type'] = 'video/amv';
915 $thisfile_video['bitrate_mode'] = 'vbr'; // it's MJPEG, presumably contant-quality encoding, thereby VBR
916 $thisfile_video['dataformat'] = 'mjpeg';
917 $thisfile_video['codec'] = 'mjpeg';
918 $thisfile_video['lossless'] = false;
919 $thisfile_video['bits_per_sample'] = 24;
921 $thisfile_audio['dataformat'] = 'adpcm';
922 $thisfile_audio['lossless'] = false;
926 // http://en.wikipedia.org/wiki/CD-DA
928 $info['fileformat'] = 'cda';
929 unset($info['mime_type']);
931 $thisfile_audio_dataformat = 'cda';
933 $info['avdataoffset'] = 44;
935 if (isset($thisfile_riff['CDDA']['fmt '][0]['data'])) {
937 $thisfile_riff_CDDA_fmt_0 = &$thisfile_riff['CDDA']['fmt '][0];
939 $thisfile_riff_CDDA_fmt_0['unknown1'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 0, 2));
940 $thisfile_riff_CDDA_fmt_0['track_num'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 2, 2));
941 $thisfile_riff_CDDA_fmt_0['disc_id'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 4, 4));
942 $thisfile_riff_CDDA_fmt_0['start_offset_frame'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 8, 4));
943 $thisfile_riff_CDDA_fmt_0['playtime_frames'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 12, 4));
944 $thisfile_riff_CDDA_fmt_0['unknown6'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 16, 4));
945 $thisfile_riff_CDDA_fmt_0['unknown7'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 20, 4));
947 $thisfile_riff_CDDA_fmt_0['start_offset_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['start_offset_frame'] / 75;
948 $thisfile_riff_CDDA_fmt_0['playtime_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['playtime_frames'] / 75;
949 $info['comments']['track_number'] = $thisfile_riff_CDDA_fmt_0['track_num'];
950 $info['playtime_seconds'] = $thisfile_riff_CDDA_fmt_0['playtime_seconds'];
952 // hardcoded data for CD-audio
953 $thisfile_audio['lossless'] = true;
954 $thisfile_audio['sample_rate'] = 44100;
955 $thisfile_audio['channels'] = 2;
956 $thisfile_audio['bits_per_sample'] = 16;
957 $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $thisfile_audio['channels'] * $thisfile_audio['bits_per_sample'];
958 $thisfile_audio['bitrate_mode'] = 'cbr';
962 // http://en.wikipedia.org/wiki/AIFF
965 $info['fileformat'] = 'aiff';
966 $info['mime_type'] = 'audio/x-aiff';
968 $thisfile_audio['bitrate_mode'] = 'cbr';
969 $thisfile_audio_dataformat = 'aiff';
970 $thisfile_audio['lossless'] = true;
972 if (isset($thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'])) {
973 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'] +
8;
974 $info['avdataend'] = $info['avdataoffset'] +
$thisfile_riff[$RIFFsubtype]['SSND'][0]['size'];
975 if ($info['avdataend'] > $info['filesize']) {
976 if (($info['avdataend'] == ($info['filesize'] +
1)) && (($info['filesize'] %
2) == 1)) {
977 // structures rounded to 2-byte boundary, but dumb encoders
978 // forget to pad end of file to make this actually work
980 $this->warning('Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['SSND'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found');
982 $info['avdataend'] = $info['filesize'];
986 if (isset($thisfile_riff[$RIFFsubtype]['COMM'][0]['data'])) {
989 $thisfile_riff_RIFFsubtype_COMM_0_data = &$thisfile_riff[$RIFFsubtype]['COMM'][0]['data'];
991 $thisfile_riff_audio['channels'] = getid3_lib
::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 0, 2), true);
992 $thisfile_riff_audio['total_samples'] = getid3_lib
::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 2, 4), false);
993 $thisfile_riff_audio['bits_per_sample'] = getid3_lib
::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 6, 2), true);
994 $thisfile_riff_audio['sample_rate'] = (int) getid3_lib
::BigEndian2Float(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 8, 10));
996 if ($thisfile_riff[$RIFFsubtype]['COMM'][0]['size'] > 18) {
997 $thisfile_riff_audio['codec_fourcc'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 18, 4);
998 $CodecNameSize = getid3_lib
::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 22, 1), false);
999 $thisfile_riff_audio['codec_name'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 23, $CodecNameSize);
1000 switch ($thisfile_riff_audio['codec_name']) {
1002 $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)';
1003 $thisfile_audio['lossless'] = true;
1007 switch ($thisfile_riff_audio['codec_fourcc']) {
1008 // http://developer.apple.com/qa/snd/snd07.html
1010 $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Little-Endian PCM';
1011 $thisfile_audio['lossless'] = true;
1015 $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Big-Endian PCM';
1016 $thisfile_audio['lossless'] = true;
1025 $thisfile_audio['codec'] = $thisfile_riff_audio['codec_name'];
1026 $thisfile_audio['lossless'] = false;
1031 $thisfile_audio['channels'] = $thisfile_riff_audio['channels'];
1032 if ($thisfile_riff_audio['bits_per_sample'] > 0) {
1033 $thisfile_audio['bits_per_sample'] = $thisfile_riff_audio['bits_per_sample'];
1035 $thisfile_audio['sample_rate'] = $thisfile_riff_audio['sample_rate'];
1036 if ($thisfile_audio['sample_rate'] == 0) {
1037 $this->error('Corrupted AIFF file: sample_rate == zero');
1040 $info['playtime_seconds'] = $thisfile_riff_audio['total_samples'] / $thisfile_audio['sample_rate'];
1043 if (isset($thisfile_riff[$RIFFsubtype]['COMT'])) {
1045 $CommentCount = getid3_lib
::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false);
1047 for ($i = 0; $i < $CommentCount; $i++
) {
1048 $info['comments_raw'][$i]['timestamp'] = getid3_lib
::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 4), false);
1050 $info['comments_raw'][$i]['marker_id'] = getid3_lib
::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), true);
1052 $CommentLength = getid3_lib
::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false);
1054 $info['comments_raw'][$i]['comment'] = substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, $CommentLength);
1055 $offset +
= $CommentLength;
1057 $info['comments_raw'][$i]['timestamp_unix'] = getid3_lib
::DateMac2Unix($info['comments_raw'][$i]['timestamp']);
1058 $thisfile_riff['comments']['comment'][] = $info['comments_raw'][$i]['comment'];
1062 $CommentsChunkNames = array('NAME'=>'title', 'author'=>'artist', '(c) '=>'copyright', 'ANNO'=>'comment');
1063 foreach ($CommentsChunkNames as $key => $value) {
1064 if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) {
1065 $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data'];
1069 if (isset($thisfile_riff[$RIFFsubtype]['ID3 '])) {
1070 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
1071 $getid3_temp = new getID3();
1072 $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
1073 $getid3_id3v2 = new getid3_id3v2($getid3_temp);
1074 $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['ID3 '][0]['offset'] + 8;
1075 if ($thisfile_riff[$RIFFsubtype]['ID3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
1076 $info['id3v2'] = $getid3_temp->info['id3v2'];
1078 unset($getid3_temp, $getid3_id3v2);
1083 // http://en.wikipedia.org/wiki/8SVX
1085 $info['fileformat'] = '8svx';
1086 $info['mime_type'] = 'audio/8svx';
1088 $thisfile_audio['bitrate_mode'] = 'cbr';
1089 $thisfile_audio_dataformat = '8svx';
1090 $thisfile_audio['bits_per_sample'] = 8;
1091 $thisfile_audio['channels'] = 1; // overridden below, if need be
1092 $ActualBitsPerSample = 0;
1094 if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) {
1095 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] +
8;
1096 $info['avdataend'] = $info['avdataoffset'] +
$thisfile_riff[$RIFFsubtype]['BODY'][0]['size'];
1097 if ($info['avdataend'] > $info['filesize']) {
1098 $this->warning('Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['BODY'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found');
1102 if (isset($thisfile_riff[$RIFFsubtype]['VHDR'][0]['offset'])) {
1104 $thisfile_riff_RIFFsubtype_VHDR_0 = &$thisfile_riff[$RIFFsubtype]['VHDR'][0];
1106 $thisfile_riff_RIFFsubtype_VHDR_0['oneShotHiSamples'] = getid3_lib
::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 0, 4));
1107 $thisfile_riff_RIFFsubtype_VHDR_0['repeatHiSamples'] = getid3_lib
::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 4, 4));
1108 $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerHiCycle'] = getid3_lib
::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 8, 4));
1109 $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec'] = getid3_lib
::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 12, 2));
1110 $thisfile_riff_RIFFsubtype_VHDR_0['ctOctave'] = getid3_lib
::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 14, 1));
1111 $thisfile_riff_RIFFsubtype_VHDR_0['sCompression'] = getid3_lib
::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 15, 1));
1112 $thisfile_riff_RIFFsubtype_VHDR_0['Volume'] = getid3_lib
::FixedPoint16_16(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 16, 4));
1114 $thisfile_audio['sample_rate'] = $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec'];
1116 switch ($thisfile_riff_RIFFsubtype_VHDR_0['sCompression']) {
1118 $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)';
1119 $thisfile_audio['lossless'] = true;
1120 $ActualBitsPerSample = 8;
1124 $thisfile_audio['codec'] = 'Fibonacci-delta encoding';
1125 $thisfile_audio['lossless'] = false;
1126 $ActualBitsPerSample = 4;
1130 $this->warning('Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.$thisfile_riff_RIFFsubtype_VHDR_0['sCompression'].'"');
1135 if (isset($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'])) {
1136 $ChannelsIndex = getid3_lib
::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'], 0, 4));
1137 switch ($ChannelsIndex) {
1139 $thisfile_audio['channels'] = 2;
1142 case 2: // Left channel only
1143 case 4: // Right channel only
1144 $thisfile_audio['channels'] = 1;
1148 $this->warning('Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "'.$ChannelsIndex.'"');
1154 $CommentsChunkNames = array('NAME'=>'title', 'author'=>'artist', '(c) '=>'copyright', 'ANNO'=>'comment');
1155 foreach ($CommentsChunkNames as $key => $value) {
1156 if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) {
1157 $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data'];
1161 $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $ActualBitsPerSample * $thisfile_audio['channels'];
1162 if (!empty($thisfile_audio['bitrate'])) {
1163 $info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset']) / ($thisfile_audio['bitrate'] / 8);
1168 $info['fileformat'] = 'vcd'; // Asume Video CD
1169 $info['mime_type'] = 'video/mpeg';
1171 if (!empty($thisfile_riff['CDXA']['data'][0]['size'])) {
1172 getid3_lib
::IncludeDependency(GETID3_INCLUDEPATH
.'module.audio-video.mpeg.php', __FILE__
, true);
1174 $getid3_temp = new getID3();
1175 $getid3_temp->openfile($this->getid3
->filename
, null, $this->getid3
->fp
);
1176 $getid3_mpeg = new getid3_mpeg($getid3_temp);
1177 $getid3_mpeg->Analyze();
1178 if (empty($getid3_temp->info
['error'])) {
1179 $info['audio'] = $getid3_temp->info
['audio'];
1180 $info['video'] = $getid3_temp->info
['video'];
1181 $info['mpeg'] = $getid3_temp->info
['mpeg'];
1182 $info['warning'] = $getid3_temp->info
['warning'];
1184 unset($getid3_temp, $getid3_mpeg);
1189 // https://developers.google.com/speed/webp/docs/riff_container
1190 // https://tools.ietf.org/html/rfc6386
1191 // https://chromium.googlesource.com/webm/libwebp/+/master/doc/webp-lossless-bitstream-spec.txt
1192 $info['fileformat'] = 'webp';
1193 $info['mime_type'] = 'image/webp';
1195 if (!empty($thisfile_riff['WEBP']['VP8 '][0]['size'])) {
1196 $old_offset = $this->ftell();
1197 $this->fseek($thisfile_riff['WEBP']['VP8 '][0]['offset'] +
8); // 4 bytes "VP8 " + 4 bytes chunk size
1198 $WEBP_VP8_header = $this->fread(10);
1199 $this->fseek($old_offset);
1200 if (substr($WEBP_VP8_header, 3, 3) == "\x9D\x01\x2A") {
1201 $thisfile_riff['WEBP']['VP8 '][0]['keyframe'] = !(getid3_lib
::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x800000);
1202 $thisfile_riff['WEBP']['VP8 '][0]['version'] = (getid3_lib
::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x700000) >> 20;
1203 $thisfile_riff['WEBP']['VP8 '][0]['show_frame'] = (getid3_lib
::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x080000);
1204 $thisfile_riff['WEBP']['VP8 '][0]['data_bytes'] = (getid3_lib
::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x07FFFF) >> 0;
1206 $thisfile_riff['WEBP']['VP8 '][0]['scale_x'] = (getid3_lib
::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0xC000) >> 14;
1207 $thisfile_riff['WEBP']['VP8 '][0]['width'] = (getid3_lib
::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0x3FFF);
1208 $thisfile_riff['WEBP']['VP8 '][0]['scale_y'] = (getid3_lib
::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0xC000) >> 14;
1209 $thisfile_riff['WEBP']['VP8 '][0]['height'] = (getid3_lib
::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0x3FFF);
1211 $info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8 '][0]['width'];
1212 $info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8 '][0]['height'];
1214 $this->error('Expecting 9D 01 2A at offset '.($thisfile_riff['WEBP']['VP8 '][0]['offset'] +
8 +
3).', found "'.getid3_lib
::PrintHexBytes(substr($WEBP_VP8_header, 3, 3)).'"');
1218 if (!empty($thisfile_riff['WEBP']['VP8L'][0]['size'])) {
1219 $old_offset = $this->ftell();
1220 $this->fseek($thisfile_riff['WEBP']['VP8L'][0]['offset'] +
8); // 4 bytes "VP8L" + 4 bytes chunk size
1221 $WEBP_VP8L_header = $this->fread(10);
1222 $this->fseek($old_offset);
1223 if (substr($WEBP_VP8L_header, 0, 1) == "\x2F") {
1224 $width_height_flags = getid3_lib
::LittleEndian2Bin(substr($WEBP_VP8L_header, 1, 4));
1225 $thisfile_riff['WEBP']['VP8L'][0]['width'] = bindec(substr($width_height_flags, 18, 14)) +
1;
1226 $thisfile_riff['WEBP']['VP8L'][0]['height'] = bindec(substr($width_height_flags, 4, 14)) +
1;
1227 $thisfile_riff['WEBP']['VP8L'][0]['alpha_is_used'] = (bool) bindec(substr($width_height_flags, 3, 1));
1228 $thisfile_riff['WEBP']['VP8L'][0]['version'] = bindec(substr($width_height_flags, 0, 3));
1230 $info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8L'][0]['width'];
1231 $info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8L'][0]['height'];
1233 $this->error('Expecting 2F at offset '.($thisfile_riff['WEBP']['VP8L'][0]['offset'] +
8).', found "'.getid3_lib
::PrintHexBytes(substr($WEBP_VP8L_header, 0, 1)).'"');
1240 $this->error('Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA|WEBP), found "'.$RIFFsubtype.'" instead');
1241 //unset($info['fileformat']);
1244 switch ($RIFFsubtype) {
1248 $ID3v2_key_good = 'id3 ';
1249 $ID3v2_keys_bad = array('ID3 ', 'tag ');
1250 foreach ($ID3v2_keys_bad as $ID3v2_key_bad) {
1251 if (isset($thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]) && !array_key_exists($ID3v2_key_good, $thisfile_riff[$RIFFsubtype])) {
1252 $thisfile_riff[$RIFFsubtype][$ID3v2_key_good] = $thisfile_riff[$RIFFsubtype][$ID3v2_key_bad];
1253 $this->warning('mapping "'.$ID3v2_key_bad.'" chunk to "'.$ID3v2_key_good.'"');
1257 if (isset($thisfile_riff[$RIFFsubtype]['id3 '])) {
1258 getid3_lib
::IncludeDependency(GETID3_INCLUDEPATH
.'module.tag.id3v2.php', __FILE__
, true);
1260 $getid3_temp = new getID3();
1261 $getid3_temp->openfile($this->getid3
->filename
, null, $this->getid3
->fp
);
1262 $getid3_id3v2 = new getid3_id3v2($getid3_temp);
1263 $getid3_id3v2->StartingOffset
= $thisfile_riff[$RIFFsubtype]['id3 '][0]['offset'] +
8;
1264 if ($thisfile_riff[$RIFFsubtype]['id3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
1265 $info['id3v2'] = $getid3_temp->info
['id3v2'];
1267 unset($getid3_temp, $getid3_id3v2);
1272 if (isset($thisfile_riff_WAVE['DISP']) && is_array($thisfile_riff_WAVE['DISP'])) {
1273 $thisfile_riff['comments']['title'][] = trim(substr($thisfile_riff_WAVE['DISP'][count($thisfile_riff_WAVE['DISP']) - 1]['data'], 4));
1275 if (isset($thisfile_riff_WAVE['INFO']) && is_array($thisfile_riff_WAVE['INFO'])) {
1276 self
::parseComments($thisfile_riff_WAVE['INFO'], $thisfile_riff['comments']);
1278 if (isset($thisfile_riff['AVI ']['INFO']) && is_array($thisfile_riff['AVI ']['INFO'])) {
1279 self
::parseComments($thisfile_riff['AVI ']['INFO'], $thisfile_riff['comments']);
1282 if (empty($thisfile_audio['encoder']) && !empty($info['mpeg']['audio']['LAME']['short_version'])) {
1283 $thisfile_audio['encoder'] = $info['mpeg']['audio']['LAME']['short_version'];
1286 if (!isset($info['playtime_seconds'])) {
1287 $info['playtime_seconds'] = 0;
1289 if (isset($thisfile_riff_raw['strh'][0]['dwLength']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) {
1290 // needed for >2GB AVIs where 'avih' chunk only lists number of frames in that chunk, not entire movie
1291 $info['playtime_seconds'] = $thisfile_riff_raw['strh'][0]['dwLength'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000);
1292 } elseif (isset($thisfile_riff_raw['avih']['dwTotalFrames']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) {
1293 $info['playtime_seconds'] = $thisfile_riff_raw['avih']['dwTotalFrames'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000);
1296 if ($info['playtime_seconds'] > 0) {
1297 if (isset($thisfile_riff_audio) && isset($thisfile_riff_video)) {
1299 if (!isset($info['bitrate'])) {
1300 $info['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8);
1303 } elseif (isset($thisfile_riff_audio) && !isset($thisfile_riff_video)) {
1305 if (!isset($thisfile_audio['bitrate'])) {
1306 $thisfile_audio['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8);
1309 } elseif (!isset($thisfile_riff_audio) && isset($thisfile_riff_video)) {
1311 if (!isset($thisfile_video['bitrate'])) {
1312 $thisfile_video['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8);
1319 if (isset($thisfile_riff_video) && isset($thisfile_audio['bitrate']) && ($thisfile_audio['bitrate'] > 0) && ($info['playtime_seconds'] > 0)) {
1321 $info['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8);
1322 $thisfile_audio['bitrate'] = 0;
1323 $thisfile_video['bitrate'] = $info['bitrate'];
1324 foreach ($thisfile_riff_audio as $channelnumber => $audioinfoarray) {
1325 $thisfile_video['bitrate'] -= $audioinfoarray['bitrate'];
1326 $thisfile_audio['bitrate'] +
= $audioinfoarray['bitrate'];
1328 if ($thisfile_video['bitrate'] <= 0) {
1329 unset($thisfile_video['bitrate']);
1331 if ($thisfile_audio['bitrate'] <= 0) {
1332 unset($thisfile_audio['bitrate']);
1336 if (isset($info['mpeg']['audio'])) {
1337 $thisfile_audio_dataformat = 'mp'.$info['mpeg']['audio']['layer'];
1338 $thisfile_audio['sample_rate'] = $info['mpeg']['audio']['sample_rate'];
1339 $thisfile_audio['channels'] = $info['mpeg']['audio']['channels'];
1340 $thisfile_audio['bitrate'] = $info['mpeg']['audio']['bitrate'];
1341 $thisfile_audio['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
1342 if (!empty($info['mpeg']['audio']['codec'])) {
1343 $thisfile_audio['codec'] = $info['mpeg']['audio']['codec'].' '.$thisfile_audio['codec'];
1345 if (!empty($thisfile_audio['streams'])) {
1346 foreach ($thisfile_audio['streams'] as $streamnumber => $streamdata) {
1347 if ($streamdata['dataformat'] == $thisfile_audio_dataformat) {
1348 $thisfile_audio['streams'][$streamnumber]['sample_rate'] = $thisfile_audio['sample_rate'];
1349 $thisfile_audio['streams'][$streamnumber]['channels'] = $thisfile_audio['channels'];
1350 $thisfile_audio['streams'][$streamnumber]['bitrate'] = $thisfile_audio['bitrate'];
1351 $thisfile_audio['streams'][$streamnumber]['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
1352 $thisfile_audio['streams'][$streamnumber]['codec'] = $thisfile_audio['codec'];
1356 $getid3_mp3 = new getid3_mp3($this->getid3
);
1357 $thisfile_audio['encoder_options'] = $getid3_mp3->GuessEncoderOptions();
1362 if (!empty($thisfile_riff_raw['fmt ']['wBitsPerSample']) && ($thisfile_riff_raw['fmt ']['wBitsPerSample'] > 0)) {
1363 switch ($thisfile_audio_dataformat) {
1365 // ignore bits_per_sample
1369 $thisfile_audio['bits_per_sample'] = $thisfile_riff_raw['fmt ']['wBitsPerSample'];
1375 if (empty($thisfile_riff_raw)) {
1376 unset($thisfile_riff['raw']);
1378 if (empty($thisfile_riff_audio)) {
1379 unset($thisfile_riff['audio']);
1381 if (empty($thisfile_riff_video)) {
1382 unset($thisfile_riff['video']);
1389 * @param int $startoffset
1390 * @param int $maxoffset
1392 * @return array|false
1395 * @throws getid3_exception
1397 public function ParseRIFFAMV($startoffset, $maxoffset) {
1398 // AMV files are RIFF-AVI files with parts of the spec deliberately broken, such as chunk size fields hardcoded to zero (because players known in hardware that these fields are always a certain size
1400 // https://code.google.com/p/amv-codec-tools/wiki/AmvDocumentation
1401 //typedef struct _amvmainheader {
1402 //FOURCC fcc; // 'amvh'
1404 //DWORD dwMicroSecPerFrame;
1416 $info = &$this->getid3
->info
;
1421 $this->fseek($startoffset);
1422 $maxoffset = min($maxoffset, $info['avdataend']);
1423 $AMVheader = $this->fread(284);
1424 if (substr($AMVheader, 0, 8) != 'hdrlamvh') {
1425 throw new Exception('expecting "hdrlamv" at offset '.($startoffset +
0).', found "'.substr($AMVheader, 0, 8).'"');
1427 if (substr($AMVheader, 8, 4) != "\x38\x00\x00\x00") { // "amvh" chunk size, hardcoded to 0x38 = 56 bytes
1428 throw new Exception('expecting "0x38000000" at offset '.($startoffset +
8).', found "'.getid3_lib
::PrintHexBytes(substr($AMVheader, 8, 4)).'"');
1430 $RIFFchunk = array();
1431 $RIFFchunk['amvh']['us_per_frame'] = getid3_lib
::LittleEndian2Int(substr($AMVheader, 12, 4));
1432 $RIFFchunk['amvh']['reserved28'] = substr($AMVheader, 16, 28); // null? reserved?
1433 $RIFFchunk['amvh']['resolution_x'] = getid3_lib
::LittleEndian2Int(substr($AMVheader, 44, 4));
1434 $RIFFchunk['amvh']['resolution_y'] = getid3_lib
::LittleEndian2Int(substr($AMVheader, 48, 4));
1435 $RIFFchunk['amvh']['frame_rate_int'] = getid3_lib
::LittleEndian2Int(substr($AMVheader, 52, 4));
1436 $RIFFchunk['amvh']['reserved0'] = getid3_lib
::LittleEndian2Int(substr($AMVheader, 56, 4)); // 1? reserved?
1437 $RIFFchunk['amvh']['reserved1'] = getid3_lib
::LittleEndian2Int(substr($AMVheader, 60, 4)); // 0? reserved?
1438 $RIFFchunk['amvh']['runtime_sec'] = getid3_lib
::LittleEndian2Int(substr($AMVheader, 64, 1));
1439 $RIFFchunk['amvh']['runtime_min'] = getid3_lib
::LittleEndian2Int(substr($AMVheader, 65, 1));
1440 $RIFFchunk['amvh']['runtime_hrs'] = getid3_lib
::LittleEndian2Int(substr($AMVheader, 66, 2));
1442 $info['video']['frame_rate'] = 1000000 / $RIFFchunk['amvh']['us_per_frame'];
1443 $info['video']['resolution_x'] = $RIFFchunk['amvh']['resolution_x'];
1444 $info['video']['resolution_y'] = $RIFFchunk['amvh']['resolution_y'];
1445 $info['playtime_seconds'] = ($RIFFchunk['amvh']['runtime_hrs'] * 3600) +
($RIFFchunk['amvh']['runtime_min'] * 60) +
$RIFFchunk['amvh']['runtime_sec'];
1447 // the rest is all hardcoded(?) and does not appear to be useful until you get to audio info at offset 256, even then everything is probably hardcoded
1449 if (substr($AMVheader, 68, 20) != 'LIST'."\x00\x00\x00\x00".'strlstrh'."\x38\x00\x00\x00") {
1450 throw new Exception('expecting "LIST<0x00000000>strlstrh<0x38000000>" at offset '.($startoffset +
68).', found "'.getid3_lib
::PrintHexBytes(substr($AMVheader, 68, 20)).'"');
1452 // followed by 56 bytes of null: substr($AMVheader, 88, 56) -> 144
1453 if (substr($AMVheader, 144, 8) != 'strf'."\x24\x00\x00\x00") {
1454 throw new Exception('expecting "strf<0x24000000>" at offset '.($startoffset +
144).', found "'.getid3_lib
::PrintHexBytes(substr($AMVheader, 144, 8)).'"');
1456 // followed by 36 bytes of null: substr($AMVheader, 144, 36) -> 180
1458 if (substr($AMVheader, 188, 20) != 'LIST'."\x00\x00\x00\x00".'strlstrh'."\x30\x00\x00\x00") {
1459 throw new Exception('expecting "LIST<0x00000000>strlstrh<0x30000000>" at offset '.($startoffset +
188).', found "'.getid3_lib
::PrintHexBytes(substr($AMVheader, 188, 20)).'"');
1461 // followed by 48 bytes of null: substr($AMVheader, 208, 48) -> 256
1462 if (substr($AMVheader, 256, 8) != 'strf'."\x14\x00\x00\x00") {
1463 throw new Exception('expecting "strf<0x14000000>" at offset '.($startoffset +
256).', found "'.getid3_lib
::PrintHexBytes(substr($AMVheader, 256, 8)).'"');
1465 // followed by 20 bytes of a modified WAVEFORMATEX:
1467 // WORD wFormatTag; //(Fixme: this is equal to PCM's 0x01 format code)
1468 // WORD nChannels; //(Fixme: this is always 1)
1469 // DWORD nSamplesPerSec; //(Fixme: for all known sample files this is equal to 22050)
1470 // DWORD nAvgBytesPerSec; //(Fixme: for all known sample files this is equal to 44100)
1471 // WORD nBlockAlign; //(Fixme: this seems to be 2 in AMV files, is this correct ?)
1472 // WORD wBitsPerSample; //(Fixme: this seems to be 16 in AMV files instead of the expected 4)
1473 // WORD cbSize; //(Fixme: this seems to be 0 in AMV files)
1476 $RIFFchunk['strf']['wformattag'] = getid3_lib
::LittleEndian2Int(substr($AMVheader, 264, 2));
1477 $RIFFchunk['strf']['nchannels'] = getid3_lib
::LittleEndian2Int(substr($AMVheader, 266, 2));
1478 $RIFFchunk['strf']['nsamplespersec'] = getid3_lib
::LittleEndian2Int(substr($AMVheader, 268, 4));
1479 $RIFFchunk['strf']['navgbytespersec'] = getid3_lib
::LittleEndian2Int(substr($AMVheader, 272, 4));
1480 $RIFFchunk['strf']['nblockalign'] = getid3_lib
::LittleEndian2Int(substr($AMVheader, 276, 2));
1481 $RIFFchunk['strf']['wbitspersample'] = getid3_lib
::LittleEndian2Int(substr($AMVheader, 278, 2));
1482 $RIFFchunk['strf']['cbsize'] = getid3_lib
::LittleEndian2Int(substr($AMVheader, 280, 2));
1483 $RIFFchunk['strf']['reserved'] = getid3_lib
::LittleEndian2Int(substr($AMVheader, 282, 2));
1486 $info['audio']['lossless'] = false;
1487 $info['audio']['sample_rate'] = $RIFFchunk['strf']['nsamplespersec'];
1488 $info['audio']['channels'] = $RIFFchunk['strf']['nchannels'];
1489 $info['audio']['bits_per_sample'] = $RIFFchunk['strf']['wbitspersample'];
1490 $info['audio']['bitrate'] = $info['audio']['sample_rate'] * $info['audio']['channels'] * $info['audio']['bits_per_sample'];
1491 $info['audio']['bitrate_mode'] = 'cbr';
1494 } catch (getid3_exception
$e) {
1495 if ($e->getCode() == 10) {
1496 $this->warning('RIFFAMV parser: '.$e->getMessage());
1506 * @param int $startoffset
1507 * @param int $maxoffset
1509 * @return array|false
1510 * @throws getid3_exception
1512 public function ParseRIFF($startoffset, $maxoffset) {
1513 $info = &$this->getid3
->info
;
1516 $FoundAllChunksWeNeed = false;
1519 $this->fseek($startoffset);
1520 $maxoffset = min($maxoffset, $info['avdataend']);
1521 while ($this->ftell() < $maxoffset) {
1522 $chunknamesize = $this->fread(8);
1523 //$chunkname = substr($chunknamesize, 0, 4);
1524 $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
1525 $chunksize = $this->EitherEndian2Int(substr($chunknamesize, 4, 4));
1526 //if (strlen(trim($chunkname, "\x00")) < 4) {
1527 if (strlen($chunkname) < 4) {
1528 $this->error('Expecting chunk name at offset '.($this->ftell() - 8).' but found nothing. Aborting RIFF parsing.');
1531 if (($chunksize == 0) && ($chunkname != 'JUNK')) {
1532 $this->warning('Chunk ('.$chunkname.') size at offset '.($this->ftell() - 4).' is zero. Aborting RIFF parsing.');
1535 if (($chunksize %
2) != 0) {
1536 // all structures are packed on word boundaries
1540 switch ($chunkname) {
1542 $listname = $this->fread(4);
1543 if (preg_match('#^(movi|rec )$#i', $listname)) {
1544 $RIFFchunk[$listname]['offset'] = $this->ftell() - 4;
1545 $RIFFchunk[$listname]['size'] = $chunksize;
1547 if (!$FoundAllChunksWeNeed) {
1548 $WhereWeWere = $this->ftell();
1549 $AudioChunkHeader = $this->fread(12);
1550 $AudioChunkStreamNum = substr($AudioChunkHeader, 0, 2);
1551 $AudioChunkStreamType = substr($AudioChunkHeader, 2, 2);
1552 $AudioChunkSize = getid3_lib
::LittleEndian2Int(substr($AudioChunkHeader, 4, 4));
1554 if ($AudioChunkStreamType == 'wb') {
1555 $FirstFourBytes = substr($AudioChunkHeader, 8, 4);
1556 if (preg_match('/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', $FirstFourBytes)) {
1558 if (getid3_mp3
::MPEGaudioHeaderBytesValid($FirstFourBytes)) {
1559 $getid3_temp = new getID3();
1560 $getid3_temp->openfile($this->getid3
->filename
, null, $this->getid3
->fp
);
1561 $getid3_temp->info
['avdataoffset'] = $this->ftell() - 4;
1562 $getid3_temp->info
['avdataend'] = $this->ftell() +
$AudioChunkSize;
1563 $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__
);
1564 $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info
['avdataoffset'], false);
1565 if (isset($getid3_temp->info
['mpeg']['audio'])) {
1566 $info['mpeg']['audio'] = $getid3_temp->info
['mpeg']['audio'];
1567 $info['audio'] = $getid3_temp->info
['audio'];
1568 $info['audio']['dataformat'] = 'mp'.$info['mpeg']['audio']['layer'];
1569 $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate'];
1570 $info['audio']['channels'] = $info['mpeg']['audio']['channels'];
1571 $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate'];
1572 $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
1573 //$info['bitrate'] = $info['audio']['bitrate'];
1575 unset($getid3_temp, $getid3_mp3);
1578 } elseif (strpos($FirstFourBytes, getid3_ac3
::syncword
) === 0) {
1581 $getid3_temp = new getID3();
1582 $getid3_temp->openfile($this->getid3
->filename
, null, $this->getid3
->fp
);
1583 $getid3_temp->info
['avdataoffset'] = $this->ftell() - 4;
1584 $getid3_temp->info
['avdataend'] = $this->ftell() +
$AudioChunkSize;
1585 $getid3_ac3 = new getid3_ac3($getid3_temp);
1586 $getid3_ac3->Analyze();
1587 if (empty($getid3_temp->info
['error'])) {
1588 $info['audio'] = $getid3_temp->info
['audio'];
1589 $info['ac3'] = $getid3_temp->info
['ac3'];
1590 if (!empty($getid3_temp->info
['warning'])) {
1591 foreach ($getid3_temp->info
['warning'] as $key => $value) {
1592 $this->warning($value);
1596 unset($getid3_temp, $getid3_ac3);
1599 $FoundAllChunksWeNeed = true;
1600 $this->fseek($WhereWeWere);
1602 $this->fseek($chunksize - 4, SEEK_CUR
);
1606 if (!isset($RIFFchunk[$listname])) {
1607 $RIFFchunk[$listname] = array();
1609 $LISTchunkParent = $listname;
1610 $LISTchunkMaxOffset = $this->ftell() - 4 +
$chunksize;
1611 if ($parsedChunk = $this->ParseRIFF($this->ftell(), $LISTchunkMaxOffset)) {
1612 $RIFFchunk[$listname] = array_merge_recursive($RIFFchunk[$listname], $parsedChunk);
1619 if (preg_match('#^[0-9]{2}(wb|pc|dc|db)$#', $chunkname)) {
1620 $this->fseek($chunksize, SEEK_CUR
);
1624 if (isset($RIFFchunk[$chunkname]) && is_array($RIFFchunk[$chunkname])) {
1625 $thisindex = count($RIFFchunk[$chunkname]);
1627 $RIFFchunk[$chunkname][$thisindex]['offset'] = $this->ftell() - 8;
1628 $RIFFchunk[$chunkname][$thisindex]['size'] = $chunksize;
1629 switch ($chunkname) {
1631 $info['avdataoffset'] = $this->ftell();
1632 $info['avdataend'] = $info['avdataoffset'] +
$chunksize;
1634 $testData = $this->fread(36);
1635 if ($testData === '') {
1638 if (preg_match('/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', substr($testData, 0, 4))) {
1640 // Probably is MP3 data
1641 if (getid3_mp3
::MPEGaudioHeaderBytesValid(substr($testData, 0, 4))) {
1642 $getid3_temp = new getID3();
1643 $getid3_temp->openfile($this->getid3
->filename
, null, $this->getid3
->fp
);
1644 $getid3_temp->info
['avdataoffset'] = $info['avdataoffset'];
1645 $getid3_temp->info
['avdataend'] = $info['avdataend'];
1646 $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__
);
1647 $getid3_mp3->getOnlyMPEGaudioInfo($info['avdataoffset'], false);
1648 if (empty($getid3_temp->info
['error'])) {
1649 $info['audio'] = $getid3_temp->info
['audio'];
1650 $info['mpeg'] = $getid3_temp->info
['mpeg'];
1652 unset($getid3_temp, $getid3_mp3);
1655 } elseif (($isRegularAC3 = (substr($testData, 0, 2) == getid3_ac3
::syncword
)) ||
substr($testData, 8, 2) == strrev(getid3_ac3
::syncword
)) {
1657 // This is probably AC-3 data
1658 $getid3_temp = new getID3();
1659 if ($isRegularAC3) {
1660 $getid3_temp->openfile($this->getid3
->filename
, null, $this->getid3
->fp
);
1661 $getid3_temp->info
['avdataoffset'] = $info['avdataoffset'];
1662 $getid3_temp->info
['avdataend'] = $info['avdataend'];
1664 $getid3_ac3 = new getid3_ac3($getid3_temp);
1665 if ($isRegularAC3) {
1666 $getid3_ac3->Analyze();
1668 // Dolby Digital WAV
1669 // AC-3 content, but not encoded in same format as normal AC-3 file
1670 // For one thing, byte order is swapped
1672 for ($i = 0; $i < 28; $i +
= 2) {
1673 $ac3_data .= substr($testData, 8 +
$i +
1, 1);
1674 $ac3_data .= substr($testData, 8 +
$i +
0, 1);
1676 $getid3_ac3->AnalyzeString($ac3_data);
1679 if (empty($getid3_temp->info
['error'])) {
1680 $info['audio'] = $getid3_temp->info
['audio'];
1681 $info['ac3'] = $getid3_temp->info
['ac3'];
1682 if (!empty($getid3_temp->info
['warning'])) {
1683 foreach ($getid3_temp->info
['warning'] as $newerror) {
1684 $this->warning('getid3_ac3() says: ['.$newerror.']');
1688 unset($getid3_temp, $getid3_ac3);
1690 } elseif (preg_match('/^('.implode('|', array_map('preg_quote', getid3_dts
::$syncwords)).')/', $testData)) {
1692 // This is probably DTS data
1693 $getid3_temp = new getID3();
1694 $getid3_temp->openfile($this->getid3
->filename
, null, $this->getid3
->fp
);
1695 $getid3_temp->info
['avdataoffset'] = $info['avdataoffset'];
1696 $getid3_dts = new getid3_dts($getid3_temp);
1697 $getid3_dts->Analyze();
1698 if (empty($getid3_temp->info
['error'])) {
1699 $info['audio'] = $getid3_temp->info
['audio'];
1700 $info['dts'] = $getid3_temp->info
['dts'];
1701 $info['playtime_seconds'] = $getid3_temp->info
['playtime_seconds']; // may not match RIFF calculations since DTS-WAV often used 14/16 bit-word packing
1702 if (!empty($getid3_temp->info
['warning'])) {
1703 foreach ($getid3_temp->info
['warning'] as $newerror) {
1704 $this->warning('getid3_dts() says: ['.$newerror.']');
1709 unset($getid3_temp, $getid3_dts);
1711 } elseif (substr($testData, 0, 4) == 'wvpk') {
1713 // This is WavPack data
1714 $info['wavpack']['offset'] = $info['avdataoffset'];
1715 $info['wavpack']['size'] = getid3_lib
::LittleEndian2Int(substr($testData, 4, 4));
1716 $this->parseWavPackHeader(substr($testData, 8, 28));
1719 // This is some other kind of data (quite possibly just PCM)
1720 // do nothing special, just skip it
1722 $nextoffset = $info['avdataend'];
1723 $this->fseek($nextoffset);
1735 // always read data in
1737 // should be: never read data in
1738 // but some programs write their version strings in a JUNK chunk (e.g. VirtualDub, AVIdemux, etc)
1739 if ($chunksize < 1048576) {
1740 if ($chunksize > 0) {
1741 $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize);
1742 if ($chunkname == 'JUNK') {
1743 if (preg_match('#^([\\x20-\\x7F]+)#', $RIFFchunk[$chunkname][$thisindex]['data'], $matches)) {
1744 // only keep text characters [chr(32)-chr(127)]
1745 $info['riff']['comments']['junk'][] = trim($matches[1]);
1747 // but if nothing there, ignore
1748 // remove the key in either case
1749 unset($RIFFchunk[$chunkname][$thisindex]['data']);
1753 $this->warning('Chunk "'.$chunkname.'" at offset '.$this->ftell().' is unexpectedly larger than 1MB (claims to be '.number_format($chunksize).' bytes), skipping data');
1754 $this->fseek($chunksize, SEEK_CUR
);
1759 // $info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunksize));
1763 // https://cmsdk.com/node-js/adding-scot-chunk-to-wav-file.html
1764 $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize);
1765 $RIFFchunk[$chunkname][$thisindex]['parsed']['alter'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 0, 1);
1766 $RIFFchunk[$chunkname][$thisindex]['parsed']['attrib'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 1, 1);
1767 $RIFFchunk[$chunkname][$thisindex]['parsed']['artnum'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 2, 2));
1768 $RIFFchunk[$chunkname][$thisindex]['parsed']['title'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 4, 43); // "name" in other documentation
1769 $RIFFchunk[$chunkname][$thisindex]['parsed']['copy'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 47, 4);
1770 $RIFFchunk[$chunkname][$thisindex]['parsed']['padd'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 51, 1);
1771 $RIFFchunk[$chunkname][$thisindex]['parsed']['asclen'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 52, 5);
1772 $RIFFchunk[$chunkname][$thisindex]['parsed']['startseconds'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 57, 2));
1773 $RIFFchunk[$chunkname][$thisindex]['parsed']['starthundredths'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 59, 2));
1774 $RIFFchunk[$chunkname][$thisindex]['parsed']['endseconds'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 61, 2));
1775 $RIFFchunk[$chunkname][$thisindex]['parsed']['endhundreths'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 63, 2));
1776 $RIFFchunk[$chunkname][$thisindex]['parsed']['sdate'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 65, 6);
1777 $RIFFchunk[$chunkname][$thisindex]['parsed']['kdate'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 71, 6);
1778 $RIFFchunk[$chunkname][$thisindex]['parsed']['start_hr'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 77, 1);
1779 $RIFFchunk[$chunkname][$thisindex]['parsed']['kill_hr'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 78, 1);
1780 $RIFFchunk[$chunkname][$thisindex]['parsed']['digital'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 79, 1);
1781 $RIFFchunk[$chunkname][$thisindex]['parsed']['sample_rate'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 80, 2));
1782 $RIFFchunk[$chunkname][$thisindex]['parsed']['stereo'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 82, 1);
1783 $RIFFchunk[$chunkname][$thisindex]['parsed']['compress'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 83, 1);
1784 $RIFFchunk[$chunkname][$thisindex]['parsed']['eomstrt'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 84, 4));
1785 $RIFFchunk[$chunkname][$thisindex]['parsed']['eomlen'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 88, 2));
1786 $RIFFchunk[$chunkname][$thisindex]['parsed']['attrib2'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 90, 4));
1787 $RIFFchunk[$chunkname][$thisindex]['parsed']['future1'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 94, 12);
1788 $RIFFchunk[$chunkname][$thisindex]['parsed']['catfontcolor'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 106, 4));
1789 $RIFFchunk[$chunkname][$thisindex]['parsed']['catcolor'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 110, 4));
1790 $RIFFchunk[$chunkname][$thisindex]['parsed']['segeompos'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 114, 4));
1791 $RIFFchunk[$chunkname][$thisindex]['parsed']['vt_startsecs'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 118, 2));
1792 $RIFFchunk[$chunkname][$thisindex]['parsed']['vt_starthunds'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 120, 2));
1793 $RIFFchunk[$chunkname][$thisindex]['parsed']['priorcat'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 122, 3);
1794 $RIFFchunk[$chunkname][$thisindex]['parsed']['priorcopy'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 125, 4);
1795 $RIFFchunk[$chunkname][$thisindex]['parsed']['priorpadd'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 129, 1);
1796 $RIFFchunk[$chunkname][$thisindex]['parsed']['postcat'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 130, 3);
1797 $RIFFchunk[$chunkname][$thisindex]['parsed']['postcopy'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 133, 4);
1798 $RIFFchunk[$chunkname][$thisindex]['parsed']['postpadd'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 137, 1);
1799 $RIFFchunk[$chunkname][$thisindex]['parsed']['hrcanplay'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 138, 21);
1800 $RIFFchunk[$chunkname][$thisindex]['parsed']['future2'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 159, 108);
1801 $RIFFchunk[$chunkname][$thisindex]['parsed']['artist'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 267, 34);
1802 $RIFFchunk[$chunkname][$thisindex]['parsed']['comment'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 301, 34); // "trivia" in other documentation
1803 $RIFFchunk[$chunkname][$thisindex]['parsed']['intro'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 335, 2);
1804 $RIFFchunk[$chunkname][$thisindex]['parsed']['end'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 337, 1);
1805 $RIFFchunk[$chunkname][$thisindex]['parsed']['year'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 338, 4);
1806 $RIFFchunk[$chunkname][$thisindex]['parsed']['obsolete2'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 342, 1);
1807 $RIFFchunk[$chunkname][$thisindex]['parsed']['rec_hr'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 343, 1);
1808 $RIFFchunk[$chunkname][$thisindex]['parsed']['rdate'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 344, 6);
1809 $RIFFchunk[$chunkname][$thisindex]['parsed']['mpeg_bitrate'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 350, 2));
1810 $RIFFchunk[$chunkname][$thisindex]['parsed']['pitch'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 352, 2));
1811 $RIFFchunk[$chunkname][$thisindex]['parsed']['playlevel'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 354, 2));
1812 $RIFFchunk[$chunkname][$thisindex]['parsed']['lenvalid'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 356, 1);
1813 $RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 357, 4));
1814 $RIFFchunk[$chunkname][$thisindex]['parsed']['newplaylevel'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 361, 2));
1815 $RIFFchunk[$chunkname][$thisindex]['parsed']['chopsize'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 363, 4));
1816 $RIFFchunk[$chunkname][$thisindex]['parsed']['vteomovr'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 367, 4));
1817 $RIFFchunk[$chunkname][$thisindex]['parsed']['desiredlen'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 371, 4));
1818 $RIFFchunk[$chunkname][$thisindex]['parsed']['triggers'] = getid3_lib
::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 375, 4));
1819 $RIFFchunk[$chunkname][$thisindex]['parsed']['fillout'] = substr($RIFFchunk[$chunkname][$thisindex]['data'], 379, 33);
1821 foreach (array('title', 'artist', 'comment') as $key) {
1822 if (trim($RIFFchunk[$chunkname][$thisindex]['parsed'][$key])) {
1823 $info['riff']['comments'][$key] = array($RIFFchunk[$chunkname][$thisindex]['parsed'][$key]);
1826 if ($RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'] && !empty($info['filesize']) && ($RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'] != $info['filesize'])) {
1827 $this->warning('RIFF.WAVE.scot.filelength ('.$RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'].') different from actual filesize ('.$info['filesize'].')');
1832 if (!empty($LISTchunkParent) && isset($LISTchunkMaxOffset) && (($RIFFchunk[$chunkname][$thisindex]['offset'] +
$RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) {
1833 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
1834 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size'] = $RIFFchunk[$chunkname][$thisindex]['size'];
1835 unset($RIFFchunk[$chunkname][$thisindex]['offset']);
1836 unset($RIFFchunk[$chunkname][$thisindex]['size']);
1837 if (isset($RIFFchunk[$chunkname][$thisindex]) && empty($RIFFchunk[$chunkname][$thisindex])) {
1838 unset($RIFFchunk[$chunkname][$thisindex]);
1840 if (isset($RIFFchunk[$chunkname]) && empty($RIFFchunk[$chunkname])) {
1841 unset($RIFFchunk[$chunkname]);
1843 $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['data'] = $this->fread($chunksize);
1844 } elseif ($chunksize < 2048) {
1845 // only read data in if smaller than 2kB
1846 $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize);
1848 $this->fseek($chunksize, SEEK_CUR
);
1856 } catch (getid3_exception
$e) {
1857 if ($e->getCode() == 10) {
1858 $this->warning('RIFF parser: '.$e->getMessage());
1868 * @param string $RIFFdata
1872 public function ParseRIFFdata(&$RIFFdata) {
1873 $info = &$this->getid3
->info
;
1875 $tempfile = tempnam(GETID3_TEMP_DIR
, 'getID3');
1876 $fp_temp = fopen($tempfile, 'wb');
1877 $RIFFdataLength = strlen($RIFFdata);
1878 $NewLengthString = getid3_lib
::LittleEndian2String($RIFFdataLength, 4);
1879 for ($i = 0; $i < 4; $i++
) {
1880 $RIFFdata[($i +
4)] = $NewLengthString[$i];
1882 fwrite($fp_temp, $RIFFdata);
1885 $getid3_temp = new getID3();
1886 $getid3_temp->openfile($tempfile);
1887 $getid3_temp->info
['filesize'] = $RIFFdataLength;
1888 $getid3_temp->info
['filenamepath'] = $info['filenamepath'];
1889 $getid3_temp->info
['tags'] = $info['tags'];
1890 $getid3_temp->info
['warning'] = $info['warning'];
1891 $getid3_temp->info
['error'] = $info['error'];
1892 $getid3_temp->info
['comments'] = $info['comments'];
1893 $getid3_temp->info
['audio'] = (isset($info['audio']) ?
$info['audio'] : array());
1894 $getid3_temp->info
['video'] = (isset($info['video']) ?
$info['video'] : array());
1895 $getid3_riff = new getid3_riff($getid3_temp);
1896 $getid3_riff->Analyze();
1898 $info['riff'] = $getid3_temp->info
['riff'];
1899 $info['warning'] = $getid3_temp->info
['warning'];
1900 $info['error'] = $getid3_temp->info
['error'];
1901 $info['tags'] = $getid3_temp->info
['tags'];
1902 $info['comments'] = $getid3_temp->info
['comments'];
1903 unset($getid3_riff, $getid3_temp);
1910 * @param array $RIFFinfoArray
1911 * @param array $CommentsTargetArray
1915 public static function parseComments(&$RIFFinfoArray, &$CommentsTargetArray) {
1916 $RIFFinfoKeyLookup = array(
1917 'IARL'=>'archivallocation',
1919 'ICDS'=>'costumedesigner',
1920 'ICMS'=>'commissionedby',
1923 'ICOP'=>'copyright',
1924 'ICRD'=>'creationdate',
1925 'IDIM'=>'dimensions',
1926 'IDIT'=>'digitizationdate',
1927 'IDPI'=>'resolution',
1928 'IDST'=>'distributor',
1930 'IENG'=>'engineers',
1931 'IFRM'=>'accountofparts',
1934 'ILGT'=>'lightness',
1936 'IMED'=>'orignalmedium',
1939 'IPDS'=>'productiondesigner',
1947 'ISGN'=>'secondarygenre',
1948 'ISHP'=>'sharpness',
1949 'ISRC'=>'sourcesupplier',
1950 'ISRF'=>'digitizationsource',
1951 'ISTD'=>'productionstudio',
1953 'ITCH'=>'encoded_by',
1958 foreach ($RIFFinfoKeyLookup as $key => $value) {
1959 if (isset($RIFFinfoArray[$key])) {
1960 foreach ($RIFFinfoArray[$key] as $commentid => $commentdata) {
1961 if (trim($commentdata['data']) != '') {
1962 if (isset($CommentsTargetArray[$value])) {
1963 $CommentsTargetArray[$value][] = trim($commentdata['data']);
1965 $CommentsTargetArray[$value] = array(trim($commentdata['data']));
1975 * @param string $WaveFormatExData
1979 public static function parseWAVEFORMATex($WaveFormatExData) {
1981 $WaveFormatEx = array();
1982 $WaveFormatEx['raw'] = array();
1983 $WaveFormatEx_raw = &$WaveFormatEx['raw'];
1985 $WaveFormatEx_raw['wFormatTag'] = substr($WaveFormatExData, 0, 2);
1986 $WaveFormatEx_raw['nChannels'] = substr($WaveFormatExData, 2, 2);
1987 $WaveFormatEx_raw['nSamplesPerSec'] = substr($WaveFormatExData, 4, 4);
1988 $WaveFormatEx_raw['nAvgBytesPerSec'] = substr($WaveFormatExData, 8, 4);
1989 $WaveFormatEx_raw['nBlockAlign'] = substr($WaveFormatExData, 12, 2);
1990 $WaveFormatEx_raw['wBitsPerSample'] = substr($WaveFormatExData, 14, 2);
1991 if (strlen($WaveFormatExData) > 16) {
1992 $WaveFormatEx_raw['cbSize'] = substr($WaveFormatExData, 16, 2);
1994 $WaveFormatEx_raw = array_map('getid3_lib::LittleEndian2Int', $WaveFormatEx_raw);
1996 $WaveFormatEx['codec'] = self
::wFormatTagLookup($WaveFormatEx_raw['wFormatTag']);
1997 $WaveFormatEx['channels'] = $WaveFormatEx_raw['nChannels'];
1998 $WaveFormatEx['sample_rate'] = $WaveFormatEx_raw['nSamplesPerSec'];
1999 $WaveFormatEx['bitrate'] = $WaveFormatEx_raw['nAvgBytesPerSec'] * 8;
2000 $WaveFormatEx['bits_per_sample'] = $WaveFormatEx_raw['wBitsPerSample'];
2002 return $WaveFormatEx;
2006 * @param string $WavPackChunkData
2010 public function parseWavPackHeader($WavPackChunkData) {
2015 // short bits; // added for version 2.00
2016 // short flags, shift; // added for version 3.00
2017 // long total_samples, crc, crc2;
2018 // char extension [4], extra_bc, extras [3];
2022 $info = &$this->getid3
->info
;
2023 $info['wavpack'] = array();
2024 $thisfile_wavpack = &$info['wavpack'];
2026 $thisfile_wavpack['version'] = getid3_lib
::LittleEndian2Int(substr($WavPackChunkData, 0, 2));
2027 if ($thisfile_wavpack['version'] >= 2) {
2028 $thisfile_wavpack['bits'] = getid3_lib
::LittleEndian2Int(substr($WavPackChunkData, 2, 2));
2030 if ($thisfile_wavpack['version'] >= 3) {
2031 $thisfile_wavpack['flags_raw'] = getid3_lib
::LittleEndian2Int(substr($WavPackChunkData, 4, 2));
2032 $thisfile_wavpack['shift'] = getid3_lib
::LittleEndian2Int(substr($WavPackChunkData, 6, 2));
2033 $thisfile_wavpack['total_samples'] = getid3_lib
::LittleEndian2Int(substr($WavPackChunkData, 8, 4));
2034 $thisfile_wavpack['crc1'] = getid3_lib
::LittleEndian2Int(substr($WavPackChunkData, 12, 4));
2035 $thisfile_wavpack['crc2'] = getid3_lib
::LittleEndian2Int(substr($WavPackChunkData, 16, 4));
2036 $thisfile_wavpack['extension'] = substr($WavPackChunkData, 20, 4);
2037 $thisfile_wavpack['extra_bc'] = getid3_lib
::LittleEndian2Int(substr($WavPackChunkData, 24, 1));
2038 for ($i = 0; $i <= 2; $i++
) {
2039 $thisfile_wavpack['extras'][] = getid3_lib
::LittleEndian2Int(substr($WavPackChunkData, 25 +
$i, 1));
2043 $thisfile_wavpack['flags'] = array();
2044 $thisfile_wavpack_flags = &$thisfile_wavpack['flags'];
2046 $thisfile_wavpack_flags['mono'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000001);
2047 $thisfile_wavpack_flags['fast_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000002);
2048 $thisfile_wavpack_flags['raw_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000004);
2049 $thisfile_wavpack_flags['calc_noise'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000008);
2050 $thisfile_wavpack_flags['high_quality'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000010);
2051 $thisfile_wavpack_flags['3_byte_samples'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000020);
2052 $thisfile_wavpack_flags['over_20_bits'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000040);
2053 $thisfile_wavpack_flags['use_wvc'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000080);
2054 $thisfile_wavpack_flags['noiseshaping'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000100);
2055 $thisfile_wavpack_flags['very_fast_mode'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000200);
2056 $thisfile_wavpack_flags['new_high_quality'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000400);
2057 $thisfile_wavpack_flags['cancel_extreme'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x000800);
2058 $thisfile_wavpack_flags['cross_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x001000);
2059 $thisfile_wavpack_flags['new_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x002000);
2060 $thisfile_wavpack_flags['joint_stereo'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x004000);
2061 $thisfile_wavpack_flags['extra_decorrelation'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x008000);
2062 $thisfile_wavpack_flags['override_noiseshape'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x010000);
2063 $thisfile_wavpack_flags['override_jointstereo'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x020000);
2064 $thisfile_wavpack_flags['copy_source_filetime'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x040000);
2065 $thisfile_wavpack_flags['create_exe'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x080000);
2072 * @param string $BITMAPINFOHEADER
2073 * @param bool $littleEndian
2077 public static function ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true) {
2079 $parsed['biSize'] = substr($BITMAPINFOHEADER, 0, 4); // number of bytes required by the BITMAPINFOHEADER structure
2080 $parsed['biWidth'] = substr($BITMAPINFOHEADER, 4, 4); // width of the bitmap in pixels
2081 $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
2082 $parsed['biPlanes'] = substr($BITMAPINFOHEADER, 12, 2); // number of color planes on the target device. In most cases this value must be set to 1
2083 $parsed['biBitCount'] = substr($BITMAPINFOHEADER, 14, 2); // Specifies the number of bits per pixels
2084 $parsed['biSizeImage'] = substr($BITMAPINFOHEADER, 20, 4); // size of the bitmap data section of the image (the actual pixel data, excluding BITMAPINFOHEADER and RGBQUAD structures)
2085 $parsed['biXPelsPerMeter'] = substr($BITMAPINFOHEADER, 24, 4); // horizontal resolution, in pixels per metre, of the target device
2086 $parsed['biYPelsPerMeter'] = substr($BITMAPINFOHEADER, 28, 4); // vertical resolution, in pixels per metre, of the target device
2087 $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
2088 $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
2089 $parsed = array_map('getid3_lib::'.($littleEndian ?
'Little' : 'Big').'Endian2Int', $parsed);
2091 $parsed['fourcc'] = substr($BITMAPINFOHEADER, 16, 4); // compression identifier
2097 * @param string $DIVXTAG
2102 public static function ParseDIVXTAG($DIVXTAG, $raw=false) {
2103 // structure from "IDivX" source, Form1.frm, by "Greg Frazier of Daemonic Software Group", email: gfrazier@icestorm.net, web: http://dsg.cjb.net/
2104 // source available at http://files.divx-digest.com/download/c663efe7ef8ad2e90bf4af4d3ea6188a/on0SWN2r/edit/IDivX.zip
2105 // 'Byte Layout: '1111111111111111
2106 // '32 for Movie - 1 '1111111111111111
2107 // '28 for Author - 6 '6666666666666666
2108 // '4 for year - 2 '6666666666662222
2109 // '3 for genre - 3 '7777777777777777
2110 // '48 for Comments - 7 '7777777777777777
2111 // '1 for Rating - 4 '7777777777777777
2112 // '5 for Future Additions - 0 '333400000DIVXTAG
2115 static $DIVXTAGgenre = array(
2117 1 => 'Action/Adventure',
2129 13 => 'Infomercial',
2130 14 => 'Interactive',
2132 16 => 'Music Video',
2139 $DIVXTAGrating = array(
2149 $parsed['title'] = trim(substr($DIVXTAG, 0, 32));
2150 $parsed['artist'] = trim(substr($DIVXTAG, 32, 28));
2151 $parsed['year'] = intval(trim(substr($DIVXTAG, 60, 4)));
2152 $parsed['comment'] = trim(substr($DIVXTAG, 64, 48));
2153 $parsed['genre_id'] = intval(trim(substr($DIVXTAG, 112, 3)));
2154 $parsed['rating_id'] = ord(substr($DIVXTAG, 115, 1));
2155 //$parsed['padding'] = substr($DIVXTAG, 116, 5); // 5-byte null
2156 //$parsed['magic'] = substr($DIVXTAG, 121, 7); // "DIVXTAG"
2158 $parsed['genre'] = (isset($DIVXTAGgenre[$parsed['genre_id']]) ?
$DIVXTAGgenre[$parsed['genre_id']] : $parsed['genre_id']);
2159 $parsed['rating'] = (isset($DIVXTAGrating[$parsed['rating_id']]) ?
$DIVXTAGrating[$parsed['rating_id']] : $parsed['rating_id']);
2162 unset($parsed['genre_id'], $parsed['rating_id']);
2163 foreach ($parsed as $key => $value) {
2164 if (empty($value)) {
2165 unset($parsed[$key]);
2170 foreach ($parsed as $tag => $value) {
2171 $parsed[$tag] = array($value);
2178 * @param string $tagshortname
2182 public static function waveSNDMtagLookup($tagshortname) {
2185 /** This is not a comment!
2192 ©fin featuredinstrument
2202 return getid3_lib
::EmbeddedLookup($tagshortname, $begin, __LINE__
, __FILE__
, 'riff-sndm');
2206 * @param int $wFormatTag
2210 public static function wFormatTagLookup($wFormatTag) {
2214 /** This is not a comment!
2216 0x0000 Microsoft Unknown Wave Format
2217 0x0001 Pulse Code Modulation (PCM)
2218 0x0002 Microsoft ADPCM
2220 0x0004 Compaq Computer VSELP
2222 0x0006 Microsoft A-Law
2223 0x0007 Microsoft mu-Law
2224 0x0008 Microsoft DTS
2226 0x0011 Intel DVI/IMA ADPCM
2227 0x0012 Videologic MediaSpace ADPCM
2228 0x0013 Sierra Semiconductor ADPCM
2229 0x0014 Antex Electronics G.723 ADPCM
2230 0x0015 DSP Solutions DigiSTD
2231 0x0016 DSP Solutions DigiFIX
2232 0x0017 Dialogic OKI ADPCM
2233 0x0018 MediaVision ADPCM
2234 0x0019 Hewlett-Packard CU
2236 0x0021 Speech Compression Sonarc
2237 0x0022 DSP Group TrueSpeech
2238 0x0023 Echo Speech EchoSC1
2239 0x0024 Audiofile AF36
2240 0x0025 Audio Processing Technology APTX
2241 0x0026 AudioFile AF10
2245 0x0031 Microsoft GSM 6.10
2247 0x0033 Antex Electronics ADPCME
2248 0x0034 Control Resources VQLPC
2249 0x0035 DSP Solutions DigiREAL
2250 0x0036 DSP Solutions DigiADPCM
2251 0x0037 Control Resources CR10
2252 0x0038 Natural MicroSystems VBXADPCM
2253 0x0039 Crystal Semiconductor IMA ADPCM
2255 0x003B Rockwell ADPCM
2256 0x003C Rockwell Digit LK
2258 0x0040 Antex Electronics G.721 ADPCM
2261 0x0050 MPEG Layer-2 or Layer-1
2269 0x0063 Canopus Atrac
2274 0x0069 Voxware Byte Aligned
2279 0x0074 Voxware MetaVoice
2280 0x0075 Voxware MetaSound
2281 0x0076 Voxware RT29HW
2295 0x0092 Dolby AC3 SPDIF
2296 0x0093 MediaSonic G.723
2297 0x0094 Aculab PLC Prosody 8kbps
2299 0x0098 Philips LPCBB
2302 0x0100 Rhetorex ADPCM
2305 0x0103 IBM AVC Adaptive Differential Pulse Code Modulation (ADPCM)
2308 0x0123 Digital G.723
2309 0x0125 Sanyo LD ADPCM
2310 0x0130 Sipro Lab Telecom ACELP NET
2311 0x0131 Sipro Lab Telecom ACELP 4800
2312 0x0132 Sipro Lab Telecom ACELP 8V3
2313 0x0133 Sipro Lab Telecom G.729
2314 0x0134 Sipro Lab Telecom G.729A
2315 0x0135 Sipro Lab Telecom Kelvin
2316 0x0140 Windows Media Video V8
2317 0x0150 Qualcomm PureVoice
2318 0x0151 Qualcomm HalfRate
2319 0x0155 Ring Zero Systems TUB GSM
2320 0x0160 Microsoft Audio 1
2321 0x0161 Windows Media Audio V7 / V8 / V9
2322 0x0162 Windows Media Audio Professional V9
2323 0x0163 Windows Media Audio Lossless V9
2324 0x0200 Creative Labs ADPCM
2325 0x0202 Creative Labs Fastspeech8
2326 0x0203 Creative Labs Fastspeech10
2327 0x0210 UHER Informatic GmbH ADPCM
2329 0x0230 I-link Worldwide VC
2330 0x0240 Aureal RAW Sport
2331 0x0250 Interactive Products HSX
2332 0x0251 Interactive Products RPELP
2333 0x0260 Consistent Software CS2
2335 0x0300 Fujitsu FM Towns Snd
2337 0x0401 Intel Music Coder
2338 0x0450 QDesign Music
2340 0x0681 AT&T Labs TPC
2341 0x08AE ClearJump LiteWave
2343 0x1001 Olivetti ADPCM
2344 0x1002 Olivetti CELP
2347 0x1100 Lernout & Hauspie Codec (0x1100)
2348 0x1101 Lernout & Hauspie CELP Codec (0x1101)
2349 0x1102 Lernout & Hauspie SBC Codec (0x1102)
2350 0x1103 Lernout & Hauspie SBC Codec (0x1103)
2351 0x1104 Lernout & Hauspie SBC Codec (0x1104)
2353 0x1401 AT&T ISIAudio
2354 0x1500 Soundspace Music Compression
2355 0x181C VoxWare RT24 Speech
2356 0x1FC4 NCT Soft ALF2CD (www.nctsoft.com)
2359 0x2002 WAVE_FORMAT_14_4
2360 0x2003 WAVE_FORMAT_28_8
2361 0x2004 WAVE_FORMAT_COOK
2362 0x2005 WAVE_FORMAT_DNET
2366 0x676F Ogg Vorbis 1+
2367 0x6770 Ogg Vorbis 2+
2368 0x6771 Ogg Vorbis 3+
2369 0x7A21 GSM-AMR (CBR, no SID)
2370 0x7A22 GSM-AMR (VBR, including SID)
2371 0xFFFE WAVE_FORMAT_EXTENSIBLE
2372 0xFFFF WAVE_FORMAT_DEVELOPMENT
2376 return getid3_lib
::EmbeddedLookup('0x'.str_pad(strtoupper(dechex($wFormatTag)), 4, '0', STR_PAD_LEFT
), $begin, __LINE__
, __FILE__
, 'riff-wFormatTag');
2380 * @param string $fourcc
2384 public static function fourccLookup($fourcc) {
2388 /** This is not a comment!
2390 swot http://developer.apple.com/qa/snd/snd07.html
2391 ____ No Codec (____)
2392 _BIT BI_BITFIELDS (Raw RGB)
2393 _JPG JPEG compressed
2394 _PNG PNG compressed W3C/ISO/IEC (RFC-2083)
2395 _RAW Full Frames (Uncompressed)
2402 AASC Autodesk Animator
2403 ABYR Kensington ?ABYR?
2404 AEMI Array Microsystems VideoONE MPEG1-I Capture
2405 AFLC Autodesk Animator FLC
2406 AFLI Autodesk Animator FLI
2407 AMPG Array Microsystems VideoONE MPEG
2408 ANIM Intel RDX (ANIM)
2409 AP41 AngelPotion Definitive
2412 ASVX Asus Video 2.0 (audio)
2413 AUR2 AuraVision Aura 2 Codec - YUV 4:2:2
2414 AURA AuraVision Aura 1 Codec - YUV 4:1:1
2415 AVDJ Independent JPEG Group\'s codec (AVDJ)
2416 AVRN Independent JPEG Group\'s codec (AVRN)
2417 AYUV 4:4:4 YUV (AYUV)
2418 AZPR Quicktime Apple Video (AZPR)
2420 BLZ0 Blizzard DivX MPEG-4
2421 BTVC Conexant Composite Video
2422 BINK RAD Game Tools Bink Video
2423 BT20 Conexant Prosumer Video
2424 BTCV Conexant Composite Video Codec
2425 BW10 Data Translation Broadway MPEG Capture
2428 CFCC Digital Processing Systems DPS Perception
2429 CGDI Microsoft Office 97 Camcorder Video
2430 CHAM Winnov Caviara Champagne
2431 CJPG Creative WebCam JPEG
2432 CLJR Cirrus Logic YUV 4:1:1
2433 CMYK Common Data Format in Printing (Colorgraph)
2434 CPLA Weitek 4:2:0 YUV Planar
2435 CRAM Microsoft Video 1 (CRAM)
2438 CWLT Microsoft Color WLT DIB
2439 CYUV Creative Labs YUV
2443 DIB Device Independent Bitmap
2444 DIV1 FFmpeg OpenDivX
2445 DIV2 Microsoft MPEG-4 v1/v2
2446 DIV3 DivX ;-) MPEG-4 v3.x Low-Motion
2447 DIV4 DivX ;-) MPEG-4 v3.x Fast-Motion
2448 DIV5 DivX MPEG-4 v5.x
2449 DIV6 DivX ;-) (MS MPEG-4 v3.x)
2450 DIVX DivX MPEG-4 v4 (OpenDivX / Project Mayo)
2452 DMB1 Matrox Rainbow Runner hardware MJPEG
2455 DUCK Duck TrueMotion 1.0
2456 DPS0 DPS/Leitch Reality Motion JPEG
2457 DPSC DPS/Leitch PAR Motion JPEG
2458 DV25 Matrox DVCPRO codec
2459 DV50 Matrox DVCPRO50 codec
2460 DVC IEC 61834 and SMPTE 314M (DVC/DV Video)
2461 DVCP IEC 61834 and SMPTE 314M (DVC/DV Video)
2462 DVHD IEC Standard DV 1125 lines @ 30fps / 1250 lines @ 25fps
2463 DVMA Darim Vision DVMPEG (dummy for MPEG compressor) (www.darvision.com)
2464 DVSL IEC Standard DV compressed in SD (SDL)
2466 DVE2 InSoft DVE-2 Videoconferencing
2467 dvsd IEC 61834 and SMPTE 314M DVC/DV Video
2468 DVSD IEC 61834 and SMPTE 314M DVC/DV Video
2469 DVX1 Lucent DVX1000SP Video Decoder
2470 DVX2 Lucent DVX2000S Video Decoder
2471 DVX3 Lucent DVX3000S Video Decoder
2473 DXT1 Microsoft DirectX Compressed Texture (DXT1)
2474 DXT2 Microsoft DirectX Compressed Texture (DXT2)
2475 DXT3 Microsoft DirectX Compressed Texture (DXT3)
2476 DXT4 Microsoft DirectX Compressed Texture (DXT4)
2477 DXT5 Microsoft DirectX Compressed Texture (DXT5)
2478 DXTC Microsoft DirectX Compressed Texture (DXTC)
2479 DXTn Microsoft DirectX Compressed Texture (DXTn)
2480 EM2V Etymonix MPEG-2 I-frame (www.etymonix.com)
2484 ETV1 eTreppid Video ETV1
2485 ETV2 eTreppid Video ETV2
2486 ETVC eTreppid Video ETVC
2487 FLIC Autodesk FLI/FLC Animation
2489 FLV4 On2 TrueMotion VP6
2490 FRWT Darim Vision Forward Motion JPEG (www.darvision.com)
2491 FRWU Darim Vision Forward Uncompressed (www.darvision.com)
2492 FLJP D-Vision Field Encoded Motion JPEG
2494 FRWA SoftLab-Nsk Forward Motion JPEG w/ alpha channel
2495 FRWD SoftLab-Nsk Forward Motion JPEG
2496 FVF1 Iterated Systems Fractal Video Frame
2497 GLZW Motion LZW (gabest@freemail.hu)
2498 GPEG Motion JPEG (gabest@freemail.hu)
2499 GWLT Microsoft Greyscale WLT DIB
2500 H260 Intel ITU H.260 Videoconferencing
2501 H261 Intel ITU H.261 Videoconferencing
2502 H262 Intel ITU H.262 Videoconferencing
2503 H263 Intel ITU H.263 Videoconferencing
2504 H264 Intel ITU H.264 Videoconferencing
2505 H265 Intel ITU H.265 Videoconferencing
2506 H266 Intel ITU H.266 Videoconferencing
2507 H267 Intel ITU H.267 Videoconferencing
2508 H268 Intel ITU H.268 Videoconferencing
2509 H269 Intel ITU H.269 Videoconferencing
2510 HFYU Huffman Lossless Codec
2511 HMCR Rendition Motion Compensation Format (HMCR)
2512 HMRR Rendition Motion Compensation Format (HMRR)
2513 I263 FFmpeg I263 decoder
2514 IF09 Indeo YVU9 ("YVU9 with additional delta-frame info after the U plane")
2515 IUYV Interlaced version of UYVY (www.leadtools.com)
2516 IY41 Interlaced version of Y41P (www.leadtools.com)
2517 IYU1 12 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec IEEE standard
2518 IYU2 24 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec IEEE standard
2519 IYUV Planar YUV format (8-bpp Y plane, followed by 8-bpp 2×2 U and V planes)
2520 i263 Intel ITU H.263 Videoconferencing (i263)
2522 IAN Intel Indeo 4 (RDX)
2523 ICLB InSoft CellB Videoconferencing
2525 IJPG Intergraph JPEG
2526 ILVC Intel Layered Video
2528 IPDV I-O Data Device Giga AVI DV Codec
2529 IR21 Intel Indeo 2.1
2530 IRAW Intel YUV Uncompressed
2531 IV30 Intel Indeo 3.0
2532 IV31 Intel Indeo 3.1
2533 IV32 Ligos Indeo 3.2
2534 IV33 Ligos Indeo 3.3
2535 IV34 Ligos Indeo 3.4
2536 IV35 Ligos Indeo 3.5
2537 IV36 Ligos Indeo 3.6
2538 IV37 Ligos Indeo 3.7
2539 IV38 Ligos Indeo 3.8
2540 IV39 Ligos Indeo 3.9
2541 IV40 Ligos Indeo Interactive 4.0
2542 IV41 Ligos Indeo Interactive 4.1
2543 IV42 Ligos Indeo Interactive 4.2
2544 IV43 Ligos Indeo Interactive 4.3
2545 IV44 Ligos Indeo Interactive 4.4
2546 IV45 Ligos Indeo Interactive 4.5
2547 IV46 Ligos Indeo Interactive 4.6
2548 IV47 Ligos Indeo Interactive 4.7
2549 IV48 Ligos Indeo Interactive 4.8
2550 IV49 Ligos Indeo Interactive 4.9
2551 IV50 Ligos Indeo Interactive 5.0
2552 JBYR Kensington ?JBYR?
2553 JPEG Still Image JPEG DIB
2554 JPGL Pegasus Lossless Motion JPEG
2555 KMVC Team17 Software Karl Morton\'s Video Codec
2556 LSVM Vianet Lighting Strike Vmail (Streaming) (www.vianet.com)
2557 LEAD LEAD Video Codec
2558 Ljpg LEAD MJPEG Codec
2559 MDVD Alex MicroDVD Video (hacked MS MPEG-4) (www.tiasoft.de)
2560 MJPA Morgan Motion JPEG (MJPA) (www.morgan-multimedia.com)
2561 MJPB Morgan Motion JPEG (MJPB) (www.morgan-multimedia.com)
2562 MMES Matrox MPEG-2 I-frame
2563 MP2v Microsoft S-Mpeg 4 version 1 (MP2v)
2564 MP42 Microsoft S-Mpeg 4 version 2 (MP42)
2565 MP43 Microsoft S-Mpeg 4 version 3 (MP43)
2566 MP4S Microsoft S-Mpeg 4 version 3 (MP4S)
2568 MPG1 FFmpeg MPEG 1/2
2569 MPG2 FFmpeg MPEG 1/2
2570 MPG3 FFmpeg DivX ;-) (MS MPEG-4 v3)
2571 MPG4 Microsoft MPEG-4
2572 MPGI Sigma Designs MPEG
2573 MPNG PNG images decoder
2574 MSS1 Microsoft Windows Screen Video
2575 MSZH LCL (Lossless Codec Library) (www.geocities.co.jp/Playtown-Denei/2837/LRC.htm)
2576 M261 Microsoft H.261
2577 M263 Microsoft H.263
2578 M4S2 Microsoft Fully Compliant MPEG-4 v2 simple profile (M4S2)
2579 m4s2 Microsoft Fully Compliant MPEG-4 v2 simple profile (m4s2)
2580 MC12 ATI Motion Compensation Format (MC12)
2581 MCAM ATI Motion Compensation Format (MCAM)
2582 MJ2C Morgan Multimedia Motion JPEG2000
2583 mJPG IBM Motion JPEG w/ Huffman Tables
2584 MJPG Microsoft Motion JPEG DIB
2585 MP42 Microsoft MPEG-4 (low-motion)
2586 MP43 Microsoft MPEG-4 (fast-motion)
2587 MP4S Microsoft MPEG-4 (MP4S)
2588 mp4s Microsoft MPEG-4 (mp4s)
2589 MPEG Chromatic Research MPEG-1 Video I-Frame
2590 MPG4 Microsoft MPEG-4 Video High Speed Compressor
2591 MPGI Sigma Designs MPEG
2592 MRCA FAST Multimedia Martin Regen Codec
2593 MRLE Microsoft Run Length Encoding
2594 MSVC Microsoft Video 1
2604 MV12 Motion Pixels Codec (old)
2605 MWV1 Aware Motion Wavelets
2606 nAVI SMR Codec (hack of Microsoft MPEG-4) (IRC #shadowrealm)
2607 NT00 NewTek LightWave HDTV YUV w/ Alpha (www.newtek.com)
2609 NTN1 Nogatech Video Compression 1
2610 NVS0 nVidia GeForce Texture (NVS0)
2611 NVS1 nVidia GeForce Texture (NVS1)
2612 NVS2 nVidia GeForce Texture (NVS2)
2613 NVS3 nVidia GeForce Texture (NVS3)
2614 NVS4 nVidia GeForce Texture (NVS4)
2615 NVS5 nVidia GeForce Texture (NVS5)
2616 NVT0 nVidia GeForce Texture (NVT0)
2617 NVT1 nVidia GeForce Texture (NVT1)
2618 NVT2 nVidia GeForce Texture (NVT2)
2619 NVT3 nVidia GeForce Texture (NVT3)
2620 NVT4 nVidia GeForce Texture (NVT4)
2621 NVT5 nVidia GeForce Texture (NVT5)
2622 PIXL MiroXL, Pinnacle PCTV
2623 PDVC I-O Data Device Digital Video Capture DV codec
2624 PGVV Radius Video Vision
2625 PHMO IBM Photomotion
2626 PIM1 MPEG Realtime (Pinnacle Cards)
2627 PIM2 Pegasus Imaging ?PIM2?
2628 PIMJ Pegasus Imaging Lossless JPEG
2629 PVEZ Horizons Technology PowerEZ
2630 PVMM PacketVideo Corporation MPEG-4
2631 PVW2 Pegasus Imaging Wavelet Compression
2632 Q1.0 Q-Team\'s QPEG 1.0 (www.q-team.de)
2633 Q1.1 Q-Team\'s QPEG 1.1 (www.q-team.de)
2634 QPEG Q-Team QPEG 1.0
2635 qpeq Q-Team QPEG 1.1
2637 RGBA Raw RGB w/ Alpha
2638 RMP4 REALmagic MPEG-4 (unauthorized XVID copy) (www.sigmadesigns.com)
2639 ROQV Id RoQ File Video Decoder
2640 RPZA Quicktime Apple Video (RPZA)
2641 RUD0 Rududu video codec (http://rududu.ifrance.com/rududu/)
2642 RV10 RealVideo 1.0 (aka RealVideo 5.0)
2643 RV13 RealVideo 1.0 (RV13)
2647 RGBT Raw RGB w/ Transparency
2648 RLE Microsoft Run Length Encoder
2649 RLE4 Run Length Encoded (4bpp, 16-color)
2650 RLE8 Run Length Encoded (8bpp, 256-color)
2651 RT21 Intel Indeo RealTime Video 2.1
2654 RVX Intel RDX (RVX )
2655 SMC Apple Graphics (SMC )
2656 SP54 Logitech Sunplus Sp54 Codec for Mustek GSmart Mini 2
2658 SVQ3 Sorenson Video 3 (Apple Quicktime 5)
2659 s422 Tekram VideoCap C210 YUV 4:2:2
2660 SDCC Sun Communication Digital Camera Codec
2661 SFMC CrystalNet Surface Fitting Method
2664 smsv WorldConnect Wavelet Video
2666 SPLC Splash Studios ACM Audio Codec (www.splashstudios.net)
2667 SQZ2 Microsoft VXTreme Video Codec V2
2668 STVA ST Microelectronics CMOS Imager Data (Bayer)
2669 STVB ST Microelectronics CMOS Imager Data (Nudged Bayer)
2670 STVC ST Microelectronics CMOS Imager Data (Bunched)
2671 STVX ST Microelectronics CMOS Imager Data (Extended CODEC Data Format)
2672 STVY ST Microelectronics CMOS Imager Data (Extended CODEC Data Format with Correction Data)
2673 SV10 Sorenson Video R1
2675 T420 Toshiba YUV 4:2:0
2676 TM2A Duck TrueMotion Archiver 2.0 (www.duck.com)
2677 TVJP Pinnacle/Truevision Targa 2000 board (TVJP)
2678 TVMJ Pinnacle/Truevision Targa 2000 board (TVMJ)
2679 TY0N Tecomac Low-Bit Rate Codec (www.tecomac.com)
2680 TY2C Trident Decompression Driver
2681 TLMS TeraLogic Motion Intraframe Codec (TLMS)
2682 TLST TeraLogic Motion Intraframe Codec (TLST)
2683 TM20 Duck TrueMotion 2.0
2684 TM2X Duck TrueMotion 2X
2685 TMIC TeraLogic Motion Intraframe Codec (TMIC)
2686 TMOT Horizons Technology TrueMotion S
2687 tmot Horizons TrueMotion Video Compression
2688 TR20 Duck TrueMotion RealTime 2.0
2689 TSCC TechSmith Screen Capture Codec
2690 TV10 Tecomac Low-Bit Rate Codec
2692 U263 UB Video H.263/H.263+/H.263++ Decoder
2693 UMP4 UB Video MPEG 4 (www.ubvideo.com)
2694 UYNV Nvidia UYVY packed 4:2:2
2695 UYVP Evans & Sutherland YCbCr 4:2:2 extended precision
2696 UCOD eMajix.com ClearVideo
2698 UYVY UYVY packed 4:2:2
2700 VIFP VFAPI Reader Codec (www.yks.ne.jp/~hori/)
2701 VIV1 FFmpeg H263+ decoder
2703 VQC2 Vector-quantised codec 2 (research) http://eprints.ecs.soton.ac.uk/archive/00001310/01/VTC97-js.pdf)
2704 VTLP Alaris VideoGramPiX
2708 V422 Vitec Multimedia 24-bit YUV 4:2:2 Format
2709 V655 Vitec Multimedia 16-bit YUV 4:2:2 Format
2710 VCR1 ATI Video Codec 1
2711 VCR2 ATI Video Codec 2
2719 VDCT Vitec Multimedia Video Maker Pro DIB
2721 VDOW VDOnet VDOLive (H.263)
2722 VDTZ Darim Vison VideoTizer YUV
2723 VGPX Alaris VideoGramPiX
2724 VIDS Vitec Multimedia YUV 4:2:2 CCIR 601 for V422
2725 VIVO Vivo H.263 v2.00
2727 VIXL Miro/Pinnacle Video XL
2728 VLV1 VideoLogic/PURE Digital Videologic Capture
2731 VP6F On2 TrueMotion VP6
2732 VX1K Lucent VX1000S Video Codec
2733 VX2K Lucent VX2000S Video Codec
2734 VXSP Lucent VX1000SP Video Codec
2736 WHAM Microsoft Video 1 (WHAM)
2737 WINX Winnov Software Compression
2738 WJPG AverMedia Winbond JPEG
2739 WMV1 Windows Media Video V7
2740 WMV2 Windows Media Video V8
2741 WMV3 Windows Media Video V9
2742 WNV1 Winnov Hardware Compression
2743 XYZP Extended PAL format XYZ palette (www.riff.org)
2745 XLV0 NetXL Video Decoder
2746 XMPG Xing MPEG (I-Frame only)
2747 XVID XviD MPEG-4 (www.xvid.org)
2749 YU92 Intel YUV (YU92)
2750 YUNV Nvidia Uncompressed YUV 4:2:2
2751 YUVP Extended PAL format YUV palette (www.riff.org)
2752 Y211 YUV 2:1:1 Packed
2753 Y411 YUV 4:1:1 Packed
2754 Y41B Weitek YUV 4:1:1 Planar
2755 Y41P Brooktree PC1 YUV 4:1:1 Packed
2756 Y41T Brooktree PC1 YUV 4:1:1 with transparency
2757 Y42B Weitek YUV 4:2:2 Planar
2758 Y42T Brooktree UYUV 4:2:2 with transparency
2759 Y422 ADS Technologies Copy of UYVY used in Pyro WebCam firewire camera
2760 Y800 Simple, single Y plane for monochrome images
2762 YC12 Intel YUV 12 codec
2763 YUV8 Winnov Caviar YUV8
2765 YUY2 Uncompressed YUV 4:2:2
2768 YVU9 Intel YVU9 Planar (8-bpp Y plane, followed by 8-bpp 4x4 U and V planes)
2769 YVYU YVYU 4:2:2 Packed
2770 ZLIB Lossless Codec Library zlib compression (www.geocities.co.jp/Playtown-Denei/2837/LRC.htm)
2771 ZPEG Metheus Video Zipper
2775 return getid3_lib
::EmbeddedLookup($fourcc, $begin, __LINE__
, __FILE__
, 'riff-fourcc');
2779 * @param string $byteword
2780 * @param bool $signed
2782 * @return int|float|false
2784 private function EitherEndian2Int($byteword, $signed=false) {
2785 if ($this->container
== 'riff') {
2786 return getid3_lib
::LittleEndian2Int($byteword, $signed);
2788 return getid3_lib
::BigEndian2Int($byteword, false, $signed);