~armagetronad-dev/armagetronad/0.2.9-winlibs-work

« back to all changes in this revision

Viewing changes to SDL_mixer/mikmod/mplayer.c

  • Committer: luke-jr
  • Date: 2006-05-29 01:55:42 UTC
  • Revision ID: svn-v3-list-QlpoOTFBWSZTWZvbKhsAAAdRgAAQABK6798QIABURMgAAaeoNT1TxT1DQbKaeobXKiyAmlWT7Y5MkdJOtXDtB7w7DOGFBHiOBxaUIu7HQyyQSvxdyRThQkJvbKhs:7d95bf1e-0414-0410-9756-b78462a59f44:armagetronad%2Fbranches%2F0.2.8%2Fwinlibs:4612
Unify tags/branches of modules released together

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*      MikMod sound library
 
2
        (c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
 
3
        complete list.
 
4
 
 
5
        This library is free software; you can redistribute it and/or modify
 
6
        it under the terms of the GNU Library General Public License as
 
7
        published by the Free Software Foundation; either version 2 of
 
8
        the License, or (at your option) any later version.
 
9
 
 
10
        This program is distributed in the hope that it will be useful,
 
11
        but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
        GNU Library General Public License for more details.
 
14
 
 
15
        You should have received a copy of the GNU Library General Public
 
16
        License along with this library; if not, write to the Free Software
 
17
        Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
18
        02111-1307, USA.
 
19
*/
 
20
 
 
21
/*==============================================================================
 
22
 
 
23
  $Id$
 
24
 
 
25
  The Protracker Player Driver
 
26
 
 
27
  The protracker driver supports all base Protracker 3.x commands and features.
 
28
 
 
29
==============================================================================*/
 
30
 
 
31
#ifdef HAVE_CONFIG_H
 
32
#include "config.h"
 
33
#endif
 
34
 
 
35
#include <string.h>
 
36
#include <stdarg.h>
 
37
#ifdef SUNOS
 
38
extern long int random(void);
 
39
#endif
 
40
#ifdef SRANDOM_IN_MATH_H
 
41
#include <math.h>
 
42
#else
 
43
#include <stdlib.h>
 
44
#endif
 
45
 
 
46
#include "mikmod_internals.h"
 
47
 
 
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. */
 
51
 
 
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;
 
56
 
 
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
 
62
};
 
63
 
 
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
 
67
};
 
68
 
 
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
 
78
};
 
79
 
 
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
 
178
};
 
179
 
 
180
#define LOGFAC 2*16
 
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
 
208
};
 
209
 
 
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
 
227
};
 
228
 
 
229
/* returns a random value between 0 and ceil-1, ceil must be a power of two */
 
230
static int getrandom(int ceil)
 
231
{
 
232
#ifdef HAVE_SRANDOM
 
233
        return random()&(ceil-1);
 
234
#else
 
235
        return (int)((rand()*ceil)/(RAND_MAX+1.0));
 
236
#endif
 
237
}
 
238
 
 
239
/*      New Note Action Scoring System :
 
240
        --------------------------------
 
241
1)      total-volume (fadevol, chanvol, volume) is the main scorer.
 
242
2)      a looping sample is a bonus x2
 
243
3)      a foreground channel is a bonus x4
 
244
4)      an active envelope with keyoff is a handicap -x2                          */
 
245
static int MP_FindEmptyChannel(void)
 
246
{
 
247
        MP_VOICE *a;
 
248
        ULONG t,k,tvol,pp;
 
249
 
 
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))
 
253
                        return t;
 
254
 
 
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))
 
260
                                pp<<=2;
 
261
 
 
262
                        if (pp<tvol) {
 
263
                                tvol=pp;
 
264
                                t=k;
 
265
                        }
 
266
                }
 
267
 
 
268
        if (tvol>8000*7) return -1;
 
269
        return t;
 
270
}
 
271
 
 
272
static SWORD Interpolate(SWORD p,SWORD p1,SWORD p2,SWORD v1,SWORD v2)
 
273
{
 
274
        if ((p1==p2)||(p==p1)) return v1;
 
275
        return v1+((SLONG)((p-p1)*(v2-v1))/(p2-p1));
 
276
}
 
277
 
 
278
UWORD getlinearperiod(UWORD note,ULONG fine)
 
279
{
 
280
        UWORD t;
 
281
 
 
282
        t=(20L*OCTAVE+2-note)*32L-(fine>>1);
 
283
        return t;
 
284
}
 
285
 
 
286
static UWORD getlogperiod(UWORD note,ULONG fine)
 
287
{
 
288
        UWORD n,o;
 
289
        UWORD p1,p2;
 
290
        ULONG i;
 
291
 
 
292
        n=note%(2*OCTAVE);
 
293
        o=note/(2*OCTAVE);
 
294
        i=(n<<2)+(fine>>4); /* n*8 + fine/16 */
 
295
 
 
296
        p1=logtab[i];
 
297
        p2=logtab[i+1];
 
298
 
 
299
        return (Interpolate(fine>>4,0,15,p1,p2)>>o);
 
300
}
 
301
 
 
302
static UWORD getoldperiod(UWORD note,ULONG speed)
 
303
{
 
304
        UWORD n,o;
 
305
 
 
306
        if (!speed) {
 
307
#ifdef MIKMOD_DEBUG
 
308
                fprintf(stderr,"\rmplayer: getoldperiod() called with note=%d, speed=0 !\n",note);
 
309
#endif
 
310
                return 4242; /* <- prevent divide overflow.. (42 hehe) */
 
311
        }
 
312
 
 
313
        n=note%(2*OCTAVE);
 
314
        o=note/(2*OCTAVE);
 
315
        return ((8363L*(ULONG)oldperiods[n])>>o)/speed;
 
316
}
 
317
 
 
318
static UWORD GetPeriod(UWORD note,ULONG speed)
 
319
{
 
320
        if (pf->flags & UF_XMPERIODS)
 
321
                return (pf->flags&UF_LINEAR)?getlinearperiod(note,speed):getlogperiod(note,speed);
 
322
 
 
323
        return getoldperiod(note,speed);
 
324
}
 
325
 
 
326
static SWORD InterpolateEnv(SWORD p,ENVPT *a,ENVPT *b)
 
327
{
 
328
        return (Interpolate(p,a->pos,b->pos,a->val,b->val));
 
329
}
 
330
 
 
331
static SWORD DoPan(SWORD envpan,SWORD pan)
 
332
{
 
333
        int newpan;
 
334
 
 
335
        newpan=pan+(((envpan-PAN_CENTER)*(128-abs(pan-PAN_CENTER)))/128);
 
336
 
 
337
        return (newpan<PAN_LEFT)?PAN_LEFT:(newpan>PAN_RIGHT?PAN_RIGHT:newpan);
 
338
}
 
339
 
 
340
static void StartEnvelope(ENVPR *t,UBYTE flg,UBYTE pts,UBYTE susbeg,UBYTE susend,UBYTE beg,UBYTE end,ENVPT *p,UBYTE keyoff)
 
341
{
 
342
        t->flg=flg;
 
343
        t->pts=pts;
 
344
        t->susbeg=susbeg;
 
345
        t->susend=susend;
 
346
        t->beg=beg;
 
347
        t->end=end;
 
348
        t->env=p;
 
349
        t->p=0;
 
350
        t->a=0;
 
351
        t->b=((t->flg&EF_SUSTAIN)&&(!(keyoff&KEY_OFF)))?0:1;
 
352
 
 
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)) {
 
355
                t->a++;t->b++;
 
356
        }
 
357
 
 
358
        if (t->b>=t->pts) t->b=t->pts-1;
 
359
}
 
360
 
 
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
 
364
   position.
 
365
 
 
366
   Envelopes work in the following manner:
 
367
 
 
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
 
370
       interpolated.
 
371
 
 
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.
 
375
 
 
376
   Misc:
 
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)
 
380
{
 
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 */
 
384
 
 
385
                a=t->a;
 
386
                b=t->b;
 
387
                p=t->p;
 
388
 
 
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;
 
394
                else {
 
395
                        /* compute the current envelope value between points a and b */
 
396
                        if (a==b)
 
397
                                v=t->env[a].val;
 
398
                        else
 
399
                                v=InterpolateEnv(p,&t->env[a],&t->env[b]);
 
400
 
 
401
                        p++;
 
402
                        /* pointer reached point b? */
 
403
                        if (p>=t->env[b].pos) {
 
404
                                a=b++; /* shift points a and b */
 
405
 
 
406
                                /* Check for loops, sustain loops, or end of envelope. */
 
407
                                if ((t->flg&EF_SUSTAIN)&&(!(keyoff&KEY_OFF))&&(b>t->susend)) {
 
408
                                        a=t->susbeg;
 
409
                                        b=(t->susbeg==t->susend)?a:a+1;
 
410
                                        p=t->env[a].pos;
 
411
                                } else
 
412
                                  if ((t->flg & EF_LOOP)&&(b>t->end)) {
 
413
                                        a=t->beg;
 
414
                                        b=(t->beg==t->end)?a:a+1;
 
415
                                        p=t->env[a].pos;
 
416
                                } else {
 
417
                                        if (b>=t->pts) {
 
418
                                                if ((t->flg & EF_VOLENV)&&(mp_channel!=-1)) {
 
419
                                                        pf->voice[mp_channel].keyoff|=KEY_FADE;
 
420
                                                        if (!v)
 
421
                                                                pf->voice[mp_channel].fadevol=0;
 
422
                                                }
 
423
                                                b--;p--;
 
424
                                        }
 
425
                                }
 
426
                        }
 
427
                        t->a=a;
 
428
                        t->b=b;
 
429
                        t->p=p;
 
430
                }
 
431
        }
 
432
        return v;
 
433
}
 
434
 
 
435
/* XM linear period to frequency conversion */
 
436
ULONG getfrequency(UBYTE flags,ULONG period)
 
437
{
 
438
        if (flags & UF_LINEAR)
 
439
                return lintab[period%768]>>(period/768);
 
440
        else
 
441
                return (8363L*1712L)/(period?period:1);
 
442
}
 
443
 
 
444
/*========== Protracker effects */
 
445
 
 
446
static void DoEEffects(UBYTE dat)
 
447
{
 
448
        UBYTE nib=dat&0xf;
 
449
 
 
450
        switch (dat>>4) {
 
451
                case 0x0: /* hardware filter toggle, not supported */
 
452
                        break;
 
453
                case 0x1: /* fineslide up */
 
454
                        if (a->period)
 
455
                                if (!pf->vbtick) a->tmpperiod-=(nib<<2);
 
456
                        break;
 
457
                case 0x2: /* fineslide dn */
 
458
                        if (a->period)
 
459
                                if (!pf->vbtick) a->tmpperiod+=(nib<<2);
 
460
                        break;
 
461
                case 0x3: /* glissando ctrl */
 
462
                        a->glissando=nib;
 
463
                        break;
 
464
                case 0x4: /* set vibrato waveform */
 
465
                        a->wavecontrol&=0xf0;
 
466
                        a->wavecontrol|=nib;
 
467
                        break;
 
468
                case 0x5: /* set finetune */
 
469
                        if (a->period) {
 
470
                                if (pf->flags&UF_XMPERIODS)
 
471
                                        a->speed=nib+128;
 
472
                                else
 
473
                                        a->speed=finetune[nib];
 
474
                                a->tmpperiod=GetPeriod((UWORD)a->note<<1,a->speed);
 
475
                        }
 
476
                        break;
 
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 */
 
482
                                if (a->pat_repcnt)
 
483
                                        a->pat_repcnt--; /* already looping, decrease counter */
 
484
                                else {
 
485
#if 0
 
486
                                        /* this would make walker.xm, shipped with Xsoundtracker,
 
487
                                           play correctly, but it's better to remain compatible
 
488
                                           with FT2 */
 
489
                                        if ((!(pf->flags&UF_NOWRAP))||(a->pat_reppos!=POS_NONE))
 
490
#endif
 
491
                                                a->pat_repcnt=nib; /* not yet looping, so set repcnt */
 
492
                                }
 
493
 
 
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) {
 
498
                                                pf->pat_repcrazy=1;
 
499
                                                pf->patpos=0;
 
500
                                        } else
 
501
                                                pf->patpos=a->pat_reppos;
 
502
                                } else a->pat_reppos=POS_NONE;
 
503
                        } else
 
504
                                a->pat_reppos=pf->patpos-1; /* set reppos - can be (-1) */
 
505
                        break;
 
506
                case 0x7: /* set tremolo waveform */
 
507
                        a->wavecontrol&=0x0f;
 
508
                        a->wavecontrol|=nib<<4;
 
509
                        break;
 
510
                case 0x8: /* set panning */
 
511
                        if (pf->panflag) {
 
512
                                if (nib<=8) nib<<=4;
 
513
                                else nib*=17;
 
514
                                a->panning=pf->panning[mp_channel]=nib;
 
515
                        }
 
516
                        break;
 
