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  *  PlayerSTD.h
32  *  MilkyPlay
33  *
34  *  Created by Peter Barth on Tue Oct 19 2004.
35  *
36  */
37 #ifndef __PLAYERSTD_H__
38 #define __PLAYERSTD_H__
39 
40 #include "ChannelMixer.h"
41 #include "PlayerBase.h"
42 #include "XModule.h"
43 
44 class PlayerSTD : public PlayerBase
45 {
46 public:
47 	struct StatusEventListener
48 	{
~StatusEventListenerStatusEventListener49 		virtual ~StatusEventListener() { }
50 
playerTickStartedStatusEventListener51 		virtual void playerTickStarted(PlayerSTD& player, XModule& module) { }
playerTickEndedStatusEventListener52 		virtual void playerTickEnded(PlayerSTD& player, XModule& module) { }
timerTickStartedStatusEventListener53 		virtual void timerTickStarted(PlayerSTD& player, XModule& module) { }
timerTickEndedStatusEventListener54 		virtual void timerTickEnded(PlayerSTD& player, XModule& module) { }
patternEndReachedStatusEventListener55 		virtual void patternEndReached(PlayerSTD& player, XModule& module, mp_sint32& newOrderIndex) { }
56 	};
57 
58 private:
59 	enum
60 	{
61 		XM_MINPERIOD = 50
62 	};
63 
64 	struct TPrEnv
65 	{
66 		TEnvelope*	envstruc;
67 		mp_sint32   a,b,step;
68 		mp_uint32	bpmCounter, bpmAdder;
69 
70 		mp_uint32	timeTrackSize;
71 
72 		struct TTimeRecord
73 		{
74 			mp_sword pos;
75 			const TEnvelope* envstruc;
76 		};
77 
78 		TTimeRecord* timeRecord;
79 
TPrEnvTPrEnv80 		TPrEnv() :
81 			timeTrackSize(0),
82 			timeRecord(NULL)
83 		{
84 		}
85 
~TPrEnvTPrEnv86 		~TPrEnv()
87 		{
88 			delete[] timeRecord;
89 		}
90 
clearTPrEnv91 		void clear()
92 		{
93 			envstruc	= 0;
94 			a = b = step = 0;
95 			bpmCounter = bpmAdder = 0;
96 
97 			if (timeTrackSize && timeRecord)
98 				memset(timeRecord, 0, sizeof(TTimeRecord)*timeTrackSize);
99 		}
100 
reallocTimeRecordTPrEnv101 		void reallocTimeRecord(mp_uint32 size)
102 		{
103 			timeTrackSize = size;
104 			delete[] timeRecord;
105 			timeRecord = new TTimeRecord[size];
106 		}
107 
108 		void setToTick(mp_uint32 tick);
109 	};
110 
111 	struct TLastOperands
112 	{
113 		mp_ubyte portaup;
114 		mp_ubyte portadown;
115 		mp_ubyte portanote;
116 		mp_ubyte fineportaup;
117 		mp_ubyte fineportadown;
118 		mp_ubyte xfineportaup;
119 		mp_ubyte xfineportadown;
120 		mp_ubyte volslide;
121 		mp_ubyte finevolslide;
122 		mp_ubyte gvolslide;
123 		mp_ubyte panslide;
124 		mp_ubyte arpeg;
125 		mp_ubyte retrig;
126 		mp_ubyte tremor;
127 		mp_ubyte smpoffset;
128 	};
129 
130 	struct TModuleChannel
131 	{
132 		mp_uint32		flags;
133 		mp_sint32		ins;
134 		mp_sint32		smp;
135 		bool			hasSetVolume;
136 		mp_sint32		vol, tremoloVol, finalTremoloVol, tremorVol;
137 		bool			hasTremolo;
138 		mp_sint32		masterVol;
139 		mp_sint32		pan;
140 		mp_sint32		per, finalVibratoPer, destper;
141 		bool			hasVibrato;
142 		//mp_sint32 c4spd;
143 		mp_sint32		currentnote, relnote;
144 		mp_sint32		finetune;
145 		mp_sword		freqadjust;
146 		mp_sint32		note, destnote, lastnoportanote;
147 		bool			validnote;
148 		mp_ubyte		eff[MP_NUMEFFECTS];
149 		mp_ubyte		eop[MP_NUMEFFECTS];
150 		TLastOperands	old[MP_NUMEFFECTS];
151 
152 		mp_sint32		loopstart;
153 		mp_sint32		execloop;
154 		mp_sint32		loopcounter;
155 		bool			isLooping;
156 		mp_sint32		loopingValidPosition;
157 
158 		mp_ubyte		vibdepth[MP_NUMEFFECTS];
159 		mp_ubyte		vibspeed[MP_NUMEFFECTS];
160 		mp_ubyte		vibpos[MP_NUMEFFECTS];
161 		mp_ubyte		trmdepth[MP_NUMEFFECTS];
162 		mp_ubyte		trmspeed[MP_NUMEFFECTS];
163 		mp_ubyte		trmpos[MP_NUMEFFECTS];
164 		mp_ubyte		tremorcnt[MP_NUMEFFECTS];
165 		mp_sint32		retrigcounterE9x[MP_NUMEFFECTS];
166 		mp_ubyte		retrigmaxE9x[MP_NUMEFFECTS];
167 		mp_sint32		retrigcounterRxx[MP_NUMEFFECTS];
168 		mp_ubyte		retrigmaxRxx[MP_NUMEFFECTS];
169 
170 		bool			keyon;
171 		TPrEnv			venv;
172 		TPrEnv			penv;
173 		TPrEnv			fenv;
174 		TPrEnv			vibenv;
175 		mp_sint32		fadevolstart;
176 		mp_sint32		fadevolstep;
177 		mp_ubyte		avibused;
178 		mp_ubyte		avibspd;
179 		mp_ubyte		avibdepth;
180 		mp_ubyte		avibcnt;
181 		mp_ubyte		avibsweep;
182 		mp_ubyte		avibswcnt;
183 
clearTModuleChannel184 		void clear()
185 		{
186 			flags = 0;
187 			ins = 0;
188 			smp = 0;
189 			hasSetVolume = 0;
190 			vol = tremoloVol = finalTremoloVol = tremorVol = 0;
191 			hasTremolo = false;
192 			masterVol = 0;
193 			pan = 0;
194 			per = finalVibratoPer = destper = 0;
195 			hasVibrato = 0;
196 			currentnote = relnote = 0;
197 			finetune = 0;
198 			freqadjust = 0;
199 			note = destnote = lastnoportanote = 0;
200 			validnote = false;
201 			memset(&eff, 0, sizeof(eff));
202 			memset(&eop, 0, sizeof(eop));
203 			memset(&old, 0, sizeof(old));
204 
205 			loopstart = 0;
206 			execloop = 0;
207 			loopcounter = 0;
208 			isLooping = false;
209 			loopingValidPosition = 0;
210 
211 			memset(&vibdepth, 0, sizeof(vibdepth));
212 			memset(&vibpos, 0, sizeof(vibpos));
213 			memset(&trmdepth, 0, sizeof(trmdepth));
214 			memset(&trmspeed, 0, sizeof(trmspeed));
215 			memset(&trmpos, 0, sizeof(trmpos));
216 			memset(&tremorcnt, 0, sizeof(tremorcnt));
217 			memset(&retrigcounterE9x, 0, sizeof(retrigcounterE9x));
218 
219 			memset(&retrigmaxE9x, 0, sizeof(retrigmaxE9x));
220 			memset(&retrigcounterRxx, 0, sizeof(retrigcounterRxx));
221 			memset(&retrigmaxRxx, 0, sizeof(retrigmaxRxx));
222 
223 			keyon = false;
224 			venv.clear();
225 			penv.clear();
226 			fenv.clear();
227 			vibenv.clear();
228 
229 			fadevolstart = 0;
230 			fadevolstep = 0;
231 			avibused = 0;
232 			avibspd = 0;
233 			avibdepth = 0;
234 			avibcnt = 0;
235 			avibsweep = 0;
236 			avibswcnt = 0;
237 		}
238 
reallocTimeRecordTModuleChannel239 		void reallocTimeRecord(mp_uint32 size)
240 		{
241 			venv.reallocTimeRecord(size);
242 			penv.reallocTimeRecord(size);
243 			fenv.reallocTimeRecord(size);
244 			vibenv.reallocTimeRecord(size);
245 		}
246 	};
247 
248 private:
249 
250 	static const mp_sint32	vibtab[32];
251 	static const mp_uword	lintab[769];
252 	static const mp_uint32	logtab[];
253 
254 	StatusEventListener* statusEventListener;
255 
256 	TModuleChannel*	chninfo;				// our channel information
257 	mp_sint32		lastNumAllocatedChannels;
258 
259 	mp_uint32*		smpoffs;
260 	mp_ubyte*		attick;
261 
262 	mp_sint32		patternIndex;			// holds current pattern index
263 	mp_sint32		numEffects;				// current number of effects
264 	mp_sint32		numChannels;			// current number of channels
265 
266 	mp_ubyte		pbreak;
267 	mp_ubyte		pbreakpos;
268 	mp_sint32		pbreakPriority;
269 	mp_ubyte		pjump;
270 	mp_ubyte		pjumppos,pjumprow;
271 	mp_sint32		pjumpPriority;
272 	bool			patDelay;
273 	bool			haltFlag;
274 	mp_sint32		startNextRow;
275 
276 	mp_sint32		patDelayCount;
277 
278 	// keep track of what positions we already visited (bitmap)
279 	mp_ubyte		rowHits[256*256/8];
280 	bool			isLooping;
281 
282 	///////////////////////////////////////////////////////////////////////////////////////////////////
283 	//					    this information is updated while the song plays
284 	///////////////////////////////////////////////////////////////////////////////////////////////////
285 	bool newInsPTFlag;			// New instrument PT like
286 	bool newInsST3Flag;			// New instrument ST3 like
287 	bool oldPTInsChangeFlag;	// sample without note flag (old PT style)
288 	bool playModePT;
289 	bool playModePTPitchLimit;
290 	bool playModeFT2;
291 	bool playModeChopSampleOffset;
292 
isRowVisited(mp_sint32 row)293 	bool isRowVisited(mp_sint32 row)
294 	{
295 		return (rowHits[row>>3]>>(row&7))&1;
296 	}
297 
visitRow(mp_sint32 row)298 	void visitRow(mp_sint32 row)
299 	{
300 		rowHits[row>>3] |= (1<<(row&7));
301 	}
302 
303 	static void			prenvelope(mp_sint32 c, TPrEnv* env, mp_sint32 keyon);		// process envelopes
304 
305 	static mp_sint32	getenvval(mp_sint32 c, TPrEnv* env, mp_sint32 n);			// get envelope value
306 
307 	// This takes the period *with* 8 bit fractional part
308 	static mp_sint32	getlinfreq(mp_sint32 per);
309 	// This takes the period *with* 8 bit fractional part
310 	static mp_sint32	getlogfreq(mp_sint32 per);
311 	// this returns a period *without* the 8 bit fractional part
312 	static mp_sint32	getlinperiod(mp_sint32 note,mp_sint32 relnote,mp_sint32 finetune);
313 	static mp_sint32	interpolate(mp_sint32 eax,mp_sint32 ebx,mp_sint32 ecx,mp_sint32 edi,mp_sint32 esi);
314 	// this returns a period *without* the 8 bit fractional part
315 	static mp_sint32	getlogperiod(mp_sint32 note,mp_sint32 relnote,mp_sint32 finetune);
316 
getbpmrate(mp_uint32 bpm)317 	mp_uint32		getbpmrate(mp_uint32 bpm)
318 	{
319 		// digibooster "real BPM" setting
320 		mp_uint32 realCiaTempo = (bpm * (baseBpm << 8) / 125) >> 8;
321 
322 		if (!realCiaTempo) realCiaTempo++;
323 
324 		mp_int64 t = ((mp_int64)realCiaTempo)<<(32+2);
325 
326 		const mp_uint32 timerBase = (mp_uint32)(5.0f*500.0f*(MP_BEATLENGTH*MP_TIMERFREQ / (float)MP_BASEFREQ));
327 
328 		return (mp_uint32)(t/timerBase);
329 	}
330 
getperiod(mp_sint32 note,mp_sint32 relnote,mp_sint32 finetune)331 	mp_sint32		getperiod(mp_sint32 note,mp_sint32 relnote,mp_sint32 finetune)
332 	{
333 		if (playModeFT2)
334 		{
335 			// FT2 doesn't support lower 3 bits
336 			if (finetune > 0)
337 				finetune &= 0xF8;
338 			else if (finetune < 0)
339 			{
340 				finetune = -((-finetune + 7) & 0xF8);
341 				if (finetune < -128)
342 					finetune = -128;
343 			}
344 		}
345 
346 		return (module->header.freqtab&1) ? getlinperiod(note,relnote,finetune) : getlogperiod(note,relnote,finetune);
347 	}
348 
getvolume(mp_sint32 c,mp_sint32 nv)349 	mp_sint32		getvolume(mp_sint32 c,mp_sint32 nv)
350 	{
351 		mp_sint32 vol = (nv*getenvval(c,&chninfo[c].venv,256))>>7;
352 		vol = (vol*chninfo[c].fadevolstart)>>16;
353 		vol = (vol*chninfo[c].masterVol)>>8;
354 		vol = (vol*mainVolume)>>8;
355 		return vol;
356 	}
357 
getpanning(mp_sint32 c,mp_sint32 np)358 	mp_sint32		getpanning(mp_sint32 c,mp_sint32 np)
359 	{
360 		mp_sint32 envpan = getenvval(c,&chninfo[c].penv,128);
361 		//if (envpan!=256) cprintf("%i\r\n",envpan);
362 		mp_sint32 finalpan = np+(envpan-128)*(128-abs(np-128))/128;
363 		if (finalpan<0) finalpan=0;
364 		if (finalpan>255) finalpan=255;
365 		return finalpan;
366 	}
367 
getfreq(mp_sint32 c,mp_sint32 per,mp_sword freqadjust)368 	mp_sint32		getfreq(mp_sint32 c,mp_sint32 per,mp_sword freqadjust)
369 	{
370 		if (per<1) return 0;
371 		mp_sint32 eval = getenvval(c,&chninfo[c].fenv,128)-128;
372 		mp_uint32 freq;
373 
374 		freq = (module->header.freqtab&1) ? getlinfreq(per) : getlogfreq(per);
375 
376 		mp_sint32 finalFreq = (freq+(eval*63))+freqadjust;
377 		if (finalFreq < 0) finalFreq = 0;
378 
379 		return finalFreq;
380 	}
381 
382 	mp_sint32		getfinalperiod(mp_sint32 c, mp_sint32 p);
383 
384 	void			playInstrument(mp_sint32 chn, TModuleChannel* chnInf, bool bNoRestart = false);
385 
386 	void			triggerEnvelope(TPrEnv& dstEnv, TEnvelope& srcEnv);
387 	void			triggerEnvelopes(TModuleChannel* chnInf);
388 	void			triggerAutovibrato(TModuleChannel* chnInf);
389 	void			triggerInstrumentFX(TModuleChannel* chnInf);
390 
391 	void			updatePlayModeFlags();
392 
handlePeriodOverflow(mp_sint32 channel)393 	void			handlePeriodOverflow(mp_sint32 channel)
394 	{
395 		// PTK/FT1 playmode
396 		if (playModePTPitchLimit && options[PlayModeOptionForcePTPitchLimit])
397 		{
398 			if (chninfo[channel].per > 856*4)
399 				chninfo[channel].per = 856*4;
400 		}
401 		// FT2 playmode (does nothing right now)
402 		else
403 		{
404 			//if (chninfo[channel].per > 14150)
405 			//	chninfo[channel].per %= 14150;
406 		}
407 	}
408 
handlePeriodUnderflow(mp_sint32 channel)409 	void			handlePeriodUnderflow(mp_sint32 channel)
410 	{
411 		// PTK/FT1 playmode
412 		if (playModePTPitchLimit && options[PlayModeOptionForcePTPitchLimit])
413 		{
414 			if (chninfo[channel].per < 113*4)
415 				chninfo[channel].per = 113*4;
416 		}
417 		// FT2 playmode (clamp on low value, not what FT2 does btw.)
418 		else
419 		{
420 			if (chninfo[channel].per < XM_MINPERIOD)
421 				chninfo[channel].per = XM_MINPERIOD;
422 			//chninfo[channel].per &= 0x3FFF;
423 		}
424 	}
425 
426 	mp_sint32		calcVibrato(TModuleChannel* chnInf, mp_sint32 effcnt);
427 	void			doTickEffect(mp_sint32 chn, TModuleChannel* chnInf, mp_sint32 effcnt);
428 	void			doEffect(mp_sint32 chn, TModuleChannel* chnInf, mp_sint32 effcnt);
429 
430 	void			doTickeffects();
431 	void			progressRow();
432 	void			update();
433 	void			updateBPMIndependent();
434 
435 	//void			handleQueuedPositions(mp_sint32& poscnt);
436 	void			setNewPosition(mp_sint32 poscnt);
437 
438 	void			tickhandler();
439 
440 	mp_sint32		allocateStructures();
441 	void			freeMemory();
442 
443 	// stop song by setting flag and setting speed to zero
444 	void			halt();
445 
446 protected:
447 	virtual void	clearEffectMemory();
448 
449 public:
450 					PlayerSTD(mp_uint32 frequency,
451 							  StatusEventListener* statusEventListener = NULL);
452 
453 	virtual			~PlayerSTD();
454 
getType()455 	virtual PlayerTypes getType() const { return PlayerType_Generic; }
456 
457 	virtual mp_sint32 adjustFrequency(mp_uint32 frequency);
458 	virtual mp_sint32 setBufferSize(mp_uint32 bufferSize);
459 
460 	// virtual from mixer class, perform playing here
461 	virtual void	timerHandler(mp_sint32 currentBeatPacket);
462 
463 	virtual void	restart(mp_uint32 startPosition = 0, mp_uint32 startRow = 0,
464 							bool resetMixer = true,
465 							const mp_ubyte* customPanningTable = NULL,
466 							bool playOneRowOnly = false);
467 
468 	virtual void	reset();
469 
470 	virtual void	resetAllSpeed();
471 
472 	virtual bool	grabChannelInfo(mp_sint32 chn, TPlayerChannelInfo& channelInfo) const;
473 
474 	// milkytracker
475 	virtual void	playNote(mp_ubyte chn, mp_sint32 note, mp_sint32 ins, mp_sint32 vol = -1);
476 
setPanning(mp_ubyte chn,mp_ubyte pan)477 	virtual void	setPanning(mp_ubyte chn, mp_ubyte pan) { chninfo[chn].pan = pan; }
478 
479 #ifdef MILKYTRACKER
480 	friend class PlayerController;
481 	friend class PlayerGeneric;
482 	friend class PlayerStatusTracker;
483 #endif
484 };
485 
486 #endif
487