[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/ID3/ -> module.audio-video.riff.php (source)

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


Generated: Tue Dec 1 01:00:04 2020 Cross-referenced by PHPXref 0.7.1