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
)
552 if (!dat
&& (flags
& UF_ARPMEM
))
558 DoArpeggio(tick
, flags
, a
, 0);
563 static int DoPTEffect1(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
569 a
->slidespeed
= (UWORD
)dat
<< 2;
572 a
->tmpperiod
-= a
->slidespeed
;
577 static int DoPTEffect2(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
583 a
->slidespeed
= (UWORD
)dat
<< 2;
586 a
->tmpperiod
+= a
->slidespeed
;
591 static void DoToneSlide(UWORD tick
, MP_CONTROL
*a
)
593 if (!a
->main
.fadevol
)
594 a
->main
.kick
= (a
->main
.kick
== KICK_NOTE
)? KICK_NOTE
: KICK_KEYOFF
;
596 a
->main
.kick
= (a
->main
.kick
== KICK_NOTE
)? KICK_ENV
: KICK_ABSENT
;
601 /* We have to slide a->main.period towards a->wantedperiod, so compute
602 the difference between those two values */
603 dist
=a
->main
.period
-a
->wantedperiod
;
605 /* if they are equal or if portamentospeed is too big ...*/
606 if (dist
== 0 || a
->portspeed
> abs(dist
))
607 /* ...make tmpperiod equal tperiod */
608 a
->tmpperiod
=a
->main
.period
=a
->wantedperiod
;
610 a
->tmpperiod
-=a
->portspeed
;
611 a
->main
.period
-=a
->portspeed
; /* dist>0, slide up */
613 a
->tmpperiod
+=a
->portspeed
;
614 a
->main
.period
+=a
->portspeed
; /* dist<0, slide down */
617 a
->tmpperiod
=a
->main
.period
;
621 static int DoPTEffect3(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
626 if ((!tick
)&&(dat
)) a
->portspeed
=(UWORD
)dat
<<2;
628 DoToneSlide(tick
, a
);
633 static void DoVibrato(UWORD tick
, MP_CONTROL
*a
)
636 UWORD temp
= 0; /* silence warning */
641 q
=(a
->vibpos
>>2)&0x1f;
643 switch (a
->wavecontrol
&3) {
645 temp
=VibratoTable
[q
];
647 case 1: /* ramp down */
649 if (a
->vibpos
<0) q
=255-q
;
652 case 2: /* square wave */
655 case 3: /* random wave */
664 a
->main
.period
=a
->tmpperiod
+temp
;
666 a
->main
.period
=a
->tmpperiod
-temp
;
670 a
->vibpos
+=a
->vibspd
;
673 static int DoPTEffect4(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
679 if (dat
&0x0f) a
->vibdepth
=dat
&0xf;
680 if (dat
&0xf0) a
->vibspd
=(dat
&0xf0)>>2;
688 static void DoVolSlide(MP_CONTROL
*a
, UBYTE dat
)
691 a
->tmpvolume
-=(dat
&0x0f);
695 a
->tmpvolume
+=(dat
>>4);
701 static int DoPTEffect5(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
707 DoToneSlide(tick
, a
);
715 /* DoPTEffect6 after DoPTEffectA */
717 static int DoPTEffect7(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
721 UWORD temp
= 0; /* silence warning */
725 if (dat
&0x0f) a
->trmdepth
=dat
&0xf;
726 if (dat
&0xf0) a
->trmspd
=(dat
&0xf0)>>2;
728 if (a
->main
.period
) {
729 q
=(a
->trmpos
>>2)&0x1f;
731 switch ((a
->wavecontrol
>>4)&3) {
733 temp
=VibratoTable
[q
];
735 case 1: /* ramp down */
737 if (a
->trmpos
<0) q
=255-q
;
740 case 2: /* square wave */
743 case 3: /* random wave */
751 a
->volume
=a
->tmpvolume
+temp
;
752 if (a
->volume
>64) a
->volume
=64;
754 a
->volume
=a
->tmpvolume
-temp
;
755 if (a
->volume
<0) a
->volume
=0;
760 a
->trmpos
+=a
->trmspd
;
766 static int DoPTEffect8(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
772 a
->main
.panning
= mod
->panning
[channel
] = dat
;
777 static int DoPTEffect9(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
783 if (dat
) a
->soffset
=(UWORD
)dat
<<8;
784 a
->main
.start
=a
->hioffset
|a
->soffset
;
786 if ((a
->main
.s
)&&(a
->main
.start
>a
->main
.s
->length
))
787 a
->main
.start
=a
->main
.s
->flags
&(SF_LOOP
|SF_BIDI
)?
788 a
->main
.s
->loopstart
:a
->main
.s
->length
;
794 static int DoPTEffectA(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
805 static int DoPTEffect6(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
809 DoPTEffectA(tick
, flags
, a
, mod
, channel
);
814 static int DoPTEffectB(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
820 if (tick
|| mod
->patdly2
)
823 /* Vincent Voois uses a nasty trick in "Universal Bolero" */
824 if (dat
== mod
->sngpos
&& mod
->patbrk
== mod
->patpos
)
827 if (!mod
->loop
&& !mod
->patbrk
&&
828 (dat
< mod
->sngpos
||
829 (mod
->sngpos
== (mod
->numpos
- 1) && !mod
->patbrk
) ||
830 (dat
== mod
->sngpos
&& (flags
& UF_NOWRAP
))
832 /* if we don't loop, better not to skip the end of the
833 pattern, after all... so:
837 /* if we were fading, adjust... */
838 if (mod
->sngpos
== (mod
->numpos
-1))
839 mod
->volume
=mod
->initvolume
>128?128:mod
->initvolume
;
848 static int DoPTEffectC(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
854 if (dat
==(UBYTE
)-1) a
->anote
=dat
=0; /* note cut */
855 else if (dat
>64) dat
=64;
861 static int DoPTEffectD(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
866 if ((tick
)||(mod
->patdly2
)) return 0;
867 if ((mod
->positions
[mod
->sngpos
]!=LAST_PATTERN
)&&
868 (dat
>mod
->pattrows
[mod
->positions
[mod
->sngpos
]]))
869 dat
=mod
->pattrows
[mod
->positions
[mod
->sngpos
]];
872 /* don't ask me to explain this code - it makes
873 backwards.s3m and children.xm (heretic's version) play
874 correctly, among others. Take that for granted, or write
875 the page of comments yourself... you might need some
877 if ((mod
->sngpos
==mod
->numpos
-1)&&(dat
)&&((mod
->loop
)||
878 (mod
->positions
[mod
->sngpos
]==(mod
->numpat
-1)
879 && !(flags
&UF_NOWRAP
)))) {
889 static void DoEEffects(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
,
890 SWORD channel
, UBYTE dat
)
892 UBYTE nib
= dat
& 0xf;
895 case 0x0: /* hardware filter toggle, not supported */
897 case 0x1: /* fineslide up */
900 a
->tmpperiod
-=(nib
<<2);
902 case 0x2: /* fineslide dn */
905 a
->tmpperiod
+=(nib
<<2);
907 case 0x3: /* glissando ctrl */
910 case 0x4: /* set vibrato waveform */
911 a
->wavecontrol
&=0xf0;
914 case 0x5: /* set finetune */
915 if (a
->main
.period
) {
916 if (flags
&UF_XMPERIODS
)
919 a
->speed
=finetune
[nib
];
920 a
->tmpperiod
=GetPeriod(flags
, (UWORD
)a
->main
.note
<<1,a
->speed
);
923 case 0x6: /* set patternloop */
926 if (nib
) { /* set reppos or repcnt ? */
927 /* set repcnt, so check if repcnt already is set, which means we
928 are already looping */
930 a
->pat_repcnt
--; /* already looping, decrease counter */
933 /* this would make walker.xm, shipped with Xsoundtracker,
934 play correctly, but it's better to remain compatible
936 if ((!(flags
&UF_NOWRAP
))||(a
->pat_reppos
!=POS_NONE
))
938 a
->pat_repcnt
=nib
; /* not yet looping, so set repcnt */
941 if (a
->pat_repcnt
) { /* jump to reppos if repcnt>0 */
942 if (a
->pat_reppos
==POS_NONE
)
943 a
->pat_reppos
=mod
->patpos
-1;
944 if (a
->pat_reppos
==-1) {
948 mod
->patpos
=a
->pat_reppos
;
949 } else a
->pat_reppos
=POS_NONE
;
951 a
->pat_reppos
=mod
->patpos
-1; /* set reppos - can be (-1) */
953 case 0x7: /* set tremolo waveform */
954 a
->wavecontrol
&=0x0f;
955 a
->wavecontrol
|=nib
<<4;
957 case 0x8: /* set panning */
961 a
->main
.panning
=mod
->panning
[channel
]=nib
;
964 case 0x9: /* retrig note */
965 /* do not retrigger on tick 0, until we are emulating FT2 and effect
967 if (!tick
&& !((flags
& UF_FT2QUIRKS
) && (!nib
)))
969 /* only retrigger if data nibble > 0, or if tick 0 (FT2 compat) */
972 /* when retrig counter reaches 0, reset counter and restart
974 if (a
->main
.period
) a
->main
.kick
=KICK_NOTE
;
977 a
->retrig
--; /* countdown */
980 case 0xa: /* fine volume slide up */
984 if (a
->tmpvolume
>64) a
->tmpvolume
=64;
986 case 0xb: /* fine volume slide dn */
990 if (a
->tmpvolume
<0)a
->tmpvolume
=0;
992 case 0xc: /* cut note */
993 /* When tick reaches the cut-note value, turn the volume to
994 zero (just like on the amiga) */
996 a
->tmpvolume
=0; /* just turn the volume down */
998 case 0xd: /* note delay */
999 /* delay the start of the sample until tick==nib */
1001 a
->main
.notedelay
=nib
;
1002 else if (a
->main
.notedelay
)
1003 a
->main
.notedelay
--;
1005 case 0xe: /* pattern delay */
1008 mod
->patdly
=nib
+1; /* only once, when tick=0 */
1010 case 0xf: /* invert loop, not supported */
1015 static int DoPTEffectE(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1017 DoEEffects(tick
, flags
, a
, mod
, channel
, UniGetByte());
1022 static int DoPTEffectF(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1027 if (tick
||mod
->patdly2
) return 0;
1028 if (mod
->extspd
&&(dat
>=mod
->bpmlimit
))
1032 mod
->sngspd
=(dat
>=mod
->bpmlimit
)?mod
->bpmlimit
-1:dat
;
1039 /*========== Scream Tracker effects */
1041 static int DoS3MEffectA(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1045 speed
= UniGetByte();
1047 if (tick
|| mod
->patdly2
)
1053 mod
->sngspd
= speed
;
1060 static void DoS3MVolSlide(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, UBYTE inf
)
1073 if ((tick
)||(flags
&UF_S3MSLIDES
)) a
->tmpvolume
+=hi
;
1076 if ((tick
)||(flags
&UF_S3MSLIDES
)) a
->tmpvolume
-=lo
;
1079 if (!tick
) a
->tmpvolume
+=(hi
?hi
:0xf);
1082 if (!tick
) a
->tmpvolume
-=(lo
?lo
:0xf);
1088 else if (a
->tmpvolume
>64)
1092 static int DoS3MEffectD(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1094 DoS3MVolSlide(tick
, flags
, a
, UniGetByte());
1099 static void DoS3MSlideDn(UWORD tick
, MP_CONTROL
*a
, UBYTE inf
)
1112 if (!tick
) a
->tmpperiod
+=(UWORD
)lo
<<2;
1115 if (!tick
) a
->tmpperiod
+=lo
;
1117 if (tick
) a
->tmpperiod
+=(UWORD
)inf
<<2;
1121 static int DoS3MEffectE(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1127 DoS3MSlideDn(tick
, a
,dat
);
1132 static void DoS3MSlideUp(UWORD tick
, MP_CONTROL
*a
, UBYTE inf
)
1136 if (inf
) a
->slidespeed
=inf
;
1137 else inf
=a
->slidespeed
;
1143 if (!tick
) a
->tmpperiod
-=(UWORD
)lo
<<2;
1146 if (!tick
) a
->tmpperiod
-=lo
;
1148 if (tick
) a
->tmpperiod
-=(UWORD
)inf
<<2;
1152 static int DoS3MEffectF(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1158 DoS3MSlideUp(tick
, a
,dat
);
1163 static int DoS3MEffectI(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1181 a
->s3mtremor
%=(on
+off
);
1182 a
->volume
=(a
->s3mtremor
<on
)?a
->tmpvolume
:0;
1189 static int DoS3MEffectQ(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1194 if (a
->main
.period
) {
1196 a
->s3mrtgslide
=inf
>>4;
1197 a
->s3mrtgspeed
=inf
&0xf;
1200 /* only retrigger if low nibble > 0 */
1201 if (a
->s3mrtgspeed
>0) {
1203 /* when retrig counter reaches 0, reset counter and restart the
1205 if (a
->main
.kick
!=KICK_NOTE
) a
->main
.kick
=KICK_KEYOFF
;
1206 a
->retrig
=a
->s3mrtgspeed
;
1208 if ((tick
)||(flags
&UF_S3MSLIDES
)) {
1209 switch (a
->s3mrtgslide
) {
1215 a
->tmpvolume
-=(1<<(a
->s3mrtgslide
-1));
1218 a
->tmpvolume
=(2*a
->tmpvolume
)/3;
1228 a
->tmpvolume
+=(1<<(a
->s3mrtgslide
-9));
1231 a
->tmpvolume
=(3*a
->tmpvolume
)>>1;
1234 a
->tmpvolume
=a
->tmpvolume
<<1;
1239 else if (a
->tmpvolume
>64)
1243 a
->retrig
--; /* countdown */
1250 static int DoS3MEffectR(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1253 UWORD temp
=0; /* silence warning */
1257 if (dat
&0x0f) a
->trmdepth
=dat
&0xf;
1258 if (dat
&0xf0) a
->trmspd
=(dat
&0xf0)>>2;
1261 q
=(a
->trmpos
>>2)&0x1f;
1263 switch ((a
->wavecontrol
>>4)&3) {
1265 temp
=VibratoTable
[q
];
1267 case 1: /* ramp down */
1269 if (a
->trmpos
<0) q
=255-q
;
1272 case 2: /* square wave */
1275 case 3: /* random */
1276 temp
=getrandom(256);
1284 a
->volume
=a
->tmpvolume
+temp
;
1285 if (a
->volume
>64) a
->volume
=64;
1287 a
->volume
=a
->tmpvolume
-temp
;
1288 if (a
->volume
<0) a
->volume
=0;
1293 a
->trmpos
+=a
->trmspd
;
1298 static int DoS3MEffectT(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1302 tempo
= UniGetByte();
1304 if (tick
|| mod
->patdly2
)
1307 mod
->bpm
= (tempo
< 32) ? 32 : tempo
;
1312 static int DoS3MEffectU(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1315 UWORD temp
= 0; /* silence warning */
1319 if (dat
&0x0f) a
->vibdepth
=dat
&0xf;
1320 if (dat
&0xf0) a
->vibspd
=(dat
&0xf0)>>2;
1322 if (a
->main
.period
) {
1323 q
=(a
->vibpos
>>2)&0x1f;
1325 switch (a
->wavecontrol
&3) {
1327 temp
=VibratoTable
[q
];
1329 case 1: /* ramp down */
1331 if (a
->vibpos
<0) q
=255-q
;
1334 case 2: /* square wave */
1337 case 3: /* random */
1338 temp
=getrandom(256);
1346 a
->main
.period
=a
->tmpperiod
+temp
;
1348 a
->main
.period
=a
->tmpperiod
-temp
;
1351 a
->vibpos
+=a
->vibspd
;
1357 /*========== Envelope helpers */
1359 static int DoKeyOff(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1361 a
->main
.keyoff
|=KEY_OFF
;
1362 if ((!(a
->main
.volflg
&EF_ON
))||(a
->main
.volflg
&EF_LOOP
))
1363 a
->main
.keyoff
=KEY_KILL
;
1368 static int DoKeyFade(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1373 if ((tick
>=dat
)||(tick
==mod
->sngspd
-1)) {
1374 a
->main
.keyoff
=KEY_KILL
;
1375 if (!(a
->main
.volflg
&EF_ON
))
1382 /*========== Fast Tracker effects */
1384 /* DoXMEffect6 after DoXMEffectA */
1386 static int DoXMEffectA(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1392 a
->s3mvolslide
= inf
;
1394 inf
= a
->s3mvolslide
;
1402 if (a
->tmpvolume
<0) a
->tmpvolume
=0;
1405 if (a
->tmpvolume
>64) a
->tmpvolume
=64;
1412 static int DoXMEffect6(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1417 return DoXMEffectA(tick
, flags
, a
, mod
, channel
);
1420 static int DoXMEffectE1(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1426 if (dat
) a
->fportupspd
=dat
;
1428 a
->tmpperiod
-=(a
->fportupspd
<<2);
1434 static int DoXMEffectE2(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1440 if (dat
) a
->fportdnspd
=dat
;
1442 a
->tmpperiod
+=(a
->fportdnspd
<<2);
1448 static int DoXMEffectEA(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1454 if (dat
) a
->fslideupspd
=dat
;
1455 a
->tmpvolume
+=a
->fslideupspd
;
1456 if (a
->tmpvolume
>64) a
->tmpvolume
=64;
1461 static int DoXMEffectEB(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1467 if (dat
) a
->fslidednspd
=dat
;
1468 a
->tmpvolume
-=a
->fslidednspd
;
1469 if (a
->tmpvolume
<0) a
->tmpvolume
=0;
1474 static int DoXMEffectG(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1476 mod
->volume
=UniGetByte()<<1;
1477 if (mod
->volume
>128) mod
->volume
=128;
1482 static int DoXMEffectH(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1489 if (inf
) mod
->globalslide
=inf
;
1490 else inf
=mod
->globalslide
;
1491 if (inf
& 0xf0) inf
&=0xf0;
1492 mod
->volume
=mod
->volume
+((inf
>>4)-(inf
&0xf))*2;
1496 else if (mod
->volume
>128)
1503 static int DoXMEffectL(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1508 if ((!tick
)&&(a
->main
.i
)) {
1510 INSTRUMENT
*i
=a
->main
.i
;
1513 if ((aout
=a
->slave
)) {
1514 if (aout
->venv
.env
) {
1515 points
=i
->volenv
[i
->volpts
-1].pos
;
1516 aout
->venv
.p
=aout
->venv
.env
[(dat
>points
)?points
:dat
].pos
;
1518 if (aout
->penv
.env
) {
1519 points
=i
->panenv
[i
->panpts
-1].pos
;
1520 aout
->penv
.p
=aout
->penv
.env
[(dat
>points
)?points
:dat
].pos
;
1528 static int DoXMEffectP(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1546 /* slide right has absolute priority */
1550 pan
=((a
->main
.panning
==PAN_SURROUND
)?PAN_CENTER
:a
->main
.panning
)+hi
-lo
;
1551 a
->main
.panning
=(pan
<PAN_LEFT
)?PAN_LEFT
:(pan
>PAN_RIGHT
?PAN_RIGHT
:pan
);
1557 static int DoXMEffectX1(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1563 a
->ffportupspd
= dat
;
1565 dat
= a
->ffportupspd
;
1569 a
->main
.period
-=dat
;
1577 static int DoXMEffectX2(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1585 dat
= a
->ffportdnspd
;
1589 a
->main
.period
+=dat
;
1597 /*========== Impulse Tracker effects */
1599 static void DoITToneSlide(UWORD tick
, MP_CONTROL
*a
, UBYTE dat
)
1604 /* if we don't come from another note, ignore the slide and play the note
1606 if (!a
->oldnote
|| !a
->main
.period
)
1609 if ((!tick
)&&(a
->newsamp
)){
1610 a
->main
.kick
=KICK_NOTE
;
1613 a
->main
.kick
=(a
->main
.kick
==KICK_NOTE
)?KICK_ENV
:KICK_ABSENT
;
1618 /* We have to slide a->main.period towards a->wantedperiod, compute the
1619 difference between those two values */
1620 dist
=a
->main
.period
-a
->wantedperiod
;
1622 /* if they are equal or if portamentospeed is too big... */
1623 if ((!dist
)||((a
->portspeed
<<2)>abs(dist
)))
1624 /* ... make tmpperiod equal tperiod */
1625 a
->tmpperiod
=a
->main
.period
=a
->wantedperiod
;
1628 a
->tmpperiod
-=a
->portspeed
<<2;
1629 a
->main
.period
-=a
->portspeed
<<2; /* dist>0 slide up */
1631 a
->tmpperiod
+=a
->portspeed
<<2;
1632 a
->main
.period
+=a
->portspeed
<<2; /* dist<0 slide down */
1635 a
->tmpperiod
=a
->main
.period
;
1639 static int DoITEffectG(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1641 DoITToneSlide(tick
, a
, UniGetByte());
1646 static void DoITVibrato(UWORD tick
, MP_CONTROL
*a
, UBYTE dat
)
1652 if (dat
&0x0f) a
->vibdepth
=dat
&0xf;
1653 if (dat
&0xf0) a
->vibspd
=(dat
&0xf0)>>2;
1655 if (!a
->main
.period
)
1658 q
=(a
->vibpos
>>2)&0x1f;
1660 switch (a
->wavecontrol
&3) {
1662 temp
=VibratoTable
[q
];
1664 case 1: /* square wave */
1667 case 2: /* ramp down */
1669 if (a
->vibpos
<0) q
=255-q
;
1672 case 3: /* random */
1673 temp
=getrandom(256);
1682 a
->main
.period
=a
->tmpperiod
+temp
;
1684 a
->main
.period
=a
->tmpperiod
-temp
;
1687 a
->vibpos
+=a
->vibspd
;
1690 static int DoITEffectH(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1692 DoITVibrato(tick
, a
, UniGetByte());
1697 static int DoITEffectI(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1713 a
->s3mtremor
%=(on
+off
);
1714 a
->volume
=(a
->s3mtremor
<on
)?a
->tmpvolume
:0;
1721 static int DoITEffectM(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1723 a
->main
.chanvol
=UniGetByte();
1724 if (a
->main
.chanvol
>64)
1726 else if (a
->main
.chanvol
<0)
1732 static int DoITEffectN(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1739 a
->chanvolslide
= inf
;
1741 inf
= a
->chanvolslide
;
1747 a
->main
.chanvol
-=lo
;
1750 a
->main
.chanvol
+=hi
;
1753 if (!tick
) a
->main
.chanvol
-=lo
;
1756 if (!tick
) a
->main
.chanvol
+=hi
;
1759 if (a
->main
.chanvol
<0)
1761 else if (a
->main
.chanvol
>64)
1767 static int DoITEffectP(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1784 pan
=(a
->main
.panning
==PAN_SURROUND
)?PAN_CENTER
:a
->main
.panning
;
1793 if (!tick
) pan
+=lo
<<2;
1796 if (!tick
) pan
-=hi
<<2;
1799 (pan
<PAN_LEFT
)?PAN_LEFT
:(pan
>PAN_RIGHT
?PAN_RIGHT
:pan
);
1804 static int DoITEffectT(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1809 tempo
= UniGetByte();
1816 temp
+= (tempo
& 0x0f);
1820 mod
->bpm
=(temp
>255)?255:(temp
<1?1:temp
);
1825 static int DoITEffectU(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1828 UWORD temp
= 0; /* silence warning */
1832 if (dat
&0x0f) a
->vibdepth
=dat
&0xf;
1833 if (dat
&0xf0) a
->vibspd
=(dat
&0xf0)>>2;
1835 if (a
->main
.period
) {
1836 q
=(a
->vibpos
>>2)&0x1f;
1838 switch (a
->wavecontrol
&3) {
1840 temp
=VibratoTable
[q
];
1842 case 1: /* square wave */
1845 case 2: /* ramp down */
1847 if (a
->vibpos
<0) q
=255-q
;
1850 case 3: /* random */
1851 temp
=getrandom(256);
1859 a
->main
.period
=a
->tmpperiod
+temp
;
1861 a
->main
.period
=a
->tmpperiod
-temp
;
1864 a
->vibpos
+=a
->vibspd
;
1870 static int DoITEffectW(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1877 mod
->globalslide
= inf
;
1879 inf
= mod
->globalslide
;
1885 if (tick
) mod
->volume
+=hi
;
1888 if (tick
) mod
->volume
-=lo
;
1891 if (!tick
) mod
->volume
+=hi
;
1894 if (!tick
) mod
->volume
-=lo
;
1899 else if (mod
->volume
>128)
1905 static int DoITEffectY(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1908 SLONG temp
= 0; /* silence warning */
1913 if (dat
&0x0f) a
->panbdepth
=(dat
&0xf);
1914 if (dat
&0xf0) a
->panbspd
=(dat
&0xf0)>>4;
1919 switch (a
->panbwave
) {
1921 temp
=PanbrelloTable
[q
];
1923 case 1: /* square wave */
1926 case 2: /* ramp down */
1930 case 3: /* random */
1931 temp
=getrandom(256);
1936 temp
=(temp
/8)+mod
->panning
[channel
];
1939 (temp
<PAN_LEFT
)?PAN_LEFT
:(temp
>PAN_RIGHT
?PAN_RIGHT
:temp
);
1940 a
->panbpos
+=a
->panbspd
;
1947 static void DoNNAEffects(MODULE
*, MP_CONTROL
*, UBYTE
);
1949 /* Impulse/Scream Tracker Sxx effects.
1950 All Sxx effects share the same memory space. */
1951 static int DoITEffectS0(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
1968 case SS_GLISSANDO
: /* S1x set glissando voice */
1969 DoEEffects(tick
, flags
, a
, mod
, channel
, 0x30|inf
);
1971 case SS_FINETUNE
: /* S2x set finetune */
1972 DoEEffects(tick
, flags
, a
, mod
, channel
, 0x50|inf
);
1974 case SS_VIBWAVE
: /* S3x set vibrato waveform */
1975 DoEEffects(tick
, flags
, a
, mod
, channel
, 0x40|inf
);
1977 case SS_TREMWAVE
: /* S4x set tremolo waveform */
1978 DoEEffects(tick
, flags
, a
, mod
, channel
, 0x70|inf
);
1980 case SS_PANWAVE
: /* S5x panbrello */
1983 case SS_FRAMEDELAY
: /* S6x delay x number of frames (patdly) */
1984 DoEEffects(tick
, flags
, a
, mod
, channel
, 0xe0|inf
);
1986 case SS_S7EFFECTS
: /* S7x instrument / NNA commands */
1987 DoNNAEffects(mod
, a
, inf
);
1989 case SS_PANNING
: /* S8x set panning position */
1990 DoEEffects(tick
, flags
, a
, mod
, channel
, 0x80 | inf
);
1992 case SS_SURROUND
: /* S9x set surround sound */
1994 a
->main
.panning
= mod
->panning
[channel
] = PAN_SURROUND
;
1996 case SS_HIOFFSET
: /* SAy set high order sample offset yxx00h */
1998 a
->hioffset
=inf
<<16;
1999 a
->main
.start
=a
->hioffset
|a
->soffset
;
2001 if ((a
->main
.s
)&&(a
->main
.start
>a
->main
.s
->length
))
2002 a
->main
.start
=a
->main
.s
->flags
&(SF_LOOP
|SF_BIDI
)?
2003 a
->main
.s
->loopstart
:a
->main
.s
->length
;
2006 case SS_PATLOOP
: /* SBx pattern loop */
2007 DoEEffects(tick
, flags
, a
, mod
, channel
, 0x60|inf
);
2009 case SS_NOTECUT
: /* SCx notecut */
2011 DoEEffects(tick
, flags
, a
, mod
, channel
, 0xC0|inf
);
2013 case SS_NOTEDELAY
: /* SDx notedelay */
2014 DoEEffects(tick
, flags
, a
, mod
, channel
, 0xD0|inf
);
2016 case SS_PATDELAY
: /* SEx patterndelay */
2017 DoEEffects(tick
, flags
, a
, mod
, channel
, 0xE0|inf
);
2024 /*========== Impulse Tracker Volume/Pan Column effects */
2027 * All volume/pan column effects share the same memory space.
2030 static int DoVolEffects(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
2054 a
->main
.panning
=inf
;
2057 DoS3MVolSlide(tick
, flags
, a
, inf
);
2059 case VOL_PITCHSLIDEDN
:
2061 DoS3MSlideDn(tick
, a
, inf
);
2063 case VOL_PITCHSLIDEUP
:
2065 DoS3MSlideUp(tick
, a
, inf
);
2067 case VOL_PORTAMENTO
:
2068 DoITToneSlide(tick
, a
, inf
);
2071 DoITVibrato(tick
, a
, inf
);
2078 /*========== UltraTracker effects */
2080 static int DoULTEffect9(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
2082 UWORD offset
=UniGetWord();
2085 a
->ultoffset
=offset
;
2087 a
->main
.start
=a
->ultoffset
<<2;
2088 if ((a
->main
.s
)&&(a
->main
.start
>a
->main
.s
->length
))
2089 a
->main
.start
=a
->main
.s
->flags
&(SF_LOOP
|SF_BIDI
)?
2090 a
->main
.s
->loopstart
:a
->main
.s
->length
;
2095 /*========== OctaMED effects */
2097 static int DoMEDSpeed(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
2099 UWORD speed
=UniGetWord();
2106 static int DoMEDEffectF1(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
2108 DoEEffects(tick
, flags
, a
, mod
, channel
, 0x90|(mod
->sngspd
/2));
2113 static int DoMEDEffectF2(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
2115 DoEEffects(tick
, flags
, a
, mod
, channel
, 0xd0|(mod
->sngspd
/2));
2120 static int DoMEDEffectF3(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
2122 DoEEffects(tick
, flags
, a
, mod
, channel
, 0x90|(mod
->sngspd
/3));
2127 /*========== Oktalyzer effects */
2129 static int DoOktArp(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
2133 dat2
= UniGetByte(); /* arpeggio style */
2136 if (!dat
&& (flags
& UF_ARPMEM
))
2142 DoArpeggio(tick
, flags
, a
, dat2
);
2147 /*========== General player functions */
2149 static int DoNothing(UWORD tick
, UWORD flags
, MP_CONTROL
*a
, MODULE
*mod
, SWORD channel
)
2156 typedef int (*effect_func
) (UWORD
, UWORD
, MP_CONTROL
*, MODULE
*, SWORD
);
2158 static effect_func effects
[UNI_LAST
] = {
2160 DoNothing
, /* UNI_NOTE */
2161 DoNothing
, /* UNI_INSTRUMENT */
2162 DoPTEffect0
, /* UNI_PTEFFECT0 */
2163 DoPTEffect1
, /* UNI_PTEFFECT1 */
2164 DoPTEffect2
, /* UNI_PTEFFECT2 */
2165 DoPTEffect3
, /* UNI_PTEFFECT3 */
2166 DoPTEffect4
, /* UNI_PTEFFECT4 */
2167 DoPTEffect5
, /* UNI_PTEFFECT5 */
2168 DoPTEffect6
, /* UNI_PTEFFECT6 */
2169 DoPTEffect7
, /* UNI_PTEFFECT7 */
2170 DoPTEffect8
, /* UNI_PTEFFECT8 */
2171 DoPTEffect9
, /* UNI_PTEFFECT9 */
2172 DoPTEffectA
, /* UNI_PTEFFECTA */
2173 DoPTEffectB
, /* UNI_PTEFFECTB */
2174 DoPTEffectC
, /* UNI_PTEFFECTC */
2175 DoPTEffectD
, /* UNI_PTEFFECTD */
2176 DoPTEffectE
, /* UNI_PTEFFECTE */
2177 DoPTEffectF
, /* UNI_PTEFFECTF */
2178 DoS3MEffectA
, /* UNI_S3MEFFECTA */
2179 DoS3MEffectD
, /* UNI_S3MEFFECTD */
2180 DoS3MEffectE
, /* UNI_S3MEFFECTE */
2181 DoS3MEffectF
, /* UNI_S3MEFFECTF */
2182 DoS3MEffectI
, /* UNI_S3MEFFECTI */
2183 DoS3MEffectQ
, /* UNI_S3MEFFECTQ */
2184 DoS3MEffectR
, /* UNI_S3MEFFECTR */
2185 DoS3MEffectT
, /* UNI_S3MEFFECTT */
2186 DoS3MEffectU
, /* UNI_S3MEFFECTU */
2187 DoKeyOff
, /* UNI_KEYOFF */
2188 DoKeyFade
, /* UNI_KEYFADE */
2189 DoVolEffects
, /* UNI_VOLEFFECTS */
2190 DoPTEffect4
, /* UNI_XMEFFECT4 */
2191 DoXMEffect6
, /* UNI_XMEFFECT6 */
2192 DoXMEffectA
, /* UNI_XMEFFECTA */
2193 DoXMEffectE1
, /* UNI_XMEFFECTE1 */
2194 DoXMEffectE2
, /* UNI_XMEFFECTE2 */
2195 DoXMEffectEA
, /* UNI_XMEFFECTEA */
2196 DoXMEffectEB
, /* UNI_XMEFFECTEB */
2197 DoXMEffectG
, /* UNI_XMEFFECTG */
2198 DoXMEffectH
, /* UNI_XMEFFECTH */
2199 DoXMEffectL
, /* UNI_XMEFFECTL */
2200 DoXMEffectP
, /* UNI_XMEFFECTP */
2201 DoXMEffectX1
, /* UNI_XMEFFECTX1 */
2202 DoXMEffectX2
, /* UNI_XMEFFECTX2 */
2203 DoITEffectG
, /* UNI_ITEFFECTG */
2204 DoITEffectH
, /* UNI_ITEFFECTH */
2205 DoITEffectI
, /* UNI_ITEFFECTI */
2206 DoITEffectM
, /* UNI_ITEFFECTM */
2207 DoITEffectN
, /* UNI_ITEFFECTN */
2208 DoITEffectP
, /* UNI_ITEFFECTP */
2209 DoITEffectT
, /* UNI_ITEFFECTT */
2210 DoITEffectU
, /* UNI_ITEFFECTU */
2211 DoITEffectW
, /* UNI_ITEFFECTW */
2212 DoITEffectY
, /* UNI_ITEFFECTY */
2213 DoNothing
, /* UNI_ITEFFECTZ */
2214 DoITEffectS0
, /* UNI_ITEFFECTS0 */
2215 DoULTEffect9
, /* UNI_ULTEFFECT9 */
2216 DoMEDSpeed
, /* UNI_MEDSPEED */
2217 DoMEDEffectF1
, /* UNI_MEDEFFECTF1 */
2218 DoMEDEffectF2
, /* UNI_MEDEFFECTF2 */
2219 DoMEDEffectF3
, /* UNI_MEDEFFECTF3 */
2220 DoOktArp
, /* UNI_OKTARP */
2223 static int pt_playeffects(MODULE
*mod
, SWORD channel
, MP_CONTROL
*a
)
2225 UWORD tick
= mod
->vbtick
;
2226 UWORD flags
= mod
->flags
;
2228 int explicitslides
= 0;
2231 while((c
=UniGetByte())) {
2235 explicitslides
|= f(tick
, flags
, a
, mod
, channel
);
2237 return explicitslides
;
2240 static void DoNNAEffects(MODULE
*mod
, MP_CONTROL
*a
, UBYTE dat
)
2246 aout
=(a
->slave
)?a
->slave
:NULL
;
2249 case 0x0: /* past note cut */
2250 for (t
=0;t
<md_sngchn
;t
++)
2251 if (mod
->voice
[t
].master
==a
)
2252 mod
->voice
[t
].main
.fadevol
=0;
2254 case 0x1: /* past note off */
2255 for (t
=0;t
<md_sngchn
;t
++)
2256 if (mod
->voice
[t
].master
==a
) {
2257 mod
->voice
[t
].main
.keyoff
|=KEY_OFF
;
2258 if ((!(mod
->voice
[t
].venv
.flg
& EF_ON
))||
2259 (mod
->voice
[t
].venv
.flg
& EF_LOOP
))
2260 mod
->voice
[t
].main
.keyoff
=KEY_KILL
;
2263 case 0x2: /* past note fade */
2264 for (t
=0;t
<md_sngchn
;t
++)
2265 if (mod
->voice
[t
].master
==a
)
2266 mod
->voice
[t
].main
.keyoff
|=KEY_FADE
;
2268 case 0x3: /* set NNA note cut */
2269 a
->main
.nna
=(a
->main
.nna
&~NNA_MASK
)|NNA_CUT
;
2271 case 0x4: /* set NNA note continue */
2272 a
->main
.nna
=(a
->main
.nna
&~NNA_MASK
)|NNA_CONTINUE
;
2274 case 0x5: /* set NNA note off */
2275 a
->main
.nna
=(a
->main
.nna
&~NNA_MASK
)|NNA_OFF
;
2277 case 0x6: /* set NNA note fade */
2278 a
->main
.nna
=(a
->main
.nna
&~NNA_MASK
)|NNA_FADE
;
2280 case 0x7: /* disable volume envelope */
2282 aout
->main
.volflg
&=~EF_ON
;
2284 case 0x8: /* enable volume envelope */
2286 aout
->main
.volflg
|=EF_ON
;
2288 case 0x9: /* disable panning envelope */
2290 aout
->main
.panflg
&=~EF_ON
;
2292 case 0xa: /* enable panning envelope */
2294 aout
->main
.panflg
|=EF_ON
;
2296 case 0xb: /* disable pitch envelope */
2298 aout
->main
.pitflg
&=~EF_ON
;
2300 case 0xc: /* enable pitch envelope */
2302 aout
->main
.pitflg
|=EF_ON
;
2307 void pt_UpdateVoices(MODULE
*mod
, int max_volume
)
2309 SWORD envpan
,envvol
,envpit
,channel
;
2311 SLONG vibval
,vibdpt
;
2318 mod
->totalchn
=mod
->realchn
=0;
2319 for (channel
=0;channel
<md_sngchn
;channel
++) {
2320 aout
=&mod
->voice
[channel
];
2324 if (!s
|| !s
->length
) continue;
2326 if (aout
->main
.period
<40)
2327 aout
->main
.period
=40;
2328 else if (aout
->main
.period
>50000)
2329 aout
->main
.period
=50000;
2331 if ((aout
->main
.kick
==KICK_NOTE
)||(aout
->main
.kick
==KICK_KEYOFF
)) {
2332 Voice_Play_internal(channel
,s
,(aout
->main
.start
==-1)?
2333 ((s
->flags
&SF_UST_LOOP
)?s
->loopstart
:0):aout
->main
.start
);
2334 aout
->main
.fadevol
=32768;
2339 envpan
= PAN_CENTER
;
2341 if (i
&& ((aout
->main
.kick
==KICK_NOTE
)||(aout
->main
.kick
==KICK_ENV
))) {
2342 if (aout
->main
.volflg
& EF_ON
)
2343 envvol
= StartEnvelope(&aout
->venv
,aout
->main
.volflg
,
2344 i
->volpts
,i
->volsusbeg
,i
->volsusend
,
2345 i
->volbeg
,i
->volend
,i
->volenv
,aout
->main
.keyoff
);
2346 if (aout
->main
.panflg
& EF_ON
)
2347 envpan
= StartEnvelope(&aout
->penv
,aout
->main
.panflg
,
2348 i
->panpts
,i
->pansusbeg
,i
->pansusend
,
2349 i
->panbeg
,i
->panend
,i
->panenv
,aout
->main
.keyoff
);
2350 if (aout
->main
.pitflg
& EF_ON
)
2351 envpit
= StartEnvelope(&aout
->cenv
,aout
->main
.pitflg
,
2352 i
->pitpts
,i
->pitsusbeg
,i
->pitsusend
,
2353 i
->pitbeg
,i
->pitend
,i
->pitenv
,aout
->main
.keyoff
);
2355 if (aout
->cenv
.flg
& EF_ON
)
2356 aout
->masterperiod
=GetPeriod(mod
->flags
,
2357 (UWORD
)aout
->main
.note
<<1, aout
->master
->speed
);
2359 if (aout
->main
.volflg
& EF_ON
)
2360 envvol
= ProcessEnvelope(aout
,&aout
->venv
,256);
2361 if (aout
->main
.panflg
& EF_ON
)
2362 envpan
= ProcessEnvelope(aout
,&aout
->penv
,PAN_CENTER
);
2363 if (aout
->main
.pitflg
& EF_ON
)
2364 envpit
= ProcessEnvelope(aout
,&aout
->cenv
,32);
2366 if (aout
->main
.kick
== KICK_NOTE
) {
2367 aout
->main
.kick_flag
= 1;
2369 aout
->main
.kick
=KICK_ABSENT
;
2371 tmpvol
= aout
->main
.fadevol
; /* max 32768 */
2372 tmpvol
*= aout
->main
.chanvol
; /* * max 64 */
2373 tmpvol
*= aout
->main
.outvolume
; /* * max 256 */
2374 tmpvol
/= (256 * 64); /* tmpvol is max 32768 again */
2375 aout
->totalvol
= tmpvol
>> 2; /* used to determine samplevolume */
2376 tmpvol
*= envvol
; /* * max 256 */
2377 tmpvol
*= mod
->volume
; /* * max 128 */
2378 tmpvol
/= (128 * 256 * 128);
2381 if (mod
->sngpos
>=mod
->numpos
)
2384 tmpvol
=(tmpvol
*max_volume
)/128;
2386 if ((aout
->masterchn
!=-1)&& mod
->control
[aout
->masterchn
].muted
)
2387 Voice_SetVolume_internal(channel
,0);
2389 Voice_SetVolume_internal(channel
,tmpvol
);
2390 if ((tmpvol
)&&(aout
->master
)&&(aout
->master
->slave
==aout
))
2395 if (aout
->main
.panning
==PAN_SURROUND
)
2396 Voice_SetPanning_internal(channel
,PAN_SURROUND
);
2398 if ((mod
->panflag
)&&(aout
->penv
.flg
& EF_ON
))
2399 Voice_SetPanning_internal(channel
,
2400 DoPan(envpan
,aout
->main
.panning
));
2402 Voice_SetPanning_internal(channel
,aout
->main
.panning
);
2404 if (aout
->main
.period
&& s
->vibdepth
)
2405 switch (s
->vibtype
) {
2407 vibval
=avibtab
[s
->avibpos
&127];
2408 if (aout
->avibpos
& 0x80) vibval
=-vibval
;
2412 if (aout
->avibpos
& 0x80) vibval
=-vibval
;
2415 vibval
=63-(((aout
->avibpos
+128)&255)>>1);
2418 vibval
=(((aout
->avibpos
+128)&255)>>1)-64;
2424 if (s
->vibflags
& AV_IT
) {
2425 if ((aout
->aswppos
>>8)<s
->vibdepth
) {
2426 aout
->aswppos
+= s
->vibsweep
;
2427 vibdpt
=aout
->aswppos
;
2429 vibdpt
=s
->vibdepth
<<8;
2430 vibval
=(vibval
*vibdpt
)>>16;
2432 if (!(mod
->flags
&UF_LINEAR
)) vibval
>>=1;
2433 aout
->main
.period
-=vibval
;
2436 /* do XM style auto-vibrato */
2437 if (!(aout
->main
.keyoff
& KEY_OFF
)) {
2438 if (aout
->aswppos
<s
->vibsweep
) {
2439 vibdpt
=(aout
->aswppos
*s
->vibdepth
)/s
->vibsweep
;
2444 /* keyoff -> depth becomes 0 if final depth wasn't reached or
2445 stays at final level if depth WAS reached */
2446 if (aout
->aswppos
>=s
->vibsweep
)
2451 vibval
=(vibval
*vibdpt
)>>8;
2452 aout
->main
.period
-=vibval
;
2455 /* update vibrato position */
2456 aout
->avibpos
=(aout
->avibpos
+s
->vibrate
)&0xff;
2458 /* process pitch envelope */
2459 playperiod
=aout
->main
.period
;
2461 if ((aout
->main
.pitflg
&EF_ON
)&&(envpit
!=32)) {
2465 if ((aout
->main
.note
<<1)+envpit
<=0) envpit
=-(aout
->main
.note
<<1);
2467 p1
=GetPeriod(mod
->flags
, ((UWORD
)aout
->main
.note
<<1)+envpit
,
2468 aout
->master
->speed
)-aout
->masterperiod
;
2470 if ((UWORD
)(playperiod
+p1
)<=playperiod
) {
2472 aout
->main
.keyoff
|=KEY_OFF
;
2475 if ((UWORD
)(playperiod
+p1
)>=playperiod
) {
2477 aout
->main
.keyoff
|=KEY_OFF
;
2483 if (!aout
->main
.fadevol
) { /* check for a dead note (fadevol=0) */
2484 Voice_Stop_internal(channel
);
2486 if ((tmpvol
)&&(aout
->master
)&&(aout
->master
->slave
==aout
))
2489 Voice_SetFrequency_internal(channel
,
2490 getfrequency(mod
->flags
,playperiod
));
2492 /* if keyfade, start substracting fadeoutspeed from fadevol: */
2493 if ((i
)&&(aout
->main
.keyoff
&KEY_FADE
)) {
2494 if (aout
->main
.fadevol
>=i
->volfade
)
2495 aout
->main
.fadevol
-=i
->volfade
;
2497 aout
->main
.fadevol
=0;
2501 md_bpm
=mod
->bpm
+mod
->relspd
;
2504 else if ((!(mod
->flags
&UF_HIGHBPM
)) && md_bpm
>255)
2509 /* Handles new notes or instruments */
2510 void pt_Notes(MODULE
*mod
)
2515 int tr
,funky
; /* funky is set to indicate note or instrument change */
2517 for (channel
=0;channel
<mod
->numchn
;channel
++) {
2518 a
=&mod
->control
[channel
];
2520 if (mod
->sngpos
>=mod
->numpos
) {
2524 tr
=mod
->patterns
[(mod
->positions
[mod
->sngpos
]*mod
->numchn
)+channel
];
2525 mod
->numrow
=mod
->pattrows
[mod
->positions
[mod
->sngpos
]];
2528 a
->row
=(tr
<mod
->numtrk
)?UniFindRow(mod
->tracks
[tr
],mod
->patpos
):NULL
;
2530 if (!mod
->vbtick
) a
->main
.notedelay
=0;
2532 if (!a
->row
) continue;
2536 while((c
=UniGetByte()))
2540 a
->oldnote
=a
->anote
,a
->anote
=UniGetByte();
2541 a
->main
.kick
=KICK_NOTE
;
2545 /* retrig tremolo and vibrato waves ? */
2546 if (!(a
->wavecontrol
& 0x80)) a
->trmpos
=0;
2547 if (!(a
->wavecontrol
& 0x08)) a
->vibpos
=0;
2548 if (!a
->panbwave
) a
->panbpos
=0;
2550 case UNI_INSTRUMENT
:
2552 if (inst
>=mod
->numins
) break; /* safety valve */
2554 a
->main
.i
=(mod
->flags
& UF_INST
)?&mod
->instruments
[inst
]:NULL
;
2558 a
->main
.sample
=inst
;
2569 if ((i
=a
->main
.i
)) {
2570 if (i
->samplenumber
[a
->anote
] >= mod
->numsmp
) continue;
2571 s
=&mod
->samples
[i
->samplenumber
[a
->anote
]];
2572 a
->main
.note
=i
->samplenote
[a
->anote
];
2574 a
->main
.note
=a
->anote
;
2575 s
=&mod
->samples
[a
->main
.sample
];
2580 a
->newsamp
=a
->main
.period
;
2583 /* channel or instrument determined panning ? */
2584 a
->main
.panning
=mod
->panning
[channel
];
2585 if (s
->flags
& SF_OWNPAN
)
2586 a
->main
.panning
=s
->panning
;
2587 else if ((i
)&&(i
->flags
& IF_OWNPAN
))
2588 a
->main
.panning
=i
->panning
;
2590 a
->main
.handle
=s
->handle
;
2594 if ((mod
->panflag
)&&(i
->flags
& IF_PITCHPAN
)
2595 &&(a
->main
.panning
!=PAN_SURROUND
)){
2597 ((a
->anote
-i
->pitpancenter
)*i
->pitpansep
)/8;
2598 if (a
->main
.panning
<PAN_LEFT
)
2599 a
->main
.panning
=PAN_LEFT
;
2600 else if (a
->main
.panning
>PAN_RIGHT
)
2601 a
->main
.panning
=PAN_RIGHT
;
2603 a
->main
.pitflg
=i
->pitflg
;
2604 a
->main
.volflg
=i
->volflg
;
2605 a
->main
.panflg
=i
->panflg
;
2606 a
->main
.nna
=i
->nnatype
;
2610 a
->main
.pitflg
=a
->main
.volflg
=a
->main
.panflg
=0;
2611 a
->main
.nna
=a
->dca
=0;
2615 if (funky
&2) /* instrument change */ {
2616 /* IT random volume variations: 0:8 bit fixed, and one bit for
2618 a
->volume
=a
->tmpvolume
=s
->volume
;
2621 a
->volume
=a
->tmpvolume
=s
->volume
+
2622 ((s
->volume
*((SLONG
)i
->rvolvar
*(SLONG
)getrandom(512)
2625 a
->volume
=a
->tmpvolume
=0;
2626 else if (a
->volume
>64)
2627 a
->volume
=a
->tmpvolume
=64;
2629 if ((mod
->panflag
)&&(a
->main
.panning
!=PAN_SURROUND
)) {
2630 a
->main
.panning
+=((a
->main
.panning
*((SLONG
)i
->rpanvar
*
2631 (SLONG
)getrandom(512)))/25600);
2632 if (a
->main
.panning
<PAN_LEFT
)
2633 a
->main
.panning
=PAN_LEFT
;
2634 else if (a
->main
.panning
>PAN_RIGHT
)
2635 a
->main
.panning
=PAN_RIGHT
;
2640 a
->wantedperiod
=a
->tmpperiod
=
2641 GetPeriod(mod
->flags
, (UWORD
)a
->main
.note
<<1,a
->speed
);
2642 a
->main
.keyoff
=KEY_KICK
;
2647 /* Handles effects */
2648 void pt_EffectsPass1(MODULE
*mod
)
2655 for (channel
=0;channel
<mod
->numchn
;channel
++) {
2656 a
=&mod
->control
[channel
];
2658 if ((aout
=a
->slave
)) {
2659 a
->main
.fadevol
=aout
->main
.fadevol
;
2660 a
->main
.period
=aout
->main
.period
;
2661 if (a
->main
.kick
==KICK_KEYOFF
)
2662 a
->main
.keyoff
=aout
->main
.keyoff
;
2665 if (!a
->row
) continue;
2668 a
->ownper
=a
->ownvol
=0;
2669 explicitslides
= pt_playeffects(mod
, channel
, a
);
2671 /* continue volume slide if necessary for XM and IT */
2672 if (mod
->flags
&UF_BGSLIDES
) {
2673 if (!explicitslides
&& a
->sliding
)
2674 DoS3MVolSlide(mod
->vbtick
, mod
->flags
, a
, 0);
2675 else if (a
->tmpvolume
)
2676 a
->sliding
= explicitslides
;
2680 a
->main
.period
=a
->tmpperiod
;
2682 a
->volume
=a
->tmpvolume
;
2687 (a
->volume
*a
->main
.s
->globvol
*a
->main
.i
->globvol
)>>10;
2689 a
->main
.outvolume
=(a
->volume
*a
->main
.s
->globvol
)>>4;
2690 if (a
->main
.outvolume
>256)
2691 a
->main
.outvolume
=256;
2692 else if (a
->main
.outvolume
<0)
2693 a
->main
.outvolume
=0;
2698 /* NNA management */
2699 void pt_NNA(MODULE
*mod
)
2704 for (channel
=0;channel
<mod
->numchn
;channel
++) {
2705 a
=&mod
->control
[channel
];
2707 if (a
->main
.kick
==KICK_NOTE
) {
2714 if (aout
->main
.nna
& NNA_MASK
) {
2715 /* Make sure the old MP_VOICE channel knows it has no
2718 /* assume the channel is taken by NNA */
2721 switch (aout
->main
.nna
) {
2722 case NNA_CONTINUE
: /* continue note, do nothing */
2724 case NNA_OFF
: /* note off */
2725 aout
->main
.keyoff
|=KEY_OFF
;
2726 if ((!(aout
->main
.volflg
& EF_ON
))||
2727 (aout
->main
.volflg
& EF_LOOP
))
2728 aout
->main
.keyoff
=KEY_KILL
;
2731 aout
->main
.keyoff
|= KEY_FADE
;
2737 if (a
->dct
!=DCT_OFF
) {
2740 for (t
=0;t
<md_sngchn
;t
++)
2741 if ((!Voice_Stopped_internal(t
))&&
2742 (mod
->voice
[t
].masterchn
==channel
)&&
2743 (a
->main
.sample
==mod
->voice
[t
].main
.sample
)) {
2747 if (a
->main
.note
==mod
->voice
[t
].main
.note
)
2751 if (a
->main
.handle
==mod
->voice
[t
].main
.handle
)
2761 mod
->voice
[t
].main
.fadevol
=0;
2764 mod
->voice
[t
].main
.keyoff
|=KEY_OFF
;
2765 if ((!(mod
->voice
[t
].main
.volflg
&EF_ON
))||
2766 (mod
->voice
[t
].main
.volflg
&EF_LOOP
))
2767 mod
->voice
[t
].main
.keyoff
=KEY_KILL
;
2770 mod
->voice
[t
].main
.keyoff
|=KEY_FADE
;
2775 } /* if (a->main.kick==KICK_NOTE) */
2779 /* Setup module and NNA voices */
2780 void pt_SetupVoices(MODULE
*mod
)
2786 for (channel
=0;channel
<mod
->numchn
;channel
++) {
2787 a
=&mod
->control
[channel
];
2789 if (a
->main
.notedelay
) continue;
2790 if (a
->main
.kick
==KICK_NOTE
) {
2791 /* if no channel was cut above, find an empty or quiet channel
2793 if (mod
->flags
&UF_NNA
) {
2797 if ((newchn
=MP_FindEmptyChannel(mod
))!=-1)
2798 a
->slave
=&mod
->voice
[a
->slavechn
=newchn
];
2801 a
->slave
=&mod
->voice
[a
->slavechn
=channel
];
2803 /* assign parts of MP_VOICE only done for a KICK_NOTE */
2804 if ((aout
=a
->slave
)) {
2805 if (aout
->mflag
&& aout
->master
) aout
->master
->slave
=NULL
;
2808 aout
->masterchn
=channel
;
2816 a
->main
.kick
=KICK_ABSENT
;
2820 /* second effect pass */
2821 void pt_EffectsPass2(MODULE
*mod
)
2827 for (channel
=0;channel
<mod
->numchn
;channel
++) {
2828 a
=&mod
->control
[channel
];
2830 if (!a
->row
) continue;
2833 while((c
=UniGetByte()))
2834 if (c
==UNI_ITEFFECTS0
) {
2836 if ((c
>>4)==SS_S7EFFECTS
)
2837 DoNNAEffects(mod
, a
, c
&0xf);
2843 void Player_HandleTick(void)
2849 /* don't handle the very first ticks, this allows the other hardware to
2850 settle down so we don't loose any starting notes */
2857 if ((!pf
)||(pf
->forbid
)||(pf
->sngpos
>=pf
->numpos
)) return;
2859 /* update time counter (sngtime is in milliseconds (in fact 2^-10)) */
2860 pf
->sngremainder
+=(1<<9)*5; /* thus 2.5*(1<<10), since fps=0.4xtempo */
2861 pf
->sngtime
+=pf
->sngremainder
/pf
->bpm
;
2862 pf
->sngremainder
%=pf
->bpm
;
2864 if (++pf
->vbtick
>=pf
->sngspd
) {
2865 if (pf
->pat_repcrazy
)
2866 pf
->pat_repcrazy
=0; /* play 2 times row 0 */
2871 /* process pattern-delay. pf->patdly2 is the counter and pf->patdly is
2872 the command memory. */
2874 pf
->patdly2
=pf
->patdly
,pf
->patdly
=0;
2876 /* patterndelay active */
2878 /* so turn back pf->patpos by 1 */
2879 if (pf
->patpos
) pf
->patpos
--;
2882 /* do we have to get a new patternpointer ? (when pf->patpos reaches the
2883 pattern size, or when a patternbreak is active) */
2884 if (((pf
->patpos
>=pf
->numrow
)&&(pf
->numrow
>0))&&(!pf
->posjmp
))
2888 pf
->patpos
=pf
->numrow
?(pf
->patbrk
%pf
->numrow
):0;
2890 pf
->sngpos
+=(pf
->posjmp
-2);
2891 for (channel
=0;channel
<pf
->numchn
;channel
++)
2892 pf
->control
[channel
].pat_reppos
=-1;
2894 pf
->patbrk
=pf
->posjmp
=0;
2895 /* handle the "---" (end of song) pattern since it can occur
2896 *inside* the module in some formats */
2897 if ((pf
->sngpos
>=pf
->numpos
)||
2898 (pf
->positions
[pf
->sngpos
]==LAST_PATTERN
)) {
2899 if (!pf
->wrap
) return;
2900 if (!(pf
->sngpos
=pf
->reppos
)) {
2901 pf
->volume
=pf
->initvolume
>128?128:pf
->initvolume
;
2902 if(pf
->initspeed
!=0)
2903 pf
->sngspd
=pf
->initspeed
<32?pf
->initspeed
:32;
2906 pf
->bpm
=pf
->inittempo
<32?32:pf
->inittempo
;
2909 if (pf
->sngpos
<0) pf
->sngpos
=pf
->numpos
-1;
2916 /* Fade global volume if enabled and we're playing the last pattern */
2917 if (((pf
->sngpos
==pf
->numpos
-1)||
2918 (pf
->positions
[pf
->sngpos
+1]==LAST_PATTERN
))&&
2920 max_volume
=pf
->numrow
?((pf
->numrow
-pf
->patpos
)*128)/pf
->numrow
:0;
2924 pt_EffectsPass1(pf
);
2925 if (pf
->flags
&UF_NNA
)
2928 pt_EffectsPass2(pf
);
2930 /* now set up the actual hardware channel playback information */
2931 pt_UpdateVoices(pf
, max_volume
);
2934 static void Player_Init_internal(MODULE
* mod
)
2938 for (t
=0;t
<mod
->numchn
;t
++) {
2939 mod
->control
[t
].main
.chanvol
=mod
->chanvol
[t
];
2940 mod
->control
[t
].main
.panning
=mod
->panning
[t
];
2944 mod
->sngremainder
=0;
2946 mod
->pat_repcrazy
=0;
2948 if(mod
->initspeed
!=0)
2949 mod
->sngspd
=mod
->initspeed
<32?mod
->initspeed
:32;
2952 mod
->volume
=mod
->initvolume
>128?128:mod
->initvolume
;
2954 mod
->vbtick
=mod
->sngspd
;
2957 mod
->bpm
=mod
->inittempo
<32?32:mod
->inittempo
;
2961 mod
->posjmp
=2; /* make sure the player fetches the first note */
2966 int Player_Init(MODULE
* mod
)
2976 /* make sure the player doesn't start with garbage */
2977 if (!(mod
->control
=(MP_CONTROL
*)MikMod_calloc(mod
->numchn
,sizeof(MP_CONTROL
))))
2979 if (!(mod
->voice
=(MP_VOICE
*)MikMod_calloc(md_sngchn
,sizeof(MP_VOICE
))))
2982 Player_Init_internal(mod
);
2986 void Player_Exit_internal(MODULE
* mod
)
2991 /* Stop playback if necessary */
2993 Player_Stop_internal();
2998 MikMod_free(mod
->control
);
3000 MikMod_free(mod
->voice
);
3005 void Player_Exit(MODULE
* mod
)
3008 Player_Exit_internal(mod
);
3012 MIKMODAPI
void Player_SetVolume(SWORD volume
)
3016 pf
->volume
=(volume
<0)?0:(volume
>128)?128:volume
;
3020 MIKMODAPI MODULE
* Player_GetModule(void)
3031 MIKMODAPI
void Player_Start(MODULE
*mod
)
3038 if (!MikMod_Active())
3039 MikMod_EnableOutput();
3045 /* new song is being started, so completely stop out the old one. */
3046 if (pf
) pf
->forbid
=1;
3047 for (t
=0;t
<md_sngchn
;t
++) Voice_Stop_internal(t
);
3053 void Player_Stop_internal(void)
3055 if (!md_sfxchn
) MikMod_DisableOutput_internal();
3056 if (pf
) pf
->forbid
=1;
3060 MIKMODAPI
void Player_Stop(void)
3063 Player_Stop_internal();
3067 MIKMODAPI
int Player_Active(void)
3073 result
=(!(pf
->sngpos
>=pf
->numpos
));
3079 MIKMODAPI
void Player_NextPosition(void)
3088 pf
->vbtick
=pf
->sngspd
;
3090 for (t
=0;t
<md_sngchn
;t
++) {
3091 Voice_Stop_internal(t
);
3092 pf
->voice
[t
].main
.i
=NULL
;
3093 pf
->voice
[t
].main
.s
=NULL
;
3095 for (t
=0;t
<pf
->numchn
;t
++) {
3096 pf
->control
[t
].main
.i
=NULL
;
3097 pf
->control
[t
].main
.s
=NULL
;
3104 MIKMODAPI
void Player_PrevPosition(void)
3113 pf
->vbtick
=pf
->sngspd
;
3115 for (t
=0;t
<md_sngchn
;t
++) {
3116 Voice_Stop_internal(t
);
3117 pf
->voice
[t
].main
.i
=NULL
;
3118 pf
->voice
[t
].main
.s
=NULL
;
3120 for (t
=0;t
<pf
->numchn
;t
++) {
3121 pf
->control
[t
].main
.i
=NULL
;
3122 pf
->control
[t
].main
.s
=NULL
;
3129 MIKMODAPI
void Player_SetPosition(UWORD pos
)
3136 if (pos
>=pf
->numpos
) pos
=pf
->numpos
;
3140 pf
->vbtick
=pf
->sngspd
;
3142 for (t
=0;t
<md_sngchn
;t
++) {
3143 Voice_Stop_internal(t
);
3144 pf
->voice
[t
].main
.i
=NULL
;
3145 pf
->voice
[t
].main
.s
=NULL
;
3147 for (t
=0;t
<pf
->numchn
;t
++) {
3148 pf
->control
[t
].main
.i
=NULL
;
3149 pf
->control
[t
].main
.s
=NULL
;
3154 Player_Init_internal(pf
);
3159 static void Player_Unmute_internal(SLONG arg1
,va_list ap
)
3161 SLONG t
,arg2
,arg3
=0;
3165 case MUTE_INCLUSIVE
:
3166 if (((!(arg2
=va_arg(ap
,SLONG
)))&&(!(arg3
=va_arg(ap
,SLONG
))))||
3167 (arg2
>arg3
)||(arg3
>=pf
->numchn
))
3169 for (;arg2
<pf
->numchn
&& arg2
<=arg3
;arg2
++)
3170 pf
->control
[arg2
].muted
=0;
3172 case MUTE_EXCLUSIVE
:
3173 if (((!(arg2
=va_arg(ap
,SLONG
)))&&(!(arg3
=va_arg(ap
,SLONG
))))||
3174 (arg2
>arg3
)||(arg3
>=pf
->numchn
))
3176 for (t
=0;t
<pf
->numchn
;t
++) {
3177 if ((t
>=arg2
) && (t
<=arg3
))
3179 pf
->control
[t
].muted
=0;
3183 if (arg1
<pf
->numchn
) pf
->control
[arg1
].muted
=0;
3189 MIKMODAPI
void Player_Unmute(SLONG arg1
, ...)
3193 va_start(args
,arg1
);
3195 Player_Unmute_internal(arg1
,args
);
3200 static void Player_Mute_internal(SLONG arg1
,va_list ap
)
3202 SLONG t
,arg2
,arg3
=0;
3206 case MUTE_INCLUSIVE
:
3207 if (((!(arg2
=va_arg(ap
,SLONG
)))&&(!(arg3
=va_arg(ap
,SLONG
))))||
3208 (arg2
>arg3
)||(arg3
>=pf
->numchn
))
3210 for (;arg2
<pf
->numchn
&& arg2
<=arg3
;arg2
++)
3211 pf
->control
[arg2
].muted
=1;
3213 case MUTE_EXCLUSIVE
:
3214 if (((!(arg2
=va_arg(ap
,SLONG
)))&&(!(arg3
=va_arg(ap
,SLONG
))))||
3215 (arg2
>arg3
)||(arg3
>=pf
->numchn
))
3217 for (t
=0;t
<pf
->numchn
;t
++) {
3218 if ((t
>=arg2
) && (t
<=arg3
))
3220 pf
->control
[t
].muted
=1;
3224 if (arg1
<pf
->numchn
)
3225 pf
->control
[arg1
].muted
=1;
3231 MIKMODAPI
void Player_Mute(SLONG arg1
,...)
3235 va_start(args
,arg1
);
3237 Player_Mute_internal(arg1
,args
);
3242 static void Player_ToggleMute_internal(SLONG arg1
,va_list ap
)
3249 case MUTE_INCLUSIVE
:
3250 if (((!(arg2
=va_arg(ap
,SLONG
)))&&(!(arg3
=va_arg(ap
,SLONG
))))||
3251 (arg2
>arg3
)||(arg3
>=pf
->numchn
))
3253 for (;arg2
<pf
->numchn
&& arg2
<=arg3
;arg2
++)
3254 pf
->control
[arg2
].muted
=1-pf
->control
[arg2
].muted
;
3256 case MUTE_EXCLUSIVE
:
3257 if (((!(arg2
=va_arg(ap
,SLONG
)))&&(!(arg3
=va_arg(ap
,SLONG
))))||
3258 (arg2
>arg3
)||(arg3
>=pf
->numchn
))
3260 for (t
=0;t
<pf
->numchn
;t
++) {
3261 if ((t
>=arg2
) && (t
<=arg3
))
3263 pf
->control
[t
].muted
=1-pf
->control
[t
].muted
;
3267 if (arg1
<pf
->numchn
)
3268 pf
->control
[arg1
].muted
=1-pf
->control
[arg1
].muted
;
3274 MIKMODAPI
void Player_ToggleMute(SLONG arg1
,...)
3278 va_start(args
,arg1
);
3280 Player_ToggleMute_internal(arg1
,args
);
3285 MIKMODAPI
int Player_Muted(UBYTE chan
)
3291 result
=(chan
<pf
->numchn
)?pf
->control
[chan
].muted
:1;
3297 MIKMODAPI
int Player_GetChannelVoice(UBYTE chan
)
3303 result
=(chan
<pf
->numchn
)?pf
->control
[chan
].slavechn
:-1;
3309 MIKMODAPI UWORD
Player_GetChannelPeriod(UBYTE chan
)
3315 result
=(chan
<pf
->numchn
)?pf
->control
[chan
].main
.period
:0;
3321 int Player_Paused_internal(void)
3323 return pf
?pf
->forbid
:1;
3326 MIKMODAPI
int Player_Paused(void)
3331 result
=Player_Paused_internal();
3337 MIKMODAPI
void Player_TogglePause(void)
3341 pf
->forbid
=1-pf
->forbid
;
3345 MIKMODAPI
void Player_SetSpeed(UWORD speed
)
3349 pf
->sngspd
=speed
?(speed
<32?speed
:32):1;
3353 MIKMODAPI
void Player_SetTempo(UWORD tempo
)
3355 if (tempo
<32) tempo
=32;
3358 if ((!(pf
->flags
&UF_HIGHBPM
))&&(tempo
>255)) tempo
=255;
3364 MIKMODAPI
int Player_QueryVoices(UWORD numvoices
, VOICEINFO
*vinfo
)
3368 if (numvoices
> md_sngchn
)
3369 numvoices
= md_sngchn
;
3373 for (i
= 0; i
< md_sngchn
; i
++) {
3374 vinfo
[i
].i
= pf
->voice
[i
].main
.i
;
3375 vinfo
[i
].s
= pf
->voice
[i
].main
.s
;
3376 vinfo
[i
].panning
= pf
->voice
[i
].main
.panning
;
3377 vinfo
[i
].volume
= pf
->voice
[i
].main
.chanvol
;
3378 vinfo
[i
].period
= pf
->voice
[i
].main
.period
;
3379 vinfo
[i
].kick
= pf
->voice
[i
].main
.kick_flag
;
3380 pf
->voice
[i
].main
.kick_flag
= 0;
3388 // Get current module order
3389 MIKMODAPI
int Player_GetOrder(void)
3393 ret
= pf
? pf
->sngpos
:0; // pf->positions[pf->sngpos ? pf->sngpos-1 : 0]: 0;
3398 // Get current module row
3399 MIKMODAPI
int Player_GetRow(void)
3403 ret
= pf
? pf
->patpos
: 0;