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.");
+ }
}
}
}
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;
// 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);
}
}
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;
}
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
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);
}
}
*/
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;
/*!
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);
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()
}
}
- 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"));