22 fseek($fd, $ThisFileInfo[
'avdataoffset'], SEEK_SET);
26 $wavpackheader = fread($fd, 32);
28 if (ftell($fd) >= $ThisFileInfo[
'avdataend']) {
30 } elseif (feof($fd)) {
33 (@$ThisFileInfo[
'wavpack'][
'blockheader'][
'total_samples'] > 0) &&
34 (@$ThisFileInfo[
'wavpack'][
'blockheader'][
'block_samples'] > 0) &&
35 (!isset($ThisFileInfo[
'wavpack'][
'riff_trailer_size']) || ($ThisFileInfo[
'wavpack'][
'riff_trailer_size'] <= 0)) &&
36 ((@$ThisFileInfo[
'wavpack'][
'config_flags'][
'md5_checksum'] ===
false) || !empty($ThisFileInfo[
'md5_data_source']))) {
40 $blockheader_offset = ftell($fd) - 32;
41 $blockheader_magic = substr($wavpackheader, 0, 4);
44 if ($blockheader_magic !=
'wvpk') {
45 $ThisFileInfo[
'error'][] =
'Expecting "wvpk" at offset '.$blockheader_offset.
', found "'.$blockheader_magic.
'"';
46 if ((@$ThisFileInfo[
'audio'][
'dataformat'] !=
'wavpack') && (@$ThisFileInfo[
'audio'][
'dataformat'] !=
'wvc')) {
47 unset($ThisFileInfo[
'fileformat']);
48 unset($ThisFileInfo[
'audio']);
49 unset($ThisFileInfo[
'wavpack']);
55 if ((@$ThisFileInfo[
'wavpack'][
'blockheader'][
'block_samples'] <= 0) ||
56 (@$ThisFileInfo[
'wavpack'][
'blockheader'][
'total_samples'] <= 0)) {
68 $ThisFileInfo[
'audio'][
'dataformat'] =
'wavpack';
69 $ThisFileInfo[
'fileformat'] =
'wavpack';
70 $ThisFileInfo[
'audio'][
'lossless'] =
true;
71 $ThisFileInfo[
'audio'][
'bitrate_mode'] =
'vbr';
73 $ThisFileInfo[
'wavpack'][
'blockheader'][
'offset'] = $blockheader_offset;
74 $ThisFileInfo[
'wavpack'][
'blockheader'][
'magic'] = $blockheader_magic;
75 $ThisFileInfo[
'wavpack'][
'blockheader'][
'size'] = $blockheader_size;
77 if ($ThisFileInfo[
'wavpack'][
'blockheader'][
'size'] >= 0x100000) {
78 $ThisFileInfo[
'error'][] =
'Expecting WavPack block size less than "0x100000", found "'.$ThisFileInfo[
'wavpack'][
'blockheader'][
'size'].
'" at offset '.$ThisFileInfo[
'wavpack'][
'blockheader'][
'offset'];
79 if ((@$ThisFileInfo[
'audio'][
'dataformat'] !=
'wavpack') && (@$ThisFileInfo[
'audio'][
'dataformat'] !=
'wvc')) {
80 unset($ThisFileInfo[
'fileformat']);
81 unset($ThisFileInfo[
'audio']);
82 unset($ThisFileInfo[
'wavpack']);
87 $ThisFileInfo[
'wavpack'][
'blockheader'][
'minor_version'] = ord($wavpackheader{8});
88 $ThisFileInfo[
'wavpack'][
'blockheader'][
'major_version'] = ord($wavpackheader{9});
90 if (($ThisFileInfo[
'wavpack'][
'blockheader'][
'major_version'] != 4) ||
91 (($ThisFileInfo[
'wavpack'][
'blockheader'][
'minor_version'] < 4) &&
92 ($ThisFileInfo[
'wavpack'][
'blockheader'][
'minor_version'] > 16))) {
93 $ThisFileInfo[
'error'][] =
'Expecting WavPack version between "4.2" and "4.16", found version "'.$ThisFileInfo[
'wavpack'][
'blockheader'][
'major_version'].
'.'.$ThisFileInfo[
'wavpack'][
'blockheader'][
'minor_version'].
'" at offset '.$ThisFileInfo[
'wavpack'][
'blockheader'][
'offset'];
94 if ((@$ThisFileInfo[
'audio'][
'dataformat'] !=
'wavpack') && (@$ThisFileInfo[
'audio'][
'dataformat'] !=
'wvc')) {
95 unset($ThisFileInfo[
'fileformat']);
96 unset($ThisFileInfo[
'audio']);
97 unset($ThisFileInfo[
'wavpack']);
102 $ThisFileInfo[
'wavpack'][
'blockheader'][
'track_number'] = ord($wavpackheader{10});
103 $ThisFileInfo[
'wavpack'][
'blockheader'][
'index_number'] = ord($wavpackheader{11});
110 $ThisFileInfo[
'wavpack'][
'blockheader'][
'flags'][
'bytes_per_sample'] = 1 + ($ThisFileInfo[
'wavpack'][
'blockheader'][
'flags_raw'] & 0x00000003);
111 $ThisFileInfo[
'wavpack'][
'blockheader'][
'flags'][
'mono'] = (bool) ($ThisFileInfo[
'wavpack'][
'blockheader'][
'flags_raw'] & 0x00000004);
112 $ThisFileInfo[
'wavpack'][
'blockheader'][
'flags'][
'hybrid'] = (bool) ($ThisFileInfo[
'wavpack'][
'blockheader'][
'flags_raw'] & 0x00000008);
113 $ThisFileInfo[
'wavpack'][
'blockheader'][
'flags'][
'joint_stereo'] = (bool) ($ThisFileInfo[
'wavpack'][
'blockheader'][
'flags_raw'] & 0x00000010);
114 $ThisFileInfo[
'wavpack'][
'blockheader'][
'flags'][
'cross_decorrelation'] = (bool) ($ThisFileInfo[
'wavpack'][
'blockheader'][
'flags_raw'] & 0x00000020);
115 $ThisFileInfo[
'wavpack'][
'blockheader'][
'flags'][
'hybrid_noiseshape'] = (bool) ($ThisFileInfo[
'wavpack'][
'blockheader'][
'flags_raw'] & 0x00000040);
116 $ThisFileInfo[
'wavpack'][
'blockheader'][
'flags'][
'ieee_32bit_float'] = (bool) ($ThisFileInfo[
'wavpack'][
'blockheader'][
'flags_raw'] & 0x00000080);
117 $ThisFileInfo[
'wavpack'][
'blockheader'][
'flags'][
'int_32bit'] = (bool) ($ThisFileInfo[
'wavpack'][
'blockheader'][
'flags_raw'] & 0x00000100);
118 $ThisFileInfo[
'wavpack'][
'blockheader'][
'flags'][
'hybrid_bitrate_noise'] = (bool) ($ThisFileInfo[
'wavpack'][
'blockheader'][
'flags_raw'] & 0x00000200);
119 $ThisFileInfo[
'wavpack'][
'blockheader'][
'flags'][
'hybrid_balance_noise'] = (bool) ($ThisFileInfo[
'wavpack'][
'blockheader'][
'flags_raw'] & 0x00000400);
120 $ThisFileInfo[
'wavpack'][
'blockheader'][
'flags'][
'multichannel_initial'] = (bool) ($ThisFileInfo[
'wavpack'][
'blockheader'][
'flags_raw'] & 0x00000800);
121 $ThisFileInfo[
'wavpack'][
'blockheader'][
'flags'][
'multichannel_final'] = (bool) ($ThisFileInfo[
'wavpack'][
'blockheader'][
'flags_raw'] & 0x00001000);
123 $ThisFileInfo[
'audio'][
'lossless'] = !$ThisFileInfo[
'wavpack'][
'blockheader'][
'flags'][
'hybrid'];
126 while (!feof($fd) && (ftell($fd) < ($blockheader_offset + $blockheader_size + 8))) {
128 $metablock = array(
'offset'=>ftell($fd));
129 $metablockheader = fread($fd, 2);
133 $metablock[
'id'] = ord($metablockheader{0});
134 $metablock[
'function_id'] = ($metablock[
'id'] & 0x3F);
144 $metablock[
'non_decoder'] = (bool) ($metablock[
'id'] & 0x20);
146 $metablock[
'padded_data'] = (bool) ($metablock[
'id'] & 0x40);
147 $metablock[
'large_block'] = (bool) ($metablock[
'id'] & 0x80);
148 if ($metablock[
'large_block']) {
149 $metablockheader .= fread($fd, 2);
152 $metablock[
'data'] = null;
154 if ($metablock[
'size'] > 0) {
156 switch ($metablock[
'function_id']) {
163 $metablock[
'data'] = fread($fd, $metablock[
'size']);
165 if ($metablock[
'padded_data']) {
167 $metablock[
'size']--;
168 $metablock[
'data'] = substr($metablock[
'data'], 0, -1);
186 fseek($fd, $metablock[
'offset'] + ($metablock[
'large_block'] ? 4 : 2) + $metablock[
'size'], SEEK_SET);
190 $ThisFileInfo[
'warning'][] =
'Unexpected metablock type "0x'.str_pad(dechex($metablock[
'function_id']), 2,
'0', STR_PAD_LEFT).
'" at offset '.$metablock[
'offset'];
191 fseek($fd, $metablock[
'offset'] + ($metablock[
'large_block'] ? 4 : 2) + $metablock[
'size'], SEEK_SET);
195 switch ($metablock[
'function_id']) {
200 $metablock[
'riff'] = $ParsedRIFFheader[
'riff'];
201 $metablock[
'riff'][
'original_filesize'] = $original_wav_filesize;
202 $ThisFileInfo[
'wavpack'][
'riff_trailer_size'] = $original_wav_filesize - $metablock[
'riff'][
'WAVE'][
'data'][0][
'size'] - $metablock[
'riff'][
'header_size'];
204 $ThisFileInfo[
'audio'][
'sample_rate'] = $ParsedRIFFheader[
'riff'][
'raw'][
'fmt '][
'nSamplesPerSec'];
205 $ThisFileInfo[
'playtime_seconds'] = $ThisFileInfo[
'wavpack'][
'blockheader'][
'total_samples'] / $ThisFileInfo[
'audio'][
'sample_rate'];
208 $metablockRIFFheader = $metablock[
'data'];
213 $metablockRIFFfooter = $metablockRIFFheader.$metablock[
'data'];
216 $ftell_old = ftell($fd);
217 $startoffset = $metablock[
'offset'] + ($metablock[
'large_block'] ? 4 : 2);
218 $ParsedRIFFfooter = array(
'avdataend'=>$ThisFileInfo[
'avdataend'],
'fileformat'=>
'riff',
'error'=>array(),
'warning'=>array());
219 $metablock[
'riff'] =
getid3_riff::ParseRIFF($fd, $startoffset, $startoffset + $metablock[
'size'], $ParsedRIFFfooter);
220 fseek($fd, $ftell_old, SEEK_SET);
222 if (!empty($metablock[
'riff'][
'INFO'])) {
224 $ThisFileInfo[
'tags'][
'riff'] = $metablock[
'comments'];
230 $ThisFileInfo[
'warning'][] =
'WavPack "Replay Gain" contents not yet handled by getID3() in metablock at offset '.$metablock[
'offset'];
235 $ThisFileInfo[
'warning'][] =
'WavPack "Cuesheet" contents not yet handled by getID3() in metablock at offset '.$metablock[
'offset'];
242 $metablock[
'flags'][
'adobe_mode'] = (bool) ($metablock[
'flags_raw'] & 0x000001);
243 $metablock[
'flags'][
'fast_flag'] = (bool) ($metablock[
'flags_raw'] & 0x000002);
244 $metablock[
'flags'][
'very_fast_flag'] = (bool) ($metablock[
'flags_raw'] & 0x000004);
245 $metablock[
'flags'][
'high_flag'] = (bool) ($metablock[
'flags_raw'] & 0x000008);
246 $metablock[
'flags'][
'very_high_flag'] = (bool) ($metablock[
'flags_raw'] & 0x000010);
247 $metablock[
'flags'][
'bitrate_kbps'] = (bool) ($metablock[
'flags_raw'] & 0x000020);
248 $metablock[
'flags'][
'auto_shaping'] = (bool) ($metablock[
'flags_raw'] & 0x000040);
249 $metablock[
'flags'][
'shape_override'] = (bool) ($metablock[
'flags_raw'] & 0x000080);
250 $metablock[
'flags'][
'joint_override'] = (bool) ($metablock[
'flags_raw'] & 0x000100);
251 $metablock[
'flags'][
'copy_time'] = (bool) ($metablock[
'flags_raw'] & 0x000200);
252 $metablock[
'flags'][
'create_exe'] = (bool) ($metablock[
'flags_raw'] & 0x000400);
253 $metablock[
'flags'][
'create_wvc'] = (bool) ($metablock[
'flags_raw'] & 0x000800);
254 $metablock[
'flags'][
'optimize_wvc'] = (bool) ($metablock[
'flags_raw'] & 0x001000);
255 $metablock[
'flags'][
'quality_mode'] = (bool) ($metablock[
'flags_raw'] & 0x002000);
256 $metablock[
'flags'][
'raw_flag'] = (bool) ($metablock[
'flags_raw'] & 0x004000);
257 $metablock[
'flags'][
'calc_noise'] = (bool) ($metablock[
'flags_raw'] & 0x008000);
258 $metablock[
'flags'][
'lossy_mode'] = (bool) ($metablock[
'flags_raw'] & 0x010000);
259 $metablock[
'flags'][
'extra_mode'] = (bool) ($metablock[
'flags_raw'] & 0x020000);
260 $metablock[
'flags'][
'skip_wvx'] = (bool) ($metablock[
'flags_raw'] & 0x040000);
261 $metablock[
'flags'][
'md5_checksum'] = (bool) ($metablock[
'flags_raw'] & 0x080000);
262 $metablock[
'flags'][
'quiet_mode'] = (bool) ($metablock[
'flags_raw'] & 0x100000);
264 $ThisFileInfo[
'wavpack'][
'config_flags'] = $metablock[
'flags'];
267 if ($ThisFileInfo[
'wavpack'][
'blockheader'][
'flags'][
'hybrid']) {
268 @$ThisFileInfo[
'audio'][
'encoder_options'] .=
' -b???';
270 @$ThisFileInfo[
'audio'][
'encoder_options'] .= ($metablock[
'flags'][
'adobe_mode'] ?
' -a' :
'');
271 @$ThisFileInfo[
'audio'][
'encoder_options'] .= ($metablock[
'flags'][
'optimize_wvc'] ?
' -cc' :
'');
272 @$ThisFileInfo[
'audio'][
'encoder_options'] .= ($metablock[
'flags'][
'create_exe'] ?
' -e' :
'');
273 @$ThisFileInfo[
'audio'][
'encoder_options'] .= ($metablock[
'flags'][
'fast_flag'] ?
' -f' :
'');
274 @$ThisFileInfo[
'audio'][
'encoder_options'] .= ($metablock[
'flags'][
'joint_override'] ?
' -j?' :
'');
275 @$ThisFileInfo[
'audio'][
'encoder_options'] .= ($metablock[
'flags'][
'high_flag'] ?
' -h' :
'');
276 @$ThisFileInfo[
'audio'][
'encoder_options'] .= ($metablock[
'flags'][
'md5_checksum'] ?
' -m' :
'');
277 @$ThisFileInfo[
'audio'][
'encoder_options'] .= ($metablock[
'flags'][
'calc_noise'] ?
' -n' :
'');
278 @$ThisFileInfo[
'audio'][
'encoder_options'] .= ($metablock[
'flags'][
'shape_override'] ?
' -s?' :
'');
279 @$ThisFileInfo[
'audio'][
'encoder_options'] .= ($metablock[
'flags'][
'extra_mode'] ?
' -x?' :
'');
280 if (@$ThisFileInfo[
'audio'][
'encoder_options']) {
281 $ThisFileInfo[
'audio'][
'encoder_options'] = trim(@$ThisFileInfo[
'audio'][
'encoder_options']);
283 elseif (isset($ThisFileInfo[
'audio'][
'encoder_options'])) {
284 unset($ThisFileInfo[
'audio'][
'encoder_options']);
290 if (strlen($metablock[
'data']) == 16) {
293 $ThisFileInfo[
'warning'][] =
'Expecting 16 bytes of WavPack "MD5 Checksum" in metablock at offset '.$metablock[
'offset'].
', but found '.strlen($metablock[
'data']).
' bytes';
317 if (!empty($metablock)) {
318 $ThisFileInfo[
'wavpack'][
'metablocks'][] = $metablock;
325 $ThisFileInfo[
'audio'][
'encoder'] =
'WavPack v'.$ThisFileInfo[
'wavpack'][
'blockheader'][
'major_version'].
'.'.str_pad($ThisFileInfo[
'wavpack'][
'blockheader'][
'minor_version'], 2,
'0', STR_PAD_LEFT);
326 $ThisFileInfo[
'audio'][
'bits_per_sample'] = $ThisFileInfo[
'wavpack'][
'blockheader'][
'flags'][
'bytes_per_sample'] * 8;
327 $ThisFileInfo[
'audio'][
'channels'] = ($ThisFileInfo[
'wavpack'][
'blockheader'][
'flags'][
'mono'] ? 1 : 2);
329 if (@$ThisFileInfo[
'playtime_seconds']) {
331 $ThisFileInfo[
'audio'][
'bitrate'] = (($ThisFileInfo[
'avdataend'] - $ThisFileInfo[
'avdataoffset']) * 8) / $ThisFileInfo[
'playtime_seconds'];
335 $ThisFileInfo[
'audio'][
'dataformat'] =
'wvc';
344 static $WavPackMetablockNameLookup = array(
346 0x01 =>
'Encoder Info',
347 0x02 =>
'Decorrelation Terms',
348 0x03 =>
'Decorrelation Weights',
349 0x04 =>
'Decorrelation Samples',
350 0x05 =>
'Entropy Variables',
351 0x06 =>
'Hybrid Profile',
352 0x07 =>
'Shaping Weights',
353 0x08 =>
'Float Info',
354 0x09 =>
'Int32 Info',
355 0x0A =>
'WV Bitstream',
356 0x0B =>
'WVC Bitstream',
357 0x0C =>
'WVX Bitstream',
358 0x0D =>
'Channel Info',
359 0x21 =>
'RIFF header',
360 0x22 =>
'RIFF trailer',
361 0x23 =>
'Replay Gain',
363 0x25 =>
'Config Block',
364 0x26 =>
'MD5 Checksum',
366 return (@$WavPackMetablockNameLookup[$id]);