517
                case 0x9: /* retrig note */
 
518
                        /* only retrigger if data nibble > 0 */
 
519
                        if (nib) {
 
520
                                if (!a->retrig) {
 
521
                                        /* when retrig counter reaches 0, reset counter and restart
 
522
                                           the sample */
 
523
                                        if (a->period) a->kick=KICK_NOTE;
 
524
                                        a->retrig=nib;
 
525
                                }
 
526
                                a->retrig--; /* countdown */
 
527
                        }
 
528
                        break;
 
529
                case 0xa: /* fine volume slide up */
 
530
                        if (pf->vbtick) break;
 
531
                        a->tmpvolume+=nib;
 
532
                        if (a->tmpvolume>64) a->tmpvolume=64;
 
533
                        break;
 
534
                case 0xb: /* fine volume slide dn  */
 
535
                        if (pf->vbtick) break;
 
536
                        a->tmpvolume-=nib;
 
537
                        if (a->tmpvolume<0) a->tmpvolume=0;
 
538
                        break;
 
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) */
 
542
                        if (pf->vbtick>=nib)
 
543
                                a->tmpvolume=0; /* just turn the volume down */
 
544
                        break;
 
545
                case 0xd: /* note delay */
 
546
                        /* delay the start of the sample until pf->vbtick==nib */
 
547
                        if (!pf->vbtick)
 
548
                                a->notedelay=nib;
 
549
                        else if (a->notedelay)
 
550
                                a->notedelay--;
 
551
                        break;
 
552
                case 0xe: /* pattern delay */
 
553
                        if (pf->vbtick) break;
 
554
                        if (!pf->patdly2) pf->patdly=nib+1; /* only once, when vbtick=0 */
 
555
                        break;
 
556
                case 0xf: /* invert loop, not supported  */
 
557
                        break;
 
558
        }
 
559
}
 
560
 
 
561
static void DoVibrato(void)
 
562
{
 
563
        UBYTE q;
 
564
        UWORD temp=0;
 
565
 
 
566
        q=(a->vibpos>>2)&0x1f;
 
567
 
 
568
        switch (a->wavecontrol&3) {
 
569
                case 0: /* sine */
 
570
                        temp=VibratoTable[q];
 
571
                        break;
 
572
                case 1: /* ramp down */
 
573
                        q<<=3;
 
574
                        if (a->vibpos<0) q=255-q;
 
575
                        temp=q;
 
576
                        break;
 
577
                case 2: /* square wave */
 
578
                        temp=255;
 
579
                        break;
 
580
                case 3: /* random wave */
 
581
                        temp=getrandom(256);
 
582
                        break;
 
583
        }
 
584
 
 
585
        temp*=a->vibdepth;
 
586
        temp>>=7;temp<<=2;
 
587
 
 
588
        if (a->vibpos>=0)
 
589
                a->period=a->tmpperiod+temp;
 
590
        else
 
591
                a->period=a->tmpperiod-temp;
 
592
 
 
593
        if (pf->vbtick) a->vibpos+=a->vibspd;
 
594
}
 
595
 
 
596
static void DoTremolo(void)
 
597
{
 
598
        UBYTE q;
 
599
        UWORD temp=0;
 
600
 
 
601
        q=(a->trmpos>>2)&0x1f;
 
602
 
 
603
        switch ((a->wavecontrol>>4)&3) {
 
604
                case 0: /* sine */
 
605
                        temp=VibratoTable[q];
 
606
                        break;
 
607
                case 1: /* ramp down */
 
608
                        q<<=3;
 
609
                        if (a->trmpos<0) q=255-q;
 
610
                        temp=q;
 
611
                        break;
 
612
                case 2: /* square wave */
 
613
                        temp=255;
 
614
                        break;
 
615
                case 3: /* random wave */
 
616
                        temp=getrandom(256);
 
617
                        break;
 
618
        }
 
619
        temp*=a->trmdepth;
 
620
        temp>>=6;
 
621
 
 
622
        if (a->trmpos>=0) {
 
623
                a->volume=a->tmpvolume+temp;
 
624
                if (a->volume>64) a->volume=64;
 
625
        } else {
 
626
                a->volume=a->tmpvolume-temp;
 
627
                if (a->volume<0) a->volume=0;
 
628
        }
 
629
 
 
630
        if (pf->vbtick) a->trmpos+=a->trmspd;
 
631
}
 
632
 
 
633
static void DoVolSlide(UBYTE dat)
 
634
{
 
635
        if (!pf->vbtick) return;
 
636
 
 
637
        if (dat&0xf) {
 
638
                a->tmpvolume-=(dat&0x0f);
 
639
                if (a->tmpvolume<0) a->tmpvolume=0;
 
640
        } else {
 
641
                a->tmpvolume+=(dat>>4);
 
642
                if (a->tmpvolume>64) a->tmpvolume=64;
 
643
        }
 
644
}
 
645
 
 
646
static void DoToneSlide(void)
 
647
{
 
648
        if (pf->vbtick) {
 
649
                int dist;
 
650
 
 
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;
 
654
 
 
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;
 
659
                else if (dist>0) {
 
660
                        a->tmpperiod-=a->portspeed;
 
661
                        a->period-=a->portspeed; /* dist>0, slide up */
 
662
                } else {
 
663
                        a->tmpperiod+=a->portspeed;
 
664
                        a->period+=a->portspeed; /* dist<0, slide down */
 
665
                }
 
666
        } else
 
667
                a->tmpperiod=a->period;
 
668
}
 
669
 
 
670
static void DoArpeggio(UBYTE dat)
 
671
{
 
672
        UBYTE note=a->note;
 
673
 
 
674
        if (dat) {
 
675
                switch (pf->vbtick%3) {
 
676
                        case 1:
 
677
                                note+=(dat>>4);  break;
 
678
                        case 2:
 
679
                                note+=(dat&0xf); break;
 
680
                }
 
681
                a->period=GetPeriod((UWORD)note<<1,a->speed);
 
682
                a->ownper=1;
 
683
        }
 
684
}
 
685
 
 
686
/*========== Scream Tracker effects */
 
687
 
 
688
static void DoS3MVolSlide(UBYTE inf)
 
689
{
 
690
        UBYTE lo, hi;
 
691
 
 
692
        explicitslides=1;
 
693
 
 
694
        if (inf) a->s3mvolslide=inf;
 
695
        else inf=a->s3mvolslide;
 
696
 
 
697
        lo=inf&0xf;
 
698
        hi=inf>>4;
 
699
 
 
700
        if (!lo) {
 
701
                if ((pf->vbtick)||(pf->flags&UF_S3MSLIDES)) a->tmpvolume+=hi;
 
702
        } else
 
703
          if (!hi) {
 
704
                if ((pf->vbtick)||(pf->flags&UF_S3MSLIDES)) a->tmpvolume-=lo;
 
705
        } else
 
706
          if (lo==0xf) {
 
707
                if (!pf->vbtick) a->tmpvolume+=(hi?hi:0xf);
 
708
        } else
 
709
          if (hi==0xf) {
 
710
                if (!pf->vbtick) a->tmpvolume-=(lo?lo:0xf);
 
711
        } else
 
712
          return;
 
713
 
 
714
        if (a->tmpvolume<0) a->tmpvolume=0;
 
715
        else if (a->tmpvolume>64) a->tmpvolume=64;
 
716
}
 
717
 
 
718
static void DoS3MSlideDn(UBYTE inf)
 
719
{
 
720
        UBYTE hi,lo;
 
721
 
 
722
        if (inf) a->slidespeed=inf;
 
723
        else inf=a->slidespeed;
 
724
 
 
725
        hi=inf>>4;
 
726
        lo=inf&0xf;
 
727
 
 
728
        if (hi==0xf) {
 
729
                if (!pf->vbtick) a->tmpperiod+=(UWORD)lo<<2;
 
730
        } else
 
731
          if (hi==0xe) {
 
732
                if (!pf->vbtick) a->tmpperiod+=lo;
 
733
        } else {
 
734
                if (pf->vbtick) a->tmpperiod+=(UWORD)inf<<2;
 
735
        }
 
736
}
 
737
 
 
738
static void DoS3MSlideUp(UBYTE inf)
 
739
{
 
740
        UBYTE hi,lo;
 
741
 
 
742
        if (inf) a->slidespeed=inf;
 
743
        else inf=a->slidespeed;
 
744
 
 
745
        hi=inf>>4;
 
746
        lo=inf&0xf;
 
747
 
 
748
        if (hi==0xf) {
 
749
                if (!pf->vbtick) a->tmpperiod-=(UWORD)lo<<2;
 
750
        } else
 
751
          if (hi==0xe) {
 
752
                if (!pf->vbtick) a->tmpperiod-=lo;
 
753
        } else {
 
754
                if (pf->vbtick) a->tmpperiod-=(UWORD)inf<<2;
 
755
        }
 
756
}
 
757
 
 
758
static void DoS3MTremor(UBYTE inf)
 
759
{
 
760
        UBYTE on,off;
 
761
 
 
762
        if (inf)
 
763
                a->s3mtronof=inf;
 
764
        else {
 
765
                inf=a->s3mtronof;
 
766
                if (!inf) return;
 
767
        }
 
768
 
 
769
        if (!pf->vbtick) return;
 
770
 
 
771
        on=(inf>>4)+1;
 
772
        off=(inf&0xf)+1;
 
773
        a->s3mtremor%=(on+off);
 
774
        a->volume=(a->s3mtremor<on)?a->tmpvolume:0;
 
775
        a->s3mtremor++;
 
776
}
 
777
 
 
778
static void DoS3MRetrig(UBYTE inf)
 
779
{
 
780
        if (inf) {
 
781
                a->s3mrtgslide=inf>>4;
 
782
                a->s3mrtgspeed=inf&0xf;
 
783
        }
 
784
 
 
785
        /* only retrigger if low nibble > 0 */
 
786
        if ( a->s3mrtgspeed>0) {
 
787
                if (!a->retrig) {
 
788
                        /* when retrig counter reaches 0, reset counter and restart the
 
789
                           sample */
 
790
                        if (a->kick!=KICK_NOTE) a->kick=KICK_KEYOFF;
 
791
                        a->retrig=a->s3mrtgspeed;
 
792
 
 
793
                        if ((pf->vbtick)||(pf->flags&UF_S3MSLIDES)) {
 
794
                                switch (a->s3mrtgslide) {
 
795
                                        case 1:
 
796
                                        case 2:
 
797
                                        case 3:
 
798
                                        case 4:
 
799
                                        case 5:
 
800
                                                a->tmpvolume-=(1<<(a->s3mrtgslide-1));
 
801
                                                break;
 
802
                                        case 6:
 
803
                                                a->tmpvolume=(2*a->tmpvolume)/3;
 
804
                                                break;
 
805
                                        case 7:
 
806
                                                a->tmpvolume>>=1;
 
807
                                                break;
 
808
                                        case 9:
 
809
                                        case 0xa:
 
810
                                        case 0xb:
 
811
                                        case 0xc:
 
812
                                        case 0xd:
 
813
                                                a->tmpvolume+=(1<<(a->s3mrtgslide-9));
 
814
                                                break;
 
815
                                        case 0xe:
 
816
                                                a->tmpvolume=(3*a->tmpvolume)>>1;
 
817
                                                break;
 
818
                                        case 0xf:
 
819
                                                a->tmpvolume=a->tmpvolume<<1;
 
820
                                                break;
 
821
                                }
 
822
                                if (a->tmpvolume<0) a->tmpvolume=0;
 
823
                                else if (a->tmpvolume>64) a->tmpvolume=64;
 
824
                        }
 
825
                }
 
826
                a->retrig--; /* countdown  */
 
827
        }
 
828
}
 
829
 
 
830
static void DoS3MSpeed(UBYTE speed)
 
831
{
 
832
        if (pf->vbtick||pf->patdly2) return;
 
833
 
 
834
        if (speed>128) speed-=128;
 
835
        if (speed) {
 
836
                pf->sngspd=speed;
 
837
                pf->vbtick=0;
 
838
        }
 
839
}
 
840
 
 
841
static void DoS3MTempo(UBYTE tempo)
 
842
{
 
843
        if (pf->vbtick||pf->patdly2) return;
 
844
 
 
845
        pf->bpm=(tempo<32)?32:tempo;
 
846
}
 
847
 
 
848
static void DoS3MFineVibrato(void)
 
849
{
 
850
        UBYTE q;
 
851
        UWORD temp=0;
 
852
 
 
853
        q=(a->vibpos>>2)&0x1f;
 
854
 
 
855
        switch (a->wavecontrol&3) {
 
856
                case 0: /* sine */
 
857
                        temp=VibratoTable[q];
 
858
                        break;
 
859
                case 1: /* ramp down */
 
860
                        q<<=3;
 
861
                        if (a->vibpos<0) q=255-q;
 
862
                        temp=q;
 
863
                        break;
 
864
                case 2: /* square wave */
 
865
                        temp=255;
 
866
                        break;
 
867
                case 3: /* random */
 
868
                        temp=getrandom(256);
 
869
                        break;
 
870
        }
 
871
 
 
872
        temp*=a->vibdepth;
 
873
        temp>>=8;
 
874
 
 
875
        if (a->vibpos>=0)
 
876
                a->period=a->tmpperiod+temp;
 
877
        else
 
878
                a->period=a->tmpperiod-temp;
 
879
 
 
880
        a->vibpos+=a->vibspd;
 
881
}
 
