Merge pull request #566 from TsudaKageyu/audioprop-tta

(wishlist) TrueAudio: AudioProperties improvements
This commit is contained in:
Tsuda Kageyu 2015-08-01 01:30:12 +09:00
commit 9759bd2dd7
6 changed files with 134 additions and 48 deletions

View File

@ -84,38 +84,38 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
TrueAudio::File::File(FileName file, bool readProperties,
Properties::ReadStyle propertiesStyle) : TagLib::File(file)
TrueAudio::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
TagLib::File(file),
d(new FilePrivate())
{
d = new FilePrivate;
if(isOpen())
read(readProperties, propertiesStyle);
read(readProperties);
}
TrueAudio::File::File(FileName file, ID3v2::FrameFactory *frameFactory,
bool readProperties, Properties::ReadStyle propertiesStyle) :
TagLib::File(file)
bool readProperties, Properties::ReadStyle) :
TagLib::File(file),
d(new FilePrivate(frameFactory))
{
d = new FilePrivate(frameFactory);
if(isOpen())
read(readProperties, propertiesStyle);
read(readProperties);
}
TrueAudio::File::File(IOStream *stream, bool readProperties,
Properties::ReadStyle propertiesStyle) : TagLib::File(stream)
TrueAudio::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) :
TagLib::File(stream),
d(new FilePrivate())
{
d = new FilePrivate;
if(isOpen())
read(readProperties, propertiesStyle);
read(readProperties);
}
TrueAudio::File::File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
bool readProperties, Properties::ReadStyle propertiesStyle) :
TagLib::File(stream)
bool readProperties, Properties::ReadStyle) :
TagLib::File(stream),
d(new FilePrivate(frameFactory))
{
d = new FilePrivate(frameFactory);
if(isOpen())
read(readProperties, propertiesStyle);
read(readProperties);
}
TrueAudio::File::~File()
@ -246,12 +246,11 @@ bool TrueAudio::File::hasID3v2Tag() const
return d->hasID3v2;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
void TrueAudio::File::read(bool readProperties, Properties::ReadStyle /* propertiesStyle */)
void TrueAudio::File::read(bool readProperties)
{
// Look for an ID3v2 tag
@ -284,16 +283,23 @@ void TrueAudio::File::read(bool readProperties, Properties::ReadStyle /* propert
// Look for TrueAudio metadata
if(readProperties) {
if(d->ID3v2Location >= 0) {
long streamLength;
if(d->hasID3v1)
streamLength = d->ID3v1Location;
else
streamLength = length();
if(d->hasID3v2) {
seek(d->ID3v2Location + d->ID3v2OriginalSize);
d->properties = new Properties(readBlock(TrueAudio::HeaderSize),
length() - d->ID3v2OriginalSize);
streamLength -= (d->ID3v2Location + d->ID3v2OriginalSize);
}
else {
seek(0);
d->properties = new Properties(readBlock(TrueAudio::HeaderSize),
length());
}
d->properties = new Properties(readBlock(TrueAudio::HeaderSize), streamLength);
}
}

View File

@ -239,7 +239,7 @@ namespace TagLib {
File(const File &);
File &operator=(const File &);
void read(bool readProperties, Properties::ReadStyle propertiesStyle);
void read(bool readProperties);
long findID3v1();
long findID3v2();

View 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;
}
int pos = 3;
if(!data.startsWith("TTA")) {
debug("TrueAudio::Properties::read() -- invalid header signature.");
return;
}
d->version = d->data[pos] - '0';
uint pos = 3;
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);
}
}
}

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

BIN
tests/data/tagged.tta Normal file

Binary file not shown.

View File

@ -11,6 +11,7 @@ class TestTrueAudio : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE(TestTrueAudio);
CPPUNIT_TEST(testReadPropertiesWithoutID3v2);
CPPUNIT_TEST(testReadPropertiesWithTags);
CPPUNIT_TEST_SUITE_END();
public:
@ -20,6 +21,29 @@ 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());
}
void testReadPropertiesWithTags()
{
TrueAudio::File f(TEST_FILE_PATH_C("tagged.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());
}
};