wp/wp-includes/ID3/module.audio-video.riff.php
changeset 0 d970ebf37754
child 5 5e2f62d02dcd
equal deleted inserted replaced
-1:000000000000 0:d970ebf37754
       
     1 <?php
       
     2 /////////////////////////////////////////////////////////////////
       
     3 /// getID3() by James Heinrich <info@getid3.org>               //
       
     4 //  available at http://getid3.sourceforge.net                 //
       
     5 //            or http://www.getid3.org                         //
       
     6 /////////////////////////////////////////////////////////////////
       
     7 // See readme.txt for more details                             //
       
     8 /////////////////////////////////////////////////////////////////
       
     9 //                                                             //
       
    10 // module.audio-video.riff.php                                 //
       
    11 // module for analyzing RIFF files                             //
       
    12 // multiple formats supported by this module:                  //
       
    13 //    Wave, AVI, AIFF/AIFC, (MP3,AC3)/RIFF, Wavpack v3, 8SVX   //
       
    14 // dependencies: module.audio.mp3.php                          //
       
    15 //               module.audio.ac3.php                          //
       
    16 //               module.audio.dts.php                          //
       
    17 //                                                            ///
       
    18 /////////////////////////////////////////////////////////////////
       
    19 
       
    20 /**
       
    21 * @todo Parse AC-3/DTS audio inside WAVE correctly
       
    22 * @todo Rewrite RIFF parser totally
       
    23 */
       
    24 
       
    25 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true);
       
    26 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ac3.php', __FILE__, true);
       
    27 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.dts.php', __FILE__, true);
       
    28 
       
    29 class getid3_riff extends getid3_handler
       
    30 {
       
    31 
       
    32 	public function Analyze() {
       
    33 		$info = &$this->getid3->info;
       
    34 
       
    35 		// initialize these values to an empty array, otherwise they default to NULL
       
    36 		// and you can't append array values to a NULL value
       
    37 		$info['riff'] = array('raw'=>array());
       
    38 
       
    39 		// Shortcuts
       
    40 		$thisfile_riff             = &$info['riff'];
       
    41 		$thisfile_riff_raw         = &$thisfile_riff['raw'];
       
    42 		$thisfile_audio            = &$info['audio'];
       
    43 		$thisfile_video            = &$info['video'];
       
    44 		$thisfile_audio_dataformat = &$thisfile_audio['dataformat'];
       
    45 		$thisfile_riff_audio       = &$thisfile_riff['audio'];
       
    46 		$thisfile_riff_video       = &$thisfile_riff['video'];
       
    47 
       
    48 		$Original['avdataoffset'] = $info['avdataoffset'];
       
    49 		$Original['avdataend']    = $info['avdataend'];
       
    50 
       
    51 		$this->fseek($info['avdataoffset']);
       
    52 		$RIFFheader = $this->fread(12);
       
    53 		$offset = $this->ftell();
       
    54 		$RIFFtype    = substr($RIFFheader, 0, 4);
       
    55 		$RIFFsize    = substr($RIFFheader, 4, 4);
       
    56 		$RIFFsubtype = substr($RIFFheader, 8, 4);
       
    57 
       
    58 		switch ($RIFFtype) {
       
    59 
       
    60 			case 'FORM':  // AIFF, AIFC
       
    61 				$info['fileformat']   = 'aiff';
       
    62 				$thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize);
       
    63 				$thisfile_riff[$RIFFsubtype]  = $this->ParseRIFF($offset, ($offset + $thisfile_riff['header_size'] - 4));
       
    64 				break;
       
    65 
       
    66 			case 'RIFF':  // AVI, WAV, etc
       
    67 			case 'SDSS':  // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com)
       
    68 			case 'RMP3':  // RMP3 is identical to RIFF, just renamed. Used by [unknown program] when creating RIFF-MP3s
       
    69 				$info['fileformat']   = 'riff';
       
    70 				$thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize);
       
    71 				if ($RIFFsubtype == 'RMP3') {
       
    72 					// RMP3 is identical to WAVE, just renamed. Used by [unknown program] when creating RIFF-MP3s
       
    73 					$RIFFsubtype = 'WAVE';
       
    74 				}
       
    75 				$thisfile_riff[$RIFFsubtype]  = $this->ParseRIFF($offset, ($offset + $thisfile_riff['header_size'] - 4));
       
    76 				if (($info['avdataend'] - $info['filesize']) == 1) {
       
    77 					// LiteWave appears to incorrectly *not* pad actual output file
       
    78 					// to nearest WORD boundary so may appear to be short by one
       
    79 					// byte, in which case - skip warning
       
    80 					$info['avdataend'] = $info['filesize'];
       
    81 				}
       
    82 
       
    83 				$nextRIFFoffset = $Original['avdataoffset'] + 8 + $thisfile_riff['header_size']; // 8 = "RIFF" + 32-bit offset
       
    84 				while ($nextRIFFoffset < min($info['filesize'], $info['avdataend'])) {
       
    85 					try {
       
    86 						$this->fseek($nextRIFFoffset);
       
    87 					} catch (getid3_exception $e) {
       
    88 						if ($e->getCode() == 10) {
       
    89 							//$this->warning('RIFF parser: '.$e->getMessage());
       
    90 							$this->error('AVI extends beyond '.round(PHP_INT_MAX / 1073741824).'GB and PHP filesystem functions cannot read that far, playtime may be wrong');
       
    91 							$this->warning('[avdataend] value may be incorrect, multiple AVIX chunks may be present');
       
    92 							break;
       
    93 						} else {
       
    94 							throw $e;
       
    95 						}
       
    96 					}
       
    97 					$nextRIFFheader = $this->fread(12);
       
    98 					if ($nextRIFFoffset == ($info['avdataend'] - 1)) {
       
    99 						if (substr($nextRIFFheader, 0, 1) == "\x00") {
       
   100 							// RIFF padded to WORD boundary, we're actually already at the end
       
   101 							break;
       
   102 						}
       
   103 					}
       
   104 					$nextRIFFheaderID =                         substr($nextRIFFheader, 0, 4);
       
   105 					$nextRIFFsize     = $this->EitherEndian2Int(substr($nextRIFFheader, 4, 4));
       
   106 					$nextRIFFtype     =                         substr($nextRIFFheader, 8, 4);
       
   107 					$chunkdata = array();
       
   108 					$chunkdata['offset'] = $nextRIFFoffset + 8;
       
   109 					$chunkdata['size']   = $nextRIFFsize;
       
   110 					$nextRIFFoffset = $chunkdata['offset'] + $chunkdata['size'];
       
   111 
       
   112 					switch ($nextRIFFheaderID) {
       
   113 
       
   114 						case 'RIFF':
       
   115 							$chunkdata['chunks'] = $this->ParseRIFF($chunkdata['offset'] + 4, $nextRIFFoffset);
       
   116 
       
   117 							if (!isset($thisfile_riff[$nextRIFFtype])) {
       
   118 								$thisfile_riff[$nextRIFFtype] = array();
       
   119 							}
       
   120 							$thisfile_riff[$nextRIFFtype][] = $chunkdata;
       
   121 							break;
       
   122 
       
   123 						case 'JUNK':
       
   124 							// ignore
       
   125 							$thisfile_riff[$nextRIFFheaderID][] = $chunkdata;
       
   126 							break;
       
   127 
       
   128 						case 'IDVX':
       
   129 							$info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunkdata['size']));
       
   130 							break;
       
   131 
       
   132 						default:
       
   133 							if ($info['filesize'] == ($chunkdata['offset'] - 8 + 128)) {
       
   134 								$DIVXTAG = $nextRIFFheader.$this->fread(128 - 12);
       
   135 								if (substr($DIVXTAG, -7) == 'DIVXTAG') {
       
   136 									// DIVXTAG is supposed to be inside an IDVX chunk in a LIST chunk, but some bad encoders just slap it on the end of a file
       
   137 									$this->warning('Found wrongly-structured DIVXTAG at offset '.($this->ftell() - 128).', parsing anyway');
       
   138 									$info['divxtag']['comments'] = self::ParseDIVXTAG($DIVXTAG);
       
   139 									break 2;
       
   140 								}
       
   141 							}
       
   142 							$this->warning('Expecting "RIFF|JUNK|IDVX" at '.$nextRIFFoffset.', found "'.$nextRIFFheaderID.'" ('.getid3_lib::PrintHexBytes($nextRIFFheaderID).') - skipping rest of file');
       
   143 							break 2;
       
   144 
       
   145 					}
       
   146 
       
   147 				}
       
   148 				if ($RIFFsubtype == 'WAVE') {
       
   149 					$thisfile_riff_WAVE = &$thisfile_riff['WAVE'];
       
   150 				}
       
   151 				break;
       
   152 
       
   153 			default:
       
   154 				$this->error('Cannot parse RIFF (this is maybe not a RIFF / WAV / AVI file?) - expecting "FORM|RIFF|SDSS|RMP3" found "'.$RIFFsubtype.'" instead');
       
   155 				unset($info['fileformat']);
       
   156 				return false;
       
   157 		}
       
   158 
       
   159 		$streamindex = 0;
       
   160 		switch ($RIFFsubtype) {
       
   161 			case 'WAVE':
       
   162 				if (empty($thisfile_audio['bitrate_mode'])) {
       
   163 					$thisfile_audio['bitrate_mode'] = 'cbr';
       
   164 				}
       
   165 				if (empty($thisfile_audio_dataformat)) {
       
   166 					$thisfile_audio_dataformat = 'wav';
       
   167 				}
       
   168 
       
   169 				if (isset($thisfile_riff_WAVE['data'][0]['offset'])) {
       
   170 					$info['avdataoffset'] = $thisfile_riff_WAVE['data'][0]['offset'] + 8;
       
   171 					$info['avdataend']    = $info['avdataoffset'] + $thisfile_riff_WAVE['data'][0]['size'];
       
   172 				}
       
   173 				if (isset($thisfile_riff_WAVE['fmt '][0]['data'])) {
       
   174 
       
   175 					$thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($thisfile_riff_WAVE['fmt '][0]['data']);
       
   176 					$thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
       
   177 					if (!isset($thisfile_riff_audio[$streamindex]['bitrate']) || ($thisfile_riff_audio[$streamindex]['bitrate'] == 0)) {
       
   178 						$info['error'][] = 'Corrupt RIFF file: bitrate_audio == zero';
       
   179 						return false;
       
   180 					}
       
   181 					$thisfile_riff_raw['fmt '] = $thisfile_riff_audio[$streamindex]['raw'];
       
   182 					unset($thisfile_riff_audio[$streamindex]['raw']);
       
   183 					$thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
       
   184 
       
   185 					$thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
       
   186 					if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') {
       
   187 						$info['warning'][] = 'Audio codec = '.$thisfile_audio['codec'];
       
   188 					}
       
   189 					$thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
       
   190 
       
   191 					if (empty($info['playtime_seconds'])) { // may already be set (e.g. DTS-WAV)
       
   192 						$info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $thisfile_audio['bitrate']);
       
   193 					}
       
   194 
       
   195 					$thisfile_audio['lossless'] = false;
       
   196 					if (isset($thisfile_riff_WAVE['data'][0]['offset']) && isset($thisfile_riff_raw['fmt ']['wFormatTag'])) {
       
   197 						switch ($thisfile_riff_raw['fmt ']['wFormatTag']) {
       
   198 
       
   199 							case 0x0001:  // PCM
       
   200 								$thisfile_audio['lossless'] = true;
       
   201 								break;
       
   202 
       
   203 							case 0x2000:  // AC-3
       
   204 								$thisfile_audio_dataformat = 'ac3';
       
   205 								break;
       
   206 
       
   207 							default:
       
   208 								// do nothing
       
   209 								break;
       
   210 
       
   211 						}
       
   212 					}
       
   213 					$thisfile_audio['streams'][$streamindex]['wformattag']   = $thisfile_audio['wformattag'];
       
   214 					$thisfile_audio['streams'][$streamindex]['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
       
   215 					$thisfile_audio['streams'][$streamindex]['lossless']     = $thisfile_audio['lossless'];
       
   216 					$thisfile_audio['streams'][$streamindex]['dataformat']   = $thisfile_audio_dataformat;
       
   217 				}
       
   218 
       
   219 				if (isset($thisfile_riff_WAVE['rgad'][0]['data'])) {
       
   220 
       
   221 					// shortcuts
       
   222 					$rgadData = &$thisfile_riff_WAVE['rgad'][0]['data'];
       
   223 					$thisfile_riff_raw['rgad']    = array('track'=>array(), 'album'=>array());
       
   224 					$thisfile_riff_raw_rgad       = &$thisfile_riff_raw['rgad'];
       
   225 					$thisfile_riff_raw_rgad_track = &$thisfile_riff_raw_rgad['track'];
       
   226 					$thisfile_riff_raw_rgad_album = &$thisfile_riff_raw_rgad['album'];
       
   227 
       
   228 					$thisfile_riff_raw_rgad['fPeakAmplitude']      = getid3_lib::LittleEndian2Float(substr($rgadData, 0, 4));
       
   229 					$thisfile_riff_raw_rgad['nRadioRgAdjust']      =        $this->EitherEndian2Int(substr($rgadData, 4, 2));
       
   230 					$thisfile_riff_raw_rgad['nAudiophileRgAdjust'] =        $this->EitherEndian2Int(substr($rgadData, 6, 2));
       
   231 
       
   232 					$nRadioRgAdjustBitstring      = str_pad(getid3_lib::Dec2Bin($thisfile_riff_raw_rgad['nRadioRgAdjust']), 16, '0', STR_PAD_LEFT);
       
   233 					$nAudiophileRgAdjustBitstring = str_pad(getid3_lib::Dec2Bin($thisfile_riff_raw_rgad['nAudiophileRgAdjust']), 16, '0', STR_PAD_LEFT);
       
   234 					$thisfile_riff_raw_rgad_track['name']       = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 0, 3));
       
   235 					$thisfile_riff_raw_rgad_track['originator'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 3, 3));
       
   236 					$thisfile_riff_raw_rgad_track['signbit']    = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 6, 1));
       
   237 					$thisfile_riff_raw_rgad_track['adjustment'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 7, 9));
       
   238 					$thisfile_riff_raw_rgad_album['name']       = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 0, 3));
       
   239 					$thisfile_riff_raw_rgad_album['originator'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 3, 3));
       
   240 					$thisfile_riff_raw_rgad_album['signbit']    = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 6, 1));
       
   241 					$thisfile_riff_raw_rgad_album['adjustment'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 7, 9));
       
   242 
       
   243 					$thisfile_riff['rgad']['peakamplitude'] = $thisfile_riff_raw_rgad['fPeakAmplitude'];
       
   244 					if (($thisfile_riff_raw_rgad_track['name'] != 0) && ($thisfile_riff_raw_rgad_track['originator'] != 0)) {
       
   245 						$thisfile_riff['rgad']['track']['name']            = getid3_lib::RGADnameLookup($thisfile_riff_raw_rgad_track['name']);
       
   246 						$thisfile_riff['rgad']['track']['originator']      = getid3_lib::RGADoriginatorLookup($thisfile_riff_raw_rgad_track['originator']);
       
   247 						$thisfile_riff['rgad']['track']['adjustment']      = getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_track['adjustment'], $thisfile_riff_raw_rgad_track['signbit']);
       
   248 					}
       
   249 					if (($thisfile_riff_raw_rgad_album['name'] != 0) && ($thisfile_riff_raw_rgad_album['originator'] != 0)) {
       
   250 						$thisfile_riff['rgad']['album']['name']       = getid3_lib::RGADnameLookup($thisfile_riff_raw_rgad_album['name']);
       
   251 						$thisfile_riff['rgad']['album']['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_riff_raw_rgad_album['originator']);
       
   252 						$thisfile_riff['rgad']['album']['adjustment'] = getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_album['adjustment'], $thisfile_riff_raw_rgad_album['signbit']);
       
   253 					}
       
   254 				}
       
   255 
       
   256 				if (isset($thisfile_riff_WAVE['fact'][0]['data'])) {
       
   257 					$thisfile_riff_raw['fact']['NumberOfSamples'] = $this->EitherEndian2Int(substr($thisfile_riff_WAVE['fact'][0]['data'], 0, 4));
       
   258 
       
   259 					// This should be a good way of calculating exact playtime,
       
   260 					// but some sample files have had incorrect number of samples,
       
   261 					// so cannot use this method
       
   262 
       
   263 					// if (!empty($thisfile_riff_raw['fmt ']['nSamplesPerSec'])) {
       
   264 					//     $info['playtime_seconds'] = (float) $thisfile_riff_raw['fact']['NumberOfSamples'] / $thisfile_riff_raw['fmt ']['nSamplesPerSec'];
       
   265 					// }
       
   266 				}
       
   267 				if (!empty($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'])) {
       
   268 					$thisfile_audio['bitrate'] = getid3_lib::CastAsInt($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'] * 8);
       
   269 				}
       
   270 
       
   271 				if (isset($thisfile_riff_WAVE['bext'][0]['data'])) {
       
   272 					// shortcut
       
   273 					$thisfile_riff_WAVE_bext_0 = &$thisfile_riff_WAVE['bext'][0];
       
   274 
       
   275 					$thisfile_riff_WAVE_bext_0['title']          =                         trim(substr($thisfile_riff_WAVE_bext_0['data'],   0, 256));
       
   276 					$thisfile_riff_WAVE_bext_0['author']         =                         trim(substr($thisfile_riff_WAVE_bext_0['data'], 256,  32));
       
   277 					$thisfile_riff_WAVE_bext_0['reference']      =                         trim(substr($thisfile_riff_WAVE_bext_0['data'], 288,  32));
       
   278 					$thisfile_riff_WAVE_bext_0['origin_date']    =                              substr($thisfile_riff_WAVE_bext_0['data'], 320,  10);
       
   279 					$thisfile_riff_WAVE_bext_0['origin_time']    =                              substr($thisfile_riff_WAVE_bext_0['data'], 330,   8);
       
   280 					$thisfile_riff_WAVE_bext_0['time_reference'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 338,   8));
       
   281 					$thisfile_riff_WAVE_bext_0['bwf_version']    = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 346,   1));
       
   282 					$thisfile_riff_WAVE_bext_0['reserved']       =                              substr($thisfile_riff_WAVE_bext_0['data'], 347, 254);
       
   283 					$thisfile_riff_WAVE_bext_0['coding_history'] =         explode("\r\n", trim(substr($thisfile_riff_WAVE_bext_0['data'], 601)));
       
   284 					if (preg_match('#^([0-9]{4}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_date'], $matches_bext_date)) {
       
   285 						if (preg_match('#^([0-9]{2}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_time'], $matches_bext_time)) {
       
   286 							list($dummy, $bext_timestamp['year'], $bext_timestamp['month'],  $bext_timestamp['day'])    = $matches_bext_date;
       
   287 							list($dummy, $bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second']) = $matches_bext_time;
       
   288 							$thisfile_riff_WAVE_bext_0['origin_date_unix'] = gmmktime($bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second'], $bext_timestamp['month'], $bext_timestamp['day'], $bext_timestamp['year']);
       
   289 						} else {
       
   290 							$info['warning'][] = 'RIFF.WAVE.BEXT.origin_time is invalid';
       
   291 						}
       
   292 					} else {
       
   293 						$info['warning'][] = 'RIFF.WAVE.BEXT.origin_date is invalid';
       
   294 					}
       
   295 					$thisfile_riff['comments']['author'][] = $thisfile_riff_WAVE_bext_0['author'];
       
   296 					$thisfile_riff['comments']['title'][]  = $thisfile_riff_WAVE_bext_0['title'];
       
   297 				}
       
   298 
       
   299 				if (isset($thisfile_riff_WAVE['MEXT'][0]['data'])) {
       
   300 					// shortcut
       
   301 					$thisfile_riff_WAVE_MEXT_0 = &$thisfile_riff_WAVE['MEXT'][0];
       
   302 
       
   303 					$thisfile_riff_WAVE_MEXT_0['raw']['sound_information']      = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 0, 2));
       
   304 					$thisfile_riff_WAVE_MEXT_0['flags']['homogenous']           = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0001);
       
   305 					if ($thisfile_riff_WAVE_MEXT_0['flags']['homogenous']) {
       
   306 						$thisfile_riff_WAVE_MEXT_0['flags']['padding']          = ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0002) ? false : true;
       
   307 						$thisfile_riff_WAVE_MEXT_0['flags']['22_or_44']         =        (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0004);
       
   308 						$thisfile_riff_WAVE_MEXT_0['flags']['free_format']      =        (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x0008);
       
   309 
       
   310 						$thisfile_riff_WAVE_MEXT_0['nominal_frame_size']        = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 2, 2));
       
   311 					}
       
   312 					$thisfile_riff_WAVE_MEXT_0['anciliary_data_length']         = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 6, 2));
       
   313 					$thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def']     = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 8, 2));
       
   314 					$thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_left']  = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0001);
       
   315 					$thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_free']  = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0002);
       
   316 					$thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_right'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x0004);
       
   317 				}
       
   318 
       
   319 				if (isset($thisfile_riff_WAVE['cart'][0]['data'])) {
       
   320 					// shortcut
       
   321 					$thisfile_riff_WAVE_cart_0 = &$thisfile_riff_WAVE['cart'][0];
       
   322 
       
   323 					$thisfile_riff_WAVE_cart_0['version']              =                              substr($thisfile_riff_WAVE_cart_0['data'],   0,  4);
       
   324 					$thisfile_riff_WAVE_cart_0['title']                =                         trim(substr($thisfile_riff_WAVE_cart_0['data'],   4, 64));
       
   325 					$thisfile_riff_WAVE_cart_0['artist']               =                         trim(substr($thisfile_riff_WAVE_cart_0['data'],  68, 64));
       
   326 					$thisfile_riff_WAVE_cart_0['cut_id']               =                         trim(substr($thisfile_riff_WAVE_cart_0['data'], 132, 64));
       
   327 					$thisfile_riff_WAVE_cart_0['client_id']            =                         trim(substr($thisfile_riff_WAVE_cart_0['data'], 196, 64));
       
   328 					$thisfile_riff_WAVE_cart_0['category']             =                         trim(substr($thisfile_riff_WAVE_cart_0['data'], 260, 64));
       
   329 					$thisfile_riff_WAVE_cart_0['classification']       =                         trim(substr($thisfile_riff_WAVE_cart_0['data'], 324, 64));
       
   330 					$thisfile_riff_WAVE_cart_0['out_cue']              =                         trim(substr($thisfile_riff_WAVE_cart_0['data'], 388, 64));
       
   331 					$thisfile_riff_WAVE_cart_0['start_date']           =                         trim(substr($thisfile_riff_WAVE_cart_0['data'], 452, 10));
       
   332 					$thisfile_riff_WAVE_cart_0['start_time']           =                         trim(substr($thisfile_riff_WAVE_cart_0['data'], 462,  8));
       
   333 					$thisfile_riff_WAVE_cart_0['end_date']             =                         trim(substr($thisfile_riff_WAVE_cart_0['data'], 470, 10));
       
   334 					$thisfile_riff_WAVE_cart_0['end_time']             =                         trim(substr($thisfile_riff_WAVE_cart_0['data'], 480,  8));
       
   335 					$thisfile_riff_WAVE_cart_0['producer_app_id']      =                         trim(substr($thisfile_riff_WAVE_cart_0['data'], 488, 64));
       
   336 					$thisfile_riff_WAVE_cart_0['producer_app_version'] =                         trim(substr($thisfile_riff_WAVE_cart_0['data'], 552, 64));
       
   337 					$thisfile_riff_WAVE_cart_0['user_defined_text']    =                         trim(substr($thisfile_riff_WAVE_cart_0['data'], 616, 64));
       
   338 					$thisfile_riff_WAVE_cart_0['zero_db_reference']    = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_cart_0['data'], 680,  4), true);
       
   339 					for ($i = 0; $i < 8; $i++) {
       
   340 						$thisfile_riff_WAVE_cart_0['post_time'][$i]['usage_fourcc'] =                  substr($thisfile_riff_WAVE_cart_0['data'], 684 + ($i * 8), 4);
       
   341 						$thisfile_riff_WAVE_cart_0['post_time'][$i]['timer_value']  = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_cart_0['data'], 684 + ($i * 8) + 4, 4));
       
   342 					}
       
   343 					$thisfile_riff_WAVE_cart_0['url']              =                 trim(substr($thisfile_riff_WAVE_cart_0['data'],  748, 1024));
       
   344 					$thisfile_riff_WAVE_cart_0['tag_text']         = explode("\r\n", trim(substr($thisfile_riff_WAVE_cart_0['data'], 1772)));
       
   345 
       
   346 					$thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist'];
       
   347 					$thisfile_riff['comments']['title'][]  = $thisfile_riff_WAVE_cart_0['title'];
       
   348 				}
       
   349 
       
   350 				if (isset($thisfile_riff_WAVE['SNDM'][0]['data'])) {
       
   351 					// SoundMiner metadata
       
   352 
       
   353 					// shortcuts
       
   354 					$thisfile_riff_WAVE_SNDM_0      = &$thisfile_riff_WAVE['SNDM'][0];
       
   355 					$thisfile_riff_WAVE_SNDM_0_data = &$thisfile_riff_WAVE_SNDM_0['data'];
       
   356 					$SNDM_startoffset = 0;
       
   357 					$SNDM_endoffset   = $thisfile_riff_WAVE_SNDM_0['size'];
       
   358 
       
   359 					while ($SNDM_startoffset < $SNDM_endoffset) {
       
   360 						$SNDM_thisTagOffset = 0;
       
   361 						$SNDM_thisTagSize      = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4));
       
   362 						$SNDM_thisTagOffset += 4;
       
   363 						$SNDM_thisTagKey       =                           substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4);
       
   364 						$SNDM_thisTagOffset += 4;
       
   365 						$SNDM_thisTagDataSize  = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2));
       
   366 						$SNDM_thisTagOffset += 2;
       
   367 						$SNDM_thisTagDataFlags = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2));
       
   368 						$SNDM_thisTagOffset += 2;
       
   369 						$SNDM_thisTagDataText =                            substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, $SNDM_thisTagDataSize);
       
   370 						$SNDM_thisTagOffset += $SNDM_thisTagDataSize;
       
   371 
       
   372 						if ($SNDM_thisTagSize != (4 + 4 + 2 + 2 + $SNDM_thisTagDataSize)) {
       
   373 							$info['warning'][] = 'RIFF.WAVE.SNDM.data contains tag not expected length (expected: '.$SNDM_thisTagSize.', found: '.(4 + 4 + 2 + 2 + $SNDM_thisTagDataSize).') at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')';
       
   374 							break;
       
   375 						} elseif ($SNDM_thisTagSize <= 0) {
       
   376 							$info['warning'][] = 'RIFF.WAVE.SNDM.data contains zero-size tag at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')';
       
   377 							break;
       
   378 						}
       
   379 						$SNDM_startoffset += $SNDM_thisTagSize;
       
   380 
       
   381 						$thisfile_riff_WAVE_SNDM_0['parsed_raw'][$SNDM_thisTagKey] = $SNDM_thisTagDataText;
       
   382 						if ($parsedkey = self::waveSNDMtagLookup($SNDM_thisTagKey)) {
       
   383 							$thisfile_riff_WAVE_SNDM_0['parsed'][$parsedkey] = $SNDM_thisTagDataText;
       
   384 						} else {
       
   385 							$info['warning'][] = 'RIFF.WAVE.SNDM contains unknown tag "'.$SNDM_thisTagKey.'" at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')';
       
   386 						}
       
   387 					}
       
   388 
       
   389 					$tagmapping = array(
       
   390 						'tracktitle'=>'title',
       
   391 						'category'  =>'genre',
       
   392 						'cdtitle'   =>'album',
       
   393 						'tracktitle'=>'title',
       
   394 					);
       
   395 					foreach ($tagmapping as $fromkey => $tokey) {
       
   396 						if (isset($thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey])) {
       
   397 							$thisfile_riff['comments'][$tokey][] = $thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey];
       
   398 						}
       
   399 					}
       
   400 				}
       
   401 
       
   402 				if (isset($thisfile_riff_WAVE['iXML'][0]['data'])) {
       
   403 					// requires functions simplexml_load_string and get_object_vars
       
   404 					if ($parsedXML = getid3_lib::XML2array($thisfile_riff_WAVE['iXML'][0]['data'])) {
       
   405 						$thisfile_riff_WAVE['iXML'][0]['parsed'] = $parsedXML;
       
   406 						if (isset($parsedXML['SPEED']['MASTER_SPEED'])) {
       
   407 							@list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['MASTER_SPEED']);
       
   408 							$thisfile_riff_WAVE['iXML'][0]['master_speed'] = $numerator / ($denominator ? $denominator : 1000);
       
   409 						}
       
   410 						if (isset($parsedXML['SPEED']['TIMECODE_RATE'])) {
       
   411 							@list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['TIMECODE_RATE']);
       
   412 							$thisfile_riff_WAVE['iXML'][0]['timecode_rate'] = $numerator / ($denominator ? $denominator : 1000);
       
   413 						}
       
   414 						if (isset($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO']) && !empty($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) && !empty($thisfile_riff_WAVE['iXML'][0]['timecode_rate'])) {
       
   415 							$samples_since_midnight = floatval(ltrim($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_HI'].$parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO'], '0'));
       
   416 							$thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] = $samples_since_midnight / $parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE'];
       
   417 							$h = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds']       / 3600);
       
   418 							$m = floor(($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600))      / 60);
       
   419 							$s = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60));
       
   420 							$f =       ($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60) - $s) * $thisfile_riff_WAVE['iXML'][0]['timecode_rate'];
       
   421 							$thisfile_riff_WAVE['iXML'][0]['timecode_string']       = sprintf('%02d:%02d:%02d:%05.2f', $h, $m, $s,       $f);
       
   422 							$thisfile_riff_WAVE['iXML'][0]['timecode_string_round'] = sprintf('%02d:%02d:%02d:%02d',   $h, $m, $s, round($f));
       
   423 						}
       
   424 						unset($parsedXML);
       
   425 					}
       
   426 				}
       
   427 
       
   428 
       
   429 
       
   430 				if (!isset($thisfile_audio['bitrate']) && isset($thisfile_riff_audio[$streamindex]['bitrate'])) {
       
   431 					$thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
       
   432 					$info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $thisfile_audio['bitrate']);
       
   433 				}
       
   434 
       
   435 				if (!empty($info['wavpack'])) {
       
   436 					$thisfile_audio_dataformat = 'wavpack';
       
   437 					$thisfile_audio['bitrate_mode'] = 'vbr';
       
   438 					$thisfile_audio['encoder']      = 'WavPack v'.$info['wavpack']['version'];
       
   439 
       
   440 					// Reset to the way it was - RIFF parsing will have messed this up
       
   441 					$info['avdataend']        = $Original['avdataend'];
       
   442 					$thisfile_audio['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
       
   443 
       
   444 					$this->fseek($info['avdataoffset'] - 44);
       
   445 					$RIFFdata = $this->fread(44);
       
   446 					$OrignalRIFFheaderSize = getid3_lib::LittleEndian2Int(substr($RIFFdata,  4, 4)) +  8;
       
   447 					$OrignalRIFFdataSize   = getid3_lib::LittleEndian2Int(substr($RIFFdata, 40, 4)) + 44;
       
   448 
       
   449 					if ($OrignalRIFFheaderSize > $OrignalRIFFdataSize) {
       
   450 						$info['avdataend'] -= ($OrignalRIFFheaderSize - $OrignalRIFFdataSize);
       
   451 						$this->fseek($info['avdataend']);
       
   452 						$RIFFdata .= $this->fread($OrignalRIFFheaderSize - $OrignalRIFFdataSize);
       
   453 					}
       
   454 
       
   455 					// move the data chunk after all other chunks (if any)
       
   456 					// so that the RIFF parser doesn't see EOF when trying
       
   457 					// to skip over the data chunk
       
   458 					$RIFFdata = substr($RIFFdata, 0, 36).substr($RIFFdata, 44).substr($RIFFdata, 36, 8);
       
   459 					$getid3_riff = new getid3_riff($this->getid3);
       
   460 					$getid3_riff->ParseRIFFdata($RIFFdata);
       
   461 					unset($getid3_riff);
       
   462 				}
       
   463 
       
   464 				if (isset($thisfile_riff_raw['fmt ']['wFormatTag'])) {
       
   465 					switch ($thisfile_riff_raw['fmt ']['wFormatTag']) {
       
   466 						case 0x0001: // PCM
       
   467 							if (!empty($info['ac3'])) {
       
   468 								// Dolby Digital WAV files masquerade as PCM-WAV, but they're not
       
   469 								$thisfile_audio['wformattag']  = 0x2000;
       
   470 								$thisfile_audio['codec']       = self::wFormatTagLookup($thisfile_audio['wformattag']);
       
   471 								$thisfile_audio['lossless']    = false;
       
   472 								$thisfile_audio['bitrate']     = $info['ac3']['bitrate'];
       
   473 								$thisfile_audio['sample_rate'] = $info['ac3']['sample_rate'];
       
   474 							}
       
   475 							if (!empty($info['dts'])) {
       
   476 								// Dolby DTS files masquerade as PCM-WAV, but they're not
       
   477 								$thisfile_audio['wformattag']  = 0x2001;
       
   478 								$thisfile_audio['codec']       = self::wFormatTagLookup($thisfile_audio['wformattag']);
       
   479 								$thisfile_audio['lossless']    = false;
       
   480 								$thisfile_audio['bitrate']     = $info['dts']['bitrate'];
       
   481 								$thisfile_audio['sample_rate'] = $info['dts']['sample_rate'];
       
   482 							}
       
   483 							break;
       
   484 						case 0x08AE: // ClearJump LiteWave
       
   485 							$thisfile_audio['bitrate_mode'] = 'vbr';
       
   486 							$thisfile_audio_dataformat   = 'litewave';
       
   487 
       
   488 							//typedef struct tagSLwFormat {
       
   489 							//  WORD    m_wCompFormat;     // low byte defines compression method, high byte is compression flags
       
   490 							//  DWORD   m_dwScale;         // scale factor for lossy compression
       
   491 							//  DWORD   m_dwBlockSize;     // number of samples in encoded blocks
       
   492 							//  WORD    m_wQuality;        // alias for the scale factor
       
   493 							//  WORD    m_wMarkDistance;   // distance between marks in bytes
       
   494 							//  WORD    m_wReserved;
       
   495 							//
       
   496 							//  //following paramters are ignored if CF_FILESRC is not set
       
   497 							//  DWORD   m_dwOrgSize;       // original file size in bytes
       
   498 							//  WORD    m_bFactExists;     // indicates if 'fact' chunk exists in the original file
       
   499 							//  DWORD   m_dwRiffChunkSize; // riff chunk size in the original file
       
   500 							//
       
   501 							//  PCMWAVEFORMAT m_OrgWf;     // original wave format
       
   502 							// }SLwFormat, *PSLwFormat;
       
   503 
       
   504 							// shortcut
       
   505 							$thisfile_riff['litewave']['raw'] = array();
       
   506 							$riff_litewave     = &$thisfile_riff['litewave'];
       
   507 							$riff_litewave_raw = &$riff_litewave['raw'];
       
   508 
       
   509 							$flags = array(
       
   510 								'compression_method' => 1,
       
   511 								'compression_flags'  => 1,
       
   512 								'm_dwScale'          => 4,
       
   513 								'm_dwBlockSize'      => 4,
       
   514 								'm_wQuality'         => 2,
       
   515 								'm_wMarkDistance'    => 2,
       
   516 								'm_wReserved'        => 2,
       
   517 								'm_dwOrgSize'        => 4,
       
   518 								'm_bFactExists'      => 2,
       
   519 								'm_dwRiffChunkSize'  => 4,
       
   520 							);
       
   521 							$litewave_offset = 18;
       
   522 							foreach ($flags as $flag => $length) {
       
   523 								$riff_litewave_raw[$flag] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE['fmt '][0]['data'], $litewave_offset, $length));
       
   524 								$litewave_offset += $length;
       
   525 							}
       
   526 
       
   527 							//$riff_litewave['quality_factor'] = intval(round((2000 - $riff_litewave_raw['m_dwScale']) / 20));
       
   528 							$riff_litewave['quality_factor'] = $riff_litewave_raw['m_wQuality'];
       
   529 
       
   530 							$riff_litewave['flags']['raw_source']    = ($riff_litewave_raw['compression_flags'] & 0x01) ? false : true;
       
   531 							$riff_litewave['flags']['vbr_blocksize'] = ($riff_litewave_raw['compression_flags'] & 0x02) ? false : true;
       
   532 							$riff_litewave['flags']['seekpoints']    =        (bool) ($riff_litewave_raw['compression_flags'] & 0x04);
       
   533 
       
   534 							$thisfile_audio['lossless']        = (($riff_litewave_raw['m_wQuality'] == 100) ? true : false);
       
   535 							$thisfile_audio['encoder_options'] = '-q'.$riff_litewave['quality_factor'];
       
   536 							break;
       
   537 
       
   538 						default:
       
   539 							break;
       
   540 					}
       
   541 				}
       
   542 				if ($info['avdataend'] > $info['filesize']) {
       
   543 					switch (!empty($thisfile_audio_dataformat) ? $thisfile_audio_dataformat : '') {
       
   544 						case 'wavpack': // WavPack
       
   545 						case 'lpac':    // LPAC
       
   546 						case 'ofr':     // OptimFROG
       
   547 						case 'ofs':     // OptimFROG DualStream
       
   548 							// lossless compressed audio formats that keep original RIFF headers - skip warning
       
   549 							break;
       
   550 
       
   551 						case 'litewave':
       
   552 							if (($info['avdataend'] - $info['filesize']) == 1) {
       
   553 								// LiteWave appears to incorrectly *not* pad actual output file
       
   554 								// to nearest WORD boundary so may appear to be short by one
       
   555 								// byte, in which case - skip warning
       
   556 							} else {
       
   557 								// Short by more than one byte, throw warning
       
   558 								$info['warning'][] = 'Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)';
       
   559 								$info['avdataend'] = $info['filesize'];
       
   560 							}
       
   561 							break;
       
   562 
       
   563 						default:
       
   564 							if ((($info['avdataend'] - $info['filesize']) == 1) && (($thisfile_riff[$RIFFsubtype]['data'][0]['size'] % 2) == 0) && ((($info['filesize'] - $info['avdataoffset']) % 2) == 1)) {
       
   565 								// output file appears to be incorrectly *not* padded to nearest WORD boundary
       
   566 								// Output less severe warning
       
   567 								$info['warning'][] = 'File should probably be padded to nearest WORD boundary, but it is not (expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' therefore short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)';
       
   568 								$info['avdataend'] = $info['filesize'];
       
   569 							} else {
       
   570 								// Short by more than one byte, throw warning
       
   571 								$info['warning'][] = 'Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)';
       
   572 								$info['avdataend'] = $info['filesize'];
       
   573 							}
       
   574 							break;
       
   575 					}
       
   576 				}
       
   577 				if (!empty($info['mpeg']['audio']['LAME']['audio_bytes'])) {
       
   578 					if ((($info['avdataend'] - $info['avdataoffset']) - $info['mpeg']['audio']['LAME']['audio_bytes']) == 1) {
       
   579 						$info['avdataend']--;
       
   580 						$info['warning'][] = 'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored';
       
   581 					}
       
   582 				}
       
   583 				if (isset($thisfile_audio_dataformat) && ($thisfile_audio_dataformat == 'ac3')) {
       
   584 					unset($thisfile_audio['bits_per_sample']);
       
   585 					if (!empty($info['ac3']['bitrate']) && ($info['ac3']['bitrate'] != $thisfile_audio['bitrate'])) {
       
   586 						$thisfile_audio['bitrate'] = $info['ac3']['bitrate'];
       
   587 					}
       
   588 				}
       
   589 				break;
       
   590 
       
   591 			case 'AVI ':
       
   592 				$thisfile_video['bitrate_mode'] = 'vbr'; // maybe not, but probably
       
   593 				$thisfile_video['dataformat']   = 'avi';
       
   594 				$info['mime_type']      = 'video/avi';
       
   595 
       
   596 				if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) {
       
   597 					$info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['movi']['offset'] + 8;
       
   598 					if (isset($thisfile_riff['AVIX'])) {
       
   599 						$info['avdataend'] = $thisfile_riff['AVIX'][(count($thisfile_riff['AVIX']) - 1)]['chunks']['movi']['offset'] + $thisfile_riff['AVIX'][(count($thisfile_riff['AVIX']) - 1)]['chunks']['movi']['size'];
       
   600 					} else {
       
   601 						$info['avdataend'] = $thisfile_riff['AVI ']['movi']['offset'] + $thisfile_riff['AVI ']['movi']['size'];
       
   602 					}
       
   603 					if ($info['avdataend'] > $info['filesize']) {
       
   604 						$info['warning'][] = 'Probably truncated file - expecting '.($info['avdataend'] - $info['avdataoffset']).' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($info['avdataend'] - $info['filesize']).' bytes)';
       
   605 						$info['avdataend'] = $info['filesize'];
       
   606 					}
       
   607 				}
       
   608 
       
   609 				if (isset($thisfile_riff['AVI ']['hdrl']['strl']['indx'])) {
       
   610 					//$bIndexType = array(
       
   611 					//	0x00 => 'AVI_INDEX_OF_INDEXES',
       
   612 					//	0x01 => 'AVI_INDEX_OF_CHUNKS',
       
   613 					//	0x80 => 'AVI_INDEX_IS_DATA',
       
   614 					//);
       
   615 					//$bIndexSubtype = array(
       
   616 					//	0x01 => array(
       
   617 					//		0x01 => 'AVI_INDEX_2FIELD',
       
   618 					//	),
       
   619 					//);
       
   620 					foreach ($thisfile_riff['AVI ']['hdrl']['strl']['indx'] as $streamnumber => $steamdataarray) {
       
   621 						$ahsisd = &$thisfile_riff['AVI ']['hdrl']['strl']['indx'][$streamnumber]['data'];
       
   622 
       
   623 						$thisfile_riff_raw['indx'][$streamnumber]['wLongsPerEntry'] = $this->EitherEndian2Int(substr($ahsisd,  0, 2));
       
   624 						$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType']  = $this->EitherEndian2Int(substr($ahsisd,  2, 1));
       
   625 						$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']     = $this->EitherEndian2Int(substr($ahsisd,  3, 1));
       
   626 						$thisfile_riff_raw['indx'][$streamnumber]['nEntriesInUse']  = $this->EitherEndian2Int(substr($ahsisd,  4, 4));
       
   627 						$thisfile_riff_raw['indx'][$streamnumber]['dwChunkId']      =                         substr($ahsisd,  8, 4);
       
   628 						$thisfile_riff_raw['indx'][$streamnumber]['dwReserved']     = $this->EitherEndian2Int(substr($ahsisd, 12, 4));
       
   629 
       
   630 						//$thisfile_riff_raw['indx'][$streamnumber]['bIndexType_name']    =    $bIndexType[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']];
       
   631 						//$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType_name'] = $bIndexSubtype[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']][$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType']];
       
   632 
       
   633 						unset($ahsisd);
       
   634 					}
       
   635 				}
       
   636 				if (isset($thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'])) {
       
   637 					$avihData = $thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'];
       
   638 
       
   639 					// shortcut
       
   640 					$thisfile_riff_raw['avih'] = array();
       
   641 					$thisfile_riff_raw_avih = &$thisfile_riff_raw['avih'];
       
   642 
       
   643 					$thisfile_riff_raw_avih['dwMicroSecPerFrame']    = $this->EitherEndian2Int(substr($avihData,  0, 4)); // frame display rate (or 0L)
       
   644 					if ($thisfile_riff_raw_avih['dwMicroSecPerFrame'] == 0) {
       
   645 						$info['error'][] = 'Corrupt RIFF file: avih.dwMicroSecPerFrame == zero';
       
   646 						return false;
       
   647 					}
       
   648 
       
   649 					$flags = array(
       
   650 						'dwMaxBytesPerSec',       // max. transfer rate
       
   651 						'dwPaddingGranularity',   // pad to multiples of this size; normally 2K.
       
   652 						'dwFlags',                // the ever-present flags
       
   653 						'dwTotalFrames',          // # frames in file
       
   654 						'dwInitialFrames',        //
       
   655 						'dwStreams',              //
       
   656 						'dwSuggestedBufferSize',  //
       
   657 						'dwWidth',                //
       
   658 						'dwHeight',               //
       
   659 						'dwScale',                //
       
   660 						'dwRate',                 //
       
   661 						'dwStart',                //
       
   662 						'dwLength',               //
       
   663 					);
       
   664 					$avih_offset = 4;
       
   665 					foreach ($flags as $flag) {
       
   666 						$thisfile_riff_raw_avih[$flag] = $this->EitherEndian2Int(substr($avihData, $avih_offset, 4));
       
   667 						$avih_offset += 4;
       
   668 					}
       
   669 
       
   670 					$flags = array(
       
   671 						'hasindex'     => 0x00000010,
       
   672 						'mustuseindex' => 0x00000020,
       
   673 						'interleaved'  => 0x00000100,
       
   674 						'trustcktype'  => 0x00000800,
       
   675 						'capturedfile' => 0x00010000,
       
   676 						'copyrighted'  => 0x00020010,
       
   677 					);
       
   678                     foreach ($flags as $flag => $value) {
       
   679 						$thisfile_riff_raw_avih['flags'][$flag] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & $value);
       
   680 					}
       
   681 
       
   682 					// shortcut
       
   683 					$thisfile_riff_video[$streamindex] = array();
       
   684 					$thisfile_riff_video_current = &$thisfile_riff_video[$streamindex];
       
   685 
       
   686 					if ($thisfile_riff_raw_avih['dwWidth'] > 0) {
       
   687 						$thisfile_riff_video_current['frame_width'] = $thisfile_riff_raw_avih['dwWidth'];
       
   688 						$thisfile_video['resolution_x']             = $thisfile_riff_video_current['frame_width'];
       
   689 					}
       
   690 					if ($thisfile_riff_raw_avih['dwHeight'] > 0) {
       
   691 						$thisfile_riff_video_current['frame_height'] = $thisfile_riff_raw_avih['dwHeight'];
       
   692 						$thisfile_video['resolution_y']              = $thisfile_riff_video_current['frame_height'];
       
   693 					}
       
   694 					if ($thisfile_riff_raw_avih['dwTotalFrames'] > 0) {
       
   695 						$thisfile_riff_video_current['total_frames'] = $thisfile_riff_raw_avih['dwTotalFrames'];
       
   696 						$thisfile_video['total_frames']              = $thisfile_riff_video_current['total_frames'];
       
   697 					}
       
   698 
       
   699 					$thisfile_riff_video_current['frame_rate'] = round(1000000 / $thisfile_riff_raw_avih['dwMicroSecPerFrame'], 3);
       
   700 					$thisfile_video['frame_rate'] = $thisfile_riff_video_current['frame_rate'];
       
   701 				}
       
   702 				if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][0]['data'])) {
       
   703 					if (is_array($thisfile_riff['AVI ']['hdrl']['strl']['strh'])) {
       
   704 						for ($i = 0; $i < count($thisfile_riff['AVI ']['hdrl']['strl']['strh']); $i++) {
       
   705 							if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'])) {
       
   706 								$strhData = $thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'];
       
   707 								$strhfccType = substr($strhData,  0, 4);
       
   708 
       
   709 								if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'])) {
       
   710 									$strfData = $thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'];
       
   711 
       
   712 									// shortcut
       
   713 									$thisfile_riff_raw_strf_strhfccType_streamindex = &$thisfile_riff_raw['strf'][$strhfccType][$streamindex];
       
   714 
       
   715 									switch ($strhfccType) {
       
   716 										case 'auds':
       
   717 											$thisfile_audio['bitrate_mode'] = 'cbr';
       
   718 											$thisfile_audio_dataformat      = 'wav';
       
   719 											if (isset($thisfile_riff_audio) && is_array($thisfile_riff_audio)) {
       
   720 												$streamindex = count($thisfile_riff_audio);
       
   721 											}
       
   722 
       
   723 											$thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($strfData);
       
   724 											$thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
       
   725 
       
   726 											// shortcut
       
   727 											$thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
       
   728 											$thisfile_audio_streams_currentstream = &$thisfile_audio['streams'][$streamindex];
       
   729 
       
   730 											if ($thisfile_audio_streams_currentstream['bits_per_sample'] == 0) {
       
   731 												unset($thisfile_audio_streams_currentstream['bits_per_sample']);
       
   732 											}
       
   733 											$thisfile_audio_streams_currentstream['wformattag'] = $thisfile_audio_streams_currentstream['raw']['wFormatTag'];
       
   734 											unset($thisfile_audio_streams_currentstream['raw']);
       
   735 
       
   736 											// shortcut
       
   737 											$thisfile_riff_raw['strf'][$strhfccType][$streamindex] = $thisfile_riff_audio[$streamindex]['raw'];
       
   738 
       
   739 											unset($thisfile_riff_audio[$streamindex]['raw']);
       
   740 											$thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
       
   741 
       
   742 											$thisfile_audio['lossless'] = false;
       
   743 											switch ($thisfile_riff_raw_strf_strhfccType_streamindex['wFormatTag']) {
       
   744 												case 0x0001:  // PCM
       
   745 													$thisfile_audio_dataformat  = 'wav';
       
   746 													$thisfile_audio['lossless'] = true;
       
   747 													break;
       
   748 
       
   749 												case 0x0050: // MPEG Layer 2 or Layer 1
       
   750 													$thisfile_audio_dataformat = 'mp2'; // Assume Layer-2
       
   751 													break;
       
   752 
       
   753 												case 0x0055: // MPEG Layer 3
       
   754 													$thisfile_audio_dataformat = 'mp3';
       
   755 													break;
       
   756 
       
   757 												case 0x00FF: // AAC
       
   758 													$thisfile_audio_dataformat = 'aac';
       
   759 													break;
       
   760 
       
   761 												case 0x0161: // Windows Media v7 / v8 / v9
       
   762 												case 0x0162: // Windows Media Professional v9
       
   763 												case 0x0163: // Windows Media Lossess v9
       
   764 													$thisfile_audio_dataformat = 'wma';
       
   765 													break;
       
   766 
       
   767 												case 0x2000: // AC-3
       
   768 													$thisfile_audio_dataformat = 'ac3';
       
   769 													break;
       
   770 
       
   771 												case 0x2001: // DTS
       
   772 													$thisfile_audio_dataformat = 'dts';
       
   773 													break;
       
   774 
       
   775 												default:
       
   776 													$thisfile_audio_dataformat = 'wav';
       
   777 													break;
       
   778 											}
       
   779 											$thisfile_audio_streams_currentstream['dataformat']   = $thisfile_audio_dataformat;
       
   780 											$thisfile_audio_streams_currentstream['lossless']     = $thisfile_audio['lossless'];
       
   781 											$thisfile_audio_streams_currentstream['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
       
   782 											break;
       
   783 
       
   784 
       
   785 										case 'iavs':
       
   786 										case 'vids':
       
   787 											// shortcut
       
   788 											$thisfile_riff_raw['strh'][$i]                  = array();
       
   789 											$thisfile_riff_raw_strh_current                 = &$thisfile_riff_raw['strh'][$i];
       
   790 
       
   791 											$thisfile_riff_raw_strh_current['fccType']               =                         substr($strhData,  0, 4);  // same as $strhfccType;
       
   792 											$thisfile_riff_raw_strh_current['fccHandler']            =                         substr($strhData,  4, 4);
       
   793 											$thisfile_riff_raw_strh_current['dwFlags']               = $this->EitherEndian2Int(substr($strhData,  8, 4)); // Contains AVITF_* flags
       
   794 											$thisfile_riff_raw_strh_current['wPriority']             = $this->EitherEndian2Int(substr($strhData, 12, 2));
       
   795 											$thisfile_riff_raw_strh_current['wLanguage']             = $this->EitherEndian2Int(substr($strhData, 14, 2));
       
   796 											$thisfile_riff_raw_strh_current['dwInitialFrames']       = $this->EitherEndian2Int(substr($strhData, 16, 4));
       
   797 											$thisfile_riff_raw_strh_current['dwScale']               = $this->EitherEndian2Int(substr($strhData, 20, 4));
       
   798 											$thisfile_riff_raw_strh_current['dwRate']                = $this->EitherEndian2Int(substr($strhData, 24, 4));
       
   799 											$thisfile_riff_raw_strh_current['dwStart']               = $this->EitherEndian2Int(substr($strhData, 28, 4));
       
   800 											$thisfile_riff_raw_strh_current['dwLength']              = $this->EitherEndian2Int(substr($strhData, 32, 4));
       
   801 											$thisfile_riff_raw_strh_current['dwSuggestedBufferSize'] = $this->EitherEndian2Int(substr($strhData, 36, 4));
       
   802 											$thisfile_riff_raw_strh_current['dwQuality']             = $this->EitherEndian2Int(substr($strhData, 40, 4));
       
   803 											$thisfile_riff_raw_strh_current['dwSampleSize']          = $this->EitherEndian2Int(substr($strhData, 44, 4));
       
   804 											$thisfile_riff_raw_strh_current['rcFrame']               = $this->EitherEndian2Int(substr($strhData, 48, 4));
       
   805 
       
   806 											$thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strh_current['fccHandler']);
       
   807 											$thisfile_video['fourcc']             = $thisfile_riff_raw_strh_current['fccHandler'];
       
   808 											if (!$thisfile_riff_video_current['codec'] && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) && self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
       
   809 												$thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']);
       
   810 												$thisfile_video['fourcc']             = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
       
   811 											}
       
   812 											$thisfile_video['codec']              = $thisfile_riff_video_current['codec'];
       
   813 											$thisfile_video['pixel_aspect_ratio'] = (float) 1;
       
   814 											switch ($thisfile_riff_raw_strh_current['fccHandler']) {
       
   815 												case 'HFYU': // Huffman Lossless Codec
       
   816 												case 'IRAW': // Intel YUV Uncompressed
       
   817 												case 'YUY2': // Uncompressed YUV 4:2:2
       
   818 													$thisfile_video['lossless'] = true;
       
   819 													break;
       
   820 
       
   821 												default:
       
   822 													$thisfile_video['lossless'] = false;
       
   823 													break;
       
   824 											}
       
   825 
       
   826 											switch ($strhfccType) {
       
   827 												case 'vids':
       
   828 													$thisfile_riff_raw_strf_strhfccType_streamindex = self::ParseBITMAPINFOHEADER(substr($strfData, 0, 40), ($info['fileformat'] == 'riff'));
       
   829 													$thisfile_video['bits_per_sample'] = $thisfile_riff_raw_strf_strhfccType_streamindex['biBitCount'];
       
   830 
       
   831 													if ($thisfile_riff_video_current['codec'] == 'DV') {
       
   832 														$thisfile_riff_video_current['dv_type'] = 2;
       
   833 													}
       
   834 													break;
       
   835 
       
   836 												case 'iavs':
       
   837 													$thisfile_riff_video_current['dv_type'] = 1;
       
   838 													break;
       
   839 											}
       
   840 											break;
       
   841 
       
   842 										default:
       
   843 											$info['warning'][] = 'Unhandled fccType for stream ('.$i.'): "'.$strhfccType.'"';
       
   844 											break;
       
   845 
       
   846 									}
       
   847 								}
       
   848 							}
       
   849 
       
   850 							if (isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
       
   851 
       
   852 								$thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
       
   853 								if (self::fourccLookup($thisfile_video['fourcc'])) {
       
   854 									$thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_video['fourcc']);
       
   855 									$thisfile_video['codec']              = $thisfile_riff_video_current['codec'];
       
   856 								}
       
   857 
       
   858 								switch ($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) {
       
   859 									case 'HFYU': // Huffman Lossless Codec
       
   860 									case 'IRAW': // Intel YUV Uncompressed
       
   861 									case 'YUY2': // Uncompressed YUV 4:2:2
       
   862 										$thisfile_video['lossless']        = true;
       
   863 										//$thisfile_video['bits_per_sample'] = 24;
       
   864 										break;
       
   865 
       
   866 									default:
       
   867 										$thisfile_video['lossless']        = false;
       
   868 										//$thisfile_video['bits_per_sample'] = 24;
       
   869 										break;
       
   870 								}
       
   871 
       
   872 							}
       
   873 						}
       
   874 					}
       
   875 				}
       
   876 				break;
       
   877 
       
   878 			case 'CDDA':
       
   879 				$thisfile_audio['bitrate_mode'] = 'cbr';
       
   880 				$thisfile_audio_dataformat      = 'cda';
       
   881 				$thisfile_audio['lossless']     = true;
       
   882 				unset($info['mime_type']);
       
   883 
       
   884 				$info['avdataoffset'] = 44;
       
   885 
       
   886 				if (isset($thisfile_riff['CDDA']['fmt '][0]['data'])) {
       
   887 					// shortcut
       
   888 					$thisfile_riff_CDDA_fmt_0 = &$thisfile_riff['CDDA']['fmt '][0];
       
   889 
       
   890 					$thisfile_riff_CDDA_fmt_0['unknown1']           = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'],  0, 2));
       
   891 					$thisfile_riff_CDDA_fmt_0['track_num']          = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'],  2, 2));
       
   892 					$thisfile_riff_CDDA_fmt_0['disc_id']            = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'],  4, 4));
       
   893 					$thisfile_riff_CDDA_fmt_0['start_offset_frame'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'],  8, 4));
       
   894 					$thisfile_riff_CDDA_fmt_0['playtime_frames']    = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 12, 4));
       
   895 					$thisfile_riff_CDDA_fmt_0['unknown6']           = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 16, 4));
       
   896 					$thisfile_riff_CDDA_fmt_0['unknown7']           = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 20, 4));
       
   897 
       
   898 					$thisfile_riff_CDDA_fmt_0['start_offset_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['start_offset_frame'] / 75;
       
   899 					$thisfile_riff_CDDA_fmt_0['playtime_seconds']     = (float) $thisfile_riff_CDDA_fmt_0['playtime_frames'] / 75;
       
   900 					$info['comments']['track']                = $thisfile_riff_CDDA_fmt_0['track_num'];
       
   901 					$info['playtime_seconds']                 = $thisfile_riff_CDDA_fmt_0['playtime_seconds'];
       
   902 
       
   903 					// hardcoded data for CD-audio
       
   904 					$thisfile_audio['sample_rate']     = 44100;
       
   905 					$thisfile_audio['channels']        = 2;
       
   906 					$thisfile_audio['bits_per_sample'] = 16;
       
   907 					$thisfile_audio['bitrate']         = $thisfile_audio['sample_rate'] * $thisfile_audio['channels'] * $thisfile_audio['bits_per_sample'];
       
   908 					$thisfile_audio['bitrate_mode']    = 'cbr';
       
   909 				}
       
   910 				break;
       
   911 
       
   912 
       
   913 			case 'AIFF':
       
   914 			case 'AIFC':
       
   915 				$thisfile_audio['bitrate_mode'] = 'cbr';
       
   916 				$thisfile_audio_dataformat      = 'aiff';
       
   917 				$thisfile_audio['lossless']     = true;
       
   918 				$info['mime_type']      = 'audio/x-aiff';
       
   919 
       
   920 				if (isset($thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'])) {
       
   921 					$info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'] + 8;
       
   922 					$info['avdataend']    = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['SSND'][0]['size'];
       
   923 					if ($info['avdataend'] > $info['filesize']) {
       
   924 						if (($info['avdataend'] == ($info['filesize'] + 1)) && (($info['filesize'] % 2) == 1)) {
       
   925 							// structures rounded to 2-byte boundary, but dumb encoders
       
   926 							// forget to pad end of file to make this actually work
       
   927 						} else {
       
   928 							$info['warning'][] = 'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['SSND'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found';
       
   929 						}
       
   930 						$info['avdataend'] = $info['filesize'];
       
   931 					}
       
   932 				}
       
   933 
       
   934 				if (isset($thisfile_riff[$RIFFsubtype]['COMM'][0]['data'])) {
       
   935 
       
   936 					// shortcut
       
   937 					$thisfile_riff_RIFFsubtype_COMM_0_data = &$thisfile_riff[$RIFFsubtype]['COMM'][0]['data'];
       
   938 
       
   939 					$thisfile_riff_audio['channels']         =         getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data,  0,  2), true);
       
   940 					$thisfile_riff_audio['total_samples']    =         getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data,  2,  4), false);
       
   941 					$thisfile_riff_audio['bits_per_sample']  =         getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data,  6,  2), true);
       
   942 					$thisfile_riff_audio['sample_rate']      = (int) getid3_lib::BigEndian2Float(substr($thisfile_riff_RIFFsubtype_COMM_0_data,  8, 10));
       
   943 
       
   944 					if ($thisfile_riff[$RIFFsubtype]['COMM'][0]['size'] > 18) {
       
   945 						$thisfile_riff_audio['codec_fourcc'] =                                   substr($thisfile_riff_RIFFsubtype_COMM_0_data, 18,  4);
       
   946 						$CodecNameSize                       =         getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 22,  1), false);
       
   947 						$thisfile_riff_audio['codec_name']   =                                   substr($thisfile_riff_RIFFsubtype_COMM_0_data, 23,  $CodecNameSize);
       
   948 						switch ($thisfile_riff_audio['codec_name']) {
       
   949 							case 'NONE':
       
   950 								$thisfile_audio['codec']    = 'Pulse Code Modulation (PCM)';
       
   951 								$thisfile_audio['lossless'] = true;
       
   952 								break;
       
   953 
       
   954 							case '':
       
   955 								switch ($thisfile_riff_audio['codec_fourcc']) {
       
   956 									// http://developer.apple.com/qa/snd/snd07.html
       
   957 									case 'sowt':
       
   958 										$thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Little-Endian PCM';
       
   959 										$thisfile_audio['lossless'] = true;
       
   960 										break;
       
   961 
       
   962 									case 'twos':
       
   963 										$thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Big-Endian PCM';
       
   964 										$thisfile_audio['lossless'] = true;
       
   965 										break;
       
   966 
       
   967 									default:
       
   968 										break;
       
   969 								}
       
   970 								break;
       
   971 
       
   972 							default:
       
   973 								$thisfile_audio['codec']    = $thisfile_riff_audio['codec_name'];
       
   974 								$thisfile_audio['lossless'] = false;
       
   975 								break;
       
   976 						}
       
   977 					}
       
   978 
       
   979 					$thisfile_audio['channels']        = $thisfile_riff_audio['channels'];
       
   980 					if ($thisfile_riff_audio['bits_per_sample'] > 0) {
       
   981 						$thisfile_audio['bits_per_sample'] = $thisfile_riff_audio['bits_per_sample'];
       
   982 					}
       
   983 					$thisfile_audio['sample_rate']     = $thisfile_riff_audio['sample_rate'];
       
   984 					if ($thisfile_audio['sample_rate'] == 0) {
       
   985 						$info['error'][] = 'Corrupted AIFF file: sample_rate == zero';
       
   986 						return false;
       
   987 					}
       
   988 					$info['playtime_seconds'] = $thisfile_riff_audio['total_samples'] / $thisfile_audio['sample_rate'];
       
   989 				}
       
   990 
       
   991 				if (isset($thisfile_riff[$RIFFsubtype]['COMT'])) {
       
   992 					$offset = 0;
       
   993 					$CommentCount                                   = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false);
       
   994 					$offset += 2;
       
   995 					for ($i = 0; $i < $CommentCount; $i++) {
       
   996 						$info['comments_raw'][$i]['timestamp']      = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 4), false);
       
   997 						$offset += 4;
       
   998 						$info['comments_raw'][$i]['marker_id']      = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), true);
       
   999 						$offset += 2;
       
  1000 						$CommentLength                              = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false);
       
  1001 						$offset += 2;
       
  1002 						$info['comments_raw'][$i]['comment']        =                           substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, $CommentLength);
       
  1003 						$offset += $CommentLength;
       
  1004 
       
  1005 						$info['comments_raw'][$i]['timestamp_unix'] = getid3_lib::DateMac2Unix($info['comments_raw'][$i]['timestamp']);
       
  1006 						$thisfile_riff['comments']['comment'][] = $info['comments_raw'][$i]['comment'];
       
  1007 					}
       
  1008 				}
       
  1009 
       
  1010 				$CommentsChunkNames = array('NAME'=>'title', 'author'=>'artist', '(c) '=>'copyright', 'ANNO'=>'comment');
       
  1011 				foreach ($CommentsChunkNames as $key => $value) {
       
  1012 					if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) {
       
  1013 						$thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data'];
       
  1014 					}
       
  1015 				}
       
  1016 /*
       
  1017 				if (isset($thisfile_riff[$RIFFsubtype]['ID3 '])) {
       
  1018 					getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
       
  1019 					$getid3_temp = new getID3();
       
  1020 					$getid3_temp->openfile($this->getid3->filename);
       
  1021 					$getid3_id3v2 = new getid3_id3v2($getid3_temp);
       
  1022 					$getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['ID3 '][0]['offset'] + 8;
       
  1023 					if ($thisfile_riff[$RIFFsubtype]['ID3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
       
  1024 						$info['id3v2'] = $getid3_temp->info['id3v2'];
       
  1025 					}
       
  1026 					unset($getid3_temp, $getid3_id3v2);
       
  1027 				}
       
  1028 */
       
  1029 				break;
       
  1030 
       
  1031 			case '8SVX':
       
  1032 				$thisfile_audio['bitrate_mode']    = 'cbr';
       
  1033 				$thisfile_audio_dataformat         = '8svx';
       
  1034 				$thisfile_audio['bits_per_sample'] = 8;
       
  1035 				$thisfile_audio['channels']        = 1; // overridden below, if need be
       
  1036 				$info['mime_type']                = 'audio/x-aiff';
       
  1037 
       
  1038 				if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) {
       
  1039 					$info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8;
       
  1040 					$info['avdataend']    = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['BODY'][0]['size'];
       
  1041 					if ($info['avdataend'] > $info['filesize']) {
       
  1042 						$info['warning'][] = 'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['BODY'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found';
       
  1043 					}
       
  1044 				}
       
  1045 
       
  1046 				if (isset($thisfile_riff[$RIFFsubtype]['VHDR'][0]['offset'])) {
       
  1047 					// shortcut
       
  1048 					$thisfile_riff_RIFFsubtype_VHDR_0 = &$thisfile_riff[$RIFFsubtype]['VHDR'][0];
       
  1049 
       
  1050 					$thisfile_riff_RIFFsubtype_VHDR_0['oneShotHiSamples']  =   getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'],  0, 4));
       
  1051 					$thisfile_riff_RIFFsubtype_VHDR_0['repeatHiSamples']   =   getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'],  4, 4));
       
  1052 					$thisfile_riff_RIFFsubtype_VHDR_0['samplesPerHiCycle'] =   getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'],  8, 4));
       
  1053 					$thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec']     =   getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 12, 2));
       
  1054 					$thisfile_riff_RIFFsubtype_VHDR_0['ctOctave']          =   getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 14, 1));
       
  1055 					$thisfile_riff_RIFFsubtype_VHDR_0['sCompression']      =   getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 15, 1));
       
  1056 					$thisfile_riff_RIFFsubtype_VHDR_0['Volume']            = getid3_lib::FixedPoint16_16(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 16, 4));
       
  1057 
       
  1058 					$thisfile_audio['sample_rate'] = $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec'];
       
  1059 
       
  1060 					switch ($thisfile_riff_RIFFsubtype_VHDR_0['sCompression']) {
       
  1061 						case 0:
       
  1062 							$thisfile_audio['codec']    = 'Pulse Code Modulation (PCM)';
       
  1063 							$thisfile_audio['lossless'] = true;
       
  1064 							$ActualBitsPerSample        = 8;
       
  1065 							break;
       
  1066 
       
  1067 						case 1:
       
  1068 							$thisfile_audio['codec']    = 'Fibonacci-delta encoding';
       
  1069 							$thisfile_audio['lossless'] = false;
       
  1070 							$ActualBitsPerSample        = 4;
       
  1071 							break;
       
  1072 
       
  1073 						default:
       
  1074 							$info['warning'][] = 'Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.sCompression.'"';
       
  1075 							break;
       
  1076 					}
       
  1077 				}
       
  1078 
       
  1079 				if (isset($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'])) {
       
  1080 					$ChannelsIndex = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'], 0, 4));
       
  1081 					switch ($ChannelsIndex) {
       
  1082 						case 6: // Stereo
       
  1083 							$thisfile_audio['channels'] = 2;
       
  1084 							break;
       
  1085 
       
  1086 						case 2: // Left channel only
       
  1087 						case 4: // Right channel only
       
  1088 							$thisfile_audio['channels'] = 1;
       
  1089 							break;
       
  1090 
       
  1091 						default:
       
  1092 							$info['warning'][] = 'Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "'.$ChannelsIndex.'"';
       
  1093 							break;
       
  1094 					}
       
  1095 
       
  1096 				}
       
  1097 
       
  1098 				$CommentsChunkNames = array('NAME'=>'title', 'author'=>'artist', '(c) '=>'copyright', 'ANNO'=>'comment');
       
  1099 				foreach ($CommentsChunkNames as $key => $value) {
       
  1100 					if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) {
       
  1101 						$thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data'];
       
  1102 					}
       
  1103 				}
       
  1104 
       
  1105 				$thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $ActualBitsPerSample * $thisfile_audio['channels'];
       
  1106 				if (!empty($thisfile_audio['bitrate'])) {
       
  1107 					$info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset']) / ($thisfile_audio['bitrate'] / 8);
       
  1108 				}
       
  1109 				break;
       
  1110 
       
  1111 
       
  1112 			case 'CDXA':
       
  1113 				$info['mime_type'] = 'video/mpeg';
       
  1114 				if (!empty($thisfile_riff['CDXA']['data'][0]['size'])) {
       
  1115 					if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.mpeg.php', __FILE__, false)) {
       
  1116 						$getid3_temp = new getID3();
       
  1117 						$getid3_temp->openfile($this->getid3->filename);
       
  1118 						$getid3_mpeg = new getid3_mpeg($getid3_temp);
       
  1119 						$getid3_mpeg->Analyze();
       
  1120 						if (empty($getid3_temp->info['error'])) {
       
  1121 							$info['audio']   = $getid3_temp->info['audio'];
       
  1122 							$info['video']   = $getid3_temp->info['video'];
       
  1123 							$info['mpeg']    = $getid3_temp->info['mpeg'];
       
  1124 							$info['warning'] = $getid3_temp->info['warning'];
       
  1125 						}
       
  1126 						unset($getid3_temp, $getid3_mpeg);
       
  1127 					}
       
  1128 				}
       
  1129 				break;
       
  1130 
       
  1131 
       
  1132 			default:
       
  1133 				$info['error'][] = 'Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA), found "'.$RIFFsubtype.'" instead';
       
  1134 				unset($info['fileformat']);
       
  1135 				break;
       
  1136 		}
       
  1137 
       
  1138 		switch ($RIFFsubtype) {
       
  1139 			case 'WAVE':
       
  1140 			case 'AIFF':
       
  1141 			case 'AIFC':
       
  1142 				$ID3v2_key_good = 'id3 ';
       
  1143 				$ID3v2_keys_bad = array('ID3 ', 'tag ');
       
  1144 				foreach ($ID3v2_keys_bad as $ID3v2_key_bad) {
       
  1145 					if (isset($thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]) && !array_key_exists($ID3v2_key_good, $thisfile_riff[$RIFFsubtype])) {
       
  1146 						$thisfile_riff[$RIFFsubtype][$ID3v2_key_good] = $thisfile_riff[$RIFFsubtype][$ID3v2_key_bad];
       
  1147 						$info['warning'][] = 'mapping "'.$ID3v2_key_bad.'" chunk to "'.$ID3v2_key_good.'"';
       
  1148 					}
       
  1149 				}
       
  1150 
       
  1151 				if (isset($thisfile_riff[$RIFFsubtype]['id3 '])) {
       
  1152 					getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
       
  1153 					$getid3_temp = new getID3();
       
  1154 					$getid3_temp->openfile($this->getid3->filename);
       
  1155 					$getid3_id3v2 = new getid3_id3v2($getid3_temp);
       
  1156 					$getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['id3 '][0]['offset'] + 8;
       
  1157 					if ($thisfile_riff[$RIFFsubtype]['id3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
       
  1158 						$info['id3v2'] = $getid3_temp->info['id3v2'];
       
  1159 					}
       
  1160 					unset($getid3_temp, $getid3_id3v2);
       
  1161 				}
       
  1162 				break;
       
  1163 		}
       
  1164 
       
  1165 		if (isset($thisfile_riff_WAVE['DISP']) && is_array($thisfile_riff_WAVE['DISP'])) {
       
  1166 			$thisfile_riff['comments']['title'][] = trim(substr($thisfile_riff_WAVE['DISP'][count($thisfile_riff_WAVE['DISP']) - 1]['data'], 4));
       
  1167 		}
       
  1168 		if (isset($thisfile_riff_WAVE['INFO']) && is_array($thisfile_riff_WAVE['INFO'])) {
       
  1169 			self::parseComments($thisfile_riff_WAVE['INFO'], $thisfile_riff['comments']);
       
  1170 		}
       
  1171 		if (isset($thisfile_riff['AVI ']['INFO']) && is_array($thisfile_riff['AVI ']['INFO'])) {
       
  1172 			self::parseComments($thisfile_riff['AVI ']['INFO'], $thisfile_riff['comments']);
       
  1173 		}
       
  1174 
       
  1175 		if (empty($thisfile_audio['encoder']) && !empty($info['mpeg']['audio']['LAME']['short_version'])) {
       
  1176 			$thisfile_audio['encoder'] = $info['mpeg']['audio']['LAME']['short_version'];
       
  1177 		}
       
  1178 
       
  1179 		if (!isset($info['playtime_seconds'])) {
       
  1180 			$info['playtime_seconds'] = 0;
       
  1181 		}
       
  1182 		if (isset($thisfile_riff_raw['strh'][0]['dwLength']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) {
       
  1183 			// needed for >2GB AVIs where 'avih' chunk only lists number of frames in that chunk, not entire movie
       
  1184 			$info['playtime_seconds'] = $thisfile_riff_raw['strh'][0]['dwLength'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000);
       
  1185 		} elseif (isset($thisfile_riff_raw['avih']['dwTotalFrames']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) {
       
  1186 			$info['playtime_seconds'] = $thisfile_riff_raw['avih']['dwTotalFrames'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000);
       
  1187 		}
       
  1188 
       
  1189 		if ($info['playtime_seconds'] > 0) {
       
  1190 			if (isset($thisfile_riff_audio) && isset($thisfile_riff_video)) {
       
  1191 
       
  1192 				if (!isset($info['bitrate'])) {
       
  1193 					$info['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8);
       
  1194 				}
       
  1195 
       
  1196 			} elseif (isset($thisfile_riff_audio) && !isset($thisfile_riff_video)) {
       
  1197 
       
  1198 				if (!isset($thisfile_audio['bitrate'])) {
       
  1199 					$thisfile_audio['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8);
       
  1200 				}
       
  1201 
       
  1202 			} elseif (!isset($thisfile_riff_audio) && isset($thisfile_riff_video)) {
       
  1203 
       
  1204 				if (!isset($thisfile_video['bitrate'])) {
       
  1205 					$thisfile_video['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8);
       
  1206 				}
       
  1207 
       
  1208 			}
       
  1209 		}
       
  1210 
       
  1211 
       
  1212 		if (isset($thisfile_riff_video) && isset($thisfile_audio['bitrate']) && ($thisfile_audio['bitrate'] > 0) && ($info['playtime_seconds'] > 0)) {
       
  1213 
       
  1214 			$info['bitrate'] = ((($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds']) * 8);
       
  1215 			$thisfile_audio['bitrate'] = 0;
       
  1216 			$thisfile_video['bitrate'] = $info['bitrate'];
       
  1217 			foreach ($thisfile_riff_audio as $channelnumber => $audioinfoarray) {
       
  1218 				$thisfile_video['bitrate'] -= $audioinfoarray['bitrate'];
       
  1219 				$thisfile_audio['bitrate'] += $audioinfoarray['bitrate'];
       
  1220 			}
       
  1221 			if ($thisfile_video['bitrate'] <= 0) {
       
  1222 				unset($thisfile_video['bitrate']);
       
  1223 			}
       
  1224 			if ($thisfile_audio['bitrate'] <= 0) {
       
  1225 				unset($thisfile_audio['bitrate']);
       
  1226 			}
       
  1227 		}
       
  1228 
       
  1229 		if (isset($info['mpeg']['audio'])) {
       
  1230 			$thisfile_audio_dataformat      = 'mp'.$info['mpeg']['audio']['layer'];
       
  1231 			$thisfile_audio['sample_rate']  = $info['mpeg']['audio']['sample_rate'];
       
  1232 			$thisfile_audio['channels']     = $info['mpeg']['audio']['channels'];
       
  1233 			$thisfile_audio['bitrate']      = $info['mpeg']['audio']['bitrate'];
       
  1234 			$thisfile_audio['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
       
  1235 			if (!empty($info['mpeg']['audio']['codec'])) {
       
  1236 				$thisfile_audio['codec'] = $info['mpeg']['audio']['codec'].' '.$thisfile_audio['codec'];
       
  1237 			}
       
  1238 			if (!empty($thisfile_audio['streams'])) {
       
  1239 				foreach ($thisfile_audio['streams'] as $streamnumber => $streamdata) {
       
  1240 					if ($streamdata['dataformat'] == $thisfile_audio_dataformat) {
       
  1241 						$thisfile_audio['streams'][$streamnumber]['sample_rate']  = $thisfile_audio['sample_rate'];
       
  1242 						$thisfile_audio['streams'][$streamnumber]['channels']     = $thisfile_audio['channels'];
       
  1243 						$thisfile_audio['streams'][$streamnumber]['bitrate']      = $thisfile_audio['bitrate'];
       
  1244 						$thisfile_audio['streams'][$streamnumber]['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
       
  1245 						$thisfile_audio['streams'][$streamnumber]['codec']        = $thisfile_audio['codec'];
       
  1246 					}
       
  1247 				}
       
  1248 			}
       
  1249 			$getid3_mp3 = new getid3_mp3($this->getid3);
       
  1250 			$thisfile_audio['encoder_options'] = $getid3_mp3->GuessEncoderOptions();
       
  1251 			unset($getid3_mp3);
       
  1252 		}
       
  1253 
       
  1254 
       
  1255 		if (!empty($thisfile_riff_raw['fmt ']['wBitsPerSample']) && ($thisfile_riff_raw['fmt ']['wBitsPerSample'] > 0)) {
       
  1256 			switch ($thisfile_audio_dataformat) {
       
  1257 				case 'ac3':
       
  1258 					// ignore bits_per_sample
       
  1259 					break;
       
  1260 
       
  1261 				default:
       
  1262 					$thisfile_audio['bits_per_sample'] = $thisfile_riff_raw['fmt ']['wBitsPerSample'];
       
  1263 					break;
       
  1264 			}
       
  1265 		}
       
  1266 
       
  1267 
       
  1268 		if (empty($thisfile_riff_raw)) {
       
  1269 			unset($thisfile_riff['raw']);
       
  1270 		}
       
  1271 		if (empty($thisfile_riff_audio)) {
       
  1272 			unset($thisfile_riff['audio']);
       
  1273 		}
       
  1274 		if (empty($thisfile_riff_video)) {
       
  1275 			unset($thisfile_riff['video']);
       
  1276 		}
       
  1277 
       
  1278 		return true;
       
  1279 	}
       
  1280 
       
  1281 	public function ParseRIFF($startoffset, $maxoffset) {
       
  1282 		$info = &$this->getid3->info;
       
  1283 
       
  1284 		$RIFFchunk = false;
       
  1285 		$FoundAllChunksWeNeed = false;
       
  1286 
       
  1287 		try {
       
  1288 			$this->fseek($startoffset);
       
  1289 			$maxoffset = min($maxoffset, $info['avdataend']);
       
  1290 			while ($this->ftell() < $maxoffset) {
       
  1291 				$chunknamesize = $this->fread(8);
       
  1292 				//$chunkname =                          substr($chunknamesize, 0, 4);
       
  1293 				$chunkname = str_replace("\x00", '_', substr($chunknamesize, 0, 4));  // note: chunk names of 4 null bytes do appear to be legal (has been observed inside INFO and PRMI chunks, for example), but makes traversing array keys more difficult
       
  1294 				$chunksize =  $this->EitherEndian2Int(substr($chunknamesize, 4, 4));
       
  1295 				//if (strlen(trim($chunkname, "\x00")) < 4) {
       
  1296 				if (strlen($chunkname) < 4) {
       
  1297 					$this->error('Expecting chunk name at offset '.($this->ftell() - 8).' but found nothing. Aborting RIFF parsing.');
       
  1298 					break;
       
  1299 				}
       
  1300 				if (($chunksize == 0) && ($chunkname != 'JUNK')) {
       
  1301 					$this->warning('Chunk ('.$chunkname.') size at offset '.($this->ftell() - 4).' is zero. Aborting RIFF parsing.');
       
  1302 					break;
       
  1303 				}
       
  1304 				if (($chunksize % 2) != 0) {
       
  1305 					// all structures are packed on word boundaries
       
  1306 					$chunksize++;
       
  1307 				}
       
  1308 
       
  1309 				switch ($chunkname) {
       
  1310 					case 'LIST':
       
  1311 						$listname = $this->fread(4);
       
  1312 						if (preg_match('#^(movi|rec )$#i', $listname)) {
       
  1313 							$RIFFchunk[$listname]['offset'] = $this->ftell() - 4;
       
  1314 							$RIFFchunk[$listname]['size']   = $chunksize;
       
  1315 
       
  1316 							if (!$FoundAllChunksWeNeed) {
       
  1317 								$WhereWeWere      = $this->ftell();
       
  1318 								$AudioChunkHeader = $this->fread(12);
       
  1319 								$AudioChunkStreamNum  =                              substr($AudioChunkHeader, 0, 2);
       
  1320 								$AudioChunkStreamType =                              substr($AudioChunkHeader, 2, 2);
       
  1321 								$AudioChunkSize       = getid3_lib::LittleEndian2Int(substr($AudioChunkHeader, 4, 4));
       
  1322 
       
  1323 								if ($AudioChunkStreamType == 'wb') {
       
  1324 									$FirstFourBytes = substr($AudioChunkHeader, 8, 4);
       
  1325 									if (preg_match('/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', $FirstFourBytes)) {
       
  1326 										// MP3
       
  1327 										if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) {
       
  1328 											$getid3_temp = new getID3();
       
  1329 											$getid3_temp->openfile($this->getid3->filename);
       
  1330 											$getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
       
  1331 											$getid3_temp->info['avdataend']    = $this->ftell() + $AudioChunkSize;
       
  1332 											$getid3_mp3 = new getid3_mp3($getid3_temp);
       
  1333 											$getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false);
       
  1334 											if (isset($getid3_temp->info['mpeg']['audio'])) {
       
  1335 												$info['mpeg']['audio']         = $getid3_temp->info['mpeg']['audio'];
       
  1336 												$info['audio']                 = $getid3_temp->info['audio'];
       
  1337 												$info['audio']['dataformat']   = 'mp'.$info['mpeg']['audio']['layer'];
       
  1338 												$info['audio']['sample_rate']  = $info['mpeg']['audio']['sample_rate'];
       
  1339 												$info['audio']['channels']     = $info['mpeg']['audio']['channels'];
       
  1340 												$info['audio']['bitrate']      = $info['mpeg']['audio']['bitrate'];
       
  1341 												$info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
       
  1342 												//$info['bitrate']               = $info['audio']['bitrate'];
       
  1343 											}
       
  1344 											unset($getid3_temp, $getid3_mp3);
       
  1345 										}
       
  1346 
       
  1347 									} elseif (strpos($FirstFourBytes, getid3_ac3::syncword) === 0) {
       
  1348 
       
  1349 										// AC3
       
  1350 										$getid3_temp = new getID3();
       
  1351 										$getid3_temp->openfile($this->getid3->filename);
       
  1352 										$getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
       
  1353 										$getid3_temp->info['avdataend']    = $this->ftell() + $AudioChunkSize;
       
  1354 										$getid3_ac3 = new getid3_ac3($getid3_temp);
       
  1355 										$getid3_ac3->Analyze();
       
  1356 										if (empty($getid3_temp->info['error'])) {
       
  1357 											$info['audio']   = $getid3_temp->info['audio'];
       
  1358 											$info['ac3']     = $getid3_temp->info['ac3'];
       
  1359 											if (!empty($getid3_temp->info['warning'])) {
       
  1360 												foreach ($getid3_temp->info['warning'] as $key => $value) {
       
  1361 													$info['warning'][] = $value;
       
  1362 												}
       
  1363 											}
       
  1364 										}
       
  1365 										unset($getid3_temp, $getid3_ac3);
       
  1366 									}
       
  1367 								}
       
  1368 								$FoundAllChunksWeNeed = true;
       
  1369 								$this->fseek($WhereWeWere);
       
  1370 							}
       
  1371 							$this->fseek($chunksize - 4, SEEK_CUR);
       
  1372 
       
  1373 						} else {
       
  1374 
       
  1375 							if (!isset($RIFFchunk[$listname])) {
       
  1376 								$RIFFchunk[$listname] = array();
       
  1377 							}
       
  1378 							$LISTchunkParent    = $listname;
       
  1379 							$LISTchunkMaxOffset = $this->ftell() - 4 + $chunksize;
       
  1380 							if ($parsedChunk = $this->ParseRIFF($this->ftell(), $LISTchunkMaxOffset)) {
       
  1381 								$RIFFchunk[$listname] = array_merge_recursive($RIFFchunk[$listname], $parsedChunk);
       
  1382 							}
       
  1383 
       
  1384 						}
       
  1385 						break;
       
  1386 
       
  1387 					default:
       
  1388 						if (preg_match('#^[0-9]{2}(wb|pc|dc|db)$#', $chunkname)) {
       
  1389 							$this->fseek($chunksize, SEEK_CUR);
       
  1390 							break;
       
  1391 						}
       
  1392 						$thisindex = 0;
       
  1393 						if (isset($RIFFchunk[$chunkname]) && is_array($RIFFchunk[$chunkname])) {
       
  1394 							$thisindex = count($RIFFchunk[$chunkname]);
       
  1395 						}
       
  1396 						$RIFFchunk[$chunkname][$thisindex]['offset'] = $this->ftell() - 8;
       
  1397 						$RIFFchunk[$chunkname][$thisindex]['size']   = $chunksize;
       
  1398 						switch ($chunkname) {
       
  1399 							case 'data':
       
  1400 								$info['avdataoffset'] = $this->ftell();
       
  1401 								$info['avdataend']    = $info['avdataoffset'] + $chunksize;
       
  1402 
       
  1403 								$testData = $this->fread(36);
       
  1404 								if ($testData === '') {
       
  1405 									break;
       
  1406 								}
       
  1407 								if (preg_match('/^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]/s', substr($testData, 0, 4))) {
       
  1408 
       
  1409 									// Probably is MP3 data
       
  1410 									if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($testData, 0, 4))) {
       
  1411 										$getid3_temp = new getID3();
       
  1412 										$getid3_temp->openfile($this->getid3->filename);
       
  1413 										$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
       
  1414 										$getid3_temp->info['avdataend']    = $info['avdataend'];
       
  1415 										$getid3_mp3 = new getid3_mp3($getid3_temp);
       
  1416 										$getid3_mp3->getOnlyMPEGaudioInfo($info['avdataoffset'], false);
       
  1417 										if (empty($getid3_temp->info['error'])) {
       
  1418 											$info['audio'] = $getid3_temp->info['audio'];
       
  1419 											$info['mpeg']  = $getid3_temp->info['mpeg'];
       
  1420 										}
       
  1421 										unset($getid3_temp, $getid3_mp3);
       
  1422 									}
       
  1423 
       
  1424 								} elseif (($isRegularAC3 = (substr($testData, 0, 2) == getid3_ac3::syncword)) || substr($testData, 8, 2) == strrev(getid3_ac3::syncword)) {
       
  1425 
       
  1426 									// This is probably AC-3 data
       
  1427 									$getid3_temp = new getID3();
       
  1428 									if ($isRegularAC3) {
       
  1429 										$getid3_temp->openfile($this->getid3->filename);
       
  1430 										$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
       
  1431 										$getid3_temp->info['avdataend']    = $info['avdataend'];
       
  1432 									}
       
  1433 									$getid3_ac3 = new getid3_ac3($getid3_temp);
       
  1434 									if ($isRegularAC3) {
       
  1435 										$getid3_ac3->Analyze();
       
  1436 									} else {
       
  1437 										// Dolby Digital WAV
       
  1438 										// AC-3 content, but not encoded in same format as normal AC-3 file
       
  1439 										// For one thing, byte order is swapped
       
  1440 										$ac3_data = '';
       
  1441 										for ($i = 0; $i < 28; $i += 2) {
       
  1442 											$ac3_data .= substr($testData, 8 + $i + 1, 1);
       
  1443 											$ac3_data .= substr($testData, 8 + $i + 0, 1);
       
  1444 										}
       
  1445 										$getid3_ac3->AnalyzeString($ac3_data);
       
  1446 									}
       
  1447 
       
  1448 									if (empty($getid3_temp->info['error'])) {
       
  1449 										$info['audio'] = $getid3_temp->info['audio'];
       
  1450 										$info['ac3']   = $getid3_temp->info['ac3'];
       
  1451 										if (!empty($getid3_temp->info['warning'])) {
       
  1452 											foreach ($getid3_temp->info['warning'] as $newerror) {
       
  1453 												$this->warning('getid3_ac3() says: ['.$newerror.']');
       
  1454 											}
       
  1455 										}
       
  1456 									}
       
  1457 									unset($getid3_temp, $getid3_ac3);
       
  1458 
       
  1459 								} elseif (preg_match('/^('.implode('|', array_map('preg_quote', getid3_dts::$syncwords)).')/', $testData)) {
       
  1460 
       
  1461 									// This is probably DTS data
       
  1462 									$getid3_temp = new getID3();
       
  1463 									$getid3_temp->openfile($this->getid3->filename);
       
  1464 									$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
       
  1465 									$getid3_dts = new getid3_dts($getid3_temp);
       
  1466 									$getid3_dts->Analyze();
       
  1467 									if (empty($getid3_temp->info['error'])) {
       
  1468 										$info['audio']            = $getid3_temp->info['audio'];
       
  1469 										$info['dts']              = $getid3_temp->info['dts'];
       
  1470 										$info['playtime_seconds'] = $getid3_temp->info['playtime_seconds']; // may not match RIFF calculations since DTS-WAV often used 14/16 bit-word packing
       
  1471 										if (!empty($getid3_temp->info['warning'])) {
       
  1472 											foreach ($getid3_temp->info['warning'] as $newerror) {
       
  1473 												$this->warning('getid3_dts() says: ['.$newerror.']');
       
  1474 											}
       
  1475 										}
       
  1476 									}
       
  1477 
       
  1478 									unset($getid3_temp, $getid3_dts);
       
  1479 
       
  1480 								} elseif (substr($testData, 0, 4) == 'wvpk') {
       
  1481 
       
  1482 									// This is WavPack data
       
  1483 									$info['wavpack']['offset'] = $info['avdataoffset'];
       
  1484 									$info['wavpack']['size']   = getid3_lib::LittleEndian2Int(substr($testData, 4, 4));
       
  1485 									$this->parseWavPackHeader(substr($testData, 8, 28));
       
  1486 
       
  1487 								} else {
       
  1488 									// This is some other kind of data (quite possibly just PCM)
       
  1489 									// do nothing special, just skip it
       
  1490 								}
       
  1491 								$nextoffset = $info['avdataend'];
       
  1492 								$this->fseek($nextoffset);
       
  1493 								break;
       
  1494 
       
  1495 							case 'iXML':
       
  1496 							case 'bext':
       
  1497 							case 'cart':
       
  1498 							case 'fmt ':
       
  1499 							case 'strh':
       
  1500 							case 'strf':
       
  1501 							case 'indx':
       
  1502 							case 'MEXT':
       
  1503 							case 'DISP':
       
  1504 								// always read data in
       
  1505 							case 'JUNK':
       
  1506 								// should be: never read data in
       
  1507 								// but some programs write their version strings in a JUNK chunk (e.g. VirtualDub, AVIdemux, etc)
       
  1508 								if ($chunksize < 1048576) {
       
  1509 									if ($chunksize > 0) {
       
  1510 										$RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize);
       
  1511 										if ($chunkname == 'JUNK') {
       
  1512 											if (preg_match('#^([\\x20-\\x7F]+)#', $RIFFchunk[$chunkname][$thisindex]['data'], $matches)) {
       
  1513 												// only keep text characters [chr(32)-chr(127)]
       
  1514 												$info['riff']['comments']['junk'][] = trim($matches[1]);
       
  1515 											}
       
  1516 											// but if nothing there, ignore
       
  1517 											// remove the key in either case
       
  1518 											unset($RIFFchunk[$chunkname][$thisindex]['data']);
       
  1519 										}
       
  1520 									}
       
  1521 								} else {
       
  1522 									$this->warning('Chunk "'.$chunkname.'" at offset '.$this->ftell().' is unexpectedly larger than 1MB (claims to be '.number_format($chunksize).' bytes), skipping data');
       
  1523 									$this->fseek($chunksize, SEEK_CUR);
       
  1524 								}
       
  1525 								break;
       
  1526 
       
  1527 							//case 'IDVX':
       
  1528 							//	$info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunksize));
       
  1529 							//	break;
       
  1530 
       
  1531 							default:
       
  1532 								if (!empty($LISTchunkParent) && (($RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) {
       
  1533 									$RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
       
  1534 									$RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size']   = $RIFFchunk[$chunkname][$thisindex]['size'];
       
  1535 									unset($RIFFchunk[$chunkname][$thisindex]['offset']);
       
  1536 									unset($RIFFchunk[$chunkname][$thisindex]['size']);
       
  1537 									if (isset($RIFFchunk[$chunkname][$thisindex]) && empty($RIFFchunk[$chunkname][$thisindex])) {
       
  1538 										unset($RIFFchunk[$chunkname][$thisindex]);
       
  1539 									}
       
  1540 									if (isset($RIFFchunk[$chunkname]) && empty($RIFFchunk[$chunkname])) {
       
  1541 										unset($RIFFchunk[$chunkname]);
       
  1542 									}
       
  1543 									$RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['data'] = $this->fread($chunksize);
       
  1544 								} elseif ($chunksize < 2048) {
       
  1545 									// only read data in if smaller than 2kB
       
  1546 									$RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize);
       
  1547 								} else {
       
  1548 									$this->fseek($chunksize, SEEK_CUR);
       
  1549 								}
       
  1550 								break;
       
  1551 						}
       
  1552 						break;
       
  1553 				}
       
  1554 			}
       
  1555 
       
  1556 		} catch (getid3_exception $e) {
       
  1557 			if ($e->getCode() == 10) {
       
  1558 				$this->warning('RIFF parser: '.$e->getMessage());
       
  1559 			} else {
       
  1560 				throw $e;
       
  1561 			}
       
  1562 		}
       
  1563 
       
  1564 		return $RIFFchunk;
       
  1565 	}
       
  1566 
       
  1567 	public function ParseRIFFdata(&$RIFFdata) {
       
  1568 		$info = &$this->getid3->info;
       
  1569 		if ($RIFFdata) {
       
  1570 			$tempfile = tempnam(GETID3_TEMP_DIR, 'getID3');
       
  1571 			$fp_temp  = fopen($tempfile, 'wb');
       
  1572 			$RIFFdataLength = strlen($RIFFdata);
       
  1573 			$NewLengthString = getid3_lib::LittleEndian2String($RIFFdataLength, 4);
       
  1574 			for ($i = 0; $i < 4; $i++) {
       
  1575 				$RIFFdata[($i + 4)] = $NewLengthString[$i];
       
  1576 			}
       
  1577 			fwrite($fp_temp, $RIFFdata);
       
  1578 			fclose($fp_temp);
       
  1579 
       
  1580 			$getid3_temp = new getID3();
       
  1581 			$getid3_temp->openfile($tempfile);
       
  1582 			$getid3_temp->info['filesize']     = $RIFFdataLength;
       
  1583 			$getid3_temp->info['filenamepath'] = $info['filenamepath'];
       
  1584 			$getid3_temp->info['tags']         = $info['tags'];
       
  1585 			$getid3_temp->info['warning']      = $info['warning'];
       
  1586 			$getid3_temp->info['error']        = $info['error'];
       
  1587 			$getid3_temp->info['comments']     = $info['comments'];
       
  1588 			$getid3_temp->info['audio']        = (isset($info['audio']) ? $info['audio'] : array());
       
  1589 			$getid3_temp->info['video']        = (isset($info['video']) ? $info['video'] : array());
       
  1590 			$getid3_riff = new getid3_riff($getid3_temp);
       
  1591 			$getid3_riff->Analyze();
       
  1592 
       
  1593 			$info['riff']     = $getid3_temp->info['riff'];
       
  1594 			$info['warning']  = $getid3_temp->info['warning'];
       
  1595 			$info['error']    = $getid3_temp->info['error'];
       
  1596 			$info['tags']     = $getid3_temp->info['tags'];
       
  1597 			$info['comments'] = $getid3_temp->info['comments'];
       
  1598 			unset($getid3_riff, $getid3_temp);
       
  1599 			unlink($tempfile);
       
  1600 		}
       
  1601 		return false;
       
  1602 	}
       
  1603 
       
  1604 	public static function parseComments(&$RIFFinfoArray, &$CommentsTargetArray) {
       
  1605 		$RIFFinfoKeyLookup = array(
       
  1606 			'IARL'=>'archivallocation',
       
  1607 			'IART'=>'artist',
       
  1608 			'ICDS'=>'costumedesigner',
       
  1609 			'ICMS'=>'commissionedby',
       
  1610 			'ICMT'=>'comment',
       
  1611 			'ICNT'=>'country',
       
  1612 			'ICOP'=>'copyright',
       
  1613 			'ICRD'=>'creationdate',
       
  1614 			'IDIM'=>'dimensions',
       
  1615 			'IDIT'=>'digitizationdate',
       
  1616 			'IDPI'=>'resolution',
       
  1617 			'IDST'=>'distributor',
       
  1618 			'IEDT'=>'editor',
       
  1619 			'IENG'=>'engineers',
       
  1620 			'IFRM'=>'accountofparts',
       
  1621 			'IGNR'=>'genre',
       
  1622 			'IKEY'=>'keywords',
       
  1623 			'ILGT'=>'lightness',
       
  1624 			'ILNG'=>'language',
       
  1625 			'IMED'=>'orignalmedium',
       
  1626 			'IMUS'=>'composer',
       
  1627 			'INAM'=>'title',
       
  1628 			'IPDS'=>'productiondesigner',
       
  1629 			'IPLT'=>'palette',
       
  1630 			'IPRD'=>'product',
       
  1631 			'IPRO'=>'producer',
       
  1632 			'IPRT'=>'part',
       
  1633 			'IRTD'=>'rating',
       
  1634 			'ISBJ'=>'subject',
       
  1635 			'ISFT'=>'software',
       
  1636 			'ISGN'=>'secondarygenre',
       
  1637 			'ISHP'=>'sharpness',
       
  1638 			'ISRC'=>'sourcesupplier',
       
  1639 			'ISRF'=>'digitizationsource',
       
  1640 			'ISTD'=>'productionstudio',
       
  1641 			'ISTR'=>'starring',
       
  1642 			'ITCH'=>'encoded_by',
       
  1643 			'IWEB'=>'url',
       
  1644 			'IWRI'=>'writer',
       
  1645 			'____'=>'comment',
       
  1646 		);
       
  1647 		foreach ($RIFFinfoKeyLookup as $key => $value) {
       
  1648 			if (isset($RIFFinfoArray[$key])) {
       
  1649 				foreach ($RIFFinfoArray[$key] as $commentid => $commentdata) {
       
  1650 					if (trim($commentdata['data']) != '') {
       
  1651 						if (isset($CommentsTargetArray[$value])) {
       
  1652 							$CommentsTargetArray[$value][] =     trim($commentdata['data']);
       
  1653 						} else {
       
  1654 							$CommentsTargetArray[$value] = array(trim($commentdata['data']));
       
  1655 						}
       
  1656 					}
       
  1657 				}
       
  1658 			}
       
  1659 		}
       
  1660 		return true;
       
  1661 	}
       
  1662 
       
  1663 	public static function parseWAVEFORMATex($WaveFormatExData) {
       
  1664 		// shortcut
       
  1665 		$WaveFormatEx['raw'] = array();
       
  1666 		$WaveFormatEx_raw    = &$WaveFormatEx['raw'];
       
  1667 
       
  1668 		$WaveFormatEx_raw['wFormatTag']      = substr($WaveFormatExData,  0, 2);
       
  1669 		$WaveFormatEx_raw['nChannels']       = substr($WaveFormatExData,  2, 2);
       
  1670 		$WaveFormatEx_raw['nSamplesPerSec']  = substr($WaveFormatExData,  4, 4);
       
  1671 		$WaveFormatEx_raw['nAvgBytesPerSec'] = substr($WaveFormatExData,  8, 4);
       
  1672 		$WaveFormatEx_raw['nBlockAlign']     = substr($WaveFormatExData, 12, 2);
       
  1673 		$WaveFormatEx_raw['wBitsPerSample']  = substr($WaveFormatExData, 14, 2);
       
  1674 		if (strlen($WaveFormatExData) > 16) {
       
  1675 			$WaveFormatEx_raw['cbSize']      = substr($WaveFormatExData, 16, 2);
       
  1676 		}
       
  1677 		$WaveFormatEx_raw = array_map('getid3_lib::LittleEndian2Int', $WaveFormatEx_raw);
       
  1678 
       
  1679 		$WaveFormatEx['codec']           = self::wFormatTagLookup($WaveFormatEx_raw['wFormatTag']);
       
  1680 		$WaveFormatEx['channels']        = $WaveFormatEx_raw['nChannels'];
       
  1681 		$WaveFormatEx['sample_rate']     = $WaveFormatEx_raw['nSamplesPerSec'];
       
  1682 		$WaveFormatEx['bitrate']         = $WaveFormatEx_raw['nAvgBytesPerSec'] * 8;
       
  1683 		$WaveFormatEx['bits_per_sample'] = $WaveFormatEx_raw['wBitsPerSample'];
       
  1684 
       
  1685 		return $WaveFormatEx;
       
  1686 	}
       
  1687 
       
  1688 	public function parseWavPackHeader($WavPackChunkData) {
       
  1689 		// typedef struct {
       
  1690 		//     char ckID [4];
       
  1691 		//     long ckSize;
       
  1692 		//     short version;
       
  1693 		//     short bits;                // added for version 2.00
       
  1694 		//     short flags, shift;        // added for version 3.00
       
  1695 		//     long total_samples, crc, crc2;
       
  1696 		//     char extension [4], extra_bc, extras [3];
       
  1697 		// } WavpackHeader;
       
  1698 
       
  1699 		// shortcut
       
  1700 		$info = &$this->getid3->info;
       
  1701 		$info['wavpack']  = array();
       
  1702 		$thisfile_wavpack = &$info['wavpack'];
       
  1703 
       
  1704 		$thisfile_wavpack['version']           = getid3_lib::LittleEndian2Int(substr($WavPackChunkData,  0, 2));
       
  1705 		if ($thisfile_wavpack['version'] >= 2) {
       
  1706 			$thisfile_wavpack['bits']          = getid3_lib::LittleEndian2Int(substr($WavPackChunkData,  2, 2));
       
  1707 		}
       
  1708 		if ($thisfile_wavpack['version'] >= 3) {
       
  1709 			$thisfile_wavpack['flags_raw']     = getid3_lib::LittleEndian2Int(substr($WavPackChunkData,  4, 2));
       
  1710 			$thisfile_wavpack['shift']         = getid3_lib::LittleEndian2Int(substr($WavPackChunkData,  6, 2));
       
  1711 			$thisfile_wavpack['total_samples'] = getid3_lib::LittleEndian2Int(substr($WavPackChunkData,  8, 4));
       
  1712 			$thisfile_wavpack['crc1']          = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 12, 4));
       
  1713 			$thisfile_wavpack['crc2']          = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 16, 4));
       
  1714 			$thisfile_wavpack['extension']     =                              substr($WavPackChunkData, 20, 4);
       
  1715 			$thisfile_wavpack['extra_bc']      = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 24, 1));
       
  1716 			for ($i = 0; $i <= 2; $i++) {
       
  1717 				$thisfile_wavpack['extras'][]  = getid3_lib::LittleEndian2Int(substr($WavPackChunkData, 25 + $i, 1));
       
  1718 			}
       
  1719 
       
  1720 			// shortcut
       
  1721 			$thisfile_wavpack['flags'] = array();
       
  1722 			$thisfile_wavpack_flags = &$thisfile_wavpack['flags'];
       
  1723 
       
  1724 			$thisfile_wavpack_flags['mono']                 = (bool) ($thisfile_wavpack['flags_raw'] & 0x000001);
       
  1725 			$thisfile_wavpack_flags['fast_mode']            = (bool) ($thisfile_wavpack['flags_raw'] & 0x000002);
       
  1726 			$thisfile_wavpack_flags['raw_mode']             = (bool) ($thisfile_wavpack['flags_raw'] & 0x000004);
       
  1727 			$thisfile_wavpack_flags['calc_noise']           = (bool) ($thisfile_wavpack['flags_raw'] & 0x000008);
       
  1728 			$thisfile_wavpack_flags['high_quality']         = (bool) ($thisfile_wavpack['flags_raw'] & 0x000010);
       
  1729 			$thisfile_wavpack_flags['3_byte_samples']       = (bool) ($thisfile_wavpack['flags_raw'] & 0x000020);
       
  1730 			$thisfile_wavpack_flags['over_20_bits']         = (bool) ($thisfile_wavpack['flags_raw'] & 0x000040);
       
  1731 			$thisfile_wavpack_flags['use_wvc']              = (bool) ($thisfile_wavpack['flags_raw'] & 0x000080);
       
  1732 			$thisfile_wavpack_flags['noiseshaping']         = (bool) ($thisfile_wavpack['flags_raw'] & 0x000100);
       
  1733 			$thisfile_wavpack_flags['very_fast_mode']       = (bool) ($thisfile_wavpack['flags_raw'] & 0x000200);
       
  1734 			$thisfile_wavpack_flags['new_high_quality']     = (bool) ($thisfile_wavpack['flags_raw'] & 0x000400);
       
  1735 			$thisfile_wavpack_flags['cancel_extreme']       = (bool) ($thisfile_wavpack['flags_raw'] & 0x000800);
       
  1736 			$thisfile_wavpack_flags['cross_decorrelation']  = (bool) ($thisfile_wavpack['flags_raw'] & 0x001000);
       
  1737 			$thisfile_wavpack_flags['new_decorrelation']    = (bool) ($thisfile_wavpack['flags_raw'] & 0x002000);
       
  1738 			$thisfile_wavpack_flags['joint_stereo']         = (bool) ($thisfile_wavpack['flags_raw'] & 0x004000);
       
  1739 			$thisfile_wavpack_flags['extra_decorrelation']  = (bool) ($thisfile_wavpack['flags_raw'] & 0x008000);
       
  1740 			$thisfile_wavpack_flags['override_noiseshape']  = (bool) ($thisfile_wavpack['flags_raw'] & 0x010000);
       
  1741 			$thisfile_wavpack_flags['override_jointstereo'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x020000);
       
  1742 			$thisfile_wavpack_flags['copy_source_filetime'] = (bool) ($thisfile_wavpack['flags_raw'] & 0x040000);
       
  1743 			$thisfile_wavpack_flags['create_exe']           = (bool) ($thisfile_wavpack['flags_raw'] & 0x080000);
       
  1744 		}
       
  1745 
       
  1746 		return true;
       
  1747 	}
       
  1748 
       
  1749 	public static function ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true) {
       
  1750 
       
  1751 		$parsed['biSize']          = substr($BITMAPINFOHEADER,  0, 4); // number of bytes required by the BITMAPINFOHEADER structure
       
  1752 		$parsed['biWidth']         = substr($BITMAPINFOHEADER,  4, 4); // width of the bitmap in pixels
       
  1753 		$parsed['biHeight']        = substr($BITMAPINFOHEADER,  8, 4); // height of the bitmap in pixels. If biHeight is positive, the bitmap is a 'bottom-up' DIB and its origin is the lower left corner. If biHeight is negative, the bitmap is a 'top-down' DIB and its origin is the upper left corner
       
  1754 		$parsed['biPlanes']        = substr($BITMAPINFOHEADER, 12, 2); // number of color planes on the target device. In most cases this value must be set to 1
       
  1755 		$parsed['biBitCount']      = substr($BITMAPINFOHEADER, 14, 2); // Specifies the number of bits per pixels
       
  1756 		$parsed['biSizeImage']     = substr($BITMAPINFOHEADER, 20, 4); // size of the bitmap data section of the image (the actual pixel data, excluding BITMAPINFOHEADER and RGBQUAD structures)
       
  1757 		$parsed['biXPelsPerMeter'] = substr($BITMAPINFOHEADER, 24, 4); // horizontal resolution, in pixels per metre, of the target device
       
  1758 		$parsed['biYPelsPerMeter'] = substr($BITMAPINFOHEADER, 28, 4); // vertical resolution, in pixels per metre, of the target device
       
  1759 		$parsed['biClrUsed']       = substr($BITMAPINFOHEADER, 32, 4); // actual number of color indices in the color table used by the bitmap. If this value is zero, the bitmap uses the maximum number of colors corresponding to the value of the biBitCount member for the compression mode specified by biCompression
       
  1760 		$parsed['biClrImportant']  = substr($BITMAPINFOHEADER, 36, 4); // number of color indices that are considered important for displaying the bitmap. If this value is zero, all colors are important
       
  1761 		$parsed = array_map('getid3_lib::'.($littleEndian ? 'Little' : 'Big').'Endian2Int', $parsed);
       
  1762 
       
  1763 		$parsed['fourcc']          = substr($BITMAPINFOHEADER, 16, 4);  // compression identifier
       
  1764 
       
  1765 		return $parsed;
       
  1766 	}
       
  1767 
       
  1768 	public static function ParseDIVXTAG($DIVXTAG, $raw=false) {
       
  1769 		// structure from "IDivX" source, Form1.frm, by "Greg Frazier of Daemonic Software Group", email: gfrazier@icestorm.net, web: http://dsg.cjb.net/
       
  1770 		// source available at http://files.divx-digest.com/download/c663efe7ef8ad2e90bf4af4d3ea6188a/on0SWN2r/edit/IDivX.zip
       
  1771 		// 'Byte Layout:                   '1111111111111111
       
  1772 		// '32 for Movie - 1               '1111111111111111
       
  1773 		// '28 for Author - 6              '6666666666666666
       
  1774 		// '4  for year - 2                '6666666666662222
       
  1775 		// '3  for genre - 3               '7777777777777777
       
  1776 		// '48 for Comments - 7            '7777777777777777
       
  1777 		// '1  for Rating - 4              '7777777777777777
       
  1778 		// '5  for Future Additions - 0    '333400000DIVXTAG
       
  1779 		// '128 bytes total
       
  1780 
       
  1781 		static $DIVXTAGgenre  = array(
       
  1782 			 0 => 'Action',
       
  1783 			 1 => 'Action/Adventure',
       
  1784 			 2 => 'Adventure',
       
  1785 			 3 => 'Adult',
       
  1786 			 4 => 'Anime',
       
  1787 			 5 => 'Cartoon',
       
  1788 			 6 => 'Claymation',
       
  1789 			 7 => 'Comedy',
       
  1790 			 8 => 'Commercial',
       
  1791 			 9 => 'Documentary',
       
  1792 			10 => 'Drama',
       
  1793 			11 => 'Home Video',
       
  1794 			12 => 'Horror',
       
  1795 			13 => 'Infomercial',
       
  1796 			14 => 'Interactive',
       
  1797 			15 => 'Mystery',
       
  1798 			16 => 'Music Video',
       
  1799 			17 => 'Other',
       
  1800 			18 => 'Religion',
       
  1801 			19 => 'Sci Fi',
       
  1802 			20 => 'Thriller',
       
  1803 			21 => 'Western',
       
  1804 		),
       
  1805 		$DIVXTAGrating = array(
       
  1806 			 0 => 'Unrated',
       
  1807 			 1 => 'G',
       
  1808 			 2 => 'PG',
       
  1809 			 3 => 'PG-13',
       
  1810 			 4 => 'R',
       
  1811 			 5 => 'NC-17',
       
  1812 		);
       
  1813 
       
  1814 		$parsed['title']     =        trim(substr($DIVXTAG,   0, 32));
       
  1815 		$parsed['artist']    =        trim(substr($DIVXTAG,  32, 28));
       
  1816 		$parsed['year']      = intval(trim(substr($DIVXTAG,  60,  4)));
       
  1817 		$parsed['comment']   =        trim(substr($DIVXTAG,  64, 48));
       
  1818 		$parsed['genre_id']  = intval(trim(substr($DIVXTAG, 112,  3)));
       
  1819 		$parsed['rating_id'] =         ord(substr($DIVXTAG, 115,  1));
       
  1820 		//$parsed['padding'] =             substr($DIVXTAG, 116,  5);  // 5-byte null
       
  1821 		//$parsed['magic']   =             substr($DIVXTAG, 121,  7);  // "DIVXTAG"
       
  1822 
       
  1823 		$parsed['genre']  = (isset($DIVXTAGgenre[$parsed['genre_id']])   ? $DIVXTAGgenre[$parsed['genre_id']]   : $parsed['genre_id']);
       
  1824 		$parsed['rating'] = (isset($DIVXTAGrating[$parsed['rating_id']]) ? $DIVXTAGrating[$parsed['rating_id']] : $parsed['rating_id']);
       
  1825 
       
  1826 		if (!$raw) {
       
  1827 			unset($parsed['genre_id'], $parsed['rating_id']);
       
  1828 			foreach ($parsed as $key => $value) {
       
  1829 				if (!$value === '') {
       
  1830 					unset($parsed['key']);
       
  1831 				}
       
  1832 			}
       
  1833 		}
       
  1834 
       
  1835 		foreach ($parsed as $tag => $value) {
       
  1836 			$parsed[$tag] = array($value);
       
  1837 		}
       
  1838 
       
  1839 		return $parsed;
       
  1840 	}
       
  1841 
       
  1842 	public static function waveSNDMtagLookup($tagshortname) {
       
  1843 		$begin = __LINE__;
       
  1844 
       
  1845 		/** This is not a comment!
       
  1846 
       
  1847 			©kwd	keywords
       
  1848 			©BPM	bpm
       
  1849 			©trt	tracktitle
       
  1850 			©des	description
       
  1851 			©gen	category
       
  1852 			©fin	featuredinstrument
       
  1853 			©LID	longid
       
  1854 			©bex	bwdescription
       
  1855 			©pub	publisher
       
  1856 			©cdt	cdtitle
       
  1857 			©alb	library
       
  1858 			©com	composer
       
  1859 
       
  1860 		*/
       
  1861 
       
  1862 		return getid3_lib::EmbeddedLookup($tagshortname, $begin, __LINE__, __FILE__, 'riff-sndm');
       
  1863 	}
       
  1864 
       
  1865 	public static function wFormatTagLookup($wFormatTag) {
       
  1866 
       
  1867 		$begin = __LINE__;
       
  1868 
       
  1869 		/** This is not a comment!
       
  1870 
       
  1871 			0x0000	Microsoft Unknown Wave Format
       
  1872 			0x0001	Pulse Code Modulation (PCM)
       
  1873 			0x0002	Microsoft ADPCM
       
  1874 			0x0003	IEEE Float
       
  1875 			0x0004	Compaq Computer VSELP
       
  1876 			0x0005	IBM CVSD
       
  1877 			0x0006	Microsoft A-Law
       
  1878 			0x0007	Microsoft mu-Law
       
  1879 			0x0008	Microsoft DTS
       
  1880 			0x0010	OKI ADPCM
       
  1881 			0x0011	Intel DVI/IMA ADPCM
       
  1882 			0x0012	Videologic MediaSpace ADPCM
       
  1883 			0x0013	Sierra Semiconductor ADPCM
       
  1884 			0x0014	Antex Electronics G.723 ADPCM
       
  1885 			0x0015	DSP Solutions DigiSTD
       
  1886 			0x0016	DSP Solutions DigiFIX
       
  1887 			0x0017	Dialogic OKI ADPCM
       
  1888 			0x0018	MediaVision ADPCM
       
  1889 			0x0019	Hewlett-Packard CU
       
  1890 			0x0020	Yamaha ADPCM
       
  1891 			0x0021	Speech Compression Sonarc
       
  1892 			0x0022	DSP Group TrueSpeech
       
  1893 			0x0023	Echo Speech EchoSC1
       
  1894 			0x0024	Audiofile AF36
       
  1895 			0x0025	Audio Processing Technology APTX
       
  1896 			0x0026	AudioFile AF10
       
  1897 			0x0027	Prosody 1612
       
  1898 			0x0028	LRC
       
  1899 			0x0030	Dolby AC2
       
  1900 			0x0031	Microsoft GSM 6.10
       
  1901 			0x0032	MSNAudio
       
  1902 			0x0033	Antex Electronics ADPCME
       
  1903 			0x0034	Control Resources VQLPC
       
  1904 			0x0035	DSP Solutions DigiREAL
       
  1905 			0x0036	DSP Solutions DigiADPCM
       
  1906 			0x0037	Control Resources CR10
       
  1907 			0x0038	Natural MicroSystems VBXADPCM
       
  1908 			0x0039	Crystal Semiconductor IMA ADPCM
       
  1909 			0x003A	EchoSC3
       
  1910 			0x003B	Rockwell ADPCM
       
  1911 			0x003C	Rockwell Digit LK
       
  1912 			0x003D	Xebec
       
  1913 			0x0040	Antex Electronics G.721 ADPCM
       
  1914 			0x0041	G.728 CELP
       
  1915 			0x0042	MSG723
       
  1916 			0x0050	MPEG Layer-2 or Layer-1
       
  1917 			0x0052	RT24
       
  1918 			0x0053	PAC
       
  1919 			0x0055	MPEG Layer-3
       
  1920 			0x0059	Lucent G.723
       
  1921 			0x0060	Cirrus
       
  1922 			0x0061	ESPCM
       
  1923 			0x0062	Voxware
       
  1924 			0x0063	Canopus Atrac
       
  1925 			0x0064	G.726 ADPCM
       
  1926 			0x0065	G.722 ADPCM
       
  1927 			0x0066	DSAT
       
  1928 			0x0067	DSAT Display
       
  1929 			0x0069	Voxware Byte Aligned
       
  1930 			0x0070	Voxware AC8
       
  1931 			0x0071	Voxware AC10
       
  1932 			0x0072	Voxware AC16
       
  1933 			0x0073	Voxware AC20
       
  1934 			0x0074	Voxware MetaVoice
       
  1935 			0x0075	Voxware MetaSound
       
  1936 			0x0076	Voxware RT29HW
       
  1937 			0x0077	Voxware VR12
       
  1938 			0x0078	Voxware VR18
       
  1939 			0x0079	Voxware TQ40
       
  1940 			0x0080	Softsound
       
  1941 			0x0081	Voxware TQ60
       
  1942 			0x0082	MSRT24
       
  1943 			0x0083	G.729A
       
  1944 			0x0084	MVI MV12
       
  1945 			0x0085	DF G.726
       
  1946 			0x0086	DF GSM610
       
  1947 			0x0088	ISIAudio
       
  1948 			0x0089	Onlive
       
  1949 			0x0091	SBC24
       
  1950 			0x0092	Dolby AC3 SPDIF
       
  1951 			0x0093	MediaSonic G.723
       
  1952 			0x0094	Aculab PLC    Prosody 8kbps
       
  1953 			0x0097	ZyXEL ADPCM
       
  1954 			0x0098	Philips LPCBB
       
  1955 			0x0099	Packed
       
  1956 			0x00FF	AAC
       
  1957 			0x0100	Rhetorex ADPCM
       
  1958 			0x0101	IBM mu-law
       
  1959 			0x0102	IBM A-law
       
  1960 			0x0103	IBM AVC Adaptive Differential Pulse Code Modulation (ADPCM)
       
  1961 			0x0111	Vivo G.723
       
  1962 			0x0112	Vivo Siren
       
  1963 			0x0123	Digital G.723
       
  1964 			0x0125	Sanyo LD ADPCM
       
  1965 			0x0130	Sipro Lab Telecom ACELP NET
       
  1966 			0x0131	Sipro Lab Telecom ACELP 4800
       
  1967 			0x0132	Sipro Lab Telecom ACELP 8V3
       
  1968 			0x0133	Sipro Lab Telecom G.729
       
  1969 			0x0134	Sipro Lab Telecom G.729A
       
  1970 			0x0135	Sipro Lab Telecom Kelvin
       
  1971 			0x0140	Windows Media Video V8
       
  1972 			0x0150	Qualcomm PureVoice
       
  1973 			0x0151	Qualcomm HalfRate
       
  1974 			0x0155	Ring Zero Systems TUB GSM
       
  1975 			0x0160	Microsoft Audio 1
       
  1976 			0x0161	Windows Media Audio V7 / V8 / V9
       
  1977 			0x0162	Windows Media Audio Professional V9
       
  1978 			0x0163	Windows Media Audio Lossless V9
       
  1979 			0x0200	Creative Labs ADPCM
       
  1980 			0x0202	Creative Labs Fastspeech8
       
  1981 			0x0203	Creative Labs Fastspeech10
       
  1982 			0x0210	UHER Informatic GmbH ADPCM
       
  1983 			0x0220	Quarterdeck
       
  1984 			0x0230	I-link Worldwide VC
       
  1985 			0x0240	Aureal RAW Sport
       
  1986 			0x0250	Interactive Products HSX
       
  1987 			0x0251	Interactive Products RPELP
       
  1988 			0x0260	Consistent Software CS2
       
  1989 			0x0270	Sony SCX
       
  1990 			0x0300	Fujitsu FM Towns Snd
       
  1991 			0x0400	BTV Digital
       
  1992 			0x0401	Intel Music Coder
       
  1993 			0x0450	QDesign Music
       
  1994 			0x0680	VME VMPCM
       
  1995 			0x0681	AT&T Labs TPC
       
  1996 			0x08AE	ClearJump LiteWave
       
  1997 			0x1000	Olivetti GSM
       
  1998 			0x1001	Olivetti ADPCM
       
  1999 			0x1002	Olivetti CELP
       
  2000 			0x1003	Olivetti SBC
       
  2001 			0x1004	Olivetti OPR
       
  2002 			0x1100	Lernout & Hauspie Codec (0x1100)
       
  2003 			0x1101	Lernout & Hauspie CELP Codec (0x1101)
       
  2004 			0x1102	Lernout & Hauspie SBC Codec (0x1102)
       
  2005 			0x1103	Lernout & Hauspie SBC Codec (0x1103)
       
  2006 			0x1104	Lernout & Hauspie SBC Codec (0x1104)
       
  2007 			0x1400	Norris
       
  2008 			0x1401	AT&T ISIAudio
       
  2009 			0x1500	Soundspace Music Compression
       
  2010 			0x181C	VoxWare RT24 Speech
       
  2011 			0x1FC4	NCT Soft ALF2CD (www.nctsoft.com)
       
  2012 			0x2000	Dolby AC3
       
  2013 			0x2001	Dolby DTS
       
  2014 			0x2002	WAVE_FORMAT_14_4
       
  2015 			0x2003	WAVE_FORMAT_28_8
       
  2016 			0x2004	WAVE_FORMAT_COOK
       
  2017 			0x2005	WAVE_FORMAT_DNET
       
  2018 			0x674F	Ogg Vorbis 1
       
  2019 			0x6750	Ogg Vorbis 2
       
  2020 			0x6751	Ogg Vorbis 3
       
  2021 			0x676F	Ogg Vorbis 1+
       
  2022 			0x6770	Ogg Vorbis 2+
       
  2023 			0x6771	Ogg Vorbis 3+
       
  2024 			0x7A21	GSM-AMR (CBR, no SID)
       
  2025 			0x7A22	GSM-AMR (VBR, including SID)
       
  2026 			0xFFFE	WAVE_FORMAT_EXTENSIBLE
       
  2027 			0xFFFF	WAVE_FORMAT_DEVELOPMENT
       
  2028 
       
  2029 		*/
       
  2030 
       
  2031 		return getid3_lib::EmbeddedLookup('0x'.str_pad(strtoupper(dechex($wFormatTag)), 4, '0', STR_PAD_LEFT), $begin, __LINE__, __FILE__, 'riff-wFormatTag');
       
  2032 	}
       
  2033 
       
  2034 	public static function fourccLookup($fourcc) {
       
  2035 
       
  2036 		$begin = __LINE__;
       
  2037 
       
  2038 		/** This is not a comment!
       
  2039 
       
  2040 			swot	http://developer.apple.com/qa/snd/snd07.html
       
  2041 			____	No Codec (____)
       
  2042 			_BIT	BI_BITFIELDS (Raw RGB)
       
  2043 			_JPG	JPEG compressed
       
  2044 			_PNG	PNG compressed W3C/ISO/IEC (RFC-2083)
       
  2045 			_RAW	Full Frames (Uncompressed)
       
  2046 			_RGB	Raw RGB Bitmap
       
  2047 			_RL4	RLE 4bpp RGB
       
  2048 			_RL8	RLE 8bpp RGB
       
  2049 			3IV1	3ivx MPEG-4 v1
       
  2050 			3IV2	3ivx MPEG-4 v2
       
  2051 			3IVX	3ivx MPEG-4
       
  2052 			AASC	Autodesk Animator
       
  2053 			ABYR	Kensington ?ABYR?
       
  2054 			AEMI	Array Microsystems VideoONE MPEG1-I Capture
       
  2055 			AFLC	Autodesk Animator FLC
       
  2056 			AFLI	Autodesk Animator FLI
       
  2057 			AMPG	Array Microsystems VideoONE MPEG
       
  2058 			ANIM	Intel RDX (ANIM)
       
  2059 			AP41	AngelPotion Definitive
       
  2060 			ASV1	Asus Video v1
       
  2061 			ASV2	Asus Video v2
       
  2062 			ASVX	Asus Video 2.0 (audio)
       
  2063 			AUR2	AuraVision Aura 2 Codec - YUV 4:2:2
       
  2064 			AURA	AuraVision Aura 1 Codec - YUV 4:1:1
       
  2065 			AVDJ	Independent JPEG Group\'s codec (AVDJ)
       
  2066 			AVRN	Independent JPEG Group\'s codec (AVRN)
       
  2067 			AYUV	4:4:4 YUV (AYUV)
       
  2068 			AZPR	Quicktime Apple Video (AZPR)
       
  2069 			BGR 	Raw RGB32
       
  2070 			BLZ0	Blizzard DivX MPEG-4
       
  2071 			BTVC	Conexant Composite Video
       
  2072 			BINK	RAD Game Tools Bink Video
       
  2073 			BT20	Conexant Prosumer Video
       
  2074 			BTCV	Conexant Composite Video Codec
       
  2075 			BW10	Data Translation Broadway MPEG Capture
       
  2076 			CC12	Intel YUV12
       
  2077 			CDVC	Canopus DV
       
  2078 			CFCC	Digital Processing Systems DPS Perception
       
  2079 			CGDI	Microsoft Office 97 Camcorder Video
       
  2080 			CHAM	Winnov Caviara Champagne
       
  2081 			CJPG	Creative WebCam JPEG
       
  2082 			CLJR	Cirrus Logic YUV 4:1:1
       
  2083 			CMYK	Common Data Format in Printing (Colorgraph)
       
  2084 			CPLA	Weitek 4:2:0 YUV Planar
       
  2085 			CRAM	Microsoft Video 1 (CRAM)
       
  2086 			cvid	Radius Cinepak
       
  2087 			CVID	Radius Cinepak
       
  2088 			CWLT	Microsoft Color WLT DIB
       
  2089 			CYUV	Creative Labs YUV
       
  2090 			CYUY	ATI YUV
       
  2091 			D261	H.261
       
  2092 			D263	H.263
       
  2093 			DIB 	Device Independent Bitmap
       
  2094 			DIV1	FFmpeg OpenDivX
       
  2095 			DIV2	Microsoft MPEG-4 v1/v2
       
  2096 			DIV3	DivX ;-) MPEG-4 v3.x Low-Motion
       
  2097 			DIV4	DivX ;-) MPEG-4 v3.x Fast-Motion
       
  2098 			DIV5	DivX MPEG-4 v5.x
       
  2099 			DIV6	DivX ;-) (MS MPEG-4 v3.x)
       
  2100 			DIVX	DivX MPEG-4 v4 (OpenDivX / Project Mayo)
       
  2101 			divx	DivX MPEG-4
       
  2102 			DMB1	Matrox Rainbow Runner hardware MJPEG
       
  2103 			DMB2	Paradigm MJPEG
       
  2104 			DSVD	?DSVD?
       
  2105 			DUCK	Duck TrueMotion 1.0
       
  2106 			DPS0	DPS/Leitch Reality Motion JPEG
       
  2107 			DPSC	DPS/Leitch PAR Motion JPEG
       
  2108 			DV25	Matrox DVCPRO codec
       
  2109 			DV50	Matrox DVCPRO50 codec
       
  2110 			DVC 	IEC 61834 and SMPTE 314M (DVC/DV Video)
       
  2111 			DVCP	IEC 61834 and SMPTE 314M (DVC/DV Video)
       
  2112 			DVHD	IEC Standard DV 1125 lines @ 30fps / 1250 lines @ 25fps
       
  2113 			DVMA	Darim Vision DVMPEG (dummy for MPEG compressor) (www.darvision.com)
       
  2114 			DVSL	IEC Standard DV compressed in SD (SDL)
       
  2115 			DVAN	?DVAN?
       
  2116 			DVE2	InSoft DVE-2 Videoconferencing
       
  2117 			dvsd	IEC 61834 and SMPTE 314M DVC/DV Video
       
  2118 			DVSD	IEC 61834 and SMPTE 314M DVC/DV Video
       
  2119 			DVX1	Lucent DVX1000SP Video Decoder
       
  2120 			DVX2	Lucent DVX2000S Video Decoder
       
  2121 			DVX3	Lucent DVX3000S Video Decoder
       
  2122 			DX50	DivX v5
       
  2123 			DXT1	Microsoft DirectX Compressed Texture (DXT1)
       
  2124 			DXT2	Microsoft DirectX Compressed Texture (DXT2)
       
  2125 			DXT3	Microsoft DirectX Compressed Texture (DXT3)
       
  2126 			DXT4	Microsoft DirectX Compressed Texture (DXT4)
       
  2127 			DXT5	Microsoft DirectX Compressed Texture (DXT5)
       
  2128 			DXTC	Microsoft DirectX Compressed Texture (DXTC)
       
  2129 			DXTn	Microsoft DirectX Compressed Texture (DXTn)
       
  2130 			EM2V	Etymonix MPEG-2 I-frame (www.etymonix.com)
       
  2131 			EKQ0	Elsa ?EKQ0?
       
  2132 			ELK0	Elsa ?ELK0?
       
  2133 			ESCP	Eidos Escape
       
  2134 			ETV1	eTreppid Video ETV1
       
  2135 			ETV2	eTreppid Video ETV2
       
  2136 			ETVC	eTreppid Video ETVC
       
  2137 			FLIC	Autodesk FLI/FLC Animation
       
  2138 			FLV1	Sorenson Spark
       
  2139 			FLV4	On2 TrueMotion VP6
       
  2140 			FRWT	Darim Vision Forward Motion JPEG (www.darvision.com)
       
  2141 			FRWU	Darim Vision Forward Uncompressed (www.darvision.com)
       
  2142 			FLJP	D-Vision Field Encoded Motion JPEG
       
  2143 			FPS1	FRAPS v1
       
  2144 			FRWA	SoftLab-Nsk Forward Motion JPEG w/ alpha channel
       
  2145 			FRWD	SoftLab-Nsk Forward Motion JPEG
       
  2146 			FVF1	Iterated Systems Fractal Video Frame
       
  2147 			GLZW	Motion LZW (gabest@freemail.hu)
       
  2148 			GPEG	Motion JPEG (gabest@freemail.hu)
       
  2149 			GWLT	Microsoft Greyscale WLT DIB
       
  2150 			H260	Intel ITU H.260 Videoconferencing
       
  2151 			H261	Intel ITU H.261 Videoconferencing
       
  2152 			H262	Intel ITU H.262 Videoconferencing
       
  2153 			H263	Intel ITU H.263 Videoconferencing
       
  2154 			H264	Intel ITU H.264 Videoconferencing
       
  2155 			H265	Intel ITU H.265 Videoconferencing
       
  2156 			H266	Intel ITU H.266 Videoconferencing
       
  2157 			H267	Intel ITU H.267 Videoconferencing
       
  2158 			H268	Intel ITU H.268 Videoconferencing
       
  2159 			H269	Intel ITU H.269 Videoconferencing
       
  2160 			HFYU	Huffman Lossless Codec
       
  2161 			HMCR	Rendition Motion Compensation Format (HMCR)
       
  2162 			HMRR	Rendition Motion Compensation Format (HMRR)
       
  2163 			I263	FFmpeg I263 decoder
       
  2164 			IF09	Indeo YVU9 ("YVU9 with additional delta-frame info after the U plane")
       
  2165 			IUYV	Interlaced version of UYVY (www.leadtools.com)
       
  2166 			IY41	Interlaced version of Y41P (www.leadtools.com)
       
  2167 			IYU1	12 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec    IEEE standard
       
  2168 			IYU2	24 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec    IEEE standard
       
  2169 			IYUV	Planar YUV format (8-bpp Y plane, followed by 8-bpp 2×2 U and V planes)
       
  2170 			i263	Intel ITU H.263 Videoconferencing (i263)
       
  2171 			I420	Intel Indeo 4
       
  2172 			IAN 	Intel Indeo 4 (RDX)
       
  2173 			ICLB	InSoft CellB Videoconferencing
       
  2174 			IGOR	Power DVD
       
  2175 			IJPG	Intergraph JPEG
       
  2176 			ILVC	Intel Layered Video
       
  2177 			ILVR	ITU-T H.263+
       
  2178 			IPDV	I-O Data Device Giga AVI DV Codec
       
  2179 			IR21	Intel Indeo 2.1
       
  2180 			IRAW	Intel YUV Uncompressed
       
  2181 			IV30	Intel Indeo 3.0
       
  2182 			IV31	Intel Indeo 3.1
       
  2183 			IV32	Ligos Indeo 3.2
       
  2184 			IV33	Ligos Indeo 3.3
       
  2185 			IV34	Ligos Indeo 3.4
       
  2186 			IV35	Ligos Indeo 3.5
       
  2187 			IV36	Ligos Indeo 3.6
       
  2188 			IV37	Ligos Indeo 3.7
       
  2189 			IV38	Ligos Indeo 3.8
       
  2190 			IV39	Ligos Indeo 3.9
       
  2191 			IV40	Ligos Indeo Interactive 4.0
       
  2192 			IV41	Ligos Indeo Interactive 4.1
       
  2193 			IV42	Ligos Indeo Interactive 4.2
       
  2194 			IV43	Ligos Indeo Interactive 4.3
       
  2195 			IV44	Ligos Indeo Interactive 4.4
       
  2196 			IV45	Ligos Indeo Interactive 4.5
       
  2197 			IV46	Ligos Indeo Interactive 4.6
       
  2198 			IV47	Ligos Indeo Interactive 4.7
       
  2199 			IV48	Ligos Indeo Interactive 4.8
       
  2200 			IV49	Ligos Indeo Interactive 4.9
       
  2201 			IV50	Ligos Indeo Interactive 5.0
       
  2202 			JBYR	Kensington ?JBYR?
       
  2203 			JPEG	Still Image JPEG DIB
       
  2204 			JPGL	Pegasus Lossless Motion JPEG
       
  2205 			KMVC	Team17 Software Karl Morton\'s Video Codec
       
  2206 			LSVM	Vianet Lighting Strike Vmail (Streaming) (www.vianet.com)
       
  2207 			LEAD	LEAD Video Codec
       
  2208 			Ljpg	LEAD MJPEG Codec
       
  2209 			MDVD	Alex MicroDVD Video (hacked MS MPEG-4) (www.tiasoft.de)
       
  2210 			MJPA	Morgan Motion JPEG (MJPA) (www.morgan-multimedia.com)
       
  2211 			MJPB	Morgan Motion JPEG (MJPB) (www.morgan-multimedia.com)
       
  2212 			MMES	Matrox MPEG-2 I-frame
       
  2213 			MP2v	Microsoft S-Mpeg 4 version 1 (MP2v)
       
  2214 			MP42	Microsoft S-Mpeg 4 version 2 (MP42)
       
  2215 			MP43	Microsoft S-Mpeg 4 version 3 (MP43)
       
  2216 			MP4S	Microsoft S-Mpeg 4 version 3 (MP4S)
       
  2217 			MP4V	FFmpeg MPEG-4
       
  2218 			MPG1	FFmpeg MPEG 1/2
       
  2219 			MPG2	FFmpeg MPEG 1/2
       
  2220 			MPG3	FFmpeg DivX ;-) (MS MPEG-4 v3)
       
  2221 			MPG4	Microsoft MPEG-4
       
  2222 			MPGI	Sigma Designs MPEG
       
  2223 			MPNG	PNG images decoder
       
  2224 			MSS1	Microsoft Windows Screen Video
       
  2225 			MSZH	LCL (Lossless Codec Library) (www.geocities.co.jp/Playtown-Denei/2837/LRC.htm)
       
  2226 			M261	Microsoft H.261
       
  2227 			M263	Microsoft H.263
       
  2228 			M4S2	Microsoft Fully Compliant MPEG-4 v2 simple profile (M4S2)
       
  2229 			m4s2	Microsoft Fully Compliant MPEG-4 v2 simple profile (m4s2)
       
  2230 			MC12	ATI Motion Compensation Format (MC12)
       
  2231 			MCAM	ATI Motion Compensation Format (MCAM)
       
  2232 			MJ2C	Morgan Multimedia Motion JPEG2000
       
  2233 			mJPG	IBM Motion JPEG w/ Huffman Tables
       
  2234 			MJPG	Microsoft Motion JPEG DIB
       
  2235 			MP42	Microsoft MPEG-4 (low-motion)
       
  2236 			MP43	Microsoft MPEG-4 (fast-motion)
       
  2237 			MP4S	Microsoft MPEG-4 (MP4S)
       
  2238 			mp4s	Microsoft MPEG-4 (mp4s)
       
  2239 			MPEG	Chromatic Research MPEG-1 Video I-Frame
       
  2240 			MPG4	Microsoft MPEG-4 Video High Speed Compressor
       
  2241 			MPGI	Sigma Designs MPEG
       
  2242 			MRCA	FAST Multimedia Martin Regen Codec
       
  2243 			MRLE	Microsoft Run Length Encoding
       
  2244 			MSVC	Microsoft Video 1
       
  2245 			MTX1	Matrox ?MTX1?
       
  2246 			MTX2	Matrox ?MTX2?
       
  2247 			MTX3	Matrox ?MTX3?
       
  2248 			MTX4	Matrox ?MTX4?
       
  2249 			MTX5	Matrox ?MTX5?
       
  2250 			MTX6	Matrox ?MTX6?
       
  2251 			MTX7	Matrox ?MTX7?
       
  2252 			MTX8	Matrox ?MTX8?
       
  2253 			MTX9	Matrox ?MTX9?
       
  2254 			MV12	Motion Pixels Codec (old)
       
  2255 			MWV1	Aware Motion Wavelets
       
  2256 			nAVI	SMR Codec (hack of Microsoft MPEG-4) (IRC #shadowrealm)
       
  2257 			NT00	NewTek LightWave HDTV YUV w/ Alpha (www.newtek.com)
       
  2258 			NUV1	NuppelVideo
       
  2259 			NTN1	Nogatech Video Compression 1
       
  2260 			NVS0	nVidia GeForce Texture (NVS0)
       
  2261 			NVS1	nVidia GeForce Texture (NVS1)
       
  2262 			NVS2	nVidia GeForce Texture (NVS2)
       
  2263 			NVS3	nVidia GeForce Texture (NVS3)
       
  2264 			NVS4	nVidia GeForce Texture (NVS4)
       
  2265 			NVS5	nVidia GeForce Texture (NVS5)
       
  2266 			NVT0	nVidia GeForce Texture (NVT0)
       
  2267 			NVT1	nVidia GeForce Texture (NVT1)
       
  2268 			NVT2	nVidia GeForce Texture (NVT2)
       
  2269 			NVT3	nVidia GeForce Texture (NVT3)
       
  2270 			NVT4	nVidia GeForce Texture (NVT4)
       
  2271 			NVT5	nVidia GeForce Texture (NVT5)
       
  2272 			PIXL	MiroXL, Pinnacle PCTV
       
  2273 			PDVC	I-O Data Device Digital Video Capture DV codec
       
  2274 			PGVV	Radius Video Vision
       
  2275 			PHMO	IBM Photomotion
       
  2276 			PIM1	MPEG Realtime (Pinnacle Cards)
       
  2277 			PIM2	Pegasus Imaging ?PIM2?
       
  2278 			PIMJ	Pegasus Imaging Lossless JPEG
       
  2279 			PVEZ	Horizons Technology PowerEZ
       
  2280 			PVMM	PacketVideo Corporation MPEG-4
       
  2281 			PVW2	Pegasus Imaging Wavelet Compression
       
  2282 			Q1.0	Q-Team\'s QPEG 1.0 (www.q-team.de)
       
  2283 			Q1.1	Q-Team\'s QPEG 1.1 (www.q-team.de)
       
  2284 			QPEG	Q-Team QPEG 1.0
       
  2285 			qpeq	Q-Team QPEG 1.1
       
  2286 			RGB 	Raw BGR32
       
  2287 			RGBA	Raw RGB w/ Alpha
       
  2288 			RMP4	REALmagic MPEG-4 (unauthorized XVID copy) (www.sigmadesigns.com)
       
  2289 			ROQV	Id RoQ File Video Decoder
       
  2290 			RPZA	Quicktime Apple Video (RPZA)
       
  2291 			RUD0	Rududu video codec (http://rududu.ifrance.com/rududu/)
       
  2292 			RV10	RealVideo 1.0 (aka RealVideo 5.0)
       
  2293 			RV13	RealVideo 1.0 (RV13)
       
  2294 			RV20	RealVideo G2
       
  2295 			RV30	RealVideo 8
       
  2296 			RV40	RealVideo 9
       
  2297 			RGBT	Raw RGB w/ Transparency
       
  2298 			RLE 	Microsoft Run Length Encoder
       
  2299 			RLE4	Run Length Encoded (4bpp, 16-color)
       
  2300 			RLE8	Run Length Encoded (8bpp, 256-color)
       
  2301 			RT21	Intel Indeo RealTime Video 2.1
       
  2302 			rv20	RealVideo G2
       
  2303 			rv30	RealVideo 8
       
  2304 			RVX 	Intel RDX (RVX )
       
  2305 			SMC 	Apple Graphics (SMC )
       
  2306 			SP54	Logitech Sunplus Sp54 Codec for Mustek GSmart Mini 2
       
  2307 			SPIG	Radius Spigot
       
  2308 			SVQ3	Sorenson Video 3 (Apple Quicktime 5)
       
  2309 			s422	Tekram VideoCap C210 YUV 4:2:2
       
  2310 			SDCC	Sun Communication Digital Camera Codec
       
  2311 			SFMC	CrystalNet Surface Fitting Method
       
  2312 			SMSC	Radius SMSC
       
  2313 			SMSD	Radius SMSD
       
  2314 			smsv	WorldConnect Wavelet Video
       
  2315 			SPIG	Radius Spigot
       
  2316 			SPLC	Splash Studios ACM Audio Codec (www.splashstudios.net)
       
  2317 			SQZ2	Microsoft VXTreme Video Codec V2
       
  2318 			STVA	ST Microelectronics CMOS Imager Data (Bayer)
       
  2319 			STVB	ST Microelectronics CMOS Imager Data (Nudged Bayer)
       
  2320 			STVC	ST Microelectronics CMOS Imager Data (Bunched)
       
  2321 			STVX	ST Microelectronics CMOS Imager Data (Extended CODEC Data Format)
       
  2322 			STVY	ST Microelectronics CMOS Imager Data (Extended CODEC Data Format with Correction Data)
       
  2323 			SV10	Sorenson Video R1
       
  2324 			SVQ1	Sorenson Video
       
  2325 			T420	Toshiba YUV 4:2:0
       
  2326 			TM2A	Duck TrueMotion Archiver 2.0 (www.duck.com)
       
  2327 			TVJP	Pinnacle/Truevision Targa 2000 board (TVJP)
       
  2328 			TVMJ	Pinnacle/Truevision Targa 2000 board (TVMJ)
       
  2329 			TY0N	Tecomac Low-Bit Rate Codec (www.tecomac.com)
       
  2330 			TY2C	Trident Decompression Driver
       
  2331 			TLMS	TeraLogic Motion Intraframe Codec (TLMS)
       
  2332 			TLST	TeraLogic Motion Intraframe Codec (TLST)
       
  2333 			TM20	Duck TrueMotion 2.0
       
  2334 			TM2X	Duck TrueMotion 2X
       
  2335 			TMIC	TeraLogic Motion Intraframe Codec (TMIC)
       
  2336 			TMOT	Horizons Technology TrueMotion S
       
  2337 			tmot	Horizons TrueMotion Video Compression
       
  2338 			TR20	Duck TrueMotion RealTime 2.0
       
  2339 			TSCC	TechSmith Screen Capture Codec
       
  2340 			TV10	Tecomac Low-Bit Rate Codec
       
  2341 			TY2N	Trident ?TY2N?
       
  2342 			U263	UB Video H.263/H.263+/H.263++ Decoder
       
  2343 			UMP4	UB Video MPEG 4 (www.ubvideo.com)
       
  2344 			UYNV	Nvidia UYVY packed 4:2:2
       
  2345 			UYVP	Evans & Sutherland YCbCr 4:2:2 extended precision
       
  2346 			UCOD	eMajix.com ClearVideo
       
  2347 			ULTI	IBM Ultimotion
       
  2348 			UYVY	UYVY packed 4:2:2
       
  2349 			V261	Lucent VX2000S
       
  2350 			VIFP	VFAPI Reader Codec (www.yks.ne.jp/~hori/)
       
  2351 			VIV1	FFmpeg H263+ decoder
       
  2352 			VIV2	Vivo H.263
       
  2353 			VQC2	Vector-quantised codec 2 (research) http://eprints.ecs.soton.ac.uk/archive/00001310/01/VTC97-js.pdf)
       
  2354 			VTLP	Alaris VideoGramPiX
       
  2355 			VYU9	ATI YUV (VYU9)
       
  2356 			VYUY	ATI YUV (VYUY)
       
  2357 			V261	Lucent VX2000S
       
  2358 			V422	Vitec Multimedia 24-bit YUV 4:2:2 Format
       
  2359 			V655	Vitec Multimedia 16-bit YUV 4:2:2 Format
       
  2360 			VCR1	ATI Video Codec 1
       
  2361 			VCR2	ATI Video Codec 2
       
  2362 			VCR3	ATI VCR 3.0
       
  2363 			VCR4	ATI VCR 4.0
       
  2364 			VCR5	ATI VCR 5.0
       
  2365 			VCR6	ATI VCR 6.0
       
  2366 			VCR7	ATI VCR 7.0
       
  2367 			VCR8	ATI VCR 8.0
       
  2368 			VCR9	ATI VCR 9.0
       
  2369 			VDCT	Vitec Multimedia Video Maker Pro DIB
       
  2370 			VDOM	VDOnet VDOWave
       
  2371 			VDOW	VDOnet VDOLive (H.263)
       
  2372 			VDTZ	Darim Vison VideoTizer YUV
       
  2373 			VGPX	Alaris VideoGramPiX
       
  2374 			VIDS	Vitec Multimedia YUV 4:2:2 CCIR 601 for V422
       
  2375 			VIVO	Vivo H.263 v2.00
       
  2376 			vivo	Vivo H.263
       
  2377 			VIXL	Miro/Pinnacle Video XL
       
  2378 			VLV1	VideoLogic/PURE Digital Videologic Capture
       
  2379 			VP30	On2 VP3.0
       
  2380 			VP31	On2 VP3.1
       
  2381 			VP6F	On2 TrueMotion VP6
       
  2382 			VX1K	Lucent VX1000S Video Codec
       
  2383 			VX2K	Lucent VX2000S Video Codec
       
  2384 			VXSP	Lucent VX1000SP Video Codec
       
  2385 			WBVC	Winbond W9960
       
  2386 			WHAM	Microsoft Video 1 (WHAM)
       
  2387 			WINX	Winnov Software Compression
       
  2388 			WJPG	AverMedia Winbond JPEG
       
  2389 			WMV1	Windows Media Video V7
       
  2390 			WMV2	Windows Media Video V8
       
  2391 			WMV3	Windows Media Video V9
       
  2392 			WNV1	Winnov Hardware Compression
       
  2393 			XYZP	Extended PAL format XYZ palette (www.riff.org)
       
  2394 			x263	Xirlink H.263
       
  2395 			XLV0	NetXL Video Decoder
       
  2396 			XMPG	Xing MPEG (I-Frame only)
       
  2397 			XVID	XviD MPEG-4 (www.xvid.org)
       
  2398 			XXAN	?XXAN?
       
  2399 			YU92	Intel YUV (YU92)
       
  2400 			YUNV	Nvidia Uncompressed YUV 4:2:2
       
  2401 			YUVP	Extended PAL format YUV palette (www.riff.org)
       
  2402 			Y211	YUV 2:1:1 Packed
       
  2403 			Y411	YUV 4:1:1 Packed
       
  2404 			Y41B	Weitek YUV 4:1:1 Planar
       
  2405 			Y41P	Brooktree PC1 YUV 4:1:1 Packed
       
  2406 			Y41T	Brooktree PC1 YUV 4:1:1 with transparency
       
  2407 			Y42B	Weitek YUV 4:2:2 Planar
       
  2408 			Y42T	Brooktree UYUV 4:2:2 with transparency
       
  2409 			Y422	ADS Technologies Copy of UYVY used in Pyro WebCam firewire camera
       
  2410 			Y800	Simple, single Y plane for monochrome images
       
  2411 			Y8  	Grayscale video
       
  2412 			YC12	Intel YUV 12 codec
       
  2413 			YUV8	Winnov Caviar YUV8
       
  2414 			YUV9	Intel YUV9
       
  2415 			YUY2	Uncompressed YUV 4:2:2
       
  2416 			YUYV	Canopus YUV
       
  2417 			YV12	YVU12 Planar
       
  2418 			YVU9	Intel YVU9 Planar (8-bpp Y plane, followed by 8-bpp 4x4 U and V planes)
       
  2419 			YVYU	YVYU 4:2:2 Packed
       
  2420 			ZLIB	Lossless Codec Library zlib compression (www.geocities.co.jp/Playtown-Denei/2837/LRC.htm)
       
  2421 			ZPEG	Metheus Video Zipper
       
  2422 
       
  2423 		*/
       
  2424 
       
  2425 		return getid3_lib::EmbeddedLookup($fourcc, $begin, __LINE__, __FILE__, 'riff-fourcc');
       
  2426 	}
       
  2427 
       
  2428 	private function EitherEndian2Int($byteword, $signed=false) {
       
  2429 		if ($this->getid3->info['fileformat'] == 'riff') {
       
  2430 			return getid3_lib::LittleEndian2Int($byteword, $signed);
       
  2431 		}
       
  2432 		return getid3_lib::BigEndian2Int($byteword, false, $signed);
       
  2433 	}
       
  2434 
       
  2435 }