882
 
 
883
static void DoS3MTremolo(void)
 
884
{
 
885
        UBYTE q;
 
886
        UWORD temp=0;
 
887
 
 
888
        q=(a->trmpos>>2)&0x1f;
 
889
 
 
890
        switch ((a->wavecontrol>>4)&3) {
 
891
                case 0: /* sine */
 
892
                        temp=VibratoTable[q];
 
893
                        break;
 
894
                case 1: /* ramp down */
 
895
                        q<<=3;
 
896
                        if (a->trmpos<0) q=255-q;
 
897
                        temp=q;
 
898
                        break;
 
899
                case 2: /* square wave */
 
900
                        temp=255;
 
901
                        break;
 
902
                case 3: /* random */
 
903
                        temp=getrandom(256);
 
904
                        break;
 
905
        }
 
906
 
 
907
        temp*=a->trmdepth;
 
908
        temp>>=7;
 
909
 
 
910
        if (a->trmpos>=0) {
 
911
                a->volume=a->tmpvolume+temp;
 
912
                if (a->volume>64) a->volume=64;
 
913
        } else {
 
914
                a->volume=a->tmpvolume-temp;
 
915
                if (a->volume<0) a->volume=0;
 
916
        }
 
917
 
 
918
        if (pf->vbtick) a->trmpos+=a->trmspd;
 
919
}
 
920
 
 
921
/*========== Fast Tracker effects */
 
922
 
 
923
static void DoXMVolSlide(UBYTE inf)
 
924
{
 
925
        UBYTE lo,hi;
 
926
 
 
927
        explicitslides=2;
 
928
 
 
929
        if (inf) a->s3mvolslide=inf;
 
930
        else inf=a->s3mvolslide;
 
931
 
 
932
        if (!pf->vbtick) return;
 
933
 
 
934
        lo=inf&0xf;
 
935
        hi=inf>>4;
 
936
 
 
937
        if (!hi) {
 
938
                a->tmpvolume-=lo;
 
939
                if (a->tmpvolume<0) a->tmpvolume=0;
 
940
        } else {
 
941
                a->tmpvolume+=hi;
 
942
                if (a->tmpvolume>64) a->tmpvolume=64;
 
943
        }
 
944
}
 
945
 
 
946
static void DoXMGlobalSlide(UBYTE inf)
 
947
{
 
948
        if (pf->vbtick) {
 
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;
 
953
 
 
954
                if (pf->volume<0) pf->volume=0;
 
955
                else if (pf->volume>128) pf->volume=128;
 
956
        }
 
957
}
 
958
 
 
959
static void DoXMPanSlide(UBYTE inf)
 
960
{
 
961
        UBYTE lo,hi;
 
962
        SWORD pan;
 
963
 
 
964
        if (inf) a->pansspd=inf;
 
965
        else inf=a->pansspd;
 
966
 
 
967
        if (!pf->vbtick) return;
 
968
 
 
969
        lo=inf&0xf;
 
970
        hi=inf>>4;
 
971
 
 
972
        /* slide right has absolute priority */
 
973
        if (hi) lo=0;
 
974
 
 
975
        pan=((a->panning==PAN_SURROUND)?PAN_CENTER:a->panning)+hi-lo;
 
976
 
 
977
        a->panning=(pan<PAN_LEFT)?PAN_LEFT:(pan>PAN_RIGHT?PAN_RIGHT:pan);
 
978
}
 
979
 
 
980
static void DoXMExtraFineSlideUp(UBYTE inf)
 
981
{
 
982
        if (!pf->vbtick) {
 
983
                a->period-=inf;
 
984
                a->tmpperiod-=inf;
 
985
        }
 
986
}
 
987
 
 
988
static void DoXMExtraFineSlideDown(UBYTE inf)
 
989
{
 
990
        if (!pf->vbtick) {
 
991
                a->period+=inf;
 
992
                a->tmpperiod+=inf;
 
993
        }
 
994
}
 
995
 
 
996
/*========== Impulse Tracker effects */
 
997
 
 
998
static void DoITChanVolSlide(UBYTE inf)
 
999
{
 
1000
        UBYTE lo, hi;
 
1001
 
 
1002
        if (inf) a->chanvolslide=inf;
 
1003
        inf=a->chanvolslide;
 
1004
 
 
1005
        lo=inf&0xf;
 
1006
        hi=inf>>4;
 
1007
 
 
1008
        if (!hi)
 
1009
                a->chanvol-=lo;
 
1010
        else
 
1011
          if (!lo) {
 
1012
                a->chanvol+=hi;
 
1013
        } else
 
1014
          if (hi==0xf) {
 
1015
                if (!pf->vbtick) a->chanvol-=lo;
 
1016
        } else
 
1017
          if (lo==0xf) {
 
1018
                if (!pf->vbtick) a->chanvol+=hi;
 
1019
        }
 
1020
 
 
1021
        if (a->chanvol<0) a->chanvol=0;
 
1022
        if (a->chanvol>64) a->chanvol=64;
 
1023
}
 
1024
 
 
1025
static void DoITGlobalSlide(UBYTE inf)
 
1026
{
 
1027
        UBYTE lo,hi;
 
1028
 
 
1029
        if (inf) pf->globalslide=inf;
 
1030
        inf=pf->globalslide;
 
1031
 
 
1032
        lo=inf&0xf;
 
1033
        hi=inf>>4;
 
1034
 
 
1035
        if (!lo) {
 
1036
                if (pf->vbtick) pf->volume+=hi;
 
1037
        } else
 
1038
          if (!hi) {
 
1039
                if (pf->vbtick) pf->volume-=lo;
 
1040
        } else
 
1041
          if (lo==0xf) {
 
1042
                if (!pf->vbtick) pf->volume+=hi;
 
1043
        } else
 
1044
          if (hi==0xf) {
 
1045
                if (!pf->vbtick) pf->volume-=lo;
 
1046
        }
 
1047
 
 
1048
        if (pf->volume<0)   pf->volume=0;
 
1049
        if (pf->volume>128) pf->volume=128;
 
1050
}
 
1051
 
 
1052
static void DoITPanSlide(UBYTE inf)
 
1053
{
 
1054
        UBYTE lo,hi;
 
1055
        SWORD pan;
 
1056
 
 
1057
        if (inf) a->pansspd=inf;
 
1058
        else inf=a->pansspd;
 
1059
 
 
1060
        lo=inf&0xf;
 
1061
        hi=inf>>4;
 
1062
 
 
1063
        pan=(a->panning==PAN_SURROUND)?PAN_CENTER:a->panning;
 
1064
 
 
1065
        if (!hi)
 
1066
                pan+=lo<<2;
 
1067
        else
 
1068
          if (!lo) {
 
1069
                pan-=hi<<2;
 
1070
        } else
 
1071
          if (hi==0xf) {
 
1072
                if (!pf->vbtick) pan+=lo<<2;
 
1073
        } else
 
1074
          if (lo==0xf) {
 
1075
                if (!pf->vbtick) pan-=hi<<2;
 
1076
        }
 
1077
        a->panning=/*pf->panning[mp_channel]=*/
 
1078
          (pan<PAN_LEFT)?PAN_LEFT:(pan>PAN_RIGHT?PAN_RIGHT:pan);
 
1079
}
 
1080
 
 
1081
static void DoITTempo(UBYTE tempo)
 
1082
{
 
1083
        SWORD temp=pf->bpm;
 
1084
 
 
1085
        if (pf->vbtick||pf->patdly2) return;
 
1086
 
 
1087
        if (tempo&0x10)
 
1088
                temp+=(tempo&0x0f);
 
1089
        else
 
1090
                temp-=tempo;
 
1091
 
 
1092
        pf->bpm=(temp>255)?255:(temp<1?1:temp);
 
1093
}
 
1094
 
 
1095
static void DoITVibrato(void)
 
1096
{
 
1097
        UBYTE q;
 
1098
        UWORD temp=0;
 
1099
 
 
1100
        q=(a->vibpos>>2)&0x1f;
 
1101
 
 
1102
        switch (a->wavecontrol&3) {
 
1103
                case 0: /* sine */
 
1104
                        temp=VibratoTable[q];
 
1105
                        break;
 
1106
                case 1: /* square wave */
 
1107
                        temp=255;
 
1108
                        break;
 
1109
                case 2: /* ramp down */
 
1110
                        q<<=3;
 
1111
                        if (a->vibpos<0) q=255-q;
 
1112
                        temp=q;
 
1113
                        break;
 
1114
                case 3: /* random */
 
1115
                        temp=getrandom(256);
 
1116
                        break;
 
1117
        }
 
1118
 
 
1119
        temp*=a->vibdepth;
 
1120
        temp>>=8;
 
1121
        temp<<=2;
 
1122
 
 
1123
        if (a->vibpos>=0)
 
1124
                a->period=a->tmpperiod+temp;
 
1125
        else
 
1126
                a->period=a->tmpperiod-temp;
 
1127
 
 
1128
        a->vibpos+=a->vibspd;
 
1129
}
 
1130
 
 
1131
static void DoITFineVibrato(void)
 
1132
{
 
1133
        UBYTE q;
 
1134
        UWORD temp=0;
 
1135
 
 
1136
        q=(a->vibpos>>2)&0x1f;
 
1137
 
 
1138
        switch (a->wavecontrol&3) {
 
1139
                case 0: /* sine */
 
1140
                        temp=VibratoTable[q];
 
1141
                        break;
 
1142
                case 1: /* square wave */
 
1143
                        temp=255;
 
1144
                        break;
 
1145
                case 2: /* ramp down */
 
1146
                        q<<=3;
 
1147
                        if (a->vibpos<0) q=255-q;
 
1148
                        temp=q;
 
1149
                        break;
 
1150
                case 3: /* random */
 
1151
                        temp=getrandom(256);
 
1152
                        break;
 
1153
        }
 
1154
 
 
1155
        temp*=a->vibdepth;
 
1156
        temp>>=8;
 
1157
 
 
1158
        if (a->vibpos>=0)
 
1159
                a->period=a->tmpperiod+temp;
 
1160
        else
 
1161
                a->period=a->tmpperiod-temp;
 
1162
 
 
1163
        a->vibpos+=a->vibspd;
 
1164
}
 
1165
 
 
1166
static void DoITTremor(UBYTE inf)
 
1167
{
 
1168
        UBYTE on,off;
 
1169
 
 
1170
        if (inf)
 
1171
                a->s3mtronof=inf;
 
1172
        else {
 
1173
                inf=a->s3mtronof;
 
1174
                if (!inf) return;
 
1175
        }
 
1176
 
 
1177
        if (!pf->vbtick) return;
 
1178
 
 
1179
        on=(inf>>4);
 
1180
        off=(inf&0xf);
 
1181
 
 
1182
        a->s3mtremor%=(on+off);
 
1183
        a->volume=(a->s3mtremor<on)?a->tmpvolume:0;
 
1184
        a->s3mtremor++;
 
1185
}
 
1186
 
 
1187
static void DoITPanbrello(void)
 
1188
{
 
1189
        UBYTE q;
 
1190
        SLONG temp=0;
 
1191
 
 
1192
        q=a->panbpos;
 
1193
 
 
1194
        switch (a->panbwave) {
 
1195
                case 0: /* sine */
 
1196
                        temp=PanbrelloTable[q];
 
1197
                        break;
 
1198
                case 1: /* square wave */
 
1199
                        temp=(q<0x80)?64:0;
 
1200
                        break;
 
1201
                case 2: /* ramp down */
 
1202
                        q<<=3;
 
1203
                        temp=q;
 
1204
                        break;
 
1205
                case 3: /* random */
 
1206
                        if (a->panbpos>=a->panbspd) {
 
1207
                                a->panbpos=0;
 
1208
                                temp=getrandom(256);
 
1209
                        }
 
1210
        }
 
1211
 
 
1212
        temp*=a->panbdepth;
 
1213
        temp=(temp/8)+pf->panning[mp_channel];
 
1214
 
 
1215
        a->panning=(temp<PAN_LEFT)?PAN_LEFT:(temp>PAN_RIGHT?PAN_RIGHT:temp);
 
1216
        a->panbpos+=a->panbspd;
 
1217
}
 
1218
 
 
1219
static void DoITToneSlide(void)
 
