Annotation of /trunk/lib/getid3/module.audio.wavpack.php
Parent Directory
|
Revision Log
Revision 2 - (view) (download)
| 1 : | andphe | 2 | <?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.wavpack.php // | ||
| 11 : | // module for analyzing WavPack v4.0+ Audio files // | ||
| 12 : | // dependencies: NONE // | ||
| 13 : | // /// | ||
| 14 : | ///////////////////////////////////////////////////////////////// | ||
| 15 : | // MOS Intruder Alerts | ||
| 16 : | defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' ); | ||
| 17 : | |||
| 18 : | class getid3_wavpack | ||
| 19 : | { | ||
| 20 : | |||
| 21 : | function getid3_wavpack(&$fd, &$ThisFileInfo) { | ||
| 22 : | |||
| 23 : | fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET); | ||
| 24 : | |||
| 25 : | while (true) { | ||
| 26 : | |||
| 27 : | $wavpackheader = fread($fd, 32); | ||
| 28 : | |||
| 29 : | if (ftell($fd) >= $ThisFileInfo['avdataend']) { | ||
| 30 : | break; | ||
| 31 : | } elseif (feof($fd)) { | ||
| 32 : | break; | ||
| 33 : | } elseif ( | ||
| 34 : | (@$ThisFileInfo['wavpack']['blockheader']['total_samples'] > 0) && | ||
| 35 : | (@$ThisFileInfo['wavpack']['blockheader']['block_samples'] > 0) && | ||
| 36 : | (!isset($ThisFileInfo['wavpack']['riff_trailer_size']) || ($ThisFileInfo['wavpack']['riff_trailer_size'] <= 0)) && | ||
| 37 : | ((@$ThisFileInfo['wavpack']['config_flags']['md5_checksum'] === false) || !empty($ThisFileInfo['md5_data_source']))) { | ||
| 38 : | break; | ||
| 39 : | } | ||
| 40 : | |||
| 41 : | $blockheader_offset = ftell($fd) - 32; | ||
| 42 : | $blockheader_magic = substr($wavpackheader, 0, 4); | ||
| 43 : | $blockheader_size = getid3_lib::LittleEndian2Int(substr($wavpackheader, 4, 4)); | ||
| 44 : | |||
| 45 : | if ($blockheader_magic != 'wvpk') { | ||
| 46 : | $ThisFileInfo['error'][] = 'Expecting "wvpk" at offset '.$blockheader_offset.', found "'.$blockheader_magic.'"'; | ||
| 47 : | if ((@$ThisFileInfo['audio']['dataformat'] != 'wavpack') && (@$ThisFileInfo['audio']['dataformat'] != 'wvc')) { | ||
| 48 : | unset($ThisFileInfo['fileformat']); | ||
| 49 : | unset($ThisFileInfo['audio']); | ||
| 50 : | unset($ThisFileInfo['wavpack']); | ||
| 51 : | } | ||
| 52 : | return false; | ||
| 53 : | } | ||
| 54 : | |||
| 55 : | |||
| 56 : | if ((@$ThisFileInfo['wavpack']['blockheader']['block_samples'] <= 0) || | ||
| 57 : | (@$ThisFileInfo['wavpack']['blockheader']['total_samples'] <= 0)) { | ||
| 58 : | // Also, it is possible that the first block might not have | ||
| 59 : | // any samples (block_samples == 0) and in this case you should skip blocks | ||
| 60 : | // until you find one with samples because the other information (like | ||
| 61 : | // total_samples) are not guaranteed to be correct until (block_samples > 0) | ||
| 62 : | |||
| 63 : | // Finally, I have defined a format for files in which the length is not known | ||
| 64 : | // (for example when raw files are created using pipes). In these cases | ||
| 65 : | // total_samples will be -1 and you must seek to the final block to determine | ||
| 66 : | // the total number of samples. | ||
| 67 : | |||
| 68 : | |||
| 69 : | $ThisFileInfo['audio']['dataformat'] = 'wavpack'; | ||
| 70 : | $ThisFileInfo['fileformat'] = 'wavpack'; | ||
| 71 : | $ThisFileInfo['audio']['lossless'] = true; | ||
| 72 : | $ThisFileInfo['audio']['bitrate_mode'] = 'vbr'; | ||
| 73 : | |||
| 74 : | $ThisFileInfo['wavpack']['blockheader']['offset'] = $blockheader_offset; | ||
| 75 : | $ThisFileInfo['wavpack']['blockheader']['magic'] = $blockheader_magic; | ||
| 76 : | $ThisFileInfo['wavpack']['blockheader']['size'] = $blockheader_size; | ||
| 77 : | |||
| 78 : | if ($ThisFileInfo['wavpack']['blockheader']['size'] >= 0x100000) { | ||
| 79 : | $ThisFileInfo['error'][] = 'Expecting WavPack block size less than "0x100000", found "'.$ThisFileInfo['wavpack']['blockheader']['size'].'" at offset '.$ThisFileInfo['wavpack']['blockheader']['offset']; | ||
| 80 : | if ((@$ThisFileInfo['audio']['dataformat'] != 'wavpack') && (@$ThisFileInfo['audio']['dataformat'] != 'wvc')) { | ||
| 81 : | unset($ThisFileInfo['fileformat']); | ||
| 82 : | unset($ThisFileInfo['audio']); | ||
| 83 : | unset($ThisFileInfo['wavpack']); | ||
| 84 : | } | ||
| 85 : | return false; | ||
| 86 : | } | ||
| 87 : | |||
| 88 : | $ThisFileInfo['wavpack']['blockheader']['minor_version'] = ord($wavpackheader{8}); | ||
| 89 : | $ThisFileInfo['wavpack']['blockheader']['major_version'] = ord($wavpackheader{9}); | ||
| 90 : | |||
| 91 : | if (($ThisFileInfo['wavpack']['blockheader']['major_version'] != 4) || | ||
| 92 : | (($ThisFileInfo['wavpack']['blockheader']['minor_version'] < 4) && | ||
| 93 : | ($ThisFileInfo['wavpack']['blockheader']['minor_version'] > 16))) { | ||
| 94 : | $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']; | ||
| 95 : | if ((@$ThisFileInfo['audio']['dataformat'] != 'wavpack') && (@$ThisFileInfo['audio']['dataformat'] != 'wvc')) { | ||
| 96 : | unset($ThisFileInfo['fileformat']); | ||
| 97 : | unset($ThisFileInfo['audio']); | ||
| 98 : | unset($ThisFileInfo['wavpack']); | ||
| 99 : | } | ||
| 100 : | return false; | ||
| 101 : | } | ||
| 102 : | |||
| 103 : | $ThisFileInfo['wavpack']['blockheader']['track_number'] = ord($wavpackheader{10}); // unused | ||
| 104 : | $ThisFileInfo['wavpack']['blockheader']['index_number'] = ord($wavpackheader{11}); // unused | ||
| 105 : | $ThisFileInfo['wavpack']['blockheader']['total_samples'] = getid3_lib::LittleEndian2Int(substr($wavpackheader, 12, 4)); | ||
| 106 : | $ThisFileInfo['wavpack']['blockheader']['block_index'] = getid3_lib::LittleEndian2Int(substr($wavpackheader, 16, 4)); | ||
| 107 : | $ThisFileInfo['wavpack']['blockheader']['block_samples'] = getid3_lib::LittleEndian2Int(substr($wavpackheader, 20, 4)); | ||
| 108 : | $ThisFileInfo['wavpack']['blockheader']['flags_raw'] = getid3_lib::LittleEndian2Int(substr($wavpackheader, 24, 4)); | ||
| 109 : | $ThisFileInfo['wavpack']['blockheader']['crc'] = getid3_lib::LittleEndian2Int(substr($wavpackheader, 28, 4)); | ||
| 110 : | |||
| 111 : | $ThisFileInfo['wavpack']['blockheader']['flags']['bytes_per_sample'] = 1 + ($ThisFileInfo['wavpack']['blockheader']['flags_raw'] & 0x00000003); | ||
| 112 : | $ThisFileInfo['wavpack']['blockheader']['flags']['mono'] = (bool) ($ThisFileInfo['wavpack']['blockheader']['flags_raw'] & 0x00000004); | ||
| 113 : | $ThisFileInfo['wavpack']['blockheader']['flags']['hybrid'] = (bool) ($ThisFileInfo['wavpack']['blockheader']['flags_raw'] & 0x00000008); | ||
| 114 : | $ThisFileInfo['wavpack']['blockheader']['flags']['joint_stereo'] = (bool) ($ThisFileInfo['wavpack']['blockheader']['flags_raw'] & 0x00000010); | ||
| 115 : | $ThisFileInfo['wavpack']['blockheader']['flags']['cross_decorrelation'] = (bool) ($ThisFileInfo['wavpack']['blockheader']['flags_raw'] & 0x00000020); | ||
| 116 : | $ThisFileInfo['wavpack']['blockheader']['flags']['hybrid_noiseshape'] = (bool) ($ThisFileInfo['wavpack']['blockheader']['flags_raw'] & 0x00000040); | ||
| 117 : | $ThisFileInfo['wavpack']['blockheader']['flags']['ieee_32bit_float'] = (bool) ($ThisFileInfo['wavpack']['blockheader']['flags_raw'] & 0x00000080); | ||
| 118 : | $ThisFileInfo['wavpack']['blockheader']['flags']['int_32bit'] = (bool) ($ThisFileInfo['wavpack']['blockheader']['flags_raw'] & 0x00000100); | ||
| 119 : | $ThisFileInfo['wavpack']['blockheader']['flags']['hybrid_bitrate_noise'] = (bool) ($ThisFileInfo['wavpack']['blockheader']['flags_raw'] & 0x00000200); | ||
| 120 : | $ThisFileInfo['wavpack']['blockheader']['flags']['hybrid_balance_noise'] = (bool) ($ThisFileInfo['wavpack']['blockheader']['flags_raw'] & 0x00000400); | ||
| 121 : | $ThisFileInfo['wavpack']['blockheader']['flags']['multichannel_initial'] = (bool) ($ThisFileInfo['wavpack']['blockheader']['flags_raw'] & 0x00000800); | ||
| 122 : | $ThisFileInfo['wavpack']['blockheader']['flags']['multichannel_final'] = (bool) ($ThisFileInfo['wavpack']['blockheader']['flags_raw'] & 0x00001000); | ||
| 123 : | |||
| 124 : | $ThisFileInfo['audio']['lossless'] = !$ThisFileInfo['wavpack']['blockheader']['flags']['hybrid']; | ||
| 125 : | } | ||
| 126 : | |||
| 127 : | while (!feof($fd) && (ftell($fd) < ($blockheader_offset + $blockheader_size + 8))) { | ||
| 128 : | |||
| 129 : | $metablock = array('offset'=>ftell($fd)); | ||
| 130 : | $metablockheader = fread($fd, 2); | ||
| 131 : | if (feof($fd)) { | ||
| 132 : | break; | ||
| 133 : | } | ||
| 134 : | $metablock['id'] = ord($metablockheader{0}); | ||
| 135 : | $metablock['function_id'] = ($metablock['id'] & 0x3F); | ||
| 136 : | $metablock['function_name'] = $this->WavPackMetablockNameLookup($metablock['function_id']); | ||
| 137 : | |||
| 138 : | // The 0x20 bit in the id of the meta subblocks (which is defined as | ||
| 139 : | // ID_OPTIONAL_DATA) is a permanent part of the id. The idea is that | ||
| 140 : | // if a decoder encounters an id that it does not know about, it uses | ||
| 141 : | // that "ID_OPTIONAL_DATA" flag to determine what to do. If it is set | ||
| 142 : | // then the decoder simply ignores the metadata, but if it is zero | ||
| 143 : | // then the decoder should quit because it means that an understanding | ||
| 144 : | // of the metadata is required to correctly decode the audio. | ||
| 145 : | $metablock['non_decoder'] = (bool) ($metablock['id'] & 0x20); | ||
| 146 : | |||
| 147 : | $metablock['padded_data'] = (bool) ($metablock['id'] & 0x40); | ||
| 148 : | $metablock['large_block'] = (bool) ($metablock['id'] & 0x80); | ||
| 149 : | if ($metablock['large_block']) { | ||
| 150 : | $metablockheader .= fread($fd, 2); | ||
| 151 : | } | ||
| 152 : | $metablock['size'] = getid3_lib::LittleEndian2Int(substr($metablockheader, 1)) * 2; // size is stored in words | ||
| 153 : | $metablock['data'] = null; | ||
| 154 : | |||
| 155 : | if ($metablock['size'] > 0) { | ||
| 156 : | |||
| 157 : | switch ($metablock['function_id']) { | ||
| 158 : | case 0x21: // ID_RIFF_HEADER | ||
| 159 : | case 0x22: // ID_RIFF_TRAILER | ||
| 160 : | case 0x23: // ID_REPLAY_GAIN | ||
| 161 : | case 0x24: // ID_CUESHEET | ||
| 162 : | case 0x25: // ID_CONFIG_BLOCK | ||
| 163 : | case 0x26: // ID_MD5_CHECKSUM | ||
| 164 : | $metablock['data'] = fread($fd, $metablock['size']); | ||
| 165 : | |||
| 166 : | if ($metablock['padded_data']) { | ||
| 167 : | // padded to the nearest even byte | ||
| 168 : | $metablock['size']--; | ||
| 169 : | $metablock['data'] = substr($metablock['data'], 0, -1); | ||
| 170 : | } | ||
| 171 : | break; | ||
| 172 : | |||
| 173 : | case 0x00: // ID_DUMMY | ||
| 174 : | case 0x01: // ID_ENCODER_INFO | ||
| 175 : | case 0x02: // ID_DECORR_TERMS | ||
| 176 : | case 0x03: // ID_DECORR_WEIGHTS | ||
| 177 : | case 0x04: // ID_DECORR_SAMPLES | ||
| 178 : | case 0x05: // ID_ENTROPY_VARS | ||
| 179 : | case 0x06: // ID_HYBRID_PROFILE | ||
| 180 : | case 0x07: // ID_SHAPING_WEIGHTS | ||
| 181 : | case 0x08: // ID_FLOAT_INFO | ||
| 182 : | case 0x09: // ID_INT32_INFO | ||
| 183 : | case 0x0A: // ID_WV_BITSTREAM | ||
| 184 : | case 0x0B: // ID_WVC_BITSTREAM | ||
| 185 : | case 0x0C: // ID_WVX_BITSTREAM | ||
| 186 : | case 0x0D: // ID_CHANNEL_INFO | ||
| 187 : | fseek($fd, $metablock['offset'] + ($metablock['large_block'] ? 4 : 2) + $metablock['size'], SEEK_SET); | ||
| 188 : | break; | ||
| 189 : | |||
| 190 : | default: | ||
| 191 : | $ThisFileInfo['warning'][] = 'Unexpected metablock type "0x'.str_pad(dechex($metablock['function_id']), 2, '0', STR_PAD_LEFT).'" at offset '.$metablock['offset']; | ||
| 192 : | fseek($fd, $metablock['offset'] + ($metablock['large_block'] ? 4 : 2) + $metablock['size'], SEEK_SET); | ||
| 193 : | break; | ||
| 194 : | } | ||
| 195 : | |||
| 196 : | switch ($metablock['function_id']) { | ||
| 197 : | case 0x21: // ID_RIFF_HEADER | ||
| 198 : | $ParsedRIFFheader = null; | ||
| 199 : | getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true); | ||
| 200 : | $original_wav_filesize = getid3_lib::LittleEndian2Int(substr($metablock['data'], 4, 4)); | ||
| 201 : | getid3_riff::ParseRIFFdata($metablock['data'], $ParsedRIFFheader); | ||
| 202 : | $metablock['riff'] = $ParsedRIFFheader['riff']; | ||
| 203 : | $metablock['riff']['original_filesize'] = $original_wav_filesize; | ||
| 204 : | $ThisFileInfo['wavpack']['riff_trailer_size'] = $original_wav_filesize - $metablock['riff']['WAVE']['data'][0]['size'] - $metablock['riff']['header_size']; | ||
| 205 : | |||
| 206 : | $ThisFileInfo['audio']['sample_rate'] = $ParsedRIFFheader['riff']['raw']['fmt ']['nSamplesPerSec']; | ||
| 207 : | $ThisFileInfo['playtime_seconds'] = $ThisFileInfo['wavpack']['blockheader']['total_samples'] / $ThisFileInfo['audio']['sample_rate']; | ||
| 208 : | |||
| 209 : | // Safe RIFF header in case there's a RIFF footer later | ||
| 210 : | $metablockRIFFheader = $metablock['data']; | ||
| 211 : | break; | ||
| 212 : | |||
| 213 : | |||
| 214 : | case 0x22: // ID_RIFF_TRAILER | ||
| 215 : | $metablockRIFFfooter = $metablockRIFFheader.$metablock['data']; | ||
| 216 : | getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true); | ||
| 217 : | |||
| 218 : | $ftell_old = ftell($fd); | ||
| 219 : | $startoffset = $metablock['offset'] + ($metablock['large_block'] ? 4 : 2); | ||
| 220 : | $ParsedRIFFfooter = array('avdataend'=>$ThisFileInfo['avdataend'], 'fileformat'=>'riff', 'error'=>array(), 'warning'=>array()); | ||
| 221 : | $metablock['riff'] = getid3_riff::ParseRIFF($fd, $startoffset, $startoffset + $metablock['size'], $ParsedRIFFfooter); | ||
| 222 : | fseek($fd, $ftell_old, SEEK_SET); | ||
| 223 : | |||
| 224 : | if (!empty($metablock['riff']['INFO'])) { | ||
| 225 : | getid3_riff::RIFFcommentsParse($metablock['riff']['INFO'], $metablock['comments']); | ||
| 226 : | $ThisFileInfo['tags']['riff'] = $metablock['comments']; | ||
| 227 : | } | ||
| 228 : | break; | ||
| 229 : | |||
| 230 : | |||
| 231 : | case 0x23: // ID_REPLAY_GAIN | ||
| 232 : | $ThisFileInfo['warning'][] = 'WavPack "Replay Gain" contents not yet handled by getID3() in metablock at offset '.$metablock['offset']; | ||
| 233 : | break; | ||
| 234 : | |||
| 235 : | |||
| 236 : | case 0x24: // ID_CUESHEET | ||
| 237 : | $ThisFileInfo['warning'][] = 'WavPack "Cuesheet" contents not yet handled by getID3() in metablock at offset '.$metablock['offset']; | ||
| 238 : | break; | ||
| 239 : | |||
| 240 : | |||
| 241 : | case 0x25: // ID_CONFIG_BLOCK | ||
| 242 : | $metablock['flags_raw'] = getid3_lib::LittleEndian2Int(substr($metablock['data'], 0, 3)); | ||
| 243 : | |||
| 244 : | $metablock['flags']['adobe_mode'] = (bool) ($metablock['flags_raw'] & 0x000001); // "adobe" mode for 32-bit floats | ||
| 245 : | $metablock['flags']['fast_flag'] = (bool) ($metablock['flags_raw'] & 0x000002); // fast mode | ||
| 246 : | $metablock['flags']['very_fast_flag'] = (bool) ($metablock['flags_raw'] & 0x000004); // double fast | ||
| 247 : | $metablock['flags']['high_flag'] = (bool) ($metablock['flags_raw'] & 0x000008); // high quality mode | ||
| 248 : | $metablock['flags']['very_high_flag'] = (bool) ($metablock['flags_raw'] & 0x000010); // double high (not used yet) | ||
| 249 : | $metablock['flags']['bitrate_kbps'] = (bool) ($metablock['flags_raw'] & 0x000020); // bitrate is kbps, not bits / sample | ||
| 250 : | $metablock['flags']['auto_shaping'] = (bool) ($metablock['flags_raw'] & 0x000040); // automatic noise shaping | ||
| 251 : | $metablock['flags']['shape_override'] = (bool) ($metablock['flags_raw'] & 0x000080); // shaping mode specified | ||
| 252 : | $metablock['flags']['joint_override'] = (bool) ($metablock['flags_raw'] & 0x000100); // joint-stereo mode specified | ||
| 253 : | $metablock['flags']['copy_time'] = (bool) ($metablock['flags_raw'] & 0x000200); // copy file-time from source | ||
| 254 : | $metablock['flags']['create_exe'] = (bool) ($metablock['flags_raw'] & 0x000400); // create executable | ||
| 255 : | $metablock['flags']['create_wvc'] = (bool) ($metablock['flags_raw'] & 0x000800); // create correction file | ||
| 256 : | $metablock['flags']['optimize_wvc'] = (bool) ($metablock['flags_raw'] & 0x001000); // maximize bybrid compression | ||
| 257 : | $metablock['flags']['quality_mode'] = (bool) ($metablock['flags_raw'] & 0x002000); // psychoacoustic quality mode | ||
| 258 : | $metablock['flags']['raw_flag'] = (bool) ($metablock['flags_raw'] & 0x004000); // raw mode (not implemented yet) | ||
| 259 : | $metablock['flags']['calc_noise'] = (bool) ($metablock['flags_raw'] & 0x008000); // calc noise in hybrid mode | ||
| 260 : | $metablock['flags']['lossy_mode'] = (bool) ($metablock['flags_raw'] & 0x010000); // obsolete (for information) | ||
| 261 : | $metablock['flags']['extra_mode'] = (bool) ($metablock['flags_raw'] & 0x020000); // extra processing mode | ||
| 262 : | $metablock['flags']['skip_wvx'] = (bool) ($metablock['flags_raw'] & 0x040000); // no wvx stream w/ floats & big ints | ||
| 263 : | $metablock['flags']['md5_checksum'] = (bool) ($metablock['flags_raw'] & 0x080000); // compute & store MD5 signature | ||
| 264 : | $metablock['flags']['quiet_mode'] = (bool) ($metablock['flags_raw'] & 0x100000); // don't report progress % | ||
| 265 : | |||
| 266 : | $ThisFileInfo['wavpack']['config_flags'] = $metablock['flags']; | ||
| 267 : | |||
| 268 : | |||
| 269 : | if ($ThisFileInfo['wavpack']['blockheader']['flags']['hybrid']) { | ||
| 270 : | @$ThisFileInfo['audio']['encoder_options'] .= ' -b???'; | ||
| 271 : | } | ||
| 272 : | @$ThisFileInfo['audio']['encoder_options'] .= ($metablock['flags']['adobe_mode'] ? ' -a' : ''); | ||
| 273 : | @$ThisFileInfo['audio']['encoder_options'] .= ($metablock['flags']['optimize_wvc'] ? ' -cc' : ''); | ||
| 274 : | @$ThisFileInfo['audio']['encoder_options'] .= ($metablock['flags']['create_exe'] ? ' -e' : ''); | ||
| 275 : | @$ThisFileInfo['audio']['encoder_options'] .= ($metablock['flags']['fast_flag'] ? ' -f' : ''); | ||
| 276 : | @$ThisFileInfo['audio']['encoder_options'] .= ($metablock['flags']['joint_override'] ? ' -j?' : ''); | ||
| 277 : | @$ThisFileInfo['audio']['encoder_options'] .= ($metablock['flags']['high_flag'] ? ' -h' : ''); | ||
| 278 : | @$ThisFileInfo['audio']['encoder_options'] .= ($metablock['flags']['md5_checksum'] ? ' -m' : ''); | ||
| 279 : | @$ThisFileInfo['audio']['encoder_options'] .= ($metablock['flags']['calc_noise'] ? ' -n' : ''); | ||
| 280 : | @$ThisFileInfo['audio']['encoder_options'] .= ($metablock['flags']['shape_override'] ? ' -s?' : ''); | ||
| 281 : | @$ThisFileInfo['audio']['encoder_options'] .= ($metablock['flags']['extra_mode'] ? ' -x?' : ''); | ||
| 282 : | if (@$ThisFileInfo['audio']['encoder_options']) { | ||
| 283 : | $ThisFileInfo['audio']['encoder_options'] = trim(@$ThisFileInfo['audio']['encoder_options']); | ||
| 284 : | } | ||
| 285 : | elseif (isset($ThisFileInfo['audio']['encoder_options'])) { | ||
| 286 : | unset($ThisFileInfo['audio']['encoder_options']); | ||
| 287 : | } | ||
| 288 : | break; | ||
| 289 : | |||
| 290 : | |||
| 291 : | case 0x26: // ID_MD5_CHECKSUM | ||
| 292 : | if (strlen($metablock['data']) == 16) { | ||
| 293 : | $ThisFileInfo['md5_data_source'] = strtolower(getid3_lib::PrintHexBytes($metablock['data'], true, false, false)); | ||
| 294 : | } else { | ||
| 295 : | $ThisFileInfo['warning'][] = 'Expecting 16 bytes of WavPack "MD5 Checksum" in metablock at offset '.$metablock['offset'].', but found '.strlen($metablock['data']).' bytes'; | ||
| 296 : | } | ||
| 297 : | break; | ||
| 298 : | |||
| 299 : | |||
| 300 : | case 0x00: // ID_DUMMY | ||
| 301 : | case 0x01: // ID_ENCODER_INFO | ||
| 302 : | case 0x02: // ID_DECORR_TERMS | ||
| 303 : | case 0x03: // ID_DECORR_WEIGHTS | ||
| 304 : | case 0x04: // ID_DECORR_SAMPLES | ||
| 305 : | case 0x05: // ID_ENTROPY_VARS | ||
| 306 : | case 0x06: // ID_HYBRID_PROFILE | ||
| 307 : | case 0x07: // ID_SHAPING_WEIGHTS | ||
| 308 : | case 0x08: // ID_FLOAT_INFO | ||
| 309 : | case 0x09: // ID_INT32_INFO | ||
| 310 : | case 0x0A: // ID_WV_BITSTREAM | ||
| 311 : | case 0x0B: // ID_WVC_BITSTREAM | ||
| 312 : | case 0x0C: // ID_WVX_BITSTREAM | ||
| 313 : | case 0x0D: // ID_CHANNEL_INFO | ||
| 314 : | unset($metablock); | ||
| 315 : | break; | ||
| 316 : | } | ||
| 317 : | |||
| 318 : | } | ||
| 319 : | if (!empty($metablock)) { | ||
| 320 : | $ThisFileInfo['wavpack']['metablocks'][] = $metablock; | ||
| 321 : | } | ||
| 322 : | |||
| 323 : | } | ||
| 324 : | |||
| 325 : | } | ||
| 326 : | |||
| 327 : | $ThisFileInfo['audio']['encoder'] = 'WavPack v'.$ThisFileInfo['wavpack']['blockheader']['major_version'].'.'.str_pad($ThisFileInfo['wavpack']['blockheader']['minor_version'], 2, '0', STR_PAD_LEFT); | ||
| 328 : | $ThisFileInfo['audio']['bits_per_sample'] = $ThisFileInfo['wavpack']['blockheader']['flags']['bytes_per_sample'] * 8; | ||
| 329 : | $ThisFileInfo['audio']['channels'] = ($ThisFileInfo['wavpack']['blockheader']['flags']['mono'] ? 1 : 2); | ||
| 330 : | |||
| 331 : | if (@$ThisFileInfo['playtime_seconds']) { | ||
| 332 : | |||
| 333 : | $ThisFileInfo['audio']['bitrate'] = (($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8) / $ThisFileInfo['playtime_seconds']; | ||
| 334 : | |||
| 335 : | } else { | ||
| 336 : | |||
| 337 : | $ThisFileInfo['audio']['dataformat'] = 'wvc'; | ||
| 338 : | |||
| 339 : | } | ||
| 340 : | |||
| 341 : | return true; | ||
| 342 : | } | ||
| 343 : | |||
| 344 : | |||
| 345 : | function WavPackMetablockNameLookup(&$id) { | ||
| 346 : | static $WavPackMetablockNameLookup = array( | ||
| 347 : | 0x00 => 'Dummy', | ||
| 348 : | 0x01 => 'Encoder Info', | ||
| 349 : | 0x02 => 'Decorrelation Terms', | ||
| 350 : | 0x03 => 'Decorrelation Weights', | ||
| 351 : | 0x04 => 'Decorrelation Samples', | ||
| 352 : | 0x05 => 'Entropy Variables', | ||
| 353 : | 0x06 => 'Hybrid Profile', | ||
| 354 : | 0x07 => 'Shaping Weights', | ||
| 355 : | 0x08 => 'Float Info', | ||
| 356 : | 0x09 => 'Int32 Info', | ||
| 357 : | 0x0A => 'WV Bitstream', | ||
| 358 : | 0x0B => 'WVC Bitstream', | ||
| 359 : | 0x0C => 'WVX Bitstream', | ||
| 360 : | 0x0D => 'Channel Info', | ||
| 361 : | 0x21 => 'RIFF header', | ||
| 362 : | 0x22 => 'RIFF trailer', | ||
| 363 : | 0x23 => 'Replay Gain', | ||
| 364 : | 0x24 => 'Cuesheet', | ||
| 365 : | 0x25 => 'Config Block', | ||
| 366 : | 0x26 => 'MD5 Checksum', | ||
| 367 : | ); | ||
| 368 : | return (@$WavPackMetablockNameLookup[$id]); | ||
| 369 : | } | ||
| 370 : | |||
| 371 : | } | ||
| 372 : | |||
| 373 : | |||
| 374 : | ?> |
| ViewVC Help | |
| Powered by ViewVC 1.0.0 |
Web Hosting provided by Network Redux.

