1 /* MikMod sound library
2 (c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of
8 the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 /*==============================================================================
25 The Protracker Player Driver
27 The protracker driver supports all base Protracker 3.x commands and features.
29 ==============================================================================*/
37 #ifdef SRANDOM_IN_MATH_H
43 #include "mikmod_internals.h"
46 extern int fprintf(FILE *, const char *, ...);
47 extern long int random(void);
50 /* The currently playing module */
53 #define NUMVOICES(mod) (md_sngchn < (mod)->numvoices ? md_sngchn : (mod)->numvoices)
55 #define HIGH_OCTAVE 2 /* number of above-range octaves */
57 static const UWORD oldperiods[OCTAVE*2]={
58 0x6b00, 0x6800, 0x6500, 0x6220, 0x5f50, 0x5c80,
59 0x5a00, 0x5740, 0x54d0, 0x5260, 0x5010, 0x4dc0,
60 0x4b90, 0x4960, 0x4750, 0x4540, 0x4350, 0x4160,
61 0x3f90, 0x3dc0, 0x3c10, 0x3a40, 0x38b0, 0x3700
64 static const UBYTE VibratoTable[32]={
65 0, 24, 49, 74, 97,120,141,161,180,197,212,224,235,244,250,253,
66 255,253,250,244,235,224,212,197,180,161,141,120, 97, 74, 49, 24
69 static const UBYTE avibtab[128]={
70 0, 1, 3, 4, 6, 7, 9,10,12,14,15,17,18,20,21,23,
71 24,25,27,28,30,31,32,34,35,36,38,39,40,41,42,44,
72 45,46,47,48,49,50,51,52,53,54,54,55,56,57,57,58,
73 59,59,60,60,61,61,62,62,62,63,63,63,63,63,63,63,
74 64,63,63,63,63,63,63,63,62,62,62,61,61,60,60,59,
75 59,58,57,57,56,55,54,54,53,52,51,50,49,48,47,46,
76 45,44,42,41,40,39,38,36,35,34,32,31,30,28,27,25,
77 24,23,21,20,18,17,15,14,12,10, 9, 7, 6, 4, 3, 1
80 /* Triton's linear periods to frequency translation table (for XM modules) */
81 static const ULONG lintab[768]={
82 535232,534749,534266,533784,533303,532822,532341,531861,
83 531381,530902,530423,529944,529466,528988,528511,528034,
84 527558,527082,526607,526131,525657,525183,524709,524236,
85 523763,523290,522818,522346,521875,521404,520934,520464,
86 519994,519525,519057,518588,518121,517653,517186,516720,
87 516253,515788,515322,514858,514393,513929,513465,513002,
88 512539,512077,511615,511154,510692,510232,509771,509312,
89 508852,508393,507934,507476,507018,506561,506104,505647,
90 505191,504735,504280,503825,503371,502917,502463,502010,
91 501557,501104,500652,500201,499749,499298,498848,498398,
92 497948,497499,497050,496602,496154,495706,495259,494812,
93 494366,493920,493474,493029,492585,492140,491696,491253,
94 490809,490367,489924,489482,489041,488600,488159,487718,
95 487278,486839,486400,485961,485522,485084,484647,484210,
96 483773,483336,482900,482465,482029,481595,481160,480726,
97 480292,479859,479426,478994,478562,478130,477699,477268,
98 476837,476407,475977,475548,475119,474690,474262,473834,
99 473407,472979,472553,472126,471701,471275,470850,470425,
100 470001,469577,469153,468730,468307,467884,467462,467041,
101 466619,466198,465778,465358,464938,464518,464099,463681,
102 463262,462844,462427,462010,461593,461177,460760,460345,
103 459930,459515,459100,458686,458272,457859,457446,457033,
104 456621,456209,455797,455386,454975,454565,454155,453745,
105 453336,452927,452518,452110,451702,451294,450887,450481,
106 450074,449668,449262,448857,448452,448048,447644,447240,
107 446836,446433,446030,445628,445226,444824,444423,444022,
108 443622,443221,442821,442422,442023,441624,441226,440828,
109 440430,440033,439636,439239,438843,438447,438051,437656,
110 437261,436867,436473,436079,435686,435293,434900,434508,
111 434116,433724,433333,432942,432551,432161,431771,431382,
112 430992,430604,430215,429827,429439,429052,428665,428278,
113 427892,427506,427120,426735,426350,425965,425581,425197,
114 424813,424430,424047,423665,423283,422901,422519,422138,
115 421757,421377,420997,420617,420237,419858,419479,419101,
116 418723,418345,417968,417591,417214,416838,416462,416086,
117 415711,415336,414961,414586,414212,413839,413465,413092,
118 412720,412347,411975,411604,411232,410862,410491,410121,
119 409751,409381,409012,408643,408274,407906,407538,407170,
120 406803,406436,406069,405703,405337,404971,404606,404241,
121 403876,403512,403148,402784,402421,402058,401695,401333,
122 400970,400609,400247,399886,399525,399165,398805,398445,
123 398086,397727,397368,397009,396651,396293,395936,395579,
124 395222,394865,394509,394153,393798,393442,393087,392733,
125 392378,392024,391671,391317,390964,390612,390259,389907,
126 389556,389204,388853,388502,388152,387802,387452,387102,
127 386753,386404,386056,385707,385359,385012,384664,384317,
128 383971,383624,383278,382932,382587,382242,381897,381552,
129 381208,380864,380521,380177,379834,379492,379149,378807,
130 378466,378124,377783,377442,377102,376762,376422,376082,
131 375743,375404,375065,374727,374389,374051,373714,373377,
132 373040,372703,372367,372031,371695,371360,371025,370690,
133 370356,370022,369688,369355,369021,368688,368356,368023,
134 367691,367360,367028,366697,366366,366036,365706,365376,
135 365046,364717,364388,364059,363731,363403,363075,362747,
136 362420,362093,361766,361440,361114,360788,360463,360137,
137 359813,359488,359164,358840,358516,358193,357869,357547,
138 357224,356902,356580,356258,355937,355616,355295,354974,
139 354654,354334,354014,353695,353376,353057,352739,352420,
140 352103,351785,351468,351150,350834,350517,350201,349885,
141 349569,349254,348939,348624,348310,347995,347682,347368,
142 347055,346741,346429,346116,345804,345492,345180,344869,
143 344558,344247,343936,343626,343316,343006,342697,342388,
144 342079,341770,341462,341154,340846,340539,340231,339924,
145 339618,339311,339005,338700,338394,338089,337784,337479,
146 337175,336870,336566,336263,335959,335656,335354,335051,
147 334749,334447,334145,333844,333542,333242,332941,332641,
148 332341,332041,331741,331442,331143,330844,330546,330247,
149 329950,329652,329355,329057,328761,328464,328168,327872,
150 327576,327280,326985,326690,326395,326101,325807,325513,
151 325219,324926,324633,324340,324047,323755,323463,323171,
152 322879,322588,322297,322006,321716,321426,321136,320846,
153 320557,320267,319978,319690,319401,319113,318825,318538,
154 318250,317963,317676,317390,317103,316817,316532,316246,
155 315961,315676,315391,315106,314822,314538,314254,313971,
156 313688,313405,313122,312839,312557,312275,311994,311712,
157 311431,311150,310869,310589,310309,310029,309749,309470,
158 309190,308911,308633,308354,308076,307798,307521,307243,
159 306966,306689,306412,306136,305860,305584,305308,305033,
160 304758,304483,304208,303934,303659,303385,303112,302838,
161 302565,302292,302019,301747,301475,301203,300931,300660,
162 300388,300117,299847,299576,299306,299036,298766,298497,
163 298227,297958,297689,297421,297153,296884,296617,296349,
164 296082,295815,295548,295281,295015,294749,294483,294217,
165 293952,293686,293421,293157,292892,292628,292364,292100,
166 291837,291574,291311,291048,290785,290523,290261,289999,
167 289737,289476,289215,288954,288693,288433,288173,287913,
168 287653,287393,287134,286875,286616,286358,286099,285841,
169 285583,285326,285068,284811,284554,284298,284041,283785,
170 283529,283273,283017,282762,282507,282252,281998,281743,
171 281489,281235,280981,280728,280475,280222,279969,279716,
172 279464,279212,278960,278708,278457,278206,277955,277704,
173 277453,277203,276953,276703,276453,276204,275955,275706,
174 275457,275209,274960,274712,274465,274217,273970,273722,
175 273476,273229,272982,272736,272490,272244,271999,271753,
176 271508,271263,271018,270774,270530,270286,270042,269798,
177 269555,269312,269069,268826,268583,268341,268099,267857
181 static const UWORD logtab[104]={
182 LOGFAC*907,LOGFAC*900,LOGFAC*894,LOGFAC*887,
183 LOGFAC*881,LOGFAC*875,LOGFAC*868,LOGFAC*862,
184 LOGFAC*856,LOGFAC*850,LOGFAC*844,LOGFAC*838,
185 LOGFAC*832,LOGFAC*826,LOGFAC*820,LOGFAC*814,
186 LOGFAC*808,LOGFAC*802,LOGFAC*796,LOGFAC*791,
187 LOGFAC*785,LOGFAC*779,LOGFAC*774,LOGFAC*768,
188 LOGFAC*762,LOGFAC*757,LOGFAC*752,LOGFAC*746,
189 LOGFAC*741,LOGFAC*736,LOGFAC*730,LOGFAC*725,
190 LOGFAC*720,LOGFAC*715,LOGFAC*709,LOGFAC*704,
191 LOGFAC*699,LOGFAC*694,LOGFAC*689,LOGFAC*684,
192 LOGFAC*678,LOGFAC*675,LOGFAC*670,LOGFAC*665,
193 LOGFAC*660,LOGFAC*655,LOGFAC*651,LOGFAC*646,
194 LOGFAC*640,LOGFAC*636,LOGFAC*632,LOGFAC*628,
195 LOGFAC*623,LOGFAC*619,LOGFAC*614,LOGFAC*610,
196 LOGFAC*604,LOGFAC*601,LOGFAC*597,LOGFAC*592,
197 LOGFAC*588,LOGFAC*584,LOGFAC*580,LOGFAC*575,
198 LOGFAC*570,LOGFAC*567,LOGFAC*563,LOGFAC*559,
199 LOGFAC*555,LOGFAC*551,LOGFAC*547,LOGFAC*543,
200 LOGFAC*538,LOGFAC*535,LOGFAC*532,LOGFAC*528,
201 LOGFAC*524,LOGFAC*520,LOGFAC*516,LOGFAC*513,
202 LOGFAC*508,LOGFAC*505,LOGFAC*502,LOGFAC*498,
203 LOGFAC*494,LOGFAC*491,LOGFAC*487,LOGFAC*484,
204 LOGFAC*480,LOGFAC*477,LOGFAC*474,LOGFAC*470,
205 LOGFAC*467,LOGFAC*463,LOGFAC*460,LOGFAC*457,
206 LOGFAC*453,LOGFAC*450,LOGFAC*447,LOGFAC*443,
207 LOGFAC*440,LOGFAC*437,LOGFAC*434,LOGFAC*431
210 static const SBYTE PanbrelloTable[256]={
211 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 17, 19, 20, 22, 23,
212 24, 26, 27, 29, 30, 32, 33, 34, 36, 37, 38, 39, 41, 42, 43, 44,
213 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59,
214 59, 60, 60, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64, 64, 64, 64,
215 64, 64, 64, 64, 64, 64, 63, 63, 63, 62, 62, 62, 61, 61, 60, 60,
216 59, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46,
217 45, 44, 43, 42, 41, 39, 38, 37, 36, 34, 33, 32, 30, 29, 27, 26,
218 24, 23, 22, 20, 19, 17, 16, 14, 12, 11, 9, 8, 6, 5, 3, 2,
219 0,- 2,- 3,- 5,- 6,- 8,- 9,-11,-12,-14,-16,-17,-19,-20,-22,-23,
220 -24,-26,-27,-29,-30,-32,-33,-34,-36,-37,-38,-39,-41,-42,-43,-44,
221 -45,-46,-47,-48,-49,-50,-51,-52,-53,-54,-55,-56,-56,-57,-58,-59,
222 -59,-60,-60,-61,-61,-62,-62,-62,-63,-63,-63,-64,-64,-64,-64,-64,
223 -64,-64,-64,-64,-64,-64,-63,-63,-63,-62,-62,-62,-61,-61,-60,-60,
224 -59,-59,-58,-57,-56,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,
225 -45,-44,-43,-42,-41,-39,-38,-37,-36,-34,-33,-32,-30,-29,-27,-26,
226 -24,-23,-22,-20,-19,-17,-16,-14,-12,-11,- 9,- 8,- 6,- 5,- 3,- 2
229 /* returns a random value between 0 and ceil-1, ceil must be a power of two */
230 static int getrandom(int ceilval)
232 #if defined(HAVE_SRANDOM) && !defined(_MIKMOD_AMIGA)
233 return random()&(ceilval-1);
235 return (rand()*ceilval)/(RAND_MAX+1.0);
239 /* New Note Action Scoring System :
240 --------------------------------
241 1) total-volume (fadevol, chanvol, volume) is the main scorer.
242 2) a looping sample is a bonus x2
243 3) a foreground channel is a bonus x4
244 4) an active envelope with keyoff is a handicap -x2
246 static int MP_FindEmptyChannel(MODULE *mod)
251 for (t=0;t<NUMVOICES(mod);t++)
252 if (((mod->voice[t].main.kick==KICK_ABSENT)||
253 (mod->voice[t].main.kick==KICK_ENV))&&
254 Voice_Stopped_internal(t))
257 tvol=0xffffffUL;t=-1;a=mod->voice;
258 for (k=0;k<NUMVOICES(mod);k++,a++) {
259 /* allow us to take over a nonexisting sample */
263 if ((a->main.kick==KICK_ABSENT)||(a->main.kick==KICK_ENV)) {
264 pp=a->totalvol<<((a->main.s->flags&SF_LOOP)?1:0);
265 if ((a->master)&&(a==a->master->slave))
275 if (tvol>8000*7) return -1;
279 static SWORD Interpolate(SWORD p,SWORD p1,SWORD p2,SWORD v1,SWORD v2)
281 if ((p1==p2)||(p==p1)) return v1;
282 return v1+((SLONG)((p-p1)*(v2-v1))/(p2-p1));
285 UWORD getlinearperiod(UWORD note,ULONG fine)
289 t=((20L+2*HIGH_OCTAVE)*OCTAVE+2-note)*32L-(fine>>1);
293 static UWORD getlogperiod(UWORD note,ULONG fine)
301 i=(n<<2)+(fine>>4); /* n*8 + fine/16 */
306 return (Interpolate(fine>>4,0,15,p1,p2)>>o);
309 static UWORD getoldperiod(UWORD note,ULONG speed)
313 /* This happens sometimes on badly converted AMF, and old MOD */
316 fprintf(stderr,"\rmplayer: getoldperiod() called with note=%d, speed=0 !\n",note);
318 return 4242; /* <- prevent divide overflow.. (42 hehe) */
323 return ((8363L*(ULONG)oldperiods[n])>>o)/speed;
326 static UWORD GetPeriod(UWORD flags, UWORD note, ULONG speed)
328 if (flags & UF_XMPERIODS) {
329 if (flags & UF_LINEAR)
330 return getlinearperiod(note, speed);
332 return getlogperiod(note, speed);
334 return getoldperiod(note, speed);
337 static SWORD InterpolateEnv(SWORD p,ENVPT *a,ENVPT *b)
339 return (Interpolate(p,a->pos,b->pos,a->val,b->val));
342 static SWORD DoPan(SWORD envpan,SWORD pan)
346 newpan=pan+(((envpan-PAN_CENTER)*(128-abs(pan-PAN_CENTER)))/128);
348 return (newpan<PAN_LEFT)?PAN_LEFT:(newpan>PAN_RIGHT?PAN_RIGHT:newpan);
351 static SWORD StartEnvelope(ENVPR *t,UBYTE flg,UBYTE pts,UBYTE susbeg,UBYTE susend,UBYTE beg,UBYTE end,ENVPT *p,UBYTE keyoff)
362 t->b=((t->flg&EF_SUSTAIN)&&(!(keyoff&KEY_OFF)))?0:1;
364 /* Imago Orpheus sometimes stores an extra initial point in the envelope */
365 if ((t->pts>=2)&&(t->env[0].pos==t->env[1].pos)) {
370 /* Fit in the envelope, still */
376 return t->env[t->a].val;
379 /* This procedure processes all envelope types, include volume, pitch, and
380 panning. Envelopes are defined by a set of points, each with a magnitude
381 [relating either to volume, panning position, or pitch modifier] and a tick
384 Envelopes work in the following manner:
386 (a) Each tick the envelope is moved a point further in its progression. For
387 an accurate progression, magnitudes between two envelope points are
390 (b) When progression reaches a defined point on the envelope, values are
391 shifted to interpolate between this point and the next, and checks for
392 loops or envelope end are done.
395 Sustain loops are loops that are only active as long as the keyoff flag is
396 clear. When a volume envelope terminates, so does the current fadeout.
398 static SWORD ProcessEnvelope(MP_VOICE *aout, ENVPR *t, SWORD v)
400 if (t->flg & EF_ON) {
401 UBYTE a, b; /* actual points in the envelope */
402 UWORD p; /* the 'tick counter' - real point being played */
409 * Sustain loop on one point (XM type).
410 * Not processed if KEYOFF.
411 * Don't move and don't interpolate when the point is reached
413 if ((t->flg & EF_SUSTAIN) && t->susbeg == t->susend &&
414 (!(aout->main.keyoff & KEY_OFF) && p == t->env[t->susbeg].pos)) {
415 v = t->env[t->susbeg].val;
418 * All following situations will require interpolation between
419 * two envelope points.
423 * Sustain loop between two points (IT type).
424 * Not processed if KEYOFF.
426 /* if we were on a loop point, loop now */
427 if ((t->flg & EF_SUSTAIN) && !(aout->main.keyoff & KEY_OFF) &&
430 b = (t->susbeg==t->susend)?a:a+1;
436 * Be sure to correctly handle single point loops.
438 if ((t->flg & EF_LOOP) && a >= t->end) {
440 b = t->beg == t->end ? a : a + 1;
445 * Non looping situations.
448 v = InterpolateEnv(p, &t->env[a], &t->env[b]);
453 * Start to fade if the volume envelope is finished.
455 if (p >= t->env[t->pts - 1].pos) {
456 if (t->flg & EF_VOLENV) {
457 aout->main.keyoff |= KEY_FADE;
459 aout->main.fadevol = 0;
463 /* did pointer reach point b? */
464 if (p >= t->env[b].pos)
465 a = b++; /* shift points a and b */
475 /* XM linear period to frequency conversion */
476 ULONG getfrequency(UWORD flags,ULONG period)
478 if (flags & UF_LINEAR) {
479 SLONG shift = ((SLONG)period / 768) - HIGH_OCTAVE;
482 return lintab[period % 768] >> shift;
484 return lintab[period % 768] << (-shift);
486 return (8363L*1712L)/(period?period:1);
489 /*========== Protracker effects */
491 static void DoArpeggio(UWORD tick, UWORD flags, MP_CONTROL *a, UBYTE style)
493 UBYTE note=a->main.note;
497 case 0: /* mod style: N, N+x, N+y */
499 /* case 0: unchanged */
501 note += (a->arpmem >> 4);
504 note += (a->arpmem & 0xf);
508 case 3: /* okt arpeggio 3: N-x, N, N+y */
511 note -= (a->arpmem >> 4);
513 /* case 1: unchanged */
515 note += (a->arpmem & 0xf);
519 case 4: /* okt arpeggio 4: N, N+y, N, N-x */
521 /* case 0, case 2: unchanged */
523 note += (a->arpmem & 0xf);
526 note -= (a->arpmem >> 4);
530 case 5: /* okt arpeggio 5: N-x, N+y, N, and nothing at tick 0 */
534 /* case 0: unchanged */
536 note -= (a->arpmem >> 4);
539 note += (a->arpmem & 0xf);
544 a->main.period = GetPeriod(flags, (UWORD)note << 1, a->speed);
549 static int DoPTEffect0(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
555 if (!dat && (flags & UF_ARPMEM))
561 DoArpeggio(tick, flags, a, 0);
566 static int DoPTEffect1(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
572 a->slidespeed = (UWORD)dat << 2;
575 a->tmpperiod -= a->slidespeed;
580 static int DoPTEffect2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
586 a->slidespeed = (UWORD)dat << 2;
589 a->tmpperiod += a->slidespeed;
594 static void DoToneSlide(UWORD tick, MP_CONTROL *a)
596 if (!a->main.fadevol)
597 a->main.kick = (a->main.kick == KICK_NOTE)? KICK_NOTE : KICK_KEYOFF;
599 a->main.kick = (a->main.kick == KICK_NOTE)? KICK_ENV : KICK_ABSENT;
604 /* We have to slide a->main.period towards a->wantedperiod, so compute
605 the difference between those two values */
606 dist=a->main.period-a->wantedperiod;
608 /* if they are equal or if portamentospeed is too big ...*/
609 if (dist == 0 || a->portspeed > abs(dist))
610 /* ...make tmpperiod equal tperiod */
611 a->tmpperiod=a->main.period=a->wantedperiod;
613 a->tmpperiod-=a->portspeed;
614 a->main.period-=a->portspeed; /* dist>0, slide up */
616 a->tmpperiod+=a->portspeed;
617 a->main.period+=a->portspeed; /* dist<0, slide down */
620 a->tmpperiod=a->main.period;
624 static int DoPTEffect3(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
629 if ((!tick)&&(dat)) a->portspeed=(UWORD)dat<<2;
631 DoToneSlide(tick, a);
636 static void DoVibrato(UWORD tick, MP_CONTROL *a)
639 UWORD temp = 0; /* silence warning */
644 q=(a->vibpos>>2)&0x1f;
646 switch (a->wavecontrol&3) {
648 temp=VibratoTable[q];
650 case 1: /* ramp down */
652 if (a->vibpos<0) q=255-q;
655 case 2: /* square wave */
658 case 3: /* random wave */
667 a->main.period=a->tmpperiod+temp;
669 a->main.period=a->tmpperiod-temp;
673 a->vibpos+=a->vibspd;
676 static int DoPTEffect4(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
682 if (dat&0x0f) a->vibdepth=dat&0xf;
683 if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
691 static void DoVolSlide(MP_CONTROL *a, UBYTE dat)
694 a->tmpvolume-=(dat&0x0f);
698 a->tmpvolume+=(dat>>4);
704 static int DoPTEffect5(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
710 DoToneSlide(tick, a);
718 /* DoPTEffect6 after DoPTEffectA */
720 static int DoPTEffect7(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
724 UWORD temp = 0; /* silence warning */
728 if (dat&0x0f) a->trmdepth=dat&0xf;
729 if (dat&0xf0) a->trmspd=(dat&0xf0)>>2;
731 if (a->main.period) {
732 q=(a->trmpos>>2)&0x1f;
734 switch ((a->wavecontrol>>4)&3) {
736 temp=VibratoTable[q];
738 case 1: /* ramp down */
740 if (a->trmpos<0) q=255-q;
743 case 2: /* square wave */
746 case 3: /* random wave */
754 a->volume=a->tmpvolume+temp;
755 if (a->volume>64) a->volume=64;
757 a->volume=a->tmpvolume-temp;
758 if (a->volume<0) a->volume=0;
763 a->trmpos+=a->trmspd;
769 static int DoPTEffect8(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
775 a->main.panning = mod->panning[channel] = dat;
780 static int DoPTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
786 if (dat) a->soffset=(UWORD)dat<<8;
787 a->main.start=a->hioffset|a->soffset;
789 if ((a->main.s)&&(a->main.start>a->main.s->length))
790 a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)?
791 a->main.s->loopstart:a->main.s->length;
797 static int DoPTEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
808 static int DoPTEffect6(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
812 DoPTEffectA(tick, flags, a, mod, channel);
817 static int DoPTEffectB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
823 if (tick || mod->patdly2)
826 /* Vincent Voois uses a nasty trick in "Universal Bolero" */
827 if (dat == mod->sngpos && mod->patbrk == mod->patpos)
830 if (!mod->loop && !mod->patbrk &&
831 (dat < mod->sngpos ||
832 (mod->sngpos == (mod->numpos - 1) && !mod->patbrk) ||
833 (dat == mod->sngpos && (flags & UF_NOWRAP)) ) )
835 /* if we don't loop, better not to skip the end of the
836 pattern, after all... so:
840 /* if we were fading, adjust... */
841 if (mod->sngpos == (mod->numpos-1))
842 mod->volume=mod->initvolume>128?128:mod->initvolume;
846 /* cancel the FT2 pattern loop (E60) bug.
847 * also see DoEEffects() below for it. */
848 if (flags & UF_FT2QUIRKS) mod->patbrk=0;
854 static int DoPTEffectC(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
860 if (dat==(UBYTE)-1) a->anote=dat=0; /* note cut */
861 else if (dat>64) dat=64;
867 static int DoPTEffectD(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
872 if ((tick)||(mod->patdly2)) return 0;
873 if ((mod->positions[mod->sngpos]!=LAST_PATTERN)&&
874 (dat>mod->pattrows[mod->positions[mod->sngpos]])) {
875 dat=mod->pattrows[mod->positions[mod->sngpos]];
879 /* don't ask me to explain this code - it makes
880 backwards.s3m and children.xm (heretic's version) play
881 correctly, among others. Take that for granted, or write
882 the page of comments yourself... you might need some
884 if ((mod->sngpos==mod->numpos-1)&&(dat)&&
885 ((mod->loop) || (mod->positions[mod->sngpos]==(mod->numpat-1) && !(flags&UF_NOWRAP)))) {
895 static void DoEEffects(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod,
896 SWORD channel, UBYTE dat)
898 UBYTE nib = dat & 0xf;
901 case 0x0: /* hardware filter toggle, not supported */
903 case 0x1: /* fineslide up */
906 a->tmpperiod-=(nib<<2);
908 case 0x2: /* fineslide dn */
911 a->tmpperiod+=(nib<<2);
913 case 0x3: /* glissando ctrl */
916 case 0x4: /* set vibrato waveform */
917 a->wavecontrol&=0xf0;
920 case 0x5: /* set finetune */
921 if (a->main.period) {
922 if (flags&UF_XMPERIODS)
925 a->speed=finetune[nib];
926 a->tmpperiod=GetPeriod(flags, (UWORD)a->main.note<<1,a->speed);
929 case 0x6: /* set patternloop */
932 if (nib) { /* set reppos or repcnt ? */
933 /* set repcnt, so check if repcnt already is set, which means we
934 are already looping */
936 a->pat_repcnt--; /* already looping, decrease counter */
939 /* this would make walker.xm, shipped with Xsoundtracker,
940 play correctly, but it's better to remain compatible
942 if ((!(flags&UF_NOWRAP))||(a->pat_reppos!=POS_NONE))
944 a->pat_repcnt=nib; /* not yet looping, so set repcnt */
947 if (a->pat_repcnt) { /* jump to reppos if repcnt>0 */
948 if (a->pat_reppos==POS_NONE)
949 a->pat_reppos=mod->patpos-1;
950 if (a->pat_reppos==-1) {
954 mod->patpos=a->pat_reppos;
955 } else a->pat_reppos=POS_NONE;
957 a->pat_reppos=mod->patpos-1; /* set reppos - can be (-1) */
958 /* emulate the FT2 pattern loop (E60) bug:
959 * http://milkytracker.org/docs/MilkyTracker.html#fxE6x
960 * roadblas.xm plays correctly with this. */
961 if (flags & UF_FT2QUIRKS) mod->patbrk=mod->patpos;
964 case 0x7: /* set tremolo waveform */
965 a->wavecontrol&=0x0f;
966 a->wavecontrol|=nib<<4;
968 case 0x8: /* set panning */
972 a->main.panning=mod->panning[channel]=nib;
975 case 0x9: /* retrig note */
976 /* do not retrigger on tick 0, until we are emulating FT2 and effect
978 if (!tick && !((flags & UF_FT2QUIRKS) && (!nib)))
980 /* only retrigger if data nibble > 0, or if tick 0 (FT2 compat) */
983 /* when retrig counter reaches 0, reset counter and restart
985 if (a->main.period) a->main.kick=KICK_NOTE;
988 a->retrig--; /* countdown */
991 case 0xa: /* fine volume slide up */
995 if (a->tmpvolume>64) a->tmpvolume=64;
997 case 0xb: /* fine volume slide dn */
1001 if (a->tmpvolume<0)a->tmpvolume=0;
1003 case 0xc: /* cut note */
1004 /* When tick reaches the cut-note value, turn the volume to
1005 zero (just like on the amiga) */
1007 a->tmpvolume=0; /* just turn the volume down */
1009 case 0xd: /* note delay */
1010 /* delay the start of the sample until tick==nib */
1012 a->main.notedelay=nib;
1013 else if (a->main.notedelay)
1014 a->main.notedelay--;
1016 case 0xe: /* pattern delay */
1019 mod->patdly=nib+1; /* only once, when tick=0 */
1021 case 0xf: /* invert loop, not supported */
1026 static int DoPTEffectE(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1028 DoEEffects(tick, flags, a, mod, channel, UniGetByte());
1033 static int DoPTEffectF(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1038 if (tick||mod->patdly2) return 0;
1039 if (mod->extspd&&(dat>=mod->bpmlimit))
1043 mod->sngspd=(dat>=mod->bpmlimit)?mod->bpmlimit-1:dat;
1050 /*========== Scream Tracker effects */
1052 static int DoS3MEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1056 speed = UniGetByte();
1058 if (tick || mod->patdly2)
1064 mod->sngspd = speed;
1071 static void DoS3MVolSlide(UWORD tick, UWORD flags, MP_CONTROL *a, UBYTE inf)
1084 if ((tick)||(flags&UF_S3MSLIDES)) a->tmpvolume+=hi;
1087 if ((tick)||(flags&UF_S3MSLIDES)) a->tmpvolume-=lo;
1090 if (!tick) a->tmpvolume+=(hi?hi:0xf);
1093 if (!tick) a->tmpvolume-=(lo?lo:0xf);
1099 else if (a->tmpvolume>64)
1103 static int DoS3MEffectD(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1105 DoS3MVolSlide(tick, flags, a, UniGetByte());
1110 static void DoS3MSlideDn(UWORD tick, MP_CONTROL *a, UBYTE inf)
1123 if (!tick) a->tmpperiod+=(UWORD)lo<<2;
1126 if (!tick) a->tmpperiod+=lo;
1128 if (tick) a->tmpperiod+=(UWORD)inf<<2;
1132 static int DoS3MEffectE(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1138 DoS3MSlideDn(tick, a,dat);
1143 static void DoS3MSlideUp(UWORD tick, MP_CONTROL *a, UBYTE inf)
1147 if (inf) a->slidespeed=inf;
1148 else inf=a->slidespeed;
1154 if (!tick) a->tmpperiod-=(UWORD)lo<<2;
1157 if (!tick) a->tmpperiod-=lo;
1159 if (tick) a->tmpperiod-=(UWORD)inf<<2;
1163 static int DoS3MEffectF(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1169 DoS3MSlideUp(tick, a,dat);
1174 static int DoS3MEffectI(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1192 a->s3mtremor%=(on+off);
1193 a->volume=(a->s3mtremor<on)?a->tmpvolume:0;
1200 static int DoS3MEffectQ(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1205 if (a->main.period) {
1207 a->s3mrtgslide=inf>>4;
1208 a->s3mrtgspeed=inf&0xf;
1211 /* only retrigger if low nibble > 0 */
1212 if (a->s3mrtgspeed>0) {
1214 /* when retrig counter reaches 0, reset counter and restart the
1216 if (a->main.kick!=KICK_NOTE) a->main.kick=KICK_KEYOFF;
1217 a->retrig=a->s3mrtgspeed;
1219 if ((tick)||(flags&UF_S3MSLIDES)) {
1220 switch (a->s3mrtgslide) {
1226 a->tmpvolume-=(1<<(a->s3mrtgslide-1));
1229 a->tmpvolume=(2*a->tmpvolume)/3;
1239 a->tmpvolume+=(1<<(a->s3mrtgslide-9));
1242 a->tmpvolume=(3*a->tmpvolume)>>1;
1245 a->tmpvolume=a->tmpvolume<<1;
1250 else if (a->tmpvolume>64)
1254 a->retrig--; /* countdown */
1261 static int DoS3MEffectR(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1264 UWORD temp=0; /* silence warning */
1268 if (dat&0x0f) a->trmdepth=dat&0xf;
1269 if (dat&0xf0) a->trmspd=(dat&0xf0)>>2;
1272 q=(a->trmpos>>2)&0x1f;
1274 switch ((a->wavecontrol>>4)&3) {
1276 temp=VibratoTable[q];
1278 case 1: /* ramp down */
1280 if (a->trmpos<0) q=255-q;
1283 case 2: /* square wave */
1286 case 3: /* random */
1287 temp=getrandom(256);
1295 a->volume=a->tmpvolume+temp;
1296 if (a->volume>64) a->volume=64;
1298 a->volume=a->tmpvolume-temp;
1299 if (a->volume<0) a->volume=0;
1304 a->trmpos+=a->trmspd;
1309 static int DoS3MEffectT(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1313 tempo = UniGetByte();
1315 if (tick || mod->patdly2)
1318 mod->bpm = (tempo < 32) ? 32 : tempo;
1323 static int DoS3MEffectU(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1326 UWORD temp = 0; /* silence warning */
1330 if (dat&0x0f) a->vibdepth=dat&0xf;
1331 if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
1333 if (a->main.period) {
1334 q=(a->vibpos>>2)&0x1f;
1336 switch (a->wavecontrol&3) {
1338 temp=VibratoTable[q];
1340 case 1: /* ramp down */
1342 if (a->vibpos<0) q=255-q;
1345 case 2: /* square wave */
1348 case 3: /* random */
1349 temp=getrandom(256);
1357 a->main.period=a->tmpperiod+temp;
1359 a->main.period=a->tmpperiod-temp;
1362 a->vibpos+=a->vibspd;
1368 /*========== Envelope helpers */
1370 static int DoKeyOff(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1372 a->main.keyoff|=KEY_OFF;
1373 if ((!(a->main.volflg&EF_ON))||(a->main.volflg&EF_LOOP))
1374 a->main.keyoff=KEY_KILL;
1379 static int DoKeyFade(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1384 if ((tick>=dat)||(tick==mod->sngspd-1)) {
1385 a->main.keyoff=KEY_KILL;
1386 if (!(a->main.volflg&EF_ON))
1393 /*========== Fast Tracker effects */
1395 /* DoXMEffect6 after DoXMEffectA */
1397 static int DoXMEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1403 a->s3mvolslide = inf;
1405 inf = a->s3mvolslide;
1413 if (a->tmpvolume<0) a->tmpvolume=0;
1416 if (a->tmpvolume>64) a->tmpvolume=64;
1423 static int DoXMEffect6(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1428 return DoXMEffectA(tick, flags, a, mod, channel);
1431 static int DoXMEffectE1(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1437 if (dat) a->fportupspd=dat;
1439 a->tmpperiod-=(a->fportupspd<<2);
1445 static int DoXMEffectE2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1451 if (dat) a->fportdnspd=dat;
1453 a->tmpperiod+=(a->fportdnspd<<2);
1459 static int DoXMEffectEA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1465 if (dat) a->fslideupspd=dat;
1466 a->tmpvolume+=a->fslideupspd;
1467 if (a->tmpvolume>64) a->tmpvolume=64;
1472 static int DoXMEffectEB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1478 if (dat) a->fslidednspd=dat;
1479 a->tmpvolume-=a->fslidednspd;
1480 if (a->tmpvolume<0) a->tmpvolume=0;
1485 static int DoXMEffectG(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1487 mod->volume=UniGetByte()<<1;
1488 if (mod->volume>128) mod->volume=128;
1493 static int DoXMEffectH(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1500 if (inf) mod->globalslide=inf;
1501 else inf=mod->globalslide;
1502 if (inf & 0xf0) inf&=0xf0;
1503 mod->volume=mod->volume+((inf>>4)-(inf&0xf))*2;
1507 else if (mod->volume>128)
1514 static int DoXMEffectL(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1519 if ((!tick)&&(a->main.i)) {
1521 INSTRUMENT *i=a->main.i;
1524 if ((aout=a->slave) != NULL) {
1525 if (aout->venv.env) {
1526 points=i->volenv[i->volpts-1].pos;
1527 aout->venv.p=aout->venv.env[(dat>points)?points:dat].pos;
1529 if (aout->penv.env) {
1530 points=i->panenv[i->panpts-1].pos;
1531 aout->penv.p=aout->penv.env[(dat>points)?points:dat].pos;
1539 static int DoXMEffectP(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1557 /* slide right has absolute priority */
1561 pan=((a->main.panning==PAN_SURROUND)?PAN_CENTER:a->main.panning)+hi-lo;
1562 a->main.panning=(pan<PAN_LEFT)?PAN_LEFT:(pan>PAN_RIGHT?PAN_RIGHT:pan);
1568 static int DoXMEffectX1(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1574 a->ffportupspd = dat;
1576 dat = a->ffportupspd;
1580 a->main.period-=dat;
1588 static int DoXMEffectX2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1596 dat = a->ffportdnspd;
1600 a->main.period+=dat;
1608 /*========== Impulse Tracker effects */
1610 static void DoITToneSlide(UWORD tick, MP_CONTROL *a, UBYTE dat)
1615 /* if we don't come from another note, ignore the slide and play the note
1617 if (!a->oldnote || !a->main.period)
1620 if ((!tick)&&(a->newsamp)){
1621 a->main.kick=KICK_NOTE;
1624 a->main.kick=(a->main.kick==KICK_NOTE)?KICK_ENV:KICK_ABSENT;
1629 /* We have to slide a->main.period towards a->wantedperiod, compute the
1630 difference between those two values */
1631 dist=a->main.period-a->wantedperiod;
1633 /* if they are equal or if portamentospeed is too big... */
1634 if ((!dist)||((a->portspeed<<2)>abs(dist)))
1635 /* ... make tmpperiod equal tperiod */
1636 a->tmpperiod=a->main.period=a->wantedperiod;
1639 a->tmpperiod-=a->portspeed<<2;
1640 a->main.period-=a->portspeed<<2; /* dist>0 slide up */
1642 a->tmpperiod+=a->portspeed<<2;
1643 a->main.period+=a->portspeed<<2; /* dist<0 slide down */
1646 a->tmpperiod=a->main.period;
1650 static int DoITEffectG(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1652 DoITToneSlide(tick, a, UniGetByte());
1657 static void DoITVibrato(UWORD tick, MP_CONTROL *a, UBYTE dat)
1663 if (dat&0x0f) a->vibdepth=dat&0xf;
1664 if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
1666 if (!a->main.period)
1669 q=(a->vibpos>>2)&0x1f;
1671 switch (a->wavecontrol&3) {
1673 temp=VibratoTable[q];
1675 case 1: /* square wave */
1678 case 2: /* ramp down */
1680 if (a->vibpos<0) q=255-q;
1683 case 3: /* random */
1684 temp=getrandom(256);
1693 a->main.period=a->tmpperiod+temp;
1695 a->main.period=a->tmpperiod-temp;
1698 a->vibpos+=a->vibspd;
1701 static int DoITEffectH(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1703 DoITVibrato(tick, a, UniGetByte());
1708 static int DoITEffectI(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1724 a->s3mtremor%=(on+off);
1725 a->volume=(a->s3mtremor<on)?a->tmpvolume:0;
1732 static int DoITEffectM(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1734 a->main.chanvol=UniGetByte();
1735 if (a->main.chanvol>64)
1737 else if (a->main.chanvol<0)
1743 static int DoITEffectN(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1750 a->chanvolslide = inf;
1752 inf = a->chanvolslide;
1758 a->main.chanvol-=lo;
1761 a->main.chanvol+=hi;
1764 if (!tick) a->main.chanvol-=lo;
1767 if (!tick) a->main.chanvol+=hi;
1770 if (a->main.chanvol<0)
1772 else if (a->main.chanvol>64)
1778 static int DoITEffectP(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1795 pan=(a->main.panning==PAN_SURROUND)?PAN_CENTER:a->main.panning;
1804 if (!tick) pan+=lo<<2;
1807 if (!tick) pan-=hi<<2;
1810 (pan<PAN_LEFT)?PAN_LEFT:(pan>PAN_RIGHT?PAN_RIGHT:pan);
1815 static int DoITEffectT(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1820 tempo = UniGetByte();
1827 temp += (tempo & 0x0f);
1831 mod->bpm=(temp>255)?255:(temp<1?1:temp);
1836 static int DoITEffectU(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1839 UWORD temp = 0; /* silence warning */
1843 if (dat&0x0f) a->vibdepth=dat&0xf;
1844 if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
1846 if (a->main.period) {
1847 q=(a->vibpos>>2)&0x1f;
1849 switch (a->wavecontrol&3) {
1851 temp=VibratoTable[q];
1853 case 1: /* square wave */
1856 case 2: /* ramp down */
1858 if (a->vibpos<0) q=255-q;
1861 case 3: /* random */
1862 temp=getrandom(256);
1870 a->main.period=a->tmpperiod+temp;
1872 a->main.period=a->tmpperiod-temp;
1875 a->vibpos+=a->vibspd;
1881 static int DoITEffectW(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1888 mod->globalslide = inf;
1890 inf = mod->globalslide;
1896 if (tick) mod->volume+=hi;
1899 if (tick) mod->volume-=lo;
1902 if (!tick) mod->volume+=hi;
1905 if (!tick) mod->volume-=lo;
1910 else if (mod->volume>128)
1916 static int DoITEffectY(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1919 SLONG temp = 0; /* silence warning */
1924 if (dat&0x0f) a->panbdepth=(dat&0xf);
1925 if (dat&0xf0) a->panbspd=(dat&0xf0)>>4;
1930 switch (a->panbwave) {
1932 temp=PanbrelloTable[q];
1934 case 1: /* square wave */
1937 case 2: /* ramp down */
1941 case 3: /* random */
1942 temp=getrandom(256);
1947 temp=(temp/8)+mod->panning[channel];
1950 (temp<PAN_LEFT)?PAN_LEFT:(temp>PAN_RIGHT?PAN_RIGHT:temp);
1951 a->panbpos+=a->panbspd;
1958 static void DoNNAEffects(MODULE *, MP_CONTROL *, UBYTE);
1960 /* Impulse/Scream Tracker Sxx effects.
1961 All Sxx effects share the same memory space. */
1962 static int DoITEffectS0(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1979 case SS_GLISSANDO: /* S1x set glissando voice */
1980 DoEEffects(tick, flags, a, mod, channel, 0x30|inf);
1982 case SS_FINETUNE: /* S2x set finetune */
1983 DoEEffects(tick, flags, a, mod, channel, 0x50|inf);
1985 case SS_VIBWAVE: /* S3x set vibrato waveform */
1986 DoEEffects(tick, flags, a, mod, channel, 0x40|inf);
1988 case SS_TREMWAVE: /* S4x set tremolo waveform */
1989 DoEEffects(tick, flags, a, mod, channel, 0x70|inf);
1991 case SS_PANWAVE: /* S5x panbrello */
1994 case SS_FRAMEDELAY: /* S6x delay x number of frames (patdly) */
1995 DoEEffects(tick, flags, a, mod, channel, 0xe0|inf);
1997 case SS_S7EFFECTS: /* S7x instrument / NNA commands */
1998 DoNNAEffects(mod, a, inf);
2000 case SS_PANNING: /* S8x set panning position */
2001 DoEEffects(tick, flags, a, mod, channel, 0x80 | inf);
2003 case SS_SURROUND: /* S9x set surround sound */
2005 a->main.panning = mod->panning[channel] = PAN_SURROUND;
2007 case SS_HIOFFSET: /* SAy set high order sample offset yxx00h */
2009 a->hioffset=inf<<16;
2010 a->main.start=a->hioffset|a->soffset;
2012 if ((a->main.s)&&(a->main.start>a->main.s->length))
2013 a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)?
2014 a->main.s->loopstart:a->main.s->length;
2017 case SS_PATLOOP: /* SBx pattern loop */
2018 DoEEffects(tick, flags, a, mod, channel, 0x60|inf);
2020 case SS_NOTECUT: /* SCx notecut */
2022 DoEEffects(tick, flags, a, mod, channel, 0xC0|inf);
2024 case SS_NOTEDELAY: /* SDx notedelay */
2025 DoEEffects(tick, flags, a, mod, channel, 0xD0|inf);
2027 case SS_PATDELAY: /* SEx patterndelay */
2028 DoEEffects(tick, flags, a, mod, channel, 0xE0|inf);
2035 /*========== Impulse Tracker Volume/Pan Column effects */
2038 * All volume/pan column effects share the same memory space.
2041 static int DoVolEffects(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2065 a->main.panning=inf;
2068 DoS3MVolSlide(tick, flags, a, inf);
2070 case VOL_PITCHSLIDEDN:
2072 DoS3MSlideDn(tick, a, inf);
2074 case VOL_PITCHSLIDEUP:
2076 DoS3MSlideUp(tick, a, inf);
2078 case VOL_PORTAMENTO:
2079 DoITToneSlide(tick, a, inf);
2082 DoITVibrato(tick, a, inf);
2089 /*========== UltraTracker effects */
2091 static int DoULTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2093 UWORD offset=UniGetWord();
2096 a->ultoffset=offset;
2098 a->main.start=a->ultoffset<<2;
2099 if ((a->main.s)&&(a->main.start>a->main.s->length))
2100 a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)?
2101 a->main.s->loopstart:a->main.s->length;
2106 /*========== OctaMED effects */
2108 static int DoMEDSpeed(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2110 UWORD speed=UniGetWord();
2117 static int DoMEDEffectF1(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2119 DoEEffects(tick, flags, a, mod, channel, 0x90|(mod->sngspd/2));
2124 static int DoMEDEffectF2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2126 DoEEffects(tick, flags, a, mod, channel, 0xd0|(mod->sngspd/2));
2131 static int DoMEDEffectF3(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2133 DoEEffects(tick, flags, a, mod, channel, 0x90|(mod->sngspd/3));
2138 /*========== Oktalyzer effects */
2140 static int DoOktArp(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2144 dat2 = UniGetByte(); /* arpeggio style */
2147 if (!dat && (flags & UF_ARPMEM))
2153 DoArpeggio(tick, flags, a, dat2);
2158 /*========== General player functions */
2160 static int DoNothing(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2167 typedef int (*effect_func) (UWORD, UWORD, MP_CONTROL *, MODULE *, SWORD);
2169 static effect_func effects[UNI_LAST] = {
2171 DoNothing, /* UNI_NOTE */
2172 DoNothing, /* UNI_INSTRUMENT */
2173 DoPTEffect0, /* UNI_PTEFFECT0 */
2174 DoPTEffect1, /* UNI_PTEFFECT1 */
2175 DoPTEffect2, /* UNI_PTEFFECT2 */
2176 DoPTEffect3, /* UNI_PTEFFECT3 */
2177 DoPTEffect4, /* UNI_PTEFFECT4 */
2178 DoPTEffect5, /* UNI_PTEFFECT5 */
2179 DoPTEffect6, /* UNI_PTEFFECT6 */
2180 DoPTEffect7, /* UNI_PTEFFECT7 */
2181 DoPTEffect8, /* UNI_PTEFFECT8 */
2182 DoPTEffect9, /* UNI_PTEFFECT9 */
2183 DoPTEffectA, /* UNI_PTEFFECTA */
2184 DoPTEffectB, /* UNI_PTEFFECTB */
2185 DoPTEffectC, /* UNI_PTEFFECTC */
2186 DoPTEffectD, /* UNI_PTEFFECTD */
2187 DoPTEffectE, /* UNI_PTEFFECTE */
2188 DoPTEffectF, /* UNI_PTEFFECTF */
2189 DoS3MEffectA, /* UNI_S3MEFFECTA */
2190 DoS3MEffectD, /* UNI_S3MEFFECTD */
2191 DoS3MEffectE, /* UNI_S3MEFFECTE */
2192 DoS3MEffectF, /* UNI_S3MEFFECTF */
2193 DoS3MEffectI, /* UNI_S3MEFFECTI */
2194 DoS3MEffectQ, /* UNI_S3MEFFECTQ */
2195 DoS3MEffectR, /* UNI_S3MEFFECTR */
2196 DoS3MEffectT, /* UNI_S3MEFFECTT */
2197 DoS3MEffectU, /* UNI_S3MEFFECTU */
2198 DoKeyOff, /* UNI_KEYOFF */
2199 DoKeyFade, /* UNI_KEYFADE */
2200 DoVolEffects, /* UNI_VOLEFFECTS */
2201 DoPTEffect4, /* UNI_XMEFFECT4 */
2202 DoXMEffect6, /* UNI_XMEFFECT6 */
2203 DoXMEffectA, /* UNI_XMEFFECTA */
2204 DoXMEffectE1, /* UNI_XMEFFECTE1 */
2205 DoXMEffectE2, /* UNI_XMEFFECTE2 */
2206 DoXMEffectEA, /* UNI_XMEFFECTEA */
2207 DoXMEffectEB, /* UNI_XMEFFECTEB */
2208 DoXMEffectG, /* UNI_XMEFFECTG */
2209 DoXMEffectH, /* UNI_XMEFFECTH */
2210 DoXMEffectL, /* UNI_XMEFFECTL */
2211 DoXMEffectP, /* UNI_XMEFFECTP */
2212 DoXMEffectX1, /* UNI_XMEFFECTX1 */
2213 DoXMEffectX2, /* UNI_XMEFFECTX2 */
2214 DoITEffectG, /* UNI_ITEFFECTG */
2215 DoITEffectH, /* UNI_ITEFFECTH */
2216 DoITEffectI, /* UNI_ITEFFECTI */
2217 DoITEffectM, /* UNI_ITEFFECTM */
2218 DoITEffectN, /* UNI_ITEFFECTN */
2219 DoITEffectP, /* UNI_ITEFFECTP */
2220 DoITEffectT, /* UNI_ITEFFECTT */
2221 DoITEffectU, /* UNI_ITEFFECTU */
2222 DoITEffectW, /* UNI_ITEFFECTW */
2223 DoITEffectY, /* UNI_ITEFFECTY */
2224 DoNothing, /* UNI_ITEFFECTZ */
2225 DoITEffectS0, /* UNI_ITEFFECTS0 */
2226 DoULTEffect9, /* UNI_ULTEFFECT9 */
2227 DoMEDSpeed, /* UNI_MEDSPEED */
2228 DoMEDEffectF1, /* UNI_MEDEFFECTF1 */
2229 DoMEDEffectF2, /* UNI_MEDEFFECTF2 */
2230 DoMEDEffectF3, /* UNI_MEDEFFECTF3 */
2231 DoOktArp, /* UNI_OKTARP */
2234 static int pt_playeffects(MODULE *mod, SWORD channel, MP_CONTROL *a)
2236 UWORD tick = mod->vbtick;
2237 UWORD flags = mod->flags;
2239 int explicitslides = 0;
2242 while((c=UniGetByte()) != 0) {
2243 #if 0 /* this doesn't normally happen unless things go fubar elsewhere */
2245 fprintf(stderr,"fubar'ed opcode %u\n",c);
2250 explicitslides |= f(tick, flags, a, mod, channel);
2252 return explicitslides;
2255 static void DoNNAEffects(MODULE *mod, MP_CONTROL *a, UBYTE dat)
2261 aout=(a->slave)?a->slave:NULL;
2264 case 0x0: /* past note cut */
2265 for (t=0;t<NUMVOICES(mod);t++)
2266 if (mod->voice[t].master==a)
2267 mod->voice[t].main.fadevol=0;
2269 case 0x1: /* past note off */
2270 for (t=0;t<NUMVOICES(mod);t++)
2271 if (mod->voice[t].master==a) {
2272 mod->voice[t].main.keyoff|=KEY_OFF;
2273 if ((!(mod->voice[t].venv.flg & EF_ON))||
2274 (mod->voice[t].venv.flg & EF_LOOP))
2275 mod->voice[t].main.keyoff=KEY_KILL;
2278 case 0x2: /* past note fade */
2279 for (t=0;t<NUMVOICES(mod);t++)
2280 if (mod->voice[t].master==a)
2281 mod->voice[t].main.keyoff|=KEY_FADE;
2283 case 0x3: /* set NNA note cut */
2284 a->main.nna=(a->main.nna&~NNA_MASK)|NNA_CUT;
2286 case 0x4: /* set NNA note continue */
2287 a->main.nna=(a->main.nna&~NNA_MASK)|NNA_CONTINUE;
2289 case 0x5: /* set NNA note off */
2290 a->main.nna=(a->main.nna&~NNA_MASK)|NNA_OFF;
2292 case 0x6: /* set NNA note fade */
2293 a->main.nna=(a->main.nna&~NNA_MASK)|NNA_FADE;
2295 case 0x7: /* disable volume envelope */
2297 aout->main.volflg&=~EF_ON;
2299 case 0x8: /* enable volume envelope */
2301 aout->main.volflg|=EF_ON;
2303 case 0x9: /* disable panning envelope */
2305 aout->main.panflg&=~EF_ON;
2307 case 0xa: /* enable panning envelope */
2309 aout->main.panflg|=EF_ON;
2311 case 0xb: /* disable pitch envelope */
2313 aout->main.pitflg&=~EF_ON;
2315 case 0xc: /* enable pitch envelope */
2317 aout->main.pitflg|=EF_ON;
2322 static void pt_UpdateVoices(MODULE *mod, int max_volume)
2324 SWORD envpan,envvol,envpit,channel;
2326 SLONG vibval,vibdpt;
2333 mod->totalchn=mod->realchn=0;
2334 for (channel=0;channel<NUMVOICES(mod);channel++) {
2335 aout=&mod->voice[channel];
2339 if (!s || !s->length) continue;
2341 if (aout->main.period<40)
2342 aout->main.period=40;
2343 else if (aout->main.period>50000)
2344 aout->main.period=50000;
2346 if ((aout->main.kick==KICK_NOTE)||(aout->main.kick==KICK_KEYOFF)) {
2347 Voice_Play_internal(channel,s,(aout->main.start==-1)?
2348 ((s->flags&SF_UST_LOOP)?s->loopstart:0):aout->main.start);
2349 aout->main.fadevol=32768;
2354 envpan = PAN_CENTER;
2356 if (i && ((aout->main.kick==KICK_NOTE)||(aout->main.kick==KICK_ENV))) {
2357 if (aout->main.volflg & EF_ON)
2358 envvol = StartEnvelope(&aout->venv,aout->main.volflg,
2359 i->volpts,i->volsusbeg,i->volsusend,
2360 i->volbeg,i->volend,i->volenv,aout->main.keyoff);
2361 if (aout->main.panflg & EF_ON)
2362 envpan = StartEnvelope(&aout->penv,aout->main.panflg,
2363 i->panpts,i->pansusbeg,i->pansusend,
2364 i->panbeg,i->panend,i->panenv,aout->main.keyoff);
2365 if (aout->main.pitflg & EF_ON)
2366 envpit = StartEnvelope(&aout->cenv,aout->main.pitflg,
2367 i->pitpts,i->pitsusbeg,i->pitsusend,
2368 i->pitbeg,i->pitend,i->pitenv,aout->main.keyoff);
2370 if (aout->cenv.flg & EF_ON)
2371 aout->masterperiod=GetPeriod(mod->flags,
2372 (UWORD)aout->main.note<<1, aout->master->speed);
2374 if (aout->main.volflg & EF_ON)
2375 envvol = ProcessEnvelope(aout,&aout->venv,256);
2376 if (aout->main.panflg & EF_ON)
2377 envpan = ProcessEnvelope(aout,&aout->penv,PAN_CENTER);
2378 if (aout->main.pitflg & EF_ON)
2379 envpit = ProcessEnvelope(aout,&aout->cenv,32);
2381 if (aout->main.kick == KICK_NOTE) {
2382 aout->main.kick_flag = 1;
2384 aout->main.kick=KICK_ABSENT;
2386 tmpvol = aout->main.fadevol; /* max 32768 */
2387 tmpvol *= aout->main.chanvol; /* * max 64 */
2388 tmpvol *= aout->main.outvolume; /* * max 256 */
2389 tmpvol /= (256 * 64); /* tmpvol is max 32768 again */
2390 aout->totalvol = tmpvol >> 2; /* used to determine samplevolume */
2391 tmpvol *= envvol; /* * max 256 */
2392 tmpvol *= mod->volume; /* * max 128 */
2393 tmpvol /= (128 * 256 * 128);
2396 if (mod->sngpos>=mod->numpos)
2399 tmpvol=(tmpvol*max_volume)/128;
2401 if ((aout->masterchn!=-1)&& mod->control[aout->masterchn].muted)
2402 Voice_SetVolume_internal(channel,0);
2404 Voice_SetVolume_internal(channel,tmpvol);
2405 if ((tmpvol)&&(aout->master)&&(aout->master->slave==aout))
2410 if (aout->main.panning==PAN_SURROUND)
2411 Voice_SetPanning_internal(channel,PAN_SURROUND);
2413 if ((mod->panflag)&&(aout->penv.flg & EF_ON))
2414 Voice_SetPanning_internal(channel,
2415 DoPan(envpan,aout->main.panning));
2417 Voice_SetPanning_internal(channel,aout->main.panning);
2419 if (aout->main.period && s->vibdepth)
2420 switch (s->vibtype) {
2422 vibval=avibtab[s->avibpos&127];
2423 if (aout->avibpos & 0x80) vibval=-vibval;
2427 if (aout->avibpos & 0x80) vibval=-vibval;
2430 vibval=63-(((aout->avibpos+128)&255)>>1);
2433 vibval=(((aout->avibpos+128)&255)>>1)-64;
2439 if (s->vibflags & AV_IT) {
2440 if ((aout->aswppos>>8)<s->vibdepth) {
2441 aout->aswppos += s->vibsweep;
2442 vibdpt=aout->aswppos;
2444 vibdpt=s->vibdepth<<8;
2445 vibval=(vibval*vibdpt)>>16;
2447 if (!(mod->flags&UF_LINEAR)) vibval>>=1;
2448 aout->main.period-=vibval;
2451 /* do XM style auto-vibrato */
2452 if (!(aout->main.keyoff & KEY_OFF)) {
2453 if (aout->aswppos<s->vibsweep) {
2454 vibdpt=(aout->aswppos*s->vibdepth)/s->vibsweep;
2459 /* keyoff -> depth becomes 0 if final depth wasn't reached or
2460 stays at final level if depth WAS reached */
2461 if (aout->aswppos>=s->vibsweep)
2466 vibval=(vibval*vibdpt)>>8;
2467 aout->main.period-=vibval;
2470 /* update vibrato position */
2471 aout->avibpos=(aout->avibpos+s->vibrate)&0xff;
2473 /* process pitch envelope */
2474 playperiod=aout->main.period;
2476 if ((aout->main.pitflg&EF_ON)&&(envpit!=32)) {
2480 if ((aout->main.note<<1)+envpit<=0) envpit=-(aout->main.note<<1);
2482 p1=GetPeriod(mod->flags, ((UWORD)aout->main.note<<1)+envpit,
2483 aout->master->speed)-aout->masterperiod;
2485 if ((UWORD)(playperiod+p1)<=playperiod) {
2487 aout->main.keyoff|=KEY_OFF;
2490 if ((UWORD)(playperiod+p1)>=playperiod) {
2492 aout->main.keyoff|=KEY_OFF;
2498 if (!aout->main.fadevol) { /* check for a dead note (fadevol=0) */
2499 Voice_Stop_internal(channel);
2501 if ((tmpvol)&&(aout->master)&&(aout->master->slave==aout))
2504 Voice_SetFrequency_internal(channel,
2505 getfrequency(mod->flags,playperiod));
2507 /* if keyfade, start substracting fadeoutspeed from fadevol: */
2508 if ((i)&&(aout->main.keyoff&KEY_FADE)) {
2509 if (aout->main.fadevol>=i->volfade)
2510 aout->main.fadevol-=i->volfade;
2512 aout->main.fadevol=0;
2516 md_bpm=mod->bpm+mod->relspd;
2519 else if ((!(mod->flags&UF_HIGHBPM)) && md_bpm>255)
2524 /* Handles new notes or instruments */
2525 static void pt_Notes(MODULE *mod)
2530 int tr,funky; /* funky is set to indicate note or instrument change */
2532 for (channel=0;channel<mod->numchn;channel++) {
2533 a=&mod->control[channel];
2535 if (mod->sngpos>=mod->numpos) {
2539 tr=mod->patterns[(mod->positions[mod->sngpos]*mod->numchn)+channel];
2540 mod->numrow=mod->pattrows[mod->positions[mod->sngpos]];
2543 a->row=(tr<mod->numtrk)?UniFindRow(mod->tracks[tr],mod->patpos):NULL;
2545 if (!mod->vbtick) a->main.notedelay=0;
2547 if (!a->row) continue;
2551 while((c=UniGetByte()) != 0)
2555 a->oldnote=a->anote,a->anote=UniGetByte();
2556 a->main.kick =KICK_NOTE;
2560 /* retrig tremolo and vibrato waves ? */
2561 if (!(a->wavecontrol & 0x80)) a->trmpos=0;
2562 if (!(a->wavecontrol & 0x08)) a->vibpos=0;
2563 if (!a->panbwave) a->panbpos=0;
2565 case UNI_INSTRUMENT:
2567 if (inst>=mod->numins) break; /* safety valve */
2569 a->main.i=(mod->flags & UF_INST)?&mod->instruments[inst]:NULL;
2573 a->main.sample=inst;
2584 if ((i=a->main.i) != NULL) {
2585 if (i->samplenumber[a->anote] >= mod->numsmp) continue;
2586 s=&mod->samples[i->samplenumber[a->anote]];
2587 a->main.note=i->samplenote[a->anote];
2589 a->main.note=a->anote;
2590 s=&mod->samples[a->main.sample];
2595 a->newsamp=a->main.period;
2598 /* channel or instrument determined panning ? */
2599 a->main.panning=mod->panning[channel];
2600 if (s->flags & SF_OWNPAN)
2601 a->main.panning=s->panning;
2602 else if ((i)&&(i->flags & IF_OWNPAN))
2603 a->main.panning=i->panning;
2605 a->main.handle=s->handle;
2609 if ((mod->panflag)&&(i->flags & IF_PITCHPAN)
2610 &&(a->main.panning!=PAN_SURROUND)){
2612 ((a->anote-i->pitpancenter)*i->pitpansep)/8;
2613 if (a->main.panning<PAN_LEFT)
2614 a->main.panning=PAN_LEFT;
2615 else if (a->main.panning>PAN_RIGHT)
2616 a->main.panning=PAN_RIGHT;
2618 a->main.pitflg=i->pitflg;
2619 a->main.volflg=i->volflg;
2620 a->main.panflg=i->panflg;
2621 a->main.nna=i->nnatype;
2625 a->main.pitflg=a->main.volflg=a->main.panflg=0;
2626 a->main.nna=a->dca=0;
2630 if (funky&2) /* instrument change */ {
2631 /* IT random volume variations: 0:8 bit fixed, and one bit for
2633 a->volume=a->tmpvolume=s->volume;
2636 a->volume=a->tmpvolume=s->volume+
2637 ((s->volume*((SLONG)i->rvolvar*(SLONG)getrandom(512)
2640 a->volume=a->tmpvolume=0;
2641 else if (a->volume>64)
2642 a->volume=a->tmpvolume=64;
2644 if ((mod->panflag)&&(a->main.panning!=PAN_SURROUND)) {
2645 a->main.panning+=((a->main.panning*((SLONG)i->rpanvar*
2646 (SLONG)getrandom(512)))/25600);
2647 if (a->main.panning<PAN_LEFT)
2648 a->main.panning=PAN_LEFT;
2649 else if (a->main.panning>PAN_RIGHT)
2650 a->main.panning=PAN_RIGHT;
2655 a->wantedperiod=a->tmpperiod=
2656 GetPeriod(mod->flags, (UWORD)a->main.note<<1,a->speed);
2657 a->main.keyoff=KEY_KICK;
2662 /* Handles effects */
2663 static void pt_EffectsPass1(MODULE *mod)
2670 for (channel=0;channel<mod->numchn;channel++) {
2671 a=&mod->control[channel];
2673 if ((aout=a->slave) != NULL) {
2674 a->main.fadevol=aout->main.fadevol;
2675 a->main.period=aout->main.period;
2676 if (a->main.kick==KICK_KEYOFF)
2677 a->main.keyoff=aout->main.keyoff;
2680 if (!a->row) continue;
2683 a->ownper=a->ownvol=0;
2684 explicitslides = pt_playeffects(mod, channel, a);
2686 /* continue volume slide if necessary for XM and IT */
2687 if (mod->flags&UF_BGSLIDES) {
2688 if (!explicitslides && a->sliding)
2689 DoS3MVolSlide(mod->vbtick, mod->flags, a, 0);
2690 else if (a->tmpvolume)
2691 a->sliding = explicitslides;
2695 a->main.period=a->tmpperiod;
2697 a->volume=a->tmpvolume;
2702 (a->volume*a->main.s->globvol*a->main.i->globvol)>>10;
2704 a->main.outvolume=(a->volume*a->main.s->globvol)>>4;
2705 if (a->main.outvolume>256)
2706 a->main.outvolume=256;
2707 else if (a->main.outvolume<0)
2708 a->main.outvolume=0;
2713 /* NNA management */
2714 static void pt_NNA(MODULE *mod)
2719 for (channel=0;channel<mod->numchn;channel++) {
2720 a=&mod->control[channel];
2722 if (a->main.kick==KICK_NOTE) {
2729 if (aout->main.nna & NNA_MASK) {
2730 /* Make sure the old MP_VOICE channel knows it has no
2733 /* assume the channel is taken by NNA */
2736 switch (aout->main.nna) {
2737 case NNA_CONTINUE: /* continue note, do nothing */
2739 case NNA_OFF: /* note off */
2740 aout->main.keyoff|=KEY_OFF;
2741 if ((!(aout->main.volflg & EF_ON))||
2742 (aout->main.volflg & EF_LOOP))
2743 aout->main.keyoff=KEY_KILL;
2746 aout->main.keyoff |= KEY_FADE;
2752 if (a->dct!=DCT_OFF) {
2755 for (t=0;t<NUMVOICES(mod);t++)
2756 if ((!Voice_Stopped_internal(t))&&
2757 (mod->voice[t].masterchn==channel)&&
2758 (a->main.sample==mod->voice[t].main.sample)) {
2762 if (a->main.note==mod->voice[t].main.note)
2766 if (a->main.handle==mod->voice[t].main.handle)
2776 mod->voice[t].main.fadevol=0;
2779 mod->voice[t].main.keyoff|=KEY_OFF;
2780 if ((!(mod->voice[t].main.volflg&EF_ON))||
2781 (mod->voice[t].main.volflg&EF_LOOP))
2782 mod->voice[t].main.keyoff=KEY_KILL;
2785 mod->voice[t].main.keyoff|=KEY_FADE;
2790 } /* if (a->main.kick==KICK_NOTE) */
2794 /* Setup module and NNA voices */
2795 static void pt_SetupVoices(MODULE *mod)
2801 for (channel=0;channel<mod->numchn;channel++) {
2802 a=&mod->control[channel];
2804 if (a->main.notedelay) continue;
2805 if (a->main.kick==KICK_NOTE) {
2806 /* if no channel was cut above, find an empty or quiet channel
2808 if (mod->flags&UF_NNA) {
2812 if ((newchn=MP_FindEmptyChannel(mod))!=-1)
2813 a->slave=&mod->voice[a->slavechn=newchn];
2816 a->slave=&mod->voice[a->slavechn=channel];
2818 /* assign parts of MP_VOICE only done for a KICK_NOTE */
2819 if ((aout=a->slave) != NULL) {
2820 if (aout->mflag && aout->master) aout->master->slave=NULL;
2823 aout->masterchn=channel;
2831 a->main.kick=KICK_ABSENT;
2835 /* second effect pass */
2836 static void pt_EffectsPass2(MODULE *mod)
2842 for (channel=0;channel<mod->numchn;channel++) {
2843 a=&mod->control[channel];
2845 if (!a->row) continue;
2848 while((c=UniGetByte()) != 0)
2849 if (c==UNI_ITEFFECTS0) {
2851 if ((c>>4)==SS_S7EFFECTS)
2852 DoNNAEffects(mod, a, c&0xf);
2858 void Player_HandleTick(void)
2864 /* don't handle the very first ticks, this allows the other hardware to
2865 settle down so we don't loose any starting notes */
2872 if ((!pf)||(pf->forbid)||(pf->sngpos>=pf->numpos)) return;
2874 /* update time counter (sngtime is in milliseconds (in fact 2^-10)) */
2875 pf->sngremainder+=(1<<9)*5; /* thus 2.5*(1<<10), since fps=0.4xtempo */
2876 pf->sngtime+=pf->sngremainder/pf->bpm;
2877 pf->sngremainder%=pf->bpm;
2879 if (++pf->vbtick>=pf->sngspd) {
2880 if (pf->pat_repcrazy)
2881 pf->pat_repcrazy=0; /* play 2 times row 0 */
2886 /* process pattern-delay. pf->patdly2 is the counter and pf->patdly is
2887 the command memory. */
2889 pf->patdly2=pf->patdly,pf->patdly=0;
2891 /* patterndelay active */
2893 /* so turn back pf->patpos by 1 */
2894 if (pf->patpos) pf->patpos--;
2897 /* do we have to get a new patternpointer ? (when pf->patpos reaches the
2898 pattern size, or when a patternbreak is active) */
2899 if (((pf->patpos>=pf->numrow)&&(pf->numrow>0))&&(!pf->posjmp))
2903 pf->patpos=pf->numrow?(pf->patbrk%pf->numrow):0;
2905 pf->sngpos+=(pf->posjmp-2);
2906 for (channel=0;channel<pf->numchn;channel++)
2907 pf->control[channel].pat_reppos=-1;
2909 pf->patbrk=pf->posjmp=0;
2911 if (pf->sngpos<0) pf->sngpos=(SWORD)(pf->numpos-1);
2913 /* handle the "---" (end of song) pattern since it can occur
2914 *inside* the module in some formats */
2915 if ((pf->sngpos>=pf->numpos)||
2916 (pf->positions[pf->sngpos]==LAST_PATTERN)) {
2917 if (!pf->wrap) return;
2918 if (!(pf->sngpos=pf->reppos)) {
2919 pf->volume=pf->initvolume>128?128:pf->initvolume;
2920 if(pf->initspeed!=0)
2921 pf->sngspd=pf->initspeed<32?pf->initspeed:32;
2924 pf->bpm=pf->inittempo<32?32:pf->inittempo;
2933 /* Fade global volume if enabled and we're playing the last pattern */
2934 if (((pf->sngpos==pf->numpos-1)||
2935 (pf->positions[pf->sngpos+1]==LAST_PATTERN))&&
2937 max_volume=pf->numrow?((pf->numrow-pf->patpos)*128)/pf->numrow:0;
2941 pt_EffectsPass1(pf);
2942 if (pf->flags&UF_NNA)
2945 pt_EffectsPass2(pf);
2947 /* now set up the actual hardware channel playback information */
2948 pt_UpdateVoices(pf, max_volume);
2951 static void Player_Init_internal(MODULE* mod)
2955 for (t=0;t<mod->numchn;t++) {
2956 mod->control[t].main.chanvol=mod->chanvol[t];
2957 mod->control[t].main.panning=mod->panning[t];
2961 mod->sngremainder=0;
2963 mod->pat_repcrazy=0;
2965 if(mod->initspeed!=0)
2966 mod->sngspd=mod->initspeed<32?mod->initspeed:32;
2969 mod->volume=mod->initvolume>128?128:mod->initvolume;
2971 mod->vbtick=mod->sngspd;
2974 mod->bpm=mod->inittempo<32?32:mod->inittempo;
2978 mod->posjmp=2; /* make sure the player fetches the first note */
2983 int Player_Init(MODULE* mod)
2993 /* make sure the player doesn't start with garbage */
2994 if (!(mod->control=(MP_CONTROL*)MikMod_calloc(mod->numchn,sizeof(MP_CONTROL))))
2996 if (!(mod->voice=(MP_VOICE*)MikMod_calloc(md_sngchn,sizeof(MP_VOICE))))
2999 /* mod->numvoices was used during loading to clamp md_sngchn.
3000 After loading it's used to remember how big mod->voice is.
3002 mod->numvoices = md_sngchn;
3004 Player_Init_internal(mod);
3008 void Player_Exit_internal(MODULE* mod)
3013 /* Stop playback if necessary */
3015 Player_Stop_internal();
3019 MikMod_free(mod->control);
3020 MikMod_free(mod->voice);
3025 void Player_Exit(MODULE* mod)
3028 Player_Exit_internal(mod);
3032 MIKMODAPI void Player_SetVolume(SWORD volume)
3036 pf->volume=(volume<0)?0:(volume>128)?128:volume;
3037 pf->initvolume=pf->volume;
3042 MIKMODAPI MODULE* Player_GetModule(void)
3053 MIKMODAPI void Player_Start(MODULE *mod)
3060 if (!MikMod_Active())
3061 MikMod_EnableOutput();
3067 /* new song is being started, so completely stop out the old one. */
3068 if (pf) pf->forbid=1;
3069 for (t=0;t<md_sngchn;t++) Voice_Stop_internal(t);
3075 void Player_Stop_internal(void)
3077 if (!md_sfxchn) MikMod_DisableOutput_internal();
3078 if (pf) pf->forbid=1;
3082 MIKMODAPI void Player_Stop(void)
3085 Player_Stop_internal();
3089 MIKMODAPI BOOL Player_Active(void)
3095 result=(!(pf->sngpos>=pf->numpos));
3101 MIKMODAPI void Player_NextPosition(void)
3110 pf->vbtick=pf->sngspd;
3112 for (t=0;t<NUMVOICES(pf);t++) {
3113 Voice_Stop_internal(t);
3114 pf->voice[t].main.i=NULL;
3115 pf->voice[t].main.s=NULL;
3117 for (t=0;t<pf->numchn;t++) {
3118 pf->control[t].main.i=NULL;
3119 pf->control[t].main.s=NULL;
3126 MIKMODAPI void Player_PrevPosition(void)
3135 pf->vbtick=pf->sngspd;
3137 for (t=0;t<NUMVOICES(pf);t++) {
3138 Voice_Stop_internal(t);
3139 pf->voice[t].main.i=NULL;
3140 pf->voice[t].main.s=NULL;
3142 for (t=0;t<pf->numchn;t++) {
3143 pf->control[t].main.i=NULL;
3144 pf->control[t].main.s=NULL;
3151 MIKMODAPI void Player_SetPosition(UWORD pos)
3158 if (pos>=pf->numpos) pos=pf->numpos;
3162 pf->vbtick=pf->sngspd;
3164 for (t=0;t<NUMVOICES(pf);t++) {
3165 Voice_Stop_internal(t);
3166 pf->voice[t].main.i=NULL;
3167 pf->voice[t].main.s=NULL;
3169 for (t=0;t<pf->numchn;t++) {
3170 pf->control[t].main.i=NULL;
3171 pf->control[t].main.s=NULL;
3176 Player_Init_internal(pf);
3181 static void Player_Unmute_internal(SLONG arg1,va_list ap)
3183 SLONG t,arg2,arg3=0;
3187 case MUTE_INCLUSIVE:
3188 if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3189 (arg2>arg3)||(arg3>=pf->numchn))
3191 for (;arg2<pf->numchn && arg2<=arg3;arg2++)
3192 pf->control[arg2].muted=0;
3194 case MUTE_EXCLUSIVE:
3195 if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3196 (arg2>arg3)||(arg3>=pf->numchn))
3198 for (t=0;t<pf->numchn;t++) {
3199 if ((t>=arg2) && (t<=arg3))
3201 pf->control[t].muted=0;
3205 if (arg1<pf->numchn) pf->control[arg1].muted=0;
3211 MIKMODAPI void Player_Unmute(SLONG arg1, ...)
3215 va_start(args,arg1);
3217 Player_Unmute_internal(arg1,args);
3222 static void Player_Mute_internal(SLONG arg1,va_list ap)
3224 SLONG t,arg2,arg3=0;
3228 case MUTE_INCLUSIVE:
3229 if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3230 (arg2>arg3)||(arg3>=pf->numchn))
3232 for (;arg2<pf->numchn && arg2<=arg3;arg2++)
3233 pf->control[arg2].muted=1;
3235 case MUTE_EXCLUSIVE:
3236 if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3237 (arg2>arg3)||(arg3>=pf->numchn))
3239 for (t=0;t<pf->numchn;t++) {
3240 if ((t>=arg2) && (t<=arg3))
3242 pf->control[t].muted=1;
3246 if (arg1<pf->numchn)
3247 pf->control[arg1].muted=1;
3253 MIKMODAPI void Player_Mute(SLONG arg1,...)
3257 va_start(args,arg1);
3259 Player_Mute_internal(arg1,args);
3264 static void Player_ToggleMute_internal(SLONG arg1,va_list ap)
3271 case MUTE_INCLUSIVE:
3272 if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3273 (arg2>arg3)||(arg3>=pf->numchn))
3275 for (;arg2<pf->numchn && arg2<=arg3;arg2++)
3276 pf->control[arg2].muted=1-pf->control[arg2].muted;
3278 case MUTE_EXCLUSIVE:
3279 if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3280 (arg2>arg3)||(arg3>=pf->numchn))
3282 for (t=0;t<pf->numchn;t++) {
3283 if ((t>=arg2) && (t<=arg3))
3285 pf->control[t].muted=1-pf->control[t].muted;
3289 if (arg1<pf->numchn)
3290 pf->control[arg1].muted=1-pf->control[arg1].muted;
3296 MIKMODAPI void Player_ToggleMute(SLONG arg1,...)
3300 va_start(args,arg1);
3302 Player_ToggleMute_internal(arg1,args);
3307 MIKMODAPI BOOL Player_Muted(UBYTE chan)
3313 result=(chan<pf->numchn)?pf->control[chan].muted:1;
3319 MIKMODAPI int Player_GetChannelVoice(UBYTE chan)
3325 result=(chan<pf->numchn)?pf->control[chan].slavechn:-1;
3331 MIKMODAPI UWORD Player_GetChannelPeriod(UBYTE chan)
3337 result=(chan<pf->numchn)?pf->control[chan].main.period:0;
3343 BOOL Player_Paused_internal(void)
3345 return pf?pf->forbid:1;
3348 MIKMODAPI BOOL Player_Paused(void)
3353 result=Player_Paused_internal();
3359 MIKMODAPI void Player_TogglePause(void)
3363 pf->forbid=1-pf->forbid;
3367 MIKMODAPI void Player_SetSpeed(UWORD speed)
3371 pf->sngspd=speed?(speed<32?speed:32):1;
3375 MIKMODAPI void Player_SetTempo(UWORD tempo)
3377 if (tempo<32) tempo=32;
3380 if ((!(pf->flags&UF_HIGHBPM))&&(tempo>255)) tempo=255;
3386 MIKMODAPI int Player_QueryVoices(UWORD numvoices, VOICEINFO *vinfo)
3390 if (numvoices > md_sngchn)
3391 numvoices = md_sngchn;
3395 for (i = 0; i < md_sngchn; i++) {
3396 vinfo [i].i = pf->voice[i].main.i;
3397 vinfo [i].s = pf->voice[i].main.s;
3398 vinfo [i].panning = pf->voice [i].main.panning;
3399 vinfo [i].volume = pf->voice [i].main.chanvol;
3400 vinfo [i].period = pf->voice [i].main.period;
3401 vinfo [i].kick = pf->voice [i].main.kick_flag;
3402 pf->voice [i].main.kick_flag = 0;
3409 /* Get current module order */
3410 MIKMODAPI int Player_GetOrder(void)
3414 ret = pf ? pf->sngpos :0; /* pf->positions[pf->sngpos ? pf->sngpos-1 : 0]: 0; */
3419 /* Get current module row */
3420 MIKMODAPI int Player_GetRow(void)
3424 ret = pf ? pf->patpos : 0;