]> granicus.if.org Git - taglib/commitdiff
AIFF: AudioProperties improvements
authorTsuda Kageyu <tsuda.kageyu@gmail.com>
Thu, 21 May 2015 08:09:18 +0000 (17:09 +0900)
committerTsuda Kageyu <tsuda.kageyu@gmail.com>
Thu, 18 Jun 2015 08:30:58 +0000 (17:30 +0900)
Add lengthInSeconds(), lengthInMilliseconds() properties. (#503)
Add bitsPerSample() property besides sampleWidth(). (#360)
Add some tests for audio properties.
Add some supplementary comments.

taglib/riff/aiff/aifffile.cpp
taglib/riff/aiff/aiffproperties.cpp
taglib/riff/aiff/aiffproperties.h
tests/test_aiff.cpp

index c7cadb6712b406b83dd4914b10b8d06ab472bec6..6c136cde8ab6ec04554fa8abd458172df1692790 100644 (file)
@@ -150,12 +150,22 @@ void RIFF::AIFF::File::read(bool readProperties, Properties::ReadStyle propertie
         debug("RIFF::AIFF::File::read() - Duplicate ID3v2 tag found.");
       }
     }
-    else if(name == "COMM" && readProperties) {
-      if(formatData.isEmpty()) {
-        formatData = chunkData(i);
+    else if(readProperties) {
+      if(name == "COMM") {
+        if(formatData.isEmpty()) {
+          formatData = chunkData(i);
+        }
+        else {
+          debug("RIFF::AIFF::File::read() - Duplicate 'COMM' chunk found.");
+        }
       }
-      else {
-        debug("RIFF::AIFF::File::read() - Duplicate 'COMM' chunk found.");
+      else if(name == "SSND") {
+        if(streamLength == 0) {
+          streamLength = chunkDataSize(i) + chunkPadding(i);
+        }
+        else {
+          debug("RIFF::AIFF::File::read() - Duplicate 'SSND' chunk found.");
+        }
       }
     }
   }
index 63fed45f2608a15d3f1b7401079616ef855be942..8cb5de62ccfea7c58f9b795cca2ae4d04bbeb8a1 100644 (file)
@@ -37,14 +37,14 @@ public:
     bitrate(0),
     sampleRate(0),
     channels(0),
-    sampleWidth(0),
+    bitsPerSample(0),
     sampleFrames(0) {}
 
   int length;
   int bitrate;
   int sampleRate;
   int channels;
-  int sampleWidth;
+  int bitsPerSample;
 
   ByteVector compressionType;
   String compressionName;
@@ -56,9 +56,10 @@ public:
 // public members
 ////////////////////////////////////////////////////////////////////////////////
 
-RIFF::AIFF::Properties::Properties(const ByteVector &data, ReadStyle style) : AudioProperties(style)
+RIFF::AIFF::Properties::Properties(const ByteVector &data, ReadStyle style) :
+  AudioProperties(style),
+  d(new PropertiesPrivate())
 {
-  d = new PropertiesPrivate;
   read(data);
 }
 
@@ -68,6 +69,16 @@ RIFF::AIFF::Properties::~Properties()
 }
 
 int RIFF::AIFF::Properties::length() const
+{
+  return lengthInSeconds();
+}
+
+int RIFF::AIFF::Properties::lengthInSeconds() const
+{
+  return d->length / 1000;
+}
+
+int RIFF::AIFF::Properties::lengthInMilliseconds() const
 {
   return d->length;
 }
@@ -87,9 +98,14 @@ int RIFF::AIFF::Properties::channels() const
   return d->channels;
 }
 
+int RIFF::AIFF::Properties::bitsPerSample() const
+{
+  return d->bitsPerSample;
+}
+
 int RIFF::AIFF::Properties::sampleWidth() const
 {
-  return d->sampleWidth;
+  return bitsPerSample();
 }
 
 TagLib::uint RIFF::AIFF::Properties::sampleFrames() const
@@ -122,16 +138,19 @@ void RIFF::AIFF::Properties::read(const ByteVector &data)
     return;
   }
 
-  d->channels       = data.toShort(0U);
-  d->sampleFrames   = data.toUInt(2U);
-  d->sampleWidth    = data.toShort(6U);
+  d->channels      = data.toShort(0U);
+  d->sampleFrames  = data.toUInt(2U);
+  d->bitsPerSample = data.toShort(6U);
+
   const long double sampleRate = data.toFloat80BE(8);
-  d->sampleRate     = (int)sampleRate;
-  d->bitrate        = (int)((sampleRate * d->sampleWidth * d->channels) / 1000.0);
-  d->length         = d->sampleRate > 0 ? d->sampleFrames / d->sampleRate : 0;
+  if(sampleRate >= 1.0) {
+    d->sampleRate = static_cast<int>(sampleRate + 0.5);
+    d->bitrate    = static_cast<int>(sampleRate * d->bitsPerSample * d->channels / 1000.0 + 0.5);
+    d->length     = static_cast<int>(d->sampleFrames * 1000.0 / sampleRate + 0.5);
+  }
 
   if(data.size() >= 23) {
     d->compressionType = data.mid(18, 4);
-    d->compressionName = String(data.mid(23, static_cast<uchar>(data[22])));
+    d->compressionName = String(data.mid(23, static_cast<uchar>(data[22])), String::Latin1);
   }
 }
