]> granicus.if.org Git - taglib/commitdiff
Ogg Opus: AudioProperties improvements
authorTsuda Kageyu <tsuda.kageyu@gmail.com>
Thu, 21 May 2015 05:30:37 +0000 (14:30 +0900)
committerTsuda Kageyu <tsuda.kageyu@gmail.com>
Thu, 18 Jun 2015 08:19:23 +0000 (17:19 +0900)
Add lengthInSeconds(), lengthInMilliseconds() properties. (#503)
Remove some data members which are not needed to carry.
Add some tests for audio properties.
Add some supplementary comments.

taglib/ogg/opus/opusproperties.cpp
taglib/ogg/opus/opusproperties.h
tests/test_opus.cpp

index f098921b907b68b8fa7b3ac9b63807b3bbc22778..c8aff624632a145c2e2e9902df887d6b53e8c4b8 100644 (file)
@@ -41,17 +41,13 @@ using namespace TagLib::Ogg;
 class Opus::Properties::PropertiesPrivate
 {
 public:
-  PropertiesPrivate(File *f, ReadStyle s) :
-    file(f),
-    style(s),
+  PropertiesPrivate() :
     length(0),
     bitrate(0),
     inputSampleRate(0),
     channels(0),
     opusVersion(0) {}
 
-  File *file;
-  ReadStyle style;
   int length;
   int bitrate;
   int inputSampleRate;
@@ -63,10 +59,11 @@ public:
 // public members
 ////////////////////////////////////////////////////////////////////////////////
 
-Opus::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style)
+Opus::Properties::Properties(File *file, ReadStyle style) :
+  AudioProperties(style),
+  d(new PropertiesPrivate())
 {
-  d = new PropertiesPrivate(file, style);
-  read();
+  read(file);
 }
 
 Opus::Properties::~Properties()
@@ -75,6 +72,16 @@ Opus::Properties::~Properties()
 }
 
 int Opus::Properties::length() const
+{
+  return lengthInSeconds();
+}
+
+int Ogg::Opus::Properties::lengthInSeconds() const
+{
+  return d->length / 1000;
+}
+
+int Ogg::Opus::Properties::lengthInMilliseconds() const
 {
   return d->length;
 }
@@ -111,13 +118,13 @@ int Opus::Properties::opusVersion() const
 // private members
 ////////////////////////////////////////////////////////////////////////////////
 
-void Opus::Properties::read()
+void Opus::Properties::read(File *file)
 {
   // Get the identification header from the Ogg implementation.
 
   // http://tools.ietf.org/html/draft-terriberry-oggopus-01#section-5.1
 
-  ByteVector data = d->file->packet(0);
+  const ByteVector data = file->packet(0);
 
   // *Magic Signature*
   uint pos = 8;
@@ -144,16 +151,21 @@ void Opus::Properties::read()
   // *Channel Mapping Family* (8 bits, unsigned)
   pos += 1;
 
-  const Ogg::PageHeader *first = d->file->firstPageHeader();
-  const Ogg::PageHeader *last  = d->file->lastPageHeader();
+  const Ogg::PageHeader *first = file->firstPageHeader();
+  const Ogg::PageHeader *last  = file->lastPageHeader();
 
   if(first && last) {
     const long long start = first->absoluteGranularPosition();
     const long long end   = last->absoluteGranularPosition();
 
     if(start >= 0 && end >= 0) {
-      d->length  = (int)((end - start - preSkip) / 48000);
-      d->bitrate = (int)(d->file->length() * 8.0 / (1000.0 * d->length) + 0.5);
+      const long long frameCount = (end - start - preSkip);
+
+      if(frameCount > 0) {
+        const double length = frameCount * 1000.0 / 48000.0;
+        d->length  = static_cast<int>(length + 0.5);
+        d->bitrate = static_cast<int>(file->length() * 8.0 / length + 0.5);
+      }
     }
     else {
       debug("Opus::Properties::read() -- The PCM values for the start or "
index 946f16757cccb416e7ae2b4a6c8e0f5e0cd82e09..be88b14614f3f0ade33b4557027dd1c1476cae04 100644 (file)
@@ -61,11 +61,49 @@ 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.
+         *
+         * \note Always returns 48000, because Opus can decode any stream at a
+         * sample rate of 8, 12, 16, 24, or 48 kHz,
+         */
         virtual int sampleRate() const;
+
+        /*!
+         * Returns the number of audio channels.
+         */
         virtual int channels() const;
 
         /*!
@@ -76,7 +114,7 @@ namespace TagLib {
         int inputSampleRate() const;
 
         /*!
-         * Returns the Opus version, currently "0" (as specified by the spec).
+         * Returns the Opus version, in the range 0...255.
          */
         int opusVersion() const;
 
@@ -84,7 +122,7 @@ namespace TagLib {
         Properties(const Properties &);
         Properties &operator=(const Properties &);
 
-        void read();
+        void read(File *file);
 
         class PropertiesPrivate;
         PropertiesPrivate *d;
index 18556241f58748f298d200002a37efc5a0cf33d3..73863bf8314ec067fd3290522a826c7f78aeec58 100644 (file)
@@ -12,21 +12,25 @@ using namespace TagLib;
 class TestOpus : public CppUnit::TestFixture
 {
   CPPUNIT_TEST_SUITE(TestOpus);
-  CPPUNIT_TEST(testProperties);
+  CPPUNIT_TEST(testAudioProperties);
   CPPUNIT_TEST(testReadComments);
   CPPUNIT_TEST(testWriteComments);
   CPPUNIT_TEST_SUITE_END();
 
 public:
 
-  void testProperties()
+  void testAudioProperties()
   {
     Ogg::Opus::File f(TEST_FILE_PATH_C("correctness_gain_silent_output.opus"));
+    CPPUNIT_ASSERT(f.audioProperties());
     CPPUNIT_ASSERT_EQUAL(7, f.audioProperties()->length());
-    CPPUNIT_ASSERT_EQUAL(41, f.audioProperties()->bitrate());
+    CPPUNIT_ASSERT_EQUAL(7, f.audioProperties()->lengthInSeconds());
+    CPPUNIT_ASSERT_EQUAL(7737, f.audioProperties()->lengthInMilliseconds());
+    CPPUNIT_ASSERT_EQUAL(37, f.audioProperties()->bitrate());
     CPPUNIT_ASSERT_EQUAL(1, f.audioProperties()->channels());
     CPPUNIT_ASSERT_EQUAL(48000, f.audioProperties()->sampleRate());
-    CPPUNIT_ASSERT_EQUAL(48000, ((Ogg::Opus::Properties *)f.audioProperties())->inputSampleRate());
+    CPPUNIT_ASSERT_EQUAL(48000, f.audioProperties()->inputSampleRate());
+    CPPUNIT_ASSERT_EQUAL(1, f.audioProperties()->opusVersion());
   }
 
   void testReadComments()