1220
{
 
1221
        /* if we don't come from another note, ignore the slide and play the note
 
1222
           as is */
 
1223
        if (!a->oldnote) return;
 
1224
 
 
1225
        if (pf->vbtick) {
 
1226
                int dist;
 
1227
 
 
1228
                /* We have to slide a->period towards a->wantedperiod, compute the
 
1229
                   difference between those two values */
 
1230
                dist=a->period-a->wantedperiod;
 
1231
 
 
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;
 
1236
                else
 
1237
                  if (dist>0) {
 
1238
                        a->tmpperiod-=a->portspeed<<2;
 
1239
                        a->period-=a->portspeed<<2; /* dist>0 slide up */
 
1240
                } else {
 
1241
                        a->tmpperiod+=a->portspeed<<2;
 
1242
                        a->period+=a->portspeed<<2; /* dist<0 slide down */
 
1243
                }
 
1244
        } else
 
1245
                a->tmpperiod=a->period;
 
1246
}
 
1247
 
 
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)
 
1252
{
 
1253
        UBYTE inf,c;
 
1254
 
 
1255
        inf=dat&0xf;
 
1256
        c=dat>>4;
 
1257
 
 
1258
        if (!dat) {
 
1259
                c=a->sseffect;
 
1260
                inf=a->ssdata;
 
1261
        } else {
 
1262
                a->sseffect=c;
 
1263
                a->ssdata=inf;
 
1264
        }
 
1265
 
 
1266
        switch (c) {
 
1267
                case SS_GLISSANDO: /* S1x set glissando voice */
 
1268
                        DoEEffects(0x30|inf);
 
1269
                        break;
 
1270
                case SS_FINETUNE: /* S2x set finetune */
 
1271
                        DoEEffects(0x50|inf);
 
1272
                        break;
 
1273
                case SS_VIBWAVE: /* S3x set vibrato waveform */
 
1274
                        DoEEffects(0x40|inf);
 
1275
                        break;
 
1276
                case SS_TREMWAVE: /* S4x set tremolo waveform */
 
1277
                        DoEEffects(0x70|inf);
 
1278
                        break;
 
1279
                case SS_PANWAVE: /* S5x panbrello */
 
1280
                        a->panbwave=inf;
 
1281
                        break;
 
1282
                case SS_FRAMEDELAY: /* S6x delay x number of frames (patdly) */
 
1283
                        DoEEffects(0xe0|inf);
 
1284
                        break;
 
1285
                case SS_S7EFFECTS: /* S7x instrument / NNA commands */
 
1286
                        DoNNAEffects(inf);
 
1287
                        break;
 
1288
                case SS_PANNING: /* S8x set panning position */
 
1289
                        DoEEffects(0x80 | inf);
 
1290
                        break;
 
1291
                case SS_SURROUND: /* S9x set surround Sound */
 
1292
                        if (pf->panflag)
 
1293
                                a->panning=pf->panning[mp_channel]=PAN_SURROUND;
 
1294
                        break;
 
1295
                case SS_HIOFFSET: /* SAy set high order sample offset yxx00h */
 
1296
                        if (!pf->vbtick) {
 
1297
                                a->hioffset=inf<<16;
 
1298
                                a->start=a->hioffset|a->soffset;
 
1299
 
 
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;
 
1302
                        }
 
1303
                        break;
 
1304
                case SS_PATLOOP: /* SBx pattern loop */
 
1305
                        DoEEffects(0x60|inf);
 
1306
                        break;
 
1307
                case SS_NOTECUT: /* SCx notecut */
 
1308
                        DoEEffects(0xC0|inf);
 
1309
                        break;
 
1310
                case SS_NOTEDELAY: /* SDx notedelay */
 
1311
                        DoEEffects(0xD0|inf);
 
1312
                        break;
 
1313
                case SS_PATDELAY: /* SEx patterndelay */
 
1314
                        DoEEffects(0xE0|inf);
 
1315
                        break;
 
1316
        }
 
1317
}
 
1318
 
 
1319
/* Impulse Tracker Volume/Pan Column effects.
 
1320
   All volume/pan column effects share the same memory space. */
 
1321
static void DoVolEffects(UBYTE c)
 
1322
{
 
1323
        UBYTE inf=UniGetByte();
 
1324
 
 
1325
        if ((!c)&&(!inf)) {
 
1326
                c=a->voleffect;
 
1327
                inf=a->voldata;
 
1328
        } else {
 
1329
                a->voleffect=c;
 
1330
                a->voldata=inf;
 
1331
        }
 
1332
 
 
1333
        if (c)
 
1334
          switch (c) {
 
1335
                case VOL_VOLUME:
 
1336
                        if (pf->vbtick) break;
 
1337
                        if (inf>64) inf=64;
 
1338
                        a->tmpvolume=inf;
 
1339
                        break;
 
1340
                case VOL_PANNING:
 
1341
                        if (pf->panflag)
 
1342
                                a->panning=/*pf->panning[mp_channel]=*/inf;
 
1343
                        break;
 
1344
                case VOL_VOLSLIDE:
 
1345
                        DoS3MVolSlide(inf);
 
1346
                        break;
 
1347
                case VOL_PITCHSLIDEDN:
 
1348
                        if (a->period)
 
1349
                                DoS3MSlideDn(inf);
 
1350
                        break;
 
1351
                case VOL_PITCHSLIDEUP:
 
1352
                        if (a->period)
 
1353
                                DoS3MSlideUp(inf);
 
1354
                        break;
 
1355
                case VOL_PORTAMENTO:
 
1356
                        if (inf) a->slidespeed=inf;
 
1357
                        if (a->period) {
 
1358
                                if ((!pf->vbtick)||(a->newsamp)){
 
1359
                                        a->kick=KICK_NOTE;
 
1360
                                        a->start=-1;
 
1361
                                } else
 
1362
                                        a->kick=(a->kick==KICK_NOTE)?KICK_ENV:KICK_ABSENT;
 
1363
                                DoITToneSlide();
 
1364
                                a->ownper=1;
 
1365
                        }
 
1366
                        break;
 
1367
                case VOL_VIBRATO:
 
1368
                        if (!pf->vbtick) {
 
1369
                                if (inf&0x0f) a->vibdepth=inf&0xf;
 
1370
                                if (inf&0xf0) a->vibspd=(inf&0xf0)>>2;
 
1371
                        }
 
1372
                        if (a->period) {
 
1373
                                DoITVibrato();
 
1374
                                a->ownper=1;
 
1375
                        }
 
1376
                        break;
 
1377
        }
 
1378
}
 
1379
 
 
1380
/*========== UltraTracker effects */
 
1381
 
 
1382
static void DoULTSampleOffset(void)
 
1383
{
 
1384
        UWORD offset=UniGetWord();
 
1385
 
 
1386
        if (offset)
 
1387
                a->ultoffset=offset;
 
1388
 
 
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;
 
1392
}
 
1393
 
 
1394
/*========== OctaMED effects */
 
1395
 
 
1396
static void DoMEDSpeed(void)
 
1397
{
 
1398
        UWORD speed=UniGetWord();
 
1399
 
 
1400
        pf->bpm=speed;
 
1401
}
 
1402
 
 
1403
/*========== General player functions */
 
1404
 
 
1405
static void pt_playeffects(void)
 
1406
{
 
1407
        UBYTE dat,c;
 
1408
 
 
1409
        while((c=UniGetByte())) {
 
1410
                int oldsliding=a->sliding;
 
1411
 
 
1412
                a->sliding=0;
 
1413
                switch (c) {
 
1414
                        case UNI_NOTE:
 
1415
                        case UNI_INSTRUMENT:
 
1416
                                a->sliding=oldsliding;
 
1417
                                UniSkipOpcode(c);
 
1418
                                break;
 
1419
                        case UNI_PTEFFECT0:
 
1420
                                dat=UniGetByte();
 
1421
                                if (!pf->vbtick) {
 
1422
                                        if ((!dat)&&(pf->flags&UF_ARPMEM)) dat=a->arpmem;
 
1423
                                        a->arpmem=dat;
 
1424
                                }
 
1425
                                if (a->period)
 
1426
                                        DoArpeggio(a->arpmem);
 
1427
                                break;
 
1428
                        case UNI_PTEFFECT1:
 
1429
                                dat=UniGetByte();
 
1430
                                if ((!pf->vbtick)&&(dat)) a->slidespeed=(UWORD)dat<<2;
 
1431
                                if (a->period)
 
1432
                                        if (pf->vbtick) a->tmpperiod-=a->slidespeed;
 
1433
                                break;
 
1434
                        case UNI_PTEFFECT2:
 
1435
                                dat=UniGetByte();
 
1436
                                if ((!pf->vbtick)&&(dat)) a->slidespeed=(UWORD)dat<<2;
 
1437
                                if (a->period)
 
1438
                                        if (pf->vbtick) a->tmpperiod+=a->slidespeed;
 
1439
                                break;
 
1440
                        case UNI_PTEFFECT3:
 
1441
                                dat=UniGetByte();
 
1442
                                if ((!pf->vbtick)&&(dat)) a->portspeed=(UWORD)dat<<2;
 
1443
                                if (a->period) {
 
1444
                                        if (!a->fadevol)
 
1445
                                                a->kick=(a->kick==KICK_NOTE)?KICK_NOTE:KICK_KEYOFF;
 
1446
                                        else
 
1447
                                                a->kick=(a->kick==KICK_NOTE)?KICK_ENV:KICK_ABSENT;
 
1448
                                        DoToneSlide();
 
1449
                                        a->ownper=1;
 
1450
                                }
 
1451
                                break;
 
1452
                        case UNI_PTEFFECT4:
 
1453
                        case UNI_XMEFFECT4:
 
1454
                                dat=UniGetByte();
 
1455
                                if (!pf->vbtick) {
 
1456
                                        if (dat&0x0f) a->vibdepth=dat&0xf;
 
1457
                                        if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
 
1458
                                } else
 
1459
                                if (a->period) {
 
1460
                                        DoVibrato();
 
1461
                                        a->ownper=1;
 
1462
                                }
 
1463
                                break;
 
1464
                        case UNI_PTEFFECT5:
 
1465
                                dat=UniGetByte();
 
1466
                                if (a->period) {
 
1467
                                        if (!a->fadevol)
 
1468
                                                a->kick=(a->kick==KICK_NOTE)?KICK_NOTE:KICK_KEYOFF;
 
1469
                                        else
 
1470
                                                a->kick=(a->kick==KICK_NOTE)?KICK_ENV:KICK_ABSENT;
 
1471
                                        DoToneSlide();
 
1472
                                        a->ownper=1;
 
1473
                                }
 
1474
                                DoVolSlide(dat);
 
1475
                                break;
 
1476
                        case UNI_PTEFFECT6:
 
1477
                                dat=UniGetByte();
 
1478
                                if ((a->period)&&(pf->vbtick)) {
 
1479
                                        DoVibrato();
 
1480
                                        a->ownper=1;
 
1481
                                }
 
1482
                                DoVolSlide(dat);
 
1483
                                break;
 
1484
                        case UNI_PTEFFECT7:
 
1485
                                dat=UniGetByte();
 
1486
                                if (!pf->vbtick) {
 
1487
                                        if (dat&0x0f) a->trmdepth=dat&0xf;
 
1488
                                        if (dat&0xf0) a->trmspd=(dat&0xf0)>>2;
 
1489
                                }
 
1490
                                if (a->period) {
 
1491
                                        DoTremolo();
 
1492
                                        a->ownvol=1;
 
1493
                                }
 
1494
                                break;
 
1495
                        case UNI_PTEFFECT8:
 
1496
                                dat=UniGetByte();
 
1497
                                if (pf->panflag)
 
1498
                                        a->panning=pf->panning[mp_channel]=dat;
 
1499
                                break;
 
1500
                        case UNI_PTEFFECT9:
 
1501
                                dat=UniGetByte();
 
1502
                                if (!pf->vbtick) {
 
1503
                                        if (dat) a->soffset=(UWORD)dat<<8;
 
1504
                                        a->start=a->hioffset|a->soffset;
 
1505
 
 
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;
 
1508
                                }
 
1509
                                break;
 
1510
                        case UNI_PTEFFECTA:
 
1511
                                DoVolSlide(UniGetByte());
 
1512
                                break;
 
1513
                        case UNI_PTEFFECTB:
 
1514
                                dat=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:
 
1523
                                        pf->patbrk=0; */
 
1524
                                        pf->posjmp=3;
 
1525
                                } else {
 
1526
                                        /* if we were fading, adjust... */
 
1527
                                        if (pf->sngpos==(pf->numpos-1))
 
1528
                                                pf->volume=pf->initvolume>128?128:pf->initvolume;
 
1529
                                        pf->sngpos=dat;
 
1530
                                        pf->posjmp=2;
 
1531
                                        pf->patpos=0;
 
1532
                                }
 
1533
                                break;
 
1534
                        case UNI_PTEFFECTC:
 
1535
                                dat=UniGetByte();
 
1536
                                if (pf->vbtick) break;
 
1537
                                if (dat==(UBYTE)-1) a->anote=dat=0; /* note cut */
 
1538
                                else if (dat>64) dat=64;
 
1539
                                a->tmpvolume=dat;
 
1540
                                break;
 
1541
                        case UNI_PTEFFECTD:
 
1542
                                dat=UniGetByte();
 
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]];
 
