From: Lukáš Lalinský Date: Sun, 11 Jul 2010 09:47:58 +0000 (+0000) Subject: Added reading of WAV audio length X-Git-Tag: v1.7rc1~41 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1d10bde500d01f00b94b2fd17703f641899d6bd6;p=taglib Added reading of WAV audio length BUG:116033 git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@1148614 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- diff --git a/NEWS b/NEWS index 919641a1..102ecda3 100644 --- a/NEWS +++ b/NEWS @@ -1,9 +1,10 @@ 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) =========================== diff --git a/taglib/riff/rifffile.cpp b/taglib/riff/rifffile.cpp index 595691f5..270c3672 100644 --- a/taglib/riff/rifffile.cpp +++ b/taglib/riff/rifffile.cpp @@ -79,6 +79,11 @@ TagLib::uint RIFF::File::chunkCount() const 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]; diff --git a/taglib/riff/rifffile.h b/taglib/riff/rifffile.h index 3b375e29..2f8881d9 100644 --- a/taglib/riff/rifffile.h +++ b/taglib/riff/rifffile.h @@ -67,6 +67,11 @@ namespace TagLib { */ 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 " */ diff --git a/taglib/riff/wav/wavfile.cpp b/taglib/riff/wav/wavfile.cpp index b2123ad5..f323a27d 100644 --- a/taglib/riff/wav/wavfile.cpp +++ b/taglib/riff/wav/wavfile.cpp @@ -96,13 +96,20 @@ bool RIFF::WAV::File::save() 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; } diff --git a/taglib/riff/wav/wavproperties.cpp b/taglib/riff/wav/wavproperties.cpp index 18920dd2..b0e4e034 100644 --- a/taglib/riff/wav/wavproperties.cpp +++ b/taglib/riff/wav/wavproperties.cpp @@ -35,12 +35,13 @@ using namespace TagLib; 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) { } @@ -50,6 +51,7 @@ public: int bitrate; int sampleRate; int channels; + uint streamLength; }; //////////////////////////////////////////////////////////////////////////////// @@ -58,7 +60,13 @@ public: 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); } @@ -93,12 +101,12 @@ int RIFF::WAV::Properties::channels() const 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; } diff --git a/taglib/riff/wav/wavproperties.h b/taglib/riff/wav/wavproperties.h index 531f877f..10fbba1c 100644 --- a/taglib/riff/wav/wavproperties.h +++ b/taglib/riff/wav/wavproperties.h @@ -26,6 +26,7 @@ #ifndef TAGLIB_WAVPROPERTIES_H #define TAGLIB_WAVPROPERTIES_H +#include "taglib.h" #include "audioproperties.h" namespace TagLib { @@ -54,6 +55,12 @@ 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. */ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 136f9b63..f5b80c69 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -12,6 +12,7 @@ INCLUDE_DIRECTORIES( ${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 @@ -40,6 +41,7 @@ SET(test_runner_SRCS test_flac.cpp test_ape.cpp test_apetag.cpp + test_wav.cpp ) IF(WITH_MP4) SET(test_runner_SRCS ${test_runner_SRCS} diff --git a/tests/data/empty.wav b/tests/data/empty.wav new file mode 100644 index 00000000..74b5a6de Binary files /dev/null and b/tests/data/empty.wav differ diff --git a/tests/test_riff.cpp b/tests/test_riff.cpp index ac7f40d7..20539ae1 100644 --- a/tests/test_riff.cpp +++ b/tests/test_riff.cpp @@ -15,6 +15,7 @@ public: 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) { @@ -48,6 +49,7 @@ public: 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");