SVN commit 1201476 by lalinsky: Fix reading of WavPack streams without a length information in the header When the WavPack's total_samples header fiels contains -1, try to find the final block and get the number of samples from there as block_index + block_samples. BUG:258016 M +2 -0 NEWS M +1 -2 taglib/wavpack/wavpackfile.cpp M +50 -1 taglib/wavpack/wavpackproperties.cpp M +10 -0 taglib/wavpack/wavpackproperties.h M +2 -0 tests/CMakeLists.txt M +4 -2 tests/Makefile.am AM tests/data/no_length.wv A tests/test_wavpack.cpp [License: UNKNOWN] --- trunk/kdesupport/taglib/NEWS #1201475:1201476 @@ -8,6 +8,8 @@ * Exposed FLAC MD5 signature of the uncompressed audio stream via FLAC::Properties::signature(). (BUG:160172) * Added function ByteVector::toHex() for hex-encoding of byte vectors. + * WavPack reader now tries to get the audio length by finding the final + block, if the header doesn't have the information. (BUG:258016) TagLib 1.6.3 (Apr 17, 2010) =========================== --- trunk/kdesupport/taglib/taglib/wavpack/wavpackfile.cpp #1201475:1201476 @@ -230,8 +230,7 @@ if(readProperties) { seek(0); - d->properties = new Properties(readBlock(WavPack::HeaderSize), - length() - d->APESize); + d->properties = new Properties(this, length() - d->APESize); } } --- trunk/kdesupport/taglib/taglib/wavpack/wavpackproperties.cpp #1201475:1201476 @@ -48,7 +48,8 @@ sampleRate(0), channels(0), version(0), - bitsPerSample(0) {} + bitsPerSample(0), + file(0) {} ByteVector data; long streamLength; @@ -59,6 +60,7 @@ int channels; int version; int bitsPerSample; + File *file; }; //////////////////////////////////////////////////////////////////////////////// @@ -71,6 +73,14 @@ read(); } +WavPack::Properties::Properties(File *file, long streamLength, ReadStyle style) : AudioProperties(style) +{ + ByteVector data = file->readBlock(32); + d = new PropertiesPrivate(data, streamLength, style); + d->file = file; + read(); +} + WavPack::Properties::~Properties() { delete d; @@ -122,12 +132,19 @@ #define SRATE_LSB 23 #define SRATE_MASK (0xfL << SRATE_LSB) +#define MIN_STREAM_VERS 0x402 +#define MAX_STREAM_VERS 0x410 + +#define FINAL_BLOCK 0x1000 + void WavPack::Properties::read() { if(!d->data.startsWith("wvpk")) return; d->version = d->data.mid(8, 2).toShort(false); + if(d->version < MIN_STREAM_VERS || d->version > MAX_STREAM_VERS) + return; unsigned int flags = d->data.mid(24, 4).toUInt(false); d->bitsPerSample = ((flags & BYTES_STORED) + 1) * 8 - @@ -137,10 +154,42 @@ unsigned int samples = d->data.mid(12, 4).toUInt(false); if (samples == ~0u) { + if(d->file && d->style != Fast) { + samples = seekFinalIndex(); + } + else { samples = 0; } + } d->length = d->sampleRate > 0 ? (samples + (d->sampleRate / 2)) / d->sampleRate : 0; d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0; } +unsigned int WavPack::Properties::seekFinalIndex() +{ + ByteVector blockID("wvpk", 4); + + long offset = d->streamLength; + while(offset > 0) { + offset = d->file->rfind(blockID, offset); + if(offset == -1) + return 0; + d->file->seek(offset); + ByteVector data = d->file->readBlock(32); + if(data.size() != 32) + return 0; + int version = data.mid(8, 2).toShort(false); + if(version < MIN_STREAM_VERS || version > MAX_STREAM_VERS) + continue; + unsigned int flags = data.mid(24, 4).toUInt(false); + if(!(flags & FINAL_BLOCK)) + return 0; + unsigned int blockIndex = data.mid(16, 4).toUInt(false); + unsigned int blockSamples = data.mid(20, 4).toUInt(false); + return blockIndex + blockSamples; + } + + return 0; +} + --- trunk/kdesupport/taglib/taglib/wavpack/wavpackproperties.h #1201475:1201476 @@ -54,10 +54,19 @@ /*! * Create an instance of WavPack::Properties with the data read from the * ByteVector \a data. + * + * \deprecated This constructor will be dropped in favor of the one below + * in a future version. */ Properties(const ByteVector &data, long streamLength, ReadStyle style = Average); /*! + * Create an instance of WavPack::Properties. + */ + // BIC: merge with the above constructor + Properties(File *file, long streamLength, ReadStyle style = Average); + + /*! * Destroys this WavPack::Properties instance. */ virtual ~Properties(); @@ -84,6 +93,7 @@ Properties &operator=(const Properties &); void read(); + unsigned int seekFinalIndex(); class PropertiesPrivate; PropertiesPrivate *d; --- trunk/kdesupport/taglib/tests/CMakeLists.txt #1201475:1201476 @@ -18,6 +18,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ogg/vorbis ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ogg/flac ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/flac + ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/wavpack ) SET(test_runner_SRCS @@ -42,6 +43,7 @@ test_ape.cpp test_apetag.cpp test_wav.cpp + test_wavpack.cpp ) IF(WITH_MP4) SET(test_runner_SRCS ${test_runner_SRCS} --- trunk/kdesupport/taglib/tests/Makefile.am #1201475:1201476 @@ -12,7 +12,8 @@ -I$(top_srcdir)/taglib/flac \ -I$(top_srcdir)/taglib/riff \ -I$(top_srcdir)/taglib/riff/aiff \ - -I$(top_srcdir)/taglib/mpeg/id3v2/frames + -I$(top_srcdir)/taglib/mpeg/id3v2/frames \ + -I$(top_srcdir)/taglib/wavpack test_runner_SOURCES = \ main.cpp \ @@ -32,7 +33,8 @@ test_aiff.cpp \ test_ogg.cpp \ test_oggflac.cpp \ - test_flac.cpp + test_flac.cpp \ + test_wavpack.cpp if build_tests TESTS = test_runner