1547
                                pf->patbrk=dat;
 
1548
                                if (!pf->posjmp) {
 
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
 
1553
                                           aspirin - Miod */
 
1554
                                        if ((pf->sngpos==pf->numpos-1)&&(dat)&&((pf->loop)||
 
1555
                                                       (pf->positions[pf->sngpos]==(pf->numpat-1)
 
1556
                                                                        && !(pf->flags&UF_NOWRAP)))) {
 
1557
                                                pf->sngpos=0;
 
1558
                                                pf->posjmp=2;
 
1559
                                        } else
 
1560
                                                pf->posjmp=3;
 
1561
                                }
 
1562
                                break;
 
1563
                        case UNI_PTEFFECTE:
 
1564
                                DoEEffects(UniGetByte());
 
1565
                                break;
 
1566
                        case UNI_PTEFFECTF:
 
1567
                                dat=UniGetByte();
 
1568
                                if (pf->vbtick||pf->patdly2) break;
 
1569
                                if (pf->extspd&&(dat>=0x20))
 
1570
                                        pf->bpm=dat;
 
1571
                                else
 
1572
                                  if (dat) {
 
1573
                                        pf->sngspd=(dat>32)?32:dat;
 
1574
                                        pf->vbtick=0;
 
1575
                                }
 
1576
                                break;
 
1577
                        case UNI_S3MEFFECTA:
 
1578
                                DoS3MSpeed(UniGetByte());
 
1579
                                break;
 
1580
                        case UNI_S3MEFFECTD:
 
1581
                                DoS3MVolSlide(UniGetByte());
 
1582
                                break;
 
1583
                        case UNI_S3MEFFECTE:
 
1584
                                dat=UniGetByte();
 
1585
                                if (a->period)
 
1586
                                        DoS3MSlideDn(dat);
 
1587
                                break;
 
1588
                        case UNI_S3MEFFECTF:
 
1589
                                dat=UniGetByte();
 
1590
                                if (a->period)
 
1591
                                        DoS3MSlideUp(dat);
 
1592
                                break;
 
1593
                        case UNI_S3MEFFECTI:
 
1594
                                DoS3MTremor(UniGetByte());
 
1595
                                a->ownvol=1;
 
1596
                                break;
 
1597
                        case UNI_S3MEFFECTQ:
 
1598
                                dat=UniGetByte();
 
1599
                                if (a->period)
 
1600
                                        DoS3MRetrig(dat);
 
1601
                                break;
 
1602
                        case UNI_S3MEFFECTR:
 
1603
                                dat=UniGetByte();
 
1604
                                if (!pf->vbtick) {
 
1605
                                        if (dat&0x0f) a->trmdepth=dat&0xf;
 
1606
                                        if (dat&0xf0) a->trmspd=(dat&0xf0)>>2;
 
1607
                                }
 
1608
                                DoS3MTremolo();
 
1609
                                a->ownvol=1;
 
1610
                                break;
 
1611
                        case UNI_S3MEFFECTT:
 
1612
                                DoS3MTempo(UniGetByte());
 
1613
                                break;
 
1614
                        case UNI_S3MEFFECTU:
 
1615
                                dat=UniGetByte();
 
1616
                                if (!pf->vbtick) {
 
1617
                                        if (dat&0x0f) a->vibdepth=dat&0xf;
 
1618
                                        if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
 
1619
                                } else
 
1620
                                if (a->period) {
 
1621
                                        DoS3MFineVibrato();
 
1622
                                        a->ownper=1;
 
1623
                                }
 
1624
                                break;
 
1625
                        case UNI_KEYOFF:
 
1626
                                a->keyoff|=KEY_OFF;
 
1627
                                if ((!(a->volflg&EF_ON))||(a->volflg&EF_LOOP))
 
1628
                                        a->keyoff=KEY_KILL;
 
1629
                                break;
 
1630
                        case UNI_KEYFADE:
 
1631
                                dat=UniGetByte();
 
1632
                                if ((pf->vbtick>=dat)||(pf->vbtick==pf->sngspd-1)) {
 
1633
                                        a->keyoff=KEY_KILL;
 
1634
                                        if (!(a->volflg&EF_ON))
 
1635
                                                a->fadevol=0;
 
1636
                                }
 
1637
                                break;
 
1638
                        case UNI_VOLEFFECTS:
 
1639
                                DoVolEffects(UniGetByte());
 
1640
                                break;
 
1641
                        case UNI_XMEFFECTA:
 
1642
                                DoXMVolSlide(UniGetByte());
 
1643
                                break;
 
1644
                        case UNI_XMEFFECTE1: /* XM fineslide up */
 
1645
                                dat=UniGetByte();
 
1646
                                if (!pf->vbtick) {
 
1647
                                        if (dat) a->fportupspd=dat;
 
1648
                                        if (a->period)
 
1649
                                                a->tmpperiod-=(a->fportupspd<<2);
 
1650
                                }
 
1651
                                break;
 
1652
                        case UNI_XMEFFECTE2: /* XM fineslide dn */
 
1653
                                dat=UniGetByte();
 
1654
                                if (!pf->vbtick) {
 
1655
                                        if (dat) a->fportdnspd=dat;
 
1656
                                        if (a->period)
 
1657
                                                a->tmpperiod+=(a->fportdnspd<<2);
 
1658
                                }
 
1659
                                break;
 
1660
                        case UNI_XMEFFECTEA: /* fine volume slide up */
 
1661
                                dat=UniGetByte();
 
1662
                                if (!pf->vbtick)
 
1663
                                        if (dat) a->fslideupspd=dat;
 
1664
                                a->tmpvolume+=a->fslideupspd;
 
1665
                                if (a->tmpvolume>64) a->tmpvolume=64;
 
1666
                                break;
 
1667
                        case UNI_XMEFFECTEB: /* fine volume slide dn */
 
1668
                                dat=UniGetByte();
 
1669
                                if (!pf->vbtick)
 
1670
                                        if (dat) a->fslidednspd=dat;
 
1671
                                a->tmpvolume-=a->fslidednspd;
 
1672
                                if (a->tmpvolume<0) a->tmpvolume=0;
 
1673
                                break;
 
1674
                        case UNI_XMEFFECTG:
 
1675
                                pf->volume=UniGetByte()<<1;
 
1676
                                if (pf->volume>128) pf->volume=128;
 
1677
                                break;
 
1678
                        case UNI_XMEFFECTH:
 
1679
                                DoXMGlobalSlide(UniGetByte());
 
1680
                                break;
 
1681
                        case UNI_XMEFFECTL:
 
1682
                                dat=UniGetByte();
 
1683
                                if ((!pf->vbtick)&&(a->i)) {
 
1684
                                        UWORD points;
 
1685
                                        INSTRUMENT *i=a->i;
 
1686
                                        MP_VOICE *aout;
 
1687
 
 
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;
 
1693
                                        }
 
1694
                                }
 
1695
                                break;
 
1696
                        case UNI_XMEFFECTP:
 
1697
                                dat=UniGetByte();
 
1698
                                if (pf->panflag)
 
1699
                                        DoXMPanSlide(dat);
 
1700
                                break;
 
1701
                        case UNI_XMEFFECTX1:
 
1702
                                dat=UniGetByte();
 
1703
                                if (dat) a->ffportupspd=dat;
 
1704
                                else dat=a->ffportupspd;
 
1705
                                if (a->period) {
 
1706
                                        DoXMExtraFineSlideUp(dat);
 
1707
                                        a->ownper=1;
 
1708
                                }
 
1709
                                break;
 
1710
                        case UNI_XMEFFECTX2:
 
1711
                                dat=UniGetByte();
 
1712
                                if (dat) a->ffportdnspd=dat;
 
1713
                                else dat=a->ffportdnspd;
 
1714
                                if (a->period) {
 
1715
                                        DoXMExtraFineSlideDown(dat);
 
1716
                                        a->ownper=1;
 
1717
                                }
 
1718
                                break;
 
1719
                        case UNI_ITEFFECTG:
 
1720
                                dat=UniGetByte();
 
1721
                                if (dat) {
 
1722
                                        a->portspeed=dat;
 
1723
                                }
 
1724
                                if (a->period) {
 
1725
                                        if ((!pf->vbtick)&&(a->newsamp)){
 
1726
                                                a->kick=KICK_NOTE;
 
1727
                                                a->start=-1;
 
1728
                                        } else
 
1729
                                                a->kick=(a->kick==KICK_NOTE)?KICK_ENV:KICK_ABSENT;
 
1730
                                        DoITToneSlide();
 
1731
                                        a->ownper=1;
 
1732
                                }
 
1733
                                break;
 
1734
                        case UNI_ITEFFECTH: /* IT vibrato */
 
1735
                                dat=UniGetByte();
 
1736
                                if (!pf->vbtick) {
 
1737
                                        if (dat&0x0f) a->vibdepth=dat&0xf;
 
1738
                                        if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
 
1739
                                }
 
1740
                                if (a->period) {
 
1741
                                        DoITVibrato();
 
1742
                                        a->ownper=1;
 
1743
                                }
 
1744
                                break;
 
1745
                        case UNI_ITEFFECTI: /* IT tremor */
 
1746
                                DoITTremor(UniGetByte());
 
1747
                                a->ownvol=1;
 
1748
                                break;
 
1749
                        case UNI_ITEFFECTM:
 
1750
                                a->chanvol=UniGetByte();
 
1751
                                if (a->chanvol>64) a->chanvol=64;
 
1752
                                else if (a->chanvol<0) a->chanvol=0;
 
1753
                                break;
 
1754
                        case UNI_ITEFFECTN: /* slide / fineslide channel volume */
 
1755
                                DoITChanVolSlide(UniGetByte());
 
1756
                                break;
 
1757
                        case UNI_ITEFFECTP:  /* slide / fineslide channel panning */
 
1758
                                dat=UniGetByte();
 
1759
                                if (pf->panflag)
 
1760
                                        DoITPanSlide(dat);
 
1761
                                break;
 
1762
                        case UNI_ITEFFECTT: /* slide / fineslide tempo */
 
1763
                                DoITTempo(UniGetByte());
 
1764
                                break;
 
1765
                        case UNI_ITEFFECTU: /* fine vibrato */
 
1766
                                dat=UniGetByte();
 
1767
                                if (!pf->vbtick) {
 
1768
                                        if (dat&0x0f) a->vibdepth=dat&0xf;
 
1769
                                        if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
 
1770
                                }
 
1771
                                if (a->period) {
 
1772
                                        DoITFineVibrato();
 
1773
                                        a->ownper=1;
 
1774
                                }
 
1775
                                break;
 
1776
                        case UNI_ITEFFECTW: /* slide / fineslide global volume */
 
1777
                                DoITGlobalSlide(UniGetByte());
 
1778
                                break;
 
1779
                        case UNI_ITEFFECTY: /* panbrello */
 
1780
                                dat=UniGetByte();
 
1781
                                if (!pf->vbtick) {
 
1782
                                        if (dat&0x0f) a->panbdepth=(dat&0xf);
 
1783
                                        if (dat&0xf0) a->panbspd=(dat&0xf0)>>4;
 
1784
                                }
 
1785
                                if (pf->panflag) DoITPanbrello();
 
1786
                                break;
 
1787
                        case UNI_ITEFFECTS0:
 
1788
                                DoSSEffects(UniGetByte());
 
1789
                                break;
 
1790
                        case UNI_ITEFFECTZ:
 
1791
                                /* FIXME not yet implemented */
 
1792
                                UniSkipOpcode(UNI_ITEFFECTZ);
 
1793
                                break;
 
1794
                        case UNI_ULTEFFECT9:
 
1795
                                DoULTSampleOffset();
 
1796
                                break;
 
1797
                        case UNI_MEDSPEED:
 
1798
                                DoMEDSpeed();
 
1799
                                break;
 
1800
                        case UNI_MEDEFFECTF1:
 
1801
                                DoEEffects(0x90|(pf->sngspd/2));
 
1802
                                break;
 
1803
                        case UNI_MEDEFFECTF2:
 
1804
                                DoEEffects(0xd0|(pf->sngspd/2));
 
1805
                                break;
 
1806
                        case UNI_MEDEFFECTF3:
 
1807
                                DoEEffects(0x90|(pf->sngspd/3));
 
1808
                                break;
 
1809
                        case UNI_XMEFFECTZ:
 
1810
                                Player_SetSynchroValue(UniGetByte());
 
1811
                                break;
 
1812
                        default:
 
1813
                                a->sliding=oldsliding;
 
1814
                                UniSkipOpcode(c);
 
1815
                                break;
 
1816
                }
 
1817
        }
 
1818
}
 
1819
 
 
1820
static void DoNNAEffects(UBYTE dat)
 
