TagLib 1.7
==========
- * Support for reading/writing tags from Monkey's Audio files.
+ * Support for reading/writing tags from Monkey's Audio files. (BUG:210404)
* Implemented APE::Tag::isEmpty() to check for all APE tags, not just the
basic ones.
+ * Added reading of WAV audio length. (BUG:116033)
TagLib 1.6.3 (Apr 17, 2010)
===========================
return d->chunkNames.size();
}
+TagLib::uint RIFF::File::chunkDataSize(uint i) const
+{
+ return d->chunkSizes[i];
+}
+
TagLib::uint RIFF::File::chunkOffset(uint i) const
{
return d->chunkOffsets[i];
*/
uint chunkOffset(uint i) const;
+ /*!
+ * \return The size of the chunk data.
+ */
+ uint chunkDataSize(uint i) const;
+
/*!
* \return The name of the specified chunk, for instance, "COMM" or "ID3 "
*/
void RIFF::WAV::File::read(bool readProperties, Properties::ReadStyle propertiesStyle)
{
+ ByteVector formatData;
+ uint streamLength = 0;
for(uint i = 0; i < chunkCount(); i++) {
if(chunkName(i) == "ID3 ")
d->tag = new ID3v2::Tag(this, chunkOffset(i));
else if(chunkName(i) == "fmt " && readProperties)
- d->properties = new Properties(chunkData(i), propertiesStyle);
+ formatData = chunkData(i);
+ else if(chunkName(i) == "data" && readProperties)
+ streamLength = chunkDataSize(i);
}
+ if(!formatData.isEmpty())
+ d->properties = new Properties(formatData, streamLength, propertiesStyle);
+
if(!d->tag)
d->tag = new ID3v2::Tag;
}
class RIFF::WAV::Properties::PropertiesPrivate
{
public:
- PropertiesPrivate() :
+ PropertiesPrivate(uint streamLength = 0) :
format(0),
length(0),
bitrate(0),
sampleRate(0),
- channels(0)
+ channels(0),
+ streamLength(streamLength)
{
}
int bitrate;
int sampleRate;
int channels;
+ uint streamLength;
};
////////////////////////////////////////////////////////////////////////////////
RIFF::WAV::Properties::Properties(const ByteVector &data, ReadStyle style) : AudioProperties(style)
{
- d = new PropertiesPrivate;
+ d = new PropertiesPrivate();
+ read(data);
+}
+
+RIFF::WAV::Properties::Properties(const ByteVector &data, uint streamLength, ReadStyle style) : AudioProperties(style)
+{
+ d = new PropertiesPrivate(streamLength);
read(data);
}
void RIFF::WAV::Properties::read(const ByteVector &data)
{
- d->format = data.mid(0, 2).toShort(false);
- d->channels = data.mid(2, 2).toShort(false);
+ d->format = data.mid(0, 2).toShort(false);
+ d->channels = data.mid(2, 2).toShort(false);
d->sampleRate = data.mid(4, 4).toUInt(false);
- d->bitrate = data.mid(8, 4).toUInt(false) * 8 / 1024;
- // short bitsPerSample = data.mid(10, 2).toShort();
- // d->bitrate = (sampleRate * sampleSize * d->channels) / 1024.0;
- // d->length = sampleFrames / d->sampleRate;
+ uint byteRate = data.mid(8, 4).toUInt(false);
+ d->bitrate = byteRate * 8 / 1024;
+
+ d->length = byteRate > 0 ? d->streamLength / byteRate : 0;
}
#ifndef TAGLIB_WAVPROPERTIES_H
#define TAGLIB_WAVPROPERTIES_H
+#include "taglib.h"
#include "audioproperties.h"
namespace TagLib {
*/
Properties(const ByteVector &data, ReadStyle style);
+ /*!
+ * Create an instance of WAV::Properties with the data read from the
+ * ByteVector \a data and the length calculated using \a streamLength.
+ */
+ Properties(const ByteVector &data, uint streamLength, ReadStyle style);
+
/*!
* Destroys this WAV::Properties instance.
*/
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mp4
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/riff
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/riff/aiff
+ ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/riff/wav
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/trueaudio
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ogg
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ogg/vorbis
test_flac.cpp
test_ape.cpp
test_apetag.cpp
+ test_wav.cpp
)
IF(WITH_MP4)
SET(test_runner_SRCS ${test_runner_SRCS}
PublicRIFF(FileName file) : RIFF::File(file, BigEndian) {};
TagLib::uint chunkCount() { return RIFF::File::chunkCount(); };
TagLib::uint chunkOffset(TagLib::uint i) { return RIFF::File::chunkOffset(i); };
+ TagLib::uint chunkDataSize(TagLib::uint i) { return RIFF::File::chunkDataSize(i); };
ByteVector chunkName(TagLib::uint i) { return RIFF::File::chunkName(i); };
ByteVector chunkData(TagLib::uint i) { return RIFF::File::chunkData(i); };
void setChunkData(const ByteVector &name, const ByteVector &data) {
f = new PublicRIFF(filename.c_str());
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f->chunkName(2));
CPPUNIT_ASSERT_EQUAL(ByteVector("foo"), f->chunkData(2));
+ CPPUNIT_ASSERT_EQUAL(TagLib::uint(3), f->chunkDataSize(2));
CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x1728 + 8), f->chunkOffset(2));
f->setChunkData("SSND", "abcd");