]> granicus.if.org Git - taglib/commitdiff
Add support for AIFF-C files.
authorTsuda Kageyu <tsuda.kageyu@gmail.com>
Tue, 30 Dec 2014 14:53:40 +0000 (23:53 +0900)
committerTsuda Kageyu <tsuda.kageyu@gmail.com>
Tue, 30 Dec 2014 14:53:40 +0000 (23:53 +0900)
taglib/fileref.cpp
taglib/riff/aiff/aiffproperties.cpp
taglib/riff/aiff/aiffproperties.h
tests/data/alaw.aifc [new file with mode: 0644]
tests/data/segfault.aif [new file with mode: 0644]
tests/test_aiff.cpp

index 4403a5fbfa3c4ec797635e460feee69548c4419f..2b5d5f2352558b0e1efd8563012d1b1ad7916715 100644 (file)
@@ -265,7 +265,7 @@ File *FileRef::create(FileName fileName, bool readAudioProperties,
       return new MP4::File(fileName, readAudioProperties, audioPropertiesStyle);
     if(ext == "WMA" || ext == "ASF")
       return new ASF::File(fileName, readAudioProperties, audioPropertiesStyle);
-    if(ext == "AIF" || ext == "AIFF")
+    if(ext == "AIF" || ext == "AIFF" || ext == "AFC" || ext == "AIFC")
       return new RIFF::AIFF::File(fileName, readAudioProperties, audioPropertiesStyle);
     if(ext == "WAV")
       return new RIFF::WAV::File(fileName, readAudioProperties, audioPropertiesStyle);
index 1afb4a99b58ed2969738e4a58458eac7e74d40a4..63fed45f2608a15d3f1b7401079616ef855be942 100644 (file)
@@ -38,16 +38,17 @@ public:
     sampleRate(0),
     channels(0),
     sampleWidth(0),
-    sampleFrames(0)
-  {
-
-  }
+    sampleFrames(0) {}
 
   int length;
   int bitrate;
   int sampleRate;
   int channels;
   int sampleWidth;
+
+  ByteVector compressionType;
+  String compressionName;
+
   uint sampleFrames;
 };
 
@@ -96,12 +97,31 @@ TagLib::uint RIFF::AIFF::Properties::sampleFrames() const
   return d->sampleFrames;
 }
 
+bool RIFF::AIFF::Properties::isAiffC() const
+{
+  return (!d->compressionType.isEmpty());
+}
+
+ByteVector RIFF::AIFF::Properties::compressionType() const
+{
+  return d->compressionType;
+}
+
+String RIFF::AIFF::Properties::compressionName() const
+{
+  return d->compressionName;
+}
 ////////////////////////////////////////////////////////////////////////////////
 // private members
 ////////////////////////////////////////////////////////////////////////////////
 
 void RIFF::AIFF::Properties::read(const ByteVector &data)
 {
+  if(data.size() < 18) {
+    debug("RIFF::AIFF::Properties::read() - \"COMM\" chunk is too short for AIFF.");
+    return;
+  }
+
   d->channels       = data.toShort(0U);
   d->sampleFrames   = data.toUInt(2U);
   d->sampleWidth    = data.toShort(6U);
@@ -109,4 +129,9 @@ void RIFF::AIFF::Properties::read(const ByteVector &data)
   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(data.size() >= 23) {
+    d->compressionType = data.mid(18, 4);
+    d->compressionName = String(data.mid(23, static_cast<uchar>(data[22])));
+  }
 }
index 68e90b792c9bf83f9cb5a10a40786773571c0c3e..d0778704ea0a363b0e878be258ab4ccdae69dd8d 100644 (file)
@@ -67,6 +67,30 @@ namespace TagLib {
         int sampleWidth() const;
         uint sampleFrames() const;
 
+        /*!
+         * Returns true if the file is in AIFF-C format, false if AIFF format.
+         */
+        bool isAiffC() const;
+
+        /*!
+         * Returns the compression type of the AIFF-C file.  For example, "NONE" for
+         * not compressed, "ACE2" for ACE 2-to-1.
+         *
+         * If the file is in AIFF format, always returns an empty vector.
+         *
+         * \see isAiffC()
+         */
+        ByteVector compressionType() const;
+
+        /*!
+         * Returns the concrete compression name of the AIFF-C file.
+         *
+         * If the file is in AIFF format, always returns an empty string.
+         *
+         * \see isAiffC()
+         */
+        String compressionName() const;
+
       private:
         Properties(const Properties &);
         Properties &operator=(const Properties &);
diff --git a/tests/data/alaw.aifc b/tests/data/alaw.aifc
new file mode 100644 (file)
index 0000000..33b4ea2
Binary files /dev/null and b/tests/data/alaw.aifc differ
diff --git a/tests/data/segfault.aif b/tests/data/segfault.aif
new file mode 100644 (file)
index 0000000..5dce192
Binary files /dev/null and b/tests/data/segfault.aif differ
index 00a120889c9062b89f355dbc35987eb1645da6e6..e90f52808f80ef8f4bab4c3b4deab397f6a7da22 100644 (file)
@@ -13,6 +13,8 @@ class TestAIFF : public CppUnit::TestFixture
 {
   CPPUNIT_TEST_SUITE(TestAIFF);
   CPPUNIT_TEST(testReading);
+  CPPUNIT_TEST(testAiffCProperties);
+  CPPUNIT_TEST(testReading);
   CPPUNIT_TEST_SUITE_END();
 
 public:
@@ -27,6 +29,24 @@ public:
     delete f;
   }
 
+  void testAiffCProperties()
+  {
+    ScopedFileCopy copy("alaw", ".aifc");
+    string filename = copy.fileName();
+
+    RIFF::AIFF::File *f = new RIFF::AIFF::File(filename.c_str());
+    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());
+    delete f;
+  }
+
+  void testFuzzedFiles()
+  {
+    RIFF::AIFF::File f(TEST_FILE_PATH_C("segfault.aif"));
+    CPPUNIT_ASSERT(!f.isValid());
+  }
+
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(TestAIFF);