From 21412e2ba2938299c887e4920388d962f5bd33d4 Mon Sep 17 00:00:00 2001
From: Tsuda Kageyu <tsuda.kageyu@gmail.com>
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);
+  if(d->sampleFrames > 0 && d->sampleRate > 0) {
+    const double length = d->sampleFrames * 1000.0 / d->sampleRate;
+    d->length  = static_cast<int>(length + 0.5);
+    d->bitrate = static_cast<int>(streamLength * 8.0 / length + 0.5);
+  }
 
-  // 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;
-
-  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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

literal 0
HcmV?d00001

diff --git a/tests/test_flac.cpp b/tests/test_flac.cpp
index 164020a6..dd09b3ea 100644
--- a/tests/test_flac.cpp
+++ b/tests/test_flac.cpp
@@ -25,6 +25,7 @@ class TestFLAC : public CppUnit::TestFixture
   CPPUNIT_TEST(testSaveMultipleValues);
   CPPUNIT_TEST(testDict);
   CPPUNIT_TEST(testInvalid);
+  CPPUNIT_TEST(testAudioProperties);
   CPPUNIT_TEST(testZeroSizedPadding);
   CPPUNIT_TEST_SUITE_END();
 
@@ -256,6 +257,24 @@ public:
     CPPUNIT_ASSERT_EQUAL(TagLib::uint(0), f.properties().size());
   }
 
+  void testAudioProperties()
+  {
+    FLAC::File f(TEST_FILE_PATH_C("sinewave.flac"));
+    CPPUNIT_ASSERT(f.audioProperties());
+    CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->length());
+    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");