1 /*
2  * Copyright (c) 2009, The MilkyTracker Team.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * - Redistributions of source code must retain the above copyright notice,
9  *   this list of conditions and the following disclaimer.
10  * - Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * - Neither the name of the <ORGANIZATION> nor the names of its contributors
14  *   may be used to endorse or promote products derived from this software
15  *   without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 /*
31  *  XModule.h
32  *  MilkyPlay
33  *
34  *
35  */
36 #ifndef __XMODULE_H__
37 #define __XMODULE_H__
38 
39 #include "XMFile.h"
40 
41 #define MP_MAXTEXT 32
42 #define MP_MAXORDERS 256
43 #define MP_MAXINS 255
44 #define MP_MAXINSSAMPS 96
45 
46 struct TXMHeader
47 {
48 	char		sig[17];
49 	char		name[MP_MAXTEXT];
50 	char		whythis1a;
51 	char		tracker[MP_MAXTEXT];
52 	mp_uword	ver;
53 	mp_uint32	hdrsize;
54 	mp_uword	ordnum;
55 	mp_uword	restart;
56 	mp_uword	channum;
57 	mp_uword	patnum;
58 	mp_uword	insnum;
59 	mp_uword	smpnum;			// additional: number of samples in tune
60 	mp_uword	volenvnum;		// additional: number of volume envelopes
61 	mp_uword	panenvnum;		// additional: number of panning envelopes
62 	mp_uword	frqenvnum;		// additional: number of frequency envelopes (MDL)
63 	mp_uword	vibenvnum;		// additional: number of vibrato envelopes (AMS)
64 	mp_uword	pitchenvnum;	// additional: number of pitch envelopes (IT)
65 	mp_uword	freqtab;
66 	mp_ubyte	uppernotebound;	// additional: note limit if not zero
67 	mp_sbyte	relnote;		// additional: semitone adjust value
68 	mp_dword    flags;			// additional: some flags
69 	mp_uword	tempo;
70 	mp_uword	speed;
71 	mp_uword	mainvol;
72 	mp_ubyte	ord[MP_MAXORDERS];
73 	mp_ubyte	pan[256];
74 };
75 
76 // ** BEWARE :) **
77 // the order of the different elements concerning the envelope info
78 // is not like in the xm format
79 struct TEnvelope
80 {
81 	mp_uword	env[256][2];
82 	mp_ubyte	num,sustain,susloope,loops,loope,type,speed;
83 };
84 
85 struct TXMInstrument
86 {
87 	enum Flags
88 	{
89 		IF_ITNOTEREMAPPING	= 0x01,
90 		IF_ITFADEOUT		= 0x02,
91 		IF_ITENVELOPES		= 0x04,
92 		IF_ITGOBALINSVOL	= 0x08
93 	};
94 
95 	mp_uint32	size;
96 	char		name[MP_MAXTEXT];
97 	char		type;
98 	mp_uword	samp;
99 	mp_uint32	shsize;
100 	mp_sword	snum[120];		// -1 is an invalid/empty sample
101 	mp_uword	flags;			// not in .XM => from myself
102 								// Also holds NNA (bit 4-5), DCT (bit 6-7), DCA (bit 8-9)
103 	mp_ubyte	notemap[120];	// Impulse Tracker addition
104 	mp_uword	volfade;		// Impulse Tracker addition
105 
106 	mp_uword	venvnum;		// Impulse Tracker envelopes can't be sample-based (different envelopes can map to the same sample) ...
107 	mp_uword	penvnum;		// ... (only when IF_ITENVELOPES flag is set)
108 	mp_uword	fenvnum;
109 	mp_uword	vibenvnum;
110 	mp_uword	pitchenvnum;	// IT pitch envelope
111 
112 	mp_uword	res;			// when bit 3 (= 8) of flags is set, take this as global instrument vol (Impulse Tracker)
113 
114 	mp_ubyte	ifc;			// IT Initial Filter cutoff
115 	mp_ubyte	ifr;			// IT Initial Filter resonance
116 	//char		extra[20];
117 };
118 
119 // some words about the samples:
120 // although the sample buffer is freely available for acess, I would not recommend
121 // accessing it directly if you don't exactly know what you are doing because
122 // to avoid sample clicks when looping samples, it uses a tricky double buffering
123 // technique between smoothed out sample loop areas and the original sample data
124 // If you need to modify sample data yourself, use the provided methods
125 // getSampleValue and setSampleValue and call postProcessSamples when you're done
126 // modifying the sample, so the loop information is updated correctly
127 // Also call postProcessSamples when you're changing the loop information
128 struct TXMSample
129 {
130 private:
131 	struct TLoopDoubleBuffProps
132 	{
133 		enum
134 		{
135 			StateUnused,
136 			StateUsed,
137 			StateDirty,
138 		};
139 
140 		mp_uint32 samplesize;
141 		mp_ubyte state[4];
142 		mp_uint32 lastloopend;
143 	};
144 
145 	enum
146 	{
147 		LoopAreaBackupSize = 4,
148 		LoopAreaBackupSizeMaxInBytes = 8,
149 		EmptySize = 8,
150 		LeadingPadding = sizeof(TLoopDoubleBuffProps) + LoopAreaBackupSizeMaxInBytes + EmptySize,
151 		TrailingPadding = 16,
152 		PaddingSpace = LeadingPadding+TrailingPadding
153 	};
154 
155 	void restoreLoopArea();
156 
157 public:
158 	mp_uint32	samplen;
159 	mp_uint32	loopstart;
160 	mp_uint32	looplen;
161 	mp_ubyte	flags;			// Bit 0: Use volume
162 								// Bit 1: Use panning
163 								// Bit 2: Use sample volume as channel global volume (.PLM modules)
164 								// Bit 3: Use the res field as global sample volume
165 								// Bit 4: Use IT style auto vibrato (not implemented yet)
166 	mp_ubyte	vol;
167 	mp_sbyte	finetune;
168 	mp_ubyte	type;			// In Addition to XM: Bit 5: One shot forward looping sample (MOD backward compatibility)
169 	mp_ubyte	pan;
170 	mp_sbyte	relnote;
171 	mp_uword	venvnum;
172 	mp_uword	penvnum;
173 	mp_uword	fenvnum;
174 	mp_uword	vibenvnum;
175 	mp_uword	pitchenvnum;
176 	mp_ubyte	vibtype, vibsweep, vibdepth, vibrate;
177 	mp_uword	volfade;
178 	mp_ubyte	res;			// when bit 3 (= 8) of flags is set, take this as global sample vol (Impulse Tracker)
179 	mp_sword	freqadjust;
180 	char		name[MP_MAXTEXT];
181 	mp_ubyte	terminate;
182 	mp_sbyte*   sample;
183 
getPaddedSizeTXMSample184 	static mp_uint32 getPaddedSize(mp_uint32 size)
185 	{
186 		return size+TXMSample::PaddingSpace;
187 	}
188 
getPadStartAddrTXMSample189 	static mp_ubyte* getPadStartAddr(mp_ubyte* mem)
190 	{
191 		return mem-TXMSample::LeadingPadding;
192 	}
193 
allocPaddedMemTXMSample194 	static mp_ubyte* allocPaddedMem(mp_uint32 size)
195 	{
196 		mp_ubyte* result = new mp_ubyte[getPaddedSize(size)];
197 
198 		if (result == NULL)
199 			return NULL;
200 
201 		// clear out padding space
202 		memset(result, 0, TXMSample::LeadingPadding);
203 		memset(result+size+TXMSample::LeadingPadding, 0, TXMSample::TrailingPadding);
204 
205 		TLoopDoubleBuffProps* loopBufferProps = (TLoopDoubleBuffProps*)result;
206 		loopBufferProps->samplesize = size;
207 
208 		return result + TXMSample::LeadingPadding;
209 	}
210 
freePaddedMemTXMSample211 	static void freePaddedMem(mp_ubyte* mem)
212 	{
213 		// behave safely on NULL
214 		if (mem == NULL)
215 			return;
216 
217 		delete[] getPadStartAddr(mem);
218 	}
219 
copyPaddedMemTXMSample220 	static void copyPaddedMem(void* dst, const void* src, mp_uint32 size)
221 	{
222 		mp_ubyte* _src = ((mp_ubyte*)src) - TXMSample::LeadingPadding;
223 		mp_ubyte* _dst = ((mp_ubyte*)dst) - TXMSample::LeadingPadding;
224 		memcpy(_dst, _src, getPaddedSize(size));
225 	}
226 
getSampleSizeInBytesTXMSample227 	static mp_uint32 getSampleSizeInBytes(mp_ubyte* mem)
228 	{
229 		TLoopDoubleBuffProps* loopBufferProps = (TLoopDoubleBuffProps*)getPadStartAddr(mem);
230 		return loopBufferProps->samplesize;
231 	}
232 
getSampleSizeInSamplesTXMSample233 	static mp_uint32 getSampleSizeInSamples(mp_ubyte* mem)
234 	{
235 		TLoopDoubleBuffProps* loopBufferProps = (TLoopDoubleBuffProps*)getPadStartAddr(mem);
236 		return (loopBufferProps->state[1] & 16) ? (loopBufferProps->samplesize >> 1) : loopBufferProps->samplesize;
237 	}
238 
239 	void smoothLooping();
240 	void restoreOriginalState();
241 	void postProcessSamples();
242 
243 	// get sample value
244 	// values range from [-32768,32767] in case of a 16 bit sample
245 	// or from [-128,127] in case of an 8 bit sample
246 	mp_sint32 getSampleValue(mp_uint32 index);
247 	mp_sint32 getSampleValue(mp_ubyte* sample, mp_uint32 index);
248 	void setSampleValue(mp_uint32 index, mp_sint32 value);
249 	void setSampleValue(mp_ubyte* sample, mp_uint32 index, mp_sint32 value);
250 
251 #ifdef MILKYTRACKER
equalsTXMSample252 	bool equals(const TXMSample& sample) const
253 	{
254 		if (this->sample != sample.sample)
255 			return false;
256 
257 		if (samplen != sample.samplen)
258 			return false;
259 
260 		return true;
261 	}
262 
isMinimizableTXMSample263 	bool isMinimizable() const
264 	{
265 		return (loopstart + looplen < samplen && (type & 3));
266 	}
267 #endif
268 
269 	friend class XModule;
270 };
271 
272 struct TXMPattern
273 {
274 	mp_uint32	len;
275 	mp_ubyte	ptype;
276 	mp_uword	rows;
277 	mp_ubyte	effnum;
278 	mp_ubyte	channum;
279 	mp_uword	patdata;
280 	mp_ubyte*   patternData;
281 
282 	mp_sint32 compress(mp_ubyte* dest) const;
283 	mp_sint32 decompress(mp_ubyte* src, mp_sint32 len);
284 #ifdef MILKYTRACKER
285 	bool saveExtendedPattern(const SYSCHAR* fileName) const;
286 	bool loadExtendedPattern(const SYSCHAR* fileName);
287 
288 	bool saveExtendedTrack(const SYSCHAR* fileName, mp_uint32 channel) const;
289 	bool loadExtendedTrack(const SYSCHAR* fileName, mp_uint32 channel);
290 
291 	const TXMPattern& operator=(const TXMPattern& src);
292 #endif
293 };
294 
295 //////////////////////////////////////////////////////////////////////////
296 // This is the class which handles a MilkyPlay module					//
297 //////////////////////////////////////////////////////////////////////////
298 class XModule
299 {
300 public:
301 	enum
302 	{
303 		IdentificationBufferSize	= 2048,
304 	};
305 
306 	///////////////////////////////////////////////////////
307 	// this is our loader interface (abstract class)	 //
308 	// each loader has to conform to this interface		 //
309 	///////////////////////////////////////////////////////
310 	class LoaderInterface
311 	{
312 	public:
313 		// make GCC shut up
~LoaderInterface()314 		virtual ~LoaderInterface() { }
315 		// returns c-string which identifies the module, NULL if loader can't identify module
316 		// IMPORTANT: buffer MUST contain eIdentifyBufferSize bytes of the beginning of the file
317 		virtual const char* identifyModule(const mp_ubyte* buffer)			= 0;
318 		// try to load module (check with identifyModule first)
319 		virtual mp_sint32   load(XMFileBase& f, XModule* module)			= 0;
320 	};
321 
322 	enum ModuleTypes
323 	{
324 		ModuleType_UNKNOWN,
325 		ModuleType_669,
326 		ModuleType_AMF,
327 		ModuleType_AMS,
328 		ModuleType_CBA,
329 		ModuleType_DBM,
330 		ModuleType_DIGI,
331 		ModuleType_DSM,
332 		ModuleType_DSm,
333 		ModuleType_DTM_1,
334 		ModuleType_DTM_2,
335 		ModuleType_FAR,
336 		ModuleType_GDM,
337 		ModuleType_GMC,
338 		ModuleType_IMF,
339 		ModuleType_IT,
340 		ModuleType_MDL,
341 		ModuleType_MOD,
342 		ModuleType_MTM,
343 		ModuleType_MXM,
344 		ModuleType_OKT,
345 		ModuleType_PLM,
346 		ModuleType_PSM,
347 		ModuleType_PTM,
348 		ModuleType_S3M,
349 		ModuleType_STM,
350 		ModuleType_SFX,
351 		ModuleType_UNI,
352 		ModuleType_ULT,
353 		ModuleType_XM,
354 		ModuleType_NONE = -1,
355 	};
356 
357 	class SampleLoader
358 	{
359 	protected:
360 		XMFileBase& f;
361 
362 	public:
SampleLoader(XMFileBase & file)363 		SampleLoader(XMFileBase& file) :
364 			f(file)
365 		{
366 		}
367 
~SampleLoader()368 		virtual ~SampleLoader()
369 		{
370 		}
371 
372 		virtual mp_sint32 load_sample_8bits(void* p_dest_buffer, mp_sint32 compressedSize, mp_sint32 p_buffsize) = 0;
373 		virtual mp_sint32 load_sample_16bits(void* p_dest_buffer, mp_sint32 compressedSize, mp_sint32 p_buffsize) = 0;
374 	};
375 
376 private:
377 	struct TLoaderInfo
378 	{
379 		LoaderInterface* loader;
380 		ModuleTypes moduleType;
381 	};
382 
383 public:
384 	enum
385 	{
386 		ST_DEFAULT			= 0x00,
387 		ST_DELTA			= 0x01,
388 		ST_UNSIGNED			= 0x02,
389 		ST_16BIT			= 0x04,
390 		ST_PACKING_MDL		= 0x08,
391 		ST_DELTA_PTM		= 0x10,
392 		ST_BIGENDIAN		= 0x20,
393 		ST_PACKING_IT		= 0x40,
394 		ST_PACKING_IT215	= 0x80,
395 		ST_PACKING_ADPCM	= 0x100
396 	};
397 
398 	static const mp_sint32  periods[12];
399 	static const mp_sint32	sfinetunes[16];
400 	static const mp_sbyte	modfinetunes[16];
401 
402 	static const mp_ubyte	numValidXMEffects;
403 	static const mp_ubyte	validXMEffects[];
404 
405 	//////////////////////////////////////////////////////////////////////////
406 	// different stuff for importing different module types into own format //
407 	//////////////////////////////////////////////////////////////////////////
FixedMUL(mp_sint32 a,mp_sint32 b)408 	static mp_sint32	FixedMUL(mp_sint32 a,mp_sint32 b) { return ((mp_sint32)(((mp_int64)(a)*(mp_int64)(b))>>16)); }
409 
410 	///////////////////////////////////////////////////////
411 	// convert relative note + finetune into C4 speed    //
412 	///////////////////////////////////////////////////////
413 	static mp_sint32	getc4spd(mp_sint32 relnote, mp_sint32 finetune);
414 	///////////////////////////////////////////////////////
415 	// convert C4 speed into relative note + finetune    //
416 	///////////////////////////////////////////////////////
417 	static void			convertc4spd(mp_uint32 c4spd, mp_sbyte* finetune, mp_sbyte* relnote);
418 
419 	static mp_uint32	amigaPeriodToNote(mp_uint32 period);
420 
421 	///////////////////////////////////////////////////////
422 	// load sample into memory							 //
423 	///////////////////////////////////////////////////////
424 	static bool			loadSample(XMFileBase& f, void* buffer,
425 								   mp_uint32 size, mp_uint32 length,
426 								   mp_sint32 flags = ST_DEFAULT);
427 
428 	///////////////////////////////////////////////////////
429 	// load a bunch of samples into memory				 //
430 	///////////////////////////////////////////////////////
431 	mp_sint32			loadModuleSample(XMFileBase& f, mp_sint32 index,
432 										 mp_sint32 flags8 = ST_DEFAULT, mp_sint32 flags16 = ST_16BIT,
433 										 mp_uint32 alternateSize = 0);
434 
435 	mp_sint32			loadModuleSamples(XMFileBase& f,
436 										  mp_sint32 flags8 = ST_DEFAULT, mp_sint32 flags16 = ST_16BIT);
437 
438 	static void			convertXMVolumeEffects(mp_ubyte volume, mp_ubyte& eff, mp_ubyte& op);
439 
440 	///////////////////////////////////////////////////////
441 	// Allocate sample memory and store pointer in pool  //
442 	// *Note* that this memory is always padded with 16  //
443 	// bytes at the start *AND* 16 bytes at the end.     //
444 	///////////////////////////////////////////////////////
445 	mp_ubyte*		allocSampleMem(mp_uint32 size);
446 
447 	///////////////////////////////////////////////////////
448 	// Free sample memory
449 	///////////////////////////////////////////////////////
450 	void			freeSampleMem(mp_ubyte* mem, bool assertCheck = true);
451 
452 #ifdef MILKYTRACKER
453 	void			insertSamplePtr(mp_ubyte* ptr);
454 	void			removeSamplePtr(mp_ubyte* ptr);
455 #endif
456 
457 	///////////////////////////////////////////////////////
458 	//    Clean up! (Is called before loading a song)    //
459 	///////////////////////////////////////////////////////
460 	bool			cleanUp();
461 
462 	///////////////////////////////////////////////////////
463 	// scan through samples and post process to avoid    //
464 	// interpolation clicks                              //
465 	///////////////////////////////////////////////////////
466 	void			postProcessSamples(bool heavy = false);
467 
468 	///////////////////////////////////////////////////////
469 	// set default panning								 //
470 	///////////////////////////////////////////////////////
471 	void			setDefaultPanning();
472 
473 private:
474 	// Identify module
475 	ModuleTypes		type;
476 
477 	// Indicates whether a file is loaded or if it's just an empty song
478 	bool			moduleLoaded;
479 
480 	// each module comes with it's own sample-memory management (MILKYPLAY_MAXSAMPLES samples max.)
481 	mp_ubyte*		samplePool[MP_MAXSAMPLES];
482 	mp_uint32		samplePointerIndex;
483 
484 	// song message retrieving
485 	char*			messagePtr;
486 
487 	// subsong position table
488 	mp_ubyte		subSongPositions[256*2];
489 	mp_sint32		numSubSongs;
490 
491 	// add nother envelope to a given list and increase size of array if necessary
492 	static bool		addEnvelope(TEnvelope*& envs,const TEnvelope& env,mp_uint32& numEnvsAlloc,mp_uint32& numEnvs);
493 	// fix broken envelopes (1 point envelope for example)
494 	static void		fixEnvelopes(TEnvelope* envs, mp_uint32 numEnvs);
495 
496 	// holds available loader instances
497 	class LoaderManager
498 	{
499 	private:
500 		TLoaderInfo*	loaders;
501 
502 		mp_uint32		numLoaders;
503 		mp_uint32		numAllocatedLoaders;
504 
505 		mp_sint32		iteratorCounter;
506 
507 		void registerLoader(LoaderInterface* loader, ModuleTypes type);
508 
509 	public:
510 		LoaderManager();
511 		~LoaderManager();
512 
513 		TLoaderInfo* getFirstLoaderInfo();
514 		TLoaderInfo* getNextLoaderInfo();
515 	};
516 
517 	friend class	LoaderManager;
518 
519 	bool			validate();
520 
521 public:
522 
523 	// Module flags
524 	enum
525 	{
526 		MODULE_OLDS3MVOLSLIDES			= 1,
527 		MODULE_ST3NOTECUT				= 2,
528 		MODULE_ST3DUALCOMMANDS			= 4,
529 		MODULE_STMARPEGGIO				= 8,
530 		MODULE_XMARPEGGIO				= 16,
531 		MODULE_XMVOLCOLUMNVIBRATO		= 32,
532 		MODULE_XMNOTECLIPPING			= 64,
533 		MODULE_XMPORTANOTEBUFFER		= 128,
534 		MODULE_AMSENVELOPES				= 256,
535 		MODULE_PTNEWINSTRUMENT			= 512,
536 		MODULE_ST3NEWINSTRUMENT			= 1024,
537 		MODULE_OLDPTINSTRUMENTCHANGE	= 2048,
538 		MODULE_ITNOTEOFF				= 4096,
539 		MODULE_ITNEWEFFECTS				= 8192,
540 		MODULE_ITNEWGXX					= 16384,
541 		MODULE_ITLINKPORTAMEM			= 32768,
542 		MODULE_ITTEMPOSLIDE				= 65536,
543 	};
544 
545 	enum
546 	{
547 		NOTE_LAST	= 120,
548 		NOTE_OFF	= 121,
549 		NOTE_CUT	= 122,
550 		NOTE_FADE	= 123,
551 
552 		SubSongMarkEffect	= 0x1E,
553 		SubSongMarkOperand	= 0xFF,
554 	};
555 
556 	TXMHeader		header;		// module header
557 	TXMInstrument*	instr;		// all instruments (256 of them)
558 	TXMSample*		smp;		// all samples (256 of them, only 255 can be used)
559 	TXMPattern*		phead;		// all pattern headers (256 of them)
560 
561 	mp_uint32		messageBytesAlloc;
562 	char*			message;	// song message
563 
564 	TEnvelope*		venvs;
565 	mp_uint32		numVEnvsAlloc;
566 	mp_uint32		numVEnvs; // should be equal to header.venvnum
addVolumeEnvelope(const TEnvelope & env)567 	bool			addVolumeEnvelope(const TEnvelope& env) { return addEnvelope(venvs, env, numVEnvsAlloc, numVEnvs); }
568 
569 	TEnvelope*		penvs;
570 	mp_uint32		numPEnvsAlloc;
571 	mp_uint32		numPEnvs; // should be equal to header.penvnum
addPanningEnvelope(const TEnvelope & env)572  	bool			addPanningEnvelope(const TEnvelope& env) { return addEnvelope(penvs, env, numPEnvsAlloc, numPEnvs); }
573 
574 	TEnvelope*		fenvs;
575 	mp_uint32		numFEnvsAlloc;
576 	mp_uint32		numFEnvs; // should be equal to header.fenvnum
addFrequencyEnvelope(const TEnvelope & env)577 	bool			addFrequencyEnvelope(const TEnvelope& env) { return addEnvelope(fenvs, env, numFEnvsAlloc, numFEnvs); }
578 
579 	TEnvelope*		vibenvs;
580 	mp_uint32		numVibEnvsAlloc;
581 	mp_uint32		numVibEnvs; // should be equal to header.vibenvnum
addVibratoEnvelope(TEnvelope & env)582 	bool			addVibratoEnvelope(TEnvelope& env) { return addEnvelope(vibenvs, env, numVibEnvsAlloc, numVibEnvs); }
583 
584 	TEnvelope*		pitchenvs;
585 	mp_uint32		numPitchEnvsAlloc;
586 	mp_uint32		numPitchEnvs; // should be equal to header.vibenvnum
addPitchEnvelope(TEnvelope & env)587 	bool			addPitchEnvelope(TEnvelope& env) { return addEnvelope(pitchenvs, env, numPitchEnvsAlloc, numPitchEnvs); }
588 
589 	///////////////////////////////////////////////////////
590 	// convert volume from range [0..64] to [0..255]     //
591 	///////////////////////////////////////////////////////
vol64to255(mp_sint32 vol)592 	static mp_sint32		vol64to255(mp_sint32 vol) { return ((vol>64?64:vol)*261120+65535)>>16; }
593 
594 	///////////////////////////////////////////////////////
595 	// convert volume from range [0..255] to [0..64]     //
596 	///////////////////////////////////////////////////////
vol255to64(mp_uint32 vol)597 	static mp_uint32		vol255to64(mp_uint32 vol) { return (vol*64)/255; }
598 
599 	///////////////////////////////////////////////////////
600 	// convert volume from range [0..127] to [0..255]    //
601 	///////////////////////////////////////////////////////
vol127to255(mp_sint32 vol)602 	static mp_sint32		vol127to255(mp_sint32 vol) { return ((vol>127?127:vol)*131588+65535)>>16; }
603 
604 	///////////////////////////////////////////////////////
605 	// convert volume from range [0..128] to [0..255]    //
606 	///////////////////////////////////////////////////////
vol128to255(mp_sint32 vol)607 	static mp_sint32		vol128to255(mp_sint32 vol) { return ((vol>128?128:vol)*130560+65535)>>16; }
608 
pan15to255(mp_sint32 pan)609 	static mp_sint32		pan15to255(mp_sint32 pan) { return pan>=0xF?0xFF:(pan<<4); }
610 
611 	///////////////////////////////////////////////////
612 	// Allocate necessary memory for song structures //
613 	///////////////////////////////////////////////////
614 					XModule();
615 
616 	///////////////////////////////////////////////////
617 	// Clean up										//
618 	///////////////////////////////////////////////////
619 					~XModule();
620 
621 	///////////////////////////////////////////////////
622 	// Get type of module							 //
623 	///////////////////////////////////////////////////
getType()624 	ModuleTypes		getType() const { return type; }
625 
626 	///////////////////////////////////////////////////
627 	// identify module type 						 //
628 	// IMPORTANT: buffer MUST contain				 //
629 	// eIdentifyBufferSize bytes from the beginning  //
630 	// of the file									 //
631 	///////////////////////////////////////////////////
632 	static const char*	identifyModule(const mp_ubyte* buffer);
633 
634 	///////////////////////////////////////////////////
635 	// generic module loader						 //
636 	///////////////////////////////////////////////////
637 	mp_sint32		loadModule(XMFileBase& f, bool scanForSubSongs = false);
638 	mp_sint32		loadModule(const SYSCHAR* fileName, bool scanForSubSongs = false);
639 
640 	///////////////////////////////////////////////////
641 	// Module exporters								 //
642 	///////////////////////////////////////////////////
643 	mp_sint32		saveExtendedModule(const SYSCHAR* fileName);		// FT2 (.XM)
644 	mp_sint32		saveProtrackerModule(const SYSCHAR* fileName);   // Protracker compatible (.MOD)
645 
646 	///////////////////////////////////////////////////
647 	// module loaded?								 //
648 	///////////////////////////////////////////////////
isModuleLoaded()649 	bool			isModuleLoaded() const { return moduleLoaded; }
650 
651 	///////////////////////////////////////////////////
652 	// string processing							 //
653 	///////////////////////////////////////////////////
654 	static void		convertStr(char* strIn, const char* strOut, mp_sint32 nLen, bool filter = true);
655 
656 	void			getTitle(char* str, bool filter = true) const;
657 	void			getSignature(char* str, bool filter = true) const;
658 	void			getTracker(char* str, bool filter = true) const;
659 
660 	///////////////////////////////////////////////////
661 	// dealing with song message				     //
662 	///////////////////////////////////////////////////
663 
664 	// allocate empty song message
665 	void			allocateSongMessage(mp_uint32 initialSize = 512);
666 
667 	// add one more line of text to the song message
668 	void			addSongMessageLine(const char* line);
669 
670 	// start iterating text lines (get size of line)
671 	mp_sint32		getFirstSongMessageLineLength();
672 	// get next size text line
673 	mp_sint32		getNextSongMessageLineLength();
674 	// get line
675 	void			getSongMessageLine(char* line);
676 
677 	void			buildSubSongTable();
678 
getNumSubSongs()679 	mp_sint32		getNumSubSongs() const { return numSubSongs; }
680 
681 	mp_sint32		getSubSongPosStart(mp_sint32 i) const;
682 	mp_sint32		getSubSongPosEnd(mp_sint32 i) const;
683 
684 	///////////////////////////////////////////////////
685 	// various post processing and analyzing		 //
686 	///////////////////////////////////////////////////
687 	// Remove stupid empty = 0xFE orders
688 	void			removeOrderSkips();
689 	// Remove unused patterns
690 	mp_sint32		removeUnusedPatterns(bool evaluate);
691 
692 	// these are located in ExporterXM.cpp
693 	mp_sint32		getNumUsedPatterns();
694 	mp_sint32		getNumUsedInstruments();
695 
696 	// Analyse various things, for example if there is an old Protracker instrument change
697 	void			postLoadAnalyser();
698 
699 	// MilkyTracker additions
700 	void			createEmptySong(bool clearPatterns = true, bool clearInstruments = true, mp_sint32 numChannels = 8);
701 
702 	enum IsPTCompatibleErrorCodes
703 	{
704 		IsPTCompatibleErrorCodeNoError = 0,
705 		IsPTCompatibleErrorCodeTooManyInstruments,
706 		IsPTCompatibleErrorCodeLinearFrequencyUsed,
707 		IsPTCompatibleErrorCodeIncompatibleSamples,
708 		IsPTCompatibleErrorCodeIncompatibleInstruments,
709 		IsPTCompatibleErrorCodeIncompatiblePatterns
710 	};
711 
712 	IsPTCompatibleErrorCodes isPTCompatible();
713 };
714 
715 #endif
716