From 21412e2ba2938299c887e4920388d962f5bd33d4 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Thu, 21 May 2015 12:15:11 +0900 Subject: [PATCH] FLAC: AudioProperties improvements Add lengthInSeconds(), lengthInMilliseconds() properties. (#503) Add bitsPerSample() property besides sampleWidth(). (#360) Remove some data members which are not needed to carry. Add some tests for audio properties. Add some supplementary comments. --- taglib/flac/flacproperties.cpp | 77 ++++++++++++++++++--------------- taglib/flac/flacproperties.h | 51 ++++++++++++++++++++-- tests/data/sinewave.flac | Bin 0 -> 64567 bytes tests/test_flac.cpp | 19 ++++++++ 4 files changed, 109 insertions(+), 38 deletions(-) create mode 100644 tests/data/sinewave.flac diff --git a/taglib/flac/flacproperties.cpp b/taglib/flac/flacproperties.cpp index e591193e..486ce2f5 100644 --- a/taglib/flac/flacproperties.cpp +++ b/taglib/flac/flacproperties.cpp @@ -34,24 +34,18 @@ using namespace TagLib; class FLAC::Properties::PropertiesPrivate { public: - PropertiesPrivate(ByteVector d, long st, ReadStyle s) : - data(d), - streamLength(st), - style(s), + PropertiesPrivate() : length(0), bitrate(0), sampleRate(0), - sampleWidth(0), + bitsPerSample(0), channels(0), sampleFrames(0) {} - ByteVector data; - long streamLength; - ReadStyle style; int length; int bitrate; int sampleRate; - int sampleWidth; + int bitsPerSample; int channels; unsigned long long sampleFrames; ByteVector signature; @@ -61,16 +55,18 @@ public: // public members //////////////////////////////////////////////////////////////////////////////// -FLAC::Properties::Properties(ByteVector data, long streamLength, ReadStyle style) : AudioProperties(style) +FLAC::Properties::Properties(ByteVector data, long streamLength, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) { - d = new PropertiesPrivate(data, streamLength, style); - read(); + read(data, streamLength); } -FLAC::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style) +FLAC::Properties::Properties(File *file, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) { - d = new PropertiesPrivate(file->streamInfoData(), file->streamLength(), style); - read(); + read(file->streamInfoData(), file->streamLength()); } FLAC::Properties::~Properties() @@ -79,6 +75,16 @@ FLAC::Properties::~Properties() } int FLAC::Properties::length() const +{ + return lengthInSeconds(); +} + +int FLAC::Properties::lengthInSeconds() const +{ + return d->length / 1000; +} + +int FLAC::Properties::lengthInMilliseconds() const { return d->length; } @@ -93,9 +99,14 @@ int FLAC::Properties::sampleRate() const return d->sampleRate; } +int FLAC::Properties::bitsPerSample() const +{ + return d->bitsPerSample; +} + int FLAC::Properties::sampleWidth() const { - return d->sampleWidth; + return bitsPerSample(); } int FLAC::Properties::channels() const @@ -117,9 +128,9 @@ ByteVector FLAC::Properties::signature() const // private members //////////////////////////////////////////////////////////////////////////////// -void FLAC::Properties::read() +void FLAC::Properties::read(const ByteVector &data, long streamLength) { - if(d->data.size() < 18) { + if(data.size() < 18) { debug("FLAC::Properties::read() - FLAC properties must contain at least 18 bytes."); return; } @@ -138,32 +149,28 @@ void FLAC::Properties::read() // Maximum frame size (in bytes) pos += 3; - uint flags = d->data.toUInt(pos, true); + const uint flags = data.toUInt(pos, true); pos += 4; - d->sampleRate = flags >> 12; - d->channels = ((flags >> 9) & 7) + 1; - d->sampleWidth = ((flags >> 4) & 31) + 1; + d->sampleRate = flags >> 12; + d->channels = ((flags >> 9) & 7) + 1; + d->bitsPerSample = ((flags >> 4) & 31) + 1; // The last 4 bits are the most significant 4 bits for the 36 bit // stream length in samples. (Audio files measured in days) - unsigned long long hi = flags & 0xf; - unsigned long long lo = d->data.toUInt(pos, true); + const ulonglong hi = flags & 0xf; + const ulonglong lo = data.toUInt(pos, true); pos += 4; d->sampleFrames = (hi << 32) | lo; - if(d->sampleRate > 0) - d->length = int(d->sampleFrames / d->sampleRate); - - // Uncompressed bitrate: - - //d->bitrate = ((d->sampleRate * d->channels) / 1000) * d->sampleWidth; - - // Real bitrate: - - d->bitrate = d->length > 0 ? ((d->streamLength * 8UL) / d->length) / 1000 : 0; + if(d->sampleFrames > 0 && d->sampleRate > 0) { + const double length = d->sampleFrames * 1000.0 / d->sampleRate; + d->length = static_cast(length + 0.5); + d->bitrate = static_cast(streamLength * 8.0 / length + 0.5); + } - d->signature = d->data.mid(pos, 32); + if(data.size() >= pos + 16) + d->signature = data.mid(pos, 16); } diff --git a/taglib/flac/flacproperties.h b/taglib/flac/flacproperties.h index a9cede0a..6f13ce62 100644 --- a/taglib/flac/flacproperties.h +++ b/taglib/flac/flacproperties.h @@ -64,16 +64,61 @@ namespace TagLib { */ virtual ~Properties(); - // Reimplementations. - + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ virtual int channels() const; + /*! + * Returns the number of bits per audio sample as read from the FLAC + * identification header. + */ + int bitsPerSample() const; + /*! * Returns the sample width as read from the FLAC identification * header. + * + * \note This method is just an alias of bitsPerSample(). + * + * \deprecated */ int sampleWidth() const; @@ -92,7 +137,7 @@ namespace TagLib { Properties(const Properties &); Properties &operator=(const Properties &); - void read(); + void read(const ByteVector &data, long streamLength); class PropertiesPrivate; PropertiesPrivate *d; diff --git a/tests/data/sinewave.flac b/tests/data/sinewave.flac new file mode 100644 index 0000000000000000000000000000000000000000..25d31b2d72ebd2d4e23c0923e06cefdd452678e4 GIT binary patch literal 64567 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 zlength()); + CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->lengthInSeconds()); + CPPUNIT_ASSERT_EQUAL(3550, f.audioProperties()->lengthInMilliseconds()); + CPPUNIT_ASSERT_EQUAL(145, f.audioProperties()->bitrate()); + CPPUNIT_ASSERT_EQUAL(44100, f.audioProperties()->sampleRate()); + CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels()); + CPPUNIT_ASSERT_EQUAL(16, f.audioProperties()->bitsPerSample()); + CPPUNIT_ASSERT_EQUAL(16, f.audioProperties()->sampleWidth()); + CPPUNIT_ASSERT_EQUAL(156556ULL, f.audioProperties()->sampleFrames()); + CPPUNIT_ASSERT_EQUAL( + ByteVector("\xcf\xe3\xd9\xda\xba\xde\xab\x2c\xbf\x2c\xa2\x35\x27\x4b\x7f\x76"), + f.audioProperties()->signature()); + } + void testZeroSizedPadding() { ScopedFileCopy copy("zero-sized-padding", ".flac"); -- 2.50.1