| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 | /* * ITTools.h * --------- * Purpose: Definition of IT file structures and helper functions * Notes  : (currently none) * Authors: OpenMPT Devs * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. */#pragma once#include "openmpt/all/BuildSettings.hpp"#include "../soundlib/ModInstrument.h"#include "../soundlib/ModSample.h"#include "../soundlib/SampleIO.h"OPENMPT_NAMESPACE_BEGINstruct ITFileHeader{	// Header Flags	enum ITHeaderFlags	{		useStereoPlayback		= 0x01,		vol0Optimisations		= 0x02,		instrumentMode			= 0x04,		linearSlides			= 0x08,		itOldEffects			= 0x10,		itCompatGxx				= 0x20,		useMIDIPitchController	= 0x40,		reqEmbeddedMIDIConfig	= 0x80,		extendedFilterRange		= 0x1000,	};	// Special Flags	enum ITHeaderSpecialFlags	{		embedSongMessage		= 0x01,		embedEditHistory		= 0x02,		embedPatternHighlights	= 0x04,		embedMIDIConfiguration	= 0x08,	};	char     id[4];				// Magic Bytes (IMPM)	char     songname[26];		// Song Name, null-terminated (but may also contain nulls)	uint8le  highlight_minor;	// Rows per Beat highlight	uint8le  highlight_major;	// Rows per Measure highlight	uint16le ordnum;			// Number of Orders	uint16le insnum;			// Number of Instruments	uint16le smpnum;			// Number of Samples	uint16le patnum;			// Number of Patterns	uint16le cwtv;				// "Made With" Tracker	uint16le cmwt;				// "Compatible With" Tracker	uint16le flags;				// Header Flags	uint16le special;			// Special Flags, for embedding extra information	uint8le  globalvol;			// Global Volume (0...128)	uint8le  mv;				// Master Volume (0...128), referred to as Sample Volume in OpenMPT	uint8le  speed;				// Initial Speed (1...255)	uint8le  tempo;				// Initial Tempo (31...255)	uint8le  sep;				// Pan Separation (0...128)	uint8le  pwd;				// Pitch Wheel Depth	uint16le msglength;			// Length of Song Message	uint32le msgoffset;			// Offset of Song Message in File (IT crops message after first null)	uint32le reserved;			// Some IT versions save an edit timer here. ChibiTracker writes "CHBI" here. OpenMPT and Schism Tracker save extended version information here.	uint8le  chnpan[64];		// Initial Channel Panning	uint8le  chnvol[64];		// Initial Channel Volume};MPT_BINARY_STRUCT(ITFileHeader, 192)struct ITEnvelope{	// Envelope Flags	enum ITEnvelopeFlags	{		envEnabled	= 0x01,		envLoop		= 0x02,		envSustain	= 0x04,		envCarry	= 0x08,		envFilter	= 0x80,	};	struct Node	{		int8le   value;		uint16le tick;	};	uint8 flags;	// Envelope Flags	uint8 num;		// Number of Envelope Nodes	uint8 lpb;		// Loop Start	uint8 lpe;		// Loop End	uint8 slb;		// Sustain Start	uint8 sle;		// Sustain End	Node  data[25];	// Envelope Node Positions / Values	uint8 reserved;	// Reserved	// Convert OpenMPT's internal envelope format to an IT/MPTM envelope.	void ConvertToIT(const InstrumentEnvelope &mptEnv, uint8 envOffset, uint8 envDefault);	// Convert IT/MPTM envelope data into OpenMPT's internal envelope format - To be used by ITInstrToMPT()	void ConvertToMPT(InstrumentEnvelope &mptEnv, uint8 envOffset, uint8 maxNodes) const;};MPT_BINARY_STRUCT(ITEnvelope::Node, 3)MPT_BINARY_STRUCT(ITEnvelope, 82)// Old Impulse Instrument Format (cmwt < 0x200)struct ITOldInstrument{	enum ITOldInstrFlags	{		envEnabled	= 0x01,		envLoop		= 0x02,		envSustain	= 0x04,	};	char     id[4];			// Magic Bytes (IMPI)	char     filename[13];	// DOS Filename, null-terminated	uint8le  flags;			// Volume Envelope Flags	uint8le  vls;			// Envelope Loop Start	uint8le  vle;			// Envelope Loop End	uint8le  sls;			// Envelope Sustain Start	uint8le  sle;			// Envelope Sustain End	char     reserved1[2];	// Reserved	uint16le fadeout;		// Instrument Fadeout (0...128)	uint8le  nna;			// New Note Action	uint8le  dnc;			// Duplicate Note Check Type	uint16le trkvers;		// Tracker ID	uint8le  nos;			// Number of embedded samples	char     reserved2;		// Reserved	char     name[26];		// Instrument Name, null-terminated (but may also contain nulls)	char     reserved3[6];	// Even more reserved bytes	uint8le  keyboard[240];	// Sample / Transpose map	uint8le  volenv[200];	// This appears to be a pre-computed (interpolated) version of the volume envelope data found below.	uint8le  nodes[25 * 2];	// Volume Envelope Node Positions / Values	// Convert an ITOldInstrument to OpenMPT's internal instrument representation.	void ConvertToMPT(ModInstrument &mptIns) const;};MPT_BINARY_STRUCT(ITOldInstrument, 554)// Impulse Instrument Formatstruct ITInstrument{	enum ITInstrumentFlags	{		ignorePanning	= 0x80,		enableCutoff	= 0x80,		enableResonance	= 0x80,	};	char     id[4];			// Magic Bytes (IMPI)	char     filename[13];	// DOS Filename, null-terminated	uint8le  nna;			// New Note Action	uint8le  dct;			// Duplicate Note Check Type	uint8le  dca;			// Duplicate Note Check Action	uint16le fadeout;		// Instrument Fadeout (0...256, although values up to 1024 would be sensible. Up to IT2.07, the limit was 0...128)	int8le   pps;			// Pitch/Pan Separatation	uint8le  ppc;			// Pitch/Pan Centre	uint8le  gbv;			// Global Volume	uint8le  dfp;			// Panning	uint8le  rv;			// Vol Swing	uint8le  rp;			// Pan Swing	uint16le trkvers;		// Tracker ID	uint8le  nos;			// Number of embedded samples	char     reserved1;		// Reserved	char     name[26];		// Instrument Name, null-terminated (but may also contain nulls)	uint8le  ifc;			// Filter Cutoff	uint8le  ifr;			// Filter Resonance	uint8le  mch;			// MIDI Channel	uint8le  mpr;			// MIDI Program	uint8le  mbank[2];		// MIDI Bank	uint8le  keyboard[240];	// Sample / Transpose map	ITEnvelope volenv;		// Volume Envelope	ITEnvelope panenv;		// Pan Envelope	ITEnvelope pitchenv;	// Pitch / Filter Envelope	char       dummy[4];	// IT saves some additional padding bytes to match the size of the old instrument format for simplified loading. We use them for some hacks.	// Convert OpenMPT's internal instrument representation to an ITInstrument. Returns amount of bytes that need to be written.	uint32 ConvertToIT(const ModInstrument &mptIns, bool compatExport, const CSoundFile &sndFile);	// Convert an ITInstrument to OpenMPT's internal instrument representation. Returns size of the instrument data that has been read.	uint32 ConvertToMPT(ModInstrument &mptIns, MODTYPE fromType) const;};MPT_BINARY_STRUCT(ITInstrument, 554)// MPT IT Instrument Extensionstruct ITInstrumentEx{	ITInstrument iti;		// Normal IT Instrument	uint8 keyboardhi[120];	// High Byte of Sample map		// Convert OpenMPT's internal instrument representation to an ITInstrumentEx. Returns amount of bytes that need to be written.	uint32 ConvertToIT(const ModInstrument &mptIns, bool compatExport, const CSoundFile &sndFile);	// Convert an ITInstrumentEx to OpenMPT's internal instrument representation. Returns size of the instrument data that has been read.	uint32 ConvertToMPT(ModInstrument &mptIns, MODTYPE fromType) const;};MPT_BINARY_STRUCT(ITInstrumentEx, sizeof(ITInstrument) + 120)// IT Sample Formatstruct ITSample{	// Magic Bytes	enum Magic	{		magic = 0x53504D49,	// "IMPS" IT Sample Header Magic Bytes	};	enum ITSampleFlags	{		sampleDataPresent	= 0x01,		sample16Bit			= 0x02,		sampleStereo		= 0x04,		sampleCompressed	= 0x08,		sampleLoop			= 0x10,		sampleSustain		= 0x20,		sampleBidiLoop		= 0x40,		sampleBidiSustain	= 0x80,		enablePanning		= 0x80,		cvtSignedSample		= 0x01,		cvtOPLInstrument	= 0x40,		// FM instrument in MPTM		cvtExternalSample	= 0x80,		// Keep MPTM sample on disk		cvtADPCMSample		= 0xFF,		// MODPlugin :(		// ITTECH.TXT says these convert flags are "safe to ignore". IT doesn't ignore them, though, so why should we? :)		cvtBigEndian		= 0x02,		cvtDelta			= 0x04,		cvtPTM8to16			= 0x08,	};	char     id[4];			// Magic Bytes (IMPS)	char     filename[13];	// DOS Filename, null-terminated	uint8le  gvl;			// Global Volume	uint8le  flags;			// Sample Flags	uint8le  vol;			// Default Volume	char     name[26];		// Sample Name, null-terminated (but may also contain nulls)	uint8le  cvt;			// Sample Import Format	uint8le  dfp;			// Sample Panning	uint32le length;		// Sample Length (in samples)	uint32le loopbegin;		// Sample Loop Begin (in samples)	uint32le loopend;		// Sample Loop End (in samples)	uint32le C5Speed;		// C-5 frequency	uint32le susloopbegin;	// Sample Sustain Begin (in samples)	uint32le susloopend;	// Sample Sustain End (in samples)	uint32le samplepointer;	// Pointer to sample data	uint8le  vis;			// Auto-Vibrato Rate (called Sweep in IT)	uint8le  vid;			// Auto-Vibrato Depth	uint8le  vir;			// Auto-Vibrato Sweep (called Rate in IT)	uint8le  vit;			// Auto-Vibrato Type	// Convert OpenMPT's internal sample representation to an ITSample.	void ConvertToIT(const ModSample &mptSmp, MODTYPE fromType, bool compress, bool compressIT215, bool allowExternal);	// Convert an ITSample to OpenMPT's internal sample representation.	uint32 ConvertToMPT(ModSample &mptSmp) const;	// Retrieve the internal sample format flags for this instrument.	SampleIO GetSampleFormat(uint16 cwtv = 0x214) const;};MPT_BINARY_STRUCT(ITSample, 80)struct FileHistory;// IT Header extension: Save historystruct ITHistoryStruct{	uint16le fatdate;  // DOS / FAT date when the file was opened / created in the editor. For details, read https://docs.microsoft.com/de-de/windows/win32/api/winbase/nf-winbase-dosdatetimetofiletime	uint16le fattime;  // DOS / FAT time when the file was opened / created in the editor.	uint32le runtime;  // The time how long the file was open in the editor, in 1/18.2th seconds. (= ticks of the DOS timer)	// Convert an ITHistoryStruct to OpenMPT's internal edit history representation	void ConvertToMPT(FileHistory &mptHistory) const;	// Convert OpenMPT's internal edit history representation to an ITHistoryStruct	void ConvertToIT(const FileHistory &mptHistory);};MPT_BINARY_STRUCT(ITHistoryStruct, 8)enum IT_ReaderBitMasks{	// pattern row parsing, the channel data is read to obtain	// number of channels active in the pattern. These bit masks are	// to blank out sections of the byte of data being read.	IT_bitmask_patternChanField_c   = 0x7f,	IT_bitmask_patternChanMask_c    = 0x3f,	IT_bitmask_patternChanEnabled_c = 0x80,	IT_bitmask_patternChanUsed_c    = 0x0f};// Calculate Schism Tracker version field for IT / S3M header based on specified release date// Date calculation derived from https://alcor.concordia.ca/~gpkatch/gdate-algorithm.htmltemplate<int32 y, int32 m, int32 d>struct SchismVersionFromDate{private:	static constexpr int32 mm = (m + 9) % 12;	static constexpr int32 yy = y - mm / 10;public:	static constexpr int32 date = yy * 365 + yy / 4 - yy / 100 + yy / 400 + (mm * 306 + 5) / 10 + (d - 1);};inline constexpr int32 SchismTrackerEpoch = SchismVersionFromDate<2009, 10, 31>::date;uint32 DecodeITEditTimer(uint16 cwtv, uint32 editTime);OPENMPT_NAMESPACE_END
 |