mirror of
https://github.com/taglib/taglib.git
synced 2025-05-27 21:20:26 -04:00
DSD Stream File (DSF) support
This commit is contained in:
parent
e275abb8a3
commit
39d1d68237
@ -24,6 +24,7 @@ include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/s3m
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/it
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/xm
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/dsf
|
||||
)
|
||||
|
||||
set(tag_HDRS
|
||||
@ -131,6 +132,8 @@ set(tag_HDRS
|
||||
s3m/s3mproperties.h
|
||||
xm/xmfile.h
|
||||
xm/xmproperties.h
|
||||
dsf/dsffile.h
|
||||
dsf/dsfproperties.h
|
||||
)
|
||||
|
||||
set(mpeg_SRCS
|
||||
@ -286,6 +289,11 @@ set(xm_SRCS
|
||||
xm/xmproperties.cpp
|
||||
)
|
||||
|
||||
set(dsf_SRCS
|
||||
dsf/dsffile.cpp
|
||||
dsf/dsfproperties.cpp
|
||||
)
|
||||
|
||||
set(toolkit_SRCS
|
||||
toolkit/tstring.cpp
|
||||
toolkit/tstringlist.cpp
|
||||
@ -306,6 +314,7 @@ set(tag_LIB_SRCS
|
||||
${vorbis_SRCS} ${oggflacs_SRCS} ${mpc_SRCS} ${ape_SRCS} ${toolkit_SRCS} ${flacs_SRCS}
|
||||
${wavpack_SRCS} ${speex_SRCS} ${trueaudio_SRCS} ${riff_SRCS} ${aiff_SRCS} ${wav_SRCS}
|
||||
${asf_SRCS} ${mp4_SRCS} ${mod_SRCS} ${s3m_SRCS} ${it_SRCS} ${xm_SRCS} ${opus_SRCS}
|
||||
${dsf_SRCS}
|
||||
tag.cpp
|
||||
tagunion.cpp
|
||||
fileref.cpp
|
||||
|
213
taglib/dsf/dsffile.cpp
Normal file
213
taglib/dsf/dsffile.cpp
Normal file
@ -0,0 +1,213 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2013-2023 Stephen F. Booth
|
||||
email : me@sbooth.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "dsffile.h"
|
||||
|
||||
#include "tdebug.h"
|
||||
#include "tpropertymap.h"
|
||||
#include "tagutils.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
// The DSF specification is located at http://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf
|
||||
|
||||
class DSF::File::FilePrivate
|
||||
{
|
||||
public:
|
||||
FilePrivate() = default;
|
||||
~FilePrivate() = default;
|
||||
|
||||
FilePrivate(const FilePrivate &) = delete;
|
||||
FilePrivate &operator=(const FilePrivate &) = delete;
|
||||
|
||||
long long fileSize = 0;
|
||||
long long metadataOffset = 0;
|
||||
std::unique_ptr<Properties> properties;
|
||||
std::unique_ptr<ID3v2::Tag> tag;
|
||||
};
|
||||
|
||||
bool DSF::File::isSupported(IOStream *stream)
|
||||
{
|
||||
// A DSF file has to start with "DSD "
|
||||
const ByteVector id = Utils::readHeader(stream, 4, false);
|
||||
return id.startsWith("DSD ");
|
||||
}
|
||||
|
||||
DSF::File::File(FileName file, bool readProperties,
|
||||
AudioProperties::ReadStyle propertiesStyle) :
|
||||
TagLib::File(file),
|
||||
d(std::make_unique<FilePrivate>())
|
||||
{
|
||||
if(isOpen())
|
||||
read(propertiesStyle);
|
||||
}
|
||||
|
||||
DSF::File::File(IOStream *stream, bool readProperties,
|
||||
AudioProperties::ReadStyle propertiesStyle) :
|
||||
TagLib::File(stream),
|
||||
d(std::make_unique<FilePrivate>())
|
||||
{
|
||||
if(isOpen())
|
||||
read(propertiesStyle);
|
||||
}
|
||||
|
||||
DSF::File::~File() = default;
|
||||
|
||||
ID3v2::Tag *DSF::File::tag() const
|
||||
{
|
||||
return d->tag.get();
|
||||
}
|
||||
|
||||
PropertyMap DSF::File::properties() const
|
||||
{
|
||||
return d->tag->properties();
|
||||
}
|
||||
|
||||
PropertyMap DSF::File::setProperties(const PropertyMap &properties)
|
||||
{
|
||||
return d->tag->setProperties(properties);
|
||||
}
|
||||
|
||||
DSF::Properties *DSF::File::audioProperties() const
|
||||
{
|
||||
return d->properties.get();
|
||||
}
|
||||
|
||||
bool DSF::File::save()
|
||||
{
|
||||
if(readOnly()) {
|
||||
debug("DSF::File::save() - Cannot save to a read only file.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Three things must be updated: the file size, the tag data, and the metadata offset
|
||||
|
||||
if(d->tag->isEmpty()) {
|
||||
long long newFileSize = d->metadataOffset ? d->metadataOffset : d->fileSize;
|
||||
|
||||
// Update the file size
|
||||
if(d->fileSize != newFileSize) {
|
||||
insert(ByteVector::fromLongLong(newFileSize, false), 12, 8);
|
||||
d->fileSize = newFileSize;
|
||||
}
|
||||
|
||||
// Update the metadata offset to 0 since there is no longer a tag
|
||||
if(d->metadataOffset) {
|
||||
insert(ByteVector::fromLongLong(0ULL, false), 20, 8);
|
||||
d->metadataOffset = 0;
|
||||
}
|
||||
|
||||
// Delete the old tag
|
||||
truncate(newFileSize);
|
||||
}
|
||||
else {
|
||||
ByteVector tagData = d->tag->render();
|
||||
|
||||
long long newMetadataOffset = d->metadataOffset ? d->metadataOffset : d->fileSize;
|
||||
long long newFileSize = newMetadataOffset + tagData.size();
|
||||
long long oldTagSize = d->fileSize - newMetadataOffset;
|
||||
|
||||
// Update the file size
|
||||
if(d->fileSize != newFileSize) {
|
||||
insert(ByteVector::fromLongLong(newFileSize, false), 12, 8);
|
||||
d->fileSize = newFileSize;
|
||||
}
|
||||
|
||||
// Update the metadata offset
|
||||
if(d->metadataOffset != newMetadataOffset) {
|
||||
insert(ByteVector::fromLongLong(newMetadataOffset, false), 20, 8);
|
||||
d->metadataOffset = newMetadataOffset;
|
||||
}
|
||||
|
||||
// Delete the old tag and write the new one
|
||||
insert(tagData, newMetadataOffset, static_cast<size_t>(oldTagSize));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DSF::File::read(AudioProperties::ReadStyle propertiesStyle)
|
||||
{
|
||||
if(!isOpen())
|
||||
return;
|
||||
|
||||
// A DSF file consists of four chunks: DSD chunk, format chunk, data chunk, and metadata chunk
|
||||
// The file format is not chunked in the sense of a RIFF File, though
|
||||
|
||||
// DSD chunk
|
||||
ByteVector chunkName = readBlock(4);
|
||||
if(chunkName != "DSD ") {
|
||||
debug("DSF::File::read() -- Not a DSF file.");
|
||||
setValid(false);
|
||||
return;
|
||||
}
|
||||
|
||||
long long chunkSize = readBlock(8).toLongLong(false);
|
||||
|
||||
// Integrity check
|
||||
if(chunkSize != 28) {
|
||||
debug("DSF::File::read() -- File is corrupted, wrong chunk size");
|
||||
setValid(false);
|
||||
return;
|
||||
}
|
||||
|
||||
d->fileSize = readBlock(8).toLongLong(false);
|
||||
|
||||
// File is malformed or corrupted
|
||||
if(d->fileSize != length()) {
|
||||
debug("DSF::File::read() -- File is corrupted wrong length");
|
||||
setValid(false);
|
||||
return;
|
||||
}
|
||||
|
||||
d->metadataOffset = readBlock(8).toLongLong(false);
|
||||
|
||||
// File is malformed or corrupted
|
||||
if(d->metadataOffset > d->fileSize) {
|
||||
debug("DSF::File::read() -- Invalid metadata offset.");
|
||||
setValid(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Format chunk
|
||||
chunkName = readBlock(4);
|
||||
if(chunkName != "fmt ") {
|
||||
debug("DSF::File::read() -- Missing 'fmt ' chunk.");
|
||||
setValid(false);
|
||||
return;
|
||||
}
|
||||
|
||||
chunkSize = readBlock(8).toLongLong(false);
|
||||
|
||||
d->properties = std::make_unique<Properties>(readBlock(chunkSize), propertiesStyle);
|
||||
|
||||
// Skip the data chunk
|
||||
|
||||
// A metadata offset of 0 indicates the absence of an ID3v2 tag
|
||||
if(d->metadataOffset == 0)
|
||||
d->tag = std::make_unique<ID3v2::Tag>();
|
||||
else
|
||||
d->tag = std::make_unique<ID3v2::Tag>(this, d->metadataOffset);
|
||||
}
|
117
taglib/dsf/dsffile.h
Normal file
117
taglib/dsf/dsffile.h
Normal file
@ -0,0 +1,117 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2013-2023 Stephen F. Booth
|
||||
email : me@sbooth.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_DSFFILE_H
|
||||
#define TAGLIB_DSFFILE_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "taglib_export.h"
|
||||
#include "tfile.h"
|
||||
|
||||
#include "dsfproperties.h"
|
||||
|
||||
#include "id3v2tag.h"
|
||||
|
||||
namespace TagLib {
|
||||
namespace DSF {
|
||||
class TAGLIB_EXPORT File : public TagLib::File {
|
||||
public:
|
||||
/*!
|
||||
* Constructs a DSD stream file from \a file.
|
||||
*
|
||||
* \note In the current implementation, both \a readProperties and
|
||||
* \a propertiesStyle are ignored. The audio properties are always
|
||||
* read.
|
||||
*/
|
||||
File(FileName file, bool readProperties = true,
|
||||
AudioProperties::ReadStyle propertiesStyle =
|
||||
AudioProperties::Average);
|
||||
|
||||
/*!
|
||||
* Constructs a DSD stream file from \a stream.
|
||||
*
|
||||
* \note In the current implementation, both \a readProperties and
|
||||
* \a propertiesStyle are ignored. The audio properties are always
|
||||
* read.
|
||||
*
|
||||
* \note TagLib will *not* take ownership of the stream, the caller is
|
||||
* responsible for deleting it after the File object.
|
||||
*/
|
||||
File(IOStream *stream, bool readProperties = true,
|
||||
AudioProperties::ReadStyle propertiesStyle =
|
||||
AudioProperties::Average);
|
||||
|
||||
/*!
|
||||
* Destroys this instance of the File.
|
||||
*/
|
||||
~File() override;
|
||||
|
||||
ID3v2::Tag *tag() const override;
|
||||
|
||||
/*!
|
||||
* Implements the unified property interface -- export function.
|
||||
* Forwards to ID3v2::Tag::properties().
|
||||
*/
|
||||
PropertyMap properties() const override;
|
||||
|
||||
/*!
|
||||
* Implements the unified property interface -- import function.
|
||||
* Forwards to ID3v2::Tag::setProperties().
|
||||
*/
|
||||
PropertyMap setProperties(const PropertyMap &) override;
|
||||
|
||||
/*!
|
||||
* Returns the DSF::Properties for this file. If no audio properties
|
||||
* were read then this will return a null pointer.
|
||||
*/
|
||||
Properties *audioProperties() const override;
|
||||
|
||||
/*!
|
||||
* Save the file.
|
||||
*
|
||||
* This returns true if the save was successful.
|
||||
*/
|
||||
bool save() override;
|
||||
|
||||
/*!
|
||||
* Returns whether or not the given \a stream can be opened as a DSF
|
||||
* file.
|
||||
*
|
||||
* \note This method is designed to do a quick check. The result may
|
||||
* not necessarily be correct.
|
||||
*/
|
||||
static bool isSupported(IOStream *stream);
|
||||
|
||||
private:
|
||||
void read(AudioProperties::ReadStyle propertiesStyle);
|
||||
|
||||
class FilePrivate;
|
||||
std::unique_ptr<FilePrivate> d;
|
||||
};
|
||||
} // namespace DSF
|
||||
} // namespace TagLib
|
||||
|
||||
#endif
|
133
taglib/dsf/dsfproperties.cpp
Normal file
133
taglib/dsf/dsfproperties.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2013-2023 Stephen F. Booth
|
||||
email : me@sbooth.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "dsfproperties.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
class DSF::Properties::PropertiesPrivate
|
||||
{
|
||||
public:
|
||||
PropertiesPrivate() = default;
|
||||
~PropertiesPrivate() = default;
|
||||
|
||||
PropertiesPrivate(const PropertiesPrivate &) = delete;
|
||||
PropertiesPrivate &operator=(const PropertiesPrivate &) = delete;
|
||||
|
||||
// Nomenclature is from DSF file format specification
|
||||
unsigned int formatVersion = 0;
|
||||
unsigned int formatID = 0;
|
||||
unsigned int channelType = 0;
|
||||
unsigned int channelNum = 0;
|
||||
unsigned int samplingFrequency = 0;
|
||||
unsigned int bitsPerSample = 0;
|
||||
long long sampleCount = 0;
|
||||
unsigned int blockSizePerChannel = 0;
|
||||
|
||||
// Computed
|
||||
unsigned int bitrate = 0;
|
||||
unsigned int length = 0;
|
||||
};
|
||||
|
||||
DSF::Properties::Properties(const ByteVector &data, ReadStyle style) :
|
||||
AudioProperties(style),
|
||||
d(std::make_unique<PropertiesPrivate>())
|
||||
{
|
||||
read(data);
|
||||
}
|
||||
|
||||
DSF::Properties::~Properties() = default;
|
||||
|
||||
int DSF::Properties::lengthInMilliseconds() const
|
||||
{
|
||||
return d->length;
|
||||
}
|
||||
|
||||
int DSF::Properties::bitrate() const
|
||||
{
|
||||
return d->bitrate;
|
||||
}
|
||||
|
||||
int DSF::Properties::sampleRate() const
|
||||
{
|
||||
return d->samplingFrequency;
|
||||
}
|
||||
|
||||
int DSF::Properties::channels() const
|
||||
{
|
||||
return d->channelNum;
|
||||
}
|
||||
|
||||
int DSF::Properties::formatVersion() const
|
||||
{
|
||||
return d->formatVersion;
|
||||
}
|
||||
|
||||
int DSF::Properties::formatID() const
|
||||
{
|
||||
return d->formatID;
|
||||
}
|
||||
|
||||
int DSF::Properties::channelType() const
|
||||
{
|
||||
return d->channelType;
|
||||
}
|
||||
|
||||
int DSF::Properties::bitsPerSample() const
|
||||
{
|
||||
return d->bitsPerSample;
|
||||
}
|
||||
|
||||
long long DSF::Properties::sampleCount() const
|
||||
{
|
||||
return d->sampleCount;
|
||||
}
|
||||
|
||||
int DSF::Properties::blockSizePerChannel() const
|
||||
{
|
||||
return d->blockSizePerChannel;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DSF::Properties::read(const ByteVector &data)
|
||||
{
|
||||
d->formatVersion = data.toUInt(0U,false);
|
||||
d->formatID = data.toUInt(4U,false);
|
||||
d->channelType = data.toUInt(8U,false);
|
||||
d->channelNum = data.toUInt(12U,false);
|
||||
d->samplingFrequency = data.toUInt(16U,false);
|
||||
d->bitsPerSample = data.toUInt(20U,false);
|
||||
d->sampleCount = data.toLongLong(24U,false);
|
||||
d->blockSizePerChannel = data.toUInt(32U,false);
|
||||
|
||||
d->bitrate
|
||||
= static_cast<unsigned int>((d->samplingFrequency * d->bitsPerSample * d->channelNum) / 1000.0 + 0.5);
|
||||
d->length
|
||||
= d->samplingFrequency > 0 ? static_cast<unsigned int>(d->sampleCount * 1000.0 / d->samplingFrequency + 0.5) : 0;
|
||||
}
|
71
taglib/dsf/dsfproperties.h
Normal file
71
taglib/dsf/dsfproperties.h
Normal file
@ -0,0 +1,71 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2013-2023 Stephen F. Booth
|
||||
email : me@sbooth.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_DSFPROPERTIES_H
|
||||
#define TAGLIB_DSFPROPERTIES_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "taglib_export.h"
|
||||
#include "tbytevector.h"
|
||||
#include "audioproperties.h"
|
||||
|
||||
namespace TagLib {
|
||||
namespace DSF {
|
||||
class TAGLIB_EXPORT Properties : public AudioProperties {
|
||||
public:
|
||||
Properties(const ByteVector &data, ReadStyle style);
|
||||
~Properties() override;
|
||||
|
||||
Properties(const Properties &) = delete;
|
||||
Properties &operator=(const Properties &) = delete;
|
||||
|
||||
int lengthInMilliseconds() const override;
|
||||
int bitrate() const override;
|
||||
int sampleRate() const override;
|
||||
int channels() const override;
|
||||
|
||||
int formatVersion() const;
|
||||
int formatID() const;
|
||||
|
||||
/*!
|
||||
* Channel type values: 1 = mono, 2 = stereo, 3 = 3 channels,
|
||||
* 4 = quad, 5 = 4 channels, 6 = 5 channels, 7 = 5.1 channels
|
||||
*/
|
||||
int channelType() const;
|
||||
int bitsPerSample() const;
|
||||
long long sampleCount() const;
|
||||
int blockSizePerChannel() const;
|
||||
|
||||
private:
|
||||
void read(const ByteVector &data);
|
||||
|
||||
class PropertiesPrivate;
|
||||
std::unique_ptr<PropertiesPrivate> d;
|
||||
};
|
||||
} // namespace DSF
|
||||
} // namespace TagLib
|
||||
|
||||
#endif
|
@ -52,6 +52,7 @@
|
||||
#include "wavfile.h"
|
||||
#include "wavpackfile.h"
|
||||
#include "xmfile.h"
|
||||
#include "dsffile.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
@ -164,6 +165,8 @@ namespace
|
||||
file = new IT::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(ext == "XM")
|
||||
file = new XM::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(ext == "DSF")
|
||||
file = new DSF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
|
||||
// if file is not valid, leave it to content-based detection.
|
||||
|
||||
@ -211,6 +214,8 @@ namespace
|
||||
file = new RIFF::WAV::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(APE::File::isSupported(stream))
|
||||
file = new APE::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(DSF::File::isSupported(stream))
|
||||
file = new DSF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
|
||||
// isSupported() only does a quick check, so double check the file here.
|
||||
|
||||
@ -290,6 +295,8 @@ namespace
|
||||
return new IT::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "XM")
|
||||
return new XM::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "DSF")
|
||||
return new DSF::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@ -417,6 +424,7 @@ StringList FileRef::defaultFileExtensions()
|
||||
l.append("s3m");
|
||||
l.append("it");
|
||||
l.append("xm");
|
||||
l.append("dsf");
|
||||
|
||||
return l;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ INCLUDE_DIRECTORIES(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/s3m
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/it
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/xm
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/dsf
|
||||
)
|
||||
|
||||
SET(test_runner_SRCS
|
||||
@ -66,6 +67,7 @@ SET(test_runner_SRCS
|
||||
test_mpc.cpp
|
||||
test_opus.cpp
|
||||
test_speex.cpp
|
||||
test_dsf.cpp
|
||||
test_sizes.cpp
|
||||
)
|
||||
|
||||
|
BIN
tests/data/empty10ms.dsf
Normal file
BIN
tests/data/empty10ms.dsf
Normal file
Binary file not shown.
57
tests/test_dsf.cpp
Normal file
57
tests/test_dsf.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
#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;
|
||||
using namespace TagLib;
|
||||
|
||||
class TestDSF : public CppUnit::TestFixture
|
||||
{
|
||||
CPPUNIT_TEST_SUITE(TestDSF);
|
||||
CPPUNIT_TEST(testBasic);
|
||||
CPPUNIT_TEST(testTags);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
|
||||
void testBasic()
|
||||
{
|
||||
DSF::File f(TEST_FILE_PATH_C("empty10ms.dsf"));
|
||||
CPPUNIT_ASSERT(f.audioProperties());
|
||||
CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->length());
|
||||
CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->lengthInSeconds());
|
||||
CPPUNIT_ASSERT_EQUAL(10, f.audioProperties()->lengthInMilliseconds());
|
||||
CPPUNIT_ASSERT_EQUAL(5645, f.audioProperties()->bitrate());
|
||||
CPPUNIT_ASSERT_EQUAL(2, 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(2, f.audioProperties()->channelType());
|
||||
CPPUNIT_ASSERT_EQUAL(1, f.audioProperties()->bitsPerSample());
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<long long>(28224), f.audioProperties()->sampleCount());
|
||||
CPPUNIT_ASSERT_EQUAL(4096, f.audioProperties()->blockSizePerChannel());
|
||||
}
|
||||
|
||||
void testTags()
|
||||
{
|
||||
ScopedFileCopy copy("empty10ms", ".dsf");
|
||||
string newname = copy.fileName();
|
||||
|
||||
DSF::File *f = new DSF::File(newname.c_str());
|
||||
CPPUNIT_ASSERT_EQUAL(String(""), f->tag()->artist());
|
||||
f->tag()->setArtist("The Artist");
|
||||
f->save();
|
||||
delete f;
|
||||
|
||||
f = new DSF::File(newname.c_str());
|
||||
CPPUNIT_ASSERT_EQUAL(String("The Artist"), f->tag()->artist());
|
||||
delete f;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(TestDSF);
|
@ -45,6 +45,7 @@
|
||||
#include "wavpackfile.h"
|
||||
#include "opusfile.h"
|
||||
#include "xmfile.h"
|
||||
#include "dsffile.h"
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include "utils.h"
|
||||
|
||||
@ -99,6 +100,7 @@ class TestFileRef : public CppUnit::TestFixture
|
||||
CPPUNIT_TEST(testAIFF_2);
|
||||
CPPUNIT_TEST(testWavPack);
|
||||
CPPUNIT_TEST(testOpus);
|
||||
CPPUNIT_TEST(testDSF);
|
||||
CPPUNIT_TEST(testUnsupported);
|
||||
CPPUNIT_TEST(testCreate);
|
||||
CPPUNIT_TEST(testAudioProperties);
|
||||
@ -331,6 +333,11 @@ public:
|
||||
fileRefSave<Ogg::Opus::File>("correctness_gain_silent_output", ".opus");
|
||||
}
|
||||
|
||||
void testDSF()
|
||||
{
|
||||
fileRefSave<DSF::File>("empty10ms",".dsf");
|
||||
}
|
||||
|
||||
void testUnsupported()
|
||||
{
|
||||
FileRef f1(TEST_FILE_PATH_C("no-extension"));
|
||||
@ -386,6 +393,7 @@ public:
|
||||
CPPUNIT_ASSERT(extensions.contains("wv"));
|
||||
CPPUNIT_ASSERT(extensions.contains("opus"));
|
||||
CPPUNIT_ASSERT(extensions.contains("xm"));
|
||||
CPPUNIT_ASSERT(extensions.contains("dsf"));
|
||||
}
|
||||
|
||||
void testFileResolver()
|
||||
|
@ -41,6 +41,8 @@
|
||||
#include "audioproperties.h"
|
||||
#include "chapterframe.h"
|
||||
#include "commentsframe.h"
|
||||
#include "dsffile.h"
|
||||
#include "dsfproperties.h"
|
||||
#include "eventtimingcodesframe.h"
|
||||
#include "fileref.h"
|
||||
#include "flacfile.h"
|
||||
@ -159,6 +161,8 @@ public:
|
||||
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::ByteVectorStream));
|
||||
CPPUNIT_ASSERT_EQUAL(classSize(0, true), sizeof(TagLib::DebugListener));
|
||||
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::FLAC::File));
|
||||
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::DSF::File));
|
||||
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::DSF::Properties));
|
||||
CPPUNIT_ASSERT_EQUAL(classSize(0, true), sizeof(TagLib::FLAC::MetadataBlock));
|
||||
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::FLAC::Picture));
|
||||
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::FLAC::Properties));
|
||||
|
Loading…
Reference in New Issue
Block a user