1821
{
 
1822
        int t;
 
1823
        MP_VOICE *aout;
 
1824
 
 
1825
        dat&=0xf;
 
1826
        aout=(a->slave)?a->slave:NULL;
 
1827
 
 
1828
        switch (dat) {
 
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;
 
1833
                        break;
 
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;
 
1841
                                }
 
1842
                        break;
 
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;
 
1847
                        break;
 
1848
                case 0x3: /* set NNA note cut */
 
1849
                        a->nna=(a->nna&~NNA_MASK)|NNA_CUT;
 
1850
                        break;
 
1851
                case 0x4: /* set NNA note continue */
 
1852
                        a->nna=(a->nna&~NNA_MASK)|NNA_CONTINUE;
 
1853
                        break;
 
1854
                case 0x5: /* set NNA note off */
 
1855
                        a->nna=(a->nna&~NNA_MASK)|NNA_OFF;
 
1856
                        break;
 
1857
                case 0x6: /* set NNA note fade */
 
1858
                        a->nna=(a->nna&~NNA_MASK)|NNA_FADE;
 
1859
                        break;
 
1860
                case 0x7: /* disable volume envelope */
 
1861
                        if (aout)
 
1862
                                aout->volflg&=~EF_ON;
 
1863
                        break;
 
1864
                case 0x8: /* enable volume envelope  */
 
1865
                        if (aout)
 
1866
                                aout->volflg|=EF_ON;
 
1867
                        break;
 
1868
                case 0x9: /* disable panning envelope */
 
1869
                        if (aout)
 
1870
                                aout->panflg&=~EF_ON;
 
1871
                        break;
 
1872
                case 0xa: /* enable panning envelope */
 
1873
                        if (aout)
 
1874
                                aout->panflg|=EF_ON;
 
1875
                        break;
 
1876
                case 0xb: /* disable pitch envelope */
 
1877
                        if (aout)
 
1878
                                aout->pitflg&=~EF_ON;
 
1879
                        break;
 
1880
                case 0xc: /* enable pitch envelope */
 
1881
                        if (aout)
 
1882
                                aout->pitflg|=EF_ON;
 
1883
                        break;
 
1884
        }
 
1885
}
 
1886
 
 
1887
void pt_UpdateVoices(int max_volume)
 
1888
{
 
1889
        SWORD envpan,envvol,envpit;
 
1890
        UWORD playperiod;
 
1891
        SLONG vibval,vibdpt;
 
1892
        ULONG tmpvol;
 
1893
 
 
1894
        MP_VOICE *aout;
 
1895
        INSTRUMENT *i;
 
1896
        SAMPLE *s;
 
1897
 
 
1898
        pf->totalchn=pf->realchn=0;
 
1899
        for (mp_channel=0;mp_channel<md_sngchn;mp_channel++) {
 
1900
                aout=&pf->voice[mp_channel];
 
1901
                i=aout->i;
 
1902
                s=aout->s;
 
1903
 
 
1904
                if ((!s)||(!s->length)) continue;
 
1905
 
 
1906
                if (aout->period<40) aout->period=40;
 
1907
                else if (aout->period>50000) aout->period=50000;
 
1908
 
 
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;
 
1912
                        aout->aswppos=0;
 
1913
                }
 
1914
 
 
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);
 
1924
                }
 
1925
                aout->kick=KICK_ABSENT;
 
1926
 
 
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);
 
1933
 
 
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 */
 
1941
                tmpvol/=4194304UL;
 
1942
               tmpvol*=pf->initvolume;   /* * max 128 */
 
1943
               tmpvol/=128;
 
1944
 
 
1945
                /* fade out */
 
1946
                if (pf->sngpos>=pf->numpos) tmpvol=0;
 
1947
                else
 
1948
                        tmpvol=(tmpvol*max_volume)/128;
 
1949
 
 
1950
                if ((aout->masterchn!=-1)&& pf->control[aout->masterchn].muted)
 
1951
                        Voice_SetVolume_internal(mp_channel,0);
 
1952
                else {
 
1953
                        Voice_SetVolume_internal(mp_channel,tmpvol);
 
1954
                        if ((tmpvol)&&(aout->master)&&(aout->master->slave==aout))
 
1955
                                pf->realchn++;
 
1956
                        pf->totalchn++;
 
1957
                }
 
1958
 
 
1959
                if (aout->panning==PAN_SURROUND)
 
1960
                        Voice_SetPanning_internal(mp_channel,PAN_SURROUND);
 
1961
                else
 
1962
                        if ((pf->panflag)&&(aout->penv.flg & EF_ON))
 
1963
                                Voice_SetPanning_internal(mp_channel,DoPan(envpan,aout->panning));
 
1964
                        else
 
1965
                                Voice_SetPanning_internal(mp_channel,aout->panning);
 
1966
 
 
1967
                if (aout->period && s->vibdepth)
 
1968
                        switch (s->vibtype) {
 
1969
                                case 0:
 
1970
                                        vibval=avibtab[s->avibpos&127];
 
1971
                                        if (s->avibpos & 0x80) vibval=-vibval;
 
1972
                                        break;
 
1973
                                case 1:
 
1974
                                        vibval=64;
 
1975
                                        if (s->avibpos & 0x80) vibval=-vibval;
 
1976
                                        break;
 
1977
                                case 2:
 
1978
                                        vibval=63-(((s->avibpos+128)&255)>>1);
 
1979
                                        break;
 
1980
                                default:
 
1981
                                        vibval=(((s->avibpos+128)&255)>>1)-64;
 
1982
                                        break;
 
1983
                        }
 
1984
                else
 
1985
                        vibval=0;
 
1986
 
 
1987
                if (s->vibflags & AV_IT) {
 
1988
                        if ((aout->aswppos>>8)<s->vibdepth) {
 
1989
                                aout->aswppos += s->vibsweep;
 
1990
                                vibdpt=aout->aswppos;
 
1991
                        } else
 
1992
                                vibdpt=s->vibdepth<<8;
 
1993
                        vibval=(vibval*vibdpt)>>16;
 
1994
                        if (aout->mflag) {
 
1995
                                if (!(pf->flags&UF_LINEAR)) vibval>>=1;
 
1996
                                aout->period-=vibval;
 
1997
                        }
 
1998
                } else {
 
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;
 
2003
                                        aout->aswppos++;
 
2004
                                } else
 
2005
                                        vibdpt=s->vibdepth;
 
2006
                        } else {
 
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)
 
2010
                                        vibdpt=s->vibdepth;
 
2011
                                else
 
2012
                                        vibdpt=0;
 
2013
                        }
 
2014
                        vibval=(vibval*vibdpt)>>8;
 
2015
                        aout->period-=vibval;
 
2016
                }
 
2017
 
 
2018
                /* update vibrato position */
 
2019
                s->avibpos=(s->avibpos+s->vibrate)&0xff;
 
2020
 
 
2021
                /* process pitch envelope */
 
2022
                playperiod=aout->period;
 
2023
 
 
2024
                if ((aout->pitflg&EF_ON)&&(envpit!=32)) {
 
2025
                        long p1;
 
2026
 
 
2027
                        envpit-=32;
 
2028
                        if ((aout->note<<1)+envpit<=0) envpit=-(aout->note<<1);
 
2029
 
 
2030
                        p1=GetPeriod(((UWORD)aout->note<<1)+envpit,aout->master->speed)-aout->masterperiod;
 
2031
                        if (p1>0) {
 
2032
                                if ((UWORD)(playperiod+p1)<=playperiod) {
 
2033
                                        p1=0;
 
2034
                                        aout->keyoff|=KEY_OFF;
 
2035
                                }
 
2036
                        } else if (p1<0) {
 
2037
                                if ((UWORD)(playperiod+p1)>=playperiod) {
 
2038
                                        p1=0;
 
2039
                                        aout->keyoff|=KEY_OFF;
 
2040
                                }
 
2041
                        }
 
2042
                        playperiod+=p1;
 
2043
                }
 
2044
 
 
2045
                if (!aout->fadevol) { /* check for a dead note (fadevol=0) */
 
2046
                        Voice_Stop_internal(mp_channel);
 
2047
                        pf->totalchn--;
 
2048
                        if ((tmpvol)&&(aout->master)&&(aout->master->slave==aout))
 
2049
                                pf->realchn--;
 
2050
                } else {
 
2051
                        Voice_SetFrequency_internal(mp_channel,
 
2052
                                                    getfrequency(pf->flags,playperiod));
 
2053
 
 
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;
 
2058
                                else
 
2059
                                        aout->fadevol=0;
 
2060
                        }
 
2061
                }
 
2062
 
 
2063
                md_bpm=pf->bpm+pf->relspd;
 
2064
                if (md_bpm<32) md_bpm=32;
 
2065
                else if (md_bpm>255) md_bpm=255;
 
2066
        }
 
2067
}
 
2068
 
 
2069
/* Handles new notes or instruments */
 
2070
void pt_Notes(void)
 
2071
{
 
2072
        UBYTE c,inst;
 
2073
        int tr,funky; /* funky is set to indicate note or instrument change */
 
2074
 
 
2075
        for (mp_channel=0;mp_channel<pf->numchn;mp_channel++) {
 
2076
                a=&pf->control[mp_channel];
 
2077
 
 
2078
                if (pf->sngpos>=pf->numpos) {
 
2079
                        tr=pf->numtrk;
 
2080
                        pf->numrow=0;
 
2081
                } else {
 
2082
                        tr=pf->patterns[(pf->positions[pf->sngpos]*pf->numchn)+mp_channel];
 
2083
                        pf->numrow=pf->pattrows[pf->positions[pf->sngpos]];
 
2084
                }
 
2085
 
 
2086
                a->row=(tr<pf->numtrk)?UniFindRow(pf->tracks[tr],pf->patpos):NULL;
 
2087
                a->newsamp=0;
 
2088
                if (!pf->vbtick) a->notedelay=0;
 
2089
 
 
2090
                if (!a->row) continue;
 
2091
                UniSetRow(a->row);
 
2092
                funky=0;
 
2093
 
 
2094
                while((c=UniGetByte()))
 
2095
                        switch (c) {
 
2096
                                case UNI_NOTE:
 
2097
                                        funky|=1;
 
2098
                                        a->oldnote=a->anote,a->anote=UniGetByte();
 
2099
                                        a->kick =KICK_NOTE;
 
2100
                                        a->start=-1;
 
2101
                                        a->sliding=0;
 
2102
 
 
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;
 
2107
                                        break;
 
2108
                                case UNI_INSTRUMENT:
 
2109
                                        inst=UniGetByte();
 
2110
                                        if (inst>=pf->numins) break; /* safety valve */
 
2111
                                        funky|=2;
 
2112
                                        a->i=(pf->flags & UF_INST)?&pf->instruments[inst]:NULL;
 
2113
                                        a->retrig=0;
 
2114
                                        a->s3mtremor=0;
 
2115
                                        a->sample=inst;
 
2116
                                        break;
 
2117
                                default:
 
2118
                                        UniSkipOpcode(c);
 
2119
                                        break;
 
2120
                        }
 
2121
 
 
2122
                if (funky) {
 
2123
                        INSTRUMENT *i;
 
2124
                        SAMPLE *s;
 
2125
 
 
2126
                        i=a->i;
 
2127
                        if (i) {
 
2128
                                if (i->samplenumber[a->anote] >= pf->numsmp) continue;
 
2129
                                s=&pf->samples[i->samplenumber[a->anote]];
 
2130
                                a->note=i->samplenote[a->anote];
 
2131
                        } else {
 
2132
                                a->note=a->anote;
 
2133
                                s=&pf->samples[a->sample];
 
2134
                        }
 
2135
 
 
2136
                        if (a->s!=s) {
 
2137
                                a->s=s;
 
2138
                                a->newsamp=a->period;
 
2139
                        }
 
2140
 
 
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;
 
2147
 
 
2148
                        a->handle=s->handle;
 
2149
                        a->speed=s->speed;
 
2150
 
 
2151
                        if (i) {
 
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;
 
2157
                                }
 
2158
                                a->pitflg=i->pitflg;
 
2159
                                a->volflg=i->volflg;
 
2160
                                a->panflg=i->panflg;
 
2161
                                a->nna=i->nnatype;
 
2162
                                a->dca=i->dca;
 
2163
                                a->dct=i->dct;
 
2164
                        } else {
 
2165
                                a->pitflg=0;
 
2166
                                a->volflg=0;
 
2167
                                a->panflg=0;
 
2168
                                a->nna=0;
 
2169
                                a->dca=0;
 
2170
                                a->dct=0;
 
2171
                        }
 
2172
 
 
2173
                        if (funky&2) /* instrument change */ {
 
2174
                                /* IT random volume variations: 0:8 bit fixed, and one bit for
 
2175
                                   sign. */
 
2176
                                a->volume=a->tmpvolume=s->volume;
 
2177
                                if ((s)&&(i)) {
 
2178
                                        if (i->rvolvar) {
 
2179
                                                a->volume=a->tmpvolume=s->volume+
 
2180
                                                  ((s->volume*((SLONG)i->rvolvar*(SLONG)getrandom(512)
 
2181
                                                  ))/25600);
 
2182
                                                if (a->volume<0) a->volume=a->tmpvolume=0;
 
2183
                                                else if (a->volume>64) a->volume=a->tmpvolume=64;
 
2184
                                        }
 
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;
 
2190
                                        }
 
2191
                                }
 
2192
                        }
 
2193
 
 
2194
                        a->wantedperiod=a->tmpperiod=GetPeriod((UWORD)a->note<<1,a->speed);
 
2195
                        a->keyoff=KEY_KICK;
 
2196
                }
 
