diff options
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/soundlib/ITTools.h')
-rw-r--r-- | Src/external_dependencies/openmpt-trunk/soundlib/ITTools.h | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/soundlib/ITTools.h b/Src/external_dependencies/openmpt-trunk/soundlib/ITTools.h new file mode 100644 index 00000000..4176df70 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/soundlib/ITTools.h @@ -0,0 +1,323 @@ +/* + * 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_BEGIN + +struct 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 Format +struct 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 Extension +struct 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 Format +struct 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 history +struct 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.html +template<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 |