index d0778704ea0a363b0e878be258ab4ccdae69dd8d..651592a7349857b42ce781bcb0421d9b29d83b0b 100644 (file)
@@ -57,14 +57,65 @@ 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.
+         */
+        int bitsPerSample() const;
+
+        /*!
+         * Returns the number of bits per audio sample.
+         *
+         * \note This method is just an alias of bitsPerSample().
+         *
+         * \deprecated
+         */
         int sampleWidth() const;
+
+        /*!
+         * Returns the number of sample frames
+         */
         uint sampleFrames() const;
 
         /*!
index 968dbebbd528cf87795f9427d9456cb42da55c6c..360b75493bc831e868247c9995196036adebc9e7 100644 (file)
@@ -12,9 +12,9 @@ using namespace TagLib;
 class TestAIFF : public CppUnit::TestFixture
 {
   CPPUNIT_TEST_SUITE(TestAIFF);
-  CPPUNIT_TEST(testReading);
-  CPPUNIT_TEST(testSaveID3v2);
+  CPPUNIT_TEST(testAiffProperties);
   CPPUNIT_TEST(testAiffCProperties);
+  CPPUNIT_TEST(testSaveID3v2);
   CPPUNIT_TEST(testDuplicateID3v2);
   CPPUNIT_TEST(testFuzzedFile1);
   CPPUNIT_TEST(testFuzzedFile2);
@@ -22,10 +22,38 @@ class TestAIFF : public CppUnit::TestFixture
 
 public:
 
-  void testReading()
+  void testAiffProperties()
   {
     RIFF::AIFF::File f(TEST_FILE_PATH_C("empty.aiff"));
-    CPPUNIT_ASSERT_EQUAL(705, f.audioProperties()->bitrate());
+    CPPUNIT_ASSERT(f.audioProperties());
+    CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->length());
+    CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->lengthInSeconds());
+    CPPUNIT_ASSERT_EQUAL(67, f.audioProperties()->lengthInMilliseconds());
+    CPPUNIT_ASSERT_EQUAL(706, f.audioProperties()->bitrate());
+    CPPUNIT_ASSERT_EQUAL(44100, f.audioProperties()->sampleRate());
+    CPPUNIT_ASSERT_EQUAL(1, f.audioProperties()->channels());
+    CPPUNIT_ASSERT_EQUAL(16, f.audioProperties()->bitsPerSample());
+    CPPUNIT_ASSERT_EQUAL(16, f.audioProperties()->sampleWidth());
+    CPPUNIT_ASSERT_EQUAL(2941U, f.audioProperties()->sampleFrames());
+    CPPUNIT_ASSERT_EQUAL(false, f.audioProperties()->isAiffC());
+  }
+
+  void testAiffCProperties()
+  {
+    RIFF::AIFF::File f(TEST_FILE_PATH_C("alaw.aifc"));
+    CPPUNIT_ASSERT(f.audioProperties());
+    CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->length());
+    CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->lengthInSeconds());
+    CPPUNIT_ASSERT_EQUAL(37, f.audioProperties()->lengthInMilliseconds());
+    CPPUNIT_ASSERT_EQUAL(706, f.audioProperties()->bitrate());
+    CPPUNIT_ASSERT_EQUAL(44100, f.audioProperties()->sampleRate());
+    CPPUNIT_ASSERT_EQUAL(1, f.audioProperties()->channels());
+    CPPUNIT_ASSERT_EQUAL(16, f.audioProperties()->bitsPerSample());
+    CPPUNIT_ASSERT_EQUAL(16, f.audioProperties()->sampleWidth());
+    CPPUNIT_ASSERT_EQUAL(1622U, f.audioProperties()->sampleFrames());
+    CPPUNIT_ASSERT_EQUAL(true, f.audioProperties()->isAiffC());
+    CPPUNIT_ASSERT_EQUAL(ByteVector("ALAW"), f.audioProperties()->compressionType());
+    CPPUNIT_ASSERT_EQUAL(String("SGI CCITT G.711 A-law"), f.audioProperties()->compressionName());
   }
 
   void testSaveID3v2()
@@ -47,14 +75,6 @@ public:
     }
   }
 
-  void testAiffCProperties()
-  {
-    RIFF::AIFF::File f(TEST_FILE_PATH_C("alaw.aifc"));
-    CPPUNIT_ASSERT(f.audioProperties()->isAiffC());
-    CPPUNIT_ASSERT_EQUAL(ByteVector("ALAW"), f.audioProperties()->compressionType());
-    CPPUNIT_ASSERT_EQUAL(String("SGI CCITT G.711 A-law"), f.audioProperties()->compressionName());
-  }
-
   void testDuplicateID3v2()
   {
     RIFF::AIFF::File f(TEST_FILE_PATH_C("duplicate_id3v2.aiff"));