2197
        }
 
2198
}
 
2199
 
 
2200
/* Handles effects */
 
2201
void pt_EffectsPass1(void)
 
2202
{
 
2203
        MP_VOICE *aout;
 
2204
 
 
2205
        for (mp_channel=0;mp_channel<pf->numchn;mp_channel++) {
 
2206
                a=&pf->control[mp_channel];
 
2207
 
 
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;
 
2212
                }
 
2213
 
 
2214
                if (!a->row) continue;
 
2215
                UniSetRow(a->row);
 
2216
 
 
2217
                a->ownper=a->ownvol=0;
 
2218
                explicitslides=0;
 
2219
                pt_playeffects();
 
2220
 
 
2221
                /* continue volume slide if necessary for XM and IT */
 
2222
                if (pf->flags&UF_BGSLIDES) {
 
2223
                        if (!explicitslides)
 
2224
                                switch (a->sliding) {
 
2225
                                        case 1:
 
2226
                                                DoS3MVolSlide(0);
 
2227
                                                break;
 
2228
                                        case 2:
 
2229
                                                DoXMVolSlide(0);
 
2230
                                                break;
 
2231
                                }
 
2232
                        else if (a->tmpvolume) a->sliding=explicitslides;
 
2233
                }
 
2234
 
 
2235
                if (!a->ownper) a->period=a->tmpperiod;
 
2236
                if (!a->ownvol) a->volume=a->tmpvolume;
 
2237
 
 
2238
                if (a->s) {
 
2239
                        if (a->i)
 
2240
                                a->outvolume=(a->volume*a->s->globvol*a->i->globvol)>>10;
 
2241
                        else
 
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;
 
2245
                }
 
2246
        }
 
2247
}
 
2248
 
 
2249
/* NNA management */
 
2250
void pt_NNA(void)
 
2251
{
 
2252
        for (mp_channel=0;mp_channel<pf->numchn;mp_channel++) {
 
2253
                a=&pf->control[mp_channel];
 
2254
 
 
2255
                if (a->kick==KICK_NOTE) {
 
2256
                        BOOL k=0;
 
2257
 
 
2258
                        if (a->slave) {
 
2259
                                MP_VOICE *aout;
 
2260
 
 
2261
                                aout=a->slave;
 
2262
                                if (aout->nna & NNA_MASK) {
 
2263
                                        /* Make sure the old MP_VOICE channel knows it has no
 
2264
                                           master now ! */
 
2265
                                        a->slave=NULL;
 
2266
                                        /* assume the channel is taken by NNA */
 
2267
                                        aout->mflag=0;
 
2268
 
 
2269
                                        switch (aout->nna) {
 
2270
                                                case NNA_CONTINUE: /* continue note, do nothing */
 
2271
                                                        break;
 
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;
 
2276
                                                        break;
 
2277
                                                case NNA_FADE:
 
2278
                                                        aout->keyoff |= KEY_FADE;
 
2279
                                                        break;
 
2280
                                        }
 
2281
                                }
 
2282
                        }
 
2283
 
 
2284
                        if (a->dct!=DCT_OFF) {
 
2285
                                int t;
 
2286
 
 
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)) {
 
2291
                                                k=0;
 
2292
                                                switch (a->dct) {
 
2293
                                                        case DCT_NOTE:
 
2294
                                                                if (a->note==pf->voice[t].note)
 
2295
                                                                        k=1;
 
2296
                                                                break;
 
2297
                                                        case DCT_SAMPLE:
 
2298
                                                                if (a->handle==pf->voice[t].handle)
 
2299
                                                                        k=1;
 
2300
                                                                break;
 
2301
                                                        case DCT_INST:
 
2302
                                                                k=1;
 
2303
                                                                break;
 
2304
                                                }
 
2305
                                                if (k)
 
2306
                                                        switch (a->dca) {
 
2307
                                                                case DCA_CUT:
 
2308
                                                                        pf->voice[t].fadevol=0;
 
2309
                                                                        break;
 
2310
                                                                case DCA_OFF:
 
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;
 
2315
                                                                        break;
 
2316
                                                                case DCA_FADE:
 
2317
                                                                        pf->voice[t].keyoff|=KEY_FADE;
 
2318
                                                                        break;
 
2319
                                                        }
 
2320
                                        }
 
2321
                        }
 
2322
                } /* if (a->kick==KICK_NOTE) */
 
2323
        }
 
2324
}
 
2325
 
 
2326
/* Setup module and NNA voices */
 
2327
void pt_SetupVoices(void)
 
2328
{
 
2329
        MP_VOICE *aout;
 
2330
 
 
2331
        for (mp_channel=0;mp_channel<pf->numchn;mp_channel++) {
 
2332
                a=&pf->control[mp_channel];
 
2333
 
 
2334
                if (a->notedelay) continue;
 
2335
                if (a->kick==KICK_NOTE) {
 
2336
                        /* if no channel was cut above, find an empty or quiet channel
 
2337
                           here */
 
2338
                        if (pf->flags&UF_NNA) {
 
2339
                                if (!a->slave) {
 
2340
                                        int newchn;
 
2341
 
 
2342
                                        if ((newchn=MP_FindEmptyChannel())!=-1)
 
2343
                                                a->slave=&pf->voice[a->slavechn=newchn];
 
2344
                                }
 
2345
                        } else
 
2346
                                a->slave=&pf->voice[a->slavechn=mp_channel];
 
2347
 
 
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;
 
2351
                                a->slave=aout;
 
2352
                                aout->master=a;
 
2353
                                aout->masterchn=mp_channel;
 
2354
                                aout->mflag=1;
 
2355
                        }
 
2356
                } else
 
2357
                        aout=a->slave;
 
2358
 
 
2359
                if (aout) {
 
2360
                        aout->kick=a->kick;
 
2361
                        aout->i=a->i;
 
2362
                        aout->s=a->s;
 
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;
 
2375
                        aout->note=a->note;
 
2376
                        aout->nna=a->nna;
 
2377
                }
 
2378
                a->kick=KICK_ABSENT;
 
2379
        }
 
2380
}
 
2381
 
 
2382
/* second effect pass */
 
2383
void pt_EffectsPass2(void)
 
2384
{
 
2385
        UBYTE c;
 
2386
 
 
2387
        for (mp_channel=0;mp_channel<pf->numchn;mp_channel++) {
 
2388
                a=&pf->control[mp_channel];
 
2389
 
 
2390
                if (!a->row) continue;
 
2391
                UniSetRow(a->row);
 
2392
 
 
2393
                while((c=UniGetByte()))
 
2394
                        if (c==UNI_ITEFFECTS0) {
 
2395
                                c=UniGetByte();
 
2396
                                if ((c>>4)==SS_S7EFFECTS)
 
2397
                                        DoNNAEffects(c&0xf);
 
2398
                        } else
 
2399
                                UniSkipOpcode(c);
 
2400
        }
 
2401
}
 
2402
 
 
2403
void Player_HandleTick(void)
 
2404
{
 
2405
        int max_volume;
 
2406
 
 
2407
#if 0
 
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 */
 
2410
        if (isfirst) {
 
2411
                isfirst--;
 
2412
                return;
 
2413
        }
 
2414
#endif
 
2415
 
 
2416
        if ((!pf)||(pf->forbid)||(pf->sngpos>=pf->numpos)) return;
 
2417
 
 
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;
 
2422
 
 
2423
        if (++pf->vbtick>=pf->sngspd) {
 
2424
                if (pf->pat_repcrazy)
 
2425
                        pf->pat_repcrazy=0; /* play 2 times row 0 */
 
2426
                else
 
2427
                        pf->patpos++;
 
2428
                pf->vbtick=0;
 
2429
 
 
2430
                /* process pattern-delay. pf->patdly2 is the counter and pf->patdly is
 
2431
                   the command memory. */
 
2432
                if (pf->patdly)
 
2433
                        pf->patdly2=pf->patdly,pf->patdly=0;
 
2434
                if (pf->patdly2) {
 
2435
                        /* patterndelay active */
 
2436
                        if (--pf->patdly2)
 
2437
                                /* so turn back pf->patpos by 1 */
 
2438
                                if (pf->patpos) pf->patpos--;
 
2439
                }
 
2440
 
 
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))
 
2444
                        pf->posjmp=3;
 
2445
 
 
2446
                if (pf->posjmp) {
 
2447
                        pf->patpos=pf->numrow?(pf->patbrk%pf->numrow):0;
 
2448
                        pf->pat_repcrazy=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;
 
2452
 
 
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;
 
2462
                                }
 
2463
                        }
 
2464
                        if (pf->sngpos<0) pf->sngpos=pf->numpos-1;
 
2465
                }
 
2466
 
 
2467
                if (!pf->patdly2)
 
2468
                        pt_Notes();
 
2469
        }
 
2470
 
 
2471
        if (((pf->sngpos==pf->numpos-1)||(pf->positions[pf->sngpos+1]==255))&&
 
2472
            (pf->fadeout))
 
2473
                max_volume=pf->numrow?((pf->numrow-pf->patpos)*128)/pf->numrow:0;
 
2474
        else
 
2475
                max_volume=128;
 
2476
 
 
2477
        pt_EffectsPass1();
 
2478
        if (pf->flags&UF_NNA)
 
2479
                pt_NNA();
 
2480
        pt_SetupVoices();
 
2481
        pt_EffectsPass2();
 
2482
 
 
2483
        /* now set up the actual hardware channel playback information */
 
2484
        pt_UpdateVoices(max_volume);
 
2485
}
 
2486
 
 
2487
static void Player_Init_internal(MODULE* mf)
 
2488
{
 
2489
        int t;
 
2490
 
 
2491
        for (t=0;t<mf->numchn;t++) {
 
2492
                mf->control[t].chanvol=mf->chanvol[t];
 
2493
                mf->control[t].panning=mf->panning[t];
 
2494
        }
 
2495
 
 
2496
        mf->sngtime=0;
 
2497
        mf->sngremainder=0;
 
2498
 
 
2499
        mf->pat_repcrazy=0;
 
2500
        mf->sngpos=0;
 
2501
        mf->sngspd=mf->initspeed?(mf->initspeed<32?mf->initspeed:32):6;
 
2502
        mf->volume=mf->initvolume>128?128:mf->initvolume;
 
2503
 
 
2504
        mf->vbtick=mf->sngspd;
 
2505
        mf->patdly=0;
 
2506
        mf->patdly2=0;
 
2507
        mf->bpm=mf->inittempo<32?32:mf->inittempo;
 
2508
        mf->realchn=0;
 
2509
 
 
2510
        mf->patpos=0;
 
2511
        mf->posjmp=2; /* make sure the player fetches the first note */
 
2512
        mf->numrow=-1;
 
2513
        mf->patbrk=0;
 
2514
}
 
2515
 
 
2516
BOOL Player_Init(MODULE* mf)
 
2517
{
 
2518
        mf->extspd=1;
 
2519
        mf->panflag=1;
 
2520
        mf->wrap=0;
 
2521
        mf->loop=1;
 
2522
        mf->fadeout=0;
 
2523
 
 
2524
        mf->relspd=0;
 
2525
 
 
2526
        /* make sure the player doesn't start with garbage */
 
2527
        if (!(mf->control=(MP_CONTROL*)_mm_calloc(mf->numchn,sizeof(MP_CONTROL))))
 
2528
                return 1;
 
2529
        if (!(mf->voice=(MP_VOICE*)_mm_calloc(md_sngchn,sizeof(MP_VOICE))))
 
2530
                return 1;
 
2531
 
 
2532
        Player_Init_internal(mf);
 
2533
        return 0;
 
2534
}
 
2535
 
 
2536
void Player_Exit_internal(MODULE* mf)
 
2537
{
 
2538
        if (!mf) return;
 
2539
        if (mf==pf) {
 
2540
                Player_Stop_internal();
 
2541
                pf=NULL;
 
2542
        }
 
2543
        if (mf->control) free(mf->control);
 
2544
        if (mf->voice) free(mf->voice);
 
2545
        mf->control=NULL;
 
2546
        mf->voice=NULL;
 
2547
}
 
2548
 
 
2549
void Player_Exit(MODULE* mf)
 
2550
{
 
2551
        MUTEX_LOCK(vars);
 
2552
        Player_Exit_internal(mf);
 
2553
        MUTEX_UNLOCK(vars);
 
2554
}
 
