From e4813f4996d788e0a4c5b8a6fd495b30eca24a9e Mon Sep 17 00:00:00 2001 From: Urs Fleisch Date: Sun, 6 Dec 2020 19:55:25 +0100 Subject: [PATCH 1/2] Calculate bitrate for IEEE Float WAV files without fact chunk (#959) When a WAV file with float format without a fact chunk containing a totalSamples value is encountered, the bitrate is not calculated. However, since all samples have the same number of bits, the number of samples can be calculated from the size of the data chunk and number of channels and bits per sample, as it is done in the PCM case. --- taglib/riff/wav/wavproperties.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/taglib/riff/wav/wavproperties.cpp b/taglib/riff/wav/wavproperties.cpp index 181e3a6c..64ce78eb 100644 --- a/taglib/riff/wav/wavproperties.cpp +++ b/taglib/riff/wav/wavproperties.cpp @@ -35,7 +35,8 @@ namespace enum WaveFormat { FORMAT_UNKNOWN = 0x0000, - FORMAT_PCM = 0x0001 + FORMAT_PCM = 0x0001, + FORMAT_IEEE_FLOAT = 0x0003 }; } @@ -183,7 +184,7 @@ void RIFF::WAV::Properties::read(File *file) } d->format = data.toShort(0, false); - if(d->format != FORMAT_PCM && totalSamples == 0) { + if(d->format != FORMAT_PCM && d->format != FORMAT_IEEE_FLOAT && totalSamples == 0) { debug("RIFF::WAV::Properties::read() - Non-PCM format, but 'fact' chunk not found."); return; } @@ -192,7 +193,7 @@ void RIFF::WAV::Properties::read(File *file) d->sampleRate = data.toUInt(4, false); d->bitsPerSample = data.toShort(14, false); - if(d->format != FORMAT_PCM) + if(d->format != FORMAT_PCM && !(d->format == FORMAT_IEEE_FLOAT && totalSamples == 0)) d->sampleFrames = totalSamples; else if(d->channels > 0 && d->bitsPerSample > 0) d->sampleFrames = streamLength / (d->channels * ((d->bitsPerSample + 7) / 8)); From 741ed4e4bf2a3edabd00aa9ceb00d48047a0afcd Mon Sep 17 00:00:00 2001 From: Urs Fleisch Date: Tue, 22 Dec 2020 16:02:01 +0100 Subject: [PATCH 2/2] Add test for IEEE Float WAV file without fact chunk --- tests/test_wav.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/test_wav.cpp b/tests/test_wav.cpp index fd0c04f7..326e42ca 100644 --- a/tests/test_wav.cpp +++ b/tests/test_wav.cpp @@ -28,9 +28,11 @@ #include #include #include +#include #include #include #include +#include "plainfile.h" #include "utils.h" using namespace std; @@ -42,6 +44,7 @@ class TestWAV : public CppUnit::TestFixture CPPUNIT_TEST(testPCMProperties); CPPUNIT_TEST(testALAWProperties); CPPUNIT_TEST(testFloatProperties); + CPPUNIT_TEST(testFloatWithoutFactChunkProperties); CPPUNIT_TEST(testZeroSizeDataChunk); CPPUNIT_TEST(testID3v2Tag); CPPUNIT_TEST(testSaveID3v23); @@ -98,6 +101,25 @@ public: CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->format()); } + void testFloatWithoutFactChunkProperties() + { + ByteVector wavData = PlainFile(TEST_FILE_PATH_C("float64.wav")).readAll(); + CPPUNIT_ASSERT_EQUAL(ByteVector("fact"), wavData.mid(36, 4)); + // Remove the fact chunk by renaming it to fakt + wavData[38] = 'k'; + ByteVectorStream wavStream(wavData); + RIFF::WAV::File f(&wavStream); + CPPUNIT_ASSERT(f.audioProperties()); + CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->lengthInSeconds()); + CPPUNIT_ASSERT_EQUAL(97, f.audioProperties()->lengthInMilliseconds()); + CPPUNIT_ASSERT_EQUAL(5645, f.audioProperties()->bitrate()); + CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels()); + CPPUNIT_ASSERT_EQUAL(44100, f.audioProperties()->sampleRate()); + CPPUNIT_ASSERT_EQUAL(64, f.audioProperties()->bitsPerSample()); + CPPUNIT_ASSERT_EQUAL(4281U, f.audioProperties()->sampleFrames()); + CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->format()); + } + void testZeroSizeDataChunk() { RIFF::WAV::File f(TEST_FILE_PATH_C("zero-size-chunk.wav"));