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  *  PlayerIT.h
32  *  MilyPlay core
33  *
34  *  Created by Peter Barth on Tue Oct 19 2004.
35  *
36  */
37 #ifndef __PLAYERIT_H__
38 #define __PLAYERIT_H__
39 
40 #include "PlayerBase.h"
41 #include "XModule.h"
42 
43 class PlayerIT : public PlayerBase
44 {
45 private:
46 	enum EXMMinPeriod
47 	{
48 		XM_MINPERIOD = 50
49 	};
50 
51 	struct TPrEnv
52 	{
53 		TEnvelope	*envstruc;
54 		bool		enabled;
55 		mp_sint32   a,b,step;
56 		mp_uint32	bpmCounter, bpmAdder;
57 
58 	private:
reachedEndTPrEnv59 		bool		reachedEnd(bool keyon)
60 		{
61 			bool reachedEnd = ((step >= envstruc->env[b][0]) && (b >= envstruc->num - 1));
62 
63 			if (!reachedEnd)
64 				return false;
65 
66 			bool ITBreakLoop = (envstruc->type & 16);
67 			if (ITBreakLoop && keyon)
68 				return false;
69 
70 			bool AMSBreakLoop = (envstruc->type & (4+8)) == (4+8);
71 			bool XMBreakLoop = ((envstruc->type & (2+4)) == (2+4)) && (envstruc->sustain == envstruc->loope);
72 
73 			bool brokeLoop = !keyon && (AMSBreakLoop || XMBreakLoop);
74 
75 			//bool res = ((envstruc->type & 4) && brokeLoop) || (!(envstruc->type & 4));
76 			return ((envstruc->type & 4) && brokeLoop) || (!(envstruc->type & 4));
77 		}
78 
79 	public:
80 
finishedTPrEnv81 		bool finished(bool keyon)
82 		{
83 			if (envstruc == NULL ||
84 				!enabled)
85 				return false;
86 
87 			return reachedEnd(keyon);
88 		}
89 
cuttedTPrEnv90 		bool cutted(bool keyon)
91 		{
92 			return (envstruc &&
93 					reachedEnd(keyon) &&
94 					envstruc->env[b][1] == 0);
95 		}
96 
setEnabledTPrEnv97 		void setEnabled(bool enabled) { this->enabled = enabled; }
isEnabledTPrEnv98 		bool isEnabled() { return enabled && envstruc != NULL; }
99 	};
100 
101 	struct TLastOperands
102 	{
103 		mp_ubyte portaup;
104 		mp_ubyte portadown;
105 		mp_ubyte portanote;
106 		mp_ubyte fineportaup;
107 		mp_ubyte fineportadown;
108 		mp_ubyte xfineportaup;
109 		mp_ubyte xfineportadown;
110 		mp_ubyte volslide;
111 		mp_ubyte finevolslide;
112 		mp_ubyte gvolslide;
113 		mp_ubyte chnvolslide;
114 		mp_ubyte panslide;
115 		mp_ubyte arpeg;
116 		mp_ubyte retrig;
117 		mp_ubyte tremor;
118 		mp_ubyte smpoffset;
119 		mp_ubyte temposlide;
120 	};
121 
122 #define DEFINE_STATINTERFACE \
123 		mp_sint32	getNote() { return chnstat().note; } \
124 		mp_sint32	getIns() { return chnstat().ins; } \
125 		mp_uword	getInsflags() { return chnstat().insflags; } \
126 		mp_sint32	getSmp() { return chnstat().smp; } \
127 \
128 		void		setNote(mp_sint32 note) { chnstat().note = note; } \
129 		void		setIns(mp_sint32 ins) { chnstat().ins = ins; } \
130 		void		setInsflags(mp_uword insflags) { chnstat().insflags = insflags; } \
131 		void		setSmp(mp_sint32 smp) { chnstat().smp = smp; } \
132 \
133 		mp_sint32	getFlags() { return chnstat().flags; } \
134 		void		setFlags(mp_uint32 flags) { chnstat().flags = flags; } \
135 		void		setFlag(mp_uint32 flag) { chnstat().flags |= flag; } \
136 		void		resetFlag(mp_uint32 flag) { chnstat().flags &= ~flag; } \
137 		bool		isFlagSet(mp_uint32 flag) { return (chnstat().flags & flag); } \
138 \
139 		void		setVol(mp_sint32 vol) { chnstat().vol = vol; } \
140 		void		incVol(mp_sint32 offs) { chnstat().vol+=offs; if (chnstat().vol>255) chnstat().vol=255; } \
141 		void		decVol(mp_sint32 offs) { chnstat().vol-=offs; if (chnstat().vol<0) chnstat().vol=0; } \
142 		void		adjustTremoloTremorVol() { chnstat().tremorVol = chnstat().tremoloVol = chnstat().vol; chnstat().hasTremolo = false; chnstat().finalTremoloVol = 0; } \
143 		void		adjustTremoloVol() { chnstat().tremoloVol = chnstat().vol; chnstat().hasTremolo = false; chnstat().finalTremoloVol = 0; } \
144 		void		setFinalTremVol(mp_sint32 vol) { chnstat().finalTremoloVol = vol; chnstat().hasTremolo = true; } \
145 \
146 		void		setPan(mp_sint32 pan) { chnstat().pan = pan; } \
147 		void		incPan(mp_sint32 offs) { chnstat().pan+=offs; if (chnstat().pan>255) chnstat().pan=255; } \
148 		void		decPan(mp_sint32 offs) { chnstat().pan-=offs; if (chnstat().pan<0) chnstat().pan=0; } \
149 \
150 		void		setPer(mp_sint32 per) { chnstat().per = per; } \
151 		void		decPer(mp_sint32 offs) { chnstat().per-=offs; } \
152 		void		incPer(mp_sint32 offs) { chnstat().per+=offs; } \
153 		void		adjustVibratoPer() { chnstat().hasVibrato = false; chnstat().finalVibratoPer = 0; } \
154 		void		setFinalVibratoPer(mp_sint32 per) { chnstat().finalVibratoPer = per; chnstat().hasVibrato = true; } \
155 \
156 		void		clampPerMax(mp_sint32 max) { if (chnstat().per > max) chnstat().per = max; } \
157 		void		clampPerMin(mp_sint32 min) { if (chnstat().per < min) chnstat().per = min; } \
158 \
159 		void		setMasterVol(mp_sint32 vol) { chnstat().masterVol = vol; } \
160 		void		incMasterVol(mp_sint32 offs) { chnstat().masterVol+=offs; if (chnstat().masterVol>255) chnstat().masterVol=255; } \
161 		void		decMasterVol(mp_sint32 offs) { chnstat().masterVol-=offs; if (chnstat().masterVol<0) chnstat().masterVol=0; } \
162 		void		setInsMasterVol(mp_sint32 vol) { chnstat().insMasterVol = vol; } \
163 		void		setSmpMasterVol(mp_sint32 vol) { chnstat().smpMasterVol = vol; } \
164 		void		setFreqadjust(mp_sword freqadjust) { chnstat().freqadjust = freqadjust; } \
165 		void		setRelnote(mp_sint32 relnote) { chnstat().relnote = relnote; } \
166 		void		setFinetune(mp_sint32 finetune) { chnstat().finetune = finetune; } \
167 \
168 		mp_sint32	getVol() { return chnstat().vol; } \
169 		mp_sint32	getTremoloVol() { return chnstat().tremoloVol; } \
170 		mp_sint32	getTremorVol() { return chnstat().tremorVol; } \
171 		mp_sint32	getVolume() { return chnstat().getVolumeInternal(); } \
172 \
173 		mp_sint32	getPan() { return chnstat().pan; } \
174 		mp_sint32	getPer() { return chnstat().per; } \
175 		mp_sint32   getPeriod() { return chnstat().getPeriodInternal(); } \
176 \
177 		mp_sint32	getMasterVol() { return chnstat().masterVol; } \
178 		mp_sint32	getInsMasterVol() { return chnstat().insMasterVol; } \
179 		mp_sint32	getSmpMasterVol() { return chnstat().smpMasterVol; } \
180 		mp_sword	getFreqadjust() { return chnstat().freqadjust; } \
181 		mp_sint32	getRelnote() { return chnstat().relnote; } \
182 		mp_sint32	getFinetune() { return chnstat().finetune; } \
183 \
184 		bool		getKeyon() { return chnstat().keyon; } \
185 \
186 		TPrEnv&		getVenv() { return chnstat().venv; } \
187 		TPrEnv&		getPenv() { return chnstat().penv; } \
188 		TPrEnv&		getFenv() { return chnstat().fenv; } \
189 		TPrEnv&		getVibenv() { return chnstat().vibenv; } \
190 		TPrEnv&		getPitchenv() { return chnstat().pitchenv; } \
191 \
192 		mp_ubyte	getAvibused() { return chnstat().avibused; } \
193 		mp_ubyte	getAvibspd() { return chnstat().avibspd; } \
194 		mp_ubyte	getAvibdepth() { return chnstat().avibdepth; } \
195 		mp_ubyte	getAvibcnt() { return chnstat().avibcnt; } \
196 		mp_ubyte	getAvibsweep() { return chnstat().avibsweep; } \
197 		mp_sint32	getAvibswcnt() { return chnstat().avibswcnt; } \
198 \
199 		void		setKeyon(bool keyon) { chnstat().keyon = keyon; } \
200 		void		setAvibused(mp_ubyte avibused) { chnstat().avibused = avibused; } \
201 		void		setAvibspd(mp_ubyte avibspd) { chnstat().avibspd = avibspd; } \
202 		void		setAvibdepth(mp_ubyte avibdepth) { chnstat().avibdepth = avibdepth; } \
203 		void		setAvibcnt(mp_ubyte avibcnt) { chnstat().avibcnt = avibcnt; } \
204 		void		setAvibsweep(mp_ubyte avibsweep) { chnstat().avibsweep = avibsweep; } \
205 		void		setAvibswcnt(mp_sint32 avibswcnt) { chnstat().avibswcnt = avibswcnt; } \
206 \
207 		void		avibAdvance() \
208 		{ \
209 			chnstat().avibcnt+=chnstat().avibspd; \
210 			/* IT style auto vibrato */ \
211 			if (chnstat().avibused & 128) \
212 			{ \
213 				if (chnstat().avibswcnt < ((mp_sint32)chnstat().avibdepth << 8) && chnstat().avibsweep) \
214 					/* Our vibrato depth is two times finer than the one from IT, increment by sweep*2 */ \
215 					chnstat().avibswcnt+=(mp_sint32)chnstat().avibsweep<<1; \
216 			} \
217 			/* XM style auto vibrato */ \
218 			else \
219 			{ \
220 				if (chnstat().avibswcnt < chnstat().avibsweep) \
221 					chnstat().avibswcnt = (chnstat().avibswcnt+1) & 0xFF; \
222 			} \
223 		} \
224 \
225 		void		setFadevolstart(mp_sint32 fadevolstart) { chnstat().fadevolstart = fadevolstart; } \
226 		mp_sint32	getFadevolstart() { return chnstat().fadevolstart; } \
227 \
228 		void		setFadevolstep(mp_sint32 fadevolstep) { chnstat().fadevolstep = fadevolstep; } \
229 		mp_sint32	getFadevolstep() { return chnstat().fadevolstep; } \
230 \
231 		void		decFadevolstart() { chnstat().fadevolstart-=chnstat().fadevolstep; if (chnstat().fadevolstart<0) chnstat().fadevolstart=0; } \
232 \
233 		void		setFadeout(bool fadeout) { chnstat().fadeout = fadeout; } \
234 		bool		getFadeout() { return chnstat().fadeout; } \
235 \
236 		void		setCutoff(mp_ubyte cutoff) { chnstat().cutoff = cutoff; } \
237 		mp_ubyte	getCutoff() { return chnstat().cutoff; } \
238 \
239 		void		setResonance(mp_ubyte resonance) { chnstat().resonance = resonance; } \
240 		mp_ubyte	getResonance() { return chnstat().resonance; }
241 
242 public:
243 	struct TChnState
244 	{
chnstatTChnState245 		TChnState&	chnstat() { return *this; }
246 
247 		mp_uint32	flags;
248 
249 		mp_sint32	note;
250 		mp_sint32	ins;
251 		mp_uword	insflags;
252 		mp_sint32	smp;
253 
254 		mp_sint32	vol;
255 		mp_sint32	tremoloVol;
256 		mp_sint32	finalTremoloVol;
257 		mp_sint32	tremorVol;
258 		bool		hasTremolo;
259 
260 		mp_sint32	pan;
261 
262 		mp_sint32	per;
263 		mp_sint32	finalVibratoPer;
264 		bool		hasVibrato;
265 
266 		mp_sint32	insMasterVol;
267 		mp_sint32	smpMasterVol;
268 		mp_sint32	masterVol;
269 
270 		mp_sint32	relnote;
271 		mp_sint32	finetune;
272 		mp_sword	freqadjust;
273 
274 		bool		keyon;
275 		bool		fadeout;
276 
277 		TPrEnv		venv;
278 		TPrEnv		penv;
279 		TPrEnv		fenv;
280 		TPrEnv		vibenv;
281 		TPrEnv		pitchenv;
282 
283 		mp_ubyte	avibused;
284 		mp_ubyte	avibspd;
285 		mp_ubyte	avibdepth;
286 		mp_ubyte	avibcnt;
287 		mp_ubyte	avibsweep;
288 		mp_sint32	avibswcnt;
289 
290 		mp_sint32	fadevolstart;
291 		mp_sint32	fadevolstep;
292 
getVolumeInternalTChnState293 		mp_sint32	getVolumeInternal() { return hasTremolo ? finalTremoloVol : vol; }
getPeriodInternalTChnState294 		mp_sint32   getPeriodInternal() { return hasVibrato ? finalVibratoPer : per; }
295 
296 		mp_ubyte	cutoff;
297 		mp_ubyte	resonance;
298 
299 		DEFINE_STATINTERFACE
300 	};
301 
302 private:
303 	struct TModuleChannel;
304 
305 	struct TVirtualChannel
306 	{
307 	private:
308 		bool		active;
309 
310 		mp_sint32	channelIndex;
311 
312 		TChnState	state;
313 
314 		TModuleChannel*	host;
315 		TModuleChannel*	oldHost;
316 
317 	public:
318 		// if we're in background we work on our own state
319 		// if not, we're just going to work on the host state
320 		TChnState&		chnstat();
321 
getRealStateTVirtualChannel322 		TChnState&		getRealState() { return state; }
323 
updateStateTVirtualChannel324 		void			updateState(const TChnState& src)
325 		{
326 			state = src;
327 			state.flags = 0;
328 		}
329 
setActiveTVirtualChannel330 		void			setActive(bool active) { this->active = active; }
getActiveTVirtualChannel331 		bool			getActive() { return active; }
332 
setHostTVirtualChannel333 		void			setHost(TModuleChannel*	host) { this->host = host; }
getHostTVirtualChannel334 		TModuleChannel* getHost() { return host; }
getBackgroundTVirtualChannel335 		bool			getBackground() { return host == NULL; }
336 
setOldHostTVirtualChannel337 		void			setOldHost(TModuleChannel*	host) { this->oldHost = host; }
getOldHostTVirtualChannel338 		TModuleChannel* getOldHost() { return oldHost; }
339 
setChannelIndexTVirtualChannel340 		void			setChannelIndex(mp_sint32 channelIndex) { this->channelIndex = channelIndex; }
getChannelIndexTVirtualChannel341 		mp_sint32		getChannelIndex() { return channelIndex; }
342 
343 		DEFINE_STATINTERFACE
344 
getResultingVolumeTVirtualChannel345 		mp_sint32		getResultingVolume()
346 		{
347 			mp_sint32 vol = (getVolume()*getFadevolstart())>>16;
348 			vol = (vol*getMasterVol()*getInsMasterVol())>>16;
349 			vol = (vol*getSmpMasterVol())>>8;
350 			return vol;
351 		}
352 
clearTVirtualChannel353 		void			clear()
354 		{
355 			mp_sint32 cIndex = channelIndex;
356 			memset(this, 0, sizeof(TVirtualChannel));
357 			channelIndex = cIndex;
358 		}
359 
360 		friend struct TModuleChannel;
361 	};
362 
363 	struct TModuleChannel
364 	{
365 	private:
366 		TChnState	state;
367 
368 		TVirtualChannel* vchn;
369 
370 	public:
371 		// if we're having a virtual channel, we need to work on the state of the virtual channel
372 		// if not, we're just going to work on our own state
chnstatTModuleChannel373 		TChnState&	chnstat() { return vchn ? vchn->chnstat() : state; }
374 
getRealStateTModuleChannel375 		TChnState&	getRealState() { return state; }
376 
hasVchnTModuleChannel377 		bool		hasVchn() { return vchn != NULL; }
getVchnTModuleChannel378 		TVirtualChannel* getVchn() { return vchn; }
linkVchnTModuleChannel379 		void		linkVchn(TVirtualChannel* vchn)
380 		{
381 			vchn->clear();
382 			vchn->setActive(true);
383 			this->vchn = vchn;
384 			vchn->setHost(this);
385 		}
386 
unlinkVchnTModuleChannel387 		TVirtualChannel* unlinkVchn()
388 		{
389 			vchn->setHost(NULL);
390 			vchn->setOldHost(this);
391 			vchn->updateState(getRealState());
392 			TVirtualChannel* result = vchn;
393 			vchn = NULL;
394 			return result;
395 		}
396 
getPlaybackChannelIndexTModuleChannel397 		mp_sint32	getPlaybackChannelIndex() { return ((vchn == NULL) ? -1 : vchn->getChannelIndex()); }
398 
399 		DEFINE_STATINTERFACE
400 
slideToPerTModuleChannel401 		void		slideToPer(mp_sint32 op)
402 		{
403 			if (destper>chnstat().per) {
404 				chnstat().per+=op;
405 				if (chnstat().per>destper) chnstat().per=destper;
406 			}
407 			else if (destper<chnstat().per) {
408 				chnstat().per-=op;
409 				if (chnstat().per<destper) chnstat().per=destper;
410 			}
411 		}
412 
413 		mp_sint32			channelIndex;
414 
415 		bool				hasSetVolume;
416 		mp_sint32			destper;
417 
418 		//mp_sint32 c4spd;
419 		mp_sint32			currentnote;
420 		mp_sint32			destnote;
421 		bool				validnote;
422 		mp_sint32			lastnoportanote;
423 
424 		mp_uint32			smpoffs;
425 		mp_uint32			smpoffshigh;
426 
427 		mp_ubyte			eff[MP_NUMEFFECTS];
428 		mp_ubyte			eop[MP_NUMEFFECTS];
429 		TLastOperands		old[MP_NUMEFFECTS];
430 
431 		mp_sint32			loopstart;
432 		mp_sint32			execloop;
433 		mp_sint32			loopcounter;
434 		bool				isLooping;
435 		mp_sint32			loopingValidPosition;
436 
437 		mp_ubyte			vibdepth[MP_NUMEFFECTS];
438 		mp_ubyte			vibspeed[MP_NUMEFFECTS];
439 		mp_ubyte			vibpos[MP_NUMEFFECTS];
440 		mp_ubyte			trmdepth[MP_NUMEFFECTS];
441 		mp_ubyte			trmspeed[MP_NUMEFFECTS];
442 		mp_ubyte			trmpos[MP_NUMEFFECTS];
443 		mp_ubyte			panbrellodepth[MP_NUMEFFECTS];
444 		mp_ubyte			panbrellospeed[MP_NUMEFFECTS];
445 		mp_ubyte			panbrellopos[MP_NUMEFFECTS];
446 		mp_ubyte			tremorcnt[MP_NUMEFFECTS];
447 		mp_sint32			retrigcounterE9x[MP_NUMEFFECTS];
448 		mp_ubyte			retrigmaxE9x[MP_NUMEFFECTS];
449 		mp_sint32			retrigcounterRxx[MP_NUMEFFECTS];
450 		mp_ubyte			retrigmaxRxx[MP_NUMEFFECTS];
451 
452 		friend struct TVirtualChannel;
453 	};
454 
455 #undef DEFINE_STATINTERFACE
456 
457 private:
458 
459 	static const mp_sint32	vibtab[32];
460 	static const mp_sint32	finesintab[256];
461 	static const mp_uword	lintab[769];
462 	static const mp_uint32	logtab[];
463 	static const mp_uint32	powtab[];
464 
465 	TModuleChannel	*chninfo;				// our channel information
466 	TVirtualChannel *vchninfo;				// our virtual channels
467 
468 	mp_ubyte		*attick;
469 
470 	mp_sint32		patternIndex;			// holds current pattern index
471 	mp_sint32		numModuleChannels;		// max number of "host" channels (from module header)
472 	mp_sint32		numMaxVirChannels;		// max number of virtual channels in total
473 	mp_sint32		numVirtualChannels;		// max number of virtual channels (dynamic)
474 	mp_sint32		numEffects;				// current number of effects
475 	mp_sint32		numChannels;			// current number of channels
476 	mp_sint32		curMaxVirChannels;
477 
478 	mp_ubyte		pbreak;
479 	mp_ubyte		pbreakpos;
480 	mp_sint32		pbreakPriority;
481 	mp_ubyte		pjump;
482 	mp_ubyte		pjumppos,pjumprow;
483 	mp_sint32		pjumpPriority;
484 	bool			patDelay;
485 	bool			haltFlag;
486 	mp_sint32		startNextRow;
487 
488 	mp_sint32		patDelayCount;
489 
490 	// keep track of what positions we already visited (bitmap)
491 	mp_ubyte		rowHits[256*256/8];
492 	bool			isLooping;
493 
494 	///////////////////////////////////////////////////////////////////////////////////////////////////
495 	//					    this information is updated while the song plays
496 	///////////////////////////////////////////////////////////////////////////////////////////////////
497 	bool newInsPTFlag;			// New instrument PT like
498 	bool newInsST3Flag;			// New instrument ST3 like
499 	bool oldPTInsChangeFlag;	// sample without note flag (old PT style)
500 	bool playModePT;
501 	bool playModePTPitchLimit;
502 	bool playModeFT2;
503 	bool playModeChopSampleOffset;
504 
isRowVisited(mp_sint32 row)505 	bool isRowVisited(mp_sint32 row)
506 	{
507 		return (rowHits[row>>3]>>(row&7))&1;
508 	}
509 
visitRow(mp_sint32 row)510 	void visitRow(mp_sint32 row)
511 	{
512 		rowHits[row>>3] |= (1<<(row&7));
513 	}
514 
515 	TVirtualChannel*	allocateVirtualChannel();
releaseVirtualChannel(TVirtualChannel * vchn)516 	void				releaseVirtualChannel(TVirtualChannel* vchn)
517 	{
518 		vchn->setActive(false);
519 		if (vchn->getChannelIndex() == curMaxVirChannels-1)
520 			curMaxVirChannels--;
521 	}
522 
523 	struct TNNATriggerInfo
524 	{
525 		mp_sint32 note;
526 		mp_sint32 ins;
527 		mp_sint32 smp;
528 	};
529 
530 	void				handleNoteOFF(TChnState& state);
531 	void				handlePastNoteAction(TModuleChannel* chnInf, mp_ubyte pastNoteActionType);
532 	bool				handleDCT(TModuleChannel* chnInf, const TNNATriggerInfo& triggerInfo, mp_ubyte DCT, mp_ubyte DCA);
533 	bool				handleNNAs(TModuleChannel* chnInf, const TNNATriggerInfo& triggerInfo);
534 	void				adjustVirtualChannels();
535 
536 	static void			prenvelope(TPrEnv* env, bool keyon, bool timingIT);		// process envelopes
537 
538 	static mp_sint32	getenvval(TPrEnv* env, mp_sint32 n);					// get envelope value
539 
540 	static mp_sint32	interpolate(mp_sint32 eax,mp_sint32 ebx,mp_sint32 ecx,mp_sint32 edi,mp_sint32 esi);
541 
542 	// This takes the period *with* 8 bit fractional part
543 	static mp_sint32	getlinfreq(mp_sint32 per);
544 	// This takes the period *with* 8 bit fractional part
545 	static mp_sint32	getlogfreq(mp_sint32 per);
546 	// this returns a period *without* the 8 bit fractional part
547 	mp_sint32			getlinperiod(mp_sint32 note, mp_sint32 relnote, mp_sint32 finetune);
548 	// this returns a period *without* the 8 bit fractional part
549 	mp_sint32			getlogperiod(mp_sint32 note, mp_sint32 relnote, mp_sint32 finetune);
550 
getbpmrate(mp_uint32 bpm)551 	mp_uint32		getbpmrate(mp_uint32 bpm)
552 	{
553 		// digibooster "real BPM" setting
554 		mp_uint32 realCiaTempo = (bpm * (baseBpm << 8) / 125) >> 8;
555 
556 		if (!realCiaTempo) realCiaTempo++;
557 
558 		mp_int64 t = ((mp_int64)realCiaTempo)<<(32+2);
559 
560 		const mp_uint32 timerBase = (mp_uint32)(5.0f*500.0f*(MP_BEATLENGTH*MP_TIMERFREQ / (float)MP_BASEFREQ));
561 
562 		return (mp_uint32)(t/timerBase);
563 	}
564 
getperiod(mp_sint32 note,mp_sint32 relnote,mp_sint32 finetune)565 	mp_sint32		getperiod(mp_sint32 note, mp_sint32 relnote, mp_sint32 finetune)
566 	{
567 		/*mp_sint32 logper = getlogperiod(note,relnote,finetune);
568 		mp_sint32 linper = getlinperiod(note,relnote,finetune);
569 
570 		mp_sint32 logfreq = getlogfreq(logper<<8);
571 		mp_sint32 linfreq = getlinfreq(linper<<8);
572 
573 		return (module->header.freqtab&1) ? linper : logper;*/
574 
575 		if (playModeFT2)
576 		{
577 			// FT2 doesn't support lower 3 bits
578 			if (finetune > 0)
579 				finetune &= ~3;
580 			else if (finetune < 0)
581 			{
582 				finetune = -((-finetune + 7) & ~3);
583 				if (finetune < -128)
584 					finetune = -128;
585 			}
586 		}
587 
588 		return (module->header.freqtab&1) ? getlinperiod(note,relnote,finetune) : getlogperiod(note,relnote,finetune);
589 	}
590 
getFinalVolume(TChnState & state,mp_sint32 nv,mp_sint32 mainVolume)591 	mp_sint32		getFinalVolume(TChnState& state, mp_sint32 nv, mp_sint32 mainVolume)
592 	{
593 		mp_sint32 vol = (nv*getenvval(&state.venv,256))>>7;
594 		vol = (vol*state.fadevolstart)>>16;
595 		vol = (vol*state.masterVol*state.insMasterVol)>>16;
596 		vol = (vol*state.smpMasterVol*mainVolume)>>16;
597 		return vol;
598 	}
599 
getFinalCutoff(TChnState & state,mp_sint32 nc)600 	mp_sint32		getFinalCutoff(TChnState& state, mp_sint32 nc)
601 	{
602 		if (state.pitchenv.envstruc != NULL &&
603 			state.pitchenv.envstruc->type & 128)
604 			return (nc != MP_INVALID_VALUE) ? nc*getenvval(&state.pitchenv, 256) : 127*getenvval(&state.pitchenv, 256);
605 		else
606 			return (nc != MP_INVALID_VALUE) ? (nc << 8) : nc;
607 	}
608 
getFinalPanning(TChnState & state,mp_sint32 np)609 	mp_sint32		getFinalPanning(TChnState& state, mp_sint32 np)
610 	{
611 		mp_sint32 envpan = getenvval(&state.penv,128);
612 		//if (envpan!=256) cprintf("%i\r\n",envpan);
613 		mp_sint32 finalpan = np+(envpan-128)*(128-abs(np-128))/128;
614 		if (finalpan<0) finalpan=0;
615 		if (finalpan>255) finalpan=255;
616 		return finalpan;
617 	}
618 
getFinalFreq(TChnState & state,mp_sint32 per)619 	mp_sint32		getFinalFreq(TChnState& state, mp_sint32 per)
620 	{
621 		if (per<1) return 0;
622 
623 		// valid envelope and pitch envelope is not configured as filter envelope
624 		if (state.pitchenv.envstruc != NULL && !(state.pitchenv.envstruc->type & 128) && (state.pitchenv.envstruc->type & 1))
625 		{
626 			// scale the envelope point that 256 units match one semitone
627 			mp_sint32 pitch = (getenvval(&state.pitchenv, 128) - 128) * 32;
628 			// add that semitone to the current note
629 			mp_sint32 note = state.getNote() + (pitch>>8);
630 			// the tone between two semitones
631 			mp_sint32 subnote = pitch & 255;
632 			// that would be the actual period we have
633 			mp_sint32 baseperiod = getperiod(state.getNote(), state.getRelnote(), state.getFinetune());
634 
635 			mp_sint32 period1 = getperiod(note, state.getRelnote(), state.getFinetune());
636 			mp_sint32 period2 = getperiod(note+1, state.getRelnote(), state.getFinetune());
637 			mp_sint32 finalperiod = (period1 * (256-subnote) + period2 * subnote);
638 
639 			mp_sint32 diff = finalperiod - (baseperiod << 8);
640 			per+=diff;
641 			if (per < XM_MINPERIOD)
642 				per = XM_MINPERIOD;
643 		}
644 		mp_sint32 eval = getenvval(&state.fenv,128)-128;
645 		mp_uint32 freq = (module->header.freqtab&1) ? getlinfreq(per) : getlogfreq(per);
646 
647 		mp_sint32 finalFreq = (freq+(eval*63))+(mp_sint32)state.freqadjust;
648 		if (finalFreq < 0) finalFreq = 0;
649 
650 		return finalFreq;
651 	}
652 
653 	mp_sint32		getFinalPeriod(TChnState& state, mp_sint32 p);
654 
655 	void			playInstrument(TModuleChannel* chnInf, bool bNoRestart = false);
656 
657 	void			triggerEnvelope(TPrEnv& dstEnv, TEnvelope& srcEnv);
658 	void			triggerEnvelopes(TModuleChannel* chnInf);
659 	void			triggerAutovibrato(TModuleChannel* chnInf);
660 	void			triggerInstrumentFX(TModuleChannel* chnInf, bool triggerEnv = true);
661 
662 	void			updatePlayModeFlags();
663 
handlePeriodOverflow(TModuleChannel * chnInf)664 	void			handlePeriodOverflow(TModuleChannel* chnInf)
665 	{
666 		// PTK/FT1 playmode
667 		if (playModePTPitchLimit && options[PlayModeOptionForcePTPitchLimit])
668 		{
669 			chnInf->clampPerMax(856*4);
670 		}
671 		// FT2 playmode (does nothing right now)
672 		else
673 		{
674 			//if (chnInf->per > 14150)
675 			//	chnInf->per %= 14150;
676 		}
677 	}
678 
handlePeriodUnderflow(TModuleChannel * chnInf)679 	void			handlePeriodUnderflow(TModuleChannel* chnInf)
680 	{
681 		// PTK/FT1 playmode
682 		if (playModePTPitchLimit && options[PlayModeOptionForcePTPitchLimit])
683 		{
684 			chnInf->clampPerMin(113*4);
685 		}
686 		// FT2 playmode (clamp on low value, not what FT2 does btw.)
687 		else
688 		{
689 			chnInf->clampPerMin(XM_MINPERIOD);
690 			//chninfo[channel].per &= 0x3FFF;
691 		}
692 	}
693 
694 	mp_sint32		calcVibrato(TModuleChannel* chnInf, mp_sint32 effcnt, mp_sint32 depthShift = 5);
695 	void			doTickVolslidePT(TModuleChannel* chnInf, mp_sint32 effcnt);
696 	void			doTickVolslideST(TModuleChannel* chnInf, mp_sint32 effcnt);
697 	void			doTickEffect(TModuleChannel* chnInf, mp_sint32 effcnt);
698 
699 	void			doVolslidePT(TModuleChannel* chnInf, mp_sint32 effcnt, mp_ubyte eop);
700 	void			doVolslideST(TModuleChannel* chnInf, mp_sint32 effcnt, mp_ubyte eop);
701 	void			doEffect(TModuleChannel* chnInf, mp_sint32 effcnt);
702 
703 	void			doTickeffects();
704 	void			progressRow();
705 	void			update();
706 	void			updateBPMIndependent();
707 
708 	void			setNewPosition(mp_sint32 poscnt);
709 
710 	void			tickhandler();
711 
712 	mp_sint32		allocateStructures();
713 	void			freeMemory();
714 
715 	// stop song by setting flag and setting speed to zero
716 	void			halt();
717 
718 protected:
719 	virtual void	clearEffectMemory();
720 
721 public:
722 					PlayerIT(mp_uint32 frequency);
723 
724 	virtual			~PlayerIT();
725 
getType()726 	virtual PlayerTypes getType() const { return PlayerType_IT; }
727 
setNumMaxVirChannels(mp_sint32 max)728 	void			setNumMaxVirChannels(mp_sint32 max) { numMaxVirChannels = max; }
getNumMaxVirChannels()729 	mp_sint32		getNumMaxVirChannels() const { return numMaxVirChannels; }
730 
731 	// virtual from mixer class, perform playing here
732 	virtual void	timerHandler(mp_sint32 currentBeatPacket);
733 
734 	// override base class method
735 	virtual mp_sint32   startPlaying(XModule* module,
736 								 bool repeat = false,
737 								 mp_uint32 startPosition = 0,
738 								 mp_uint32 startRow = 0,
739 								 mp_sint32 numChannels = -1,
740 								 const mp_ubyte* customPanningTable = NULL,
741 								 bool idle = false,
742 								 mp_sint32 patternIndex = -1,
743 								 bool playOneRowOnly = false);
744 
745 	virtual void	restart(mp_uint32 startPosition = 0, mp_uint32 startRow = 0, bool resetMixer = true, const mp_ubyte* customPanningTable = NULL, bool playOneRowOnly = false);
746 
747 	virtual void	reset();
748 
749 	virtual void	resetAllSpeed();
750 
751 	virtual bool	grabChannelInfo(mp_sint32 chn, TPlayerChannelInfo& channelInfo) const;
752 
getCurMaxVirChannels()753 	mp_sint32		getCurMaxVirChannels() const { return curMaxVirChannels; }
754 };
755 
756 #endif
757