diff --git a/bindings/c/CMakeLists.txt b/bindings/c/CMakeLists.txt index 1e8907c0..15c33487 100644 --- a/bindings/c/CMakeLists.txt +++ b/bindings/c/CMakeLists.txt @@ -8,6 +8,7 @@ INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/../../taglib ${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mpc ${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mpeg/id3v2 ${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/wavpack + ${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/speex ) diff --git a/bindings/c/Makefile.am b/bindings/c/Makefile.am index 47debc85..5416d824 100644 --- a/bindings/c/Makefile.am +++ b/bindings/c/Makefile.am @@ -9,6 +9,7 @@ INCLUDES = \ -I$(top_srcdir)/taglib/mpc \ -I$(top_srcdir)/taglib/mpeg/id3v2 \ -I$(top_srcdir)/taglib/wavpack \ + -I$(top_srcdir)/taglib/speex \ $(all_includes) lib_LTLIBRARIES = libtag_c.la diff --git a/bindings/c/tag_c.cpp b/bindings/c/tag_c.cpp index 174efaf5..fcb2dc31 100644 --- a/bindings/c/tag_c.cpp +++ b/bindings/c/tag_c.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -74,6 +75,8 @@ TagLib_File *taglib_file_new_type(const char *filename, TagLib_File_Type type) return reinterpret_cast(new Ogg::FLAC::File(filename)); case TagLib_File_WavPack: return reinterpret_cast(new WavPack::File(filename)); + case TagLib_File_Speex: + return reinterpret_cast(new Speex::File(filename)); } return 0; diff --git a/bindings/c/tag_c.h b/bindings/c/tag_c.h index 01f9c615..54201710 100644 --- a/bindings/c/tag_c.h +++ b/bindings/c/tag_c.h @@ -87,7 +87,8 @@ typedef enum { TagLib_File_FLAC, TagLib_File_MPC, TagLib_File_OggFlac, - TagLib_File_WavPack + TagLib_File_WavPack, + TagLib_File_Speex } TagLib_File_Type; /*! diff --git a/taglib/CMakeLists.txt b/taglib/CMakeLists.txt index 5d89f945..559fb9f5 100644 --- a/taglib/CMakeLists.txt +++ b/taglib/CMakeLists.txt @@ -12,6 +12,7 @@ INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/mpeg/id3v1 ${CMAKE_CURRENT_SOURCE_DIR}/ape ${CMAKE_CURRENT_SOURCE_DIR}/wavpack + ${CMAKE_CURRENT_SOURCE_DIR}/speex ${CMAKE_CURRENT_BINARY_DIR}/taglib ${CMAKE_CURRENT_BINARY_DIR}/.. ) @@ -26,6 +27,7 @@ ADD_SUBDIRECTORY( flac ) ADD_SUBDIRECTORY( ape ) ADD_SUBDIRECTORY( mpc ) ADD_SUBDIRECTORY( wavpack ) +ADD_SUBDIRECTORY( speex ) @@ -103,6 +105,11 @@ wavpack/wavpackfile.cpp wavpack/wavpackproperties.cpp ) +SET(speex_SRCS +speex/speexfile.cpp +speex/speexproperties.cpp +) + SET(toolkit_SRCS toolkit/tstring.cpp toolkit/tstringlist.cpp @@ -115,7 +122,7 @@ toolkit/unicode.cpp SET(tag_LIB_SRCS ${mpeg_SRCS} ${id3v1_SRCS} ${id3v2_SRCS} ${frames_SRCS} ${ogg_SRCS} ${vorbis_SRCS} ${oggflacs_SRCS} ${mpc_SRCS} ${ape_SRCS} ${toolkit_SRCS} ${flacs_SRCS} - ${wavpack_SRCS} + ${wavpack_SRCS} ${speex_SRCS} tag.cpp fileref.cpp audioproperties.cpp diff --git a/taglib/Makefile.am b/taglib/Makefile.am index 48d552a4..6a2e700e 100644 --- a/taglib/Makefile.am +++ b/taglib/Makefile.am @@ -10,6 +10,7 @@ INCLUDES = \ -I$(top_srcdir)/taglib/mpc \ -I$(top_srcdir)/taglib/ogg/vorbis \ -I$(top_srcdir)/taglib/wavpack \ + -I$(top_srcdir)/taglib/speex \ $(all_includes) lib_LTLIBRARIES = libtag.la @@ -19,4 +20,5 @@ taglib_include_HEADERS = tag.h fileref.h audioproperties.h taglib_export.h taglib_includedir = $(includedir)/taglib libtag_la_LDFLAGS = $(all_libraries) -no-undefined -version-info 5:0:4 -libtag_la_LIBADD = ./mpeg/libmpeg.la ./ogg/libogg.la ./flac/libflac.la ./mpc/libmpc.la ./ape/libape.la ./toolkit/libtoolkit.la ./wavpack/libwavpack.la +libtag_la_LIBADD = ./mpeg/libmpeg.la ./ogg/libogg.la ./flac/libflac.la ./mpc/libmpc.la \ + ./ape/libape.la ./toolkit/libtoolkit.la ./wavpack/libwavpack.la ./speex/libspeex.la diff --git a/taglib/fileref.cpp b/taglib/fileref.cpp index d1fbe85c..a708d4ab 100644 --- a/taglib/fileref.cpp +++ b/taglib/fileref.cpp @@ -33,6 +33,7 @@ #include "oggflacfile.h" #include "mpcfile.h" #include "wavpackfile.h" +#include "speexfile.h" using namespace TagLib; @@ -117,6 +118,7 @@ StringList FileRef::defaultFileExtensions() l.append("mp3"); l.append("mpc"); l.append("wv"); + l.append("spx"); return l; } @@ -189,7 +191,9 @@ File *FileRef::create(FileName fileName, bool readAudioProperties, return new FLAC::File(fileName, readAudioProperties, audioPropertiesStyle); if(s.substr(s.size() - 4, 4).upper() == ".MPC") return new MPC::File(fileName, readAudioProperties, audioPropertiesStyle); - if(s.substr(s.size() - 4, 4).upper() == ".WV") + if(s.substr(s.size() - 3, 3).upper() == ".WV") + return new WavPack::File(fileName, readAudioProperties, audioPropertiesStyle); + if(s.substr(s.size() - 4, 4).upper() == ".SPX") return new WavPack::File(fileName, readAudioProperties, audioPropertiesStyle); } diff --git a/taglib/speex/CMakeLists.txt b/taglib/speex/CMakeLists.txt new file mode 100644 index 00000000..7f35b71f --- /dev/null +++ b/taglib/speex/CMakeLists.txt @@ -0,0 +1 @@ +INSTALL( FILES speexfile.h speexproperties.h DESTINATION ${INCLUDE_INSTALL_DIR}/taglib) diff --git a/taglib/speex/Makefile.am b/taglib/speex/Makefile.am new file mode 100644 index 00000000..da47fa8a --- /dev/null +++ b/taglib/speex/Makefile.am @@ -0,0 +1,11 @@ +INCLUDES = \ + -I$(top_srcdir)/taglib \ + -I$(top_srcdir)/taglib/ogg \ + $(all_includes) + +noinst_LTLIBRARIES = libspeex.la + +libspeex_la_SOURCES = speexfile.cpp speexproperties.cpp + +taglib_include_HEADERS = speexfile.h speexproperties.h +taglib_includedir = $(includedir)/taglib diff --git a/taglib/speex/speexfile.cpp b/taglib/speex/speexfile.cpp new file mode 100644 index 00000000..fe274dc7 --- /dev/null +++ b/taglib/speex/speexfile.cpp @@ -0,0 +1,111 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) + ***************************************************************************/ + +/*************************************************************************** + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * + * 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 + +#include +#include + +#include "speexfile.h" + +using namespace TagLib; + +class Speex::File::FilePrivate +{ +public: + FilePrivate() : + comment(0), + properties(0) {} + + ~FilePrivate() + { + delete comment; + delete properties; + } + + Ogg::XiphComment *comment; + Properties *properties; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Speex::File::File(FileName file, bool readProperties, + Properties::ReadStyle propertiesStyle) : Ogg::File(file) +{ + d = new FilePrivate; + read(readProperties, propertiesStyle); +} + +Speex::File::~File() +{ + delete d; +} + +Ogg::XiphComment *Speex::File::tag() const +{ + return d->comment; +} + +Speex::Properties *Speex::File::audioProperties() const +{ + return d->properties; +} + +bool Speex::File::save() +{ + if(!d->comment) + d->comment = new Ogg::XiphComment; + + setPacket(1, d->comment->render()); + + return Ogg::File::save(); +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Speex::File::read(bool readProperties, Properties::ReadStyle propertiesStyle) +{ + ByteVector speexHeaderData = packet(0); + + if(!speexHeaderData.startsWith("Speex ")) { + debug("Speex::File::read() -- invalid Speex identification header"); + return; + } + + ByteVector commentHeaderData = packet(1); + + d->comment = new Ogg::XiphComment(commentHeaderData); + + if(readProperties) + d->properties = new Properties(this, propertiesStyle); +} diff --git a/taglib/speex/speexfile.h b/taglib/speex/speexfile.h new file mode 100644 index 00000000..79b07953 --- /dev/null +++ b/taglib/speex/speexfile.h @@ -0,0 +1,97 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) + ***************************************************************************/ + +/*************************************************************************** + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * + * 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_SPEEXFILE_H +#define TAGLIB_SPEEXFILE_H + +#include +#include + +#include "speexproperties.h" + +namespace TagLib { + + //! A namespace containing classes for Speex metadata + + namespace Speex { + + //! An implementation of Ogg::File with Speex specific methods + + /*! + * This is the central class in the Ogg Speex metadata processing collection + * of classes. It's built upon Ogg::File which handles processing of the Ogg + * logical bitstream and breaking it down into pages which are handled by + * the codec implementations, in this case Speex specifically. + */ + + class TAGLIB_EXPORT File : public Ogg::File + { + public: + /*! + * Contructs a Speex file from \a file. If \a readProperties is true the + * file's audio properties will also be read using \a propertiesStyle. If + * false, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the XiphComment for this file. XiphComment implements the tag + * interface, so this serves as the reimplementation of + * TagLib::File::tag(). + */ + virtual Ogg::XiphComment *tag() const; + + /*! + * Returns the Speex::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + virtual bool save(); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + + class FilePrivate; + FilePrivate *d; + }; + } + +} + +#endif diff --git a/taglib/speex/speexproperties.cpp b/taglib/speex/speexproperties.cpp new file mode 100644 index 00000000..08d91cc1 --- /dev/null +++ b/taglib/speex/speexproperties.cpp @@ -0,0 +1,169 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) + ***************************************************************************/ + +/*************************************************************************** + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * + * 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 +#include + +#include + +#include "speexproperties.h" +#include "speexfile.h" + +using namespace TagLib; + +class Speex::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate(File *f, ReadStyle s) : + file(f), + style(s), + length(0), + bitrate(0), + sampleRate(0), + channels(0), + speexVersion(0), + vbr(false), + mode(0) {} + + File *file; + ReadStyle style; + int length; + int bitrate; + int sampleRate; + int channels; + int speexVersion; + bool vbr; + int mode; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Speex::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style) +{ + d = new PropertiesPrivate(file, style); + read(); +} + +Speex::Properties::~Properties() +{ + delete d; +} + +int Speex::Properties::length() const +{ + return d->length; +} + +int Speex::Properties::bitrate() const +{ + return int(float(d->bitrate) / float(1000) + 0.5); +} + +int Speex::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int Speex::Properties::channels() const +{ + return d->channels; +} + +int Speex::Properties::speexVersion() const +{ + return d->speexVersion; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Speex::Properties::read() +{ + // Get the identification header from the Ogg implementation. + + ByteVector data = d->file->packet(0); + + int pos = 28; + + // speex_version_id; /**< Version for Speex (for checking compatibility) */ + d->speexVersion = data.mid(pos, 4).toUInt(false); + pos += 4; + + // header_size; /**< Total size of the header ( sizeof(SpeexHeader) ) */ + pos += 4; + + // rate; /**< Sampling rate used */ + d->sampleRate = data.mid(pos, 4).toUInt(false); + pos += 4; + + // mode; /**< Mode used (0 for narrowband, 1 for wideband) */ + d->mode = data.mid(pos, 4).toUInt(false); + pos += 4; + + // mode_bitstream_version; /**< Version ID of the bit-stream */ + pos += 4; + + // nb_channels; /**< Number of channels encoded */ + d->channels = data.mid(pos, 4).toUInt(false); + pos += 4; + + // bitrate; /**< Bit-rate used */ + d->bitrate = data.mid(pos, 4).toUInt(false); + pos += 4; + + // frame_size; /**< Size of frames */ + //unsigned int frameSize = data.mid(pos, 4).toUInt(false); + pos += 4; + + // vbr; /**< 1 for a VBR encoding, 0 otherwise */ + d->vbr = data.mid(pos, 4).toUInt(false) == 1; + pos += 4; + + // frames_per_packet; /**< Number of frames stored per Ogg packet */ + //unsigned int framesPerPacket = data.mid(pos, 4).toUInt(false); + + const Ogg::PageHeader *first = d->file->firstPageHeader(); + const Ogg::PageHeader *last = d->file->lastPageHeader(); + + if(first && last) { + long long start = first->absoluteGranularPosition(); + long long end = last->absoluteGranularPosition(); + + if(start >= 0 && end >= 0 && d->sampleRate > 0) + d->length = (int) ((end - start) / (long long) d->sampleRate); + else + debug("Speex::Properties::read() -- Either the PCM values for the start or " + "end of this file was incorrect or the sample rate is zero."); + } + else + debug("Speex::Properties::read() -- Could not find valid first and last Ogg pages."); +} diff --git a/taglib/speex/speexproperties.h b/taglib/speex/speexproperties.h new file mode 100644 index 00000000..4bee52c4 --- /dev/null +++ b/taglib/speex/speexproperties.h @@ -0,0 +1,87 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) + ***************************************************************************/ + +/*************************************************************************** + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * + * 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_SPEEXPROPERTIES_H +#define TAGLIB_SPEEXPROPERTIES_H + +#include + +namespace TagLib { + + namespace Speex { + + class File; + + //! An implementation of audio property reading for Ogg Speex + + /*! + * This reads the data from an Ogg Speex stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of Vorbis::Properties with the data read from the + * Vorbis::File \a file. + */ + Properties(File *file, ReadStyle style = Average); + + /*! + * Destroys this VorbisProperties instance. + */ + virtual ~Properties(); + + // Reimplementations. + + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + + /*! + * Returns the Vorbis version, currently "0" (as specified by the spec). + */ + int speexVersion() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } + +} + +#endif