1 /* MikMod sound library
2 (c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of
8 the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 /*==============================================================================
23 $Id: mplayer.c,v 1.4 2006/08/08 00:06:31 realtech Exp $
25 The Protracker Player Driver
27 The protracker driver supports all base Protracker 3.x commands and features.
29 ==============================================================================*/
37 #ifdef SRANDOM_IN_MATH_H
43 #include "mikmod_internals.h"
46 extern int fprintf(FILE *, const char *, ...);
47 extern long int random(void);
50 /* The currently playing module */
53 #define HIGH_OCTAVE 2 /* number of above-range octaves */
55 static UWORD oldperiods
[OCTAVE
*2]={
56 0x6b00, 0x6800, 0x6500, 0x6220, 0x5f50, 0x5c80,
57 0x5a00, 0x5740, 0x54d0, 0x5260, 0x5010, 0x4dc0,
58 0x4b90, 0x4960, 0x4750, 0x4540, 0x4350, 0x4160,
59 0x3f90, 0x3dc0, 0x3c10, 0x3a40, 0x38b0, 0x3700
62 static UBYTE VibratoTable
[32]={
63 0, 24, 49, 74, 97,120,141,161,180,197,212,224,235,244,250,253,
64 255,253,250,244,235,224,212,197,180,161,141,120, 97, 74, 49, 24
67 static UBYTE avibtab
[128]={
68 0, 1, 3, 4, 6, 7, 9,10,12,14,15,17,18,20,21,23,
69 24,25,27,28,30,31,32,34,35,36,38,39,40,41,42,44,
70 45,46,47,48,49,50,51,52,53,54,54,55,56,57,57,58,
71 59,59,60,60,61,61,62,62,62,63,63,63,63,63,63,63,
72 64,63,63,63,63,63,63,63,62,62,62,61,61,60,60,59,
73 59,58,57,57,56,55,54,54,53,52,51,50,49,48,47,46,
74 45,44,42,41,40,39,38,36,35,34,32,31,30,28,27,25,
75 24,23,21,20,18,17,15,14,12,10, 9, 7, 6, 4, 3, 1
78 /* Triton's linear periods to frequency translation table (for XM modules) */
79 static ULONG lintab
[768]={
80 535232,534749,534266,533784,533303,532822,532341,531861,
81 531381,530902,530423,529944,529466,528988,528511,528034,
82 527558,527082,526607,526131,525657,525183,524709,524236,
83 523763,523290,522818,522346,521875,521404,520934,520464,
84 519994,519525,519057,518588,518121,517653,517186,516720,
85 516253,515788,515322,514858,514393,513929,513465,513002,
86 512539,512077,511615,511154,510692,510232,509771,509312,
87 508852,508393,507934,507476,507018,506561,506104,505647,
88 505191,504735,504280,503825,503371,502917,502463,502010,
89 501557,501104,500652,500201,499749,499298,498848,498398,
90 497948,497499,497050,496602,496154,495706,495259,494812,
91 494366,493920,493474,493029,492585,492140,491696,491253,
92 490809,490367,489924,489482,489041,488600,488159,487718,
93 487278,486839,486400,485961,485522,485084,484647,484210,
94 483773,483336,482900,482465,482029,481595,481160,480726,
95 480292,479859,479426,478994,478562,478130,477699,477268,
96 476837,476407,475977,475548,475119,474690,474262,473834,
97 473407,472979,472553,472126,471701,471275,470850,470425,
98 470001,469577,469153,468730,468307,467884,467462,467041,
99 466619,466198,465778,465358,464938,464518,464099,463681,
100 463262,462844,462427,462010,461593,461177,460760,460345,
101 459930,459515,459100,458686,458272,457859,457446,457033,
102 456621,456209,455797,455386,454975,454565,454155,453745,
103 453336,452927,452518,452110,451702,451294,450887,450481,
104 450074,449668,449262,448857,448452,448048,447644,447240,
105 446836,446433,446030,445628,445226,444824,444423,444022,
106 443622,443221,442821,442422,442023,441624,441226,440828,
107 440430,440033,439636,439239,438843,438447,438051,437656,
108 437261,436867,436473,436079,435686,435293,434900,434508,
109 434116,433724,433333,432942,432551,432161,431771,431382,
110 430992,430604,430215,429827,429439,429052,428665,428278,
111 427892,427506,427120,426735,426350,425965,425581,425197,
112 424813,424430,424047,423665,423283,422901,422519,422138,
113 421757,421377,420997,420617,420237,419858,419479,419101,
114 418723,418345,417968,417591,417214,416838,416462,416086,
115 415711,415336,414961,414586,414212,413839,413465,413092,
116 412720,412347,411975,411604,411232,410862,410491,410121,
117 409751,409381,409012,408643,408274,407906,407538,407170,
118 406803,406436,406069,405703,405337,404971,404606,404241,
119 403876,403512,403148,402784,402421,402058,401695,401333,
120 400970,400609,400247,399886,399525,399165,398805,398445,
121 398086,397727,397368,397009,396651,396293,395936,395579,
122 395222,394865,394509,394153,393798,393442,393087,392733,
123 392378,392024,391671,391317,390964,390612,390259,389907,
124 389556,389204,388853,388502,388152,387802,387452,387102,
125 386753,386404,386056,385707,385359,385012,384664,384317,
126 383971,383624,383278,382932,382587,382242,381897,381552,
127 381208,380864,380521,380177,379834,379492,379149,378807,
128 378466,378124,377783,377442,377102,376762,376422,376082,
129 375743,375404,375065,374727,374389,374051,373714,373377,
130 373040,372703,372367,372031,371695,371360,371025,370690,
131 370356,370022,369688,369355,369021,368688,368356,368023,
132 367691,367360,367028,366697,366366,366036,365706,365376,
133 365046,364717,364388,364059,363731,363403,363075,362747,
134 362420,362093,361766,361440,361114,360788,360463,360137,
135 359813,359488,359164,358840,358516,358193,357869,357547,
136 357224,356902,356580,356258,355937,355616,355295,354974,
137 354654,354334,354014,353695,353376,353057,352739,352420,
138 352103,351785,351468,351150,350834,350517,350201,349885,
139 349569,349254,348939,348624,348310,347995,347682,347368,
140 347055,346741,346429,346116,345804,345492,345180,344869,
141 344558,344247,343936,343626,343316,343006,342697,342388,
142 342079,341770,341462,341154,340846,340539,340231,339924,
143 339618,339311,339005,338700,338394,338089,337784,337479,
144 337175,336870,336566,336263,335959,335656,335354,335051,
145 334749,334447,334145,333844,333542,333242,332941,332641,
146 332341,332041,331741,331442,331143,330844,330546,330247,
147 329950,329652,329355,329057,328761,328464,328168,327872,
148 327576,327280,326985,326690,326395,326101,325807,325513,
149 325219,324926,324633,324340,324047,323755,323463,323171,
150 322879,322588,322297,322006,321716,321426,321136,320846,
151 320557,320267,319978,319690,319401,319113,318825,318538,
152 318250,317963,317676,317390,317103,316817,316532,316246,
153 315961,315676,315391,315106,314822,314538,314254,313971,
154 313688,313405,313122,312839,312557,312275,311994,311712,
155 311431,311150,310869,310589,310309,310029,309749,309470,
156 309190,308911,308633,308354,308076,307798,307521,307243,
157 306966,306689,306412,306136,305860,305584,305308,305033,
158 304758,304483,304208,303934,303659,303385,303112,302838,
159 302565,302292,302019,301747,301475,301203,300931,300660,
160 300388,300117,299847,299576,299306,299036,298766,298497,
161 298227,297958,297689,297421,297153,296884,296617,296349,
162 296082,295815,295548,295281,295015,294749,294483,294217,
163 293952,293686,293421,293157,292892,292628,292364,292100,
164 291837,291574,291311,291048,290785,290523,290261,289999,
165 289737,289476,289215,288954,288693,288433,288173,287913,
166 287653,287393,287134,286875,286616,286358,286099,285841,
167 285583,285326,285068,284811,284554,284298,284041,283785,
168 283529,283273,283017,282762,282507,282252,281998,281743,
169 281489,281235,280981,280728,280475,280222,279969,279716,
170 279464,279212,278960,278708,278457,278206,277955,277704,
171 277453,277203,276953,276703,276453,276204,275955,275706,
172 275457,275209,274960,274712,274465,274217,273970,273722,
173 273476,273229,272982,272736,272490,272244,271999,271753,
174 271508,271263,271018,270774,270530,270286,270042,269798,
175 269555,269312,269069,268826,268583,268341,268099,267857
179 static UWORD logtab
[104]={
180 LOGFAC
*907,LOGFAC
*900,LOGFAC
*894,LOGFAC
*887,
181 LOGFAC
*881,LOGFAC
*875,LOGFAC
*868,LOGFAC
*862,
182 LOGFAC
*856,LOGFAC
*850,LOGFAC
*844,LOGFAC
*838,
183 LOGFAC
*832,LOGFAC
*826,LOGFAC
*820,LOGFAC
*814,
184 LOGFAC
*808,LOGFAC
*802,LOGFAC
*796,LOGFAC
*791,
185 LOGFAC
*785,LOGFAC
*779,LOGFAC
*774,LOGFAC
*768,
186 LOGFAC
*762,LOGFAC
*757,LOGFAC
*752,LOGFAC
*746,
187 LOGFAC
*741,LOGFAC
*736,LOGFAC
*730,LOGFAC
*725,
188 LOGFAC
*720,LOGFAC
*715,LOGFAC
*709,LOGFAC
*704,
189 LOGFAC
*699,LOGFAC
*694,LOGFAC
*689,LOGFAC
*684,
190 LOGFAC
*678,LOGFAC
*675,LOGFAC
*670,LOGFAC
*665,
191 LOGFAC
*660,LOGFAC
*655,LOGFAC
*651,LOGFAC
*646,
192 LOGFAC
*640,LOGFAC
*636,LOGFAC
*632,LOGFAC
*628,
193 LOGFAC
*623,LOGFAC
*619,LOGFAC
*614,LOGFAC
*610,
194 LOGFAC
*604,LOGFAC
*601,LOGFAC
*597,LOGFAC
*592,
195 LOGFAC
*588,LOGFAC
*584,LOGFAC
*580,LOGFAC
*575,
196 LOGFAC
*570,LOGFAC
*567,LOGFAC
*563,LOGFAC
*559,
197 LOGFAC
*555,LOGFAC
*551,LOGFAC
*547,LOGFAC
*543,
198 LOGFAC
*538,LOGFAC
*535,LOGFAC
*532,LOGFAC
*528,
199 LOGFAC
*524,LOGFAC
*520,LOGFAC
*516,LOGFAC
*513,
200 LOGFAC
*508,LOGFAC
*505,LOGFAC
*502,LOGFAC
*498,
201 LOGFAC
*494,LOGFAC
*491,LOGFAC
*487,LOGFAC
*484,
202 LOGFAC
*480,LOGFAC
*477,LOGFAC
*474,LOGFAC
*470,
203 LOGFAC
*467,LOGFAC
*463,LOGFAC
*460,LOGFAC
*457,
204 LOGFAC
*453,LOGFAC
*450,LOGFAC
*447,LOGFAC
*443,
205 LOGFAC
*440,LOGFAC
*437,LOGFAC
*434,LOGFAC
*431
208 static SBYTE PanbrelloTable
[256]={
209 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 17, 19, 20, 22, 23,
210 24, 26, 27, 29, 30, 32, 33, 34, 36, 37, 38, 39, 41, 42, 43, 44,
211 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59,
212 59, 60, 60, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64, 64, 64, 64,
213 64, 64, 64, 64, 64, 64, 63, 63, 63, 62, 62, 62, 61, 61, 60, 60,
214 59, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46,
215 45, 44, 43, 42, 41, 39, 38, 37, 36, 34, 33, 32, 30, 29, 27, 26,
216 24, 23, 22, 20, 19, 17, 16, 14, 12, 11, 9, 8, 6, 5, 3, 2,
217 0,- 2,- 3,- 5,- 6,- 8,- 9,-11,-12,-14,-16,-17,-19,-20,-22,-23,
218 -24,-26,-27,-29,-30,-32,-33,-34,-36,-37,-38,-39,-41,-42,-43,-44,
219 -45,-46,-47,-48,-49,-50,-51,-52,-53,-54,-55,-56,-56,-57,-58,-59,
220 -59,-60,-60,-61,-61,-62,-62,-62,-63,-63,-63,-64,-64,-64,-64,-64,
221 -64,-64,-64,-64,-64,-64,-63,-63,-63,-62,-62,-62,-61,-61,-60,-60,
222 -59,-59,-58,-57,-56,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,
223 -45,-44,-43,-42,-41,-39,-38,-37,-36,-34,-33,-32,-30,-29,-27,-26,
224 -24,-23,-22,-20,-19,-17,-16,-14,-12,-11,- 9,- 8,- 6,- 5,- 3,- 2
227 /* returns a random value between 0 and ceil-1, ceil must be a power of two */
228 static int getrandom(int ceil
)
231 return random()&(ceil
-1);
233 return (rand()*ceil
)/(RAND_MAX
+1.0);
237 /* New Note Action Scoring System :
238 --------------------------------
239 1) total-volume (fadevol, chanvol, volume) is the main scorer.
240 2) a looping sample is a bonus x2
241 3) a foreground channel is a bonus x4
242 4) an active envelope with keyoff is a handicap -x2
244 static int MP_FindEmptyChannel(MODULE
*mod
)
249 for (t
=0;t
<md_sngchn
;t
++)
250 if (((mod
->voice
[t
].main
.kick
==KICK_ABSENT
)||
251 (mod
->voice
[t
].main
.kick
==KICK_ENV
))&&
252 Voice_Stopped_internal(t
))
255 tvol
=0xffffffUL
;t
=-1;a
=mod
->voice
;
256 for (k
=0;k
<md_sngchn
;k
++,a
++) {
257 /* allow us to take over a nonexisting sample */
261 if ((a
->main
.kick
==KICK_ABSENT
)||(a
->main
.kick
==KICK_ENV
)) {
262 pp
=a
->totalvol
<<((a
->main
.s
->flags
&SF_LOOP
)?1:0);
263 if ((a
->master
)&&(a
==a
->master
->slave
))
273 if (tvol
>8000*7) return -1;
277 static SWORD
Interpolate(SWORD p
,SWORD p1
,SWORD p2
,SWORD v1
,SWORD v2
)
279 if ((p1
==p2
)||(p
==p1
)) return v1
;
280 return v1
+((SLONG
)((p
-p1
)*(v2
-v1
))/(p2
-p1
));
283 UWORD
getlinearperiod(UWORD note
,ULONG fine
)
287 t
=((20L+2*HIGH_OCTAVE
)*OCTAVE
+2-note
)*32L-(fine
>>1);
291 static UWORD
getlogperiod(UWORD note
,ULONG fine
)
299 i
=(n
<<2)+(fine
>>4); /* n*8 + fine/16 */
304 return (Interpolate(fine
>>4,0,15,p1
,p2
)>>o
);
307 static UWORD
getoldperiod(UWORD note
,ULONG speed
)
311 /* This happens sometimes on badly converted AMF, and old MOD */
314 fprintf(stderr
,"\rmplayer: getoldperiod() called with note=%d, speed=0 !\n",note
);
316 return 4242; /* <- prevent divide overflow.. (42 hehe) */
321 return ((8363L*(ULONG
)oldperiods
[n
])>>o
)/speed
;
324 static UWORD
GetPeriod(UWORD flags
, UWORD note
, ULONG speed
)
326 if (flags
& UF_XMPERIODS
) {
327 if (flags
& UF_LINEAR
)
328 return getlinearperiod(note
, speed
);
330 return getlogperiod(note
, speed
);
332 return getoldperiod(note
, speed
);
335 static SWORD
InterpolateEnv(SWORD p
,ENVPT
*a
,ENVPT
*b
)
337 return (Interpolate(p
,a
->pos
,b
->pos
,a
->val
,b
->val
));
340 static SWORD
DoPan(SWORD envpan
,SWORD pan
)
344 newpan
=pan
+(((envpan
-PAN_CENTER
)*(128-abs(pan
-PAN_CENTER
)))/128);
346 return (newpan
<PAN_LEFT
)?PAN_LEFT
:(newpan
>PAN_RIGHT
?PAN_RIGHT
:newpan
);
349 static SWORD
StartEnvelope(ENVPR
*t
,UBYTE flg
,UBYTE pts
,UBYTE susbeg
,UBYTE susend
,UBYTE beg
,UBYTE end
,ENVPT
*p
,UBYTE keyoff
)
360 t
->b
=((t
->flg
&EF_SUSTAIN
)&&(!(keyoff
&KEY_OFF
)))?0:1;
362 /* Imago Orpheus sometimes stores an extra initial point in the envelope */
363 if ((t
->pts
>=2)&&(t
->env
[0].pos
==t
->env
[1].pos
)) {
367 /* Fit in the envelope, still */
373 return t
->env
[t
->a
].val
;
376 /* This procedure processes all envelope types, include volume, pitch, and
377 panning. Envelopes are defined by a set of points, each with a magnitude
378 [relating either to volume, panning position, or pitch modifier] and a tick
381 Envelopes work in the following manner:
383 (a) Each tick the envelope is moved a point further in its progression. For
384 an accurate progression, magnitudes between two envelope points are
387 (b) When progression reaches a defined point on the envelope, values are
388 shifted to interpolate between this point and the next, and checks for
389 loops or envelope end are done.
392 Sustain loops are loops that are only active as long as the keyoff flag is
393 clear. When a volume envelope terminates, so does the current fadeout.
395 static SWORD
ProcessEnvelope(MP_VOICE
*aout
, ENVPR
*t
, SWORD v
)
397 if (t
->flg
& EF_ON
) {
398 UBYTE a
, b
; /* actual points in the envelope */
399 UWORD p
; /* the 'tick counter' - real point being played */
406 * Sustain loop on one point (XM type).
407 * Not processed if KEYOFF.
408 * Don't move and don't interpolate when the point is reached
410 if ((t
->flg
& EF_SUSTAIN
) && t
->susbeg
== t
->susend
&&
411 (!(aout
->main
.keyoff
& KEY_OFF
) && p
== t
->env
[t
->susbeg
].pos
)) {
412 v
= t
->env
[t
->susbeg
].val
;
415 * All following situations will require interpolation between
416 * two envelope points.
420 * Sustain loop between two points (IT type).
421 * Not processed if KEYOFF.
423 /* if we were on a loop point, loop now */
424 if ((t
->flg
& EF_SUSTAIN
) && !(aout
->main
.keyoff
& KEY_OFF
) &&
427 b
= (t
->susbeg
==t
->susend
)?a
:a
+1;
433 * Be sure to correctly handle single point loops.
435 if ((t
->flg
& EF_LOOP
) && a
>= t
->end
) {
437 b
= t
->beg
== t
->end
? a
: a
+ 1;
442 * Non looping situations.
445 v
= InterpolateEnv(p
, &t
->env
[a
], &t
->env
[b
]);
450 * Start to fade if the volume envelope is finished.
452 if (p
>= t
->env
[t
->pts
- 1].pos
) {
453 if (t
->flg
& EF_VOLENV
) {
454 aout
->main
.keyoff
|= KEY_FADE
;
456 aout
->main
.fadevol
= 0;
460 /* did pointer reach point b? */
461 if (p
>= t
->env
[b
].pos
)
462 a
= b
++; /* shift points a and b */
472 /* XM linear period to frequency conversion */
473 ULONG
getfrequency(UWORD flags
,ULONG period
)
475 if (flags
& UF_LINEAR
) {
476 SLONG shift
= ((SLONG
)period
/ 768) - HIGH_OCTAVE
;
479 return lintab
[period
% 768] >> shift
;
481 return lintab
[period
% 768] << (-shift
);
483 return (8363L*1712L)/(period
?period
:1);
486 /*========== Protracker effects */
488 static void DoArpeggio(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, UBYTE style
)
490 UBYTE note
=a
->main
.note
;
494 case 0: /* mod style: N, N+x, N+y */
496 /* case 0: unchanged */
498 note
+= (a
->arpmem
>> 4);
501 note
+= (a
->arpmem
& 0xf);
505 case 3: /* okt arpeggio 3: N-x, N, N+y */
508 note
-= (a
->arpmem
>> 4);
510 /* case 1: unchanged */
512 note
+= (a
->arpmem
& 0xf);
516 case 4: /* okt arpeggio 4: N, N+y, N, N-x */
518 /* case 0, case 2: unchanged */
520 note
+= (a
->arpmem
& 0xf);
523 note
-= (a
->arpmem
>> 4);
527 case 5: /* okt arpeggio 5: N-x, N+y, N, and nothing at tick 0 */
531 /* case 0: unchanged */
533 note
-= (a
->arpmem
>> 4);
536 note
+= (a
->arpmem
& 0xf);
541 a
->main
.period
= GetPeriod(flags
, (UWORD
)note
<< 1, a
->speed
);
546 static int DoPTEffect0(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
554 if (!dat
&& (flags
& UF_ARPMEM
))
560 DoArpeggio(tick
, flags
, a
, 0);
565 static int DoPTEffect1(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
574 a
->slidespeed
= (UWORD
)dat
<< 2;
577 a
->tmpperiod
-= a
->slidespeed
;
582 static int DoPTEffect2(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
591 a
->slidespeed
= (UWORD
)dat
<< 2;
594 a
->tmpperiod
+= a
->slidespeed
;
599 static void DoToneSlide(UWORD tick
, MP_CONTROL
*a
)
601 if (!a
->main
.fadevol
)
602 a
->main
.kick
= (a
->main
.kick
== KICK_NOTE
)? KICK_NOTE
: KICK_KEYOFF
;
604 a
->main
.kick
= (a
->main
.kick
== KICK_NOTE
)? KICK_ENV
: KICK_ABSENT
;
609 /* We have to slide a->main.period towards a->wantedperiod, so compute
610 the difference between those two values */
611 dist
=a
->main
.period
-a
->wantedperiod
;
613 /* if they are equal or if portamentospeed is too big ...*/
614 if (dist
== 0 || a
->portspeed
> abs(dist
))
615 /* ...make tmpperiod equal tperiod */
616 a
->tmpperiod
=a
->main
.period
=a
->wantedperiod
;
618 a
->tmpperiod
-=a
->portspeed
;
619 a
->main
.period
-=a
->portspeed
; /* dist>0, slide up */
621 a
->tmpperiod
+=a
->portspeed
;
622 a
->main
.period
+=a
->portspeed
; /* dist<0, slide down */
625 a
->tmpperiod
=a
->main
.period
;
629 static int DoPTEffect3(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
637 if ((!tick
)&&(dat
)) a
->portspeed
=(UWORD
)dat
<<2;
639 DoToneSlide(tick
, a
);
644 static void DoVibrato(UWORD tick
, MP_CONTROL
*a
)
647 UWORD temp
= 0; /* silence warning */
652 q
=(a
->vibpos
>>2)&0x1f;
654 switch (a
->wavecontrol
&3) {
656 temp
=VibratoTable
[q
];
658 case 1: /* ramp down */
660 if (a
->vibpos
<0) q
=255-q
;
663 case 2: /* square wave */
666 case 3: /* random wave */
675 a
->main
.period
=a
->tmpperiod
+temp
;
677 a
->main
.period
=a
->tmpperiod
-temp
;
681 a
->vibpos
+=a
->vibspd
;
684 static int DoPTEffect4(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
693 if (dat
&0x0f) a
->vibdepth
=dat
&0xf;
694 if (dat
&0xf0) a
->vibspd
=(dat
&0xf0)>>2;
702 static void DoVolSlide(MP_CONTROL
*a
, UBYTE dat
)
705 a
->tmpvolume
-=(dat
&0x0f);
709 a
->tmpvolume
+=(dat
>>4);
715 static int DoPTEffect5(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
724 DoToneSlide(tick
, a
);
732 /* DoPTEffect6 after DoPTEffectA */
734 static int DoPTEffect7(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
738 UWORD temp
= 0; /* silence warning */
745 if (dat
&0x0f) a
->trmdepth
=dat
&0xf;
746 if (dat
&0xf0) a
->trmspd
=(dat
&0xf0)>>2;
748 if (a
->main
.period
) {
749 q
=(a
->trmpos
>>2)&0x1f;
751 switch ((a
->wavecontrol
>>4)&3) {
753 temp
=VibratoTable
[q
];
755 case 1: /* ramp down */
757 if (a
->trmpos
<0) q
=255-q
;
760 case 2: /* square wave */
763 case 3: /* random wave */
771 a
->volume
=a
->tmpvolume
+temp
;
772 if (a
->volume
>64) a
->volume
=64;
774 a
->volume
=a
->tmpvolume
-temp
;
775 if (a
->volume
<0) a
->volume
=0;
780 a
->trmpos
+=a
->trmspd
;
786 static int DoPTEffect8(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
794 a
->main
.panning
= mod
->panning
[channel
] = dat
;
799 static int DoPTEffect9(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
808 if (dat
) a
->soffset
=(UWORD
)dat
<<8;
809 a
->main
.start
=a
->hioffset
|a
->soffset
;
811 if ((a
->main
.s
)&&(a
->main
.start
> (SLONG
)a
->main
.s
->length
))
812 a
->main
.start
=a
->main
.s
->flags
&(SF_LOOP
|SF_BIDI
)?
813 a
->main
.s
->loopstart
:a
->main
.s
->length
;
819 static int DoPTEffectA(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
833 static int DoPTEffect6(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
837 DoPTEffectA(tick
, flags
, a
, mod
, channel
);
842 static int DoPTEffectB(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
850 if (tick
|| mod
->patdly2
)
853 /* Vincent Voois uses a nasty trick in "Universal Bolero" */
854 if (dat
== mod
->sngpos
&& mod
->patbrk
== mod
->patpos
)
857 if (!mod
->loop
&& !mod
->patbrk
&&
858 (dat
< mod
->sngpos
||
859 (mod
->sngpos
== (mod
->numpos
- 1) && !mod
->patbrk
) ||
860 (dat
== mod
->sngpos
&& (flags
& UF_NOWRAP
))
862 /* if we don't loop, better not to skip the end of the
863 pattern, after all... so:
867 /* if we were fading, adjust... */
868 if (mod
->sngpos
== (mod
->numpos
-1))
869 mod
->volume
=mod
->initvolume
>128?128:mod
->initvolume
;
878 static int DoPTEffectC(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
887 if (dat
==(UBYTE
)-1) a
->anote
=dat
=0; /* note cut */
888 else if (dat
>64) dat
=64;
894 static int DoPTEffectD(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
901 if ((tick
)||(mod
->patdly2
)) return 0;
902 if ((mod
->positions
[mod
->sngpos
]!=LAST_PATTERN
)&&
903 (dat
>mod
->pattrows
[mod
->positions
[mod
->sngpos
]]))
904 dat
=mod
->pattrows
[mod
->positions
[mod
->sngpos
]];
907 /* don't ask me to explain this code - it makes
908 backwards.s3m and children.xm (heretic's version) play
909 correctly, among others. Take that for granted, or write
910 the page of comments yourself... you might need some
912 if ((mod
->sngpos
==mod
->numpos
-1)&&(dat
)&&((mod
->loop
)||
913 (mod
->positions
[mod
->sngpos
]==(mod
->numpat
-1)
914 && !(flags
&UF_NOWRAP
)))) {
924 static void DoEEffects(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
,
925 SWORD channel
, UBYTE dat
)
927 UBYTE nib
= dat
& 0xf;
930 case 0x0: /* hardware filter toggle, not supported */
932 case 0x1: /* fineslide up */
935 a
->tmpperiod
-=(nib
<<2);
937 case 0x2: /* fineslide dn */
940 a
->tmpperiod
+=(nib
<<2);
942 case 0x3: /* glissando ctrl */
945 case 0x4: /* set vibrato waveform */
946 a
->wavecontrol
&=0xf0;
949 case 0x5: /* set finetune */
950 if (a
->main
.period
) {
951 if (flags
&UF_XMPERIODS
)
954 a
->speed
=finetune
[nib
];
955 a
->tmpperiod
=GetPeriod(flags
, (UWORD
)a
->main
.note
<<1,a
->speed
);
958 case 0x6: /* set patternloop */
961 if (nib
) { /* set reppos or repcnt ? */
962 /* set repcnt, so check if repcnt already is set, which means we
963 are already looping */
965 a
->pat_repcnt
--; /* already looping, decrease counter */
968 /* this would make walker.xm, shipped with Xsoundtracker,
969 play correctly, but it's better to remain compatible
971 if ((!(flags
&UF_NOWRAP
))||(a
->pat_reppos
!=POS_NONE
))
973 a
->pat_repcnt
=nib
; /* not yet looping, so set repcnt */
976 if (a
->pat_repcnt
) { /* jump to reppos if repcnt>0 */
977 if (a
->pat_reppos
==POS_NONE
)
978 a
->pat_reppos
=mod
->patpos
-1;
979 if (a
->pat_reppos
==-1) {
983 mod
->patpos
=a
->pat_reppos
;
984 } else a
->pat_reppos
=POS_NONE
;
986 a
->pat_reppos
=mod
->patpos
-1; /* set reppos - can be (-1) */
988 case 0x7: /* set tremolo waveform */
989 a
->wavecontrol
&=0x0f;
990 a
->wavecontrol
|=nib
<<4;
992 case 0x8: /* set panning */
996 a
->main
.panning
=mod
->panning
[channel
]=nib
;
999 case 0x9: /* retrig note */
1000 /* do not retrigger on tick 0, until we are emulating FT2 and effect
1002 if (!tick
&& !((flags
& UF_FT2QUIRKS
) && (!nib
)))
1004 /* only retrigger if data nibble > 0, or if tick 0 (FT2 compat) */
1007 /* when retrig counter reaches 0, reset counter and restart
1009 if (a
->main
.period
) a
->main
.kick
=KICK_NOTE
;
1012 a
->retrig
--; /* countdown */
1015 case 0xa: /* fine volume slide up */
1019 if (a
->tmpvolume
>64) a
->tmpvolume
=64;
1021 case 0xb: /* fine volume slide dn */
1025 if (a
->tmpvolume
<0)a
->tmpvolume
=0;
1027 case 0xc: /* cut note */
1028 /* When tick reaches the cut-note value, turn the volume to
1029 zero (just like on the amiga) */
1031 a
->tmpvolume
=0; /* just turn the volume down */
1033 case 0xd: /* note delay */
1034 /* delay the start of the sample until tick==nib */
1036 a
->main
.notedelay
=nib
;
1037 else if (a
->main
.notedelay
)
1038 a
->main
.notedelay
--;
1040 case 0xe: /* pattern delay */
1043 mod
->patdly
=nib
+1; /* only once, when tick=0 */
1045 case 0xf: /* invert loop, not supported */
1050 static int DoPTEffectE(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1052 DoEEffects(tick
, flags
, a
, mod
, channel
, UniGetByte());
1057 static int DoPTEffectF(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1065 if (tick
||mod
->patdly2
) return 0;
1066 if (mod
->extspd
&&(dat
>=mod
->bpmlimit
))
1070 mod
->sngspd
=(dat
>=mod
->bpmlimit
)?mod
->bpmlimit
-1:dat
;
1077 /*========== Scream Tracker effects */
1079 static int DoS3MEffectA(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1086 speed
= UniGetByte();
1088 if (tick
|| mod
->patdly2
)
1094 mod
->sngspd
= speed
;
1101 static void DoS3MVolSlide(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, UBYTE inf
)
1114 if ((tick
)||(flags
&UF_S3MSLIDES
)) a
->tmpvolume
+=hi
;
1117 if ((tick
)||(flags
&UF_S3MSLIDES
)) a
->tmpvolume
-=lo
;
1120 if (!tick
) a
->tmpvolume
+=(hi
?hi
:0xf);
1123 if (!tick
) a
->tmpvolume
-=(lo
?lo
:0xf);
1129 else if (a
->tmpvolume
>64)
1133 static int DoS3MEffectD(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1138 DoS3MVolSlide(tick
, flags
, a
, UniGetByte());
1143 static void DoS3MSlideDn(UWORD tick
, MP_CONTROL
*a
, UBYTE inf
)
1156 if (!tick
) a
->tmpperiod
+=(UWORD
)lo
<<2;
1159 if (!tick
) a
->tmpperiod
+=lo
;
1161 if (tick
) a
->tmpperiod
+=(UWORD
)inf
<<2;
1165 static int DoS3MEffectE(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1174 DoS3MSlideDn(tick
, a
,dat
);
1179 static void DoS3MSlideUp(UWORD tick
, MP_CONTROL
*a
, UBYTE inf
)
1183 if (inf
) a
->slidespeed
=inf
;
1184 else inf
=a
->slidespeed
;
1190 if (!tick
) a
->tmpperiod
-=(UWORD
)lo
<<2;
1193 if (!tick
) a
->tmpperiod
-=lo
;
1195 if (tick
) a
->tmpperiod
-=(UWORD
)inf
<<2;
1199 static int DoS3MEffectF(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1208 DoS3MSlideUp(tick
, a
,dat
);
1213 static int DoS3MEffectI(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1234 a
->s3mtremor
%=(on
+off
);
1235 a
->volume
=(a
->s3mtremor
<on
)?a
->tmpvolume
:0;
1242 static int DoS3MEffectQ(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1249 if (a
->main
.period
) {
1251 a
->s3mrtgslide
=inf
>>4;
1252 a
->s3mrtgspeed
=inf
&0xf;
1255 /* only retrigger if low nibble > 0 */
1256 if (a
->s3mrtgspeed
>0) {
1258 /* when retrig counter reaches 0, reset counter and restart the
1260 if (a
->main
.kick
!=KICK_NOTE
) a
->main
.kick
=KICK_KEYOFF
;
1261 a
->retrig
=a
->s3mrtgspeed
;
1263 if ((tick
)||(flags
&UF_S3MSLIDES
)) {
1264 switch (a
->s3mrtgslide
) {
1270 a
->tmpvolume
-=(1<<(a
->s3mrtgslide
-1));
1273 a
->tmpvolume
=(2*a
->tmpvolume
)/3;
1283 a
->tmpvolume
+=(1<<(a
->s3mrtgslide
-9));
1286 a
->tmpvolume
=(3*a
->tmpvolume
)>>1;
1289 a
->tmpvolume
=a
->tmpvolume
<<1;
1294 else if (a
->tmpvolume
>64)
1298 a
->retrig
--; /* countdown */
1305 static int DoS3MEffectR(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1308 UWORD temp
=0; /* silence warning */
1315 if (dat
&0x0f) a
->trmdepth
=dat
&0xf;
1316 if (dat
&0xf0) a
->trmspd
=(dat
&0xf0)>>2;
1319 q
=(a
->trmpos
>>2)&0x1f;
1321 switch ((a
->wavecontrol
>>4)&3) {
1323 temp
=VibratoTable
[q
];
1325 case 1: /* ramp down */
1327 if (a
->trmpos
<0) q
=255-q
;
1330 case 2: /* square wave */
1333 case 3: /* random */
1334 temp
=getrandom(256);
1342 a
->volume
=a
->tmpvolume
+temp
;
1343 if (a
->volume
>64) a
->volume
=64;
1345 a
->volume
=a
->tmpvolume
-temp
;
1346 if (a
->volume
<0) a
->volume
=0;
1351 a
->trmpos
+=a
->trmspd
;
1356 static int DoS3MEffectT(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1363 tempo
= UniGetByte();
1365 if (tick
|| mod
->patdly2
)
1368 mod
->bpm
= (tempo
< 32) ? 32 : tempo
;
1373 static int DoS3MEffectU(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1376 UWORD temp
= 0; /* silence warning */
1383 if (dat
&0x0f) a
->vibdepth
=dat
&0xf;
1384 if (dat
&0xf0) a
->vibspd
=(dat
&0xf0)>>2;
1386 if (a
->main
.period
) {
1387 q
=(a
->vibpos
>>2)&0x1f;
1389 switch (a
->wavecontrol
&3) {
1391 temp
=VibratoTable
[q
];
1393 case 1: /* ramp down */
1395 if (a
->vibpos
<0) q
=255-q
;
1398 case 2: /* square wave */
1401 case 3: /* random */
1402 temp
=getrandom(256);
1410 a
->main
.period
=a
->tmpperiod
+temp
;
1412 a
->main
.period
=a
->tmpperiod
-temp
;
1415 a
->vibpos
+=a
->vibspd
;
1421 /*========== Envelope helpers */
1423 static int DoKeyOff(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1429 a
->main
.keyoff
|=KEY_OFF
;
1430 if ((!(a
->main
.volflg
&EF_ON
))||(a
->main
.volflg
&EF_LOOP
))
1431 a
->main
.keyoff
=KEY_KILL
;
1436 static int DoKeyFade(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1443 if ((tick
>=dat
)||(tick
==mod
->sngspd
-1)) {
1444 a
->main
.keyoff
=KEY_KILL
;
1445 if (!(a
->main
.volflg
&EF_ON
))
1452 /*========== Fast Tracker effects */
1454 /* DoXMEffect6 after DoXMEffectA */
1456 static int DoXMEffectA(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1465 a
->s3mvolslide
= inf
;
1467 inf
= a
->s3mvolslide
;
1475 if (a
->tmpvolume
<0) a
->tmpvolume
=0;
1478 if (a
->tmpvolume
>64) a
->tmpvolume
=64;
1485 static int DoXMEffect6(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1493 return DoXMEffectA(tick
, flags
, a
, mod
, channel
);
1496 static int DoXMEffectE1(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1505 if (dat
) a
->fportupspd
=dat
;
1507 a
->tmpperiod
-=(a
->fportupspd
<<2);
1513 static int DoXMEffectE2(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1522 if (dat
) a
->fportdnspd
=dat
;
1524 a
->tmpperiod
+=(a
->fportdnspd
<<2);
1530 static int DoXMEffectEA(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1539 if (dat
) a
->fslideupspd
=dat
;
1540 a
->tmpvolume
+=a
->fslideupspd
;
1541 if (a
->tmpvolume
>64) a
->tmpvolume
=64;
1546 static int DoXMEffectEB(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1555 if (dat
) a
->fslidednspd
=dat
;
1556 a
->tmpvolume
-=a
->fslidednspd
;
1557 if (a
->tmpvolume
<0) a
->tmpvolume
=0;
1562 static int DoXMEffectG(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1568 mod
->volume
=UniGetByte()<<1;
1569 if (mod
->volume
>128) mod
->volume
=128;
1574 static int DoXMEffectH(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1584 if (inf
) mod
->globalslide
=inf
;
1585 else inf
=mod
->globalslide
;
1586 if (inf
& 0xf0) inf
&=0xf0;
1587 mod
->volume
=mod
->volume
+((inf
>>4)-(inf
&0xf))*2;
1591 else if (mod
->volume
>128)
1598 static int DoXMEffectL(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1606 if ((!tick
)&&(a
->main
.i
)) {
1608 INSTRUMENT
*i
=a
->main
.i
;
1611 if ((aout
=a
->slave
)) {
1612 if (aout
->venv
.env
) {
1613 points
=i
->volenv
[i
->volpts
-1].pos
;
1614 aout
->venv
.p
=aout
->venv
.env
[(dat
>points
)?points
:dat
].pos
;
1616 if (aout
->penv
.env
) {
1617 points
=i
->panenv
[i
->panpts
-1].pos
;
1618 aout
->penv
.p
=aout
->penv
.env
[(dat
>points
)?points
:dat
].pos
;
1626 static int DoXMEffectP(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1646 /* slide right has absolute priority */
1650 pan
=((a
->main
.panning
==PAN_SURROUND
)?PAN_CENTER
:a
->main
.panning
)+hi
-lo
;
1651 a
->main
.panning
=(pan
<PAN_LEFT
)?PAN_LEFT
:(pan
>PAN_RIGHT
?PAN_RIGHT
:pan
);
1657 static int DoXMEffectX1(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1666 a
->ffportupspd
= dat
;
1668 dat
= a
->ffportupspd
;
1672 a
->main
.period
-=dat
;
1680 static int DoXMEffectX2(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1691 dat
= a
->ffportdnspd
;
1695 a
->main
.period
+=dat
;
1703 /*========== Impulse Tracker effects */
1705 static void DoITToneSlide(UWORD tick
, MP_CONTROL
*a
, UBYTE dat
)
1710 /* if we don't come from another note, ignore the slide and play the note
1712 if (!a
->oldnote
|| !a
->main
.period
)
1715 if ((!tick
)&&(a
->newsamp
)){
1716 a
->main
.kick
=KICK_NOTE
;
1719 a
->main
.kick
=(a
->main
.kick
==KICK_NOTE
)?KICK_ENV
:KICK_ABSENT
;
1724 /* We have to slide a->main.period towards a->wantedperiod, compute the
1725 difference between those two values */
1726 dist
=a
->main
.period
-a
->wantedperiod
;
1728 /* if they are equal or if portamentospeed is too big... */
1729 if ((!dist
)||((a
->portspeed
<<2)>abs(dist
)))
1730 /* ... make tmpperiod equal tperiod */
1731 a
->tmpperiod
=a
->main
.period
=a
->wantedperiod
;
1734 a
->tmpperiod
-=a
->portspeed
<<2;
1735 a
->main
.period
-=a
->portspeed
<<2; /* dist>0 slide up */
1737 a
->tmpperiod
+=a
->portspeed
<<2;
1738 a
->main
.period
+=a
->portspeed
<<2; /* dist<0 slide down */
1741 a
->tmpperiod
=a
->main
.period
;
1745 static int DoITEffectG(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1750 DoITToneSlide(tick
, a
, UniGetByte());
1755 static void DoITVibrato(UWORD tick
, MP_CONTROL
*a
, UBYTE dat
)
1761 if (dat
&0x0f) a
->vibdepth
=dat
&0xf;
1762 if (dat
&0xf0) a
->vibspd
=(dat
&0xf0)>>2;
1764 if (!a
->main
.period
)
1767 q
=(a
->vibpos
>>2)&0x1f;
1769 switch (a
->wavecontrol
&3) {
1771 temp
=VibratoTable
[q
];
1773 case 1: /* square wave */
1776 case 2: /* ramp down */
1778 if (a
->vibpos
<0) q
=255-q
;
1781 case 3: /* random */
1782 temp
=getrandom(256);
1791 a
->main
.period
=a
->tmpperiod
+temp
;
1793 a
->main
.period
=a
->tmpperiod
-temp
;
1796 a
->vibpos
+=a
->vibspd
;
1799 static int DoITEffectH(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1804 DoITVibrato(tick
, a
, UniGetByte());
1809 static int DoITEffectI(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1829 a
->s3mtremor
%=(on
+off
);
1830 a
->volume
=(a
->s3mtremor
<on
)?a
->tmpvolume
:0;
1837 static int DoITEffectM(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1843 a
->main
.chanvol
=UniGetByte();
1844 if (a
->main
.chanvol
>64)
1846 else if (a
->main
.chanvol
<0)
1852 static int DoITEffectN(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1863 a
->chanvolslide
= inf
;
1865 inf
= a
->chanvolslide
;
1871 a
->main
.chanvol
-=lo
;
1874 a
->main
.chanvol
+=hi
;
1877 if (!tick
) a
->main
.chanvol
-=lo
;
1880 if (!tick
) a
->main
.chanvol
+=hi
;
1883 if (a
->main
.chanvol
<0)
1885 else if (a
->main
.chanvol
>64)
1891 static int DoITEffectP(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1911 pan
=(a
->main
.panning
==PAN_SURROUND
)?PAN_CENTER
:a
->main
.panning
;
1920 if (!tick
) pan
+=lo
<<2;
1923 if (!tick
) pan
-=hi
<<2;
1926 (pan
<PAN_LEFT
)?PAN_LEFT
:(pan
>PAN_RIGHT
?PAN_RIGHT
:pan
);
1931 static int DoITEffectT(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1940 tempo
= UniGetByte();
1947 temp
+= (tempo
& 0x0f);
1951 mod
->bpm
=(temp
>255)?255:(temp
<1?1:temp
);
1956 static int DoITEffectU(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1959 UWORD temp
= 0; /* silence warning */
1966 if (dat
&0x0f) a
->vibdepth
=dat
&0xf;
1967 if (dat
&0xf0) a
->vibspd
=(dat
&0xf0)>>2;
1969 if (a
->main
.period
) {
1970 q
=(a
->vibpos
>>2)&0x1f;
1972 switch (a
->wavecontrol
&3) {
1974 temp
=VibratoTable
[q
];
1976 case 1: /* square wave */
1979 case 2: /* ramp down */
1981 if (a
->vibpos
<0) q
=255-q
;
1984 case 3: /* random */
1985 temp
=getrandom(256);
1993 a
->main
.period
=a
->tmpperiod
+temp
;
1995 a
->main
.period
=a
->tmpperiod
-temp
;
1998 a
->vibpos
+=a
->vibspd
;
2004 static int DoITEffectW(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
2014 mod
->globalslide
= inf
;
2016 inf
= mod
->globalslide
;
2022 if (tick
) mod
->volume
+=hi
;
2025 if (tick
) mod
->volume
-=lo
;
2028 if (!tick
) mod
->volume
+=hi
;
2031 if (!tick
) mod
->volume
-=lo
;
2036 else if (mod
->volume
>128)
2042 static int DoITEffectY(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
2045 SLONG temp
= 0; /* silence warning */
2051 if (dat
&0x0f) a
->panbdepth
=(dat
&0xf);
2052 if (dat
&0xf0) a
->panbspd
=(dat
&0xf0)>>4;
2057 switch (a
->panbwave
) {
2059 temp
=PanbrelloTable
[q
];
2061 case 1: /* square wave */
2064 case 2: /* ramp down */
2068 case 3: /* random */
2069 temp
=getrandom(256);
2074 temp
=(temp
/8)+mod
->panning
[channel
];
2077 (temp
<PAN_LEFT
)?PAN_LEFT
:(temp
>PAN_RIGHT
?PAN_RIGHT
:temp
);
2078 a
->panbpos
+=a
->panbspd
;
2085 static void DoNNAEffects(MODULE
*, MP_CONTROL
*, UBYTE
);
2087 /* Impulse/Scream Tracker Sxx effects.
2088 All Sxx effects share the same memory space. */
2089 static int DoITEffectS0(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
2106 case SS_GLISSANDO
: /* S1x set glissando voice */
2107 DoEEffects(tick
, flags
, a
, mod
, channel
, 0x30|inf
);
2109 case SS_FINETUNE
: /* S2x set finetune */
2110 DoEEffects(tick
, flags
, a
, mod
, channel
, 0x50|inf
);
2112 case SS_VIBWAVE
: /* S3x set vibrato waveform */
2113 DoEEffects(tick
, flags
, a
, mod
, channel
, 0x40|inf
);
2115 case SS_TREMWAVE
: /* S4x set tremolo waveform */
2116 DoEEffects(tick
, flags
, a
, mod
, channel
, 0x70|inf
);
2118 case SS_PANWAVE
: /* S5x panbrello */
2121 case SS_FRAMEDELAY
: /* S6x delay x number of frames (patdly) */
2122 DoEEffects(tick
, flags
, a
, mod
, channel
, 0xe0|inf
);
2124 case SS_S7EFFECTS
: /* S7x instrument / NNA commands */
2125 DoNNAEffects(mod
, a
, inf
);
2127 case SS_PANNING
: /* S8x set panning position */
2128 DoEEffects(tick
, flags
, a
, mod
, channel
, 0x80 | inf
);
2130 case SS_SURROUND
: /* S9x set surround sound */
2132 a
->main
.panning
= mod
->panning
[channel
] = PAN_SURROUND
;
2134 case SS_HIOFFSET
: /* SAy set high order sample offset yxx00h */
2136 a
->hioffset
=inf
<<16;
2137 a
->main
.start
=a
->hioffset
|a
->soffset
;
2139 if ((a
->main
.s
)&&(a
->main
.start
> (SLONG
)a
->main
.s
->length
))
2140 a
->main
.start
=a
->main
.s
->flags
&(SF_LOOP
|SF_BIDI
)?
2141 a
->main
.s
->loopstart
:a
->main
.s
->length
;
2144 case SS_PATLOOP
: /* SBx pattern loop */
2145 DoEEffects(tick
, flags
, a
, mod
, channel
, 0x60|inf
);
2147 case SS_NOTECUT
: /* SCx notecut */
2149 DoEEffects(tick
, flags
, a
, mod
, channel
, 0xC0|inf
);
2151 case SS_NOTEDELAY
: /* SDx notedelay */
2152 DoEEffects(tick
, flags
, a
, mod
, channel
, 0xD0|inf
);
2154 case SS_PATDELAY
: /* SEx patterndelay */
2155 DoEEffects(tick
, flags
, a
, mod
, channel
, 0xE0|inf
);
2162 /*========== Impulse Tracker Volume/Pan Column effects */
2165 * All volume/pan column effects share the same memory space.
2168 static int DoVolEffects(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
2193 a
->main
.panning
=inf
;
2196 DoS3MVolSlide(tick
, flags
, a
, inf
);
2198 case VOL_PITCHSLIDEDN
:
2200 DoS3MSlideDn(tick
, a
, inf
);
2202 case VOL_PITCHSLIDEUP
:
2204 DoS3MSlideUp(tick
, a
, inf
);
2206 case VOL_PORTAMENTO
:
2207 DoITToneSlide(tick
, a
, inf
);
2210 DoITVibrato(tick
, a
, inf
);
2217 /*========== UltraTracker effects */
2219 static int DoULTEffect9(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
2221 UWORD offset
=UniGetWord();
2228 a
->ultoffset
=offset
;
2230 a
->main
.start
=a
->ultoffset
<<2;
2231 if ((a
->main
.s
)&&(a
->main
.start
> (SLONG
)a
->main
.s
->length
))
2232 a
->main
.start
=a
->main
.s
->flags
&(SF_LOOP
|SF_BIDI
)?
2233 a
->main
.s
->loopstart
:a
->main
.s
->length
;
2238 /*========== OctaMED effects */
2240 static int DoMEDSpeed(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
2242 UWORD speed
=UniGetWord();
2253 static int DoMEDEffectF1(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
2255 DoEEffects(tick
, flags
, a
, mod
, channel
, 0x90|(mod
->sngspd
/2));
2260 static int DoMEDEffectF2(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
2262 DoEEffects(tick
, flags
, a
, mod
, channel
, 0xd0|(mod
->sngspd
/2));
2267 static int DoMEDEffectF3(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
2269 DoEEffects(tick
, flags
, a
, mod
, channel
, 0x90|(mod
->sngspd
/3));
2274 /*========== Oktalyzer effects */
2276 static int DoOktArp(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
2282 dat2
= UniGetByte(); /* arpeggio style */
2285 if (!dat
&& (flags
& UF_ARPMEM
))
2291 DoArpeggio(tick
, flags
, a
, dat2
);
2296 /*========== General player functions */
2298 static int DoNothing(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
2310 typedef int (*effect_func
) (UWORD
, UWORD
, MP_CONTROL
*, MODULE
*, SWORD
);
2312 static effect_func effects
[UNI_LAST
] = {
2314 DoNothing
, /* UNI_NOTE */
2315 DoNothing
, /* UNI_INSTRUMENT */
2316 DoPTEffect0
, /* UNI_PTEFFECT0 */
2317 DoPTEffect1
, /* UNI_PTEFFECT1 */
2318 DoPTEffect2
, /* UNI_PTEFFECT2 */
2319 DoPTEffect3
, /* UNI_PTEFFECT3 */
2320 DoPTEffect4
, /* UNI_PTEFFECT4 */
2321 DoPTEffect5
, /* UNI_PTEFFECT5 */
2322 DoPTEffect6
, /* UNI_PTEFFECT6 */
2323 DoPTEffect7
, /* UNI_PTEFFECT7 */
2324 DoPTEffect8
, /* UNI_PTEFFECT8 */
2325 DoPTEffect9
, /* UNI_PTEFFECT9 */
2326 DoPTEffectA
, /* UNI_PTEFFECTA */
2327 DoPTEffectB
, /* UNI_PTEFFECTB */
2328 DoPTEffectC
, /* UNI_PTEFFECTC */
2329 DoPTEffectD
, /* UNI_PTEFFECTD */
2330 DoPTEffectE
, /* UNI_PTEFFECTE */
2331 DoPTEffectF
, /* UNI_PTEFFECTF */
2332 DoS3MEffectA
, /* UNI_S3MEFFECTA */
2333 DoS3MEffectD
, /* UNI_S3MEFFECTD */
2334 DoS3MEffectE
, /* UNI_S3MEFFECTE */
2335 DoS3MEffectF
, /* UNI_S3MEFFECTF */
2336 DoS3MEffectI
, /* UNI_S3MEFFECTI */
2337 DoS3MEffectQ
, /* UNI_S3MEFFECTQ */
2338 DoS3MEffectR
, /* UNI_S3MEFFECTR */
2339 DoS3MEffectT
, /* UNI_S3MEFFECTT */
2340 DoS3MEffectU
, /* UNI_S3MEFFECTU */
2341 DoKeyOff
, /* UNI_KEYOFF */
2342 DoKeyFade
, /* UNI_KEYFADE */
2343 DoVolEffects
, /* UNI_VOLEFFECTS */
2344 DoPTEffect4
, /* UNI_XMEFFECT4 */
2345 DoXMEffect6
, /* UNI_XMEFFECT6 */
2346 DoXMEffectA
, /* UNI_XMEFFECTA */
2347 DoXMEffectE1
, /* UNI_XMEFFECTE1 */
2348 DoXMEffectE2
, /* UNI_XMEFFECTE2 */
2349 DoXMEffectEA
, /* UNI_XMEFFECTEA */
2350 DoXMEffectEB
, /* UNI_XMEFFECTEB */
2351 DoXMEffectG
, /* UNI_XMEFFECTG */
2352 DoXMEffectH
, /* UNI_XMEFFECTH */
2353 DoXMEffectL
, /* UNI_XMEFFECTL */
2354 DoXMEffectP
, /* UNI_XMEFFECTP */
2355 DoXMEffectX1
, /* UNI_XMEFFECTX1 */
2356 DoXMEffectX2
, /* UNI_XMEFFECTX2 */
2357 DoITEffectG
, /* UNI_ITEFFECTG */
2358 DoITEffectH
, /* UNI_ITEFFECTH */
2359 DoITEffectI
, /* UNI_ITEFFECTI */
2360 DoITEffectM
, /* UNI_ITEFFECTM */
2361 DoITEffectN
, /* UNI_ITEFFECTN */
2362 DoITEffectP
, /* UNI_ITEFFECTP */
2363 DoITEffectT
, /* UNI_ITEFFECTT */
2364 DoITEffectU
, /* UNI_ITEFFECTU */
2365 DoITEffectW
, /* UNI_ITEFFECTW */
2366 DoITEffectY
, /* UNI_ITEFFECTY */
2367 DoNothing
, /* UNI_ITEFFECTZ */
2368 DoITEffectS0
, /* UNI_ITEFFECTS0 */
2369 DoULTEffect9
, /* UNI_ULTEFFECT9 */
2370 DoMEDSpeed
, /* UNI_MEDSPEED */
2371 DoMEDEffectF1
, /* UNI_MEDEFFECTF1 */
2372 DoMEDEffectF2
, /* UNI_MEDEFFECTF2 */
2373 DoMEDEffectF3
, /* UNI_MEDEFFECTF3 */
2374 DoOktArp
, /* UNI_OKTARP */
2377 static int pt_playeffects(MODULE
*mod
, SWORD channel
, MP_CONTROL
*a
)
2379 UWORD tick
= mod
->vbtick
;
2380 UWORD flags
= mod
->flags
;
2382 int explicitslides
= 0;
2385 while((c
=UniGetByte())) {
2389 explicitslides
|= f(tick
, flags
, a
, mod
, channel
);
2391 return explicitslides
;
2394 static void DoNNAEffects(MODULE
*mod
, MP_CONTROL
*a
, UBYTE dat
)
2400 aout
=(a
->slave
)?a
->slave
:NULL
;
2403 case 0x0: /* past note cut */
2404 for (t
=0;t
<md_sngchn
;t
++)
2405 if (mod
->voice
[t
].master
==a
)
2406 mod
->voice
[t
].main
.fadevol
=0;
2408 case 0x1: /* past note off */
2409 for (t
=0;t
<md_sngchn
;t
++)
2410 if (mod
->voice
[t
].master
==a
) {
2411 mod
->voice
[t
].main
.keyoff
|=KEY_OFF
;
2412 if ((!(mod
->voice
[t
].venv
.flg
& EF_ON
))||
2413 (mod
->voice
[t
].venv
.flg
& EF_LOOP
))
2414 mod
->voice
[t
].main
.keyoff
=KEY_KILL
;
2417 case 0x2: /* past note fade */
2418 for (t
=0;t
<md_sngchn
;t
++)
2419 if (mod
->voice
[t
].master
==a
)
2420 mod
->voice
[t
].main
.keyoff
|=KEY_FADE
;
2422 case 0x3: /* set NNA note cut */
2423 a
->main
.nna
=(a
->main
.nna
&~NNA_MASK
)|NNA_CUT
;
2425 case 0x4: /* set NNA note continue */
2426 a
->main
.nna
=(a
->main
.nna
&~NNA_MASK
)|NNA_CONTINUE
;
2428 case 0x5: /* set NNA note off */
2429 a
->main
.nna
=(a
->main
.nna
&~NNA_MASK
)|NNA_OFF
;
2431 case 0x6: /* set NNA note fade */
2432 a
->main
.nna
=(a
->main
.nna
&~NNA_MASK
)|NNA_FADE
;
2434 case 0x7: /* disable volume envelope */
2436 aout
->main
.volflg
&=~EF_ON
;
2438 case 0x8: /* enable volume envelope */
2440 aout
->main
.volflg
|=EF_ON
;
2442 case 0x9: /* disable panning envelope */
2444 aout
->main
.panflg
&=~EF_ON
;
2446 case 0xa: /* enable panning envelope */
2448 aout
->main
.panflg
|=EF_ON
;
2450 case 0xb: /* disable pitch envelope */
2452 aout
->main
.pitflg
&=~EF_ON
;
2454 case 0xc: /* enable pitch envelope */
2456 aout
->main
.pitflg
|=EF_ON
;
2461 static void pt_UpdateVoices(MODULE
*mod
, int max_volume
)
2463 SWORD envpan
,envvol
,envpit
,channel
;
2465 SLONG vibval
,vibdpt
;
2472 mod
->totalchn
=mod
->realchn
=0;
2473 for (channel
=0;channel
<md_sngchn
;channel
++) {
2474 aout
=&mod
->voice
[channel
];
2478 if (!s
|| !s
->length
) continue;
2480 if (aout
->main
.period
<40)
2481 aout
->main
.period
=40;
2482 else if (aout
->main
.period
>50000)
2483 aout
->main
.period
=50000;
2485 if ((aout
->main
.kick
==KICK_NOTE
)||(aout
->main
.kick
==KICK_KEYOFF
)) {
2486 Voice_Play_internal(channel
,s
,(aout
->main
.start
==-1)?
2487 ((s
->flags
&SF_UST_LOOP
) ? (SLONG
)s
->loopstart
: 0) : aout
->main
.start
);
2488 aout
->main
.fadevol
=32768;
2493 envpan
= PAN_CENTER
;
2495 if (i
&& ((aout
->main
.kick
==KICK_NOTE
)||(aout
->main
.kick
==KICK_ENV
))) {
2496 if (aout
->main
.volflg
& EF_ON
)
2497 envvol
= StartEnvelope(&aout
->venv
,aout
->main
.volflg
,
2498 i
->volpts
,i
->volsusbeg
,i
->volsusend
,
2499 i
->volbeg
,i
->volend
,i
->volenv
,aout
->main
.keyoff
);
2500 if (aout
->main
.panflg
& EF_ON
)
2501 envpan
= StartEnvelope(&aout
->penv
,aout
->main
.panflg
,
2502 i
->panpts
,i
->pansusbeg
,i
->pansusend
,
2503 i
->panbeg
,i
->panend
,i
->panenv
,aout
->main
.keyoff
);
2504 if (aout
->main
.pitflg
& EF_ON
)
2505 envpit
= StartEnvelope(&aout
->cenv
,aout
->main
.pitflg
,
2506 i
->pitpts
,i
->pitsusbeg
,i
->pitsusend
,
2507 i
->pitbeg
,i
->pitend
,i
->pitenv
,aout
->main
.keyoff
);
2509 if (aout
->cenv
.flg
& EF_ON
)
2510 aout
->masterperiod
=GetPeriod(mod
->flags
,
2511 (UWORD
)aout
->main
.note
<<1, aout
->master
->speed
);
2513 if (aout
->main
.volflg
& EF_ON
)
2514 envvol
= ProcessEnvelope(aout
,&aout
->venv
,256);
2515 if (aout
->main
.panflg
& EF_ON
)
2516 envpan
= ProcessEnvelope(aout
,&aout
->penv
,PAN_CENTER
);
2517 if (aout
->main
.pitflg
& EF_ON
)
2518 envpit
= ProcessEnvelope(aout
,&aout
->cenv
,32);
2520 if (aout
->main
.kick
== KICK_NOTE
) {
2521 aout
->main
.kick_flag
= 1;
2523 aout
->main
.kick
=KICK_ABSENT
;
2525 tmpvol
= aout
->main
.fadevol
; /* max 32768 */
2526 tmpvol
*= aout
->main
.chanvol
; /* * max 64 */
2527 tmpvol
*= aout
->main
.outvolume
; /* * max 256 */
2528 tmpvol
/= (256 * 64); /* tmpvol is max 32768 again */
2529 aout
->totalvol
= tmpvol
>> 2; /* used to determine samplevolume */
2530 tmpvol
*= envvol
; /* * max 256 */
2531 tmpvol
*= mod
->volume
; /* * max 128 */
2532 tmpvol
/= (128 * 256 * 128);
2535 if (mod
->sngpos
>=mod
->numpos
)
2538 tmpvol
=(tmpvol
*max_volume
)/128;
2540 if ((aout
->masterchn
!=-1)&& mod
->control
[aout
->masterchn
].muted
)
2541 Voice_SetVolume_internal(channel
,0);
2543 Voice_SetVolume_internal(channel
,tmpvol
);
2544 if ((tmpvol
)&&(aout
->master
)&&(aout
->master
->slave
==aout
))
2549 if (aout
->main
.panning
==PAN_SURROUND
)
2550 Voice_SetPanning_internal(channel
,PAN_SURROUND
);
2552 if ((mod
->panflag
)&&(aout
->penv
.flg
& EF_ON
))
2553 Voice_SetPanning_internal(channel
,
2554 DoPan(envpan
,aout
->main
.panning
));
2556 Voice_SetPanning_internal(channel
,aout
->main
.panning
);
2558 if (aout
->main
.period
&& s
->vibdepth
)
2559 switch (s
->vibtype
) {
2561 vibval
=avibtab
[s
->avibpos
&127];
2562 if (aout
->avibpos
& 0x80) vibval
=-vibval
;
2566 if (aout
->avibpos
& 0x80) vibval
=-vibval
;
2569 vibval
=63-(((aout
->avibpos
+128)&255)>>1);
2572 vibval
=(((aout
->avibpos
+128)&255)>>1)-64;
2578 if (s
->vibflags
& AV_IT
) {
2579 if ((aout
->aswppos
>>8)<s
->vibdepth
) {
2580 aout
->aswppos
+= s
->vibsweep
;
2581 vibdpt
=aout
->aswppos
;
2583 vibdpt
=s
->vibdepth
<<8;
2584 vibval
=(vibval
*vibdpt
)>>16;
2586 if (!(mod
->flags
&UF_LINEAR
)) vibval
>>=1;
2587 aout
->main
.period
-=vibval
;
2590 /* do XM style auto-vibrato */
2591 if (!(aout
->main
.keyoff
& KEY_OFF
)) {
2592 if (aout
->aswppos
<s
->vibsweep
) {
2593 vibdpt
=(aout
->aswppos
*s
->vibdepth
)/s
->vibsweep
;
2598 /* keyoff -> depth becomes 0 if final depth wasn't reached or
2599 stays at final level if depth WAS reached */
2600 if (aout
->aswppos
>=s
->vibsweep
)
2605 vibval
=(vibval
*vibdpt
)>>8;
2606 aout
->main
.period
-=vibval
;
2609 /* update vibrato position */
2610 aout
->avibpos
=(aout
->avibpos
+s
->vibrate
)&0xff;
2612 /* process pitch envelope */
2613 playperiod
=aout
->main
.period
;
2615 if ((aout
->main
.pitflg
&EF_ON
)&&(envpit
!=32)) {
2619 if ((aout
->main
.note
<<1)+envpit
<=0) envpit
=-(aout
->main
.note
<<1);
2621 p1
=GetPeriod(mod
->flags
, ((UWORD
)aout
->main
.note
<<1)+envpit
,
2622 aout
->master
->speed
)-aout
->masterperiod
;
2624 if ((UWORD
)(playperiod
+p1
)<=playperiod
) {
2626 aout
->main
.keyoff
|=KEY_OFF
;
2629 if ((UWORD
)(playperiod
+p1
)>=playperiod
) {
2631 aout
->main
.keyoff
|=KEY_OFF
;
2637 if (!aout
->main
.fadevol
) { /* check for a dead note (fadevol=0) */
2638 Voice_Stop_internal(channel
);
2640 if ((tmpvol
)&&(aout
->master
)&&(aout
->master
->slave
==aout
))
2643 Voice_SetFrequency_internal(channel
,
2644 getfrequency(mod
->flags
,playperiod
));
2646 /* if keyfade, start substracting fadeoutspeed from fadevol: */
2647 if ((i
)&&(aout
->main
.keyoff
&KEY_FADE
)) {
2648 if (aout
->main
.fadevol
>=i
->volfade
)
2649 aout
->main
.fadevol
-=i
->volfade
;
2651 aout
->main
.fadevol
=0;
2655 md_bpm
=mod
->bpm
+mod
->relspd
;
2658 else if ((!(mod
->flags
&UF_HIGHBPM
)) && md_bpm
>255)
2663 /* Handles new notes or instruments */
2664 static void pt_Notes(MODULE
*mod
)
2669 int tr
,funky
; /* funky is set to indicate note or instrument change */
2671 for (channel
=0;channel
<mod
->numchn
;channel
++) {
2672 a
=&mod
->control
[channel
];
2674 if (mod
->sngpos
>=mod
->numpos
) {
2678 tr
=mod
->patterns
[(mod
->positions
[mod
->sngpos
]*mod
->numchn
)+channel
];
2679 mod
->numrow
=mod
->pattrows
[mod
->positions
[mod
->sngpos
]];
2682 a
->row
=(tr
<mod
->numtrk
)?UniFindRow(mod
->tracks
[tr
],mod
->patpos
):NULL
;
2684 if (!mod
->vbtick
) a
->main
.notedelay
=0;
2686 if (!a
->row
) continue;
2690 while((c
=UniGetByte()))
2694 a
->oldnote
=a
->anote
,a
->anote
=UniGetByte();
2695 a
->main
.kick
=KICK_NOTE
;
2699 /* retrig tremolo and vibrato waves ? */
2700 if (!(a
->wavecontrol
& 0x80)) a
->trmpos
=0;
2701 if (!(a
->wavecontrol
& 0x08)) a
->vibpos
=0;
2702 if (!a
->panbwave
) a
->panbpos
=0;
2704 case UNI_INSTRUMENT
:
2706 if (inst
>=mod
->numins
) break; /* safety valve */
2708 a
->main
.i
=(mod
->flags
& UF_INST
)?&mod
->instruments
[inst
]:NULL
;
2712 a
->main
.sample
=inst
;
2723 if ((i
=a
->main
.i
)) {
2724 if (i
->samplenumber
[a
->anote
] >= mod
->numsmp
) continue;
2725 s
=&mod
->samples
[i
->samplenumber
[a
->anote
]];
2726 a
->main
.note
=i
->samplenote
[a
->anote
];
2728 a
->main
.note
=a
->anote
;
2729 s
=&mod
->samples
[a
->main
.sample
];
2734 a
->newsamp
=a
->main
.period
;
2737 /* channel or instrument determined panning ? */
2738 a
->main
.panning
=mod
->panning
[channel
];
2739 if (s
->flags
& SF_OWNPAN
)
2740 a
->main
.panning
=s
->panning
;
2741 else if ((i
)&&(i
->flags
& IF_OWNPAN
))
2742 a
->main
.panning
=i
->panning
;
2744 a
->main
.handle
=s
->handle
;
2748 if ((mod
->panflag
)&&(i
->flags
& IF_PITCHPAN
)
2749 &&(a
->main
.panning
!=PAN_SURROUND
)){
2751 ((a
->anote
-i
->pitpancenter
)*i
->pitpansep
)/8;
2752 if (a
->main
.panning
<PAN_LEFT
)
2753 a
->main
.panning
=PAN_LEFT
;
2754 else if (a
->main
.panning
>PAN_RIGHT
)
2755 a
->main
.panning
=PAN_RIGHT
;
2757 a
->main
.pitflg
=i
->pitflg
;
2758 a
->main
.volflg
=i
->volflg
;
2759 a
->main
.panflg
=i
->panflg
;
2760 a
->main
.nna
=i
->nnatype
;
2764 a
->main
.pitflg
=a
->main
.volflg
=a
->main
.panflg
=0;
2765 a
->main
.nna
=a
->dca
=0;
2769 if (funky
&2) /* instrument change */ {
2770 /* IT random volume variations: 0:8 bit fixed, and one bit for
2772 a
->volume
=a
->tmpvolume
=s
->volume
;
2775 a
->volume
=a
->tmpvolume
=s
->volume
+
2776 ((s
->volume
*((SLONG
)i
->rvolvar
*(SLONG
)getrandom(512)
2779 a
->volume
=a
->tmpvolume
=0;
2780 else if (a
->volume
>64)
2781 a
->volume
=a
->tmpvolume
=64;
2783 if ((mod
->panflag
)&&(a
->main
.panning
!=PAN_SURROUND
)) {
2784 a
->main
.panning
+=((a
->main
.panning
*((SLONG
)i
->rpanvar
*
2785 (SLONG
)getrandom(512)))/25600);
2786 if (a
->main
.panning
<PAN_LEFT
)
2787 a
->main
.panning
=PAN_LEFT
;
2788 else if (a
->main
.panning
>PAN_RIGHT
)
2789 a
->main
.panning
=PAN_RIGHT
;
2794 a
->wantedperiod
=a
->tmpperiod
=
2795 GetPeriod(mod
->flags
, (UWORD
)a
->main
.note
<<1,a
->speed
);
2796 a
->main
.keyoff
=KEY_KICK
;
2801 /* Handles effects */
2802 static void pt_EffectsPass1(MODULE
*mod
)
2809 for (channel
=0;channel
<mod
->numchn
;channel
++) {
2810 a
=&mod
->control
[channel
];
2812 if ((aout
=a
->slave
)) {
2813 a
->main
.fadevol
=aout
->main
.fadevol
;
2814 a
->main
.period
=aout
->main
.period
;
2815 if (a
->main
.kick
==KICK_KEYOFF
)
2816 a
->main
.keyoff
=aout
->main
.keyoff
;
2819 if (!a
->row
) continue;
2822 a
->ownper
=a
->ownvol
=0;
2823 explicitslides
= pt_playeffects(mod
, channel
, a
);
2825 /* continue volume slide if necessary for XM and IT */
2826 if (mod
->flags
&UF_BGSLIDES
) {
2827 if (!explicitslides
&& a
->sliding
)
2828 DoS3MVolSlide(mod
->vbtick
, mod
->flags
, a
, 0);
2829 else if (a
->tmpvolume
)
2830 a
->sliding
= explicitslides
;
2834 a
->main
.period
=a
->tmpperiod
;
2836 a
->volume
=a
->tmpvolume
;
2841 (a
->volume
*a
->main
.s
->globvol
*a
->main
.i
->globvol
)>>10;
2843 a
->main
.outvolume
=(a
->volume
*a
->main
.s
->globvol
)>>4;
2844 if (a
->main
.outvolume
>256)
2845 a
->main
.outvolume
=256;
2846 else if (a
->main
.outvolume
<0)
2847 a
->main
.outvolume
=0;
2852 /* NNA management */
2853 static void pt_NNA(MODULE
*mod
)
2858 for (channel
=0;channel
<mod
->numchn
;channel
++) {
2859 a
=&mod
->control
[channel
];
2861 if (a
->main
.kick
==KICK_NOTE
) {
2868 if (aout
->main
.nna
& NNA_MASK
) {
2869 /* Make sure the old MP_VOICE channel knows it has no
2872 /* assume the channel is taken by NNA */
2875 switch (aout
->main
.nna
) {
2876 case NNA_CONTINUE
: /* continue note, do nothing */
2878 case NNA_OFF
: /* note off */
2879 aout
->main
.keyoff
|=KEY_OFF
;
2880 if ((!(aout
->main
.volflg
& EF_ON
))||
2881 (aout
->main
.volflg
& EF_LOOP
))
2882 aout
->main
.keyoff
=KEY_KILL
;
2885 aout
->main
.keyoff
|= KEY_FADE
;
2891 if (a
->dct
!=DCT_OFF
) {
2894 for (t
=0;t
<md_sngchn
;t
++)
2895 if ((!Voice_Stopped_internal(t
))&&
2896 (mod
->voice
[t
].masterchn
==channel
)&&
2897 (a
->main
.sample
==mod
->voice
[t
].main
.sample
)) {
2901 if (a
->main
.note
==mod
->voice
[t
].main
.note
)
2905 if (a
->main
.handle
==mod
->voice
[t
].main
.handle
)
2915 mod
->voice
[t
].main
.fadevol
=0;
2918 mod
->voice
[t
].main
.keyoff
|=KEY_OFF
;
2919 if ((!(mod
->voice
[t
].main
.volflg
&EF_ON
))||
2920 (mod
->voice
[t
].main
.volflg
&EF_LOOP
))
2921 mod
->voice
[t
].main
.keyoff
=KEY_KILL
;
2924 mod
->voice
[t
].main
.keyoff
|=KEY_FADE
;
2929 } /* if (a->main.kick==KICK_NOTE) */
2933 /* Setup module and NNA voices */
2934 static void pt_SetupVoices(MODULE
*mod
)
2940 for (channel
=0;channel
<mod
->numchn
;channel
++) {
2941 a
=&mod
->control
[channel
];
2943 if (a
->main
.notedelay
) continue;
2944 if (a
->main
.kick
==KICK_NOTE
) {
2945 /* if no channel was cut above, find an empty or quiet channel
2947 if (mod
->flags
&UF_NNA
) {
2951 if ((newchn
=MP_FindEmptyChannel(mod
))!=-1)
2952 a
->slave
=&mod
->voice
[a
->slavechn
=newchn
];
2955 a
->slave
=&mod
->voice
[a
->slavechn
=channel
];
2957 /* assign parts of MP_VOICE only done for a KICK_NOTE */
2958 if ((aout
=a
->slave
)) {
2959 if (aout
->mflag
&& aout
->master
) aout
->master
->slave
=NULL
;
2962 aout
->masterchn
=channel
;
2970 a
->main
.kick
=KICK_ABSENT
;
2974 /* second effect pass */
2975 static void pt_EffectsPass2(MODULE
*mod
)
2981 for (channel
=0;channel
<mod
->numchn
;channel
++) {
2982 a
=&mod
->control
[channel
];
2984 if (!a
->row
) continue;
2987 while((c
=UniGetByte()))
2988 if (c
==UNI_ITEFFECTS0
) {
2990 if ((c
>>4)==SS_S7EFFECTS
)
2991 DoNNAEffects(mod
, a
, c
&0xf);
2997 void Player_HandleTick(void)
3003 /* don't handle the very first ticks, this allows the other hardware to
3004 settle down so we don't loose any starting notes */
3011 if ((!pf
)||(pf
->forbid
)||(pf
->sngpos
>=pf
->numpos
)) return;
3013 /* update time counter (sngtime is in milliseconds (in fact 2^-10)) */
3014 pf
->sngremainder
+=(1<<9)*5; /* thus 2.5*(1<<10), since fps=0.4xtempo */
3015 pf
->sngtime
+=pf
->sngremainder
/pf
->bpm
;
3016 pf
->sngremainder
%=pf
->bpm
;
3018 if (++pf
->vbtick
>=pf
->sngspd
) {
3019 if (pf
->pat_repcrazy
)
3020 pf
->pat_repcrazy
=0; /* play 2 times row 0 */
3025 /* process pattern-delay. pf->patdly2 is the counter and pf->patdly is
3026 the command memory. */
3028 pf
->patdly2
=pf
->patdly
,pf
->patdly
=0;
3030 /* patterndelay active */
3032 /* so turn back pf->patpos by 1 */
3033 if (pf
->patpos
) pf
->patpos
--;
3036 /* do we have to get a new patternpointer ? (when pf->patpos reaches the
3037 pattern size, or when a patternbreak is active) */
3038 if (((pf
->patpos
>=pf
->numrow
)&&(pf
->numrow
>0))&&(!pf
->posjmp
))
3042 pf
->patpos
=pf
->numrow
?(pf
->patbrk
%pf
->numrow
):0;
3044 pf
->sngpos
+=(pf
->posjmp
-2);
3045 for (channel
=0;channel
<pf
->numchn
;channel
++)
3046 pf
->control
[channel
].pat_reppos
=-1;
3048 pf
->patbrk
=pf
->posjmp
=0;
3049 /* handle the "---" (end of song) pattern since it can occur
3050 *inside* the module in some formats */
3051 if ((pf
->sngpos
>=pf
->numpos
)||
3052 (pf
->positions
[pf
->sngpos
]==LAST_PATTERN
)) {
3053 if (!pf
->wrap
) return;
3054 if (!(pf
->sngpos
=pf
->reppos
)) {
3055 pf
->volume
=pf
->initvolume
>128?128:pf
->initvolume
;
3056 if(pf
->initspeed
!=0)
3057 pf
->sngspd
=pf
->initspeed
<32?pf
->initspeed
:32;
3060 pf
->bpm
=pf
->inittempo
<32?32:pf
->inittempo
;
3063 if (pf
->sngpos
<0) pf
->sngpos
=pf
->numpos
-1;
3070 /* Fade global volume if enabled and we're playing the last pattern */
3071 if (((pf
->sngpos
==pf
->numpos
-1)||
3072 (pf
->positions
[pf
->sngpos
+1]==LAST_PATTERN
))&&
3074 max_volume
=pf
->numrow
?((pf
->numrow
-pf
->patpos
)*128)/pf
->numrow
:0;
3078 pt_EffectsPass1(pf
);
3079 if (pf
->flags
&UF_NNA
)
3082 pt_EffectsPass2(pf
);
3084 /* now set up the actual hardware channel playback information */
3085 pt_UpdateVoices(pf
, max_volume
);
3088 static void Player_Init_internal(MODULE
* mod
)
3092 for (t
=0;t
<mod
->numchn
;t
++) {
3093 mod
->control
[t
].main
.chanvol
=mod
->chanvol
[t
];
3094 mod
->control
[t
].main
.panning
=mod
->panning
[t
];
3098 mod
->sngremainder
=0;
3100 mod
->pat_repcrazy
=0;
3102 if(mod
->initspeed
!=0)
3103 mod
->sngspd
=mod
->initspeed
<32?mod
->initspeed
:32;
3106 mod
->volume
=mod
->initvolume
>128?128:mod
->initvolume
;
3108 mod
->vbtick
=mod
->sngspd
;
3111 mod
->bpm
=mod
->inittempo
<32?32:mod
->inittempo
;
3115 mod
->posjmp
=2; /* make sure the player fetches the first note */
3120 int Player_Init(MODULE
* mod
)
3130 /* make sure the player doesn't start with garbage */
3131 if (!(mod
->control
=(MP_CONTROL
*)MikMod_calloc(mod
->numchn
,sizeof(MP_CONTROL
))))
3133 if (!(mod
->voice
=(MP_VOICE
*)MikMod_calloc(md_sngchn
,sizeof(MP_VOICE
))))
3136 Player_Init_internal(mod
);
3140 void Player_Exit_internal(MODULE
* mod
)
3145 /* Stop playback if necessary */
3147 Player_Stop_internal();
3152 MikMod_free(mod
->control
);
3154 MikMod_free(mod
->voice
);
3159 void Player_Exit(MODULE
* mod
)
3162 Player_Exit_internal(mod
);
3166 MIKMODAPI
void Player_SetVolume(SWORD volume
)
3170 pf
->volume
=(volume
<0)?0:(volume
>128)?128:volume
;
3174 MIKMODAPI MODULE
* Player_GetModule(void)
3185 MIKMODAPI
void Player_Start(MODULE
*mod
)
3192 if (!MikMod_Active())
3193 MikMod_EnableOutput();
3199 /* new song is being started, so completely stop out the old one. */
3200 if (pf
) pf
->forbid
=1;
3201 for (t
=0;t
<md_sngchn
;t
++) Voice_Stop_internal(t
);
3207 void Player_Stop_internal(void)
3209 if (!md_sfxchn
) MikMod_DisableOutput_internal();
3210 if (pf
) pf
->forbid
=1;
3214 MIKMODAPI
void Player_Stop(void)
3217 Player_Stop_internal();
3221 MIKMODAPI
int Player_Active(void)
3227 result
=(!(pf
->sngpos
>=pf
->numpos
));
3233 MIKMODAPI
void Player_NextPosition(void)
3242 pf
->vbtick
=pf
->sngspd
;
3244 for (t
=0;t
<md_sngchn
;t
++) {
3245 Voice_Stop_internal(t
);
3246 pf
->voice
[t
].main
.i
=NULL
;
3247 pf
->voice
[t
].main
.s
=NULL
;
3249 for (t
=0;t
<pf
->numchn
;t
++) {
3250 pf
->control
[t
].main
.i
=NULL
;
3251 pf
->control
[t
].main
.s
=NULL
;
3258 MIKMODAPI
void Player_PrevPosition(void)
3267 pf
->vbtick
=pf
->sngspd
;
3269 for (t
=0;t
<md_sngchn
;t
++) {
3270 Voice_Stop_internal(t
);
3271 pf
->voice
[t
].main
.i
=NULL
;
3272 pf
->voice
[t
].main
.s
=NULL
;
3274 for (t
=0;t
<pf
->numchn
;t
++) {
3275 pf
->control
[t
].main
.i
=NULL
;
3276 pf
->control
[t
].main
.s
=NULL
;
3283 MIKMODAPI
void Player_SetPosition(UWORD pos
)
3290 if (pos
>=pf
->numpos
) pos
=pf
->numpos
;
3294 pf
->vbtick
=pf
->sngspd
;
3296 for (t
=0;t
<md_sngchn
;t
++) {
3297 Voice_Stop_internal(t
);
3298 pf
->voice
[t
].main
.i
=NULL
;
3299 pf
->voice
[t
].main
.s
=NULL
;
3301 for (t
=0;t
<pf
->numchn
;t
++) {
3302 pf
->control
[t
].main
.i
=NULL
;
3303 pf
->control
[t
].main
.s
=NULL
;
3308 Player_Init_internal(pf
);
3313 static void Player_Unmute_internal(SLONG arg1
,va_list ap
)
3315 SLONG t
,arg2
,arg3
=0;
3319 case MUTE_INCLUSIVE
:
3320 if (((!(arg2
=va_arg(ap
,SLONG
)))&&(!(arg3
=va_arg(ap
,SLONG
))))||
3321 (arg2
>arg3
)||(arg3
>=pf
->numchn
))
3323 for (;arg2
<pf
->numchn
&& arg2
<=arg3
;arg2
++)
3324 pf
->control
[arg2
].muted
=0;
3326 case MUTE_EXCLUSIVE
:
3327 if (((!(arg2
=va_arg(ap
,SLONG
)))&&(!(arg3
=va_arg(ap
,SLONG
))))||
3328 (arg2
>arg3
)||(arg3
>=pf
->numchn
))
3330 for (t
=0;t
<pf
->numchn
;t
++) {
3331 if ((t
>=arg2
) && (t
<=arg3
))
3333 pf
->control
[t
].muted
=0;
3337 if (arg1
<pf
->numchn
) pf
->control
[arg1
].muted
=0;
3343 MIKMODAPI
void Player_Unmute(SLONG arg1
, ...)
3347 va_start(args
,arg1
);
3349 Player_Unmute_internal(arg1
,args
);
3354 static void Player_Mute_internal(SLONG arg1
,va_list ap
)
3356 SLONG t
,arg2
,arg3
=0;
3360 case MUTE_INCLUSIVE
:
3361 if (((!(arg2
=va_arg(ap
,SLONG
)))&&(!(arg3
=va_arg(ap
,SLONG
))))||
3362 (arg2
>arg3
)||(arg3
>=pf
->numchn
))
3364 for (;arg2
<pf
->numchn
&& arg2
<=arg3
;arg2
++)
3365 pf
->control
[arg2
].muted
=1;
3367 case MUTE_EXCLUSIVE
:
3368 if (((!(arg2
=va_arg(ap
,SLONG
)))&&(!(arg3
=va_arg(ap
,SLONG
))))||
3369 (arg2
>arg3
)||(arg3
>=pf
->numchn
))
3371 for (t
=0;t
<pf
->numchn
;t
++) {
3372 if ((t
>=arg2
) && (t
<=arg3
))
3374 pf
->control
[t
].muted
=1;
3378 if (arg1
<pf
->numchn
)
3379 pf
->control
[arg1
].muted
=1;
3385 MIKMODAPI
void Player_Mute(SLONG arg1
,...)
3389 va_start(args
,arg1
);
3391 Player_Mute_internal(arg1
,args
);
3396 static void Player_ToggleMute_internal(SLONG arg1
,va_list ap
)
3403 case MUTE_INCLUSIVE
:
3404 if (((!(arg2
=va_arg(ap
,SLONG
)))&&(!(arg3
=va_arg(ap
,SLONG
))))||
3405 (arg2
>arg3
)||(arg3
>=pf
->numchn
))
3407 for (;arg2
<pf
->numchn
&& arg2
<=arg3
;arg2
++)
3408 pf
->control
[arg2
].muted
=1-pf
->control
[arg2
].muted
;
3410 case MUTE_EXCLUSIVE
:
3411 if (((!(arg2
=va_arg(ap
,SLONG
)))&&(!(arg3
=va_arg(ap
,SLONG
))))||
3412 (arg2
>arg3
)||(arg3
>=pf
->numchn
))
3414 for (t
=0;t
<pf
->numchn
;t
++) {
3415 if ((t
>=arg2
) && (t
<=arg3
))
3417 pf
->control
[t
].muted
=1-pf
->control
[t
].muted
;
3421 if (arg1
<pf
->numchn
)
3422 pf
->control
[arg1
].muted
=1-pf
->control
[arg1
].muted
;
3428 MIKMODAPI
void Player_ToggleMute(SLONG arg1
,...)
3432 va_start(args
,arg1
);
3434 Player_ToggleMute_internal(arg1
,args
);
3439 MIKMODAPI
int Player_Muted(UBYTE chan
)
3445 result
=(chan
<pf
->numchn
)?pf
->control
[chan
].muted
:1;
3451 MIKMODAPI
int Player_GetChannelVoice(UBYTE chan
)
3457 result
=(chan
<pf
->numchn
)?pf
->control
[chan
].slavechn
:-1;
3463 MIKMODAPI UWORD
Player_GetChannelPeriod(UBYTE chan
)
3469 result
=(chan
<pf
->numchn
)?pf
->control
[chan
].main
.period
:0;
3475 int Player_Paused_internal(void)
3477 return pf
?pf
->forbid
:1;
3480 MIKMODAPI
int Player_Paused(void)
3485 result
=Player_Paused_internal();
3491 MIKMODAPI
void Player_TogglePause(void)
3495 pf
->forbid
=1-pf
->forbid
;
3499 MIKMODAPI
void Player_SetSpeed(UWORD speed
)
3503 pf
->sngspd
=speed
?(speed
<32?speed
:32):1;
3507 MIKMODAPI
void Player_SetTempo(UWORD tempo
)
3509 if (tempo
<32) tempo
=32;
3512 if ((!(pf
->flags
&UF_HIGHBPM
))&&(tempo
>255)) tempo
=255;
3518 MIKMODAPI
int Player_QueryVoices(UWORD numvoices
, VOICEINFO
*vinfo
)
3522 if (numvoices
> md_sngchn
)
3523 numvoices
= md_sngchn
;
3527 for (i
= 0; i
< md_sngchn
; i
++) {
3528 vinfo
[i
].i
= pf
->voice
[i
].main
.i
;
3529 vinfo
[i
].s
= pf
->voice
[i
].main
.s
;
3530 vinfo
[i
].panning
= pf
->voice
[i
].main
.panning
;
3531 vinfo
[i
].volume
= pf
->voice
[i
].main
.chanvol
;
3532 vinfo
[i
].period
= pf
->voice
[i
].main
.period
;
3533 vinfo
[i
].kick
= pf
->voice
[i
].main
.kick_flag
;
3534 pf
->voice
[i
].main
.kick_flag
= 0;
3542 // Get current module order
3543 MIKMODAPI
int Player_GetOrder(void)
3547 ret
= pf
? pf
->sngpos
:0; // pf->positions[pf->sngpos ? pf->sngpos-1 : 0]: 0;
3552 // Get current module row
3553 MIKMODAPI
int Player_GetRow(void)
3557 ret
= pf
? pf
->patpos
: 0;