File: ITTools.h

package info (click to toggle)
libopenmpt 0.4.3-1%2Bdeb10u1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 7,724 kB
  • sloc: cpp: 99,820; sh: 4,503; ansic: 3,449; makefile: 480
file content (320 lines) | stat: -rw-r--r-- 10,945 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
/*
 * 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 "BuildSettings.h"

#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 writes "OMPT" here in some cases, see Load_it.cpp
	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 http://msdn.microsoft.com/en-us/library/ms724247(VS.85).aspx
	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
{
	enum : int32 { mm = (m + 9) % 12 };
	enum : int32 { yy = y - mm / 10 };
	enum : int32 { date = yy * 365 + yy / 4 - yy / 100 + yy / 400 + (mm * 306 + 5) / 10 + (d - 1) };

	static constexpr int32 Version(const int32 trackerID = 0x1000)
	{
		return trackerID + 0x0050 + date - SchismVersionFromDate<2009, 10, 31>::date;
	}
};

OPENMPT_NAMESPACE_END