[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

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


Generated: Sat Nov 23 20:47:33 2019 Cross-referenced by PHPXref 0.7