Audio-Scan
view release on metacpan or search on metacpan
size of the leading tag data when calculating average bitrate.
- Improved Ogg Vorbis bitrate/duration calculation when file contains multiple
logical bitstreams.
- Added support for old WavPack versions < 4.
- Changed ASF file_size value to be the actual file size, not the value from within
the file metadata which may or may not be correct.
- Bundled a win32 build of zlib to make compiling on Windows a bit easier.
0.62 2010-03-02 12:00:00
- INCOMPATIBLE CHANGE: Ogg Vorbis COVERART tags are now translated to an
ALLPICTURES block and are base64-decoded.
- Added support for new Ogg Vorbis cover art tag, METADATA_BLOCK_PICTURE. Data
is returned in the same ALLPICTURES array as for FLAC.
0.61 2010-02-23 22:50:00
- RT 53118: Fixed crash under Perl 5.11.
- Updated Mac hints file to be more compatible with non-Apple Perl builds.
0.60 2010-02-22 17:45:00
- WavPack 4.x support.
- ID3: Bug 3998, Fixed parsing of multiple TCON genre values in older tag
include/wavpack.h view on Meta::CPAN
u_char track_no; // track number (0 if not used, like now)
u_char index_no; // track sub-index (0 if not used, like now)
uint32_t total_samples; // total samples for entire file, but this is
// only valid if block_index == 0 and a value of
// -1 indicates unknown length
uint32_t block_index; // index of first sample in block relative to
// beginning of file (normally this would start
// at 0 for the first block)
uint32_t block_samples; // number of samples in this block (0 = no audio)
uint32_t flags; // various flags for id and decoding
uint32_t crc; // crc for actual decoded data
} WavpackHeader;
typedef struct {
unsigned short FormatTag, NumChannels;
uint32_t SampleRate, BytesPerSecond;
unsigned short BlockAlign, BitsPerSample;
} WaveHeader3;
typedef struct {
// char ckID [4];
return ret;
}
int
_id3_parse_v2_frame(id3info *id3)
{
int ret = 1;
char id[5];
uint16_t flags = 0;
uint32_t size = 0;
uint32_t decoded_size = 0;
uint32_t unsync_extra = 0;
id3_frametype const *frametype;
Buffer *tmp_buf = 0;
// If the frame is compressed, it will be decompressed here
Buffer *decompressed = 0;
// tag_data_safe flag is used if skipping artwork and artwork is not raw image data (needs unsync)
id3->tag_data_safe = 1;
id3->size_remain -= 6;
if (size > id3->size_remain) {
DEBUG_TRACE(" frame size too big, aborting\n");
ret = 0;
goto out;
}
if (flags & ID3_FRAME_FLAG_V23_COMPRESSION) {
// tested with v2.3-compressed-frame.mp3
decoded_size = buffer_get_int(id3->buf);
id3->size_remain -= 4;
size -= 4;
}
if (flags & ID3_FRAME_FLAG_V23_ENCRYPTION) {
// tested with v2.3-encrypted-frame.mp3
#ifdef AUDIO_SCAN_DEBUG
DEBUG_TRACE(" encrypted, method %d\n", buffer_get_char(id3->buf));
#else
buffer_consume(id3->buf, 1);
#else
buffer_consume(id3->buf, 1);
#endif
id3->size_remain--;
size--;
}
// Perform decompression if necessary after all optional extra bytes have been read
// XXX need test for compressed + unsync
if (flags & ID3_FRAME_FLAG_V23_COMPRESSION && decoded_size) {
unsigned long tmp_size;
if ( !_check_buf(id3->infile, id3->buf, size, ID3_BLOCK_SIZE) ) {
ret = 0;
goto out;
}
DEBUG_TRACE(" decompressing, decoded_size %d\n", decoded_size);
Newz(0, decompressed, sizeof(Buffer), Buffer);
buffer_init(decompressed, decoded_size);
tmp_size = decoded_size;
if (
uncompress(buffer_ptr(decompressed), &tmp_size, buffer_ptr(id3->buf), size) != Z_OK
||
tmp_size != decoded_size
) {
DEBUG_TRACE(" unable to decompress frame\n");
buffer_free(decompressed);
Safefree(decompressed);
decompressed = 0;
}
else {
// Hack buffer so it knows we've added data directly
decompressed->end = decoded_size;
}
}
}
else {
// v2.4
// iTunes writes non-syncsafe length integers, check for this here
if ( _varint(buffer_ptr(id3->buf), 4) & 0x80 ) {
size = buffer_get_int(id3->buf);
DEBUG_TRACE(" found non-syncsafe iTunes size for %s, size adjusted to %d\n", id, size);
id3->size_remain--;
size--;
DEBUG_TRACE(" skipping encrypted frame\n");
_id3_skip(id3, size);
id3->size_remain -= size;
goto out;
}
if (flags & ID3_FRAME_FLAG_V24_DATALENGTHINDICATOR) {
decoded_size = buffer_get_syncsafe(id3->buf, 4);
id3->size_remain -= 4;
size -= 4;
DEBUG_TRACE(" data length indicator, size %d\n", decoded_size);
}
if (flags & ID3_FRAME_FLAG_V24_UNSYNCHRONISATION) {
// Special case, do not unsync an APIC frame if not reading artwork,
// FF's are not likely to appear in the part we care about anyway
if ( !strcmp(id, "APIC") && _env_true("AUDIO_SCAN_NO_ARTWORK") ) {
DEBUG_TRACE(" Would un-synchronize APIC frame, but ignoring because of AUDIO_SCAN_NO_ARTWORK\n");
// Reset decoded_size to 0 since we aren't actually decoding.
// XXX this would break if we have a compressed + unsync APIC frame but not very likely in the real world
decoded_size = 0;
id3->tag_data_safe = 0;
}
else {
// tested with v2.4-unsync.mp3
if ( !_check_buf(id3->infile, id3->buf, size, ID3_BLOCK_SIZE) ) {
ret = 0;
goto out;
}
decoded_size = _id3_deunsync( buffer_ptr(id3->buf), size );
unsync_extra = size - decoded_size;
DEBUG_TRACE(" Un-synchronized frame, new_size %d\n", decoded_size);
}
}
if (flags & ID3_FRAME_FLAG_V24_COMPRESSION) {
// tested with v2.4-compressed-frame.mp3
// XXX need test for compressed + unsync
unsigned long tmp_size;
if ( !_check_buf(id3->infile, id3->buf, size, ID3_BLOCK_SIZE) ) {
ret = 0;
goto out;
}
DEBUG_TRACE(" decompressing\n");
Newz(0, decompressed, sizeof(Buffer), Buffer);
buffer_init(decompressed, decoded_size);
tmp_size = decoded_size;
if (
uncompress(buffer_ptr(decompressed), &tmp_size, buffer_ptr(id3->buf), size) != Z_OK
||
tmp_size != decoded_size
) {
DEBUG_TRACE(" unable to decompress frame\n");
buffer_free(decompressed);
Safefree(decompressed);
decompressed = 0;
}
else {
// Hack buffer so it knows we've added data directly
decompressed->end = decoded_size;
}
}
}
}
// Special case, completely skip XHD3 frame (mp3HD) as it will be large
// Also skip NCON, a large tag written by MusicMatch
if ( !strcmp(id, "XHD3") || !strcmp(id, "NCON") ) {
DEBUG_TRACE(" skipping large binary %s frame\n", id);
_id3_skip(id3, size);
DEBUG_TRACE("\n");
}
#endif
// If frame was compressed, temporarily set the id3 buffer to use the decompressed buffer
if (decompressed) {
tmp_buf = id3->buf;
id3->buf = decompressed;
}
if ( !_id3_parse_v2_frame_data(id3, (char *)&id, decoded_size ? decoded_size : size, frametype) ) {
DEBUG_TRACE(" error parsing frame, aborting\n");
ret = 0;
goto out;
}
if (id3->size_remain > size) {
id3->size_remain -= size;
}
else {
id3->size_remain = 0;
( run in 0.432 second using v1.01-cache-2.11-cpan-26ccb49234f )