2555
 
 
2556
void Player_SetVolume(SWORD volume)
 
2557
{
 
2558
        MUTEX_LOCK(vars);
 
2559
        if (pf)
 
2560
                pf->volume=pf->initvolume=(volume<0)?0:(volume>128)?128:volume;
 
2561
        MUTEX_UNLOCK(vars);
 
2562
}
 
2563
 
 
2564
MODULE* Player_GetModule(void)
 
2565
{
 
2566
        MODULE* result;
 
2567
 
 
2568
        MUTEX_LOCK(vars);
 
2569
        result=pf;
 
2570
        MUTEX_UNLOCK(vars);
 
2571
 
 
2572
        return result;
 
2573
}
 
2574
 
 
2575
void Player_Start(MODULE *mf)
 
2576
{
 
2577
        int t;
 
2578
 
 
2579
        if (!mf) return;
 
2580
 
 
2581
        if (!MikMod_Active())
 
2582
                MikMod_EnableOutput();
 
2583
 
 
2584
        mf->forbid=0;
 
2585
 
 
2586
        MUTEX_LOCK(vars);
 
2587
        if (pf!=mf) {
 
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);
 
2591
        }
 
2592
        pf=mf;
 
2593
        MUTEX_UNLOCK(vars);
 
2594
}
 
2595
 
 
2596
void Player_Stop_internal(void)
 
2597
{
 
2598
        if (!md_sfxchn) MikMod_DisableOutput_internal();
 
2599
        if (pf) pf->forbid=1;
 
2600
        pf=NULL;
 
2601
}
 
2602
 
 
2603
void Player_Stop(void)
 
2604
{
 
2605
        MUTEX_LOCK(vars);
 
2606
                Player_Stop_internal();
 
2607
        MUTEX_UNLOCK(vars);
 
2608
}
 
2609
 
 
2610
BOOL Player_Active(void)
 
2611
{
 
2612
        BOOL result=0;
 
2613
 
 
2614
        MUTEX_LOCK(vars);
 
2615
        if (pf)
 
2616
                result=(!(pf->sngpos>=pf->numpos));
 
2617
        MUTEX_UNLOCK(vars);
 
2618
 
 
2619
        return result;
 
2620
}
 
2621
 
 
2622
void Player_NextPosition(void)
 
2623
{
 
2624
        MUTEX_LOCK(vars);
 
2625
        if (pf) {
 
2626
                int t;
 
2627
 
 
2628
                pf->forbid=1;
 
2629
                pf->posjmp=3;
 
2630
                pf->patbrk=0;
 
2631
                pf->vbtick=pf->sngspd;
 
2632
 
 
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;
 
2637
                }
 
2638
                for (t=0;t<pf->numchn;t++) {
 
2639
                        pf->control[t].i=NULL;
 
2640
                        pf->control[t].s=NULL;
 
2641
                }
 
2642
                pf->forbid=0;
 
2643
        }
 
2644
        MUTEX_UNLOCK(vars);
 
2645
}
 
2646
 
 
2647
void Player_PrevPosition(void)
 
2648
{
 
2649
        MUTEX_LOCK(vars);
 
2650
        if (pf) {
 
2651
                int t;
 
2652
 
 
2653
                pf->forbid=1;
 
2654
                pf->posjmp=1;
 
2655
                pf->patbrk=0;
 
2656
                pf->vbtick=pf->sngspd;
 
2657
 
 
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;
 
2662
                }
 
2663
                for (t=0;t<pf->numchn;t++) {
 
2664
                        pf->control[t].i=NULL;
 
2665
                        pf->control[t].s=NULL;
 
2666
                }
 
2667
                pf->forbid=0;
 
2668
        }
 
2669
        MUTEX_UNLOCK(vars);
 
2670
}
 
2671
 
 
2672
void Player_SetPosition(UWORD pos)
 
2673
{
 
2674
        MUTEX_LOCK(vars);
 
2675
        if (pf) {
 
2676
                int t;
 
2677
 
 
2678
                pf->forbid=1;
 
2679
                if (pos>=pf->numpos) pos=pf->numpos;
 
2680
                pf->posjmp=2;
 
2681
                pf->patbrk=0;
 
2682
                pf->sngpos=pos;
 
2683
                pf->vbtick=pf->sngspd;
 
2684
 
 
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;
 
2689
                }
 
2690
                for (t=0;t<pf->numchn;t++) {
 
2691
                        pf->control[t].i=NULL;
 
2692
                        pf->control[t].s=NULL;
 
2693
                }
 
2694
                pf->forbid=0;
 
2695
 
 
2696
                if (!pos)
 
2697
                        Player_Init_internal(pf);
 
2698
        }
 
2699
        MUTEX_UNLOCK(vars);
 
2700
}
 
2701
 
 
2702
static void Player_Unmute_internal(SLONG arg1,va_list ap)
 
2703
{
 
2704
        SLONG t,arg2,arg3=0;
 
2705
 
 
2706
        if (pf) {
 
2707
                switch (arg1) {
 
2708
                        case MUTE_INCLUSIVE:
 
2709
                                if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
 
2710
                                   (arg2>arg3)||(arg3>=pf->numchn))
 
2711
                                        return;
 
2712
                                for (;arg2<pf->numchn && arg2<=arg3;arg2++)
 
2713
                                        pf->control[arg2].muted=0;
 
2714
                                break;
 
2715
                        case MUTE_EXCLUSIVE:
 
2716
                                if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
 
2717
                                   (arg2>arg3)||(arg3>=pf->numchn))
 
2718
                                        return;
 
2719
                                for (t=0;t<pf->numchn;t++) {
 
2720
                                        if ((t>=arg2) && (t<=arg3)) continue;
 
2721
                                        pf->control[t].muted=0;
 
2722
                                }
 
2723
                                break;
 
2724
                        default:
 
2725
                                if (arg1<pf->numchn) pf->control[arg1].muted=0;
 
2726
                                break;
 
2727
                }
 
2728
        }
 
2729
}
 
2730
 
 
2731
void Player_Unmute(SLONG arg1, ...)
 
2732
{
 
2733
        va_list args;
 
2734
 
 
2735
        va_start(args,arg1);
 
2736
        MUTEX_LOCK(vars);
 
2737
        Player_Unmute_internal(arg1,args);
 
2738
        MUTEX_UNLOCK(vars);
 
2739
        va_end(args);
 
2740
}
 
2741
 
 
2742
static void Player_Mute_internal(SLONG arg1,va_list ap)
 
2743
{
 
2744
        SLONG t,arg2,arg3=0;
 
2745
 
 
2746
        if (pf) {
 
2747
                switch (arg1) {
 
2748
                        case MUTE_INCLUSIVE:
 
2749
                                if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
 
2750
                                    (arg2>arg3)||(arg3>=pf->numchn))
 
2751
                                        return;
 
2752
                                for (;arg2<pf->numchn && arg2<=arg3;arg2++)
 
2753
                                        pf->control[arg2].muted=1;
 
2754
                                break;
 
2755
                        case MUTE_EXCLUSIVE:
 
2756
                                if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
 
2757
                                    (arg2>arg3)||(arg3>=pf->numchn))
 
2758
                                        return;
 
2759
                                for (t=0;t<pf->numchn;t++) {
 
2760
                                        if ((t>=arg2) && (t<=arg3)) continue;
 
2761
                                        pf->control[t].muted=1;
 
2762
                                }
 
2763
                                break;
 
2764
                        default:
 
2765
                                if (arg1<pf->numchn)
 
2766
                                        pf->control[arg1].muted=1;
 
2767
                                break;
 
2768
                }
 
2769
        }
 
2770
}
 
2771
 
 
2772
void Player_Mute(SLONG arg1,...)
 
2773
{
 
2774
        va_list args;
 
2775
 
 
2776
        va_start(args,arg1);
 
2777
        MUTEX_LOCK(vars);
 
2778
        Player_Mute_internal(arg1,args);
 
2779
        MUTEX_UNLOCK(vars);
 
2780
        va_end(args);
 
2781
}
 
2782
 
 
2783
static void Player_ToggleMute_internal(SLONG arg1,va_list ap)
 
2784
{
 
2785
        SLONG arg2,arg3=0;
 
2786
        ULONG t;
 
2787
 
 
2788
        if (pf) {
 
2789
                switch (arg1) {
 
2790
                        case MUTE_INCLUSIVE:
 
2791
                                if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
 
2792
                                    (arg2>arg3)||(arg3>=pf->numchn))
 
2793
                                        return;
 
2794
                                for (;arg2<pf->numchn && arg2<=arg3;arg2++)
 
2795
                                        pf->control[arg2].muted=1-pf->control[arg2].muted;
 
2796
                                break;
 
2797
                        case MUTE_EXCLUSIVE:
 
2798
                                if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
 
2799
                                    (arg2>arg3)||(arg3>=pf->numchn))
 
2800
                                        return;
 
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;
 
2804
                                }
 
2805
                                break;
 
2806
                        default:
 
2807
                                if (arg1<pf->numchn)
 
2808
                                        pf->control[arg1].muted=1-pf->control[arg1].muted;
 
2809
                                break;
 
2810
                }
 
2811
        }
 
2812
}
 
2813
 
 
2814
void Player_ToggleMute(SLONG arg1,...)
 
2815
{
 
2816
        va_list args;
 
2817
 
 
2818
        va_start(args,arg1);
 
2819
        MUTEX_LOCK(vars);
 
2820
        Player_ToggleMute_internal(arg1,args);
 
2821
        MUTEX_UNLOCK(vars);
 
2822
        va_end(args);
 
2823
}
 
2824
 
 
2825
BOOL Player_Muted(UBYTE chan)
 
2826
{
 
2827
        BOOL result=1;
 
2828
 
 
2829
        MUTEX_LOCK(vars);
 
2830
        if (pf)
 
2831
                result=(chan<pf->numchn)?pf->control[chan].muted:1;
 
2832
        MUTEX_UNLOCK(vars);
 
2833
 
 
2834
        return result;
 
2835
}
 
2836
 
 
2837
int Player_GetChannelVoice(UBYTE chan)
 
2838
{
 
2839
        int result=0;
 
2840
 
 
2841
        MUTEX_LOCK(vars);
 
2842
        if (pf)
 
2843
                result=(chan<pf->numchn)?pf->control[chan].slavechn:-1;
 
2844
        MUTEX_UNLOCK(vars);
 
2845
 
 
2846
        return result;
 
2847
}
 
2848
 
 
2849
UWORD Player_GetChannelPeriod(UBYTE chan)
 
2850
{
 
2851
        UWORD result=0;
 
2852
 
 
2853
        MUTEX_LOCK(vars);
 
2854
    if (pf)
 
2855
            result=(chan<pf->numchn)?pf->control[chan].period:0;
 
2856
        MUTEX_UNLOCK(vars);
 
2857
 
 
2858
        return result;
 
2859
}
 
2860
 
 
2861
BOOL Player_Paused_internal(void)
 
2862
{
 
2863
        return pf?pf->forbid:1;
 
2864
}
 
2865
 
 
2866
BOOL Player_Paused(void)
 
2867
{
 
2868
        BOOL result;
 
2869
 
 
2870
        MUTEX_LOCK(vars);
 
2871
        result=Player_Paused_internal();
 
2872
        MUTEX_UNLOCK(vars);
 
2873
 
 
2874
        return result;
 
2875
}
 
2876
 
 
2877
void Player_TogglePause(void)
 
2878
{
 
2879
        MUTEX_LOCK(vars);
 
2880
        if (pf)
 
2881
                pf->forbid=1-pf->forbid;
 
2882
        MUTEX_UNLOCK(vars);
 
2883
}
 
2884
 
 
2885
void Player_SetSpeed(UWORD speed)
 
2886
{
 
2887
        MUTEX_LOCK(vars);
 
2888
        if (pf)
 
2889
                pf->sngspd=speed?(speed<32?speed:32):1;
 
2890
        MUTEX_UNLOCK(vars);
 
2891
}
 
2892
 
 
2893
void Player_SetTempo(UWORD tempo)
 
2894
{
 
2895
        if (tempo<32) tempo=32;
 
2896
 
 
2897
        MUTEX_LOCK(vars);
 
2898
        if (pf) {
 
2899
                if ((!(pf->flags&UF_HIGHBPM))&&(tempo>255)) tempo=255;
 
2900
                pf->bpm=tempo;
 
2901
        }
 
2902
        MUTEX_UNLOCK(vars);
 
2903
}
 
2904
 
 
2905
static int _pl_synchro_value;
 
2906
void Player_SetSynchroValue(int i)
 
2907
{
 
2908
        _pl_synchro_value = i;
 
2909
}
 
2910
 
 
2911
int Player_GetSynchroValue(void)
 
2912
{
 
2913
        return _pl_synchro_value;
 
2914
}
 
2915
        
 
2916
 
 
2917
/* ex:set ts=4: */