1 /* MikMod sound library
2 (c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS
3 for complete list.
4
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.
9
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.
14
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
18 02111-1307, USA.
19 */
20
21 /*==============================================================================
22
23 $Id$
24
25 The Protracker Player Driver
26
27 The protracker driver supports all base Protracker 3.x commands and features.
28
29 ==============================================================================*/
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include <string.h>
36 #include <stdarg.h>
37 #ifdef SRANDOM_IN_MATH_H
38 #include <math.h>
39 #else
40 #include <stdlib.h>
41 #endif
42
43 #include "mikmod_internals.h"
44
45 #ifdef SUNOS
46 extern int fprintf(FILE *, const char *, ...);
47 extern long int random(void);
48 #endif
49
50 /* The currently playing module */
51 MODULE *pf = NULL;
52
53 #define NUMVOICES(mod) (md_sngchn < (mod)->numvoices ? md_sngchn : (mod)->numvoices)
54
55 #define HIGH_OCTAVE 2 /* number of above-range octaves */
56
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
62 };
63
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
67 };
68
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
78 };
79
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
178 };
179
180 #define LOGFAC 2*16
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
208 };
209
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
227 };
228
229 /* returns a random value between 0 and ceil-1, ceil must be a power of two */
getrandom(int ceilval)230 static int getrandom(int ceilval)
231 {
232 #if defined(HAVE_SRANDOM) && !defined(_MIKMOD_AMIGA)
233 return random()&(ceilval-1);
234 #else
235 return (rand()*ceilval)/(RAND_MAX+1.0);
236 #endif
237 }
238
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
245 */
MP_FindEmptyChannel(MODULE * mod)246 static int MP_FindEmptyChannel(MODULE *mod)
247 {
248 MP_VOICE *a;
249 ULONG t,k,tvol,pp;
250
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))
255 return t;
256
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 */
260 if (!a->main.s)
261 return k;
262
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))
266 pp<<=2;
267
268 if (pp<tvol) {
269 tvol=pp;
270 t=k;
271 }
272 }
273 }
274
275 if (tvol>8000*7) return -1;
276 return t;
277 }
278
Interpolate(SWORD p,SWORD p1,SWORD p2,SWORD v1,SWORD v2)279 static SWORD Interpolate(SWORD p,SWORD p1,SWORD p2,SWORD v1,SWORD v2)
280 {
281 if ((p1==p2)||(p==p1)) return v1;
282 return v1+((SLONG)((p-p1)*(v2-v1))/(p2-p1));
283 }
284
getlinearperiod(UWORD note,ULONG fine)285 UWORD getlinearperiod(UWORD note,ULONG fine)
286 {
287 UWORD t;
288
289 t=((20L+2*HIGH_OCTAVE)*OCTAVE+2-note)*32L-(fine>>1);
290 return t;
291 }
292
getlogperiod(UWORD note,ULONG fine)293 static UWORD getlogperiod(UWORD note,ULONG fine)
294 {
295 UWORD n,o;
296 UWORD p1,p2;
297 ULONG i;
298
299 n=note%(2*OCTAVE);
300 o=note/(2*OCTAVE);
301 i=(n<<2)+(fine>>4); /* n*8 + fine/16 */
302
303 p1=logtab[i];
304 p2=logtab[i+1];
305
306 return (Interpolate(fine>>4,0,15,p1,p2)>>o);
307 }
308
getoldperiod(UWORD note,ULONG speed)309 static UWORD getoldperiod(UWORD note,ULONG speed)
310 {
311 UWORD n,o;
312
313 /* This happens sometimes on badly converted AMF, and old MOD */
314 if (!speed) {
315 #ifdef MIKMOD_DEBUG
316 fprintf(stderr,"\rmplayer: getoldperiod() called with note=%d, speed=0 !\n",note);
317 #endif
318 return 4242; /* <- prevent divide overflow.. (42 hehe) */
319 }
320
321 n=note%(2*OCTAVE);
322 o=note/(2*OCTAVE);
323 return ((8363L*(ULONG)oldperiods[n])>>o)/speed;
324 }
325
GetPeriod(UWORD flags,UWORD note,ULONG speed)326 static UWORD GetPeriod(UWORD flags, UWORD note, ULONG speed)
327 {
328 if (flags & UF_XMPERIODS) {
329 if (flags & UF_LINEAR)
330 return getlinearperiod(note, speed);
331 else
332 return getlogperiod(note, speed);
333 } else
334 return getoldperiod(note, speed);
335 }
336
InterpolateEnv(SWORD p,ENVPT * a,ENVPT * b)337 static SWORD InterpolateEnv(SWORD p,ENVPT *a,ENVPT *b)
338 {
339 return (Interpolate(p,a->pos,b->pos,a->val,b->val));
340 }
341
DoPan(SWORD envpan,SWORD pan)342 static SWORD DoPan(SWORD envpan,SWORD pan)
343 {
344 int newpan;
345
346 newpan=pan+(((envpan-PAN_CENTER)*(128-abs(pan-PAN_CENTER)))/128);
347
348 return (newpan<PAN_LEFT)?PAN_LEFT:(newpan>PAN_RIGHT?PAN_RIGHT:newpan);
349 }
350
StartEnvelope(ENVPR * t,UBYTE flg,UBYTE pts,UBYTE susbeg,UBYTE susend,UBYTE beg,UBYTE end,ENVPT * p,UBYTE keyoff)351 static SWORD StartEnvelope(ENVPR *t,UBYTE flg,UBYTE pts,UBYTE susbeg,UBYTE susend,UBYTE beg,UBYTE end,ENVPT *p,UBYTE keyoff)
352 {
353 t->flg=flg;
354 t->pts=pts;
355 t->susbeg=susbeg;
356 t->susend=susend;
357 t->beg=beg;
358 t->end=end;
359 t->env=p;
360 t->p=0;
361 t->a=0;
362 t->b=((t->flg&EF_SUSTAIN)&&(!(keyoff&KEY_OFF)))?0:1;
363
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)) {
366 t->a++;
367 t->b++;
368 }
369
370 /* Fit in the envelope, still */
371 if (t->a >= t->pts)
372 t->a = t->pts - 1;
373 if (t->b >= t->pts)
374 t->b = t->pts-1;
375
376 return t->env[t->a].val;
377 }
378
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
382 position.
383
384 Envelopes work in the following manner:
385
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
388 interpolated.
389
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.
393
394 Misc:
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.
397 */
ProcessEnvelope(MP_VOICE * aout,ENVPR * t,SWORD v)398 static SWORD ProcessEnvelope(MP_VOICE *aout, ENVPR *t, SWORD v)
399 {
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 */
403
404 a = t->a;
405 b = t->b;
406 p = t->p;
407
408 /*
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
412 */
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;
416 } else {
417 /*
418 * All following situations will require interpolation between
419 * two envelope points.
420 */
421
422 /*
423 * Sustain loop between two points (IT type).
424 * Not processed if KEYOFF.
425 */
426 /* if we were on a loop point, loop now */
427 if ((t->flg & EF_SUSTAIN) && !(aout->main.keyoff & KEY_OFF) &&
428 a >= t->susend) {
429 a = t->susbeg;
430 b = (t->susbeg==t->susend)?a:a+1;
431 p = t->env[a].pos;
432 v = t->env[a].val;
433 } else
434 /*
435 * Regular loop.
436 * Be sure to correctly handle single point loops.
437 */
438 if ((t->flg & EF_LOOP) && a >= t->end) {
439 a = t->beg;
440 b = t->beg == t->end ? a : a + 1;
441 p = t->env[a].pos;
442 v = t->env[a].val;
443 } else
444 /*
445 * Non looping situations.
446 */
447 if (a != b)
448 v = InterpolateEnv(p, &t->env[a], &t->env[b]);
449 else
450 v = t->env[a].val;
451
452 /*
453 * Start to fade if the volume envelope is finished.
454 */
455 if (p >= t->env[t->pts - 1].pos) {
456 if (t->flg & EF_VOLENV) {
457 aout->main.keyoff |= KEY_FADE;
458 if (!v)
459 aout->main.fadevol = 0;
460 }
461 } else {
462 p++;
463 /* did pointer reach point b? */
464 if (p >= t->env[b].pos)
465 a = b++; /* shift points a and b */
466 }
467 t->a = a;
468 t->b = b;
469 t->p = p;
470 }
471 }
472 return v;
473 }
474
475 /* XM linear period to frequency conversion */
getfrequency(UWORD flags,ULONG period)476 ULONG getfrequency(UWORD flags,ULONG period)
477 {
478 if (flags & UF_LINEAR) {
479 SLONG shift = ((SLONG)period / 768) - HIGH_OCTAVE;
480
481 if (shift >= 0)
482 return lintab[period % 768] >> shift;
483 else
484 return lintab[period % 768] << (-shift);
485 } else
486 return (8363L*1712L)/(period?period:1);
487 }
488
489 /*========== Protracker effects */
490
DoArpeggio(UWORD tick,UWORD flags,MP_CONTROL * a,UBYTE style)491 static void DoArpeggio(UWORD tick, UWORD flags, MP_CONTROL *a, UBYTE style)
492 {
493 UBYTE note=a->main.note;
494
495 if (a->arpmem) {
496 switch (style) {
497 case 0: /* mod style: N, N+x, N+y */
498 switch (tick % 3) {
499 /* case 0: unchanged */
500 case 1:
501 note += (a->arpmem >> 4);
502 break;
503 case 2:
504 note += (a->arpmem & 0xf);
505 break;
506 }
507 break;
508 case 3: /* okt arpeggio 3: N-x, N, N+y */
509 switch (tick % 3) {
510 case 0:
511 note -= (a->arpmem >> 4);
512 break;
513 /* case 1: unchanged */
514 case 2:
515 note += (a->arpmem & 0xf);
516 break;
517 }
518 break;
519 case 4: /* okt arpeggio 4: N, N+y, N, N-x */
520 switch (tick % 4) {
521 /* case 0, case 2: unchanged */
522 case 1:
523 note += (a->arpmem & 0xf);
524 break;
525 case 3:
526 note -= (a->arpmem >> 4);
527 break;
528 }
529 break;
530 case 5: /* okt arpeggio 5: N-x, N+y, N, and nothing at tick 0 */
531 if (!tick)
532 break;
533 switch (tick % 3) {
534 /* case 0: unchanged */
535 case 1:
536 note -= (a->arpmem >> 4);
537 break;
538 case 2:
539 note += (a->arpmem & 0xf);
540 break;
541 }
542 break;
543 }
544 a->main.period = GetPeriod(flags, (UWORD)note << 1, a->speed);
545 a->ownper = 1;
546 }
547 }
548
DoPTEffect0(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)549 static int DoPTEffect0(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
550 {
551 UBYTE dat;
552
553 dat = UniGetByte();
554 if (!tick) {
555 if (!dat && (flags & UF_ARPMEM))
556 dat=a->arpmem;
557 else
558 a->arpmem=dat;
559 }
560 if (a->main.period)
561 DoArpeggio(tick, flags, a, 0);
562
563 return 0;
564 }
565
DoPTEffect1(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)566 static int DoPTEffect1(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
567 {
568 UBYTE dat;
569
570 dat = UniGetByte();
571 if (!tick && dat)
572 a->slidespeed = (UWORD)dat << 2;
573 if (a->main.period)
574 if (tick)
575 a->tmpperiod -= a->slidespeed;
576
577 return 0;
578 }
579
DoPTEffect2(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)580 static int DoPTEffect2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
581 {
582 UBYTE dat;
583
584 dat = UniGetByte();
585 if (!tick && dat)
586 a->slidespeed = (UWORD)dat << 2;
587 if (a->main.period)
588 if (tick)
589 a->tmpperiod += a->slidespeed;
590
591 return 0;
592 }
593
DoToneSlide(UWORD tick,MP_CONTROL * a)594 static void DoToneSlide(UWORD tick, MP_CONTROL *a)
595 {
596 if (!a->main.fadevol)
597 a->main.kick = (a->main.kick == KICK_NOTE)? KICK_NOTE : KICK_KEYOFF;
598 else
599 a->main.kick = (a->main.kick == KICK_NOTE)? KICK_ENV : KICK_ABSENT;
600
601 if (tick != 0) {
602 int dist;
603
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;
607
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;
612 else if (dist>0) {
613 a->tmpperiod-=a->portspeed;
614 a->main.period-=a->portspeed; /* dist>0, slide up */
615 } else {
616 a->tmpperiod+=a->portspeed;
617 a->main.period+=a->portspeed; /* dist<0, slide down */
618 }
619 } else
620 a->tmpperiod=a->main.period;
621 a->ownper = 1;
622 }
623
DoPTEffect3(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)624 static int DoPTEffect3(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
625 {
626 UBYTE dat;
627
628 dat=UniGetByte();
629 if ((!tick)&&(dat)) a->portspeed=(UWORD)dat<<2;
630 if (a->main.period)
631 DoToneSlide(tick, a);
632
633 return 0;
634 }
635
DoVibrato(UWORD tick,MP_CONTROL * a)636 static void DoVibrato(UWORD tick, MP_CONTROL *a)
637 {
638 UBYTE q;
639 UWORD temp = 0; /* silence warning */
640
641 if (!tick)
642 return;
643
644 q=(a->vibpos>>2)&0x1f;
645
646 switch (a->wavecontrol&3) {
647 case 0: /* sine */
648 temp=VibratoTable[q];
649 break;
650 case 1: /* ramp down */
651 q<<=3;
652 if (a->vibpos<0) q=255-q;
653 temp=q;
654 break;
655 case 2: /* square wave */
656 temp=255;
657 break;
658 case 3: /* random wave */
659 temp=getrandom(256);
660 break;
661 }
662
663 temp*=a->vibdepth;
664 temp>>=7;temp<<=2;
665
666 if (a->vibpos>=0)
667 a->main.period=a->tmpperiod+temp;
668 else
669 a->main.period=a->tmpperiod-temp;
670 a->ownper = 1;
671
672 if (tick != 0)
673 a->vibpos+=a->vibspd;
674 }
675
DoPTEffect4(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)676 static int DoPTEffect4(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
677 {
678 UBYTE dat;
679
680 dat=UniGetByte();
681 if (!tick) {
682 if (dat&0x0f) a->vibdepth=dat&0xf;
683 if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
684 }
685 if (a->main.period)
686 DoVibrato(tick, a);
687
688 return 0;
689 }
690
DoVolSlide(MP_CONTROL * a,UBYTE dat)691 static void DoVolSlide(MP_CONTROL *a, UBYTE dat)
692 {
693 if (dat&0xf) {
694 a->tmpvolume-=(dat&0x0f);
695 if (a->tmpvolume<0)
696 a->tmpvolume=0;
697 } else {
698 a->tmpvolume+=(dat>>4);
699 if (a->tmpvolume>64)
700 a->tmpvolume=64;
701 }
702 }
703
DoPTEffect5(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)704 static int DoPTEffect5(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
705 {
706 UBYTE dat;
707
708 dat=UniGetByte();
709 if (a->main.period)
710 DoToneSlide(tick, a);
711
712 if (tick)
713 DoVolSlide(a, dat);
714
715 return 0;
716 }
717
718 /* DoPTEffect6 after DoPTEffectA */
719
DoPTEffect7(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)720 static int DoPTEffect7(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
721 {
722 UBYTE dat;
723 UBYTE q;
724 UWORD temp = 0; /* silence warning */
725
726 dat=UniGetByte();
727 if (!tick) {
728 if (dat&0x0f) a->trmdepth=dat&0xf;
729 if (dat&0xf0) a->trmspd=(dat&0xf0)>>2;
730 }
731 if (a->main.period) {
732 q=(a->trmpos>>2)&0x1f;
733
734 switch ((a->wavecontrol>>4)&3) {
735 case 0: /* sine */
736 temp=VibratoTable[q];
737 break;
738 case 1: /* ramp down */
739 q<<=3;
740 if (a->trmpos<0) q=255-q;
741 temp=q;
742 break;
743 case 2: /* square wave */
744 temp=255;
745 break;
746 case 3: /* random wave */
747 temp=getrandom(256);
748 break;
749 }
750 temp*=a->trmdepth;
751 temp>>=6;
752
753 if (a->trmpos>=0) {
754 a->volume=a->tmpvolume+temp;
755 if (a->volume>64) a->volume=64;
756 } else {
757 a->volume=a->tmpvolume-temp;
758 if (a->volume<0) a->volume=0;
759 }
760 a->ownvol = 1;
761
762 if (tick)
763 a->trmpos+=a->trmspd;
764 }
765
766 return 0;
767 }
768
DoPTEffect8(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)769 static int DoPTEffect8(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
770 {
771 UBYTE dat;
772
773 dat = UniGetByte();
774 if (mod->panflag)
775 a->main.panning = mod->panning[channel] = dat;
776
777 return 0;
778 }
779
DoPTEffect9(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)780 static int DoPTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
781 {
782 UBYTE dat;
783
784 dat=UniGetByte();
785 if (!tick) {
786 if (dat) a->soffset=(UWORD)dat<<8;
787 a->main.start=a->hioffset|a->soffset;
788
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;
792 }
793
794 return 0;
795 }
796
DoPTEffectA(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)797 static int DoPTEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
798 {
799 UBYTE dat;
800
801 dat=UniGetByte();
802 if (tick)
803 DoVolSlide(a, dat);
804
805 return 0;
806 }
807
DoPTEffect6(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)
809 {
810 if (a->main.period)
811 DoVibrato(tick, a);
812 DoPTEffectA(tick, flags, a, mod, channel);
813
814 return 0;
815 }
816
DoPTEffectB(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)817 static int DoPTEffectB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
818 {
819 UBYTE dat;
820
821 dat=UniGetByte();
822
823 if (tick || mod->patdly2)
824 return 0;
825
826 /* Vincent Voois uses a nasty trick in "Universal Bolero" */
827 if (dat == mod->sngpos && mod->patbrk == mod->patpos)
828 return 0;
829
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)) ) )
834 {
835 /* if we don't loop, better not to skip the end of the
836 pattern, after all... so:
837 mod->patbrk=0; */
838 mod->posjmp=3;
839 } else {
840 /* if we were fading, adjust... */
841 if (mod->sngpos == (mod->numpos-1))
842 mod->volume=mod->initvolume>128?128:mod->initvolume;
843 mod->sngpos=dat;
844 mod->posjmp=2;
845 mod->patpos=0;
846 /* cancel the FT2 pattern loop (E60) bug.
847 * also see DoEEffects() below for it. */
848 if (flags & UF_FT2QUIRKS) mod->patbrk=0;
849 }
850
851 return 0;
852 }
853
DoPTEffectC(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)854 static int DoPTEffectC(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
855 {
856 UBYTE dat;
857
858 dat=UniGetByte();
859 if (tick) return 0;
860 if (dat==(UBYTE)-1) a->anote=dat=0; /* note cut */
861 else if (dat>64) dat=64;
862 a->tmpvolume=dat;
863
864 return 0;
865 }
866
DoPTEffectD(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)867 static int DoPTEffectD(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
868 {
869 UBYTE dat;
870
871 dat=UniGetByte();
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]];
876 }
877 mod->patbrk=dat;
878 if (!mod->posjmp) {
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
883 aspirin - Miod */
884 if ((mod->sngpos==mod->numpos-1)&&(dat)&&
885 ((mod->loop) || (mod->positions[mod->sngpos]==(mod->numpat-1) && !(flags&UF_NOWRAP)))) {
886 mod->sngpos=0;
887 mod->posjmp=2;
888 } else
889 mod->posjmp=3;
890 }
891
892 return 0;
893 }
894
DoEEffects(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel,UBYTE dat)895 static void DoEEffects(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod,
896 SWORD channel, UBYTE dat)
897 {
898 UBYTE nib = dat & 0xf;
899
900 switch (dat>>4) {
901 case 0x0: /* hardware filter toggle, not supported */
902 break;
903 case 0x1: /* fineslide up */
904 if (a->main.period)
905 if (!tick)
906 a->tmpperiod-=(nib<<2);
907 break;
908 case 0x2: /* fineslide dn */
909 if (a->main.period)
910 if (!tick)
911 a->tmpperiod+=(nib<<2);
912 break;
913 case 0x3: /* glissando ctrl */
914 a->glissando=nib;
915 break;
916 case 0x4: /* set vibrato waveform */
917 a->wavecontrol&=0xf0;
918 a->wavecontrol|=nib;
919 break;
920 case 0x5: /* set finetune */
921 if (a->main.period) {
922 if (flags&UF_XMPERIODS)
923 a->speed=nib+128;
924 else
925 a->speed=finetune[nib];
926 a->tmpperiod=GetPeriod(flags, (UWORD)a->main.note<<1,a->speed);
927 }
928 break;
929 case 0x6: /* set patternloop */
930 if (tick)
931 break;
932 if (nib) { /* set reppos or repcnt ? */
933 /* set repcnt, so check if repcnt already is set, which means we
934 are already looping */
935 if (a->pat_repcnt)
936 a->pat_repcnt--; /* already looping, decrease counter */
937 else {
938 #if 0
939 /* this would make walker.xm, shipped with Xsoundtracker,
940 play correctly, but it's better to remain compatible
941 with FT2 */
942 if ((!(flags&UF_NOWRAP))||(a->pat_reppos!=POS_NONE))
943 #endif
944 a->pat_repcnt=nib; /* not yet looping, so set repcnt */
945 }
946
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) {
951 mod->pat_repcrazy=1;
952 mod->patpos=0;
953 } else
954 mod->patpos=a->pat_reppos;
955 } else a->pat_reppos=POS_NONE;
956 } else {
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;
962 }
963 break;
964 case 0x7: /* set tremolo waveform */
965 a->wavecontrol&=0x0f;
966 a->wavecontrol|=nib<<4;
967 break;
968 case 0x8: /* set panning */
969 if (mod->panflag) {
970 if (nib<=8) nib<<=4;
971 else nib*=17;
972 a->main.panning=mod->panning[channel]=nib;
973 }
974 break;
975 case 0x9: /* retrig note */
976 /* do not retrigger on tick 0, until we are emulating FT2 and effect
977 data is zero */
978 if (!tick && !((flags & UF_FT2QUIRKS) && (!nib)))
979 break;
980 /* only retrigger if data nibble > 0, or if tick 0 (FT2 compat) */
981 if (nib || !tick) {
982 if (!a->retrig) {
983 /* when retrig counter reaches 0, reset counter and restart
984 the sample */
985 if (a->main.period) a->main.kick=KICK_NOTE;
986 a->retrig=nib;
987 }
988 a->retrig--; /* countdown */
989 }
990 break;
991 case 0xa: /* fine volume slide up */
992 if (tick)
993 break;
994 a->tmpvolume+=nib;
995 if (a->tmpvolume>64) a->tmpvolume=64;
996 break;
997 case 0xb: /* fine volume slide dn */
998 if (tick)
999 break;
1000 a->tmpvolume-=nib;
1001 if (a->tmpvolume<0)a->tmpvolume=0;
1002 break;
1003 case 0xc: /* cut note */
1004 /* When tick reaches the cut-note value, turn the volume to
1005 zero (just like on the amiga) */
1006 if (tick>=nib)
1007 a->tmpvolume=0; /* just turn the volume down */
1008 break;
1009 case 0xd: /* note delay */
1010 /* delay the start of the sample until tick==nib */
1011 if (!tick)
1012 a->main.notedelay=nib;
1013 else if (a->main.notedelay)
1014 a->main.notedelay--;
1015 break;
1016 case 0xe: /* pattern delay */
1017 if (!tick)
1018 if (!mod->patdly2)
1019 mod->patdly=nib+1; /* only once, when tick=0 */
1020 break;
1021 case 0xf: /* invert loop, not supported */
1022 break;
1023 }
1024 }
1025
DoPTEffectE(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1026 static int DoPTEffectE(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1027 {
1028 DoEEffects(tick, flags, a, mod, channel, UniGetByte());
1029
1030 return 0;
1031 }
1032
DoPTEffectF(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1033 static int DoPTEffectF(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1034 {
1035 UBYTE dat;
1036
1037 dat=UniGetByte();
1038 if (tick||mod->patdly2) return 0;
1039 if (mod->extspd&&(dat>=mod->bpmlimit))
1040 mod->bpm=dat;
1041 else
1042 if (dat) {
1043 mod->sngspd=(dat>=mod->bpmlimit)?mod->bpmlimit-1:dat;
1044 mod->vbtick=0;
1045 }
1046
1047 return 0;
1048 }
1049
1050 /*========== Scream Tracker effects */
1051
DoS3MEffectA(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1052 static int DoS3MEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1053 {
1054 UBYTE speed;
1055
1056 speed = UniGetByte();
1057
1058 if (tick || mod->patdly2)
1059 return 0;
1060
1061 if (speed > 128)
1062 speed -= 128;
1063 if (speed) {
1064 mod->sngspd = speed;
1065 mod->vbtick = 0;
1066 }
1067
1068 return 0;
1069 }
1070
DoS3MVolSlide(UWORD tick,UWORD flags,MP_CONTROL * a,UBYTE inf)1071 static void DoS3MVolSlide(UWORD tick, UWORD flags, MP_CONTROL *a, UBYTE inf)
1072 {
1073 UBYTE lo, hi;
1074
1075 if (inf)
1076 a->s3mvolslide=inf;
1077 else
1078 inf=a->s3mvolslide;
1079
1080 lo=inf&0xf;
1081 hi=inf>>4;
1082
1083 if (!lo) {
1084 if ((tick)||(flags&UF_S3MSLIDES)) a->tmpvolume+=hi;
1085 } else
1086 if (!hi) {
1087 if ((tick)||(flags&UF_S3MSLIDES)) a->tmpvolume-=lo;
1088 } else
1089 if (lo==0xf) {
1090 if (!tick) a->tmpvolume+=(hi?hi:0xf);
1091 } else
1092 if (hi==0xf) {
1093 if (!tick) a->tmpvolume-=(lo?lo:0xf);
1094 } else
1095 return;
1096
1097 if (a->tmpvolume<0)
1098 a->tmpvolume=0;
1099 else if (a->tmpvolume>64)
1100 a->tmpvolume=64;
1101 }
1102
DoS3MEffectD(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1103 static int DoS3MEffectD(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1104 {
1105 DoS3MVolSlide(tick, flags, a, UniGetByte());
1106
1107 return 1;
1108 }
1109
DoS3MSlideDn(UWORD tick,MP_CONTROL * a,UBYTE inf)1110 static void DoS3MSlideDn(UWORD tick, MP_CONTROL *a, UBYTE inf)
1111 {
1112 UBYTE hi,lo;
1113
1114 if (inf)
1115 a->slidespeed=inf;
1116 else
1117 inf=a->slidespeed;
1118
1119 hi=inf>>4;
1120 lo=inf&0xf;
1121
1122 if (hi==0xf) {
1123 if (!tick) a->tmpperiod+=(UWORD)lo<<2;
1124 } else
1125 if (hi==0xe) {
1126 if (!tick) a->tmpperiod+=lo;
1127 } else {
1128 if (tick) a->tmpperiod+=(UWORD)inf<<2;
1129 }
1130 }
1131
DoS3MEffectE(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1132 static int DoS3MEffectE(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1133 {
1134 UBYTE dat;
1135
1136 dat=UniGetByte();
1137 if (a->main.period)
1138 DoS3MSlideDn(tick, a,dat);
1139
1140 return 0;
1141 }
1142
DoS3MSlideUp(UWORD tick,MP_CONTROL * a,UBYTE inf)1143 static void DoS3MSlideUp(UWORD tick, MP_CONTROL *a, UBYTE inf)
1144 {
1145 UBYTE hi,lo;
1146
1147 if (inf) a->slidespeed=inf;
1148 else inf=a->slidespeed;
1149
1150 hi=inf>>4;
1151 lo=inf&0xf;
1152
1153 if (hi==0xf) {
1154 if (!tick) a->tmpperiod-=(UWORD)lo<<2;
1155 } else
1156 if (hi==0xe) {
1157 if (!tick) a->tmpperiod-=lo;
1158 } else {
1159 if (tick) a->tmpperiod-=(UWORD)inf<<2;
1160 }
1161 }
1162
DoS3MEffectF(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1163 static int DoS3MEffectF(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1164 {
1165 UBYTE dat;
1166
1167 dat=UniGetByte();
1168 if (a->main.period)
1169 DoS3MSlideUp(tick, a,dat);
1170
1171 return 0;
1172 }
1173
DoS3MEffectI(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1174 static int DoS3MEffectI(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1175 {
1176 UBYTE inf, on, off;
1177
1178 inf = UniGetByte();
1179 if (inf)
1180 a->s3mtronof = inf;
1181 else {
1182 inf = a->s3mtronof;
1183 if (!inf)
1184 return 0;
1185 }
1186
1187 if (!tick)
1188 return 0;
1189
1190 on=(inf>>4)+1;
1191 off=(inf&0xf)+1;
1192 a->s3mtremor%=(on+off);
1193 a->volume=(a->s3mtremor<on)?a->tmpvolume:0;
1194 a->ownvol=1;
1195 a->s3mtremor++;
1196
1197 return 0;
1198 }
1199
DoS3MEffectQ(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1200 static int DoS3MEffectQ(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1201 {
1202 UBYTE inf;
1203
1204 inf = UniGetByte();
1205 if (a->main.period) {
1206 if (inf) {
1207 a->s3mrtgslide=inf>>4;
1208 a->s3mrtgspeed=inf&0xf;
1209 }
1210
1211 /* only retrigger if low nibble > 0 */
1212 if (a->s3mrtgspeed>0) {
1213 if (!a->retrig) {
1214 /* when retrig counter reaches 0, reset counter and restart the
1215 sample */
1216 if (a->main.kick!=KICK_NOTE) a->main.kick=KICK_KEYOFF;
1217 a->retrig=a->s3mrtgspeed;
1218
1219 if ((tick)||(flags&UF_S3MSLIDES)) {
1220 switch (a->s3mrtgslide) {
1221 case 1:
1222 case 2:
1223 case 3:
1224 case 4:
1225 case 5:
1226 a->tmpvolume-=(1<<(a->s3mrtgslide-1));
1227 break;
1228 case 6:
1229 a->tmpvolume=(2*a->tmpvolume)/3;
1230 break;
1231 case 7:
1232 a->tmpvolume>>=1;
1233 break;
1234 case 9:
1235 case 0xa:
1236 case 0xb:
1237 case 0xc:
1238 case 0xd:
1239 a->tmpvolume+=(1<<(a->s3mrtgslide-9));
1240 break;
1241 case 0xe:
1242 a->tmpvolume=(3*a->tmpvolume)>>1;
1243 break;
1244 case 0xf:
1245 a->tmpvolume=a->tmpvolume<<1;
1246 break;
1247 }
1248 if (a->tmpvolume<0)
1249 a->tmpvolume=0;
1250 else if (a->tmpvolume>64)
1251 a->tmpvolume=64;
1252 }
1253 }
1254 a->retrig--; /* countdown */
1255 }
1256 }
1257
1258 return 0;
1259 }
1260
DoS3MEffectR(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1261 static int DoS3MEffectR(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1262 {
1263 UBYTE dat, q;
1264 UWORD temp=0; /* silence warning */
1265
1266 dat = UniGetByte();
1267 if (!tick) {
1268 if (dat&0x0f) a->trmdepth=dat&0xf;
1269 if (dat&0xf0) a->trmspd=(dat&0xf0)>>2;
1270 }
1271
1272 q=(a->trmpos>>2)&0x1f;
1273
1274 switch ((a->wavecontrol>>4)&3) {
1275 case 0: /* sine */
1276 temp=VibratoTable[q];
1277 break;
1278 case 1: /* ramp down */
1279 q<<=3;
1280 if (a->trmpos<0) q=255-q;
1281 temp=q;
1282 break;
1283 case 2: /* square wave */
1284 temp=255;
1285 break;
1286 case 3: /* random */
1287 temp=getrandom(256);
1288 break;
1289 }
1290
1291 temp*=a->trmdepth;
1292 temp>>=7;
1293
1294 if (a->trmpos>=0) {
1295 a->volume=a->tmpvolume+temp;
1296 if (a->volume>64) a->volume=64;
1297 } else {
1298 a->volume=a->tmpvolume-temp;
1299 if (a->volume<0) a->volume=0;
1300 }
1301 a->ownvol = 1;
1302
1303 if (tick)
1304 a->trmpos+=a->trmspd;
1305
1306 return 0;
1307 }
1308
DoS3MEffectT(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1309 static int DoS3MEffectT(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1310 {
1311 UBYTE tempo;
1312
1313 tempo = UniGetByte();
1314
1315 if (tick || mod->patdly2)
1316 return 0;
1317
1318 mod->bpm = (tempo < 32) ? 32 : tempo;
1319
1320 return 0;
1321 }
1322
DoS3MEffectU(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1323 static int DoS3MEffectU(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1324 {
1325 UBYTE dat, q;
1326 UWORD temp = 0; /* silence warning */
1327
1328 dat = UniGetByte();
1329 if (!tick) {
1330 if (dat&0x0f) a->vibdepth=dat&0xf;
1331 if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
1332 } else
1333 if (a->main.period) {
1334 q=(a->vibpos>>2)&0x1f;
1335
1336 switch (a->wavecontrol&3) {
1337 case 0: /* sine */
1338 temp=VibratoTable[q];
1339 break;
1340 case 1: /* ramp down */
1341 q<<=3;
1342 if (a->vibpos<0) q=255-q;
1343 temp=q;
1344 break;
1345 case 2: /* square wave */
1346 temp=255;
1347 break;
1348 case 3: /* random */
1349 temp=getrandom(256);
1350 break;
1351 }
1352
1353 temp*=a->vibdepth;
1354 temp>>=8;
1355
1356 if (a->vibpos>=0)
1357 a->main.period=a->tmpperiod+temp;
1358 else
1359 a->main.period=a->tmpperiod-temp;
1360 a->ownper = 1;
1361
1362 a->vibpos+=a->vibspd;
1363 }
1364
1365 return 0;
1366 }
1367
1368 /*========== Envelope helpers */
1369
DoKeyOff(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1370 static int DoKeyOff(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1371 {
1372 a->main.keyoff|=KEY_OFF;
1373 if ((!(a->main.volflg&EF_ON))||(a->main.volflg&EF_LOOP))
1374 a->main.keyoff=KEY_KILL;
1375
1376 return 0;
1377 }
1378
DoKeyFade(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1379 static int DoKeyFade(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1380 {
1381 UBYTE dat;
1382
1383 dat=UniGetByte();
1384 if ((tick>=dat)||(tick==mod->sngspd-1)) {
1385 a->main.keyoff=KEY_KILL;
1386 if (!(a->main.volflg&EF_ON))
1387 a->main.fadevol=0;
1388 }
1389
1390 return 0;
1391 }
1392
1393 /*========== Fast Tracker effects */
1394
1395 /* DoXMEffect6 after DoXMEffectA */
1396
DoXMEffectA(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1397 static int DoXMEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1398 {
1399 UBYTE inf, lo, hi;
1400
1401 inf = UniGetByte();
1402 if (inf)
1403 a->s3mvolslide = inf;
1404 else
1405 inf = a->s3mvolslide;
1406
1407 if (tick) {
1408 lo=inf&0xf;
1409 hi=inf>>4;
1410
1411 if (!hi) {
1412 a->tmpvolume-=lo;
1413 if (a->tmpvolume<0) a->tmpvolume=0;
1414 } else {
1415 a->tmpvolume+=hi;
1416 if (a->tmpvolume>64) a->tmpvolume=64;
1417 }
1418 }
1419
1420 return 0;
1421 }
1422
DoXMEffect6(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1423 static int DoXMEffect6(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1424 {
1425 if (a->main.period)
1426 DoVibrato(tick, a);
1427
1428 return DoXMEffectA(tick, flags, a, mod, channel);
1429 }
1430
DoXMEffectE1(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1431 static int DoXMEffectE1(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1432 {
1433 UBYTE dat;
1434
1435 dat=UniGetByte();
1436 if (!tick) {
1437 if (dat) a->fportupspd=dat;
1438 if (a->main.period)
1439 a->tmpperiod-=(a->fportupspd<<2);
1440 }
1441
1442 return 0;
1443 }
1444
DoXMEffectE2(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1445 static int DoXMEffectE2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1446 {
1447 UBYTE dat;
1448
1449 dat=UniGetByte();
1450 if (!tick) {
1451 if (dat) a->fportdnspd=dat;
1452 if (a->main.period)
1453 a->tmpperiod+=(a->fportdnspd<<2);
1454 }
1455
1456 return 0;
1457 }
1458
DoXMEffectEA(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1459 static int DoXMEffectEA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1460 {
1461 UBYTE dat;
1462
1463 dat=UniGetByte();
1464 if (!tick)
1465 if (dat) a->fslideupspd=dat;
1466 a->tmpvolume+=a->fslideupspd;
1467 if (a->tmpvolume>64) a->tmpvolume=64;
1468
1469 return 0;
1470 }
1471
DoXMEffectEB(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1472 static int DoXMEffectEB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1473 {
1474 UBYTE dat;
1475
1476 dat=UniGetByte();
1477 if (!tick)
1478 if (dat) a->fslidednspd=dat;
1479 a->tmpvolume-=a->fslidednspd;
1480 if (a->tmpvolume<0) a->tmpvolume=0;
1481
1482 return 0;
1483 }
1484
DoXMEffectG(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1485 static int DoXMEffectG(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1486 {
1487 mod->volume=UniGetByte()<<1;
1488 if (mod->volume>128) mod->volume=128;
1489
1490 return 0;
1491 }
1492
DoXMEffectH(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1493 static int DoXMEffectH(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1494 {
1495 UBYTE inf;
1496
1497 inf = UniGetByte();
1498
1499 if (tick) {
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;
1504
1505 if (mod->volume<0)
1506 mod->volume=0;
1507 else if (mod->volume>128)
1508 mod->volume=128;
1509 }
1510
1511 return 0;
1512 }
1513
DoXMEffectL(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1514 static int DoXMEffectL(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1515 {
1516 UBYTE dat;
1517
1518 dat=UniGetByte();
1519 if ((!tick)&&(a->main.i)) {
1520 UWORD points;
1521 INSTRUMENT *i=a->main.i;
1522 MP_VOICE *aout;
1523
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;
1528 }
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;
1532 }
1533 }
1534 }
1535
1536 return 0;
1537 }
1538
DoXMEffectP(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1539 static int DoXMEffectP(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1540 {
1541 UBYTE inf, lo, hi;
1542 SWORD pan;
1543
1544 inf = UniGetByte();
1545 if (!mod->panflag)
1546 return 0;
1547
1548 if (inf)
1549 a->pansspd = inf;
1550 else
1551 inf =a->pansspd;
1552
1553 if (tick) {
1554 lo=inf&0xf;
1555 hi=inf>>4;
1556
1557 /* slide right has absolute priority */
1558 if (hi)
1559 lo = 0;
1560
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);
1563 }
1564
1565 return 0;
1566 }
1567
DoXMEffectX1(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1568 static int DoXMEffectX1(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1569 {
1570 UBYTE dat;
1571
1572 dat = UniGetByte();
1573 if (dat)
1574 a->ffportupspd = dat;
1575 else
1576 dat = a->ffportupspd;
1577
1578 if (a->main.period)
1579 if (!tick) {
1580 a->main.period-=dat;
1581 a->tmpperiod-=dat;
1582 a->ownper = 1;
1583 }
1584
1585 return 0;
1586 }
1587
DoXMEffectX2(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1588 static int DoXMEffectX2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1589 {
1590 UBYTE dat;
1591
1592 dat = UniGetByte();
1593 if (dat)
1594 a->ffportdnspd=dat;
1595 else
1596 dat = a->ffportdnspd;
1597
1598 if (a->main.period)
1599 if (!tick) {
1600 a->main.period+=dat;
1601 a->tmpperiod+=dat;
1602 a->ownper = 1;
1603 }
1604
1605 return 0;
1606 }
1607
1608 /*========== Impulse Tracker effects */
1609
DoITToneSlide(UWORD tick,MP_CONTROL * a,UBYTE dat)1610 static void DoITToneSlide(UWORD tick, MP_CONTROL *a, UBYTE dat)
1611 {
1612 if (dat)
1613 a->portspeed = dat;
1614
1615 /* if we don't come from another note, ignore the slide and play the note
1616 as is */
1617 if (!a->oldnote || !a->main.period)
1618 return;
1619
1620 if ((!tick)&&(a->newsamp)){
1621 a->main.kick=KICK_NOTE;
1622 a->main.start=-1;
1623 } else
1624 a->main.kick=(a->main.kick==KICK_NOTE)?KICK_ENV:KICK_ABSENT;
1625
1626 if (tick) {
1627 int dist;
1628
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;
1632
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;
1637 else
1638 if (dist>0) {
1639 a->tmpperiod-=a->portspeed<<2;
1640 a->main.period-=a->portspeed<<2; /* dist>0 slide up */
1641 } else {
1642 a->tmpperiod+=a->portspeed<<2;
1643 a->main.period+=a->portspeed<<2; /* dist<0 slide down */
1644 }
1645 } else
1646 a->tmpperiod=a->main.period;
1647 a->ownper=1;
1648 }
1649
DoITEffectG(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1650 static int DoITEffectG(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1651 {
1652 DoITToneSlide(tick, a, UniGetByte());
1653
1654 return 0;
1655 }
1656
DoITVibrato(UWORD tick,MP_CONTROL * a,UBYTE dat)1657 static void DoITVibrato(UWORD tick, MP_CONTROL *a, UBYTE dat)
1658 {
1659 UBYTE q;
1660 UWORD temp=0;
1661
1662 if (!tick) {
1663 if (dat&0x0f) a->vibdepth=dat&0xf;
1664 if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
1665 }
1666 if (!a->main.period)
1667 return;
1668
1669 q=(a->vibpos>>2)&0x1f;
1670
1671 switch (a->wavecontrol&3) {
1672 case 0: /* sine */
1673 temp=VibratoTable[q];
1674 break;
1675 case 1: /* square wave */
1676 temp=255;
1677 break;
1678 case 2: /* ramp down */
1679 q<<=3;
1680 if (a->vibpos<0) q=255-q;
1681 temp=q;
1682 break;
1683 case 3: /* random */
1684 temp=getrandom(256);
1685 break;
1686 }
1687
1688 temp*=a->vibdepth;
1689 temp>>=8;
1690 temp<<=2;
1691
1692 if (a->vibpos>=0)
1693 a->main.period=a->tmpperiod+temp;
1694 else
1695 a->main.period=a->tmpperiod-temp;
1696 a->ownper=1;
1697
1698 a->vibpos+=a->vibspd;
1699 }
1700
DoITEffectH(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1701 static int DoITEffectH(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1702 {
1703 DoITVibrato(tick, a, UniGetByte());
1704
1705 return 0;
1706 }
1707
DoITEffectI(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1708 static int DoITEffectI(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1709 {
1710 UBYTE inf, on, off;
1711
1712 inf = UniGetByte();
1713 if (inf)
1714 a->s3mtronof = inf;
1715 else {
1716 inf = a->s3mtronof;
1717 if (!inf)
1718 return 0;
1719 }
1720
1721 on=(inf>>4);
1722 off=(inf&0xf);
1723
1724 a->s3mtremor%=(on+off);
1725 a->volume=(a->s3mtremor<on)?a->tmpvolume:0;
1726 a->ownvol = 1;
1727 a->s3mtremor++;
1728
1729 return 0;
1730 }
1731
DoITEffectM(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1732 static int DoITEffectM(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1733 {
1734 a->main.chanvol=UniGetByte();
1735 if (a->main.chanvol>64)
1736 a->main.chanvol=64;
1737 else if (a->main.chanvol<0)
1738 a->main.chanvol=0;
1739
1740 return 0;
1741 }
1742
DoITEffectN(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1743 static int DoITEffectN(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1744 {
1745 UBYTE inf, lo, hi;
1746
1747 inf = UniGetByte();
1748
1749 if (inf)
1750 a->chanvolslide = inf;
1751 else
1752 inf = a->chanvolslide;
1753
1754 lo=inf&0xf;
1755 hi=inf>>4;
1756
1757 if (!hi)
1758 a->main.chanvol-=lo;
1759 else
1760 if (!lo) {
1761 a->main.chanvol+=hi;
1762 } else
1763 if (hi==0xf) {
1764 if (!tick) a->main.chanvol-=lo;
1765 } else
1766 if (lo==0xf) {
1767 if (!tick) a->main.chanvol+=hi;
1768 }
1769
1770 if (a->main.chanvol<0)
1771 a->main.chanvol=0;
1772 else if (a->main.chanvol>64)
1773 a->main.chanvol=64;
1774
1775 return 0;
1776 }
1777
DoITEffectP(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1778 static int DoITEffectP(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1779 {
1780 UBYTE inf, lo, hi;
1781 SWORD pan;
1782
1783 inf = UniGetByte();
1784 if (inf)
1785 a->pansspd = inf;
1786 else
1787 inf = a->pansspd;
1788
1789 if (!mod->panflag)
1790 return 0;
1791
1792 lo=inf&0xf;
1793 hi=inf>>4;
1794
1795 pan=(a->main.panning==PAN_SURROUND)?PAN_CENTER:a->main.panning;
1796
1797 if (!hi)
1798 pan+=lo<<2;
1799 else
1800 if (!lo) {
1801 pan-=hi<<2;
1802 } else
1803 if (hi==0xf) {
1804 if (!tick) pan+=lo<<2;
1805 } else
1806 if (lo==0xf) {
1807 if (!tick) pan-=hi<<2;
1808 }
1809 a->main.panning=
1810 (pan<PAN_LEFT)?PAN_LEFT:(pan>PAN_RIGHT?PAN_RIGHT:pan);
1811
1812 return 0;
1813 }
1814
DoITEffectT(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1815 static int DoITEffectT(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1816 {
1817 UBYTE tempo;
1818 SWORD temp;
1819
1820 tempo = UniGetByte();
1821
1822 if (mod->patdly2)
1823 return 0;
1824
1825 temp = mod->bpm;
1826 if (tempo & 0x10)
1827 temp += (tempo & 0x0f);
1828 else
1829 temp -= tempo;
1830
1831 mod->bpm=(temp>255)?255:(temp<1?1:temp);
1832
1833 return 0;
1834 }
1835
DoITEffectU(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1836 static int DoITEffectU(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1837 {
1838 UBYTE dat, q;
1839 UWORD temp = 0; /* silence warning */
1840
1841 dat = UniGetByte();
1842 if (!tick) {
1843 if (dat&0x0f) a->vibdepth=dat&0xf;
1844 if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
1845 }
1846 if (a->main.period) {
1847 q=(a->vibpos>>2)&0x1f;
1848
1849 switch (a->wavecontrol&3) {
1850 case 0: /* sine */
1851 temp=VibratoTable[q];
1852 break;
1853 case 1: /* square wave */
1854 temp=255;
1855 break;
1856 case 2: /* ramp down */
1857 q<<=3;
1858 if (a->vibpos<0) q=255-q;
1859 temp=q;
1860 break;
1861 case 3: /* random */
1862 temp=getrandom(256);
1863 break;
1864 }
1865
1866 temp*=a->vibdepth;
1867 temp>>=8;
1868
1869 if (a->vibpos>=0)
1870 a->main.period=a->tmpperiod+temp;
1871 else
1872 a->main.period=a->tmpperiod-temp;
1873 a->ownper = 1;
1874
1875 a->vibpos+=a->vibspd;
1876 }
1877
1878 return 0;
1879 }
1880
DoITEffectW(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1881 static int DoITEffectW(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1882 {
1883 UBYTE inf, lo, hi;
1884
1885 inf = UniGetByte();
1886
1887 if (inf)
1888 mod->globalslide = inf;
1889 else
1890 inf = mod->globalslide;
1891
1892 lo=inf&0xf;
1893 hi=inf>>4;
1894
1895 if (!lo) {
1896 if (tick) mod->volume+=hi;
1897 } else
1898 if (!hi) {
1899 if (tick) mod->volume-=lo;
1900 } else
1901 if (lo==0xf) {
1902 if (!tick) mod->volume+=hi;
1903 } else
1904 if (hi==0xf) {
1905 if (!tick) mod->volume-=lo;
1906 }
1907
1908 if (mod->volume<0)
1909 mod->volume=0;
1910 else if (mod->volume>128)
1911 mod->volume=128;
1912
1913 return 0;
1914 }
1915
DoITEffectY(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1916 static int DoITEffectY(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1917 {
1918 UBYTE dat, q;
1919 SLONG temp = 0; /* silence warning */
1920
1921
1922 dat=UniGetByte();
1923 if (!tick) {
1924 if (dat&0x0f) a->panbdepth=(dat&0xf);
1925 if (dat&0xf0) a->panbspd=(dat&0xf0)>>4;
1926 }
1927 if (mod->panflag) {
1928 q=a->panbpos;
1929
1930 switch (a->panbwave) {
1931 case 0: /* sine */
1932 temp=PanbrelloTable[q];
1933 break;
1934 case 1: /* square wave */
1935 temp=(q<0x80)?64:0;
1936 break;
1937 case 2: /* ramp down */
1938 q<<=3;
1939 temp=q;
1940 break;
1941 case 3: /* random */
1942 temp=getrandom(256);
1943 break;
1944 }
1945
1946 temp*=a->panbdepth;
1947 temp=(temp/8)+mod->panning[channel];
1948
1949 a->main.panning=
1950 (temp<PAN_LEFT)?PAN_LEFT:(temp>PAN_RIGHT?PAN_RIGHT:temp);
1951 a->panbpos+=a->panbspd;
1952
1953 }
1954
1955 return 0;
1956 }
1957
1958 static void DoNNAEffects(MODULE *, MP_CONTROL *, UBYTE);
1959
1960 /* Impulse/Scream Tracker Sxx effects.
1961 All Sxx effects share the same memory space. */
DoITEffectS0(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1962 static int DoITEffectS0(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1963 {
1964 UBYTE dat, inf, c;
1965
1966 dat = UniGetByte();
1967 inf=dat&0xf;
1968 c=dat>>4;
1969
1970 if (!dat) {
1971 c=a->sseffect;
1972 inf=a->ssdata;
1973 } else {
1974 a->sseffect=c;
1975 a->ssdata=inf;
1976 }
1977
1978 switch (c) {
1979 case SS_GLISSANDO: /* S1x set glissando voice */
1980 DoEEffects(tick, flags, a, mod, channel, 0x30|inf);
1981 break;
1982 case SS_FINETUNE: /* S2x set finetune */
1983 DoEEffects(tick, flags, a, mod, channel, 0x50|inf);
1984 break;
1985 case SS_VIBWAVE: /* S3x set vibrato waveform */
1986 DoEEffects(tick, flags, a, mod, channel, 0x40|inf);
1987 break;
1988 case SS_TREMWAVE: /* S4x set tremolo waveform */
1989 DoEEffects(tick, flags, a, mod, channel, 0x70|inf);
1990 break;
1991 case SS_PANWAVE: /* S5x panbrello */
1992 a->panbwave=inf;
1993 break;
1994 case SS_FRAMEDELAY: /* S6x delay x number of frames (patdly) */
1995 DoEEffects(tick, flags, a, mod, channel, 0xe0|inf);
1996 break;
1997 case SS_S7EFFECTS: /* S7x instrument / NNA commands */
1998 DoNNAEffects(mod, a, inf);
1999 break;
2000 case SS_PANNING: /* S8x set panning position */
2001 DoEEffects(tick, flags, a, mod, channel, 0x80 | inf);
2002 break;
2003 case SS_SURROUND: /* S9x set surround sound */
2004 if (mod->panflag)
2005 a->main.panning = mod->panning[channel] = PAN_SURROUND;
2006 break;
2007 case SS_HIOFFSET: /* SAy set high order sample offset yxx00h */
2008 if (!tick) {
2009 a->hioffset=inf<<16;
2010 a->main.start=a->hioffset|a->soffset;
2011
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;
2015 }
2016 break;
2017 case SS_PATLOOP: /* SBx pattern loop */
2018 DoEEffects(tick, flags, a, mod, channel, 0x60|inf);
2019 break;
2020 case SS_NOTECUT: /* SCx notecut */
2021 if (!inf) inf = 1;
2022 DoEEffects(tick, flags, a, mod, channel, 0xC0|inf);
2023 break;
2024 case SS_NOTEDELAY: /* SDx notedelay */
2025 DoEEffects(tick, flags, a, mod, channel, 0xD0|inf);
2026 break;
2027 case SS_PATDELAY: /* SEx patterndelay */
2028 DoEEffects(tick, flags, a, mod, channel, 0xE0|inf);
2029 break;
2030 }
2031
2032 return 0;
2033 }
2034
2035 /*========== Impulse Tracker Volume/Pan Column effects */
2036
2037 /*
2038 * All volume/pan column effects share the same memory space.
2039 */
2040
DoVolEffects(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2041 static int DoVolEffects(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2042 {
2043 UBYTE c, inf;
2044
2045 c = UniGetByte();
2046 inf = UniGetByte();
2047
2048 if ((!c)&&(!inf)) {
2049 c=a->voleffect;
2050 inf=a->voldata;
2051 } else {
2052 a->voleffect=c;
2053 a->voldata=inf;
2054 }
2055
2056 if (c)
2057 switch (c) {
2058 case VOL_VOLUME:
2059 if (tick) break;
2060 if (inf>64) inf=64;
2061 a->tmpvolume=inf;
2062 break;
2063 case VOL_PANNING:
2064 if (mod->panflag)
2065 a->main.panning=inf;
2066 break;
2067 case VOL_VOLSLIDE:
2068 DoS3MVolSlide(tick, flags, a, inf);
2069 return 1;
2070 case VOL_PITCHSLIDEDN:
2071 if (a->main.period)
2072 DoS3MSlideDn(tick, a, inf);
2073 break;
2074 case VOL_PITCHSLIDEUP:
2075 if (a->main.period)
2076 DoS3MSlideUp(tick, a, inf);
2077 break;
2078 case VOL_PORTAMENTO:
2079 DoITToneSlide(tick, a, inf);
2080 break;
2081 case VOL_VIBRATO:
2082 DoITVibrato(tick, a, inf);
2083 break;
2084 }
2085
2086 return 0;
2087 }
2088
2089 /*========== UltraTracker effects */
2090
DoULTEffect9(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2091 static int DoULTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2092 {
2093 UWORD offset=UniGetWord();
2094
2095 if (offset)
2096 a->ultoffset=offset;
2097
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;
2102
2103 return 0;
2104 }
2105
2106 /*========== OctaMED effects */
2107
DoMEDSpeed(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2108 static int DoMEDSpeed(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2109 {
2110 UWORD speed=UniGetWord();
2111
2112 mod->bpm=speed;
2113
2114 return 0;
2115 }
2116
DoMEDEffectF1(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2117 static int DoMEDEffectF1(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2118 {
2119 DoEEffects(tick, flags, a, mod, channel, 0x90|(mod->sngspd/2));
2120
2121 return 0;
2122 }
2123
DoMEDEffectF2(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2124 static int DoMEDEffectF2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2125 {
2126 DoEEffects(tick, flags, a, mod, channel, 0xd0|(mod->sngspd/2));
2127
2128 return 0;
2129 }
2130
DoMEDEffectF3(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2131 static int DoMEDEffectF3(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2132 {
2133 DoEEffects(tick, flags, a, mod, channel, 0x90|(mod->sngspd/3));
2134
2135 return 0;
2136 }
2137
2138 /*========== Oktalyzer effects */
2139
DoOktArp(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2140 static int DoOktArp(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2141 {
2142 UBYTE dat, dat2;
2143
2144 dat2 = UniGetByte(); /* arpeggio style */
2145 dat = UniGetByte();
2146 if (!tick) {
2147 if (!dat && (flags & UF_ARPMEM))
2148 dat=a->arpmem;
2149 else
2150 a->arpmem=dat;
2151 }
2152 if (a->main.period)
2153 DoArpeggio(tick, flags, a, dat2);
2154
2155 return 0;
2156 }
2157
2158 /*========== General player functions */
2159
DoNothing(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2160 static int DoNothing(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2161 {
2162 UniSkipOpcode();
2163
2164 return 0;
2165 }
2166
2167 typedef int (*effect_func) (UWORD, UWORD, MP_CONTROL *, MODULE *, SWORD);
2168
2169 static effect_func effects[UNI_LAST] = {
2170 DoNothing, /* 0 */
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 */
2232 };
2233
pt_playeffects(MODULE * mod,SWORD channel,MP_CONTROL * a)2234 static int pt_playeffects(MODULE *mod, SWORD channel, MP_CONTROL *a)
2235 {
2236 UWORD tick = mod->vbtick;
2237 UWORD flags = mod->flags;
2238 UBYTE c;
2239 int explicitslides = 0;
2240 effect_func f;
2241
2242 while((c=UniGetByte()) != 0) {
2243 #if 0 /* this doesn't normally happen unless things go fubar elsewhere */
2244 if (c >= UNI_LAST)
2245 fprintf(stderr,"fubar'ed opcode %u\n",c);
2246 #endif
2247 f = effects[c];
2248 if (f != DoNothing)
2249 a->sliding = 0;
2250 explicitslides |= f(tick, flags, a, mod, channel);
2251 }
2252 return explicitslides;
2253 }
2254
DoNNAEffects(MODULE * mod,MP_CONTROL * a,UBYTE dat)2255 static void DoNNAEffects(MODULE *mod, MP_CONTROL *a, UBYTE dat)
2256 {
2257 int t;
2258 MP_VOICE *aout;
2259
2260 dat&=0xf;
2261 aout=(a->slave)?a->slave:NULL;
2262
2263 switch (dat) {
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;
2268 break;
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;
2276 }
2277 break;
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;
2282 break;
2283 case 0x3: /* set NNA note cut */
2284 a->main.nna=(a->main.nna&~NNA_MASK)|NNA_CUT;
2285 break;
2286 case 0x4: /* set NNA note continue */
2287 a->main.nna=(a->main.nna&~NNA_MASK)|NNA_CONTINUE;
2288 break;
2289 case 0x5: /* set NNA note off */
2290 a->main.nna=(a->main.nna&~NNA_MASK)|NNA_OFF;
2291 break;
2292 case 0x6: /* set NNA note fade */
2293 a->main.nna=(a->main.nna&~NNA_MASK)|NNA_FADE;
2294 break;
2295 case 0x7: /* disable volume envelope */
2296 if (aout)
2297 aout->main.volflg&=~EF_ON;
2298 break;
2299 case 0x8: /* enable volume envelope */
2300 if (aout)
2301 aout->main.volflg|=EF_ON;
2302 break;
2303 case 0x9: /* disable panning envelope */
2304 if (aout)
2305 aout->main.panflg&=~EF_ON;
2306 break;
2307 case 0xa: /* enable panning envelope */
2308 if (aout)
2309 aout->main.panflg|=EF_ON;
2310 break;
2311 case 0xb: /* disable pitch envelope */
2312 if (aout)
2313 aout->main.pitflg&=~EF_ON;
2314 break;
2315 case 0xc: /* enable pitch envelope */
2316 if (aout)
2317 aout->main.pitflg|=EF_ON;
2318 break;
2319 }
2320 }
2321
pt_UpdateVoices(MODULE * mod,int max_volume)2322 static void pt_UpdateVoices(MODULE *mod, int max_volume)
2323 {
2324 SWORD envpan,envvol,envpit,channel;
2325 UWORD playperiod;
2326 SLONG vibval,vibdpt;
2327 ULONG tmpvol;
2328
2329 MP_VOICE *aout;
2330 INSTRUMENT *i;
2331 SAMPLE *s;
2332
2333 mod->totalchn=mod->realchn=0;
2334 for (channel=0;channel<NUMVOICES(mod);channel++) {
2335 aout=&mod->voice[channel];
2336 i=aout->main.i;
2337 s=aout->main.s;
2338
2339 if (!s || !s->length) continue;
2340
2341 if (aout->main.period<40)
2342 aout->main.period=40;
2343 else if (aout->main.period>50000)
2344 aout->main.period=50000;
2345
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;
2350 aout->aswppos=0;
2351 }
2352
2353 envvol = 256;
2354 envpan = PAN_CENTER;
2355 envpit = 32;
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);
2369
2370 if (aout->cenv.flg & EF_ON)
2371 aout->masterperiod=GetPeriod(mod->flags,
2372 (UWORD)aout->main.note<<1, aout->master->speed);
2373 } else {
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);
2380 }
2381 if (aout->main.kick == KICK_NOTE) {
2382 aout->main.kick_flag = 1;
2383 }
2384 aout->main.kick=KICK_ABSENT;
2385
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);
2394
2395 /* fade out */
2396 if (mod->sngpos>=mod->numpos)
2397 tmpvol=0;
2398 else
2399 tmpvol=(tmpvol*max_volume)/128;
2400
2401 if ((aout->masterchn!=-1)&& mod->control[aout->masterchn].muted)
2402 Voice_SetVolume_internal(channel,0);
2403 else {
2404 Voice_SetVolume_internal(channel,tmpvol);
2405 if ((tmpvol)&&(aout->master)&&(aout->master->slave==aout))
2406 mod->realchn++;
2407 mod->totalchn++;
2408 }
2409
2410 if (aout->main.panning==PAN_SURROUND)
2411 Voice_SetPanning_internal(channel,PAN_SURROUND);
2412 else
2413 if ((mod->panflag)&&(aout->penv.flg & EF_ON))
2414 Voice_SetPanning_internal(channel,
2415 DoPan(envpan,aout->main.panning));
2416 else
2417 Voice_SetPanning_internal(channel,aout->main.panning);
2418
2419 if (aout->main.period && s->vibdepth)
2420 switch (s->vibtype) {
2421 case 0:
2422 vibval=avibtab[s->avibpos&127];
2423 if (aout->avibpos & 0x80) vibval=-vibval;
2424 break;
2425 case 1:
2426 vibval=64;
2427 if (aout->avibpos & 0x80) vibval=-vibval;
2428 break;
2429 case 2:
2430 vibval=63-(((aout->avibpos+128)&255)>>1);
2431 break;
2432 default:
2433 vibval=(((aout->avibpos+128)&255)>>1)-64;
2434 break;
2435 }
2436 else
2437 vibval=0;
2438
2439 if (s->vibflags & AV_IT) {
2440 if ((aout->aswppos>>8)<s->vibdepth) {
2441 aout->aswppos += s->vibsweep;
2442 vibdpt=aout->aswppos;
2443 } else
2444 vibdpt=s->vibdepth<<8;
2445 vibval=(vibval*vibdpt)>>16;
2446 if (aout->mflag) {
2447 if (!(mod->flags&UF_LINEAR)) vibval>>=1;
2448 aout->main.period-=vibval;
2449 }
2450 } else {
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;
2455 aout->aswppos++;
2456 } else
2457 vibdpt=s->vibdepth;
2458 } else {
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)
2462 vibdpt=s->vibdepth;
2463 else
2464 vibdpt=0;
2465 }
2466 vibval=(vibval*vibdpt)>>8;
2467 aout->main.period-=vibval;
2468 }
2469
2470 /* update vibrato position */
2471 aout->avibpos=(aout->avibpos+s->vibrate)&0xff;
2472
2473 /* process pitch envelope */
2474 playperiod=aout->main.period;
2475
2476 if ((aout->main.pitflg&EF_ON)&&(envpit!=32)) {
2477 long p1;
2478
2479 envpit-=32;
2480 if ((aout->main.note<<1)+envpit<=0) envpit=-(aout->main.note<<1);
2481
2482 p1=GetPeriod(mod->flags, ((UWORD)aout->main.note<<1)+envpit,
2483 aout->master->speed)-aout->masterperiod;
2484 if (p1>0) {
2485 if ((UWORD)(playperiod+p1)<=playperiod) {
2486 p1=0;
2487 aout->main.keyoff|=KEY_OFF;
2488 }
2489 } else if (p1<0) {
2490 if ((UWORD)(playperiod+p1)>=playperiod) {
2491 p1=0;
2492 aout->main.keyoff|=KEY_OFF;
2493 }
2494 }
2495 playperiod+=p1;
2496 }
2497
2498 if (!aout->main.fadevol) { /* check for a dead note (fadevol=0) */
2499 Voice_Stop_internal(channel);
2500 mod->totalchn--;
2501 if ((tmpvol)&&(aout->master)&&(aout->master->slave==aout))
2502 mod->realchn--;
2503 } else {
2504 Voice_SetFrequency_internal(channel,
2505 getfrequency(mod->flags,playperiod));
2506
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;
2511 else
2512 aout->main.fadevol=0;
2513 }
2514 }
2515
2516 md_bpm=mod->bpm+mod->relspd;
2517 if (md_bpm<32)
2518 md_bpm=32;
2519 else if ((!(mod->flags&UF_HIGHBPM)) && md_bpm>255)
2520 md_bpm=255;
2521 }
2522 }
2523
2524 /* Handles new notes or instruments */
pt_Notes(MODULE * mod)2525 static void pt_Notes(MODULE *mod)
2526 {
2527 SWORD channel;
2528 MP_CONTROL *a;
2529 UBYTE c,inst;
2530 int tr,funky; /* funky is set to indicate note or instrument change */
2531
2532 for (channel=0;channel<mod->numchn;channel++) {
2533 a=&mod->control[channel];
2534
2535 if (mod->sngpos>=mod->numpos) {
2536 tr=mod->numtrk;
2537 mod->numrow=0;
2538 } else {
2539 tr=mod->patterns[(mod->positions[mod->sngpos]*mod->numchn)+channel];
2540 mod->numrow=mod->pattrows[mod->positions[mod->sngpos]];
2541 }
2542
2543 a->row=(tr<mod->numtrk)?UniFindRow(mod->tracks[tr],mod->patpos):NULL;
2544 a->newsamp=0;
2545 if (!mod->vbtick) a->main.notedelay=0;
2546
2547 if (!a->row) continue;
2548 UniSetRow(a->row);
2549 funky=0;
2550
2551 while((c=UniGetByte()) != 0)
2552 switch (c) {
2553 case UNI_NOTE:
2554 funky|=1;
2555 a->oldnote=a->anote,a->anote=UniGetByte();
2556 a->main.kick =KICK_NOTE;
2557 a->main.start=-1;
2558 a->sliding=0;
2559
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;
2564 break;
2565 case UNI_INSTRUMENT:
2566 inst=UniGetByte();
2567 if (inst>=mod->numins) break; /* safety valve */
2568 funky|=2;
2569 a->main.i=(mod->flags & UF_INST)?&mod->instruments[inst]:NULL;
2570 a->retrig=0;
2571 a->s3mtremor=0;
2572 a->ultoffset=0;
2573 a->main.sample=inst;
2574 break;
2575 default:
2576 UniSkipOpcode();
2577 break;
2578 }
2579
2580 if (funky) {
2581 INSTRUMENT *i;
2582 SAMPLE *s;
2583
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];
2588 } else {
2589 a->main.note=a->anote;
2590 s=&mod->samples[a->main.sample];
2591 }
2592
2593 if (a->main.s!=s) {
2594 a->main.s=s;
2595 a->newsamp=a->main.period;
2596 }
2597
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;
2604
2605 a->main.handle=s->handle;
2606 a->speed=s->speed;
2607
2608 if (i) {
2609 if ((mod->panflag)&&(i->flags & IF_PITCHPAN)
2610 &&(a->main.panning!=PAN_SURROUND)){
2611 a->main.panning+=
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;
2617 }
2618 a->main.pitflg=i->pitflg;
2619 a->main.volflg=i->volflg;
2620 a->main.panflg=i->panflg;
2621 a->main.nna=i->nnatype;
2622 a->dca=i->dca;
2623 a->dct=i->dct;
2624 } else {
2625 a->main.pitflg=a->main.volflg=a->main.panflg=0;
2626 a->main.nna=a->dca=0;
2627 a->dct=DCT_OFF;
2628 }
2629
2630 if (funky&2) /* instrument change */ {
2631 /* IT random volume variations: 0:8 bit fixed, and one bit for
2632 sign. */
2633 a->volume=a->tmpvolume=s->volume;
2634 if ((s)&&(i)) {
2635 if (i->rvolvar) {
2636 a->volume=a->tmpvolume=s->volume+
2637 ((s->volume*((SLONG)i->rvolvar*(SLONG)getrandom(512)
2638 ))/25600);
2639 if (a->volume<0)
2640 a->volume=a->tmpvolume=0;
2641 else if (a->volume>64)
2642 a->volume=a->tmpvolume=64;
2643 }
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;
2651 }
2652 }
2653 }
2654
2655 a->wantedperiod=a->tmpperiod=
2656 GetPeriod(mod->flags, (UWORD)a->main.note<<1,a->speed);
2657 a->main.keyoff=KEY_KICK;
2658 }
2659 }
2660 }
2661
2662 /* Handles effects */
pt_EffectsPass1(MODULE * mod)2663 static void pt_EffectsPass1(MODULE *mod)
2664 {
2665 SWORD channel;
2666 MP_CONTROL *a;
2667 MP_VOICE *aout;
2668 int explicitslides;
2669
2670 for (channel=0;channel<mod->numchn;channel++) {
2671 a=&mod->control[channel];
2672
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;
2678 }
2679
2680 if (!a->row) continue;
2681 UniSetRow(a->row);
2682
2683 a->ownper=a->ownvol=0;
2684 explicitslides = pt_playeffects(mod, channel, a);
2685
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;
2692 }
2693
2694 if (!a->ownper)
2695 a->main.period=a->tmpperiod;
2696 if (!a->ownvol)
2697 a->volume=a->tmpvolume;
2698
2699 if (a->main.s) {
2700 if (a->main.i)
2701 a->main.outvolume=
2702 (a->volume*a->main.s->globvol*a->main.i->globvol)>>10;
2703 else
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;
2709 }
2710 }
2711 }
2712
2713 /* NNA management */
pt_NNA(MODULE * mod)2714 static void pt_NNA(MODULE *mod)
2715 {
2716 SWORD channel;
2717 MP_CONTROL *a;
2718
2719 for (channel=0;channel<mod->numchn;channel++) {
2720 a=&mod->control[channel];
2721
2722 if (a->main.kick==KICK_NOTE) {
2723 BOOL kill=0;
2724
2725 if (a->slave) {
2726 MP_VOICE *aout;
2727
2728 aout=a->slave;
2729 if (aout->main.nna & NNA_MASK) {
2730 /* Make sure the old MP_VOICE channel knows it has no
2731 master now ! */
2732 a->slave=NULL;
2733 /* assume the channel is taken by NNA */
2734 aout->mflag=0;
2735
2736 switch (aout->main.nna) {
2737 case NNA_CONTINUE: /* continue note, do nothing */
2738 break;
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;
2744 break;
2745 case NNA_FADE:
2746 aout->main.keyoff |= KEY_FADE;
2747 break;
2748 }
2749 }
2750 }
2751
2752 if (a->dct!=DCT_OFF) {
2753 int t;
2754
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)) {
2759 kill=0;
2760 switch (a->dct) {
2761 case DCT_NOTE:
2762 if (a->main.note==mod->voice[t].main.note)
2763 kill=1;
2764 break;
2765 case DCT_SAMPLE:
2766 if (a->main.handle==mod->voice[t].main.handle)
2767 kill=1;
2768 break;
2769 case DCT_INST:
2770 kill=1;
2771 break;
2772 }
2773 if (kill)
2774 switch (a->dca) {
2775 case DCA_CUT:
2776 mod->voice[t].main.fadevol=0;
2777 break;
2778 case DCA_OFF:
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;
2783 break;
2784 case DCA_FADE:
2785 mod->voice[t].main.keyoff|=KEY_FADE;
2786 break;
2787 }
2788 }
2789 }
2790 } /* if (a->main.kick==KICK_NOTE) */
2791 }
2792 }
2793
2794 /* Setup module and NNA voices */
pt_SetupVoices(MODULE * mod)2795 static void pt_SetupVoices(MODULE *mod)
2796 {
2797 SWORD channel;
2798 MP_CONTROL *a;
2799 MP_VOICE *aout;
2800
2801 for (channel=0;channel<mod->numchn;channel++) {
2802 a=&mod->control[channel];
2803
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
2807 here */
2808 if (mod->flags&UF_NNA) {
2809 if (!a->slave) {
2810 int newchn;
2811
2812 if ((newchn=MP_FindEmptyChannel(mod))!=-1)
2813 a->slave=&mod->voice[a->slavechn=newchn];
2814 }
2815 } else
2816 a->slave=&mod->voice[a->slavechn=channel];
2817
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;
2821 aout->master=a;
2822 a->slave=aout;
2823 aout->masterchn=channel;
2824 aout->mflag=1;
2825 }
2826 } else
2827 aout=a->slave;
2828
2829 if (aout)
2830 aout->main=a->main;
2831 a->main.kick=KICK_ABSENT;
2832 }
2833 }
2834
2835 /* second effect pass */
pt_EffectsPass2(MODULE * mod)2836 static void pt_EffectsPass2(MODULE *mod)
2837 {
2838 SWORD channel;
2839 MP_CONTROL *a;
2840 UBYTE c;
2841
2842 for (channel=0;channel<mod->numchn;channel++) {
2843 a=&mod->control[channel];
2844
2845 if (!a->row) continue;
2846 UniSetRow(a->row);
2847
2848 while((c=UniGetByte()) != 0)
2849 if (c==UNI_ITEFFECTS0) {
2850 c=UniGetByte();
2851 if ((c>>4)==SS_S7EFFECTS)
2852 DoNNAEffects(mod, a, c&0xf);
2853 } else
2854 UniSkipOpcode();
2855 }
2856 }
2857
Player_HandleTick(void)2858 void Player_HandleTick(void)
2859 {
2860 SWORD channel;
2861 int max_volume;
2862
2863 #if 0
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 */
2866 if (isfirst) {
2867 isfirst--;
2868 return;
2869 }
2870 #endif
2871
2872 if ((!pf)||(pf->forbid)||(pf->sngpos>=pf->numpos)) return;
2873
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;
2878
2879 if (++pf->vbtick>=pf->sngspd) {
2880 if (pf->pat_repcrazy)
2881 pf->pat_repcrazy=0; /* play 2 times row 0 */
2882 else
2883 pf->patpos++;
2884 pf->vbtick=0;
2885
2886 /* process pattern-delay. pf->patdly2 is the counter and pf->patdly is
2887 the command memory. */
2888 if (pf->patdly)
2889 pf->patdly2=pf->patdly,pf->patdly=0;
2890 if (pf->patdly2) {
2891 /* patterndelay active */
2892 if (--pf->patdly2)
2893 /* so turn back pf->patpos by 1 */
2894 if (pf->patpos) pf->patpos--;
2895 }
2896
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))
2900 pf->posjmp=3;
2901
2902 if (pf->posjmp) {
2903 pf->patpos=pf->numrow?(pf->patbrk%pf->numrow):0;
2904 pf->pat_repcrazy=0;
2905 pf->sngpos+=(pf->posjmp-2);
2906 for (channel=0;channel<pf->numchn;channel++)
2907 pf->control[channel].pat_reppos=-1;
2908
2909 pf->patbrk=pf->posjmp=0;
2910
2911 if (pf->sngpos<0) pf->sngpos=(SWORD)(pf->numpos-1);
2912
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;
2922 else
2923 pf->sngspd=6;
2924 pf->bpm=pf->inittempo<32?32:pf->inittempo;
2925 }
2926 }
2927 }
2928
2929 if (!pf->patdly2)
2930 pt_Notes(pf);
2931 }
2932
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))&&
2936 (pf->fadeout))
2937 max_volume=pf->numrow?((pf->numrow-pf->patpos)*128)/pf->numrow:0;
2938 else
2939 max_volume=128;
2940
2941 pt_EffectsPass1(pf);
2942 if (pf->flags&UF_NNA)
2943 pt_NNA(pf);
2944 pt_SetupVoices(pf);
2945 pt_EffectsPass2(pf);
2946
2947 /* now set up the actual hardware channel playback information */
2948 pt_UpdateVoices(pf, max_volume);
2949 }
2950
Player_Init_internal(MODULE * mod)2951 static void Player_Init_internal(MODULE* mod)
2952 {
2953 int t;
2954
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];
2958 }
2959
2960 mod->sngtime=0;
2961 mod->sngremainder=0;
2962
2963 mod->pat_repcrazy=0;
2964 mod->sngpos=0;
2965 if(mod->initspeed!=0)
2966 mod->sngspd=mod->initspeed<32?mod->initspeed:32;
2967 else
2968 mod->sngspd=6;
2969 mod->volume=mod->initvolume>128?128:mod->initvolume;
2970
2971 mod->vbtick=mod->sngspd;
2972 mod->patdly=0;
2973 mod->patdly2=0;
2974 mod->bpm=mod->inittempo<32?32:mod->inittempo;
2975 mod->realchn=0;
2976
2977 mod->patpos=0;
2978 mod->posjmp=2; /* make sure the player fetches the first note */
2979 mod->numrow=-1;
2980 mod->patbrk=0;
2981 }
2982
Player_Init(MODULE * mod)2983 int Player_Init(MODULE* mod)
2984 {
2985 mod->extspd=1;
2986 mod->panflag=1;
2987 mod->wrap=0;
2988 mod->loop=1;
2989 mod->fadeout=0;
2990
2991 mod->relspd=0;
2992
2993 /* make sure the player doesn't start with garbage */
2994 if (!(mod->control=(MP_CONTROL*)MikMod_calloc(mod->numchn,sizeof(MP_CONTROL))))
2995 return 1;
2996 if (!(mod->voice=(MP_VOICE*)MikMod_calloc(md_sngchn,sizeof(MP_VOICE))))
2997 return 1;
2998
2999 /* mod->numvoices was used during loading to clamp md_sngchn.
3000 After loading it's used to remember how big mod->voice is.
3001 */
3002 mod->numvoices = md_sngchn;
3003
3004 Player_Init_internal(mod);
3005 return 0;
3006 }
3007
Player_Exit_internal(MODULE * mod)3008 void Player_Exit_internal(MODULE* mod)
3009 {
3010 if (!mod)
3011 return;
3012
3013 /* Stop playback if necessary */
3014 if (mod==pf) {
3015 Player_Stop_internal();
3016 pf=NULL;
3017 }
3018
3019 MikMod_free(mod->control);
3020 MikMod_free(mod->voice);
3021 mod->control=NULL;
3022 mod->voice=NULL;
3023 }
3024
Player_Exit(MODULE * mod)3025 void Player_Exit(MODULE* mod)
3026 {
3027 MUTEX_LOCK(vars);
3028 Player_Exit_internal(mod);
3029 MUTEX_UNLOCK(vars);
3030 }
3031
Player_SetVolume(SWORD volume)3032 MIKMODAPI void Player_SetVolume(SWORD volume)
3033 {
3034 MUTEX_LOCK(vars);
3035 if (pf) {
3036 pf->volume=(volume<0)?0:(volume>128)?128:volume;
3037 pf->initvolume=pf->volume;
3038 }
3039 MUTEX_UNLOCK(vars);
3040 }
3041
Player_GetModule(void)3042 MIKMODAPI MODULE* Player_GetModule(void)
3043 {
3044 MODULE* result;
3045
3046 MUTEX_LOCK(vars);
3047 result=pf;
3048 MUTEX_UNLOCK(vars);
3049
3050 return result;
3051 }
3052
Player_Start(MODULE * mod)3053 MIKMODAPI void Player_Start(MODULE *mod)
3054 {
3055 int t;
3056
3057 if (!mod)
3058 return;
3059
3060 if (!MikMod_Active())
3061 MikMod_EnableOutput();
3062
3063 mod->forbid=0;
3064
3065 MUTEX_LOCK(vars);
3066 if (pf!=mod) {
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);
3070 }
3071 pf=mod;
3072 MUTEX_UNLOCK(vars);
3073 }
3074
Player_Stop_internal(void)3075 void Player_Stop_internal(void)
3076 {
3077 if (!md_sfxchn) MikMod_DisableOutput_internal();
3078 if (pf) pf->forbid=1;
3079 pf=NULL;
3080 }
3081
Player_Stop(void)3082 MIKMODAPI void Player_Stop(void)
3083 {
3084 MUTEX_LOCK(vars);
3085 Player_Stop_internal();
3086 MUTEX_UNLOCK(vars);
3087 }
3088
Player_Active(void)3089 MIKMODAPI BOOL Player_Active(void)
3090 {
3091 BOOL result=0;
3092
3093 MUTEX_LOCK(vars);
3094 if (pf)
3095 result=(!(pf->sngpos>=pf->numpos));
3096 MUTEX_UNLOCK(vars);
3097
3098 return result;
3099 }
3100
Player_NextPosition(void)3101 MIKMODAPI void Player_NextPosition(void)
3102 {
3103 MUTEX_LOCK(vars);
3104 if (pf) {
3105 int t;
3106
3107 pf->forbid=1;
3108 pf->posjmp=3;
3109 pf->patbrk=0;
3110 pf->vbtick=pf->sngspd;
3111
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;
3116 }
3117 for (t=0;t<pf->numchn;t++) {
3118 pf->control[t].main.i=NULL;
3119 pf->control[t].main.s=NULL;
3120 }
3121 pf->forbid=0;
3122 }
3123 MUTEX_UNLOCK(vars);
3124 }
3125
Player_PrevPosition(void)3126 MIKMODAPI void Player_PrevPosition(void)
3127 {
3128 MUTEX_LOCK(vars);
3129 if (pf) {
3130 int t;
3131
3132 pf->forbid=1;
3133 pf->posjmp=1;
3134 pf->patbrk=0;
3135 pf->vbtick=pf->sngspd;
3136
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;
3141 }
3142 for (t=0;t<pf->numchn;t++) {
3143 pf->control[t].main.i=NULL;
3144 pf->control[t].main.s=NULL;
3145 }
3146 pf->forbid=0;
3147 }
3148 MUTEX_UNLOCK(vars);
3149 }
3150
Player_SetPosition(UWORD pos)3151 MIKMODAPI void Player_SetPosition(UWORD pos)
3152 {
3153 MUTEX_LOCK(vars);
3154 if (pf) {
3155 int t;
3156
3157 pf->forbid=1;
3158 if (pos>=pf->numpos) pos=pf->numpos;
3159 pf->posjmp=2;
3160 pf->patbrk=0;
3161 pf->sngpos=pos;
3162 pf->vbtick=pf->sngspd;
3163
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;
3168 }
3169 for (t=0;t<pf->numchn;t++) {
3170 pf->control[t].main.i=NULL;
3171 pf->control[t].main.s=NULL;
3172 }
3173 pf->forbid=0;
3174
3175 if (!pos)
3176 Player_Init_internal(pf);
3177 }
3178 MUTEX_UNLOCK(vars);
3179 }
3180
Player_Unmute_internal(SLONG arg1,va_list ap)3181 static void Player_Unmute_internal(SLONG arg1,va_list ap)
3182 {
3183 SLONG t,arg2,arg3=0;
3184
3185 if (pf) {
3186 switch (arg1) {
3187 case MUTE_INCLUSIVE:
3188 if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3189 (arg2>arg3)||(arg3>=pf->numchn))
3190 return;
3191 for (;arg2<pf->numchn && arg2<=arg3;arg2++)
3192 pf->control[arg2].muted=0;
3193 break;
3194 case MUTE_EXCLUSIVE:
3195 if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3196 (arg2>arg3)||(arg3>=pf->numchn))
3197 return;
3198 for (t=0;t<pf->numchn;t++) {
3199 if ((t>=arg2) && (t<=arg3))
3200 continue;
3201 pf->control[t].muted=0;
3202 }
3203 break;
3204 default:
3205 if (arg1<pf->numchn) pf->control[arg1].muted=0;
3206 break;
3207 }
3208 }
3209 }
3210
Player_Unmute(SLONG arg1,...)3211 MIKMODAPI void Player_Unmute(SLONG arg1, ...)
3212 {
3213 va_list args;
3214
3215 va_start(args,arg1);
3216 MUTEX_LOCK(vars);
3217 Player_Unmute_internal(arg1,args);
3218 MUTEX_UNLOCK(vars);
3219 va_end(args);
3220 }
3221
Player_Mute_internal(SLONG arg1,va_list ap)3222 static void Player_Mute_internal(SLONG arg1,va_list ap)
3223 {
3224 SLONG t,arg2,arg3=0;
3225
3226 if (pf) {
3227 switch (arg1) {
3228 case MUTE_INCLUSIVE:
3229 if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3230 (arg2>arg3)||(arg3>=pf->numchn))
3231 return;
3232 for (;arg2<pf->numchn && arg2<=arg3;arg2++)
3233 pf->control[arg2].muted=1;
3234 break;
3235 case MUTE_EXCLUSIVE:
3236 if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3237 (arg2>arg3)||(arg3>=pf->numchn))
3238 return;
3239 for (t=0;t<pf->numchn;t++) {
3240 if ((t>=arg2) && (t<=arg3))
3241 continue;
3242 pf->control[t].muted=1;
3243 }
3244 break;
3245 default:
3246 if (arg1<pf->numchn)
3247 pf->control[arg1].muted=1;
3248 break;
3249 }
3250 }
3251 }
3252
Player_Mute(SLONG arg1,...)3253 MIKMODAPI void Player_Mute(SLONG arg1,...)
3254 {
3255 va_list args;
3256
3257 va_start(args,arg1);
3258 MUTEX_LOCK(vars);
3259 Player_Mute_internal(arg1,args);
3260 MUTEX_UNLOCK(vars);
3261 va_end(args);
3262 }
3263
Player_ToggleMute_internal(SLONG arg1,va_list ap)3264 static void Player_ToggleMute_internal(SLONG arg1,va_list ap)
3265 {
3266 SLONG arg2,arg3=0;
3267 ULONG t;
3268
3269 if (pf) {
3270 switch (arg1) {
3271 case MUTE_INCLUSIVE:
3272 if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3273 (arg2>arg3)||(arg3>=pf->numchn))
3274 return;
3275 for (;arg2<pf->numchn && arg2<=arg3;arg2++)
3276 pf->control[arg2].muted=1-pf->control[arg2].muted;
3277 break;
3278 case MUTE_EXCLUSIVE:
3279 if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3280 (arg2>arg3)||(arg3>=pf->numchn))
3281 return;
3282 for (t=0;t<pf->numchn;t++) {
3283 if ((t>=arg2) && (t<=arg3))
3284 continue;
3285 pf->control[t].muted=1-pf->control[t].muted;
3286 }
3287 break;
3288 default:
3289 if (arg1<pf->numchn)
3290 pf->control[arg1].muted=1-pf->control[arg1].muted;
3291 break;
3292 }
3293 }
3294 }
3295
Player_ToggleMute(SLONG arg1,...)3296 MIKMODAPI void Player_ToggleMute(SLONG arg1,...)
3297 {
3298 va_list args;
3299
3300 va_start(args,arg1);
3301 MUTEX_LOCK(vars);
3302 Player_ToggleMute_internal(arg1,args);
3303 MUTEX_UNLOCK(vars);
3304 va_end(args);
3305 }
3306
Player_Muted(UBYTE chan)3307 MIKMODAPI BOOL Player_Muted(UBYTE chan)
3308 {
3309 BOOL result=1;
3310
3311 MUTEX_LOCK(vars);
3312 if (pf)
3313 result=(chan<pf->numchn)?pf->control[chan].muted:1;
3314 MUTEX_UNLOCK(vars);
3315
3316 return result;
3317 }
3318
Player_GetChannelVoice(UBYTE chan)3319 MIKMODAPI int Player_GetChannelVoice(UBYTE chan)
3320 {
3321 int result=0;
3322
3323 MUTEX_LOCK(vars);
3324 if (pf)
3325 result=(chan<pf->numchn)?pf->control[chan].slavechn:-1;
3326 MUTEX_UNLOCK(vars);
3327
3328 return result;
3329 }
3330
Player_GetChannelPeriod(UBYTE chan)3331 MIKMODAPI UWORD Player_GetChannelPeriod(UBYTE chan)
3332 {
3333 UWORD result=0;
3334
3335 MUTEX_LOCK(vars);
3336 if (pf)
3337 result=(chan<pf->numchn)?pf->control[chan].main.period:0;
3338 MUTEX_UNLOCK(vars);
3339
3340 return result;
3341 }
3342
Player_Paused_internal(void)3343 BOOL Player_Paused_internal(void)
3344 {
3345 return pf?pf->forbid:1;
3346 }
3347
Player_Paused(void)3348 MIKMODAPI BOOL Player_Paused(void)
3349 {
3350 BOOL result;
3351
3352 MUTEX_LOCK(vars);
3353 result=Player_Paused_internal();
3354 MUTEX_UNLOCK(vars);
3355
3356 return result;
3357 }
3358
Player_TogglePause(void)3359 MIKMODAPI void Player_TogglePause(void)
3360 {
3361 MUTEX_LOCK(vars);
3362 if (pf)
3363 pf->forbid=1-pf->forbid;
3364 MUTEX_UNLOCK(vars);
3365 }
3366
Player_SetSpeed(UWORD speed)3367 MIKMODAPI void Player_SetSpeed(UWORD speed)
3368 {
3369 MUTEX_LOCK(vars);
3370 if (pf)
3371 pf->sngspd=speed?(speed<32?speed:32):1;
3372 MUTEX_UNLOCK(vars);
3373 }
3374
Player_SetTempo(UWORD tempo)3375 MIKMODAPI void Player_SetTempo(UWORD tempo)
3376 {
3377 if (tempo<32) tempo=32;
3378 MUTEX_LOCK(vars);
3379 if (pf) {
3380 if ((!(pf->flags&UF_HIGHBPM))&&(tempo>255)) tempo=255;
3381 pf->bpm=tempo;
3382 }
3383 MUTEX_UNLOCK(vars);
3384 }
3385
Player_QueryVoices(UWORD numvoices,VOICEINFO * vinfo)3386 MIKMODAPI int Player_QueryVoices(UWORD numvoices, VOICEINFO *vinfo)
3387 {
3388 int i;
3389
3390 if (numvoices > md_sngchn)
3391 numvoices = md_sngchn;
3392
3393 MUTEX_LOCK(vars);
3394 if (pf)
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;
3403 }
3404 MUTEX_UNLOCK(vars);
3405
3406 return numvoices;
3407 }
3408
3409 /* Get current module order */
Player_GetOrder(void)3410 MIKMODAPI int Player_GetOrder(void)
3411 {
3412 int ret;
3413 MUTEX_LOCK(vars);
3414 ret = pf ? pf->sngpos :0; /* pf->positions[pf->sngpos ? pf->sngpos-1 : 0]: 0; */
3415 MUTEX_UNLOCK(vars);
3416 return ret;
3417 }
3418
3419 /* Get current module row */
Player_GetRow(void)3420 MIKMODAPI int Player_GetRow(void)
3421 {
3422 int ret;
3423 MUTEX_LOCK(vars);
3424 ret = pf ? pf->patpos : 0;
3425 MUTEX_UNLOCK(vars);
3426 return ret;
3427 }
3428
3429 /* ex:set ts=4: */
3430