PageRenderTime 65ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/getid3/module.audio-video.riff.php

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