riff/wav/wavfile.h
riff/wav/wavproperties.h
mod/modfilebase.h
+ mod/modfile.h
mod/modtag.h
+ mod/modproperties.h
it/itfile.h
it/itproperties.h
s3m/s3mfile.h
s3m/s3mproperties.h
xm/xmfile.h
xm/xmproperties.h
- xm/xmtag.h
)
if(WITH_ASF)
set(tag_HDRS ${tag_HDRS}
set(mod_SRCS
mod/modfilebase.cpp
+ mod/modfile.cpp
mod/modtag.cpp
+ mod/modproperties.cpp
)
set(s3m_SRCS
set(xm_SRCS
xm/xmfile.cpp
- xm/xmtag.cpp
xm/xmproperties.cpp
)
#include "aifffile.h"
#include "wavfile.h"
#include "apefile.h"
+#include "modfile.h"
#include "s3mfile.h"
#include "itfile.h"
#include "xmfile.h"
return new RIFF::WAV::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "APE")
return new APE::File(fileName, readAudioProperties, audioPropertiesStyle);
+ // module, nst and wow are possible but uncommon extensions
+ if(ext == "MOD" || ext == "MODULE" || ext == "NST" || ext == "WOW")
+ return new Mod::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "S3M")
return new S3M::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "IT")
for(ushort i = 0; i < instrumentCount; ++ i)
{
- seek(192 + length + (i << 2));
+ seek(192L + length + ((long)i << 2));
READ_U32L_AS(instrumentOffset);
seek(instrumentOffset);
for(ushort i = 0; i < sampleCount; ++ i)
{
- seek(192 + length + (instrumentCount << 2) + (i << 2));
+ seek(192L + length + ((long)instrumentCount << 2) + ((long)i << 2));
READ_U32L_AS(sampleOffset);
seek(sampleOffset);
}
d->tag.setComment(comment.toString("\n"));
+ d->tag.setTrackerName("Impulse Tracker");
}
#ifndef TAGLIB_ITFILE_H
#define TAGLIB_ITFILE_H
-#include <stdint.h>
-
#include "tfile.h"
#include "audioproperties.h"
#include "taglib_export.h"
--- /dev/null
+/***************************************************************************
+ copyright : (C) 2011 by Mathias Panzenböck
+ email : grosser.meister.morti@gmx.net
+ ***************************************************************************/
+
+/***************************************************************************
+ * 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 *
+ ***************************************************************************/
+
+#include "modfile.h"
+#include "tstringlist.h"
+#include "modfileprivate.h"
+
+using namespace TagLib;
+using namespace Mod;
+
+class Mod::File::FilePrivate
+{
+public:
+ FilePrivate(AudioProperties::ReadStyle propertiesStyle)
+ : properties(propertiesStyle)
+ {
+ }
+
+ Mod::Tag tag;
+ Mod::Properties properties;
+};
+
+Mod::File::File(FileName file, bool readProperties,
+ AudioProperties::ReadStyle propertiesStyle) :
+ Mod::FileBase(file),
+ d(new FilePrivate(propertiesStyle))
+{
+ read(readProperties);
+}
+
+Mod::File::File(IOStream *stream, bool readProperties,
+ AudioProperties::ReadStyle propertiesStyle) :
+ Mod::FileBase(stream),
+ d(new FilePrivate(propertiesStyle))
+{
+ read(readProperties);
+}
+
+Mod::File::~File()
+{
+ delete d;
+}
+
+Mod::Tag *Mod::File::tag() const
+{
+ return &d->tag;
+}
+
+Mod::Properties *Mod::File::audioProperties() const
+{
+ return &d->properties;
+}
+
+bool Mod::File::save()
+{
+ // note: if title starts with "Extended Module: "
+ // the file would look like an .xm file
+ seek(0);
+ writeString(d->tag.title(), 20, ' ');
+ // TODO: write comment as sample names
+ return true;
+}
+
+void Mod::File::read(bool)
+{
+ if(!isOpen())
+ return;
+
+ seek(1080);
+ ByteVector modId = readBlock(4);
+ READ_ASSERT(modId.size() == 4);
+
+ int channels = 4;
+ int instruments = 31;
+ if(modId == "M.K." || modId == "M!K!" || modId == "M&K!" || modId == "N.T.")
+ {
+ d->tag.setTrackerName("ProTracker");
+ channels = 4;
+ }
+ else if(modId.startsWith("FLT") || modId.startsWith("TDZ"))
+ {
+ d->tag.setTrackerName("StarTrekker");
+ char digit = modId[3];
+ READ_ASSERT(digit >= '0' && digit <= '9');
+ channels = digit - '0';
+ }
+ else if(modId.endsWith("CHN"))
+ {
+ d->tag.setTrackerName("StarTrekker");
+ char digit = modId[0];
+ READ_ASSERT(digit >= '0' && digit <= '9');
+ channels = digit - '0';
+ }
+ else if(modId == "CD81" || modId == "OKTA")
+ {
+ d->tag.setTrackerName("Atari Oktalyzer");
+ channels = 8;
+ }
+ else if(modId.endsWith("CH") || modId.endsWith("CN"))
+ {
+ d->tag.setTrackerName("TakeTracker");
+ char digit = modId[0];
+ READ_ASSERT(digit >= '0' && digit <= '9');
+ channels = (digit - '0') * 10;
+ digit = modId[1];
+ READ_ASSERT(digit >= '0' && digit <= '9');
+ channels += digit - '0';
+ }
+ else
+ {
+ d->tag.setTrackerName("NoiseTracker"); // probably
+ channels = 4;
+ instruments = 15;
+ }
+ d->properties.setChannels(channels);
+ d->properties.setInstrumentCount(instruments);
+
+ seek(0);
+ READ_STRING(d->tag.setTitle, 20);
+
+ StringList comment;
+ for(int i = 0; i < instruments; ++ i)
+ {
+ READ_STRING_AS(instrumentName, 22);
+ READ_U16B_AS(instrumentLength);
+
+ READ_BYTE_AS(fineTuneByte);
+ int fineTune = fineTuneByte & 0xF;
+ // > 7 means nagative value
+ if(fineTune > 7) fineTune -= 16;
+
+ READ_BYTE_AS(volume);
+ if(volume > 64) volume = 64;
+
+ READ_U16B_AS(repeatStart);
+ // (int)repatStart << 1;
+ READ_U16B_AS(repatLength);
+ // (int)repatLength << 1;
+
+ comment.append(instrumentName);
+ }
+
+ READ_BYTE(d->properties.setPatternCount);
+
+ d->tag.setComment(comment.toString("\n"));
+}
--- /dev/null
+/***************************************************************************
+ copyright : (C) 2011 by Mathias Panzenböck
+ email : grosser.meister.morti@gmx.net
+ ***************************************************************************/
+
+/***************************************************************************
+ * 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 *
+ ***************************************************************************/
+
+#ifndef TAGLIB_MODFILE_H
+#define TAGLIB_MODFILE_H
+
+#include "tfile.h"
+#include "audioproperties.h"
+#include "taglib_export.h"
+#include "modfilebase.h"
+#include "modtag.h"
+#include "modproperties.h"
+
+namespace TagLib {
+
+ namespace Mod {
+
+ class TAGLIB_EXPORT File : public TagLib::Mod::FileBase {
+ public:
+ /*!
+ * Contructs a Protracker 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,
+ AudioProperties::ReadStyle propertiesStyle =
+ AudioProperties::Average);
+
+ /*!
+ * Contructs a Protracker file from \a stream. If \a readProperties
+ * is true the file's audio properties will also be read using
+ * \a propertiesStyle. If false, \a propertiesStyle is ignored.
+ */
+ File(IOStream *stream, bool readProperties = true,
+ AudioProperties::ReadStyle propertiesStyle =
+ AudioProperties::Average);
+
+ /*!
+ * Destroys this instance of the File.
+ */
+ virtual ~File();
+
+ Mod::Tag *tag() const;
+
+ /*!
+ * Returns the Mod::Properties for this file. If no audio properties
+ * were read then this will return a null pointer.
+ */
+ Mod::Properties *audioProperties() const;
+
+ /*!
+ * Save the file.
+ * This is the same as calling save(AllTags);
+ *
+ * \note Saving Protracker tags is not supported.
+ */
+ bool save();
+
+ private:
+ File(const File &);
+ File &operator=(const File &);
+
+ void read(bool readProperties);
+
+ class FilePrivate;
+ FilePrivate *d;
+ };
+ }
+}
+
+#endif
{
}
-void Mod::FileBase::writeString(const String &s, ulong size)
+void Mod::FileBase::writeString(const String &s, ulong size, char padding)
{
ByteVector data(s.data(String::Latin1));
- data.resize(size, 0);
+ data.resize(size, padding);
writeBlock(data);
}
number = data.toUInt(false);
return true;
}
+
+bool Mod::FileBase::readU16B(ushort &number)
+{
+ ByteVector data(readBlock(2));
+ if(data.size() < 2) return false;
+ number = data.toUShort(true);
+ return true;
+}
+
+bool Mod::FileBase::readU32B(ulong &number) {
+ ByteVector data(readBlock(4));
+ if(data.size() < 4) return false;
+ number = data.toUInt(true);
+ return true;
+}
* MA 02110-1301 USA *
***************************************************************************/
-#ifndef TAGLIB_MODFILE_H
-#define TAGLIB_MODFILE_H
+#ifndef TAGLIB_MODFILEBASE_H
+#define TAGLIB_MODFILEBASE_H
#include "taglib.h"
#include "tfile.h"
FileBase(FileName file);
FileBase(IOStream *stream);
- void writeString(const String &s, ulong size);
+ void writeString(const String &s, ulong size, char padding = 0);
bool readString(String &s, ulong size);
bool readByte(uchar &byte);
bool readU16L(ushort &number);
bool readU32L(ulong &number);
+ bool readU16B(ushort &number);
+ bool readU32B(ulong &number);
};
}
}
#define READ_BYTE(setter) READ(setter,uchar,readByte)
#define READ_U16L(setter) READ(setter,ushort,readU16L)
#define READ_U32L(setter) READ(setter,ulong,readU32L)
+#define READ_U16B(setter) READ(setter,ushort,readU16B)
+#define READ_U32B(setter) READ(setter,ulong,readU32B)
#define READ_STRING(setter,size) \
{ \
#define READ_BYTE_AS(name) READ_AS(uchar,name,readByte)
#define READ_U16L_AS(name) READ_AS(ushort,name,readU16L)
#define READ_U32L_AS(name) READ_AS(ulong,name,readU32L)
+#define READ_U16B_AS(name) READ_AS(ushort,name,readU16B)
+#define READ_U32B_AS(name) READ_AS(ulong,name,readU32B)
#define READ_STRING_AS(name,size) \
String name; \
* MA 02110-1301 USA *
***************************************************************************/
-#include "xmtag.h"
+#include "modproperties.h"
using namespace TagLib;
-using namespace XM;
+using namespace Mod;
-class XM::Tag::TagPrivate
+class Mod::Properties::PropertiesPrivate
{
public:
- TagPrivate() {}
-
- String title;
- String comment;
- String trackerName;
+ PropertiesPrivate() :
+ channels(0),
+ instrumentCount(0),
+ patternCount(0)
+ {
+ }
+
+ int channels;
+ uint instrumentCount;
+ uint patternCount;
};
-XM::Tag::Tag() : TagLib::Tag()
+Mod::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) :
+ AudioProperties(propertiesStyle),
+ d(new PropertiesPrivate)
{
- d = new TagPrivate;
}
-XM::Tag::~Tag()
+Mod::Properties::~Properties()
{
delete d;
}
-String XM::Tag::title() const
-{
- return d->title;
-}
-
-String XM::Tag::artist() const
-{
- return String::null;
-}
-
-String XM::Tag::album() const
-{
- return String::null;
-}
-
-String XM::Tag::comment() const
-{
- return d->comment;
-}
-
-String XM::Tag::genre() const
-{
- return String::null;
-}
-
-uint XM::Tag::year() const
+int Mod::Properties::length() const
{
return 0;
}
-uint XM::Tag::track() const
+int Mod::Properties::bitrate() const
{
return 0;
}
-String XM::Tag::trackerName() const
-{
- return d->trackerName;
-}
-
-void XM::Tag::setTitle(const String &title)
-{
- d->title = title;
-}
-
-void XM::Tag::setArtist(const String &)
+int Mod::Properties::sampleRate() const
{
+ return 0;
}
-void XM::Tag::setAlbum(const String &)
+int Mod::Properties::channels() const
{
+ return d->channels;
}
-void XM::Tag::setComment(const String &comment)
+uint Mod::Properties::instrumentCount() const
{
- d->comment = comment;
+ return d->instrumentCount;
}
-void XM::Tag::setGenre(const String &)
+uint Mod::Properties::patternCount() const
{
+ return d->patternCount;
}
-void XM::Tag::setYear(uint)
+void Mod::Properties::setChannels(int channels)
{
+ d->channels = channels;
}
-void XM::Tag::setTrack(uint)
+void Mod::Properties::setInstrumentCount(uint instrumentCount)
{
+ d->instrumentCount = instrumentCount;
}
-void XM::Tag::setTrackerName(const String &trackerName)
+void Mod::Properties::setPatternCount(uint patternCount)
{
- d->trackerName = trackerName;
+ d->patternCount = patternCount;
}
* MA 02110-1301 USA *
***************************************************************************/
-#ifndef TAGLIB_XMTAG_H
-#define TAGLIB_XMTAG_H
+#ifndef TAGLIB_MODPROPERTIES_H
+#define TAGLIB_MODPROPERTIES_H
-#include "modtag.h"
+#include "taglib.h"
+#include "audioproperties.h"
namespace TagLib {
- namespace XM {
- class Tag : public TagLib::Tag {
- public:
- Tag();
- virtual ~Tag();
-
- String title() const;
- String artist() const;
- String album() const;
- String comment() const;
- String genre() const;
- uint year() const;
- uint track() const;
- String trackerName() const;
-
- void setTitle (const String &title);
- void setArtist (const String &artist);
- void setAlbum (const String &album);
- void setComment(const String &comment);
- void setGenre (const String &genre);
- void setYear (uint year);
- void setTrack(uint track);
- void setTrackerName(const String &trackerName);
-
- private:
- Tag(const Tag &);
- Tag &operator=(const Tag &);
-
- class TagPrivate;
- TagPrivate *d;
+ namespace Mod {
+ class TAGLIB_EXPORT Properties : public AudioProperties {
+ friend class File;
+ public:
+ Properties(AudioProperties::ReadStyle propertiesStyle);
+ virtual ~Properties();
+
+ int length() const;
+ int bitrate() const;
+ int sampleRate() const;
+ int channels() const;
+
+ uint instrumentCount() const;
+ uint patternCount() const;
+
+ protected:
+ void setChannels(int channels);
+
+ void setInstrumentCount(uint sampleCount);
+ void setPatternCount(uint patternCount);
+
+ private:
+ Properties(const Properties&);
+ Properties &operator=(const Properties&);
+
+ class PropertiesPrivate;
+ PropertiesPrivate *d;
};
}
}
String title;
String comment;
+ String trackerName;
};
Mod::Tag::Tag() : TagLib::Tag()
return 0;
}
+String Mod::Tag::trackerName() const
+{
+ return d->trackerName;
+}
+
void Mod::Tag::setTitle(const String &title)
{
d->title = title;
void Mod::Tag::setTrack(uint)
{
}
+
+void Mod::Tag::setTrackerName(const String &trackerName)
+{
+ d->trackerName = trackerName;
+}
String genre() const;
uint year() const;
uint track() const;
+ String trackerName() const;
void setTitle (const String &title);
void setArtist (const String &artist);
void setGenre (const String &genre);
void setYear (uint year);
void setTrack(uint track);
+ void setTrackerName(const String &trackerName);
private:
Tag(const Tag &);
READ_ASSERT(readBlock(4) == "SCRM");
READ_BYTE_AS(baseVolume);
- d->properties.setBaseVolume(baseVolume << 1);
+ d->properties.setBaseVolume((int)baseVolume << 1);
READ_BYTE(d->properties.setTempo);
READ_BYTE(d->properties.setBpmSpeed);
StringList comment;
for(ushort i = 0; i < sampleCount; ++ i)
{
- seek(96 + length + (i << 1));
+ seek(96L + length + ((long)i << 1));
READ_U16L_AS(instrumentOffset);
- seek(instrumentOffset << 4);
+ seek((long)instrumentOffset << 4);
READ_BYTE_AS(sampleType);
READ_STRING_AS(dosFileName, 13);
}
d->tag.setComment(comment.toString("\n"));
+ d->tag.setTrackerName("ScreamTracker III");
}
#ifndef TAGLIB_S3MFILE_H
#define TAGLIB_S3MFILE_H
-#include <stdint.h>
-
#include "tfile.h"
#include "audioproperties.h"
#include "taglib_export.h"
{
}
- XM::Tag tag;
+ Mod::Tag tag;
XM::Properties properties;
};
delete d;
}
-XM::Tag *XM::File::tag() const
+Mod::Tag *XM::File::tag() const
{
return &d->tag;
}
if(instrumentSize > 4)
{
- if(!readString(instrumentName, std::min(22UL, instrumentSize-4)))
- {
- setValid(false);
- return;
- }
+ READ_ASSERT(readString(instrumentName, std::min(22UL, instrumentSize-4)));
if(instrumentSize >= (4+22+1))
{
- if(!readByte(instrumentType))
- {
- setValid(false);
- return;
- }
+ READ_ASSERT(readByte(instrumentType));
if(instrumentSize >= (4+22+1+2))
{
- if(!readU16L(sampleCount))
- {
- setValid(false);
- return;
- }
+ READ_ASSERT(readU16L(sampleCount));
}
}
}
#ifndef TAGLIB_XMFILE_H
#define TAGLIB_XMFILE_H
-#include <stdint.h>
-
#include "tfile.h"
#include "audioproperties.h"
#include "taglib_export.h"
#include "modfilebase.h"
-#include "xmtag.h"
+#include "modtag.h"
#include "xmproperties.h"
namespace TagLib {
*/
virtual ~File();
- XM::Tag *tag() const;
+ Mod::Tag *tag() const;
/*!
* Returns the XM::Properties for this file. If no audio properties