]> granicus.if.org Git - taglib/commitdiff
TrueAudio: AudioProperties improvements
authorTsuda Kageyu <tsuda.kageyu@gmail.com>
Thu, 21 May 2015 08:44:00 +0000 (17:44 +0900)
committerTsuda Kageyu <tsuda.kageyu@gmail.com>
Thu, 18 Jun 2015 08:52:36 +0000 (17:52 +0900)
Add lengthInSeconds(), lengthInMilliseconds() properties. (#503)
Avoid possible arithmetic overflows. (#520)
Remove some data members which are not needed to carry.
Add some tests for audio properties.
Add some supplementary comments.

taglib/trueaudio/trueaudioproperties.cpp
taglib/trueaudio/trueaudioproperties.h
tests/test_trueaudio.cpp

index dedd74e94fd493721526471e194a12ee4ac23160..17e3a2abee8de8ac2416fbaff5c8db019ee7fcae 100644 (file)
@@ -39,10 +39,7 @@ using namespace TagLib;
 class TrueAudio::Properties::PropertiesPrivate
 {
 public:
-  PropertiesPrivate(const ByteVector &d, long length, ReadStyle s) :
-    data(d),
-    streamLength(length),
-    style(s),
+  PropertiesPrivate() :
     version(0),
     length(0),
     bitrate(0),
@@ -51,9 +48,6 @@ public:
     bitsPerSample(0),
     sampleFrames(0) {}
 
-  ByteVector data;
-  long streamLength;
-  ReadStyle style;
   int version;
   int length;
   int bitrate;
@@ -67,10 +61,11 @@ public:
 // public members
 ////////////////////////////////////////////////////////////////////////////////
 
-TrueAudio::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) : AudioProperties(style)
+TrueAudio::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) :
+  AudioProperties(style),
+  d(new PropertiesPrivate())
 {
-  d = new PropertiesPrivate(data, streamLength, style);
-  read();
+  read(data, streamLength);
 }
 
 TrueAudio::Properties::~Properties()
@@ -79,6 +74,16 @@ TrueAudio::Properties::~Properties()
 }
 
 int TrueAudio::Properties::length() const
+{
+  return lengthInSeconds();
+}
+
+int TrueAudio::Properties::lengthInSeconds() const
+{
+  return d->length / 1000;
+}
+
+int TrueAudio::Properties::lengthInMilliseconds() const
 {
   return d->length;
 }
@@ -117,34 +122,50 @@ int TrueAudio::Properties::ttaVersion() const
 // private members
 ////////////////////////////////////////////////////////////////////////////////
 
-void TrueAudio::Properties::read()
+void TrueAudio::Properties::read(const ByteVector &data, long streamLength)
 {
-  if(!d->data.startsWith("TTA"))
+  if(data.size() < 4) {
+    debug("TrueAudio::Properties::read() -- data is too short.");
     return;
+  }
+
+  if(!data.startsWith("TTA")) {
+    debug("TrueAudio::Properties::read() -- invalid header signature.");
+    return;
+  }
 
-  int pos = 3;
+  uint pos = 3;
 
-  d->version = d->data[pos] - '0';
+  d->version = data[pos] - '0';
   pos += 1;
 
   // According to http://en.true-audio.com/TTA_Lossless_Audio_Codec_-_Format_Description
   // TTA2 headers are in development, and have a different format
   if(1 == d->version) {
+    if(data.size() < 18) {
+      debug("TrueAudio::Properties::read() -- data is too short.");
+      return;
+    }
+
     // Skip the audio format
     pos += 2;
 
-    d->channels = d->data.toShort(pos, false);
+    d->channels = data.toShort(pos, false);
     pos += 2;
 
-    d->bitsPerSample = d->data.toShort(pos, false);
+    d->bitsPerSample = data.toShort(pos, false);
     pos += 2;
 
-    d->sampleRate = d->data.toUInt(pos, false);
+    d->sampleRate = data.toUInt(pos, false);
     pos += 4;
 
-    d->sampleFrames = d->data.toUInt(pos, false);
-    d->length = d->sampleRate > 0 ? d->sampleFrames / d->sampleRate : 0;
+    d->sampleFrames = data.toUInt(pos, false);
+    pos += 4;
 
-    d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0;
+    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);
+    }
   }
 }
index 126b6788b4a4596d3211b976c7c68c869fa455c5..4d8cd451499b046d9b84b9f904f0707b73a4f8c5 100644 (file)
@@ -61,15 +61,50 @@ 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 number of bits per sample.
+       * Returns the number of bits per audio sample.
        */
       int bitsPerSample() const;
 
@@ -87,7 +122,7 @@ namespace TagLib {
       Properties(const Properties &);
       Properties &operator=(const Properties &);
 
-      void read();
+      void read(const ByteVector &data, long streamLength);
 
       class PropertiesPrivate;
       PropertiesPrivate *d;
index 5ff114cf02b670e76ec338b0ab3ea72372f5ae74..49a28af7cb075f79781b9b375366b7275ec10b7f 100644 (file)
@@ -20,6 +20,14 @@ public:
     TrueAudio::File f(TEST_FILE_PATH_C("empty.tta"));
     CPPUNIT_ASSERT(f.audioProperties());
     CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->length());
+    CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->lengthInSeconds());
+    CPPUNIT_ASSERT_EQUAL(3685, f.audioProperties()->lengthInMilliseconds());
+    CPPUNIT_ASSERT_EQUAL(173, f.audioProperties()->bitrate());
+    CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels());
+    CPPUNIT_ASSERT_EQUAL(44100, f.audioProperties()->sampleRate());
+    CPPUNIT_ASSERT_EQUAL(16, f.audioProperties()->bitsPerSample());
+    CPPUNIT_ASSERT_EQUAL(162496U, f.audioProperties()->sampleFrames());
+    CPPUNIT_ASSERT_EQUAL(1, f.audioProperties()->ttaVersion());
   }
 
 };