mirror of
https://github.com/taglib/taglib.git
synced 2025-07-22 06:54:22 -04:00
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 git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@1201476 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
This commit is contained in:
@ -230,8 +230,7 @@ void WavPack::File::read(bool readProperties, Properties::ReadStyle /* propertie
|
||||
|
||||
if(readProperties) {
|
||||
seek(0);
|
||||
d->properties = new Properties(readBlock(WavPack::HeaderSize),
|
||||
length() - d->APESize);
|
||||
d->properties = new Properties(this, length() - d->APESize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,8 @@ public:
|
||||
sampleRate(0),
|
||||
channels(0),
|
||||
version(0),
|
||||
bitsPerSample(0) {}
|
||||
bitsPerSample(0),
|
||||
file(0) {}
|
||||
|
||||
ByteVector data;
|
||||
long streamLength;
|
||||
@ -59,6 +60,7 @@ public:
|
||||
int channels;
|
||||
int version;
|
||||
int bitsPerSample;
|
||||
File *file;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -71,6 +73,14 @@ WavPack::Properties::Properties(const ByteVector &data, long streamLength, ReadS
|
||||
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 @@ static const unsigned int sample_rates[] = { 6000, 8000, 9600, 11025, 12000,
|
||||
#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 -
|
||||
@ -136,11 +153,43 @@ void WavPack::Properties::read()
|
||||
d->channels = (flags & MONO_FLAG) ? 1 : 2;
|
||||
|
||||
unsigned int samples = d->data.mid(12, 4).toUInt(false);
|
||||
if (samples == ~0u) {
|
||||
samples = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -54,9 +54,18 @@ namespace TagLib {
|
||||
/*!
|
||||
* 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.
|
||||
*/
|
||||
@ -84,6 +93,7 @@ namespace TagLib {
|
||||
Properties &operator=(const Properties &);
|
||||
|
||||
void read();
|
||||
unsigned int seekFinalIndex();
|
||||
|
||||
class PropertiesPrivate;
|
||||
PropertiesPrivate *d;
|
||||
|
Reference in New Issue
Block a user