1
/* MikMod sound library
2
(c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
5
This library is free software; you can redistribute it and/or modify
6
it under the terms of the GNU Library General Public License as
7
published by the Free Software Foundation; either version 2 of
8
the License, or (at your option) any later version.
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU Library General Public License for more details.
15
You should have received a copy of the GNU Library General Public
16
License along with this library; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21
/*==============================================================================
25
The Protracker Player Driver
27
The protracker driver supports all base Protracker 3.x commands and features.
29
==============================================================================*/
38
extern long int random(void);
40
#ifdef SRANDOM_IN_MATH_H
46
#include "mikmod_internals.h"
48
/* Set forbid to 1 when you want to modify any of the pf->sngpos, pf->patpos etc
49
variables and clear it when you're done. This prevents getting strange
50
results due to intermediate interrupts. */
52
MODULE *pf=NULL; /* modfile being played */
53
static SWORD mp_channel; /* channel we're working on */
54
static MP_CONTROL *a; /* current AUDTMP we're working on */
55
static int explicitslides;
57
static UWORD oldperiods[OCTAVE*2]={
58
1712*16,1664*16,1616*16,1570*16,1524*16,1480*16,
59
1438*16,1396*16,1356*16,1318*16,1280*16,1244*16,
60
1208*16,1174*16,1140*16,1108*16,1076*16,1046*16,
61
1016*16, 988*16, 960*16, 932*16, 906*16, 880*16
64
static UBYTE VibratoTable[32]={
65
0, 24, 49, 74, 97,120,141,161,180,197,212,224,235,244,250,253,
66
255,253,250,244,235,224,212,197,180,161,141,120, 97, 74, 49, 24
69
static UBYTE avibtab[128]={
70
0, 1, 3, 4, 6, 7, 9,10,12,14,15,17,18,20,21,23,
71
24,25,27,28,30,31,32,34,35,36,38,39,40,41,42,44,
72
45,46,47,48,49,50,51,52,53,54,54,55,56,57,57,58,
73
59,59,60,60,61,61,62,62,62,63,63,63,63,63,63,63,
74
64,63,63,63,63,63,63,63,62,62,62,61,61,60,60,59,
75
59,58,57,57,56,55,54,54,53,52,51,50,49,48,47,46,
76
45,44,42,41,40,39,38,36,35,34,32,31,30,28,27,25,
77
24,23,21,20,18,17,15,14,12,10, 9, 7, 6, 4, 3, 1
80
/* Triton's linear periods to frequency translation table (for XM modules) */
81
static ULONG lintab[768]={
82
535232,534749,534266,533784,533303,532822,532341,531861,
83
531381,530902,530423,529944,529466,528988,528511,528034,
84
527558,527082,526607,526131,525657,525183,524709,524236,
85
523763,523290,522818,522346,521875,521404,520934,520464,
86
519994,519525,519057,518588,518121,517653,517186,516720,
87
516253,515788,515322,514858,514393,513929,513465,513002,
88
512539,512077,511615,511154,510692,510232,509771,509312,
89
508852,508393,507934,507476,507018,506561,506104,505647,
90
505191,504735,504280,503825,503371,502917,502463,502010,
91
501557,501104,500652,500201,499749,499298,498848,498398,
92
497948,497499,497050,496602,496154,495706,495259,494812,
93
494366,493920,493474,493029,492585,492140,491696,491253,
94
490809,490367,489924,489482,489041,488600,488159,487718,
95
487278,486839,486400,485961,485522,485084,484647,484210,
96
483773,483336,482900,482465,482029,481595,481160,480726,
97
480292,479859,479426,478994,478562,478130,477699,477268,
98
476837,476407,475977,475548,475119,474690,474262,473834,
99
473407,472979,472553,472126,471701,471275,470850,470425,
100
470001,469577,469153,468730,468307,467884,467462,467041,
101
466619,466198,465778,465358,464938,464518,464099,463681,
102
463262,462844,462427,462010,461593,461177,460760,460345,
103
459930,459515,459100,458686,458272,457859,457446,457033,
104
456621,456209,455797,455386,454975,454565,454155,453745,
105
453336,452927,452518,452110,451702,451294,450887,450481,
106
450074,449668,449262,448857,448452,448048,447644,447240,
107
446836,446433,446030,445628,445226,444824,444423,444022,
108
443622,443221,442821,442422,442023,441624,441226,440828,
109
440430,440033,439636,439239,438843,438447,438051,437656,
110
437261,436867,436473,436079,435686,435293,434900,434508,
111
434116,433724,433333,432942,432551,432161,431771,431382,
112
430992,430604,430215,429827,429439,429052,428665,428278,
113
427892,427506,427120,426735,426350,425965,425581,425197,
114
424813,424430,424047,423665,423283,422901,422519,422138,
115
421757,421377,420997,420617,420237,419858,419479,419101,
116
418723,418345,417968,417591,417214,416838,416462,416086,
117
415711,415336,414961,414586,414212,413839,413465,413092,
118
412720,412347,411975,411604,411232,410862,410491,410121,
119
409751,409381,409012,408643,408274,407906,407538,407170,
120
406803,406436,406069,405703,405337,404971,404606,404241,
121
403876,403512,403148,402784,402421,402058,401695,401333,
122
400970,400609,400247,399886,399525,399165,398805,398445,
123
398086,397727,397368,397009,396651,396293,395936,395579,
124
395222,394865,394509,394153,393798,393442,393087,392733,
125
392378,392024,391671,391317,390964,390612,390259,389907,
126
389556,389204,388853,388502,388152,387802,387452,387102,
127
386753,386404,386056,385707,385359,385012,384664,384317,
128
383971,383624,383278,382932,382587,382242,381897,381552,
129
381208,380864,380521,380177,379834,379492,379149,378807,
130
378466,378124,377783,377442,377102,376762,376422,376082,
131
375743,375404,375065,374727,374389,374051,373714,373377,
132
373040,372703,372367,372031,371695,371360,371025,370690,
133
370356,370022,369688,369355,369021,368688,368356,368023,
134
367691,367360,367028,366697,366366,366036,365706,365376,
135
365046,364717,364388,364059,363731,363403,363075,362747,
136
362420,362093,361766,361440,361114,360788,360463,360137,
137
359813,359488,359164,358840,358516,358193,357869,357547,
138
357224,356902,356580,356258,355937,355616,355295,354974,
139
354654,354334,354014,353695,353376,353057,352739,352420,
140
352103,351785,351468,351150,350834,350517,350201,349885,
141
349569,349254,348939,348624,348310,347995,347682,347368,
142
347055,346741,346429,346116,345804,345492,345180,344869,
143
344558,344247,343936,343626,343316,343006,342697,342388,
144
342079,341770,341462,341154,340846,340539,340231,339924,
145
339618,339311,339005,338700,338394,338089,337784,337479,
146
337175,336870,336566,336263,335959,335656,335354,335051,
147
334749,334447,334145,333844,333542,333242,332941,332641,
148
332341,332041,331741,331442,331143,330844,330546,330247,
149
329950,329652,329355,329057,328761,328464,328168,327872,
150
327576,327280,326985,326690,326395,326101,325807,325513,
151
325219,324926,324633,324340,324047,323755,323463,323171,
152
322879,322588,322297,322006,321716,321426,321136,320846,
153
320557,320267,319978,319690,319401,319113,318825,318538,
154
318250,317963,317676,317390,317103,316817,316532,316246,
155
315961,315676,315391,315106,314822,314538,314254,313971,
156
313688,313405,313122,312839,312557,312275,311994,311712,
157
311431,311150,310869,310589,310309,310029,309749,309470,
158
309190,308911,308633,308354,308076,307798,307521,307243,
159
306966,306689,306412,306136,305860,305584,305308,305033,
160
304758,304483,304208,303934,303659,303385,303112,302838,
161
302565,302292,302019,301747,301475,301203,300931,300660,
162
300388,300117,299847,299576,299306,299036,298766,298497,
163
298227,297958,297689,297421,297153,296884,296617,296349,
164
296082,295815,295548,295281,295015,294749,294483,294217,
165
293952,293686,293421,293157,292892,292628,292364,292100,
166
291837,291574,291311,291048,290785,290523,290261,289999,
167
289737,289476,289215,288954,288693,288433,288173,287913,
168
287653,287393,287134,286875,286616,286358,286099,285841,
169
285583,285326,285068,284811,284554,284298,284041,283785,
170
283529,283273,283017,282762,282507,282252,281998,281743,
171
281489,281235,280981,280728,280475,280222,279969,279716,
172
279464,279212,278960,278708,278457,278206,277955,277704,
173
277453,277203,276953,276703,276453,276204,275955,275706,
174
275457,275209,274960,274712,274465,274217,273970,273722,
175
273476,273229,272982,272736,272490,272244,271999,271753,
176
271508,271263,271018,270774,270530,270286,270042,269798,
177
269555,269312,269069,268826,268583,268341,268099,267857
181
static UWORD logtab[104]={
182
LOGFAC*907,LOGFAC*900,LOGFAC*894,LOGFAC*887,
183
LOGFAC*881,LOGFAC*875,LOGFAC*868,LOGFAC*862,
184
LOGFAC*856,LOGFAC*850,LOGFAC*844,LOGFAC*838,
185
LOGFAC*832,LOGFAC*826,LOGFAC*820,LOGFAC*814,
186
LOGFAC*808,LOGFAC*802,LOGFAC*796,LOGFAC*791,
187
LOGFAC*785,LOGFAC*779,LOGFAC*774,LOGFAC*768,
188
LOGFAC*762,LOGFAC*757,LOGFAC*752,LOGFAC*746,
189
LOGFAC*741,LOGFAC*736,LOGFAC*730,LOGFAC*725,
190
LOGFAC*720,LOGFAC*715,LOGFAC*709,LOGFAC*704,
191
LOGFAC*699,LOGFAC*694,LOGFAC*689,LOGFAC*684,
192
LOGFAC*678,LOGFAC*675,LOGFAC*670,LOGFAC*665,
193
LOGFAC*660,LOGFAC*655,LOGFAC*651,LOGFAC*646,
194
LOGFAC*640,LOGFAC*636,LOGFAC*632,LOGFAC*628,
195
LOGFAC*623,LOGFAC*619,LOGFAC*614,LOGFAC*610,
196
LOGFAC*604,LOGFAC*601,LOGFAC*597,LOGFAC*592,
197
LOGFAC*588,LOGFAC*584,LOGFAC*580,LOGFAC*575,
198
LOGFAC*570,LOGFAC*567,LOGFAC*563,LOGFAC*559,
199
LOGFAC*555,LOGFAC*551,LOGFAC*547,LOGFAC*543,
200
LOGFAC*538,LOGFAC*535,LOGFAC*532,LOGFAC*528,
201
LOGFAC*524,LOGFAC*520,LOGFAC*516,LOGFAC*513,
202
LOGFAC*508,LOGFAC*505,LOGFAC*502,LOGFAC*498,
203
LOGFAC*494,LOGFAC*491,LOGFAC*487,LOGFAC*484,
204
LOGFAC*480,LOGFAC*477,LOGFAC*474,LOGFAC*470,
205
LOGFAC*467,LOGFAC*463,LOGFAC*460,LOGFAC*457,
206
LOGFAC*453,LOGFAC*450,LOGFAC*447,LOGFAC*443,
207
LOGFAC*440,LOGFAC*437,LOGFAC*434,LOGFAC*431
210
static SBYTE PanbrelloTable[256]={
211
0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 17, 19, 20, 22, 23,
212
24, 26, 27, 29, 30, 32, 33, 34, 36, 37, 38, 39, 41, 42, 43, 44,
213
45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59,
214
59, 60, 60, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64, 64, 64, 64,
215
64, 64, 64, 64, 64, 64, 63, 63, 63, 62, 62, 62, 61, 61, 60, 60,
216
59, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46,
217
45, 44, 43, 42, 41, 39, 38, 37, 36, 34, 33, 32, 30, 29, 27, 26,
218
24, 23, 22, 20, 19, 17, 16, 14, 12, 11, 9, 8, 6, 5, 3, 2,
219
0,- 2,- 3,- 5,- 6,- 8,- 9,-11,-12,-14,-16,-17,-19,-20,-22,-23,
220
-24,-26,-27,-29,-30,-32,-33,-34,-36,-37,-38,-39,-41,-42,-43,-44,
221
-45,-46,-47,-48,-49,-50,-51,-52,-53,-54,-55,-56,-56,-57,-58,-59,
222
-59,-60,-60,-61,-61,-62,-62,-62,-63,-63,-63,-64,-64,-64,-64,-64,
223
-64,-64,-64,-64,-64,-64,-63,-63,-63,-62,-62,-62,-61,-61,-60,-60,
224
-59,-59,-58,-57,-56,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,
225
-45,-44,-43,-42,-41,-39,-38,-37,-36,-34,-33,-32,-30,-29,-27,-26,
226
-24,-23,-22,-20,-19,-17,-16,-14,-12,-11,- 9,- 8,- 6,- 5,- 3,- 2
229
/* returns a random value between 0 and ceil-1, ceil must be a power of two */
230
static int getrandom(int ceil)
233
return random()&(ceil-1);
235
return (int)((rand()*ceil)/(RAND_MAX+1.0));
239
/* New Note Action Scoring System :
240
--------------------------------
241
1) total-volume (fadevol, chanvol, volume) is the main scorer.
242
2) a looping sample is a bonus x2
243
3) a foreground channel is a bonus x4
244
4) an active envelope with keyoff is a handicap -x2 */
245
static int MP_FindEmptyChannel(void)
250
for (t=0;t<md_sngchn;t++)
251
if (((pf->voice[t].kick==KICK_ABSENT)||(pf->voice[t].kick==KICK_ENV))&&
252
Voice_Stopped_internal(t))
255
tvol=0xffffffUL;t=0;a=pf->voice;
256
for (k=0;k<md_sngchn;k++,a++)
257
if ((a->kick==KICK_ABSENT)||(a->kick==KICK_ENV)) {
258
pp=a->totalvol<<((a->s->flags&SF_LOOP)?1:0);
259
if ((a->master)&&(a==a->master->slave))
268
if (tvol>8000*7) return -1;
272
static SWORD Interpolate(SWORD p,SWORD p1,SWORD p2,SWORD v1,SWORD v2)
274
if ((p1==p2)||(p==p1)) return v1;
275
return v1+((SLONG)((p-p1)*(v2-v1))/(p2-p1));
278
UWORD getlinearperiod(UWORD note,ULONG fine)
282
t=(20L*OCTAVE+2-note)*32L-(fine>>1);
286
static UWORD getlogperiod(UWORD note,ULONG fine)
294
i=(n<<2)+(fine>>4); /* n*8 + fine/16 */
299
return (Interpolate(fine>>4,0,15,p1,p2)>>o);
302
static UWORD getoldperiod(UWORD note,ULONG speed)
308
fprintf(stderr,"\rmplayer: getoldperiod() called with note=%d, speed=0 !\n",note);
310
return 4242; /* <- prevent divide overflow.. (42 hehe) */
315
return ((8363L*(ULONG)oldperiods[n])>>o)/speed;
318
static UWORD GetPeriod(UWORD note,ULONG speed)
320
if (pf->flags & UF_XMPERIODS)
321
return (pf->flags&UF_LINEAR)?getlinearperiod(note,speed):getlogperiod(note,speed);
323
return getoldperiod(note,speed);
326
static SWORD InterpolateEnv(SWORD p,ENVPT *a,ENVPT *b)
328
return (Interpolate(p,a->pos,b->pos,a->val,b->val));
331
static SWORD DoPan(SWORD envpan,SWORD pan)
335
newpan=pan+(((envpan-PAN_CENTER)*(128-abs(pan-PAN_CENTER)))/128);
337
return (newpan<PAN_LEFT)?PAN_LEFT:(newpan>PAN_RIGHT?PAN_RIGHT:newpan);
340
static void StartEnvelope(ENVPR *t,UBYTE flg,UBYTE pts,UBYTE susbeg,UBYTE susend,UBYTE beg,UBYTE end,ENVPT *p,UBYTE keyoff)
351
t->b=((t->flg&EF_SUSTAIN)&&(!(keyoff&KEY_OFF)))?0:1;
353
/* Imago Orpheus sometimes stores an extra initial point in the envelope */
354
if ((t->pts>=2)&&(t->env[0].pos==t->env[1].pos)) {
358
if (t->b>=t->pts) t->b=t->pts-1;
361
/* This procedure processes all envelope types, include volume, pitch, and
362
panning. Envelopes are defined by a set of points, each with a magnitude
363
[relating either to volume, panning position, or pitch modifier] and a tick
366
Envelopes work in the following manner:
368
(a) Each tick the envelope is moved a point further in its progression. For
369
an accurate progression, magnitudes between two envelope points are
372
(b) When progression reaches a defined point on the envelope, values are
373
shifted to interpolate between this point and the next, and checks for
374
loops or envelope end are done.
377
Sustain loops are loops that are only active as long as the keyoff flag is
378
clear. When a volume envelope terminates, so does the current fadeout. */
379
static SWORD ProcessEnvelope(ENVPR *t,SWORD v,UBYTE keyoff)
381
if (t->flg & EF_ON) {
382
UBYTE a,b; /* actual points in the envelope */
383
UWORD p; /* the 'tick counter' - real point being played */
389
/* if sustain loop on one point (XM type), don't move and don't
390
interpolate when the point is reached */
391
if ((t->flg & EF_SUSTAIN)&&(t->susbeg==t->susend)&&
392
(!(keyoff&KEY_OFF))&&(p==t->env[t->susbeg].pos))
393
v=t->env[t->susbeg].val;
395
/* compute the current envelope value between points a and b */
399
v=InterpolateEnv(p,&t->env[a],&t->env[b]);
402
/* pointer reached point b? */
403
if (p>=t->env[b].pos) {
404
a=b++; /* shift points a and b */
406
/* Check for loops, sustain loops, or end of envelope. */
407
if ((t->flg&EF_SUSTAIN)&&(!(keyoff&KEY_OFF))&&(b>t->susend)) {
409
b=(t->susbeg==t->susend)?a:a+1;
412
if ((t->flg & EF_LOOP)&&(b>t->end)) {
414
b=(t->beg==t->end)?a:a+1;
418
if ((t->flg & EF_VOLENV)&&(mp_channel!=-1)) {
419
pf->voice[mp_channel].keyoff|=KEY_FADE;
421
pf->voice[mp_channel].fadevol=0;
435
/* XM linear period to frequency conversion */
436
ULONG getfrequency(UBYTE flags,ULONG period)
438
if (flags & UF_LINEAR)
439
return lintab[period%768]>>(period/768);
441
return (8363L*1712L)/(period?period:1);
444
/*========== Protracker effects */
446
static void DoEEffects(UBYTE dat)
451
case 0x0: /* hardware filter toggle, not supported */
453
case 0x1: /* fineslide up */
455
if (!pf->vbtick) a->tmpperiod-=(nib<<2);
457
case 0x2: /* fineslide dn */
459
if (!pf->vbtick) a->tmpperiod+=(nib<<2);
461
case 0x3: /* glissando ctrl */
464
case 0x4: /* set vibrato waveform */
465
a->wavecontrol&=0xf0;
468
case 0x5: /* set finetune */
470
if (pf->flags&UF_XMPERIODS)
473
a->speed=finetune[nib];
474
a->tmpperiod=GetPeriod((UWORD)a->note<<1,a->speed);
477
case 0x6: /* set patternloop */
478
if (pf->vbtick) break;
479
if (nib) { /* set reppos or repcnt ? */
480
/* set repcnt, so check if repcnt already is set, which means we
481
are already looping */
483
a->pat_repcnt--; /* already looping, decrease counter */
486
/* this would make walker.xm, shipped with Xsoundtracker,
487
play correctly, but it's better to remain compatible
489
if ((!(pf->flags&UF_NOWRAP))||(a->pat_reppos!=POS_NONE))
491
a->pat_repcnt=nib; /* not yet looping, so set repcnt */
494
if (a->pat_repcnt) { /* jump to reppos if repcnt>0 */
495
if (a->pat_reppos==POS_NONE)
496
a->pat_reppos=pf->patpos-1;
497
if (a->pat_reppos==-1) {
501
pf->patpos=a->pat_reppos;
502
} else a->pat_reppos=POS_NONE;
504
a->pat_reppos=pf->patpos-1; /* set reppos - can be (-1) */
506
case 0x7: /* set tremolo waveform */
507
a->wavecontrol&=0x0f;
508
a->wavecontrol|=nib<<4;
510
case 0x8: /* set panning */
514
a->panning=pf->panning[mp_channel]=nib;
517
case 0x9: /* retrig note */
518
/* only retrigger if data nibble > 0 */
521
/* when retrig counter reaches 0, reset counter and restart
523
if (a->period) a->kick=KICK_NOTE;
526
a->retrig--; /* countdown */
529
case 0xa: /* fine volume slide up */
530
if (pf->vbtick) break;
532
if (a->tmpvolume>64) a->tmpvolume=64;
534
case 0xb: /* fine volume slide dn */
535
if (pf->vbtick) break;
537
if (a->tmpvolume<0) a->tmpvolume=0;
539
case 0xc: /* cut note */
540
/* When pf->vbtick reaches the cut-note value, turn the volume to
541
zero ( Just like on the amiga) */
543
a->tmpvolume=0; /* just turn the volume down */
545
case 0xd: /* note delay */
546
/* delay the start of the sample until pf->vbtick==nib */
549
else if (a->notedelay)
552
case 0xe: /* pattern delay */
553
if (pf->vbtick) break;
554
if (!pf->patdly2) pf->patdly=nib+1; /* only once, when vbtick=0 */
556
case 0xf: /* invert loop, not supported */
561
static void DoVibrato(void)
566
q=(a->vibpos>>2)&0x1f;
568
switch (a->wavecontrol&3) {
570
temp=VibratoTable[q];
572
case 1: /* ramp down */
574
if (a->vibpos<0) q=255-q;
577
case 2: /* square wave */
580
case 3: /* random wave */
589
a->period=a->tmpperiod+temp;
591
a->period=a->tmpperiod-temp;
593
if (pf->vbtick) a->vibpos+=a->vibspd;
596
static void DoTremolo(void)
601
q=(a->trmpos>>2)&0x1f;
603
switch ((a->wavecontrol>>4)&3) {
605
temp=VibratoTable[q];
607
case 1: /* ramp down */
609
if (a->trmpos<0) q=255-q;
612
case 2: /* square wave */
615
case 3: /* random wave */
623
a->volume=a->tmpvolume+temp;
624
if (a->volume>64) a->volume=64;
626
a->volume=a->tmpvolume-temp;
627
if (a->volume<0) a->volume=0;
630
if (pf->vbtick) a->trmpos+=a->trmspd;
633
static void DoVolSlide(UBYTE dat)
635
if (!pf->vbtick) return;
638
a->tmpvolume-=(dat&0x0f);
639
if (a->tmpvolume<0) a->tmpvolume=0;
641
a->tmpvolume+=(dat>>4);
642
if (a->tmpvolume>64) a->tmpvolume=64;
646
static void DoToneSlide(void)
651
/* We have to slide a->period towards a->wantedperiod, so compute the
652
difference between those two values */
653
dist=a->period-a->wantedperiod;
655
/* if they are equal or if portamentospeed is too big ...*/
656
if ((!dist)||a->portspeed>abs(dist))
657
/* ...make tmpperiod equal tperiod */
658
a->tmpperiod=a->period=a->wantedperiod;
660
a->tmpperiod-=a->portspeed;
661
a->period-=a->portspeed; /* dist>0, slide up */
663
a->tmpperiod+=a->portspeed;
664
a->period+=a->portspeed; /* dist<0, slide down */
667
a->tmpperiod=a->period;
670
static void DoArpeggio(UBYTE dat)
675
switch (pf->vbtick%3) {
677
note+=(dat>>4); break;
679
note+=(dat&0xf); break;
681
a->period=GetPeriod((UWORD)note<<1,a->speed);
686
/*========== Scream Tracker effects */
688
static void DoS3MVolSlide(UBYTE inf)
694
if (inf) a->s3mvolslide=inf;
695
else inf=a->s3mvolslide;
701
if ((pf->vbtick)||(pf->flags&UF_S3MSLIDES)) a->tmpvolume+=hi;
704
if ((pf->vbtick)||(pf->flags&UF_S3MSLIDES)) a->tmpvolume-=lo;
707
if (!pf->vbtick) a->tmpvolume+=(hi?hi:0xf);
710
if (!pf->vbtick) a->tmpvolume-=(lo?lo:0xf);
714
if (a->tmpvolume<0) a->tmpvolume=0;
715
else if (a->tmpvolume>64) a->tmpvolume=64;
718
static void DoS3MSlideDn(UBYTE inf)
722
if (inf) a->slidespeed=inf;
723
else inf=a->slidespeed;
729
if (!pf->vbtick) a->tmpperiod+=(UWORD)lo<<2;
732
if (!pf->vbtick) a->tmpperiod+=lo;
734
if (pf->vbtick) a->tmpperiod+=(UWORD)inf<<2;
738
static void DoS3MSlideUp(UBYTE inf)
742
if (inf) a->slidespeed=inf;
743
else inf=a->slidespeed;
749
if (!pf->vbtick) a->tmpperiod-=(UWORD)lo<<2;
752
if (!pf->vbtick) a->tmpperiod-=lo;
754
if (pf->vbtick) a->tmpperiod-=(UWORD)inf<<2;
758
static void DoS3MTremor(UBYTE inf)
769
if (!pf->vbtick) return;
773
a->s3mtremor%=(on+off);
774
a->volume=(a->s3mtremor<on)?a->tmpvolume:0;
778
static void DoS3MRetrig(UBYTE inf)
781
a->s3mrtgslide=inf>>4;
782
a->s3mrtgspeed=inf&0xf;
785
/* only retrigger if low nibble > 0 */
786
if ( a->s3mrtgspeed>0) {
788
/* when retrig counter reaches 0, reset counter and restart the
790
if (a->kick!=KICK_NOTE) a->kick=KICK_KEYOFF;
791
a->retrig=a->s3mrtgspeed;
793
if ((pf->vbtick)||(pf->flags&UF_S3MSLIDES)) {
794
switch (a->s3mrtgslide) {
800
a->tmpvolume-=(1<<(a->s3mrtgslide-1));
803
a->tmpvolume=(2*a->tmpvolume)/3;
813
a->tmpvolume+=(1<<(a->s3mrtgslide-9));
816
a->tmpvolume=(3*a->tmpvolume)>>1;
819
a->tmpvolume=a->tmpvolume<<1;
822
if (a->tmpvolume<0) a->tmpvolume=0;
823
else if (a->tmpvolume>64) a->tmpvolume=64;
826
a->retrig--; /* countdown */
830
static void DoS3MSpeed(UBYTE speed)
832
if (pf->vbtick||pf->patdly2) return;
834
if (speed>128) speed-=128;
841
static void DoS3MTempo(UBYTE tempo)
843
if (pf->vbtick||pf->patdly2) return;
845
pf->bpm=(tempo<32)?32:tempo;
848
static void DoS3MFineVibrato(void)
853
q=(a->vibpos>>2)&0x1f;
855
switch (a->wavecontrol&3) {
857
temp=VibratoTable[q];
859
case 1: /* ramp down */
861
if (a->vibpos<0) q=255-q;
864
case 2: /* square wave */
876
a->period=a->tmpperiod+temp;
878
a->period=a->tmpperiod-temp;
880
a->vibpos+=a->vibspd;
883
static void DoS3MTremolo(void)
888
q=(a->trmpos>>2)&0x1f;
890
switch ((a->wavecontrol>>4)&3) {
892
temp=VibratoTable[q];
894
case 1: /* ramp down */
896
if (a->trmpos<0) q=255-q;
899
case 2: /* square wave */
911
a->volume=a->tmpvolume+temp;
912
if (a->volume>64) a->volume=64;
914
a->volume=a->tmpvolume-temp;
915
if (a->volume<0) a->volume=0;
918
if (pf->vbtick) a->trmpos+=a->trmspd;
921
/*========== Fast Tracker effects */
923
static void DoXMVolSlide(UBYTE inf)
929
if (inf) a->s3mvolslide=inf;
930
else inf=a->s3mvolslide;
932
if (!pf->vbtick) return;
939
if (a->tmpvolume<0) a->tmpvolume=0;
942
if (a->tmpvolume>64) a->tmpvolume=64;
946
static void DoXMGlobalSlide(UBYTE inf)
949
if (inf) pf->globalslide=inf;
950
else inf=pf->globalslide;
951
if (inf & 0xf0) inf&=0xf0;
952
pf->volume=pf->volume+((inf>>4)-(inf&0xf))*2;
954
if (pf->volume<0) pf->volume=0;
955
else if (pf->volume>128) pf->volume=128;
959
static void DoXMPanSlide(UBYTE inf)
964
if (inf) a->pansspd=inf;
967
if (!pf->vbtick) return;
972
/* slide right has absolute priority */
975
pan=((a->panning==PAN_SURROUND)?PAN_CENTER:a->panning)+hi-lo;
977
a->panning=(pan<PAN_LEFT)?PAN_LEFT:(pan>PAN_RIGHT?PAN_RIGHT:pan);
980
static void DoXMExtraFineSlideUp(UBYTE inf)
988
static void DoXMExtraFineSlideDown(UBYTE inf)
996
/*========== Impulse Tracker effects */
998
static void DoITChanVolSlide(UBYTE inf)
1002
if (inf) a->chanvolslide=inf;
1003
inf=a->chanvolslide;
1015
if (!pf->vbtick) a->chanvol-=lo;
1018
if (!pf->vbtick) a->chanvol+=hi;
1021
if (a->chanvol<0) a->chanvol=0;
1022
if (a->chanvol>64) a->chanvol=64;
1025
static void DoITGlobalSlide(UBYTE inf)
1029
if (inf) pf->globalslide=inf;
1030
inf=pf->globalslide;
1036
if (pf->vbtick) pf->volume+=hi;
1039
if (pf->vbtick) pf->volume-=lo;
1042
if (!pf->vbtick) pf->volume+=hi;
1045
if (!pf->vbtick) pf->volume-=lo;
1048
if (pf->volume<0) pf->volume=0;
1049
if (pf->volume>128) pf->volume=128;
1052
static void DoITPanSlide(UBYTE inf)
1057
if (inf) a->pansspd=inf;
1058
else inf=a->pansspd;
1063
pan=(a->panning==PAN_SURROUND)?PAN_CENTER:a->panning;
1072
if (!pf->vbtick) pan+=lo<<2;
1075
if (!pf->vbtick) pan-=hi<<2;
1077
a->panning=/*pf->panning[mp_channel]=*/
1078
(pan<PAN_LEFT)?PAN_LEFT:(pan>PAN_RIGHT?PAN_RIGHT:pan);
1081
static void DoITTempo(UBYTE tempo)
1085
if (pf->vbtick||pf->patdly2) return;
1092
pf->bpm=(temp>255)?255:(temp<1?1:temp);
1095
static void DoITVibrato(void)
1100
q=(a->vibpos>>2)&0x1f;
1102
switch (a->wavecontrol&3) {
1104
temp=VibratoTable[q];
1106
case 1: /* square wave */
1109
case 2: /* ramp down */
1111
if (a->vibpos<0) q=255-q;
1114
case 3: /* random */
1115
temp=getrandom(256);
1124
a->period=a->tmpperiod+temp;
1126
a->period=a->tmpperiod-temp;
1128
a->vibpos+=a->vibspd;
1131
static void DoITFineVibrato(void)
1136
q=(a->vibpos>>2)&0x1f;
1138
switch (a->wavecontrol&3) {
1140
temp=VibratoTable[q];
1142
case 1: /* square wave */
1145
case 2: /* ramp down */
1147
if (a->vibpos<0) q=255-q;
1150
case 3: /* random */
1151
temp=getrandom(256);
1159
a->period=a->tmpperiod+temp;
1161
a->period=a->tmpperiod-temp;
1163
a->vibpos+=a->vibspd;
1166
static void DoITTremor(UBYTE inf)
1177
if (!pf->vbtick) return;
1182
a->s3mtremor%=(on+off);
1183
a->volume=(a->s3mtremor<on)?a->tmpvolume:0;
1187
static void DoITPanbrello(void)
1194
switch (a->panbwave) {
1196
temp=PanbrelloTable[q];
1198
case 1: /* square wave */
1201
case 2: /* ramp down */
1205
case 3: /* random */
1206
if (a->panbpos>=a->panbspd) {
1208
temp=getrandom(256);
1213
temp=(temp/8)+pf->panning[mp_channel];
1215
a->panning=(temp<PAN_LEFT)?PAN_LEFT:(temp>PAN_RIGHT?PAN_RIGHT:temp);
1216
a->panbpos+=a->panbspd;
1219
static void DoITToneSlide(void)
1221
/* if we don't come from another note, ignore the slide and play the note
1223
if (!a->oldnote) return;
1228
/* We have to slide a->period towards a->wantedperiod, compute the
1229
difference between those two values */
1230
dist=a->period-a->wantedperiod;
1232
/* if they are equal or if portamentospeed is too big... */
1233
if ((!dist)||((a->portspeed<<2)>abs(dist)))
1234
/* ... make tmpperiod equal tperiod */
1235
a->tmpperiod=a->period=a->wantedperiod;
1238
a->tmpperiod-=a->portspeed<<2;
1239
a->period-=a->portspeed<<2; /* dist>0 slide up */
1241
a->tmpperiod+=a->portspeed<<2;
1242
a->period+=a->portspeed<<2; /* dist<0 slide down */
1245
a->tmpperiod=a->period;
1248
static void DoNNAEffects(UBYTE dat);
1249
/* Impulse/Scream Tracker Sxx effects.
1250
All Sxx effects share the same memory space. */
1251
static void DoSSEffects(UBYTE dat)
1267
case SS_GLISSANDO: /* S1x set glissando voice */
1268
DoEEffects(0x30|inf);
1270
case SS_FINETUNE: /* S2x set finetune */
1271
DoEEffects(0x50|inf);
1273
case SS_VIBWAVE: /* S3x set vibrato waveform */
1274
DoEEffects(0x40|inf);
1276
case SS_TREMWAVE: /* S4x set tremolo waveform */
1277
DoEEffects(0x70|inf);
1279
case SS_PANWAVE: /* S5x panbrello */
1282
case SS_FRAMEDELAY: /* S6x delay x number of frames (patdly) */
1283
DoEEffects(0xe0|inf);
1285
case SS_S7EFFECTS: /* S7x instrument / NNA commands */
1288
case SS_PANNING: /* S8x set panning position */
1289
DoEEffects(0x80 | inf);
1291
case SS_SURROUND: /* S9x set surround Sound */
1293
a->panning=pf->panning[mp_channel]=PAN_SURROUND;
1295
case SS_HIOFFSET: /* SAy set high order sample offset yxx00h */
1297
a->hioffset=inf<<16;
1298
a->start=a->hioffset|a->soffset;
1300
if ((a->s)&&(a->start>a->s->length))
1301
a->start=a->s->flags&(SF_LOOP|SF_BIDI)?a->s->loopstart:a->s->length;
1304
case SS_PATLOOP: /* SBx pattern loop */
1305
DoEEffects(0x60|inf);
1307
case SS_NOTECUT: /* SCx notecut */
1308
DoEEffects(0xC0|inf);
1310
case SS_NOTEDELAY: /* SDx notedelay */
1311
DoEEffects(0xD0|inf);
1313
case SS_PATDELAY: /* SEx patterndelay */
1314
DoEEffects(0xE0|inf);
1319
/* Impulse Tracker Volume/Pan Column effects.
1320
All volume/pan column effects share the same memory space. */
1321
static void DoVolEffects(UBYTE c)
1323
UBYTE inf=UniGetByte();
1336
if (pf->vbtick) break;
1342
a->panning=/*pf->panning[mp_channel]=*/inf;
1347
case VOL_PITCHSLIDEDN:
1351
case VOL_PITCHSLIDEUP:
1355
case VOL_PORTAMENTO:
1356
if (inf) a->slidespeed=inf;
1358
if ((!pf->vbtick)||(a->newsamp)){
1362
a->kick=(a->kick==KICK_NOTE)?KICK_ENV:KICK_ABSENT;
1369
if (inf&0x0f) a->vibdepth=inf&0xf;
1370
if (inf&0xf0) a->vibspd=(inf&0xf0)>>2;
1380
/*========== UltraTracker effects */
1382
static void DoULTSampleOffset(void)
1384
UWORD offset=UniGetWord();
1387
a->ultoffset=offset;
1389
a->start=a->ultoffset<<2;
1390
if ((a->s)&&(a->start>a->s->length))
1391
a->start=a->s->flags&(SF_LOOP|SF_BIDI)?a->s->loopstart:a->s->length;
1394
/*========== OctaMED effects */
1396
static void DoMEDSpeed(void)
1398
UWORD speed=UniGetWord();
1403
/*========== General player functions */
1405
static void pt_playeffects(void)
1409
while((c=UniGetByte())) {
1410
int oldsliding=a->sliding;
1415
case UNI_INSTRUMENT:
1416
a->sliding=oldsliding;
1422
if ((!dat)&&(pf->flags&UF_ARPMEM)) dat=a->arpmem;
1426
DoArpeggio(a->arpmem);
1430
if ((!pf->vbtick)&&(dat)) a->slidespeed=(UWORD)dat<<2;
1432
if (pf->vbtick) a->tmpperiod-=a->slidespeed;
1436
if ((!pf->vbtick)&&(dat)) a->slidespeed=(UWORD)dat<<2;
1438
if (pf->vbtick) a->tmpperiod+=a->slidespeed;
1442
if ((!pf->vbtick)&&(dat)) a->portspeed=(UWORD)dat<<2;
1445
a->kick=(a->kick==KICK_NOTE)?KICK_NOTE:KICK_KEYOFF;
1447
a->kick=(a->kick==KICK_NOTE)?KICK_ENV:KICK_ABSENT;
1456
if (dat&0x0f) a->vibdepth=dat&0xf;
1457
if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
1468
a->kick=(a->kick==KICK_NOTE)?KICK_NOTE:KICK_KEYOFF;
1470
a->kick=(a->kick==KICK_NOTE)?KICK_ENV:KICK_ABSENT;
1478
if ((a->period)&&(pf->vbtick)) {
1487
if (dat&0x0f) a->trmdepth=dat&0xf;
1488
if (dat&0xf0) a->trmspd=(dat&0xf0)>>2;
1498
a->panning=pf->panning[mp_channel]=dat;
1503
if (dat) a->soffset=(UWORD)dat<<8;
1504
a->start=a->hioffset|a->soffset;
1506
if ((a->s)&&(a->start>a->s->length))
1507
a->start=a->s->flags&(SF_LOOP|SF_BIDI)?a->s->loopstart:a->s->length;
1511
DoVolSlide(UniGetByte());
1515
if ((pf->vbtick)||(pf->patdly2)) break;
1516
/* Vincent Voois uses a nasty trick in "Universal Bolero" */
1517
if (dat==pf->sngpos && pf->patbrk==pf->patpos) break;
1518
if ((!pf->loop)&&(!pf->patbrk)&&((dat<pf->sngpos)||
1519
((pf->sngpos==pf->numpos-1)&&(!pf->patbrk))||
1520
((dat==pf->sngpos)&&(pf->flags&UF_NOWRAP)))) {
1521
/* if we don't loop, better not to skip the end of the
1522
pattern, after all... so:
1526
/* if we were fading, adjust... */
1527
if (pf->sngpos==(pf->numpos-1))
1528
pf->volume=pf->initvolume>128?128:pf->initvolume;
1536
if (pf->vbtick) break;
1537
if (dat==(UBYTE)-1) a->anote=dat=0; /* note cut */
1538
else if (dat>64) dat=64;
1543
if ((pf->vbtick)||(pf->patdly2)) break;
1544
if ((pf->positions[pf->sngpos]!=255)&&
1545
(dat>pf->pattrows[pf->positions[pf->sngpos]]))
1546
dat=pf->pattrows[pf->positions[pf->sngpos]];
1549
/* don't ask me to explain this code - it makes
1550
backwards.s3m and children.xm (heretic's version) play
1551
correctly, among others. Take that for granted, or write
1552
the page of comments yourself... you might need some
1554
if ((pf->sngpos==pf->numpos-1)&&(dat)&&((pf->loop)||
1555
(pf->positions[pf->sngpos]==(pf->numpat-1)
1556
&& !(pf->flags&UF_NOWRAP)))) {
1564
DoEEffects(UniGetByte());
1568
if (pf->vbtick||pf->patdly2) break;
1569
if (pf->extspd&&(dat>=0x20))
1573
pf->sngspd=(dat>32)?32:dat;
1577
case UNI_S3MEFFECTA:
1578
DoS3MSpeed(UniGetByte());
1580
case UNI_S3MEFFECTD:
1581
DoS3MVolSlide(UniGetByte());
1583
case UNI_S3MEFFECTE:
1588
case UNI_S3MEFFECTF:
1593
case UNI_S3MEFFECTI:
1594
DoS3MTremor(UniGetByte());
1597
case UNI_S3MEFFECTQ:
1602
case UNI_S3MEFFECTR:
1605
if (dat&0x0f) a->trmdepth=dat&0xf;
1606
if (dat&0xf0) a->trmspd=(dat&0xf0)>>2;
1611
case UNI_S3MEFFECTT:
1612
DoS3MTempo(UniGetByte());
1614
case UNI_S3MEFFECTU:
1617
if (dat&0x0f) a->vibdepth=dat&0xf;
1618
if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
1627
if ((!(a->volflg&EF_ON))||(a->volflg&EF_LOOP))
1632
if ((pf->vbtick>=dat)||(pf->vbtick==pf->sngspd-1)) {
1634
if (!(a->volflg&EF_ON))
1638
case UNI_VOLEFFECTS:
1639
DoVolEffects(UniGetByte());
1642
DoXMVolSlide(UniGetByte());
1644
case UNI_XMEFFECTE1: /* XM fineslide up */
1647
if (dat) a->fportupspd=dat;
1649
a->tmpperiod-=(a->fportupspd<<2);
1652
case UNI_XMEFFECTE2: /* XM fineslide dn */
1655
if (dat) a->fportdnspd=dat;
1657
a->tmpperiod+=(a->fportdnspd<<2);
1660
case UNI_XMEFFECTEA: /* fine volume slide up */
1663
if (dat) a->fslideupspd=dat;
1664
a->tmpvolume+=a->fslideupspd;
1665
if (a->tmpvolume>64) a->tmpvolume=64;
1667
case UNI_XMEFFECTEB: /* fine volume slide dn */
1670
if (dat) a->fslidednspd=dat;
1671
a->tmpvolume-=a->fslidednspd;
1672
if (a->tmpvolume<0) a->tmpvolume=0;
1675
pf->volume=UniGetByte()<<1;
1676
if (pf->volume>128) pf->volume=128;
1679
DoXMGlobalSlide(UniGetByte());
1683
if ((!pf->vbtick)&&(a->i)) {
1688
if ((aout=a->slave)) {
1689
points=i->volenv[i->volpts-1].pos;
1690
aout->venv.p=aout->venv.env[(dat>points)?points:dat].pos;
1691
points=i->panenv[i->panpts-1].pos;
1692
aout->penv.p=aout->penv.env[(dat>points)?points:dat].pos;
1701
case UNI_XMEFFECTX1:
1703
if (dat) a->ffportupspd=dat;
1704
else dat=a->ffportupspd;
1706
DoXMExtraFineSlideUp(dat);
1710
case UNI_XMEFFECTX2:
1712
if (dat) a->ffportdnspd=dat;
1713
else dat=a->ffportdnspd;
1715
DoXMExtraFineSlideDown(dat);
1725
if ((!pf->vbtick)&&(a->newsamp)){
1729
a->kick=(a->kick==KICK_NOTE)?KICK_ENV:KICK_ABSENT;
1734
case UNI_ITEFFECTH: /* IT vibrato */
1737
if (dat&0x0f) a->vibdepth=dat&0xf;
1738
if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
1745
case UNI_ITEFFECTI: /* IT tremor */
1746
DoITTremor(UniGetByte());
1750
a->chanvol=UniGetByte();
1751
if (a->chanvol>64) a->chanvol=64;
1752
else if (a->chanvol<0) a->chanvol=0;
1754
case UNI_ITEFFECTN: /* slide / fineslide channel volume */
1755
DoITChanVolSlide(UniGetByte());
1757
case UNI_ITEFFECTP: /* slide / fineslide channel panning */
1762
case UNI_ITEFFECTT: /* slide / fineslide tempo */
1763
DoITTempo(UniGetByte());
1765
case UNI_ITEFFECTU: /* fine vibrato */
1768
if (dat&0x0f) a->vibdepth=dat&0xf;
1769
if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
1776
case UNI_ITEFFECTW: /* slide / fineslide global volume */
1777
DoITGlobalSlide(UniGetByte());
1779
case UNI_ITEFFECTY: /* panbrello */
1782
if (dat&0x0f) a->panbdepth=(dat&0xf);
1783
if (dat&0xf0) a->panbspd=(dat&0xf0)>>4;
1785
if (pf->panflag) DoITPanbrello();
1787
case UNI_ITEFFECTS0:
1788
DoSSEffects(UniGetByte());
1791
/* FIXME not yet implemented */
1792
UniSkipOpcode(UNI_ITEFFECTZ);
1794
case UNI_ULTEFFECT9:
1795
DoULTSampleOffset();
1800
case UNI_MEDEFFECTF1:
1801
DoEEffects(0x90|(pf->sngspd/2));
1803
case UNI_MEDEFFECTF2:
1804
DoEEffects(0xd0|(pf->sngspd/2));
1806
case UNI_MEDEFFECTF3:
1807
DoEEffects(0x90|(pf->sngspd/3));
1810
Player_SetSynchroValue(UniGetByte());
1813
a->sliding=oldsliding;
1820
static void DoNNAEffects(UBYTE dat)
1826
aout=(a->slave)?a->slave:NULL;
1829
case 0x0: /* past note cut */
1830
for (t=0;t<md_sngchn;t++)
1831
if (pf->voice[t].master==a)
1832
pf->voice[t].fadevol=0;
1834
case 0x1: /* past note off */
1835
for (t=0;t<md_sngchn;t++)
1836
if (pf->voice[t].master==a) {
1837
pf->voice[t].keyoff|=KEY_OFF;
1838
if ((!(pf->voice[t].venv.flg & EF_ON))||
1839
(pf->voice[t].venv.flg & EF_LOOP))
1840
pf->voice[t].keyoff=KEY_KILL;
1843
case 0x2: /* past note fade */
1844
for (t=0;t<md_sngchn;t++)
1845
if (pf->voice[t].master==a)
1846
pf->voice[t].keyoff|=KEY_FADE;
1848
case 0x3: /* set NNA note cut */
1849
a->nna=(a->nna&~NNA_MASK)|NNA_CUT;
1851
case 0x4: /* set NNA note continue */
1852
a->nna=(a->nna&~NNA_MASK)|NNA_CONTINUE;
1854
case 0x5: /* set NNA note off */
1855
a->nna=(a->nna&~NNA_MASK)|NNA_OFF;
1857
case 0x6: /* set NNA note fade */
1858
a->nna=(a->nna&~NNA_MASK)|NNA_FADE;
1860
case 0x7: /* disable volume envelope */
1862
aout->volflg&=~EF_ON;
1864
case 0x8: /* enable volume envelope */
1866
aout->volflg|=EF_ON;
1868
case 0x9: /* disable panning envelope */
1870
aout->panflg&=~EF_ON;
1872
case 0xa: /* enable panning envelope */
1874
aout->panflg|=EF_ON;
1876
case 0xb: /* disable pitch envelope */
1878
aout->pitflg&=~EF_ON;
1880
case 0xc: /* enable pitch envelope */
1882
aout->pitflg|=EF_ON;
1887
void pt_UpdateVoices(int max_volume)
1889
SWORD envpan,envvol,envpit;
1891
SLONG vibval,vibdpt;
1898
pf->totalchn=pf->realchn=0;
1899
for (mp_channel=0;mp_channel<md_sngchn;mp_channel++) {
1900
aout=&pf->voice[mp_channel];
1904
if ((!s)||(!s->length)) continue;
1906
if (aout->period<40) aout->period=40;
1907
else if (aout->period>50000) aout->period=50000;
1909
if ((aout->kick==KICK_NOTE)||(aout->kick==KICK_KEYOFF)) {
1910
Voice_Play_internal(mp_channel,s,(aout->start==-1)?((s->flags&SF_UST_LOOP)?s->loopstart:0):aout->start);
1911
aout->fadevol=32768;
1915
if (i && ((aout->kick==KICK_NOTE)||(aout->kick==KICK_ENV))) {
1916
StartEnvelope(&aout->venv,aout->volflg,i->volpts,i->volsusbeg,
1917
i->volsusend,i->volbeg,i->volend,i->volenv,aout->keyoff);
1918
StartEnvelope(&aout->penv,aout->panflg,i->panpts,i->pansusbeg,
1919
i->pansusend,i->panbeg,i->panend,i->panenv,aout->keyoff);
1920
StartEnvelope(&aout->cenv,aout->pitflg,i->pitpts,i->pitsusbeg,
1921
i->pitsusend,i->pitbeg,i->pitend,i->pitenv,aout->keyoff);
1922
if (aout->cenv.flg&EF_ON)
1923
aout->masterperiod=GetPeriod((UWORD)aout->note<<1,aout->master->speed);
1925
aout->kick=KICK_ABSENT;
1927
envvol=(!(aout->volflg & EF_ON))?256:
1928
ProcessEnvelope(&aout->venv,256,aout->keyoff);
1929
envpan=(!(aout->panflg & EF_ON))?PAN_CENTER:
1930
ProcessEnvelope(&aout->penv,PAN_CENTER,aout->keyoff);
1931
envpit=(!(aout->pitflg & EF_ON))?32:
1932
ProcessEnvelope(&aout->cenv,32,aout->keyoff);
1934
tmpvol=aout->fadevol; /* max 32768 */
1935
tmpvol*=aout->chanvol; /* * max 64 */
1936
tmpvol*=aout->volume; /* * max 256 */
1937
tmpvol/=16384L; /* tmpvol is max 32768 */
1938
aout->totalvol=tmpvol>>2; /* totalvolume used to determine samplevolume */
1939
tmpvol*=envvol; /* * max 256 */
1940
tmpvol*=pf->volume; /* * max 128 */
1942
tmpvol*=pf->initvolume; /* * max 128 */
1946
if (pf->sngpos>=pf->numpos) tmpvol=0;
1948
tmpvol=(tmpvol*max_volume)/128;
1950
if ((aout->masterchn!=-1)&& pf->control[aout->masterchn].muted)
1951
Voice_SetVolume_internal(mp_channel,0);
1953
Voice_SetVolume_internal(mp_channel,tmpvol);
1954
if ((tmpvol)&&(aout->master)&&(aout->master->slave==aout))
1959
if (aout->panning==PAN_SURROUND)
1960
Voice_SetPanning_internal(mp_channel,PAN_SURROUND);
1962
if ((pf->panflag)&&(aout->penv.flg & EF_ON))
1963
Voice_SetPanning_internal(mp_channel,DoPan(envpan,aout->panning));
1965
Voice_SetPanning_internal(mp_channel,aout->panning);
1967
if (aout->period && s->vibdepth)
1968
switch (s->vibtype) {
1970
vibval=avibtab[s->avibpos&127];
1971
if (s->avibpos & 0x80) vibval=-vibval;
1975
if (s->avibpos & 0x80) vibval=-vibval;
1978
vibval=63-(((s->avibpos+128)&255)>>1);
1981
vibval=(((s->avibpos+128)&255)>>1)-64;
1987
if (s->vibflags & AV_IT) {
1988
if ((aout->aswppos>>8)<s->vibdepth) {
1989
aout->aswppos += s->vibsweep;
1990
vibdpt=aout->aswppos;
1992
vibdpt=s->vibdepth<<8;
1993
vibval=(vibval*vibdpt)>>16;
1995
if (!(pf->flags&UF_LINEAR)) vibval>>=1;
1996
aout->period-=vibval;
1999
/* do XM style auto-vibrato */
2000
if (!(aout->keyoff & KEY_OFF)) {
2001
if (aout->aswppos<s->vibsweep) {
2002
vibdpt=(aout->aswppos*s->vibdepth)/s->vibsweep;
2007
/* keyoff -> depth becomes 0 if final depth wasn't reached or
2008
stays at final level if depth WAS reached */
2009
if (aout->aswppos>=s->vibsweep)
2014
vibval=(vibval*vibdpt)>>8;
2015
aout->period-=vibval;
2018
/* update vibrato position */
2019
s->avibpos=(s->avibpos+s->vibrate)&0xff;
2021
/* process pitch envelope */
2022
playperiod=aout->period;
2024
if ((aout->pitflg&EF_ON)&&(envpit!=32)) {
2028
if ((aout->note<<1)+envpit<=0) envpit=-(aout->note<<1);
2030
p1=GetPeriod(((UWORD)aout->note<<1)+envpit,aout->master->speed)-aout->masterperiod;
2032
if ((UWORD)(playperiod+p1)<=playperiod) {
2034
aout->keyoff|=KEY_OFF;
2037
if ((UWORD)(playperiod+p1)>=playperiod) {
2039
aout->keyoff|=KEY_OFF;
2045
if (!aout->fadevol) { /* check for a dead note (fadevol=0) */
2046
Voice_Stop_internal(mp_channel);
2048
if ((tmpvol)&&(aout->master)&&(aout->master->slave==aout))
2051
Voice_SetFrequency_internal(mp_channel,
2052
getfrequency(pf->flags,playperiod));
2054
/* if keyfade, start substracting fadeoutspeed from fadevol: */
2055
if ((i)&&(aout->keyoff&KEY_FADE)) {
2056
if (aout->fadevol>=i->volfade)
2057
aout->fadevol-=i->volfade;
2063
md_bpm=pf->bpm+pf->relspd;
2064
if (md_bpm<32) md_bpm=32;
2065
else if (md_bpm>255) md_bpm=255;
2069
/* Handles new notes or instruments */
2073
int tr,funky; /* funky is set to indicate note or instrument change */
2075
for (mp_channel=0;mp_channel<pf->numchn;mp_channel++) {
2076
a=&pf->control[mp_channel];
2078
if (pf->sngpos>=pf->numpos) {
2082
tr=pf->patterns[(pf->positions[pf->sngpos]*pf->numchn)+mp_channel];
2083
pf->numrow=pf->pattrows[pf->positions[pf->sngpos]];
2086
a->row=(tr<pf->numtrk)?UniFindRow(pf->tracks[tr],pf->patpos):NULL;
2088
if (!pf->vbtick) a->notedelay=0;
2090
if (!a->row) continue;
2094
while((c=UniGetByte()))
2098
a->oldnote=a->anote,a->anote=UniGetByte();
2103
/* retrig tremolo and vibrato waves ? */
2104
if (!(a->wavecontrol & 0x80)) a->trmpos=0;
2105
if (!(a->wavecontrol & 0x08)) a->vibpos=0;
2106
if (!a->panbwave) a->panbpos=0;
2108
case UNI_INSTRUMENT:
2110
if (inst>=pf->numins) break; /* safety valve */
2112
a->i=(pf->flags & UF_INST)?&pf->instruments[inst]:NULL;
2128
if (i->samplenumber[a->anote] >= pf->numsmp) continue;
2129
s=&pf->samples[i->samplenumber[a->anote]];
2130
a->note=i->samplenote[a->anote];
2133
s=&pf->samples[a->sample];
2138
a->newsamp=a->period;
2141
/* channel or instrument determined panning ? */
2142
a->panning=pf->panning[mp_channel];
2143
if (s->flags & SF_OWNPAN)
2144
a->panning=s->panning;
2145
else if ((i)&&(i->flags & IF_OWNPAN))
2146
a->panning=i->panning;
2148
a->handle=s->handle;
2152
if ((pf->panflag)&&(i->flags & IF_PITCHPAN)
2153
&&(a->panning!=PAN_SURROUND)){
2154
a->panning+=((a->anote-i->pitpancenter)*i->pitpansep)/8;
2155
if (a->panning<PAN_LEFT) a->panning=PAN_LEFT;
2156
else if (a->panning>PAN_RIGHT) a->panning=PAN_RIGHT;
2158
a->pitflg=i->pitflg;
2159
a->volflg=i->volflg;
2160
a->panflg=i->panflg;
2173
if (funky&2) /* instrument change */ {
2174
/* IT random volume variations: 0:8 bit fixed, and one bit for
2176
a->volume=a->tmpvolume=s->volume;
2179
a->volume=a->tmpvolume=s->volume+
2180
((s->volume*((SLONG)i->rvolvar*(SLONG)getrandom(512)
2182
if (a->volume<0) a->volume=a->tmpvolume=0;
2183
else if (a->volume>64) a->volume=a->tmpvolume=64;
2185
if ((pf->panflag)&&(a->panning!=PAN_SURROUND)) {
2186
a->panning+=((a->panning*((SLONG)i->rpanvar*
2187
(SLONG)getrandom(512)))/25600);
2188
if (a->panning<PAN_LEFT) a->panning=PAN_LEFT;
2189
else if (a->panning>PAN_RIGHT) a->panning=PAN_RIGHT;
2194
a->wantedperiod=a->tmpperiod=GetPeriod((UWORD)a->note<<1,a->speed);
2200
/* Handles effects */
2201
void pt_EffectsPass1(void)
2205
for (mp_channel=0;mp_channel<pf->numchn;mp_channel++) {
2206
a=&pf->control[mp_channel];
2208
if ((aout=a->slave)) {
2209
a->fadevol=aout->fadevol;
2210
a->period=aout->period;
2211
if (a->kick==KICK_KEYOFF) a->keyoff=aout->keyoff;
2214
if (!a->row) continue;
2217
a->ownper=a->ownvol=0;
2221
/* continue volume slide if necessary for XM and IT */
2222
if (pf->flags&UF_BGSLIDES) {
2223
if (!explicitslides)
2224
switch (a->sliding) {
2232
else if (a->tmpvolume) a->sliding=explicitslides;
2235
if (!a->ownper) a->period=a->tmpperiod;
2236
if (!a->ownvol) a->volume=a->tmpvolume;
2240
a->outvolume=(a->volume*a->s->globvol*a->i->globvol)>>10;
2242
a->outvolume=(a->volume*a->s->globvol)>>4;
2243
if (a->outvolume>256)a->volume=256;
2244
else if (a->outvolume<0) a->outvolume=0;
2249
/* NNA management */
2252
for (mp_channel=0;mp_channel<pf->numchn;mp_channel++) {
2253
a=&pf->control[mp_channel];
2255
if (a->kick==KICK_NOTE) {
2262
if (aout->nna & NNA_MASK) {
2263
/* Make sure the old MP_VOICE channel knows it has no
2266
/* assume the channel is taken by NNA */
2269
switch (aout->nna) {
2270
case NNA_CONTINUE: /* continue note, do nothing */
2272
case NNA_OFF: /* note off */
2273
aout->keyoff|=KEY_OFF;
2274
if ((!(aout->volflg & EF_ON))||(aout->volflg & EF_LOOP))
2275
aout->keyoff=KEY_KILL;
2278
aout->keyoff |= KEY_FADE;
2284
if (a->dct!=DCT_OFF) {
2287
for (t=0;t<md_sngchn;t++)
2288
if ((!Voice_Stopped_internal(t))&&
2289
(pf->voice[t].masterchn==mp_channel)&&
2290
(a->sample==pf->voice[t].sample)) {
2294
if (a->note==pf->voice[t].note)
2298
if (a->handle==pf->voice[t].handle)
2308
pf->voice[t].fadevol=0;
2311
pf->voice[t].keyoff|=KEY_OFF;
2312
if ((!(pf->voice[t].volflg&EF_ON))||
2313
(pf->voice[t].volflg&EF_LOOP))
2314
pf->voice[t].keyoff=KEY_KILL;
2317
pf->voice[t].keyoff|=KEY_FADE;
2322
} /* if (a->kick==KICK_NOTE) */
2326
/* Setup module and NNA voices */
2327
void pt_SetupVoices(void)
2331
for (mp_channel=0;mp_channel<pf->numchn;mp_channel++) {
2332
a=&pf->control[mp_channel];
2334
if (a->notedelay) continue;
2335
if (a->kick==KICK_NOTE) {
2336
/* if no channel was cut above, find an empty or quiet channel
2338
if (pf->flags&UF_NNA) {
2342
if ((newchn=MP_FindEmptyChannel())!=-1)
2343
a->slave=&pf->voice[a->slavechn=newchn];
2346
a->slave=&pf->voice[a->slavechn=mp_channel];
2348
/* assign parts of MP_VOICE only done for a KICK ! */
2349
if ((aout=a->slave)) {
2350
if (aout->mflag && aout->master) aout->master->slave=NULL;
2353
aout->masterchn=mp_channel;
2363
aout->sample=a->sample;
2364
aout->handle=a->handle;
2365
aout->period=a->period;
2366
aout->panning=a->panning;
2367
aout->chanvol=a->chanvol;
2368
aout->fadevol=a->fadevol;
2369
aout->start=a->start;
2370
aout->volflg=a->volflg;
2371
aout->panflg=a->panflg;
2372
aout->pitflg=a->pitflg;
2373
aout->volume=a->outvolume;
2374
aout->keyoff=a->keyoff;
2378
a->kick=KICK_ABSENT;
2382
/* second effect pass */
2383
void pt_EffectsPass2(void)
2387
for (mp_channel=0;mp_channel<pf->numchn;mp_channel++) {
2388
a=&pf->control[mp_channel];
2390
if (!a->row) continue;
2393
while((c=UniGetByte()))
2394
if (c==UNI_ITEFFECTS0) {
2396
if ((c>>4)==SS_S7EFFECTS)
2397
DoNNAEffects(c&0xf);
2403
void Player_HandleTick(void)
2408
/* don't handle the very first ticks, this allows the other hardware to
2409
settle down so we don't loose any starting notes */
2416
if ((!pf)||(pf->forbid)||(pf->sngpos>=pf->numpos)) return;
2418
/* update time counter (sngtime is in milliseconds (in fact 2^-10)) */
2419
pf->sngremainder+=(1<<9)*5; /* thus 2.5*(1<<10), since fps=0.4xtempo */
2420
pf->sngtime+=pf->sngremainder/pf->bpm;
2421
pf->sngremainder%=pf->bpm;
2423
if (++pf->vbtick>=pf->sngspd) {
2424
if (pf->pat_repcrazy)
2425
pf->pat_repcrazy=0; /* play 2 times row 0 */
2430
/* process pattern-delay. pf->patdly2 is the counter and pf->patdly is
2431
the command memory. */
2433
pf->patdly2=pf->patdly,pf->patdly=0;
2435
/* patterndelay active */
2437
/* so turn back pf->patpos by 1 */
2438
if (pf->patpos) pf->patpos--;
2441
/* do we have to get a new patternpointer ? (when pf->patpos reaches the
2442
pattern size, or when a patternbreak is active) */
2443
if (((pf->patpos>=pf->numrow)&&(pf->numrow>0))&&(!pf->posjmp))
2447
pf->patpos=pf->numrow?(pf->patbrk%pf->numrow):0;
2449
pf->sngpos+=(pf->posjmp-2);
2450
for (mp_channel=0;mp_channel<pf->numchn;mp_channel++)
2451
pf->control[mp_channel].pat_reppos=-1;
2453
pf->patbrk=pf->posjmp=0;
2454
/* handle the "---" (end of song) pattern since it can occur
2455
*inside* the module in .IT and .S3M */
2456
if ((pf->sngpos>=pf->numpos)||(pf->positions[pf->sngpos]==255)) {
2457
if (!pf->wrap) return;
2458
if (!(pf->sngpos=pf->reppos)) {
2459
pf->volume=pf->initvolume>128?128:pf->initvolume;
2460
pf->sngspd=pf->initspeed?(pf->initspeed<32?pf->initspeed:32):6;
2461
pf->bpm=pf->inittempo<32?32:pf->inittempo;
2464
if (pf->sngpos<0) pf->sngpos=pf->numpos-1;
2471
if (((pf->sngpos==pf->numpos-1)||(pf->positions[pf->sngpos+1]==255))&&
2473
max_volume=pf->numrow?((pf->numrow-pf->patpos)*128)/pf->numrow:0;
2478
if (pf->flags&UF_NNA)
2483
/* now set up the actual hardware channel playback information */
2484
pt_UpdateVoices(max_volume);
2487
static void Player_Init_internal(MODULE* mf)
2491
for (t=0;t<mf->numchn;t++) {
2492
mf->control[t].chanvol=mf->chanvol[t];
2493
mf->control[t].panning=mf->panning[t];
2501
mf->sngspd=mf->initspeed?(mf->initspeed<32?mf->initspeed:32):6;
2502
mf->volume=mf->initvolume>128?128:mf->initvolume;
2504
mf->vbtick=mf->sngspd;
2507
mf->bpm=mf->inittempo<32?32:mf->inittempo;
2511
mf->posjmp=2; /* make sure the player fetches the first note */
2516
BOOL Player_Init(MODULE* mf)
2526
/* make sure the player doesn't start with garbage */
2527
if (!(mf->control=(MP_CONTROL*)_mm_calloc(mf->numchn,sizeof(MP_CONTROL))))
2529
if (!(mf->voice=(MP_VOICE*)_mm_calloc(md_sngchn,sizeof(MP_VOICE))))
2532
Player_Init_internal(mf);
2536
void Player_Exit_internal(MODULE* mf)
2540
Player_Stop_internal();
2543
if (mf->control) free(mf->control);
2544
if (mf->voice) free(mf->voice);
2549
void Player_Exit(MODULE* mf)
2552
Player_Exit_internal(mf);
2556
void Player_SetVolume(SWORD volume)
2560
pf->volume=pf->initvolume=(volume<0)?0:(volume>128)?128:volume;
2564
MODULE* Player_GetModule(void)
2575
void Player_Start(MODULE *mf)
2581
if (!MikMod_Active())
2582
MikMod_EnableOutput();
2588
/* new song is being started, so completely stop out the old one. */
2589
if (pf) pf->forbid=1;
2590
for (t=0;t<md_sngchn;t++) Voice_Stop_internal(t);
2596
void Player_Stop_internal(void)
2598
if (!md_sfxchn) MikMod_DisableOutput_internal();
2599
if (pf) pf->forbid=1;
2603
void Player_Stop(void)
2606
Player_Stop_internal();
2610
BOOL Player_Active(void)
2616
result=(!(pf->sngpos>=pf->numpos));
2622
void Player_NextPosition(void)
2631
pf->vbtick=pf->sngspd;
2633
for (t=0;t<md_sngchn;t++) {
2634
Voice_Stop_internal(t);
2635
pf->voice[t].i=NULL;
2636
pf->voice[t].s=NULL;
2638
for (t=0;t<pf->numchn;t++) {
2639
pf->control[t].i=NULL;
2640
pf->control[t].s=NULL;
2647
void Player_PrevPosition(void)
2656
pf->vbtick=pf->sngspd;
2658
for (t=0;t<md_sngchn;t++) {
2659
Voice_Stop_internal(t);
2660
pf->voice[t].i=NULL;
2661
pf->voice[t].s=NULL;
2663
for (t=0;t<pf->numchn;t++) {
2664
pf->control[t].i=NULL;
2665
pf->control[t].s=NULL;
2672
void Player_SetPosition(UWORD pos)
2679
if (pos>=pf->numpos) pos=pf->numpos;
2683
pf->vbtick=pf->sngspd;
2685
for (t=0;t<md_sngchn;t++) {
2686
Voice_Stop_internal(t);
2687
pf->voice[t].i=NULL;
2688
pf->voice[t].s=NULL;
2690
for (t=0;t<pf->numchn;t++) {
2691
pf->control[t].i=NULL;
2692
pf->control[t].s=NULL;
2697
Player_Init_internal(pf);
2702
static void Player_Unmute_internal(SLONG arg1,va_list ap)
2704
SLONG t,arg2,arg3=0;
2708
case MUTE_INCLUSIVE:
2709
if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
2710
(arg2>arg3)||(arg3>=pf->numchn))
2712
for (;arg2<pf->numchn && arg2<=arg3;arg2++)
2713
pf->control[arg2].muted=0;
2715
case MUTE_EXCLUSIVE:
2716
if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
2717
(arg2>arg3)||(arg3>=pf->numchn))
2719
for (t=0;t<pf->numchn;t++) {
2720
if ((t>=arg2) && (t<=arg3)) continue;
2721
pf->control[t].muted=0;
2725
if (arg1<pf->numchn) pf->control[arg1].muted=0;
2731
void Player_Unmute(SLONG arg1, ...)
2735
va_start(args,arg1);
2737
Player_Unmute_internal(arg1,args);
2742
static void Player_Mute_internal(SLONG arg1,va_list ap)
2744
SLONG t,arg2,arg3=0;
2748
case MUTE_INCLUSIVE:
2749
if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
2750
(arg2>arg3)||(arg3>=pf->numchn))
2752
for (;arg2<pf->numchn && arg2<=arg3;arg2++)
2753
pf->control[arg2].muted=1;
2755
case MUTE_EXCLUSIVE:
2756
if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
2757
(arg2>arg3)||(arg3>=pf->numchn))
2759
for (t=0;t<pf->numchn;t++) {
2760
if ((t>=arg2) && (t<=arg3)) continue;
2761
pf->control[t].muted=1;
2765
if (arg1<pf->numchn)
2766
pf->control[arg1].muted=1;
2772
void Player_Mute(SLONG arg1,...)
2776
va_start(args,arg1);
2778
Player_Mute_internal(arg1,args);
2783
static void Player_ToggleMute_internal(SLONG arg1,va_list ap)
2790
case MUTE_INCLUSIVE:
2791
if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
2792
(arg2>arg3)||(arg3>=pf->numchn))
2794
for (;arg2<pf->numchn && arg2<=arg3;arg2++)
2795
pf->control[arg2].muted=1-pf->control[arg2].muted;
2797
case MUTE_EXCLUSIVE:
2798
if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
2799
(arg2>arg3)||(arg3>=pf->numchn))
2801
for (t=0;t<pf->numchn;t++) {
2802
if ((t>=arg2) && (t<=arg3)) continue;
2803
pf->control[t].muted=1-pf->control[t].muted;
2807
if (arg1<pf->numchn)
2808
pf->control[arg1].muted=1-pf->control[arg1].muted;
2814
void Player_ToggleMute(SLONG arg1,...)
2818
va_start(args,arg1);
2820
Player_ToggleMute_internal(arg1,args);
2825
BOOL Player_Muted(UBYTE chan)
2831
result=(chan<pf->numchn)?pf->control[chan].muted:1;
2837
int Player_GetChannelVoice(UBYTE chan)
2843
result=(chan<pf->numchn)?pf->control[chan].slavechn:-1;
2849
UWORD Player_GetChannelPeriod(UBYTE chan)
2855
result=(chan<pf->numchn)?pf->control[chan].period:0;
2861
BOOL Player_Paused_internal(void)
2863
return pf?pf->forbid:1;
2866
BOOL Player_Paused(void)
2871
result=Player_Paused_internal();
2877
void Player_TogglePause(void)
2881
pf->forbid=1-pf->forbid;
2885
void Player_SetSpeed(UWORD speed)
2889
pf->sngspd=speed?(speed<32?speed:32):1;
2893
void Player_SetTempo(UWORD tempo)
2895
if (tempo<32) tempo=32;
2899
if ((!(pf->flags&UF_HIGHBPM))&&(tempo>255)) tempo=255;
2905
static int _pl_synchro_value;
2906
void Player_SetSynchroValue(int i)
2908
_pl_synchro_value = i;
2911
int Player_GetSynchroValue(void)
2913
return _pl_synchro_value;