mirror of
https://github.com/taglib/taglib.git
synced 2025-05-27 21:20:26 -04:00
Implement 'Length in milliseconds' feature of DSF/EBML.
This commit is contained in:
parent
ef09a707b8
commit
dc0cc4e7fa
@ -59,8 +59,8 @@ public:
|
||||
uint blockSizePerChannel;
|
||||
|
||||
// Computed
|
||||
uint bitrate;
|
||||
uint length;
|
||||
int bitrate;
|
||||
int length;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -85,12 +85,12 @@ int DSF::AudioProperties::length() const
|
||||
|
||||
int DSF::AudioProperties::lengthInSeconds() const
|
||||
{
|
||||
return d->length;
|
||||
return d->length / 1000;
|
||||
}
|
||||
|
||||
int DSF::AudioProperties::lengthInMilliseconds() const
|
||||
{
|
||||
return d->length * 1000;
|
||||
return d->length;
|
||||
}
|
||||
|
||||
int DSF::AudioProperties::bitrate() const
|
||||
@ -154,8 +154,8 @@ void DSF::AudioProperties::read(const ByteVector &data)
|
||||
d->sampleCount = data.toInt64LE(24);
|
||||
d->blockSizePerChannel = data.toUInt32LE(32);
|
||||
|
||||
d->bitrate
|
||||
= static_cast<uint>((d->samplingFrequency * d->bitsPerSample * d->channelNum) / 1000.0);
|
||||
d->length
|
||||
= d->samplingFrequency > 0 ? static_cast<uint>(d->sampleCount / d->samplingFrequency) : 0;
|
||||
d->bitrate = static_cast<int>(d->samplingFrequency * d->bitsPerSample * d->channelNum / 1000.0 + 0.5);
|
||||
|
||||
if(d->samplingFrequency > 0)
|
||||
d->length = static_cast<int>(d->sampleCount * 1000.0 / d->samplingFrequency + 0.5);
|
||||
}
|
||||
|
@ -32,41 +32,11 @@ class EBML::Matroska::AudioProperties::AudioPropertiesPrivate
|
||||
{
|
||||
public:
|
||||
// Constructor
|
||||
AudioPropertiesPrivate(File *document) :
|
||||
AudioPropertiesPrivate() :
|
||||
length(0),
|
||||
bitrate(0),
|
||||
channels(1),
|
||||
samplerate(8000)
|
||||
{
|
||||
Element *elem = document->getDocumentRoot()->getChild(Constants::Segment);
|
||||
Element *info = elem->getChild(Constants::SegmentInfo);
|
||||
Element *value;
|
||||
|
||||
if(info && (value = info->getChild(Constants::Duration))) {
|
||||
length = static_cast<int>(value->getAsFloat() / 1000000000.L);
|
||||
if((value = info->getChild(Constants::TimecodeScale)))
|
||||
length *= static_cast<int>(value->getAsUnsigned());
|
||||
else
|
||||
length *= 1000000;
|
||||
}
|
||||
|
||||
info = elem->getChild(Constants::Tracks);
|
||||
if(!info || !(info = info->getChild(Constants::TrackEntry)) ||
|
||||
!(info = info->getChild(Constants::Audio))) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Dirty bitrate:
|
||||
document->seek(0, File::End);
|
||||
bitrate = static_cast<int>(8 * document->tell() / ((length > 0) ? length : 1));
|
||||
|
||||
if((value = info->getChild(Constants::Channels)))
|
||||
channels = static_cast<int>(value->getAsUnsigned());
|
||||
|
||||
if((value = info->getChild(Constants::SamplingFrequency)))
|
||||
samplerate = static_cast<int>(value->getAsFloat());
|
||||
}
|
||||
samplerate(8000) {}
|
||||
|
||||
// The length of the file
|
||||
int length;
|
||||
@ -86,8 +56,9 @@ public:
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EBML::Matroska::AudioProperties::AudioProperties(File *document) :
|
||||
d(new AudioPropertiesPrivate(document))
|
||||
d(new AudioPropertiesPrivate())
|
||||
{
|
||||
read(document);
|
||||
}
|
||||
|
||||
EBML::Matroska::AudioProperties::~AudioProperties()
|
||||
@ -102,12 +73,12 @@ int EBML::Matroska::AudioProperties::length() const
|
||||
|
||||
int EBML::Matroska::AudioProperties::lengthInSeconds() const
|
||||
{
|
||||
return d->length;
|
||||
return d->length / 1000;
|
||||
}
|
||||
|
||||
int EBML::Matroska::AudioProperties::lengthInMilliseconds() const
|
||||
{
|
||||
return d->length * 1000;
|
||||
return d->length;
|
||||
}
|
||||
|
||||
int EBML::Matroska::AudioProperties::bitrate() const
|
||||
@ -124,3 +95,41 @@ int EBML::Matroska::AudioProperties::sampleRate() const
|
||||
{
|
||||
return d->samplerate;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void EBML::Matroska::AudioProperties::read(File *document)
|
||||
{
|
||||
Element *elem = document->getDocumentRoot()->getChild(Constants::Segment);
|
||||
Element *info = elem->getChild(Constants::SegmentInfo);
|
||||
Element *value;
|
||||
|
||||
if(info && (value = info->getChild(Constants::Duration))) {
|
||||
|
||||
const double length = value->getAsFloat() / 1000000.0;
|
||||
|
||||
if((value = info->getChild(Constants::TimecodeScale)))
|
||||
d->length = static_cast<int>(length * value->getAsUnsigned() + 0.5);
|
||||
else
|
||||
d->length = static_cast<int>(length * 1000000 + 0.5);
|
||||
}
|
||||
|
||||
info = elem->getChild(Constants::Tracks);
|
||||
if(!info || !(info = info->getChild(Constants::TrackEntry)) ||
|
||||
!(info = info->getChild(Constants::Audio))) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Dirty bitrate:
|
||||
if(d->length > 0)
|
||||
d->bitrate = static_cast<int>(document->length() * 8.0 / d->length + 0.5);
|
||||
|
||||
if((value = info->getChild(Constants::Channels)))
|
||||
d->channels = static_cast<int>(value->getAsUnsigned());
|
||||
|
||||
if((value = info->getChild(Constants::SamplingFrequency)))
|
||||
d->samplerate = static_cast<int>(value->getAsFloat());
|
||||
}
|
||||
|
@ -77,6 +77,8 @@ namespace TagLib {
|
||||
virtual int sampleRate() const;
|
||||
|
||||
private:
|
||||
void read(File *document);
|
||||
|
||||
class AudioPropertiesPrivate;
|
||||
AudioPropertiesPrivate *d;
|
||||
};
|
||||
|
@ -1,9 +1,9 @@
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <tag.h>
|
||||
#include <tbytevectorlist.h>
|
||||
#include <dsffile.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include "utils.h"
|
||||
|
||||
using namespace std;
|
||||
@ -21,10 +21,19 @@ public:
|
||||
void testBasic()
|
||||
{
|
||||
DSF::File f(TEST_FILE_PATH_C("empty.dsf"));
|
||||
DSF::AudioProperties *props = f.audioProperties();
|
||||
CPPUNIT_ASSERT_EQUAL(2822400, props->sampleRate());
|
||||
CPPUNIT_ASSERT_EQUAL(1, props->channels());
|
||||
CPPUNIT_ASSERT_EQUAL(1, props->bitsPerSample());
|
||||
CPPUNIT_ASSERT(f.audioProperties());
|
||||
CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->length());
|
||||
CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->lengthInSeconds());
|
||||
CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->lengthInMilliseconds());
|
||||
CPPUNIT_ASSERT_EQUAL(2822, f.audioProperties()->bitrate());
|
||||
CPPUNIT_ASSERT_EQUAL(1, f.audioProperties()->channels());
|
||||
CPPUNIT_ASSERT_EQUAL(2822400, f.audioProperties()->sampleRate());
|
||||
CPPUNIT_ASSERT_EQUAL(1, f.audioProperties()->formatVersion());
|
||||
CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->formatID());
|
||||
CPPUNIT_ASSERT_EQUAL(1, f.audioProperties()->channelType());
|
||||
CPPUNIT_ASSERT_EQUAL(1, f.audioProperties()->bitsPerSample());
|
||||
CPPUNIT_ASSERT_EQUAL((long long)0, f.audioProperties()->sampleCount());
|
||||
CPPUNIT_ASSERT_EQUAL(4096, f.audioProperties()->blockSizePerChannel());
|
||||
}
|
||||
|
||||
void testTags()
|
||||
|
@ -99,14 +99,18 @@ public:
|
||||
EBML::Matroska::File f(filename.c_str());
|
||||
CPPUNIT_ASSERT(f.isValid());
|
||||
|
||||
AudioProperties* a = f.audioProperties();
|
||||
CPPUNIT_ASSERT(a != 0);
|
||||
CPPUNIT_ASSERT(f.audioProperties());
|
||||
|
||||
// Not a very nice assertion...
|
||||
CPPUNIT_ASSERT_EQUAL(a->length(), 0);
|
||||
CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->length());
|
||||
CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->lengthInSeconds());
|
||||
CPPUNIT_ASSERT_EQUAL(735, f.audioProperties()->lengthInMilliseconds());
|
||||
|
||||
// Bitrate is not nice and thus not tested.
|
||||
CPPUNIT_ASSERT_EQUAL(a->sampleRate(), 44100);
|
||||
CPPUNIT_ASSERT_EQUAL(a->channels(), 2);
|
||||
CPPUNIT_ASSERT_EQUAL(51, f.audioProperties()->bitrate());
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels());
|
||||
CPPUNIT_ASSERT_EQUAL(44100, f.audioProperties()->sampleRate());
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user