1 /* OpenCP Module Player
2  * copyright (c) '94-'10 Niklas Beisert <nbeisert@physik.tu-muenchen.de>
3  *
4  * XMPlay - Module player for XM/MOD and affiliate formats
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  * revision history: (please note changes here)
21  *  -nb980510   Niklas Beisert <nbeisert@physik.tu-muenchen.de>
22  *    -first release
23  *  -kb980717   Tammo Hinrichs <opencp@gmx.net>
24  *    -removed all references to gmd structures to make this more flexible
25  *    -MOD: added module flag "ismod" to handle some protracker "features"
26  *          (YEZ! Finally this player is chiptune capable!)
27  *    -fixed envelope handling (sustain point was ignored when loopstart,
28  *     loopend and sustain point were the same)
29  *    -added plenty of effect status variables for screen output
30  *    -fixed "always loop the last pattern" bug
31  *    -MOD: fixed "offset greater than samplelength" bug
32  *    -MOD: rewrote PlayNote() to achieve perfect PQE
33  *          (Protracker Quirk Emulation ;)
34  *    -MOD: enabled tick0 effects while pattern delay
35  *    -MOD: added second "set speed" command for vblank timed modules
36  *    -added "set finetune" command (E5x) (thanks to jt_letgo.xm ;)
37  *    -added panpos array to xmodule for MOD/MXM channel panning
38  *    -made vibratos weaker (yes, i didnt recognize that sooner, just
39  *     blame me)
40  *    -fixed playnote() again a bit
41  *  -kb981210   Tammo Hinrichs <opencp@gmx.net>
42  *    -set max channels to 256 to play modplug 64chn XMs and such
43  *    -again many fixes in playnote() (  when...  WHEN...  )
44  *  -kb990401   Tammo Hinrichs <opencp@gmx.net>
45  *    -Note Retrig fixed
46  *  -ryg990426  Fabian Giesen  <fabian@jdcs.su.nw.schule.de>
47  *    -^^^ put this fix into cvs because kb was too lazy and i was stupid
48  *     enuff to say i would do the job :)
49  *  -doj20020901 Dirk Jagdmann <doj@cubic.org>
50  *    -enable/disable pattern looping
51  */
52 
53 #include "config.h"
54 #include <string.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include "types.h"
58 #include "cpiface/cpiface.h"
59 #include "dev/mcp.h"
60 #include "xmplay.h"
61 #include "stuff/err.h"
62 
63 struct channel
64 {
65 	int chVol;
66 	int chFinalVol;
67 	int chPan;
68 	int chFinalPan;
69 	int32_t chPitch;
70 	int32_t chFinalPitch;
71 	int curnote;
72 
73 	uint8_t chCurIns;
74 	uint8_t chLastIns;
75 	int chCurNormNote;
76 	uint8_t chSustain;
77 	uint16_t chFadeVol;
78 	uint16_t chAVibPos;
79 	uint32_t chAVibSwpPos;
80 	uint32_t chVolEnvPos;
81 	uint32_t chPanEnvPos;
82 
83 	uint8_t chDefVol;
84 	int chDefPan;
85 	uint8_t chCommand;
86 	uint8_t chVCommand;
87 	int32_t chPortaToPitch;
88 	int32_t chPortaToVal;
89 	uint8_t chVolSlideVal;
90 	uint8_t chGVolSlideVal;
91 	uint8_t chVVolPanSlideVal;
92 	uint8_t chPanSlideVal;
93 	uint8_t chFineVolSlideUVal;
94 	uint8_t chFineVolSlideDVal;
95 	int32_t chPortaUVal;
96 	int32_t chPortaDVal;
97 	uint8_t chFinePortaUVal;
98 	uint8_t chFinePortaDVal;
99 	uint8_t chXFinePortaUVal;
100 	uint8_t chXFinePortaDVal;
101 	uint8_t chVibRate;
102 	uint8_t chVibPos;
103 	uint8_t chVibType;
104 	uint8_t chVibDep;
105 	uint8_t chTremRate;
106 	uint8_t chTremPos;
107 	uint8_t chTremType;
108 	uint8_t chTremDep;
109 	uint8_t chPatLoopCount;
110 	uint8_t chPatLoopStart;
111 	uint8_t chArpPos;
112 	uint8_t chArpNotes[3];
113 	uint8_t chActionTick;
114 	uint8_t chMRetrigPos;
115 	uint8_t chMRetrigLen;
116 	uint8_t chMRetrigAct;
117 	uint8_t chDelayNote;
118 	uint8_t chDelayIns;
119 	uint8_t chDelayVol;
120 	uint8_t chOffset;
121 	uint8_t chGlissando;
122 	uint8_t chTremorPos;
123 	uint8_t chTremorLen;
124 	uint8_t chTremorOff;
125 	uint8_t chSync;
126 	int chSyncTime;
127 	int delayfreq;
128 
129 	unsigned int nextstop;
130 	unsigned int nextsamp;
131 	unsigned int nextpos;
132 	struct xmpsample *cursamp;
133 
134 	int evpos0;
135 	int evmodtype;
136 	int evmod;
137 	int evmodpos;
138 	int evpos;
139 	int evtime;
140 
141 	int notehit;
142 	uint8_t volslide;
143 	uint8_t pitchslide;
144 	uint8_t panslide;
145 	uint8_t volfx;
146 	uint8_t pitchfx;
147 	uint8_t notefx;
148 	uint8_t fx;
149 };
150 
151 static int looping;
152 static int looped;
153 static int usersetpos;
154 static struct channel channels[256];
155 
156 static uint8_t mutech[256];
157 static uint8_t globalvol;
158 static uint8_t globalfx;
159 
160 static uint8_t curtick;
161 static uint8_t curtempo;
162 static uint8_t tick0;
163 
164 static int currow;
165 static uint8_t (*patptr)[5];
166 static int patlen;
167 static int curord;
168 
169 static int nord;
170 static int ninst;
171 static int nsamp;
172 static int linearfreq;
173 static int nchan;
174 static int loopord;
175 static int nenv;
176 static char ismod;
177 static char ft2_e60bug;
178 static struct xmpinstrument *instruments;
179 static struct xmpsample *samples;
180 static struct sampleinfo *sampleinfos;
181 static struct xmpenvelope *envelopes;
182 static uint8_t (**patterns)[5];
183 static uint16_t *orders;
184 static uint16_t *patlens;
185 
186 static int jumptoord;
187 static int jumptorow;
188 static int nextpatternrow; /* which row to go do, when doing roll-over at the end of pattern - normally row 0, except for Fast Tracker II E60 bug */
189 static int patdelay;
190 
191 static uint8_t procnot;
192 static uint8_t procins;
193 static uint8_t procvol;
194 static uint8_t proccmd;
195 static uint8_t procdat;
196 static int firstspeed;
197 static int curbpm;
198 
199 static int realsync;
200 static int realsynctime;
201 
202 static int realpos;
203 
204 static int (*que)[4];
205 static int querpos;
206 static int quewpos;
207 static int quelen;
208 static int cmdtime;
209 static int realtempo;
210 static int realspeed;
211 static int realgvol;
212 
213 
214 enum
215 {
216 	quePos, queSync, queTempo, queSpeed, queGVol
217 };
218 
219 static short sintab[256]=
220 {
221 	    0,    50,   100,   151,   201,   251,   301,   350,
222 	  400,   449,   498,   546,   595,   642,   690,   737,
223 	  784,   830,   876,   921,   965,  1009,  1053,  1096,
224 	 1138,  1179,  1220,  1260,  1299,  1338,  1375,  1412,
225 	 1448,  1483,  1517,  1551,  1583,  1615,  1645,  1674,
226 	 1703,  1730,  1757,  1782,  1806,  1829,  1851,  1872,
227 	 1892,  1911,  1928,  1945,  1960,  1974,  1987,  1998,
228 	 2009,  2018,  2026,  2033,  2038,  2042,  2046,  2047,
229 	 2048,  2047,  2046,  2042,  2038,  2033,  2026,  2018,
230 	 2009,  1998,  1987,  1974,  1960,  1945,  1928,  1911,
231 	 1892,  1872,  1851,  1829,  1806,  1782,  1757,  1730,
232 	 1703,  1674,  1645,  1615,  1583,  1551,  1517,  1483,
233 	 1448,  1412,  1375,  1338,  1299,  1260,  1220,  1179,
234 	 1138,  1096,  1053,  1009,   965,   921,   876,   830,
235 	  784,   737,   690,   642,   595,   546,   498,   449,
236 	  400,   350,   301,   251,   201,   151,   100,    50,
237 	    0,   -50,  -100,  -151,  -201,  -251,  -301,  -350,
238 	 -400,  -449,  -498,  -546,  -595,  -642,  -690,  -737,
239 	 -784,  -830,  -876,  -921,  -965, -1009, -1053, -1096,
240 	-1138, -1179, -1220, -1260, -1299, -1338, -1375, -1412,
241 	-1448, -1483, -1517, -1551, -1583, -1615, -1645, -1674,
242 	-1703, -1730, -1757, -1782, -1806, -1829, -1851, -1872,
243 	-1892, -1911, -1928, -1945, -1960, -1974, -1987, -1998,
244 	-2009, -2018, -2026, -2033, -2038, -2042, -2046, -2047,
245 	-2048, -2047, -2046, -2042, -2038, -2033, -2026, -2018,
246 	-2009, -1998, -1987, -1974, -1960, -1945, -1928, -1911,
247 	-1892, -1872, -1851, -1829, -1806, -1782, -1757, -1730,
248 	-1703, -1674, -1645, -1615, -1583, -1551, -1517, -1483,
249 	-1448, -1412, -1375, -1338, -1299, -1260, -1220, -1179,
250 	-1138, -1096, -1053, -1009,  -965,  -921,  -876,  -830,
251 	 -784,  -737,  -690,  -642,  -595,  -546,  -498,  -449,
252 	 -400,  -350,  -301,  -251,  -201,  -151,  -100,   -50
253 };
254 
freqrange(int x)255 static int freqrange(int x)
256 {
257 	if (linearfreq)
258 		return (x<-72*256)?-72*256:(x>96*256)?96*256:x;
259 	else
260 		return (x<107)?107:(x>438272)?438272:x;
261 }
262 
volrange(int x)263 static int volrange(int x)
264 {
265 	return (x<0)?0:(x>0x40)?0x40:x;
266 }
267 
panrange(int x)268 static int panrange(int x)
269 {
270 	return (x<0)?0:(x>0xFF)?0xFF:x;
271 }
272 
273 
ReadQue()274 static void ReadQue()
275 {
276 	int type,val1,val2,t;
277 	int i;
278 	int time=mcpGet(-1, mcpGTimer);
279 	while (1)
280 	{
281 		if (querpos==quewpos)
282 			break;
283 		if (time<que[querpos][0])
284 			break;
285 
286 		t=que[querpos][0];
287 		type=que[querpos][1];
288 		val1=que[querpos][2];
289 		val2=que[querpos][3];
290 		querpos=(querpos+1)%quelen;
291 
292 		switch (type)
293 		{
294 			case queSync:
295 				realsync=val2;
296 				realsynctime=t;
297 				channels[val1].chSync=val2;
298 				channels[val1].chSyncTime=t;
299 				break;
300 			case quePos:
301 				realpos=val2;
302 				for (i=0; i<nchan; i++)
303 				{
304 					struct channel *c=&channels[i];
305 					if (c->evpos==-1)
306 					{
307 						if (c->evpos0==realpos)
308 						{
309 							c->evpos=realpos;
310 							c->evtime=t;
311 						}
312 					} else {
313 						switch (c->evmodtype)
314 						{
315 							case 1:
316 								c->evmodpos++;
317 								break;
318 							case 2:
319 								if (!(realpos&0xFF))
320 									c->evmodpos++;
321 								break;
322 							case 3:
323 								if (!(realpos&0xFFFF))
324 									c->evmodpos++;
325 								break;
326 						}
327 						if ((c->evmodpos==c->evmod)&&c->evmod)
328 						{
329 							c->evmodpos=0;
330 							c->evpos=realpos;
331 							c->evtime=t;
332 						}
333 					}
334 				}
335 				break;
336 			case queGVol: realgvol=val2; break;
337 			case queTempo: realtempo=val2; break;
338 			case queSpeed: realspeed=val2; break;
339 		}
340 	}
341 }
342 
putque(int type,int val1,int val2)343 static void putque(int type, int val1, int val2)
344 {
345 	if (((quewpos+1)%quelen)==querpos)
346 		return;
347 	que[quewpos][0]=cmdtime;
348 	que[quewpos][1]=type;
349 	que[quewpos][2]=val1;
350 	que[quewpos][3]=val2;
351 	quewpos=(quewpos+1)%quelen;
352 }
353 
354 
PlayNote(struct channel * ch)355 static void PlayNote(struct channel *ch)
356 {
357 	int portatmp=0;
358 	int delaytmp;
359 	int keyoff=0;
360 
361 	if (proccmd==xmpCmdPortaNote)
362 		portatmp=1;
363 	if (proccmd==xmpCmdPortaVol)
364 		portatmp=1;
365 	if ((procvol>>4)==xmpVCmdPortaNote)
366 		portatmp=1;
367 
368 	delaytmp=(proccmd==xmpCmdDelayNote)&&procdat;
369 
370 	if (procnot==97)
371 	{
372 		procnot=0;
373 		procins=0;
374 		keyoff=1;
375 	}
376 
377 	if ((proccmd==xmpCmdKeyOff)&&!procdat)
378 		keyoff=1;
379 
380 	if (!ch->chCurIns)
381 		return;
382 
383 	if (ismod && !procnot && procins && ch->chCurIns!=ch->chLastIns)
384 		procnot=ch->curnote;
385 
386 	if (procins && !keyoff && !delaytmp)
387 		ch->chSustain=1;
388 
389 	if (procnot && !delaytmp)
390 		ch->curnote=procnot;
391 
392 	if (procins && (ismod || !delaytmp))
393 	{
394 		int32_t checknote = ch->curnote;
395 		if (!checknote)
396 			checknote=49;
397 		if (ismod)
398 			ch->cursamp=&samples[ch->chCurIns-1];
399 		else {
400 			struct xmpinstrument *ins=&instruments[ch->chCurIns-1];
401 			if (ins->samples[checknote-1]>nsamp)
402 				return;
403 			ch->cursamp=&samples[ins->samples[checknote-1]];
404 		}
405 		ch->chDefVol=(ch->cursamp->stdvol+1)>>2;
406 		ch->chDefPan=ch->cursamp->stdpan;
407 	}
408 
409 	if (procnot && !delaytmp)
410 	{
411 
412 		if (!portatmp)
413 		{
414 			int32_t nn, frq;
415 			ch->nextstop=1;
416 			ch->notehit=1;
417 
418 			if (!ismod && procins)
419 			{
420 				struct xmpinstrument *ins=&instruments[ch->chCurIns-1];
421 				if (ins->samples[ch->curnote-1]>nsamp)
422 					return;
423 				ch->cursamp=&samples[ins->samples[ch->curnote-1]];
424 				ch->chDefVol=(ch->cursamp->stdvol+1)>>2;
425 				ch->chDefPan=ch->cursamp->stdpan;
426 			}
427 
428 			if (ch->cursamp)
429 			{
430 				ch->nextsamp=ch->cursamp->handle;
431 
432 				nn=ch->cursamp->normnote;
433 				if (proccmd==xmpCmdSFinetune)
434 				{
435 					nn=ch->cursamp->normtrans-(int16_t)(procdat<<4)+0x80;
436 					ch->fx=xfxSetFinetune;
437 				}
438 
439 				ch->chCurNormNote=nn;
440 			} else {
441 				/* if we have no sample yet, just do as much as we can */
442 				if (proccmd==xmpCmdSFinetune)
443 					ch->fx=xfxSetFinetune;
444 			}
445 
446 			frq=48*256-(((procnot-1)<<8)-ch->chCurNormNote);
447 			if (!linearfreq)
448 				frq=mcpGetFreq6848(frq);
449 			ch->chPitch=frq;
450 			ch->chFinalPitch=frq;
451 			ch->chPortaToPitch=frq;
452 
453 			ch->nextpos=0;
454 
455 			if (proccmd==xmpCmdOffset)
456 			{
457 				if (procdat!=0)
458 					ch->chOffset=procdat;
459 				ch->nextpos=ch->chOffset<<8;
460 				if (ismod && ch->nextpos>sampleinfos[ch->nextsamp].length)
461 					ch->nextpos=sampleinfos[ch->nextsamp].length-16;
462 				ch->fx=xfxOffset;
463 			}
464 
465 			ch->chVibPos=0;
466 			ch->chTremPos=0;
467 			ch->chArpPos=0;
468 			ch->chMRetrigPos=0;
469 			ch->chTremorPos=0;
470 		} else {
471 			int32_t frq=48*256-(((procnot-1)<<8)-ch->chCurNormNote);
472 			if (!linearfreq)
473 				frq=mcpGetFreq6848(frq);
474 			ch->chPortaToPitch=frq;
475 		}
476 	}
477 
478 	if (procnot && delaytmp && !ismod)
479 		return;
480 
481 	if (keyoff&&ch->cursamp)
482 	{
483 		ch->chSustain=0;
484 		if ((ch->cursamp->volenv>=nenv)&&!procins)
485 			ch->chFadeVol=0;
486 	}
487 
488 	if (procins && (ismod || ch->chSustain))
489 	{
490 		ch->chVol=ch->chDefVol;
491 		ch->chFinalVol=ch->chDefVol;
492 		if (ch->chDefPan!=-1)
493 		{
494 			ch->chPan=ch->chDefPan;
495 			ch->chFinalPan=ch->chDefPan;
496 		}
497 		ch->chFadeVol=0x8000;
498 		ch->chAVibPos=0;
499 		ch->chAVibSwpPos=0;
500 		ch->chVolEnvPos=0;
501 		ch->chPanEnvPos=0;
502 	}
503 }
504 
505 static uint16_t notetab[16]={32768,30929,29193,27554,26008,24548,23170,21870,20643,19484,18390,17358,16384,15464,14596,13777};
506 
xmpPlayTick(void)507 static void xmpPlayTick(void)
508 {
509 	int i;
510 	struct xmpsample *sm;
511 	int vol, pan;
512 
513 	if (firstspeed)
514 	{
515 		mcpSet(-1, mcpGSpeed, firstspeed);
516 		firstspeed=0;
517 	}
518 
519 	cmdtime=mcpGet(-1, mcpGCmdTimer);
520 	ReadQue();
521 
522 	tick0=0;
523 	for (i=0; i<nchan; i++)
524 	{
525 		struct channel *ch=&channels[i];
526 		ch->chFinalVol=ch->chVol;
527 		ch->chFinalPan=ch->chPan;
528 		ch->chFinalPitch=ch->chPitch;
529 		ch->nextstop=0;
530 		ch->nextsamp=-1;
531 		ch->nextpos=-1;
532 	}
533 
534 	curtick++;
535 	if (curtick>=curtempo)
536 		curtick=0;
537 
538 	if (!curtick&&patdelay)
539 	{
540 		if (jumptoord!=-1)
541 		{
542 			if (jumptoord!=curord)
543 				for (i=0; i<nchan; i++)
544 				{
545 					struct channel *ch=&channels[i];
546 					ch->chPatLoopCount=0;
547 					ch->chPatLoopStart=0;
548 				}
549 
550 			if (jumptoord>=nord)
551 			{
552 				jumptoord=loopord;
553 				if (!usersetpos)
554 					looped=1;
555 			}
556 			if ((jumptoord<curord)&&!usersetpos)
557 				looped=1;
558 			usersetpos=0;
559 
560 			curord=jumptoord;
561 			currow=jumptorow;
562 			jumptoord=-1;
563 			jumptorow=0;
564 			patlen=patlens[orders[curord]];
565 			patptr=patterns[orders[curord]];
566 		}
567 	}
568 
569 	if (!curtick && (!patdelay || ismod))
570 	{
571 		// no more ticks, we need to step
572 		tick0=1;
573 
574 		if (!patdelay)
575 		{
576 			currow++;
577 			// no jump configured? and at the end of row? jump to the next order, and start fresh
578 			if ((jumptoord==-1)&&(currow>=patlen))
579 			{
580 				jumptoord=curord+1;
581 				jumptorow=nextpatternrow;
582 				nextpatternrow=0;
583 			}
584 			// jump is configured
585 			if (jumptoord!=-1)
586 			{
587 				// jump is not the same order.. (jump is not caused by a loop)
588 				if (jumptoord!=curord)
589 					for (i=0; i<nchan; i++)
590 					{ // reset all loop counters
591 						struct channel *ch=&channels[i];
592 						ch->chPatLoopCount=0;
593 						ch->chPatLoopStart=0;
594 					}
595 
596 				// jumping into/beyond EOF, loop module
597 				if (jumptoord>=nord)
598 				{
599 					jumptoord=loopord;
600 				}
601 				// if jump is backwards, song has globally looped, flag it for the UI
602 				if ((jumptoord<curord)&&!usersetpos)
603 					looped=1;
604 				usersetpos=0;
605 
606 				// take the position, and clear jumptoord
607 				curord=jumptoord;
608 				currow=jumptorow;
609 				jumptoord=-1;
610 				jumptorow=0;
611 				patlen=patlens[orders[curord]];
612 				patptr=patterns[orders[curord]];
613 			}
614 		}
615 
616 		for (i=0; i<nchan; i++)
617 		{
618 			struct channel *ch=&channels[i];
619 
620 			ch->notehit=0;
621 			ch->volslide=0;
622 			ch->pitchslide=0;
623 			ch->panslide=0;
624 			ch->pitchfx=0;
625 			ch->volfx=0;
626 			ch->notefx=0;
627 			ch->fx=0;
628 
629 			procnot=patptr[nchan*currow+i][0];
630 			procins=patptr[nchan*currow+i][1];
631 			procvol=patptr[nchan*currow+i][2];
632 			proccmd=patptr[nchan*currow+i][3];
633 			procdat=patptr[nchan*currow+i][4];
634 
635 			if (!patdelay)
636 			{
637 				if (procnot==97)
638 					procins=0;
639 				if (procins && procins<=ninst)
640 				{
641 					ch->chLastIns=ch->chCurIns;
642 					ch->chCurIns=procins;
643 				}
644 				if (procins<=ninst)
645 					PlayNote(ch);
646 			}
647 
648 			ch->chVCommand=procvol>>4;
649 
650 			switch (ch->chVCommand)
651 			{
652 				case xmpVCmdVol0x: case xmpVCmdVol1x: case xmpVCmdVol2x: case xmpVCmdVol3x:
653 					if ((proccmd!=xmpCmdDelayNote)||!procdat)
654 						ch->chFinalVol=ch->chVol=procvol-0x10;
655 					break;
656 				case xmpVCmdVol40:
657 					if ((proccmd!=xmpCmdDelayNote)||!procdat)
658 						ch->chFinalVol=ch->chVol=0x40;
659 					break;
660 				case xmpVCmdVolSlideD: case xmpVCmdVolSlideU: case xmpVCmdPanSlideL: case xmpVCmdPanSlideR:
661 					ch->chVVolPanSlideVal=procvol&0xF;
662 					break;
663 				case xmpVCmdFVolSlideD:
664 					if ((proccmd!=xmpCmdDelayNote)||!procdat)
665 						ch->chFinalVol=ch->chVol=volrange(ch->chVol-(procvol&0xF));
666 					ch->fx=xfxRowVolSlideDown;
667 					break;
668 				case xmpVCmdFVolSlideU:
669 					if ((proccmd!=xmpCmdDelayNote)||!procdat)
670 						ch->chFinalVol=ch->chVol=volrange(ch->chVol+(procvol&0xF));
671 					ch->fx=xfxRowVolSlideUp;
672 					break;
673 				case xmpVCmdVibRate:
674 					if (procvol&0xF)
675 						ch->chVibRate=((procvol&0xF)<<2);
676 					break;
677 				case xmpVCmdVibDep:
678 					ch->pitchfx=xfxPXVibrato;
679 					if (procvol&0xF)
680 						ch->chVibDep=((procvol&0xF)<<(1+!linearfreq));
681 					break;
682 				case xmpVCmdPanning:
683 					if ((proccmd!=xmpCmdDelayNote)||!procdat)
684 						ch->chFinalPan=ch->chPan=(procvol&0xF)*0x11;
685 					break;
686 				case xmpVCmdPortaNote:
687 					ch->pitchslide=xfxPSToNote;
688 					if (procvol&0xF)
689 						ch->chPortaToVal=(procvol&0xF)<<8;
690 					break;
691 			}
692 
693 			ch->chCommand=proccmd;
694 			switch (ch->chCommand)
695 			{
696 				case xmpCmdArpeggio:
697 					if (!procdat)
698 						ch->chCommand=0xFF;
699 					else {
700 						ch->pitchfx=xfxPXArpeggio;
701 						ch->fx=xfxArpeggio;
702 					}
703 					ch->chArpNotes[0]=0;
704 					ch->chArpNotes[1]=procdat>>4;
705 					ch->chArpNotes[2]=procdat&0xF;
706 					break;
707 				case xmpCmdPortaU:
708 					if (procdat)
709 						ch->chPortaUVal=procdat<<4;
710 					ch->pitchslide=xfxPSUp;
711 					ch->fx=xfxPitchSlideUp;
712 					break;
713 				case xmpCmdPortaD:
714 					if (procdat)
715 						ch->chPortaDVal=procdat<<4;
716 					ch->pitchslide=xfxPSDown;
717 					ch->fx=xfxPitchSlideDown;
718 					break;
719 				case xmpCmdPortaNote:
720 					if (procdat)
721 						ch->chPortaToVal=procdat<<4;
722 					ch->pitchslide=xfxPSToNote;
723 					ch->fx=xfxPitchSlideToNote;
724 					break;
725 				case xmpCmdVibrato:
726 					ch->pitchfx=xfxPXVibrato;
727 					ch->fx=xfxPitchVibrato;
728 					if (procdat&0xF)
729 						ch->chVibDep=(procdat&0xF)<<(1+!linearfreq);
730 					if (procdat&0xF0)
731 						ch->chVibRate=(procdat>>4)<<2;
732 					break;
733 				case xmpCmdPortaVol: case xmpCmdVibVol: case xmpCmdVolSlide:
734 					if (procdat || ismod)
735 						ch->chVolSlideVal=procdat;
736 					if (ch->chVolSlideVal&0xf0)
737 					{
738 						ch->volslide=xfxVSUp;
739 						ch->fx=xfxVolSlideUp;
740 					} else if (ch->chVolSlideVal&0x0f)
741 					{
742 						ch->volslide=xfxVSDown;
743 						ch->fx=xfxVolSlideDown;
744 					}
745 					break;
746 				case xmpCmdTremolo:
747 					ch->volfx=xfxVXVibrato;
748 					ch->fx=xfxVolVibrato;
749 					if (procdat&0xF)
750 						ch->chTremDep=(procdat&0xF)<<2;
751 					if (procdat&0xF0)
752 						ch->chTremRate=(procdat>>4)<<2;
753 					break;
754 				case xmpCmdPanning:
755 					ch->chFinalPan=ch->chPan=procdat;
756 					break;
757 				case xmpCmdJump:
758 					if (!patdelay)
759 					{
760 						jumptoord=procdat;
761 						jumptorow=0;
762 						nextpatternrow=0;
763 					}
764 					break;
765 				case xmpCmdVolume:
766 					ch->chFinalVol=ch->chVol=volrange(procdat);
767 					break;
768 				case xmpCmdBreak:
769 					if (!patdelay)
770 					{
771 						if (jumptoord==-1)
772 							jumptoord=curord+1;
773 						jumptorow=(procdat&0xF)+(procdat>>4)*10;
774 						nextpatternrow=0;
775 					}
776 					break;
777 				case xmpCmdSpeed:
778 					if (!procdat)
779 					{
780 						jumptoord=0;
781 						jumptorow=0;
782 						break;
783 					}
784 					if (procdat>=0x20)
785 					{
786 						curbpm=procdat;
787 						mcpSet(-1, mcpGSpeed, 256*2*curbpm/5);
788 						putque(queTempo, -1, curbpm);
789 					} else {
790 						curtempo=procdat;
791 						putque(queSpeed, -1, curtempo);
792 					}
793 					break;
794 				case xmpCmdMODtTempo:
795 					if (!procdat)
796 					{
797 						jumptoord=procdat;
798 						jumptorow=0;
799 					} else {
800 						curtempo=procdat;
801 						putque(queSpeed, -1, curtempo);
802 					}
803 					break;
804 				case xmpCmdGVolume:
805 					globalvol=volrange(procdat);
806 					putque(queGVol, -1, globalvol);
807 					break;
808 				case xmpCmdGVolSlide:
809 					if (procdat)
810 						ch->chGVolSlideVal=procdat;
811 					if (ch->chGVolSlideVal&0xf0)
812 						globalfx=xfxGVSUp;
813 					else if (ch->chGVolSlideVal&0x0f)
814 						globalfx=xfxGVSDown;
815 					break;
816 				case xmpCmdKeyOff:
817 					ch->chActionTick=procdat;
818 					break;
819 				case xmpCmdRetrigger:
820 					ch->notefx=xfxNXRetrig;
821 					ch->fx=xfxRetrig;
822 					ch->chActionTick=procdat;
823 					break;
824 				case xmpCmdNoteCut:
825 					ch->notefx=xfxNXNoteCut;
826 					ch->fx=xfxNoteCut;
827 					ch->chActionTick=procdat;
828 					break;
829 				case xmpCmdEnvPos:
830 					ch->chVolEnvPos=ch->chPanEnvPos=procdat;
831 					ch->fx=xfxEnvPos;
832 					if (ch->cursamp)
833 					{
834 						if (ch->cursamp->volenv<nenv)
835 							if (ch->chVolEnvPos>envelopes[ch->cursamp->volenv].len)
836 								ch->chVolEnvPos=envelopes[ch->cursamp->volenv].len;
837 						if (ch->cursamp->panenv<nenv)
838 							if (ch->chPanEnvPos>envelopes[ch->cursamp->panenv].len)
839 								ch->chPanEnvPos=envelopes[ch->cursamp->panenv].len;
840 					} else
841 						fprintf(stderr, __FILE__ " CmdEnvPos ch->cursamp not set\n");
842 					break;
843 				case xmpCmdPanSlide:
844 					if (procdat)
845 						ch->chPanSlideVal=procdat;
846 					if (ch->chPanSlideVal&0xF0)
847 						ch->panslide=xfxPnSLeft;
848 					else if (ch->chPanSlideVal&0x0F)
849 						ch->panslide=xfxPnSRight;
850 					break;
851 				case xmpCmdMRetrigger:
852 					ch->notefx=xfxNXRetrig;
853 					ch->fx=xfxRetrig;
854 					if (procdat)
855 					{
856 						ch->chMRetrigLen=procdat&0xF;
857 						ch->chMRetrigAct=procdat>>4;
858 					}
859 					break;
860 				case xmpCmdSync1: case xmpCmdSync2: case xmpCmdSync3:
861 					putque(queSync, i, procdat);
862 					break;
863 				case xmpCmdTremor:
864 					ch->volfx=xfxVXTremor;
865 					ch->fx=xfxTremor;
866 					if (procdat)
867 					{
868 						ch->chTremorLen=(procdat&0xF)+(procdat>>4)+2;
869 						ch->chTremorOff=(procdat>>4)+1;
870 						ch->chTremorPos=0;
871 					}
872 					break;
873 				case xmpCmdXPorta:
874 					if ((procdat>>4)==1)
875 					{
876 						if (procdat&0xF)
877 							ch->chXFinePortaUVal=procdat&0xF;
878 						ch->chFinalPitch=ch->chPitch=freqrange(ch->chPitch-(ch->chXFinePortaUVal<<2));
879 					} else if ((procdat>>4)==2)
880 					{
881 						if (procdat&0xF)
882 							ch->chXFinePortaDVal=procdat&0xF;
883 						ch->chFinalPitch=ch->chPitch=freqrange(ch->chPitch+(ch->chXFinePortaDVal<<2));
884 					}
885 					break;
886 				case xmpCmdFPortaU:
887 					if (procdat)
888 						ch->chFinePortaUVal=procdat;
889 					ch->fx=xfxRowPitchSlideUp;
890 					ch->chFinalPitch=ch->chPitch=freqrange(ch->chPitch-(ch->chFinePortaUVal<<4));
891 					break;
892 				case xmpCmdFPortaD:
893 					if (procdat)
894 						ch->chFinePortaDVal=procdat;
895 					ch->fx=xfxRowPitchSlideDown;
896 					ch->chFinalPitch=ch->chPitch=freqrange(ch->chPitch+(ch->chFinePortaDVal<<4));
897 					break;
898 				case xmpCmdGlissando:
899 					ch->chGlissando=procdat;
900 					break;
901 				case xmpCmdVibType:
902 					ch->chVibType=procdat&3;
903 					break;
904 				case xmpCmdPatLoop:
905 					/* if(plLoopPatterns)*/ /* TODO ?? */
906 					{
907 						if (!procdat)
908 						{
909 							ch->chPatLoopStart=currow;
910 							if (ft2_e60bug)
911 							{
912 								nextpatternrow=currow;
913 							}
914 						} else {
915 							ch->chPatLoopCount++;
916 							if (ch->chPatLoopCount<=procdat)
917 							{
918 								jumptorow=ch->chPatLoopStart;
919 								jumptoord=curord;
920 							} else {
921 								ch->chPatLoopCount=0;
922 								ch->chPatLoopStart=currow+1;
923 							}
924 						}
925 					}
926 					break;
927 				case xmpCmdTremType:
928 					ch->chTremType=procdat&3;
929 					break;
930 				case xmpCmdSPanning:
931 					ch->chFinalPan=ch->chPan=procdat*0x11;
932 					break;
933 				case xmpCmdFVolSlideU:
934 					if (procdat || ismod )
935 						ch->chFineVolSlideUVal=procdat;
936 					ch->fx=xfxRowVolSlideUp;
937 					ch->chFinalVol=ch->chVol=volrange(ch->chVol+ch->chFineVolSlideUVal);
938 					break;
939 				case xmpCmdFVolSlideD:
940 					if (procdat || ismod )
941 						ch->chFineVolSlideDVal=procdat;
942 					ch->fx=xfxRowVolSlideDown;
943 					ch->chFinalVol=ch->chVol=volrange(ch->chVol-ch->chFineVolSlideDVal);
944 					break;
945 				case xmpCmdPatDelay:
946 					if (!patdelay)
947 						patdelay=procdat+1;
948 					break;
949 				case xmpCmdDelayNote:
950 					if (procnot)
951 						ch->chDelayNote=procnot;
952 					ch->fx=xfxDelay;
953 					ch->notefx=xfxNXDelay;
954 					ch->chDelayIns=procins;
955 					ch->chDelayVol=procvol;
956 					ch->chActionTick=procdat;
957 					break;
958 			}
959 		}
960 	}
961 	if (!curtick&&patdelay)
962 	{
963 		patdelay--;
964 	}
965 
966 	for (i=0; i<nchan; i++)
967 	{
968 		struct channel *ch=&channels[i];
969 
970 		switch (ch->chVCommand)
971 		{
972 			case xmpVCmdVolSlideD:
973 				ch->volslide=xfxVSDown;
974 				if (tick0)
975 					break;
976 				ch->chFinalVol=ch->chVol=volrange(ch->chVol-ch->chVVolPanSlideVal);
977 				break;
978 			case xmpVCmdVolSlideU:
979 				ch->volslide=xfxVSUp;
980 				if (tick0)
981 					break;
982 				ch->chFinalVol=ch->chVol=volrange(ch->chVol+ch->chVVolPanSlideVal);
983 				break;
984 			case xmpVCmdVibDep:  /* FICKEN */
985 				switch (ch->chVibType)
986 				{
987 					case 0:
988 						ch->chFinalPitch=freqrange((( sintab[ch->chVibPos] *ch->chVibDep)>>7)+ch->chPitch);
989 						break;
990 					case 1:
991 						ch->chFinalPitch=freqrange((( (ch->chVibPos-0x80)   *ch->chVibDep)>>3)+ch->chPitch);
992 						break;
993 					case 2:
994 						ch->chFinalPitch=freqrange((( ((ch->chVibPos&0x80)-0x40) *ch->chVibDep)>>2)+ch->chPitch);
995 						break;
996 				}
997 				if (!tick0)
998 					ch->chVibPos+=ch->chVibRate;
999 				break;
1000 			case xmpVCmdPanSlideL:
1001 				if (tick0)
1002 					break;
1003 				ch->chFinalPan=ch->chPan=panrange(ch->chPan-ch->chVVolPanSlideVal);
1004 				break;
1005 			case xmpVCmdPanSlideR:
1006 				if (tick0)
1007 					break;
1008 				ch->chFinalPan=ch->chPan=panrange(ch->chPan+ch->chVVolPanSlideVal);
1009 				break;
1010 			case xmpVCmdPortaNote:
1011 				if (!tick0)
1012 				{
1013 					if (ch->chPitch<ch->chPortaToPitch)
1014 					{
1015 						ch->chPitch+=ch->chPortaToVal;
1016 						if (ch->chPitch>ch->chPortaToPitch)
1017 							ch->chPitch=ch->chPortaToPitch;
1018 					} else {
1019 						ch->chPitch-=ch->chPortaToVal;
1020 						if (ch->chPitch<ch->chPortaToPitch)
1021 							ch->chPitch=ch->chPortaToPitch;
1022 					}
1023 				}
1024 				if (ch->chGlissando)
1025 				{
1026 					if (linearfreq)
1027 					{
1028 						ch->chFinalPitch=((ch->chPitch+ch->chCurNormNote+0x80)&~0xFF)-ch->chCurNormNote;
1029 					} else {
1030 						ch->chFinalPitch=mcpGetFreq6848(((mcpGetNote6848(ch->chPitch)+ch->chCurNormNote+0x80)&~0xFF)-ch->chCurNormNote);
1031 					}
1032 				} else
1033 					ch->chFinalPitch=ch->chPitch;
1034 				break;
1035 		}
1036 
1037 		switch (ch->chCommand)
1038 		{
1039 			case xmpCmdArpeggio:
1040 				if (linearfreq)
1041 					ch->chFinalPitch=freqrange(ch->chPitch-(ch->chArpNotes[ch->chArpPos]<<8));
1042 				else
1043 					ch->chFinalPitch=freqrange((ch->chPitch*notetab[ch->chArpNotes[ch->chArpPos]])>>15);
1044 				ch->chArpPos++;
1045 				if (ch->chArpPos==3)
1046 					ch->chArpPos=0;
1047 				break;
1048 			case xmpCmdPortaU:
1049 				if (tick0)
1050 					break;
1051 				ch->chFinalPitch=ch->chPitch=freqrange(ch->chPitch-ch->chPortaUVal);
1052 				break;
1053 			case xmpCmdPortaD:
1054 				if (tick0)
1055 					break;
1056 				ch->chFinalPitch=ch->chPitch=freqrange(ch->chPitch+ch->chPortaDVal);
1057 				break;
1058 			case xmpCmdPortaNote:
1059 				if (!tick0)
1060 				{
1061 					if (ch->chPitch<ch->chPortaToPitch)
1062 					{
1063 						ch->chPitch+=ch->chPortaToVal;
1064 						if (ch->chPitch>ch->chPortaToPitch)
1065 							ch->chPitch=ch->chPortaToPitch;
1066 					} else {
1067 						ch->chPitch-=ch->chPortaToVal;
1068 						if (ch->chPitch<ch->chPortaToPitch)
1069 							ch->chPitch=ch->chPortaToPitch;
1070 					}
1071 				}
1072 				if (ch->chGlissando)
1073 				{
1074 					if (linearfreq)
1075 						ch->chFinalPitch=((ch->chPitch+ch->chCurNormNote+0x80)&~0xFF)-ch->chCurNormNote;
1076 					else
1077 						ch->chFinalPitch=mcpGetFreq6848(((mcpGetNote6848(ch->chPitch)+ch->chCurNormNote+0x80)&~0xFF)-ch->chCurNormNote);
1078 				} else
1079 					ch->chFinalPitch=ch->chPitch;
1080 				break;
1081 			case xmpCmdVibrato:
1082 				switch (ch->chVibType)
1083 				{
1084 					case 0:
1085 						ch->chFinalPitch=freqrange((( sintab[ch->chVibPos] *ch->chVibDep)>>8)+ch->chPitch);
1086 						break;
1087 					case 1:
1088 						ch->chFinalPitch=freqrange((( (ch->chVibPos-0x80)   *ch->chVibDep)>>4)+ch->chPitch);
1089 						break;
1090 					case 2:
1091 						ch->chFinalPitch=freqrange((( ((ch->chVibPos&0x80)-0x40) *ch->chVibDep)>>3)+ch->chPitch);
1092 						break;
1093 				}
1094 				if (!tick0)
1095 					ch->chVibPos+=ch->chVibRate;
1096 				break;
1097 			case xmpCmdPortaVol:
1098 				if (!tick0)
1099 				{
1100 					if (ch->chPitch<ch->chPortaToPitch)
1101 					{
1102 						ch->chPitch+=ch->chPortaToVal;
1103 						if (ch->chPitch>ch->chPortaToPitch)
1104 							ch->chPitch=ch->chPortaToPitch;
1105 					} else {
1106 						ch->chPitch-=ch->chPortaToVal;
1107 						if (ch->chPitch<ch->chPortaToPitch)
1108 							ch->chPitch=ch->chPortaToPitch;
1109 					}
1110 				}
1111 				if (ch->chGlissando)
1112 				{
1113 					if (linearfreq)
1114 						ch->chFinalPitch=((ch->chPitch+ch->chCurNormNote+0x80)&~0xFF)-ch->chCurNormNote;
1115 					else
1116 						ch->chFinalPitch=mcpGetFreq6848(((mcpGetNote6848(ch->chPitch)+ch->chCurNormNote+0x80)&~0xFF)-ch->chCurNormNote);
1117 				} else
1118 					ch->chFinalPitch=ch->chPitch;
1119 
1120 				if (tick0)
1121 					break;
1122 				ch->chFinalVol=ch->chVol=volrange(ch->chVol+((ch->chVolSlideVal&0xF0)?(ch->chVolSlideVal>>4):-(ch->chVolSlideVal&0xF)));
1123 				break;
1124 			case xmpCmdVibVol:
1125 				switch (ch->chVibType)
1126 				{
1127 					case 0:
1128 						ch->chFinalPitch=freqrange((( sintab[ch->chVibPos] *ch->chVibDep)>>8)+ch->chPitch);
1129 						break;
1130 					case 1:
1131 						ch->chFinalPitch=freqrange((( (ch->chVibPos-0x80)   *ch->chVibDep)>>4)+ch->chPitch);
1132 						break;
1133 					case 2:
1134 						ch->chFinalPitch=freqrange((( ((ch->chVibPos&0x80)-0x40) *ch->chVibDep)>>3)+ch->chPitch);
1135 						break;
1136 				}
1137 				if (!tick0)
1138 					ch->chVibPos+=ch->chVibRate;
1139 
1140 				if (tick0)
1141 					break;
1142 				ch->chFinalVol=ch->chVol=volrange(ch->chVol+((ch->chVolSlideVal&0xF0)?(ch->chVolSlideVal>>4):-(ch->chVolSlideVal&0xF)));
1143 				break;
1144 			case xmpCmdTremolo:
1145 				switch (ch->chTremType)
1146 				{
1147 					case 0:
1148 						ch->chFinalVol+=(( sintab[ch->chTremPos] *ch->chTremDep)>>11);
1149 						break;
1150 					case 1:
1151 						ch->chFinalVol+=(( (ch->chTremPos-0x80)   *ch->chTremDep)>>7);
1152 						break;
1153 					case 2:
1154 						ch->chFinalVol+=(( ((ch->chTremPos&0x80)-0x40) *ch->chTremDep)>>6);
1155 						break;
1156 				}
1157 				ch->chFinalVol=volrange(ch->chFinalVol);
1158 				if (!tick0)
1159 					ch->chTremPos+=ch->chTremRate;
1160 				break;
1161 			case xmpCmdVolSlide:
1162 				if (tick0)
1163 					break;
1164 				ch->chFinalVol=ch->chVol=volrange(ch->chVol+((ch->chVolSlideVal&0xF0)?(ch->chVolSlideVal>>4):-(ch->chVolSlideVal&0xF)));
1165 				break;
1166 			case xmpCmdGVolSlide:
1167 				if (tick0)
1168 					break;
1169 				if (ch->chGVolSlideVal&0xF0)
1170 					globalvol=volrange(globalvol+(ch->chGVolSlideVal>>4));
1171 				else
1172 					globalvol=volrange(globalvol-(ch->chGVolSlideVal&0xF));
1173 				putque(queGVol, -1, globalvol);
1174 				break;
1175 			case xmpCmdKeyOff:
1176 				if (tick0)
1177 					break;
1178 				if (curtick==ch->chActionTick)
1179 				{
1180 					ch->chSustain=0;
1181 					if (ch->cursamp&&(ch->cursamp->volenv>=nenv))
1182 						ch->chFadeVol=0;
1183 				}
1184 				break;
1185 			case xmpCmdPanSlide:
1186 				if (tick0)
1187 					break;
1188 				ch->chFinalPan=ch->chPan=panrange(ch->chPan+((ch->chPanSlideVal&0xF0)?(ch->chPanSlideVal>>4):-(ch->chPanSlideVal&0xF)));
1189 				break;
1190 			case xmpCmdMRetrigger:
1191 				if (ch->chMRetrigPos++!=ch->chMRetrigLen)
1192 					break;
1193 				ch->chMRetrigPos=1;
1194 				ch->nextpos=0;
1195 				ch->chVolEnvPos=0;
1196 				ch->chPanEnvPos=0;
1197 
1198 				switch (ch->chMRetrigAct)
1199 				{
1200 					case 0: case 8: break;
1201 					case 1: case 2: case 3: case 4: case 5:
1202 							ch->chVol=ch->chVol-(1<<(ch->chMRetrigAct-1));
1203 							break;
1204 					case 9: case 10: case 11: case 12: case 13:
1205 							ch->chVol=ch->chVol+(1<<(ch->chMRetrigAct-9));
1206 							break;
1207 					case 6:  ch->chVol=(ch->chVol*5)>>3; break;
1208 					case 14: ch->chVol=(ch->chVol*3)>>1; break;
1209 					case 7:  ch->chVol>>=1; break;
1210 					case 15: ch->chVol<<=1; break;
1211 				}
1212 				ch->chFinalVol=ch->chVol=volrange(ch->chVol);
1213 				break;
1214 			case xmpCmdTremor:
1215 				if (ch->chTremorPos>=ch->chTremorOff)
1216 					ch->chFinalVol=0;
1217 				if (tick0)
1218 					break;
1219 				ch->chTremorPos++;
1220 				if (ch->chTremorPos==ch->chTremorLen)
1221 					ch->chTremorPos=0;
1222 				break;
1223 			case xmpCmdRetrigger:
1224 				if (!ch->chActionTick)
1225 					break;
1226 				if (!(curtick%ch->chActionTick))
1227 				{
1228 					ch->nextpos=0;
1229 					ch->chVolEnvPos=0;
1230 					ch->chPanEnvPos=0;
1231 				}
1232 
1233 				break;
1234 			case xmpCmdNoteCut:
1235 				if (tick0)
1236 					break;
1237 				if (curtick==ch->chActionTick)
1238 					ch->chFinalVol=ch->chVol=0;
1239 				break;
1240 			case xmpCmdDelayNote:
1241 				if (tick0)
1242 					break;
1243 				if (curtick!=ch->chActionTick)
1244 					break;
1245 				procnot=ch->chDelayNote;
1246 				procins=ch->chDelayIns;
1247 				proccmd=0;
1248 				procdat=0;
1249 				procvol=0;
1250 				PlayNote(ch);
1251 				switch (ch->chDelayVol>>4)
1252 				{
1253 					case xmpVCmdVol0x: case xmpVCmdVol1x: case xmpVCmdVol2x: case xmpVCmdVol3x:
1254 						ch->chFinalVol=ch->chVol=ch->chDelayVol-0x10;
1255 						break;
1256 					case xmpVCmdVol40:
1257 						ch->chFinalVol=ch->chVol=0x40;
1258 						break;
1259 					case xmpVCmdPanning:
1260 						ch->chFinalPan=ch->chPan=(ch->chDelayVol&0xF)*0x11;
1261 						break;
1262 				}
1263 				break;
1264 		}
1265 
1266 		if (!ch->cursamp)
1267 		{
1268 			mcpSet(i, mcpCStatus, 0);
1269 			continue;
1270 		}
1271 
1272 		sm=ch->cursamp;
1273 
1274 		vol=(ch->chFinalVol*globalvol)>>4;
1275 		pan=ch->chFinalPan-128;
1276 		if (!ch->chSustain)
1277 		{
1278 			vol=(vol*ch->chFadeVol)>>15;
1279 			if (ch->chFadeVol>=sm->volfade)
1280 				ch->chFadeVol-=sm->volfade;
1281 			else
1282 				ch->chFadeVol=0;
1283 		}
1284 
1285 		if (sm->volenv<nenv)
1286 		{
1287 			const struct xmpenvelope *env=&envelopes[sm->volenv];
1288 			vol=(env->env[ch->chVolEnvPos]*vol)>>8;
1289 
1290 			if (ch->chVolEnvPos<env->len)
1291 				if  (!ch->chSustain || !(env->type&xmpEnvSLoop) || ch->chVolEnvPos!=env->sustain)
1292 				{
1293 					ch->chVolEnvPos++;
1294 					if (env->type&xmpEnvLoop)
1295 					{
1296 						if (ch->chVolEnvPos==env->loope && (ch->chSustain || env->loope!=env->sustain))
1297 							ch->chVolEnvPos=env->loops;
1298 					}
1299 				}
1300 		}
1301 
1302 		if (sm->panenv<nenv)
1303 		{
1304 			const struct xmpenvelope *env=&envelopes[sm->panenv];
1305 			pan+=((env->env[ch->chPanEnvPos]-128)*(128-((pan<0)?-pan:pan)))>>7;
1306 
1307 			if (ch->chPanEnvPos<env->len)
1308 				if  (!ch->chSustain || !(env->type&xmpEnvSLoop) || ch->chPanEnvPos!=env->sustain)
1309 				{
1310 					ch->chPanEnvPos++;
1311 					if (env->type&xmpEnvLoop)
1312 					{
1313 						if (ch->chVolEnvPos==env->loope && (ch->chSustain || env->loope!=env->sustain))
1314 							ch->chPanEnvPos=env->loops;
1315 					}
1316 				}
1317 		}
1318 
1319 		if (sm->vibrate&&sm->vibdepth)
1320 		{
1321 			int dep=0;
1322 			switch (sm->vibtype)
1323 			{
1324 				case 0:
1325 					dep=(sintab[ch->chAVibPos>>8]*sm->vibdepth)>>11;
1326 					break;
1327 				case 1:
1328 					dep=(ch->chAVibPos&0x8000)?-sm->vibdepth:sm->vibdepth;
1329 					break;
1330 				case 2:
1331 					dep=(sm->vibdepth*(32768-ch->chAVibPos))>>14;
1332 					break;
1333 				case 3:
1334 					dep=(sm->vibdepth*(ch->chAVibPos-32768))>>14;
1335 					break;
1336 			}
1337 
1338 			ch->chAVibSwpPos+=sm->vibsweep;
1339 			if (ch->chAVibSwpPos>0x10000)
1340 				ch->chAVibSwpPos=0x10000;
1341 			dep=(dep*(int)ch->chAVibSwpPos)>>17;
1342 
1343 			ch->chFinalPitch-=dep;
1344 
1345 			ch->chAVibPos+=sm->vibrate;
1346 		}
1347 
1348 		if (ch->nextstop)
1349 			mcpSet(i, mcpCStatus, 0);
1350 		if (ch->nextsamp!=(unsigned)-1)
1351 			mcpSet(i, mcpCInstrument, ch->nextsamp);
1352 		if (ch->nextpos!=(unsigned)-1)
1353 		{
1354 			mcpSet(i, mcpCPosition, ch->nextpos);
1355 			mcpSet(i, mcpCLoop, 1);
1356 			mcpSet(i, mcpCDirect, 0);
1357 			mcpSet(i, mcpCStatus, 1);
1358 		}
1359 		if (linearfreq)
1360 			mcpSet(i, mcpCPitch, -ch->chFinalPitch);
1361 		else
1362 			mcpSet(i, mcpCPitch6848, ch->chFinalPitch);
1363 		mcpSet(i, mcpCVolume, (looping||!looped)?vol:0);
1364 		mcpSet(i, mcpCPanning, pan);
1365 		mcpSet(i, mcpCMute, mutech[i]);
1366 	}
1367 	putque(quePos, -1, curtick|(curord<<16)|(currow<<8));
1368 }
1369 
xmpGetRealPos(void)1370 int __attribute__ ((visibility ("internal"))) xmpGetRealPos(void)
1371 {
1372 	ReadQue();
1373 	return realpos;
1374 }
1375 
xmpChanActive(int ch)1376 int __attribute__ ((visibility ("internal"))) xmpChanActive(int ch)
1377 {
1378 	return mcpGet(ch, mcpCStatus)&&channels[ch].cursamp&&channels[ch].chVol&&channels[ch].chFadeVol;
1379 }
1380 
xmpGetChanIns(int ch)1381 int __attribute__ ((visibility ("internal"))) xmpGetChanIns(int ch)
1382 {
1383 	return channels[ch].chCurIns;
1384 }
1385 
xmpGetChanSamp(int ch)1386 int __attribute__ ((visibility ("internal"))) xmpGetChanSamp(int ch)
1387 {
1388 	if (!channels[ch].cursamp)
1389 		return 0xFFFF;
1390 	return channels[ch].cursamp-samples;
1391 }
1392 
xmpGetDotsData(int ch,int * smp,int * frq,int * voll,int * volr,int * sus)1393 int __attribute__ ((visibility ("internal"))) xmpGetDotsData(int ch, int *smp, int *frq, int *voll, int *volr, int *sus)
1394 {
1395 	struct channel *c;
1396 
1397 	if (!mcpGet(ch, mcpCStatus))
1398 		return 0;
1399 	c=&channels[ch];
1400 	if (!c->cursamp||!c->chVol||!c->chFadeVol)
1401 		return 0;
1402 	*smp=c->cursamp-samples;
1403 	if (linearfreq)
1404 		*frq=60*256+c->cursamp->normnote-freqrange(c->chFinalPitch);
1405 	else
1406 		*frq=60*256+c->cursamp->normnote+mcpGetNote8363(6848*8363/freqrange(c->chFinalPitch));
1407 	mcpGetRealVolume(ch, voll, volr);
1408 	*sus=c->chSustain;
1409 	return 1;
1410 }
1411 
xmpGetRealVolume(int ch,int * voll,int * volr)1412 void __attribute__ ((visibility ("internal"))) xmpGetRealVolume(int ch, int *voll, int *volr)
1413 {
1414 	mcpGetRealVolume(ch, voll, volr);
1415 }
1416 
xmpGetPos(void)1417 uint16_t __attribute__ ((visibility ("internal"))) xmpGetPos(void)
1418 {
1419 	return (curord<<8)|currow;
1420 }
1421 
xmpSetPos(int ord,int row)1422 void __attribute__ ((visibility ("internal"))) xmpSetPos(int ord, int row)
1423 {
1424 	int i;
1425 
1426 	if (row<0)
1427 		ord--;
1428 	if (ord>=nord)
1429 		ord=0;
1430 	if (ord<0)
1431 	{
1432 		ord=0;
1433 		row=0;
1434 	}
1435 	if (row>=patlens[orders[ord]])
1436 	{
1437 		ord++;
1438 		row=0;
1439 	}
1440 	if (ord>=nord)
1441 		ord=0;
1442 	if (row<0)
1443 	{
1444 		row+=patlens[orders[ord]];
1445 		if (row<0)
1446 			row=0;
1447 	}
1448 	for (i=0; i<nchan; i++)
1449 		mcpSet(i, mcpCReset, 0);
1450 	jumptoord=ord;
1451 	jumptorow=row;
1452 	curtick=curtempo;
1453 	curord=ord;
1454 	currow=row;
1455 	usersetpos=1;
1456 	querpos=0;
1457 	quewpos=0;
1458 	realpos=(curord<<16)|(currow<<8);
1459 }
1460 
xmpGetLChanSample(unsigned int ch,int16_t * b,unsigned int len,uint32_t rate,int opt)1461 int __attribute__ ((visibility ("internal"))) xmpGetLChanSample(unsigned int ch, int16_t *b, unsigned int len, uint32_t rate, int opt)
1462 {
1463 	return mcpGetChanSample(ch, b, len, rate, opt);
1464 }
1465 
xmpMute(int i,int m)1466 void __attribute__ ((visibility ("internal"))) xmpMute(int i, int m)
1467 {
1468 	mutech[i]=m;
1469 }
1470 
xmpLoop(void)1471 int __attribute__ ((visibility ("internal"))) xmpLoop(void)
1472 {
1473 	return looped;
1474 }
1475 
xmpSetLoop(int x)1476 void __attribute__ ((visibility ("internal"))) xmpSetLoop(int x)
1477 {
1478 	looping=x;
1479 }
1480 
xmpLoadSamples(struct xmodule * m)1481 int __attribute__ ((visibility ("internal"))) xmpLoadSamples(struct xmodule *m)
1482 {
1483 	return mcpLoadSamples(m->sampleinfos, m->nsampi);
1484 }
1485 
xmpPlayModule(struct xmodule * m,struct ocpfilehandle_t * file)1486 int __attribute__ ((visibility ("internal"))) xmpPlayModule(struct xmodule *m, struct ocpfilehandle_t *file)
1487 {
1488 	int i;
1489 
1490 	memset(channels, 0, sizeof(channels));
1491 
1492 	looping=1;
1493 	globalvol=0x40;
1494 	realgvol=0x40;
1495 	jumptorow=0;
1496 	jumptoord=0;
1497 	curord=0;
1498 	currow=0;
1499 	realpos=0;
1500 	ninst=m->ninst;
1501 	nord=m->nord;
1502 	nsamp=m->nsamp;
1503 	instruments=m->instruments;
1504 	envelopes=m->envelopes;
1505 	samples=m->samples;
1506 	sampleinfos=m->sampleinfos;
1507 	patterns=m->patterns;
1508 	orders=m->orders;
1509 	patlens=m->patlens;
1510 	linearfreq=m->linearfreq;
1511 	nchan=m->nchan;
1512 	loopord=m->loopord;
1513 	nenv=m->nenv;
1514 	ismod=m->ismod;
1515 	ft2_e60bug=m->ft2_e60bug;
1516 	looped=0;
1517 
1518 	curtempo=m->initempo;
1519 	curtick=m->initempo-1;
1520 
1521 	for (i=0; i<nchan; i++)
1522 	{
1523 		channels[i].chPan=m->panpos[i];
1524 		mutech[i]=0;
1525 	}
1526 
1527 	quelen=100;
1528 	que=malloc(sizeof(int)*quelen*4);
1529 	if (!que)
1530 		return 0;
1531 	querpos=0;
1532 	quewpos=0;
1533 
1534 	curbpm=m->inibpm;
1535 	realtempo=m->inibpm;
1536 	realspeed=m->initempo;
1537 	firstspeed=256*2*curbpm/5;
1538 	if (!mcpOpenPlayer(nchan, xmpPlayTick, file))
1539 		return 0;
1540 
1541 	if (nchan!=mcpNChan)
1542 	{
1543 		mcpClosePlayer();
1544 		return 0;
1545 	}
1546 
1547 	return 1;
1548 }
1549 
xmpStopModule(void)1550 void __attribute__ ((visibility ("internal"))) xmpStopModule(void)
1551 {
1552 	mcpClosePlayer();
1553 	free(que);
1554 }
1555 
xmpGetGlobInfo(int * tmp,int * bpm,int * gvol)1556 void __attribute__ ((visibility ("internal"))) xmpGetGlobInfo(int *tmp, int *bpm, int *gvol)
1557 {
1558 	*tmp=realspeed;
1559 	*bpm=realtempo;
1560 	*gvol=realgvol;
1561 }
1562 
1563 /*
1564 int __attribute__ ((visibility ("internal"))) xmpGetTime(void)
1565 {
1566 	return mcpGet(-1, mcpGTimer);
1567 }*/
1568 
1569 /*int __attribute__ ((visibility ("internal"))) xmpGetSync(int ch, int *time)
1570 {
1571 	ReadQue();
1572 	if ((ch<0)||(ch>=nchan))
1573 	{
1574 		*time=xmpGetTime()-realsynctime;
1575 		return realsync;
1576 	} else {
1577 		*time=xmpGetTime()-channels[ch].chSyncTime;
1578 		return channels[ch].chSync;
1579 	}
1580 }*/
1581 
1582 /*int __attribute__ ((visibility ("internal"))) xmpGetTickTime(void)
1583 {
1584 	ReadQue();
1585 	return 65536*5/(2*realtempo);
1586 }*/
1587 
1588 /*int __attribute__ ((visibility ("internal"))) xmpGetRowTime(void)
1589 {
1590 	ReadQue();
1591 	return 65536*5*realspeed/(2*realtempo);
1592 }*/
1593 
1594 /*void __attribute__ ((visibility ("internal"))) xmpSetEvPos(int ch, int pos, int modtype, int mod)
1595 {
1596 	struct channel *c;
1597 	if ((ch<0)||(ch>=nchan))
1598 		return;
1599 	c=&channels[ch];
1600 	c->evpos0=pos;
1601 	c->evmodtype=modtype;
1602 	c->evmod=mod;
1603 	c->evmodpos=0;
1604 	c->evpos=-1;
1605 	c->evtime=-1;
1606 }*/
1607 
1608 /*int __attribute__ ((visibility ("internal"))) xmpGetEvPos(int ch, int *time)
1609 {
1610 	ReadQue();
1611 	if ((ch<0)||(ch>=nchan))
1612 	{
1613 		*time=-1;
1614 		return -1;
1615 	}
1616 	*time=xmpGetTime()-channels[ch].evtime;
1617 	return channels[ch].evpos;
1618 }*/
1619 
1620 /*int __attribute__ ((visibility ("internal"))) xmpFindEvPos(int pos, int *time)
1621 {
1622 	int i;
1623 	ReadQue();
1624 	for (i=0; i<nchan; i++)
1625 		if (channels[i].evpos==pos)
1626 			break;
1627 	*time=xmpGetTime()-channels[i].evtime;
1628 	return channels[i].evpos;
1629 }*/
1630 
xmpGetChanInfo(unsigned char ch,struct xmpchaninfo * ci)1631 void __attribute__ ((visibility ("internal"))) xmpGetChanInfo(unsigned char ch, struct xmpchaninfo *ci)
1632 {
1633 	const struct channel *t=&channels[ch];
1634 	ci->note=t->curnote+11;
1635 	ci->vol=t->chVol;
1636 	if (!t->chFadeVol)
1637 		ci->vol=0;
1638 	ci->pan=t->chPan;
1639 	ci->notehit=t->notehit;
1640 	ci->volslide=t->volslide;
1641 	ci->pitchslide=t->pitchslide;
1642 	ci->panslide=t->panslide;
1643 	ci->volfx=t->volfx;
1644 	ci->pitchfx=t->pitchfx;
1645 	ci->notefx=t->notefx;
1646 	ci->fx=t->fx;
1647 }
1648 
xmpGetGlobInfo2(struct xmpglobinfo * gi)1649 void __attribute__ ((visibility ("internal"))) xmpGetGlobInfo2(struct xmpglobinfo *gi)
1650 {
1651 	gi->globvol=globalvol;
1652 	gi->globvolslide=globalfx;
1653 }
1654