Add support for AIFF-C files.

This commit is contained in:
Tsuda Kageyu 2014-12-30 23:53:40 +09:00
parent be33389884
commit 3b8c7d4e3a
6 changed files with 74 additions and 5 deletions

View 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);

View 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])));
}
}

View 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 &);

BIN
tests/data/alaw.aifc Normal file

Binary file not shown.

BIN
tests/data/segfault.aif Normal file

Binary file not shown.

View 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);