Mercurial > ~darius > hgwebdir.cgi > mikmod
comparison playercode/mplayer.c @ 7:de95ce2eacfd
Initial revision
author | darius |
---|---|
date | Fri, 23 Jan 1998 16:05:09 +0000 |
parents | |
children | 437e8455d862 |
comparison
equal
deleted
inserted
replaced
6:d14fd386d182 | 7:de95ce2eacfd |
---|---|
1 /* | |
2 --> The Protracker Player Driver | |
3 -> Part of the SPLAYER pack for MikMod 3.0 | |
4 | |
5 The protracker driver supports all base Protracker 3.x commands and fea- | |
6 tures. | |
7 */ | |
8 | |
9 #include <string.h> | |
10 #include <stdarg.h> | |
11 #include "mikmod.h" | |
12 | |
13 | |
14 static void DoNNAEffects(UBYTE dat); | |
15 | |
16 // Set forbid to 1 when you want to modify any of the pf->sngpos, pf->patpos etc. | |
17 // variables and clear it when you're done. This prevents getting strange | |
18 // results due to intermediate interrupts. | |
19 | |
20 static UNIMOD *pf; // <- this modfile is being played | |
21 static SWORD mp_channel; // channel it's working on | |
22 static MP_CONTROL *a; // current AUDTMP it's working on | |
23 static int isfirst; | |
24 | |
25 static MP_VOICE aout_dummy; | |
26 | |
27 static UWORD mytab[12] = | |
28 { 1712*16, 1616*16, 1524*16, 1440*16, 1356*16, 1280*16, | |
29 1208*16, 1140*16, 1076*16, 1016*16, 960*16, 907*16 | |
30 }; | |
31 | |
32 | |
33 static UBYTE VibratoTable[32] = | |
34 { 0,24,49,74,97,120,141,161, | |
35 180,197,212,224,235,244,250,253, | |
36 255,253,250,244,235,224,212,197, | |
37 180,161,141,120,97,74,49,24 | |
38 }; | |
39 | |
40 | |
41 static UBYTE avibtab[128] = | |
42 { 0,1,3,4,6,7,9,10,12,14,15,17,18,20,21,23, | |
43 24,25,27,28,30,31,32,34,35,36,38,39,40,41,42,44, | |
44 45,46,47,48,49,50,51,52,53,54,54,55,56,57,57,58, | |
45 59,59,60,60,61,61,62,62,62,63,63,63,63,63,63,63, | |
46 64,63,63,63,63,63,63,63,62,62,62,61,61,60,60,59, | |
47 59,58,57,57,56,55,54,54,53,52,51,50,49,48,47,46, | |
48 45,44,42,41,40,39,38,36,35,34,32,31,30,28,27,25, | |
49 24,23,21,20,18,17,15,14,12,10,9,7,6,4,3,1 | |
50 }; | |
51 | |
52 | |
53 // ** Triton's linear periods to frequency translation table (for | |
54 // ** Fast Tracker 2 [XM] modules): | |
55 | |
56 static ULONG lintab[768] = | |
57 { 535232,534749,534266,533784,533303,532822,532341,531861, | |
58 531381,530902,530423,529944,529466,528988,528511,528034, | |
59 527558,527082,526607,526131,525657,525183,524709,524236, | |
60 523763,523290,522818,522346,521875,521404,520934,520464, | |
61 519994,519525,519057,518588,518121,517653,517186,516720, | |
62 516253,515788,515322,514858,514393,513929,513465,513002, | |
63 512539,512077,511615,511154,510692,510232,509771,509312, | |
64 508852,508393,507934,507476,507018,506561,506104,505647, | |
65 505191,504735,504280,503825,503371,502917,502463,502010, | |
66 501557,501104,500652,500201,499749,499298,498848,498398, | |
67 497948,497499,497050,496602,496154,495706,495259,494812, | |
68 494366,493920,493474,493029,492585,492140,491696,491253, | |
69 490809,490367,489924,489482,489041,488600,488159,487718, | |
70 487278,486839,486400,485961,485522,485084,484647,484210, | |
71 483773,483336,482900,482465,482029,481595,481160,480726, | |
72 480292,479859,479426,478994,478562,478130,477699,477268, | |
73 476837,476407,475977,475548,475119,474690,474262,473834, | |
74 473407,472979,472553,472126,471701,471275,470850,470425, | |
75 470001,469577,469153,468730,468307,467884,467462,467041, | |
76 466619,466198,465778,465358,464938,464518,464099,463681, | |
77 463262,462844,462427,462010,461593,461177,460760,460345, | |
78 459930,459515,459100,458686,458272,457859,457446,457033, | |
79 456621,456209,455797,455386,454975,454565,454155,453745, | |
80 453336,452927,452518,452110,451702,451294,450887,450481, | |
81 450074,449668,449262,448857,448452,448048,447644,447240, | |
82 446836,446433,446030,445628,445226,444824,444423,444022, | |
83 443622,443221,442821,442422,442023,441624,441226,440828, | |
84 440430,440033,439636,439239,438843,438447,438051,437656, | |
85 437261,436867,436473,436079,435686,435293,434900,434508, | |
86 434116,433724,433333,432942,432551,432161,431771,431382, | |
87 430992,430604,430215,429827,429439,429052,428665,428278, | |
88 427892,427506,427120,426735,426350,425965,425581,425197, | |
89 424813,424430,424047,423665,423283,422901,422519,422138, | |
90 421757,421377,420997,420617,420237,419858,419479,419101, | |
91 418723,418345,417968,417591,417214,416838,416462,416086, | |
92 415711,415336,414961,414586,414212,413839,413465,413092, | |
93 412720,412347,411975,411604,411232,410862,410491,410121, | |
94 409751,409381,409012,408643,408274,407906,407538,407170, | |
95 406803,406436,406069,405703,405337,404971,404606,404241, | |
96 403876,403512,403148,402784,402421,402058,401695,401333, | |
97 400970,400609,400247,399886,399525,399165,398805,398445, | |
98 398086,397727,397368,397009,396651,396293,395936,395579, | |
99 395222,394865,394509,394153,393798,393442,393087,392733, | |
100 392378,392024,391671,391317,390964,390612,390259,389907, | |
101 389556,389204,388853,388502,388152,387802,387452,387102, | |
102 386753,386404,386056,385707,385359,385012,384664,384317, | |
103 383971,383624,383278,382932,382587,382242,381897,381552, | |
104 381208,380864,380521,380177,379834,379492,379149,378807, | |
105 | |
106 378466,378124,377783,377442,377102,376762,376422,376082, | |
107 375743,375404,375065,374727,374389,374051,373714,373377, | |
108 373040,372703,372367,372031,371695,371360,371025,370690, | |
109 370356,370022,369688,369355,369021,368688,368356,368023, | |
110 367691,367360,367028,366697,366366,366036,365706,365376, | |
111 365046,364717,364388,364059,363731,363403,363075,362747, | |
112 362420,362093,361766,361440,361114,360788,360463,360137, | |
113 359813,359488,359164,358840,358516,358193,357869,357547, | |
114 357224,356902,356580,356258,355937,355616,355295,354974, | |
115 354654,354334,354014,353695,353376,353057,352739,352420, | |
116 352103,351785,351468,351150,350834,350517,350201,349885, | |
117 349569,349254,348939,348624,348310,347995,347682,347368, | |
118 347055,346741,346429,346116,345804,345492,345180,344869, | |
119 344558,344247,343936,343626,343316,343006,342697,342388, | |
120 342079,341770,341462,341154,340846,340539,340231,339924, | |
121 339618,339311,339005,338700,338394,338089,337784,337479, | |
122 337175,336870,336566,336263,335959,335656,335354,335051, | |
123 334749,334447,334145,333844,333542,333242,332941,332641, | |
124 332341,332041,331741,331442,331143,330844,330546,330247, | |
125 329950,329652,329355,329057,328761,328464,328168,327872, | |
126 327576,327280,326985,326690,326395,326101,325807,325513, | |
127 325219,324926,324633,324340,324047,323755,323463,323171, | |
128 322879,322588,322297,322006,321716,321426,321136,320846, | |
129 320557,320267,319978,319690,319401,319113,318825,318538, | |
130 318250,317963,317676,317390,317103,316817,316532,316246, | |
131 315961,315676,315391,315106,314822,314538,314254,313971, | |
132 313688,313405,313122,312839,312557,312275,311994,311712, | |
133 311431,311150,310869,310589,310309,310029,309749,309470, | |
134 309190,308911,308633,308354,308076,307798,307521,307243, | |
135 306966,306689,306412,306136,305860,305584,305308,305033, | |
136 304758,304483,304208,303934,303659,303385,303112,302838, | |
137 302565,302292,302019,301747,301475,301203,300931,300660, | |
138 300388,300117,299847,299576,299306,299036,298766,298497, | |
139 298227,297958,297689,297421,297153,296884,296617,296349, | |
140 296082,295815,295548,295281,295015,294749,294483,294217, | |
141 293952,293686,293421,293157,292892,292628,292364,292100, | |
142 291837,291574,291311,291048,290785,290523,290261,289999, | |
143 289737,289476,289215,288954,288693,288433,288173,287913, | |
144 287653,287393,287134,286875,286616,286358,286099,285841, | |
145 285583,285326,285068,284811,284554,284298,284041,283785, | |
146 283529,283273,283017,282762,282507,282252,281998,281743, | |
147 281489,281235,280981,280728,280475,280222,279969,279716, | |
148 279464,279212,278960,278708,278457,278206,277955,277704, | |
149 277453,277203,276953,276703,276453,276204,275955,275706, | |
150 275457,275209,274960,274712,274465,274217,273970,273722, | |
151 273476,273229,272982,272736,272490,272244,271999,271753, | |
152 271508,271263,271018,270774,270530,270286,270042,269798, | |
153 269555,269312,269069,268826,268583,268341,268099,267857 | |
154 }; | |
155 | |
156 | |
157 #define LOGFAC 2*16 | |
158 | |
159 static UWORD logtab[104] = | |
160 { LOGFAC*907,LOGFAC*900,LOGFAC*894,LOGFAC*887,LOGFAC*881,LOGFAC*875,LOGFAC*868,LOGFAC*862, | |
161 LOGFAC*856,LOGFAC*850,LOGFAC*844,LOGFAC*838,LOGFAC*832,LOGFAC*826,LOGFAC*820,LOGFAC*814, | |
162 LOGFAC*808,LOGFAC*802,LOGFAC*796,LOGFAC*791,LOGFAC*785,LOGFAC*779,LOGFAC*774,LOGFAC*768, | |
163 LOGFAC*762,LOGFAC*757,LOGFAC*752,LOGFAC*746,LOGFAC*741,LOGFAC*736,LOGFAC*730,LOGFAC*725, | |
164 LOGFAC*720,LOGFAC*715,LOGFAC*709,LOGFAC*704,LOGFAC*699,LOGFAC*694,LOGFAC*689,LOGFAC*684, | |
165 LOGFAC*678,LOGFAC*675,LOGFAC*670,LOGFAC*665,LOGFAC*660,LOGFAC*655,LOGFAC*651,LOGFAC*646, | |
166 LOGFAC*640,LOGFAC*636,LOGFAC*632,LOGFAC*628,LOGFAC*623,LOGFAC*619,LOGFAC*614,LOGFAC*610, | |
167 LOGFAC*604,LOGFAC*601,LOGFAC*597,LOGFAC*592,LOGFAC*588,LOGFAC*584,LOGFAC*580,LOGFAC*575, | |
168 LOGFAC*570,LOGFAC*567,LOGFAC*563,LOGFAC*559,LOGFAC*555,LOGFAC*551,LOGFAC*547,LOGFAC*543, | |
169 LOGFAC*538,LOGFAC*535,LOGFAC*532,LOGFAC*528,LOGFAC*524,LOGFAC*520,LOGFAC*516,LOGFAC*513, | |
170 LOGFAC*508,LOGFAC*505,LOGFAC*502,LOGFAC*498,LOGFAC*494,LOGFAC*491,LOGFAC*487,LOGFAC*484, | |
171 LOGFAC*480,LOGFAC*477,LOGFAC*474,LOGFAC*470,LOGFAC*467,LOGFAC*463,LOGFAC*460,LOGFAC*457, | |
172 LOGFAC*453,LOGFAC*450,LOGFAC*447,LOGFAC*443,LOGFAC*440,LOGFAC*437,LOGFAC*434,LOGFAC*431 | |
173 }; | |
174 | |
175 static SBYTE PanbrelloTable[256] = | |
176 { 0,2,3,5,6,8,9,11,12,14,16,17,19,20,22,23, | |
177 24,26,27,29,30,32,33,34,36,37,38,39,41,42,43,44, | |
178 45,46,47,48,49,50,51,52,53,54,55,56,56,57,58,59, | |
179 59,60,60,61,61,62,62,62,63,63,63,64,64,64,64,64, | |
180 64,64,64,64,64,64,63,63,63,62,62,62,61,61,60,60, | |
181 59,59,58,57,56,56,55,54,53,52,51,50,49,48,47,46, | |
182 45,44,43,42,41,39,38,37,36,34,33,32,30,29,27,26, | |
183 24,23,22,20,19,17,16,14,12,11,9,8,6,5,3,2, | |
184 0,-2,-3,-5,-6,-8,-9,-11,-12,-14,-16,-17,-19,-20,-22,-23, | |
185 -24,-26,-27,-29,-30,-32,-33,-34,-36,-37,-38,-39,-41,-42,-43,-44, | |
186 -45,-46,-47,-48,-49,-50,-51,-52,-53,-54,-55,-56,-56,-57,-58,-59, | |
187 -59,-60,-60,-61,-61,-62,-62,-62,-63,-63,-63,-64,-64,-64,-64,-64, | |
188 -64,-64,-64,-64,-64,-64,-63,-63,-63,-62,-62,-62,-61,-61,-60,-60, | |
189 -59,-59,-58,-57,-56,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46, | |
190 -45,-44,-43,-42,-41,-39,-38,-37,-36,-34,-33,-32,-30,-29,-27,-26, | |
191 -24,-23,-22,-20,-19,-17,-16,-14,-12,-11,-9,-8,-6,-5,-3,-2 | |
192 }; | |
193 | |
194 | |
195 /* New Note Action Scoring System: | |
196 --------------------------------- | |
197 1) total-volume (fadevol, chanvol, volume) is the main scorer. | |
198 2) a looping sample is a bonus x2 | |
199 3) a forground channel is a bonus x4 | |
200 4) an active envelope with keyoff is a handicap -x2 | |
201 */ | |
202 static int MP_FindEmptyChannel(int curchan) // returns mp_control index of free channel | |
203 { | |
204 MP_VOICE *a; | |
205 ULONG t,k,tvol,p,pp; | |
206 | |
207 /*for(t=md_sngchn; t; t--, audpool++) | |
208 { if(audpool == md_sngchn) audpool = 0; | |
209 if(!(pf->voice[audpool].kick) && Voice_Stopped(audpool)) | |
210 { audpool++; | |
211 return audpool-1; | |
212 } | |
213 }*/ | |
214 | |
215 for(t=0; t<md_sngchn; t++) | |
216 { if(!(pf->voice[t].kick) && Voice_Stopped(t)) | |
217 { return t; | |
218 } | |
219 } | |
220 | |
221 tvol = 0xffffffUL; t = 0; p = 0; a = pf->voice; | |
222 for(k=0; k<md_sngchn; k++, a++) | |
223 { if(!a->kick) | |
224 { pp = a->totalvol << ((a->s->flags & SF_LOOP) ? 1 : 0); | |
225 if((a->master!=NULL) && (a==a->master->slave)) | |
226 pp <<= 2; | |
227 | |
228 /*if(a->volflg & EF_ON) | |
229 { if(a->volflg & (EF_SUSTAIN | EF_LOOP)) | |
230 { if(a->keyoff & KEY_OFF) | |
231 { pp >>= 1; | |
232 if(a->venv.env[a->venv.end].val < 32) pp>>=1; | |
233 } else | |
234 pp <<= 1; | |
235 } else pp <<= 1; | |
236 }*/ | |
237 | |
238 if(pp < tvol) | |
239 { tvol = pp; | |
240 t = k; | |
241 } | |
242 } | |
243 } | |
244 | |
245 if(tvol>8000*7) return -1; //mp_channel; | |
246 | |
247 return t; | |
248 } | |
249 | |
250 | |
251 static SWORD Interpolate(SWORD p, SWORD p1, SWORD p2, SWORD v1, SWORD v2) | |
252 { | |
253 SWORD dp,dv,di; | |
254 | |
255 if(p1==p2) return v1; | |
256 | |
257 dv = v2-v1; | |
258 dp = p2-p1; | |
259 di = p-p1; | |
260 | |
261 return v1 + ((SLONG)(di*dv) / dp); | |
262 } | |
263 | |
264 | |
265 UWORD getlinearperiod(UBYTE note, ULONG fine) | |
266 { | |
267 return((10L*12*16*4)-((ULONG)note*16*4)-(fine/2)+64); | |
268 } | |
269 | |
270 | |
271 static UWORD getlogperiod(UBYTE note,ULONG fine) | |
272 { | |
273 UBYTE n,o; | |
274 UWORD p1,p2; | |
275 ULONG i; | |
276 | |
277 n = note%12; | |
278 o = note/12; | |
279 i = (n<<3) + (fine>>4); // n*8 + fine/16 | |
280 | |
281 p1 = logtab[i]; | |
282 p2 = logtab[i+1]; | |
283 | |
284 return(Interpolate(fine/16,0,15,p1,p2)>>o); | |
285 } | |
286 | |
287 | |
288 static UWORD getoldperiod(UBYTE note, ULONG speed) | |
289 { | |
290 UBYTE n, o; | |
291 ULONG period; | |
292 | |
293 if(!speed) return 4242; // <- prevent divide overflow.. (42 eheh) | |
294 | |
295 n = note % 12; | |
296 o = note / 12; | |
297 period = ((8363l*(ULONG)mytab[n]) >> o ) / speed; | |
298 return period; | |
299 } | |
300 | |
301 | |
302 static UWORD GetPeriod(UBYTE note, ULONG speed) | |
303 { | |
304 if(pf->flags & UF_XMPERIODS) | |
305 return (pf->flags & UF_LINEAR) ? getlinearperiod(note,speed) : getlogperiod(note,speed); | |
306 | |
307 return getoldperiod(note,speed); | |
308 } | |
309 | |
310 | |
311 static SWORD InterpolateEnv(SWORD p, ENVPT *a, ENVPT *b) | |
312 { | |
313 return(Interpolate(p,a->pos,b->pos,a->val,b->val)); | |
314 } | |
315 | |
316 | |
317 static SWORD DoPan(SWORD envpan, SWORD pan) | |
318 { | |
319 return(pan + (((envpan-128)*(128-abs(pan-128)))/128)); | |
320 } | |
321 | |
322 | |
323 static void StartEnvelope(ENVPR *t, UBYTE flg, UBYTE pts, UBYTE susbeg, UBYTE susend, UBYTE beg, UBYTE end, ENVPT *p, UBYTE keyoff) | |
324 { | |
325 t->flg = flg; | |
326 t->pts = pts; | |
327 t->susbeg = susbeg; | |
328 t->susend = susend; | |
329 t->beg = beg; | |
330 t->end = end; | |
331 t->env = p; | |
332 t->p = 0; | |
333 t->a = 0; | |
334 t->b = ((t->flg & EF_SUSTAIN) && !(keyoff & KEY_OFF)) ? 0 : 1; | |
335 } | |
336 | |
337 | |
338 static SWORD ProcessEnvelope(ENVPR *t, SWORD v, UBYTE keyoff) | |
339 | |
340 // This procedure processes all envelope types, include volume, pitch, and | |
341 // panning. Envelopes are defined by a set of points, each with a magnitude | |
342 // [relating either to volume, panniong position, or pitch modifier] and a | |
343 // tick position. | |
344 // | |
345 // Envelopes work in the following manner: | |
346 // | |
347 // (a) Each tick the envelope is moved a point further in its progression. | |
348 // 1. For an accurate progression, magnitudes between two envelope points | |
349 // are interpolated. | |
350 // | |
351 // (b) When progression reaches a defined point on the envelope, values | |
352 // are shifted to interpolate between this point and the next, | |
353 // and checks for loops or envelope end are done. | |
354 // | |
355 // Misc: | |
356 // Sustain loops are loops that are only active as long as the keyoff | |
357 // flag is clear. When a volume envelope terminates, so does the current | |
358 // fadeout. | |
359 | |
360 { | |
361 if(t->flg & EF_ON) | |
362 { UBYTE a, b; // actual points in the envelope | |
363 UWORD p; // the 'tick counter' - real point being played | |
364 | |
365 a = t->a; | |
366 b = t->b; | |
367 p = t->p; | |
368 | |
369 // compute the current envelope value between points a and b | |
370 | |
371 if(a == b) | |
372 v = t->env[a].val; | |
373 else | |
374 v = InterpolateEnv(p, &t->env[a], &t->env[b]); | |
375 | |
376 p++; | |
377 | |
378 // pointer reached point b? | |
379 | |
380 if(p >= t->env[b].pos) | |
381 { a = b++; // shift points a and b | |
382 | |
383 // Check for loops, sustain loops, or end of envelope. | |
384 | |
385 if((t->flg & EF_SUSTAIN) && !(keyoff & KEY_OFF) && (b > t->susend)) | |
386 { a = t->susbeg; | |
387 if(t->susbeg == t->susend) b = a; else b = a + 1; | |
388 p = t->env[a].pos; | |
389 } else if((t->flg & EF_LOOP) && (b > t->end)) | |
390 { a = t->beg; | |
391 if(t->beg == t->end) b = a; else b = a + 1; | |
392 p = t->env[a].pos; | |
393 } else | |
394 { if(b >= t->pts) | |
395 { if((t->flg & EF_VOLENV) && (mp_channel != -1)) | |
396 { pf->voice[mp_channel].keyoff |= KEY_FADE; | |
397 if(v==0) | |
398 pf->voice[mp_channel].fadevol = 0; | |
399 } | |
400 b--; p--; | |
401 } | |
402 } | |
403 } | |
404 t->a = a; | |
405 t->b = b; | |
406 t->p = p; | |
407 } | |
408 return v; | |
409 } | |
410 | |
411 | |
412 ULONG getfrequency(UBYTE flags, ULONG period) | |
413 | |
414 // XM linear period to frequency conversion | |
415 | |
416 { | |
417 ULONG result; | |
418 | |
419 if(flags & UF_LINEAR) | |
420 result = lintab[period % 768] >> (period / 768); | |
421 else | |
422 result = (8363L*1712L) / period; | |
423 | |
424 return result; | |
425 } | |
426 | |
427 | |
428 static void DoEEffects(UBYTE dat) | |
429 { | |
430 UBYTE nib; | |
431 | |
432 nib = dat & 0xf; | |
433 | |
434 switch(dat>>4) | |
435 { case 0x0: // filter toggle, not supported | |
436 break; | |
437 | |
438 case 0x1: // fineslide up | |
439 if(!pf->vbtick) a->tmpperiod-=(nib<<2); | |
440 break; | |
441 | |
442 case 0x2: // fineslide dn | |
443 if(!pf->vbtick) a->tmpperiod+=(nib<<2); | |
444 break; | |
445 | |
446 case 0x3: // glissando ctrl | |
447 a->glissando = nib; | |
448 break; | |
449 | |
450 case 0x4: // set vibrato waveform | |
451 a->wavecontrol &= 0xf0; | |
452 a->wavecontrol |= nib; | |
453 break; | |
454 | |
455 case 0x5: // set finetune | |
456 // a->speed=finetune[nib]; | |
457 // a->tmpperiod=GetPeriod(a->note,pf->samples[a->sample].transpose,a->speed); | |
458 break; | |
459 | |
460 case 0x6: // set patternloop | |
461 if(pf->vbtick) break; | |
462 // hmm.. this one is a real kludge. But now it | |
463 // works | |
464 if(nib) // set reppos or repcnt ? | |
465 { // set repcnt, so check if repcnt already is set, | |
466 // which means we are already looping | |
467 | |
468 if(pf->pat_repcnt > 0) | |
469 pf->pat_repcnt--; // already looping, decrease counter | |
470 else | |
471 pf->pat_repcnt = nib; // not yet looping, so set repcnt | |
472 | |
473 if(pf->pat_repcnt) // jump to reppos if repcnt>0 | |
474 pf->patpos = pf->pat_reppos; | |
475 } else | |
476 { pf->pat_reppos = pf->patpos-1; // set reppos | |
477 } | |
478 break; | |
479 | |
480 | |
481 case 0x7: // set tremolo waveform | |
482 a->wavecontrol &= 0x0f; | |
483 a->wavecontrol |= nib << 4; | |
484 break; | |
485 | |
486 case 0x8: // set panning | |
487 if(pf->panflag) | |
488 { if(nib<=8) nib*=16; else nib*=17; | |
489 a->panning = nib; | |
490 pf->panning[mp_channel] = nib; | |
491 } | |
492 break; | |
493 | |
494 case 0x9: // retrig note | |
495 // only retrigger if | |
496 // data nibble > 0 | |
497 | |
498 if(nib > 0) | |
499 { if(a->retrig==0) | |
500 { // when retrig counter reaches 0, | |
501 // reset counter and restart the sample | |
502 a->kick = 1; | |
503 a->retrig = nib; | |
504 } | |
505 a->retrig--; // countdown | |
506 } | |
507 break; | |
508 | |
509 case 0xa: // fine volume slide up | |
510 if(pf->vbtick) break; | |
511 | |
512 a->tmpvolume += nib; | |
513 if(a->tmpvolume > 64) a->tmpvolume = 64; | |
514 break; | |
515 | |
516 case 0xb: // fine volume slide dn | |
517 if(pf->vbtick) break; | |
518 | |
519 a->tmpvolume -= nib; | |
520 if(a->tmpvolume < 0) a->tmpvolume = 0; | |
521 break; | |
522 | |
523 case 0xc: // cut note | |
524 // When pf->vbtick reaches the cut-note value, | |
525 // turn the volume to zero ( Just like | |
526 // on the amiga) | |
527 if(pf->vbtick>=nib) | |
528 a->tmpvolume = 0; // just turn the volume down | |
529 break; | |
530 | |
531 case 0xd: // note delay | |
532 // delay the start of the | |
533 // sample until pf->vbtick==nib | |
534 if(pf->vbtick==nib) | |
535 { //a->kick = 1; | |
536 a->notedelay = 0; | |
537 } else if(pf->vbtick==0) | |
538 { //a->kick = 0; | |
539 a->notedelay = 1; | |
540 } | |
541 break; | |
542 | |
543 case 0xe: // pattern delay | |
544 if(pf->vbtick) break; | |
545 if(!pf->patdly2) pf->patdly = nib+1; // only once (when pf->vbtick=0) | |
546 break; | |
547 | |
548 case 0xf: // invert loop, not supported | |
549 break; | |
550 } | |
551 } | |
552 | |
553 | |
554 static void DoVibrato(void) | |
555 { | |
556 UBYTE q; | |
557 UWORD temp; | |
558 | |
559 q = (a->vibpos>>2)&0x1f; | |
560 | |
561 switch(a->wavecontrol&3) | |
562 { case 0: // sine | |
563 temp = VibratoTable[q]; | |
564 break; | |
565 | |
566 case 1: // ramp down | |
567 q<<=3; | |
568 if(a->vibpos<0) q = 255-q; | |
569 temp = q; | |
570 break; | |
571 | |
572 case 2: // square wave | |
573 temp = 255; | |
574 break; | |
575 | |
576 case 3: // Evil random wave | |
577 temp = rand() & 255; | |
578 break; | |
579 } | |
580 | |
581 temp*=a->vibdepth; | |
582 temp>>=7; | |
583 temp<<=2; | |
584 | |
585 if(a->vibpos>=0) | |
586 a->period = a->tmpperiod+temp; | |
587 else | |
588 a->period = a->tmpperiod-temp; | |
589 | |
590 if(pf->vbtick) a->vibpos+=a->vibspd; // do not update when pf->vbtick==0 | |
591 } | |
592 | |
593 | |
594 static void DoTremolo(void) | |
595 { | |
596 UBYTE q; | |
597 UWORD temp; | |
598 | |
599 q = (a->trmpos>>2) & 0x1f; | |
600 | |
601 switch((a->wavecontrol>>4) & 3) | |
602 { case 0: // sine | |
603 temp = VibratoTable[q]; | |
604 break; | |
605 | |
606 case 1: // ramp down | |
607 q<<=3; | |
608 if(a->trmpos<0) q = 255-q; | |
609 temp = q; | |
610 break; | |
611 | |
612 case 2: // square wave | |
613 temp = 255; | |
614 break; | |
615 | |
616 case 3: // Evil random wave | |
617 temp = rand() & 255; | |
618 break; | |
619 } | |
620 | |
621 temp *= a->trmdepth; | |
622 temp >>= 6; | |
623 | |
624 if(a->trmpos >= 0) | |
625 { a->volume = a->tmpvolume + temp; | |
626 if(a->volume > 64) a->volume = 64; | |
627 } else | |
628 { a->volume = a->tmpvolume - temp; | |
629 if(a->volume < 0) a->volume = 0; | |
630 } | |
631 | |
632 if(pf->vbtick) a->trmpos+=a->trmspd; // do not update when pf->vbtick==0 | |
633 } | |
634 | |
635 | |
636 static void DoVolSlide(UBYTE dat) | |
637 { | |
638 if(!pf->vbtick) return; // do not update when pf->vbtick==0 | |
639 | |
640 a->tmpvolume += dat >> 4; // volume slide | |
641 a->tmpvolume -= dat & 0xf; | |
642 if(a->tmpvolume < 0) a->tmpvolume = 0; | |
643 if(a->tmpvolume > 64) a->tmpvolume = 64; | |
644 } | |
645 | |
646 | |
647 static void DoToneSlide(void) | |
648 { | |
649 int dist; | |
650 | |
651 if(a->period==0) return; | |
652 | |
653 if(!pf->vbtick) | |
654 { a->tmpperiod = a->period; | |
655 return; | |
656 } | |
657 | |
658 // We have to slide a->period towards a->wantedperiod, so | |
659 // compute the difference between those two values | |
660 | |
661 dist = a->period-a->wantedperiod; | |
662 | |
663 if( dist==0 || a->portspeed>abs(dist) ) // if they are equal or if portamentospeed is too big | |
664 a->period = a->wantedperiod; // make tmpperiod equal tperiod | |
665 else if(dist>0) // dist>0 ? | |
666 a->period-=a->portspeed; // then slide up | |
667 else | |
668 a->period+=a->portspeed; // dist<0 -> slide down | |
669 | |
670 a->tmpperiod = a->period; | |
671 } | |
672 | |
673 | |
674 static void DoPTEffect0(UBYTE dat) | |
675 { | |
676 UBYTE note; | |
677 | |
678 note = a->note; | |
679 | |
680 if(dat!=0) | |
681 { switch(pf->vbtick%3) | |
682 { case 1: | |
683 note+=(dat>>4); break; | |
684 case 2: | |
685 note+=(dat&0xf); break; | |
686 } | |
687 a->period = GetPeriod(note,a->speed); | |
688 a->ownper = 1; | |
689 } | |
690 } | |
691 | |
692 | |
693 // ----------------------------------------- | |
694 // --> ScreamTreacker 3 Specific Effects <-- | |
695 // ----------------------------------------- | |
696 | |
697 static void DoS3MVolSlide(UBYTE inf) | |
698 { | |
699 UBYTE lo, hi; | |
700 | |
701 if(inf) a->s3mvolslide = inf; | |
702 | |
703 inf = a->s3mvolslide; | |
704 lo = inf & 0xf; | |
705 hi = inf >> 4; | |
706 | |
707 if(hi==0) a->tmpvolume -= lo; | |
708 else if(lo==0) a->tmpvolume += hi; | |
709 else if(hi==0xf) | |
710 { if(!pf->vbtick) a->tmpvolume -= lo; | |
711 } else if(lo==0xf) | |
712 { if(!pf->vbtick) a->tmpvolume += hi; | |
713 } | |
714 if(a->tmpvolume < 0) a->tmpvolume = 0; | |
715 if(a->tmpvolume > 64) a->tmpvolume = 64; | |
716 } | |
717 | |
718 | |
719 static void DoS3MSlideDn(UBYTE inf) | |
720 { | |
721 UBYTE hi,lo; | |
722 | |
723 if(inf!=0) a->slidespeed = inf; | |
724 else inf = a->slidespeed; | |
725 | |
726 hi = inf>>4; | |
727 lo = inf&0xf; | |
728 | |
729 if(hi==0xf) | |
730 { if(!pf->vbtick) a->tmpperiod+=(UWORD)lo<<2; | |
731 } else 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 | |
739 static void DoS3MSlideUp(UBYTE inf) | |
740 { | |
741 UBYTE hi,lo; | |
742 | |
743 if(inf!=0) a->slidespeed = inf; | |
744 else inf = a->slidespeed; | |
745 | |
746 hi = inf>>4; | |
747 lo = inf&0xf; | |
748 | |
749 if(hi==0xf) | |
750 { if(!pf->vbtick) a->tmpperiod-=(UWORD)lo<<2; | |
751 } else 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 | |
759 static void DoS3MTremor(UBYTE inf) | |
760 { | |
761 UBYTE on,off; | |
762 | |
763 if(inf!=0) a->s3mtronof = inf; | |
764 else inf = a->s3mtronof; | |
765 | |
766 if(!pf->vbtick) return; | |
767 | |
768 on = (inf>>4)+1; | |
769 off = (inf&0xf)+1; | |
770 | |
771 a->s3mtremor %= (on+off); | |
772 a->volume = (a->s3mtremor < on ) ? a->tmpvolume : 0; | |
773 a->s3mtremor++; | |
774 } | |
775 | |
776 | |
777 static void DoS3MRetrig(UBYTE inf) | |
778 { | |
779 UBYTE hi,lo; | |
780 | |
781 hi = inf >> 4; | |
782 lo = inf & 0xf; | |
783 | |
784 if(inf) | |
785 { a->s3mrtgslide = hi; | |
786 a->s3mrtgspeed = lo; | |
787 } | |
788 | |
789 // only retrigger if | |
790 // lo nibble > 0 | |
791 | |
792 if(a->s3mrtgspeed > 0) | |
793 { if(a->retrig == 0) | |
794 { // when retrig counter reaches 0, | |
795 // reset counter and restart the sample | |
796 | |
797 if(!a->kick) a->kick = 2; | |
798 a->retrig = a->s3mrtgspeed; | |
799 | |
800 if(pf->vbtick) // don't slide on first retrig | |
801 { switch(a->s3mrtgslide) | |
802 { case 1: | |
803 case 2: | |
804 case 3: | |
805 case 4: | |
806 case 5: | |
807 a->tmpvolume-=(1<<(a->s3mrtgslide-1)); | |
808 break; | |
809 | |
810 case 6: | |
811 a->tmpvolume = (2*a->tmpvolume)/3; | |
812 break; | |
813 | |
814 case 7: | |
815 a->tmpvolume = a->tmpvolume>>1; | |
816 break; | |
817 | |
818 case 9: | |
819 case 0xa: | |
820 case 0xb: | |
821 case 0xc: | |
822 case 0xd: | |
823 a->tmpvolume+=(1<<(a->s3mrtgslide-9)); | |
824 break; | |
825 | |
826 case 0xe: | |
827 a->tmpvolume=(3*a->tmpvolume)/2; | |
828 break; | |
829 | |
830 case 0xf: | |
831 a->tmpvolume=a->tmpvolume<<1; | |
832 break; | |
833 } | |
834 if(a->tmpvolume<0) a->tmpvolume = 0; | |
835 if(a->tmpvolume>64) a->tmpvolume = 64; | |
836 } | |
837 } | |
838 a->retrig--; // countdown | |
839 } | |
840 } | |
841 | |
842 | |
843 static void DoS3MSpeed(UBYTE speed) | |
844 { | |
845 if(pf->vbtick || pf->patdly2) return; | |
846 | |
847 if(speed) | |
848 { pf->sngspd = speed; | |
849 pf->vbtick = 0; | |
850 } | |
851 } | |
852 | |
853 | |
854 static void DoS3MTempo(UBYTE tempo) | |
855 { | |
856 if(pf->vbtick || pf->patdly2) return; | |
857 pf->bpm = tempo; | |
858 } | |
859 | |
860 | |
861 static void DoS3MFineVibrato(void) | |
862 { | |
863 UBYTE q; | |
864 UWORD temp; | |
865 | |
866 q = (a->vibpos>>2)&0x1f; | |
867 | |
868 switch(a->wavecontrol&3) | |
869 { case 0: // sine | |
870 temp=VibratoTable[q]; | |
871 break; | |
872 | |
873 case 1: // ramp down | |
874 q<<=3; | |
875 if(a->vibpos<0) q=255-q; | |
876 temp=q; | |
877 break; | |
878 | |
879 case 2: // square wave | |
880 temp=255; | |
881 break; | |
882 | |
883 case 3: // evil random | |
884 temp = rand() & 255; // (range 0 to 255) | |
885 } | |
886 | |
887 temp*=a->vibdepth; | |
888 temp>>=8; | |
889 | |
890 if(a->vibpos>=0) | |
891 a->period = a->tmpperiod+temp; | |
892 else | |
893 a->period = a->tmpperiod-temp; | |
894 | |
895 a->vibpos += a->vibspd; | |
896 } | |
897 | |
898 | |
899 static void DoS3MTremolo(void) | |
900 { | |
901 UBYTE q; | |
902 UWORD temp; | |
903 | |
904 q = (a->trmpos>>2)&0x1f; | |
905 | |
906 switch((a->wavecontrol>>4)&3) | |
907 { case 0: // sine | |
908 temp = VibratoTable[q]; | |
909 break; | |
910 | |
911 case 1: // ramp down | |
912 q<<=3; | |
913 if(a->trmpos<0) q = 255-q; | |
914 temp = q; | |
915 break; | |
916 | |
917 case 2: // square wave | |
918 temp=255; | |
919 break; | |
920 | |
921 case 3: // evil random | |
922 temp = rand() & 255; // (range 0 to 255) | |
923 } | |
924 | |
925 temp*=a->trmdepth; | |
926 temp>>=7; | |
927 | |
928 if(a->trmpos>=0) | |
929 { a->volume = a->tmpvolume + temp; | |
930 if(a->volume>64) a->volume = 64; | |
931 } else | |
932 { a->volume = a->tmpvolume - temp; | |
933 if(a->volume<0) a->volume = 0; | |
934 } | |
935 | |
936 if(pf->vbtick) a->trmpos += a->trmspd; // do not update when pf->vbtick==0 | |
937 } | |
938 | |
939 | |
940 // -------------------------------------- | |
941 // --> FastTracker 2 Specific Effects <-- | |
942 // -------------------------------------- | |
943 | |
944 static void DoXMVolSlide(UBYTE inf) | |
945 { | |
946 UBYTE lo,hi; | |
947 | |
948 if(inf) | |
949 a->s3mvolslide = inf; | |
950 | |
951 inf = a->s3mvolslide; | |
952 if(!pf->vbtick) return; | |
953 | |
954 lo = inf&0xf; | |
955 hi = inf>>4; | |
956 | |
957 if(hi==0) | |
958 a->tmpvolume-=lo; | |
959 else | |
960 a->tmpvolume+=hi; | |
961 | |
962 if(a->tmpvolume<0) a->tmpvolume=0; | |
963 else if(a->tmpvolume>64) a->tmpvolume=64; | |
964 } | |
965 | |
966 | |
967 static void DoXMGlobalSlide(UBYTE inf) | |
968 { | |
969 if(pf->vbtick) | |
970 { if(inf) pf->globalslide=inf; else inf=pf->globalslide; | |
971 if(inf & 0xf0) inf &= 0xf0; | |
972 pf->volume = pf->volume + ((inf >> 4) - (inf & 0xf))*2; | |
973 | |
974 if(pf->volume<0) pf->volume = 0; | |
975 else if(pf->volume>128) pf->volume = 128; | |
976 } | |
977 } | |
978 | |
979 | |
980 static void DoXMPanSlide(UBYTE inf) | |
981 { | |
982 UBYTE lo,hi; | |
983 SWORD pan; | |
984 | |
985 | |
986 if(inf!=0) a->pansspd = inf; | |
987 else inf = a->pansspd; | |
988 | |
989 if(!pf->vbtick) return; | |
990 | |
991 lo = inf & 0xf; | |
992 hi = inf >> 4; | |
993 | |
994 // slide right has absolute priority: | |
995 | |
996 if(hi) lo = 0; | |
997 | |
998 pan = (a->panning == PAN_SURROUND) ? 128 : a->panning; | |
999 | |
1000 pan -= lo; | |
1001 pan += hi; | |
1002 | |
1003 if(pan < 0) pan = 0; | |
1004 if(pan > 255) pan = 255; | |
1005 | |
1006 a->panning = pan; | |
1007 } | |
1008 | |
1009 | |
1010 static void DoXMExtraFineSlideUp(UBYTE inf) | |
1011 { | |
1012 if(!pf->vbtick) | |
1013 { if(inf) a->ffportupspd = inf; else inf = a->ffportupspd; | |
1014 a->period -= inf; | |
1015 } | |
1016 a->tmpperiod = a->period; | |
1017 } | |
1018 | |
1019 | |
1020 static void DoXMExtraFineSlideDown(UBYTE inf) | |
1021 { | |
1022 if(!pf->vbtick) | |
1023 { if(inf) a->ffportdnspd = inf; else inf = a->ffportdnspd; | |
1024 a->period += inf; | |
1025 } | |
1026 a->tmpperiod = a->period; | |
1027 } | |
1028 | |
1029 | |
1030 // --------------------------------------- | |
1031 // --> ImpulseTracker Player Functions <-- | |
1032 // --------------------------------------- | |
1033 | |
1034 static void DoITChanVolSlide(UBYTE inf) | |
1035 { | |
1036 UBYTE lo, hi; | |
1037 | |
1038 if(inf) a->chanvolslide = inf; | |
1039 inf = a->chanvolslide; | |
1040 | |
1041 lo = inf&0xf; | |
1042 hi = inf>>4; | |
1043 | |
1044 if(hi==0) | |
1045 { a->chanvol-=lo; | |
1046 } else if(lo==0) | |
1047 { a->chanvol+=hi; | |
1048 } else if(hi==0xf) | |
1049 { if(!pf->vbtick) a->chanvol-=lo; | |
1050 } else if(lo==0xf) | |
1051 { if(!pf->vbtick) a->chanvol+=hi; | |
1052 } | |
1053 | |
1054 if(a->chanvol<0) a->chanvol = 0; | |
1055 if(a->chanvol>64) a->chanvol = 64; | |
1056 } | |
1057 | |
1058 | |
1059 static void DoITGlobalSlide(UBYTE inf) | |
1060 { | |
1061 UBYTE lo,hi; | |
1062 | |
1063 if(inf) pf->globalslide = inf; | |
1064 inf = pf->globalslide; | |
1065 | |
1066 lo = inf&0xf; | |
1067 hi = inf>>4; | |
1068 | |
1069 if(lo==0) | |
1070 { pf->volume += hi; | |
1071 } else if(hi==0) | |
1072 { pf->volume -= lo; | |
1073 } else if(lo==0xf) | |
1074 { if(!pf->vbtick) pf->volume += hi; | |
1075 } else if(hi==0xf) | |
1076 { if(!pf->vbtick) pf->volume -= lo; | |
1077 } | |
1078 | |
1079 if(pf->volume < 0) pf->volume = 0; | |
1080 if(pf->volume > 128) pf->volume = 128; | |
1081 } | |
1082 | |
1083 | |
1084 static void DoITPanSlide(UBYTE inf) | |
1085 { | |
1086 UBYTE lo,hi; | |
1087 SWORD pan; | |
1088 | |
1089 if(inf) a->pansspd = inf; | |
1090 inf = a->pansspd; | |
1091 | |
1092 lo = inf & 0xf; | |
1093 hi = inf >> 4; | |
1094 | |
1095 pan = (a->panning == PAN_SURROUND) ? 128 : a->panning; | |
1096 | |
1097 if(hi==0) | |
1098 { pan += lo << 2; | |
1099 } else if(lo==0) | |
1100 { pan -= hi << 2; | |
1101 } else if(hi==0xf) | |
1102 { if(!pf->vbtick) pan += lo << 2; | |
1103 } else if(lo==0xf) | |
1104 { if(!pf->vbtick) pan -= hi << 2; | |
1105 } | |
1106 if(pan > 255) pan = 255; | |
1107 if(pan < 0) pan = 0; | |
1108 a->panning = /*pf->panning[mp_channel] =*/ pan; | |
1109 } | |
1110 | |
1111 | |
1112 static void DoITVibrato(void) | |
1113 { | |
1114 UBYTE q; | |
1115 UWORD temp; | |
1116 | |
1117 q = (a->vibpos>>2)&0x1f; | |
1118 | |
1119 switch(a->wavecontrol&3) | |
1120 { case 0: // sine | |
1121 temp=VibratoTable[q]; | |
1122 break; | |
1123 | |
1124 case 1: // ramp down | |
1125 q<<=3; | |
1126 if(a->vibpos<0) q=255-q; | |
1127 temp=q; | |
1128 break; | |
1129 | |
1130 case 2: // square wave | |
1131 temp=255; | |
1132 break; | |
1133 | |
1134 case 3: // evil random | |
1135 temp = rand() & 255; // (range 0 to 255) | |
1136 break; | |
1137 } | |
1138 | |
1139 temp*=a->vibdepth; | |
1140 temp>>=8; | |
1141 temp<<=2; | |
1142 | |
1143 if(a->vibpos>=0) | |
1144 a->period = a->tmpperiod+temp; | |
1145 else | |
1146 a->period = a->tmpperiod-temp; | |
1147 | |
1148 a->vibpos+=a->vibspd; | |
1149 } | |
1150 | |
1151 | |
1152 static void DoITFineVibrato(void) | |
1153 { | |
1154 UBYTE q; | |
1155 UWORD temp; | |
1156 | |
1157 q = (a->vibpos>>2)&0x1f; | |
1158 | |
1159 switch(a->wavecontrol&3) | |
1160 { case 0: // sine | |
1161 temp=VibratoTable[q]; | |
1162 break; | |
1163 | |
1164 case 1: // ramp down | |
1165 q<<=3; | |
1166 if(a->vibpos<0) q = 255-q; | |
1167 temp = q; | |
1168 break; | |
1169 | |
1170 case 2: // square wave | |
1171 temp = 255; | |
1172 break; | |
1173 | |
1174 case 3: // evil random | |
1175 temp = rand() & 255; // (range 0 to 255) | |
1176 break; | |
1177 } | |
1178 | |
1179 temp*=a->vibdepth; | |
1180 temp>>=8; | |
1181 | |
1182 if(a->vibpos>=0) | |
1183 a->period = a->tmpperiod+temp; | |
1184 else | |
1185 a->period = a->tmpperiod-temp; | |
1186 | |
1187 a->vibpos+=a->vibspd; | |
1188 } | |
1189 | |
1190 | |
1191 static void DoITTremor(UBYTE inf) | |
1192 { | |
1193 UBYTE on,off; | |
1194 | |
1195 if(inf!=0) a->s3mtronof = inf; | |
1196 else inf = a->s3mtronof; | |
1197 | |
1198 if(!pf->vbtick) return; | |
1199 | |
1200 on=(inf>>4); | |
1201 off=(inf&0xf); | |
1202 | |
1203 a->s3mtremor%=(on+off); | |
1204 a->volume = (a->s3mtremor < on ) ? a->tmpvolume : 0; | |
1205 a->s3mtremor++; | |
1206 } | |
1207 | |
1208 | |
1209 static void DoITPanbrello(void) | |
1210 { | |
1211 UBYTE q; | |
1212 static SLONG temp; | |
1213 | |
1214 q = a->panbpos; | |
1215 | |
1216 switch(a->panbwave) | |
1217 { case 0: // sine | |
1218 temp = PanbrelloTable[q]; | |
1219 break; | |
1220 | |
1221 // only sinewave is correctly supported right now | |
1222 | |
1223 case 1: // ramp down | |
1224 q<<=3; | |
1225 temp = q; | |
1226 break; | |
1227 | |
1228 case 2: // square wave | |
1229 temp = 64; | |
1230 break; | |
1231 | |
1232 case 3: // evil random | |
1233 if(a->panbpos >= a->panbspd) | |
1234 { a->panbpos = 0; | |
1235 temp = rand() & 255; | |
1236 } | |
1237 } | |
1238 | |
1239 temp*=a->panbdepth; | |
1240 temp/=8; | |
1241 | |
1242 a->panning = pf->panning[mp_channel] + temp; | |
1243 a->panbpos += a->panbspd; | |
1244 } | |
1245 | |
1246 | |
1247 static void DoITToneSlide(void) | |
1248 { | |
1249 int dist; | |
1250 | |
1251 if(a->period == 0) return; | |
1252 | |
1253 if(!pf->vbtick) | |
1254 { a->tmpperiod = a->period; | |
1255 return; | |
1256 } | |
1257 | |
1258 // We have to slide a->period towards a->wantedperiod, | |
1259 // compute the difference between those two values | |
1260 | |
1261 dist = a->period - a->wantedperiod; | |
1262 | |
1263 if( (dist == 0) || // if they are equal | |
1264 ((a->slidespeed<<2) > abs(dist)) ) // or if portamentospeed is too big | |
1265 { a->period = a->wantedperiod; // make tmpperiod equal tperiod | |
1266 } else if(dist > 0) // dist>0 ? | |
1267 { a->period -= a->slidespeed << 2; // then slide up | |
1268 } else | |
1269 { a->period += a->slidespeed << 2; // dist<0 -> slide down | |
1270 } | |
1271 a->tmpperiod = a->period; | |
1272 } | |
1273 | |
1274 | |
1275 static void DoSSEffects(UBYTE dat) | |
1276 | |
1277 // Impulse/Scream Tracker Sxx effects. | |
1278 // All Sxx effects share the same memory space. | |
1279 | |
1280 { | |
1281 UBYTE inf,c; | |
1282 | |
1283 inf = dat&0xf; | |
1284 c = dat>>4; | |
1285 | |
1286 if(dat==0) | |
1287 { c = a->sseffect; | |
1288 inf = a->ssdata; | |
1289 } else | |
1290 { a->sseffect = c; | |
1291 a->ssdata = inf; | |
1292 } | |
1293 | |
1294 switch(c) | |
1295 { case SS_GLISSANDO: // S1x set glissando voice | |
1296 DoEEffects(0x30|inf); | |
1297 break; | |
1298 | |
1299 case SS_FINETUNE: // S2x set finetune | |
1300 DoEEffects(0x50|inf); | |
1301 break; | |
1302 | |
1303 case SS_VIBWAVE: // S3x set vibrato waveform | |
1304 DoEEffects(0x40|inf); | |
1305 break; | |
1306 | |
1307 case SS_TREMWAVE: // S4x set tremolo waveform | |
1308 DoEEffects(0x70|inf); | |
1309 break; | |
1310 | |
1311 case SS_PANWAVE: // The Satanic Panbrello waveform | |
1312 a->panbwave = (UniGetByte()); | |
1313 break; | |
1314 | |
1315 case SS_FRAMEDELAY: // S6x Delay x number of frames (patdly) | |
1316 DoEEffects(0xe0|inf); | |
1317 break; | |
1318 | |
1319 case SS_S7EFFECTS: // S7x Instrument / NNA commands | |
1320 DoNNAEffects(UniGetByte()); | |
1321 break; | |
1322 | |
1323 case SS_PANNING: // S8x set panning position | |
1324 DoEEffects(0x80 | inf); | |
1325 break; | |
1326 | |
1327 case SS_SURROUND: // S9x Set Surround Sound | |
1328 a->panning = pf->panning[mp_channel] = PAN_SURROUND; | |
1329 break; | |
1330 | |
1331 case SS_HIOFFSET: // SAy Set high order sample offset yxx00h | |
1332 a->hioffset |= UniGetByte() << 16; | |
1333 break; | |
1334 | |
1335 case SS_PATLOOP: // SBx pattern loop | |
1336 DoEEffects(0x60|inf); | |
1337 break; | |
1338 | |
1339 case SS_NOTECUT: // SCx notecut | |
1340 DoEEffects(0xC0|inf); | |
1341 break; | |
1342 | |
1343 case SS_NOTEDELAY: // SDx notedelay | |
1344 DoEEffects(0xD0|inf); | |
1345 break; | |
1346 | |
1347 case SS_PATDELAY: // SEx patterndelay | |
1348 DoEEffects(0xE0|inf); | |
1349 break; | |
1350 } | |
1351 } | |
1352 | |
1353 | |
1354 static void DoVolEffects(UBYTE c) | |
1355 | |
1356 // Impulse Tracker Volume/Pan Column effects. | |
1357 // All volume/pan column effects share the same memory space. | |
1358 | |
1359 { | |
1360 UBYTE inf; | |
1361 | |
1362 inf = UniGetByte(); | |
1363 | |
1364 if(c==0 && inf==0) | |
1365 { c = a->voleffect; | |
1366 inf = a->voldata; | |
1367 } else | |
1368 { a->voleffect = c; | |
1369 a->voldata = inf; | |
1370 } | |
1371 | |
1372 switch(c) | |
1373 { case 0: break; // do nothing | |
1374 case VOL_VOLUME: | |
1375 if(pf->vbtick) break; | |
1376 if(inf>64) inf = 64; | |
1377 a->tmpvolume = inf; | |
1378 break; | |
1379 | |
1380 case VOL_PANNING: | |
1381 if(pf->panflag) | |
1382 { a->panning = inf; | |
1383 pf->panning[mp_channel] = inf; | |
1384 } | |
1385 break; | |
1386 | |
1387 case VOL_VOLSLIDE: | |
1388 DoS3MVolSlide(inf); | |
1389 break; | |
1390 | |
1391 case VOL_PITCHSLIDEDN: | |
1392 DoS3MSlideDn(UniGetByte()); | |
1393 break; | |
1394 | |
1395 case VOL_PITCHSLIDEUP: | |
1396 DoS3MSlideUp(UniGetByte()); | |
1397 break; | |
1398 | |
1399 case VOL_PORTAMENTO: | |
1400 if(inf != 0) a->slidespeed = inf; | |
1401 | |
1402 if(a->period != 0) | |
1403 { if(!(pf->vbtick==pf->sngspd-1) && (a->newsamp)) | |
1404 { a->kick = 1; | |
1405 a->start = -1; | |
1406 //a->period *= a->speed * a->newsamp; | |
1407 } else | |
1408 a->kick = 0; | |
1409 | |
1410 DoITToneSlide(); | |
1411 a->ownper = 1; | |
1412 } | |
1413 break; | |
1414 | |
1415 case VOL_VIBRATO: | |
1416 if(inf & 0x0f) a->vibdepth = inf & 0xf; | |
1417 if(inf & 0xf0) a->vibspd = (inf & 0xf0) >> 2; | |
1418 DoITVibrato(); | |
1419 a->ownper = 1; | |
1420 break; | |
1421 } | |
1422 } | |
1423 | |
1424 | |
1425 | |
1426 // -------------------------------- | |
1427 // --> General Player Functions <-- | |
1428 // -------------------------------- | |
1429 | |
1430 static void pt_playeffects(void) | |
1431 { | |
1432 UBYTE dat,c; | |
1433 | |
1434 while(c = UniGetByte()) | |
1435 switch(c) | |
1436 { case UNI_NOTE: | |
1437 case UNI_INSTRUMENT: | |
1438 UniSkipOpcode(c); | |
1439 break; | |
1440 | |
1441 case UNI_PTEFFECT0: | |
1442 DoPTEffect0(UniGetByte()); | |
1443 break; | |
1444 | |
1445 case UNI_PTEFFECT1: | |
1446 dat = UniGetByte(); | |
1447 if(dat != 0) a->slidespeed = (UWORD)dat << 2; | |
1448 if(pf->vbtick) a->tmpperiod -= a->slidespeed; | |
1449 break; | |
1450 | |
1451 case UNI_PTEFFECT2: | |
1452 dat = UniGetByte(); | |
1453 if(dat != 0) a->slidespeed = (UWORD)dat << 2; | |
1454 if(pf->vbtick) a->tmpperiod += a->slidespeed; | |
1455 break; | |
1456 | |
1457 case UNI_PTEFFECT3: | |
1458 dat = UniGetByte(); | |
1459 | |
1460 if(dat!=0) | |
1461 { a->portspeed = dat; | |
1462 a->portspeed <<= 2; | |
1463 } | |
1464 | |
1465 if(a->period != 0) | |
1466 { a->kick = 0; // temp XM fix | |
1467 DoToneSlide(); | |
1468 a->ownper = 1; | |
1469 } | |
1470 break; | |
1471 | |
1472 case UNI_PTEFFECT4: | |
1473 dat = UniGetByte(); | |
1474 if(dat & 0x0f) a->vibdepth = dat & 0xf; | |
1475 if(dat & 0xf0) a->vibspd = (dat & 0xf0) >> 2; | |
1476 DoVibrato(); | |
1477 a->ownper = 1; | |
1478 break; | |
1479 | |
1480 case UNI_PTEFFECT5: | |
1481 dat = UniGetByte(); | |
1482 a->kick = 0; | |
1483 DoToneSlide(); | |
1484 DoVolSlide(dat); | |
1485 a->ownper = 1; | |
1486 break; | |
1487 | |
1488 case UNI_PTEFFECT6: | |
1489 dat = UniGetByte(); | |
1490 DoVibrato(); | |
1491 DoVolSlide(dat); | |
1492 a->ownper = 1; | |
1493 break; | |
1494 | |
1495 case UNI_PTEFFECT7: | |
1496 dat = UniGetByte(); | |
1497 if(dat & 0x0f) a->trmdepth = dat & 0xf; | |
1498 if(dat & 0xf0) a->trmspd = (dat & 0xf0) >> 2; | |
1499 DoTremolo(); | |
1500 a->ownvol = 1; | |
1501 break; | |
1502 | |
1503 case UNI_PTEFFECT8: | |
1504 dat = UniGetByte(); | |
1505 if(pf->panflag) | |
1506 { a->panning = dat; | |
1507 pf->panning[mp_channel] = dat; | |
1508 } | |
1509 break; | |
1510 | |
1511 case UNI_PTEFFECT9: | |
1512 dat = UniGetByte(); | |
1513 if(dat) a->soffset = (UWORD)dat << 8; | |
1514 a->start = a->hioffset | a->soffset; | |
1515 if((a->s != NULL) && (a->start > a->s->length)) a->start = a->s->loopstart; | |
1516 break; | |
1517 | |
1518 case UNI_PTEFFECTA: | |
1519 DoVolSlide(UniGetByte()); | |
1520 break; | |
1521 | |
1522 case UNI_PTEFFECTB: | |
1523 dat = UniGetByte(); | |
1524 if(pf->patdly2) break; | |
1525 pf->patbrk = 0; | |
1526 pf->sngpos = dat-1; | |
1527 pf->posjmp = 3; | |
1528 break; | |
1529 | |
1530 case UNI_PTEFFECTC: | |
1531 dat = UniGetByte(); | |
1532 if(pf->vbtick) break; | |
1533 if(dat>64) dat = 64; | |
1534 a->tmpvolume = dat; | |
1535 break; | |
1536 | |
1537 case UNI_PTEFFECTD: | |
1538 dat = UniGetByte(); | |
1539 if(pf->patdly2) break; | |
1540 pf->patbrk = dat; | |
1541 if(pf->patbrk>pf->pattrows[mp_channel]) | |
1542 pf->patbrk = pf->pattrows[mp_channel]; | |
1543 pf->posjmp = 3; | |
1544 break; | |
1545 | |
1546 case UNI_PTEFFECTE: | |
1547 DoEEffects(UniGetByte()); | |
1548 break; | |
1549 | |
1550 case UNI_PTEFFECTF: | |
1551 dat = UniGetByte(); | |
1552 | |
1553 if(pf->vbtick || pf->patdly2) break; | |
1554 | |
1555 if(pf->extspd && (dat >= 0x20)) | |
1556 pf->bpm = dat; | |
1557 else | |
1558 { if(dat) | |
1559 { pf->sngspd = dat; | |
1560 pf->vbtick = 0; | |
1561 } | |
1562 } | |
1563 break; | |
1564 | |
1565 case UNI_S3MEFFECTA: | |
1566 DoS3MSpeed(UniGetByte()); | |
1567 break; | |
1568 | |
1569 case UNI_S3MEFFECTD: | |
1570 DoS3MVolSlide(UniGetByte()); | |
1571 break; | |
1572 | |
1573 case UNI_S3MEFFECTE: | |
1574 DoS3MSlideDn(UniGetByte()); | |
1575 break; | |
1576 | |
1577 case UNI_S3MEFFECTF: | |
1578 DoS3MSlideUp(UniGetByte()); | |
1579 break; | |
1580 | |
1581 case UNI_S3MEFFECTI: | |
1582 DoS3MTremor(UniGetByte()); | |
1583 a->ownvol = 1; | |
1584 break; | |
1585 | |
1586 case UNI_S3MEFFECTQ: | |
1587 DoS3MRetrig(UniGetByte()); | |
1588 break; | |
1589 | |
1590 case UNI_S3MEFFECTR: | |
1591 dat = UniGetByte(); | |
1592 if(dat & 0x0f) a->trmdepth = dat & 0xf; | |
1593 if(dat & 0xf0) a->trmspd = (dat & 0xf0) >> 2; | |
1594 DoS3MTremolo(); | |
1595 a->ownvol = 1; | |
1596 break; | |
1597 | |
1598 case UNI_S3MEFFECTT: | |
1599 DoS3MTempo(UniGetByte()); | |
1600 break; | |
1601 | |
1602 case UNI_S3MEFFECTU: | |
1603 dat = UniGetByte(); | |
1604 if(dat & 0x0f) a->vibdepth = dat & 0xf; | |
1605 if(dat & 0xf0) a->vibspd = (dat & 0xf0) >> 2; | |
1606 DoS3MFineVibrato(); | |
1607 a->ownper = 1; | |
1608 break; | |
1609 | |
1610 case UNI_KEYOFF: | |
1611 a->keyoff |= KEY_OFF; | |
1612 if(a->i != NULL) | |
1613 { if(!(a->i->volflg & EF_ON) || (a->i->volflg & EF_LOOP)) | |
1614 a->keyoff = KEY_KILL; | |
1615 } | |
1616 break; | |
1617 | |
1618 case UNI_KEYFADE: | |
1619 if(pf->vbtick >= UniGetByte()) | |
1620 { a->keyoff = KEY_KILL; | |
1621 if((a->i != NULL) && !(a->i->volflg & EF_ON)) | |
1622 a->fadevol = 0; | |
1623 } | |
1624 break; | |
1625 | |
1626 case UNI_VOLEFFECTS: | |
1627 DoVolEffects(UniGetByte()); | |
1628 break; | |
1629 | |
1630 case UNI_XMEFFECT4: | |
1631 dat = UniGetByte(); | |
1632 if(pf->vbtick) | |
1633 { if(dat & 0x0f) a->vibdepth = dat & 0xf; | |
1634 if(dat & 0xf0) a->vibspd = (dat & 0xf0) >> 2; | |
1635 } | |
1636 DoVibrato(); | |
1637 a->ownper = 1; | |
1638 break; | |
1639 | |
1640 case UNI_XMEFFECTA: | |
1641 DoXMVolSlide(UniGetByte()); | |
1642 break; | |
1643 | |
1644 case UNI_XMEFFECTE1: // xm fineslide up | |
1645 dat = UniGetByte(); | |
1646 if(!pf->vbtick) | |
1647 { if(dat) a->fportupspd = dat; else dat = a->fportupspd; | |
1648 a->tmpperiod -= (dat << 2); | |
1649 } | |
1650 break; | |
1651 | |
1652 case UNI_XMEFFECTE2: // xm fineslide dn | |
1653 dat = UniGetByte(); | |
1654 if(!pf->vbtick) | |
1655 { if(dat) a->fportdnspd = dat; else dat = a->fportdnspd; | |
1656 a->tmpperiod += (dat<<2); | |
1657 } | |
1658 break; | |
1659 | |
1660 case UNI_XMEFFECTEA: // fine volume slide up | |
1661 dat = UniGetByte(); | |
1662 if(pf->vbtick) break; | |
1663 if(dat) a->fslideupspd = dat; else dat = a->fslideupspd; | |
1664 a->tmpvolume+=dat; | |
1665 if(a->tmpvolume>64) a->tmpvolume = 64; | |
1666 break; | |
1667 | |
1668 case UNI_XMEFFECTEB: // fine volume slide dn | |
1669 dat = UniGetByte(); | |
1670 if(pf->vbtick) break; | |
1671 if(dat) a->fslidednspd = dat; else dat = a->fslidednspd; | |
1672 a->tmpvolume-=dat; | |
1673 if(a->tmpvolume<0) a->tmpvolume = 0; | |
1674 break; | |
1675 | |
1676 case UNI_XMEFFECTG: | |
1677 pf->volume = UniGetByte(); | |
1678 break; | |
1679 | |
1680 case UNI_XMEFFECTH: | |
1681 DoXMGlobalSlide(UniGetByte()); | |
1682 break; | |
1683 | |
1684 case UNI_XMEFFECTL: | |
1685 dat = UniGetByte(); | |
1686 if(!pf->vbtick && a->i!=NULL) | |
1687 { UWORD points; | |
1688 INSTRUMENT *i = a->i; | |
1689 MP_VOICE *aout; | |
1690 | |
1691 if((aout = a->slave) != NULL) | |
1692 { points = i->volenv[i->volpts-1].pos; | |
1693 aout->venv.p = aout->venv.env[(dat>points) ? points : dat].pos; | |
1694 | |
1695 points = i->panenv[i->panpts-1].pos; | |
1696 aout->penv.p = aout->penv.env[(dat>points) ? points : dat].pos; | |
1697 } | |
1698 } | |
1699 break; | |
1700 | |
1701 case UNI_XMEFFECTP: | |
1702 DoXMPanSlide(UniGetByte()); | |
1703 break; | |
1704 | |
1705 case UNI_XMEFFECTX1: | |
1706 DoXMExtraFineSlideUp(UniGetByte()); | |
1707 a->ownper = 1; | |
1708 break; | |
1709 | |
1710 case UNI_XMEFFECTX2: | |
1711 DoXMExtraFineSlideDown(UniGetByte()); | |
1712 a->ownper = 1; | |
1713 break; | |
1714 | |
1715 case UNI_ITEFFECTG: | |
1716 dat = UniGetByte(); | |
1717 if(dat != 0) a->slidespeed = dat; | |
1718 | |
1719 if(a->period != 0) | |
1720 { if((pf->vbtick < 1) && (a->newsamp)) | |
1721 { a->kick = 1; | |
1722 a->start = -1; | |
1723 //a->period *= a->speed * a->newsamp; | |
1724 } else | |
1725 a->kick = 0; | |
1726 | |
1727 DoITToneSlide(); | |
1728 a->ownper = 1; | |
1729 } | |
1730 break; | |
1731 | |
1732 case UNI_ITEFFECTH: // it vibrato | |
1733 dat = UniGetByte(); | |
1734 if(dat & 0x0f) a->vibdepth = dat & 0xf; | |
1735 if(dat & 0xf0) a->vibspd = (dat & 0xf0) >> 2; | |
1736 DoITVibrato(); | |
1737 a->ownper = 1; | |
1738 break; | |
1739 | |
1740 case UNI_ITEFFECTI: // it tremor | |
1741 DoITTremor(UniGetByte()); | |
1742 a->ownvol = 1; | |
1743 break; | |
1744 | |
1745 case UNI_ITEFFECTM: | |
1746 a->chanvol = UniGetByte(); | |
1747 if(a->chanvol > 64) a->chanvol = 64; | |
1748 else if(a->chanvol < 0) a->chanvol = 0; | |
1749 break; | |
1750 | |
1751 case UNI_ITEFFECTN: // Slide / Fineslide Channel Volume | |
1752 DoITChanVolSlide(UniGetByte()); | |
1753 break; | |
1754 | |
1755 case UNI_ITEFFECTP: // slide / fineslide channel panning | |
1756 DoITPanSlide(UniGetByte()); | |
1757 break; | |
1758 | |
1759 case UNI_ITEFFECTU: // fine vibrato | |
1760 dat = UniGetByte(); | |
1761 if(dat & 0x0f) a->vibdepth = dat & 0xf; | |
1762 if(dat & 0xf0) a->vibspd = (dat & 0xf0) >> 2; | |
1763 DoITFineVibrato(); | |
1764 a->ownper = 1; | |
1765 break; | |
1766 | |
1767 case UNI_ITEFFECTW: // Slide / Fineslide Global volume | |
1768 DoITGlobalSlide(UniGetByte()); | |
1769 break; | |
1770 | |
1771 case UNI_ITEFFECTY: // The Satanic Panbrello | |
1772 dat = UniGetByte(); | |
1773 if(dat & 0x0f) a->panbdepth = (dat & 0xf); | |
1774 if(dat & 0xf0) a->panbspd = (dat & 0xf0) >> 4; | |
1775 DoITPanbrello(); | |
1776 break; | |
1777 | |
1778 case UNI_ITEFFECTS0: | |
1779 DoSSEffects(UniGetByte()); | |
1780 break; | |
1781 | |
1782 default: | |
1783 UniSkipOpcode(c); | |
1784 break; | |
1785 } | |
1786 } | |
1787 | |
1788 | |
1789 static void DoNNAEffects(UBYTE dat) | |
1790 { | |
1791 int t; | |
1792 MP_VOICE *aout; | |
1793 | |
1794 dat &= 0xf; | |
1795 aout = (a->slave==NULL) ? &aout_dummy : a->slave; | |
1796 | |
1797 switch(dat) | |
1798 { case 0x0: // Past note cut | |
1799 for(t=0; t<md_sngchn; t++) | |
1800 if(pf->voice[t].master == a) | |
1801 pf->voice[t].fadevol = 0; | |
1802 break; | |
1803 | |
1804 case 0x1: // Past note off | |
1805 for(t=0; t<md_sngchn; t++) | |
1806 if(pf->voice[t].master == a) | |
1807 { pf->voice[t].keyoff |= KEY_OFF; | |
1808 if(!(pf->voice[t].venv.flg & EF_ON)) | |
1809 pf->voice[t].keyoff = KEY_KILL; | |
1810 } | |
1811 break; | |
1812 | |
1813 case 0x2: // Past note fade | |
1814 for(t=0; t<md_sngchn; t++) | |
1815 if(pf->voice[t].master == a) | |
1816 pf->voice[t].keyoff |= KEY_FADE; | |
1817 break; | |
1818 | |
1819 case 0x3: // set NNA note cut | |
1820 a->nna = (a->nna & ~0x3f) | NNA_CUT; | |
1821 break; | |
1822 | |
1823 case 0x4: // set NNA note continue | |
1824 a->nna = (a->nna & ~0x3f) | NNA_CONTINUE; | |
1825 break; | |
1826 | |
1827 case 0x5: // set NNA note off | |
1828 a->nna = (a->nna & ~0x3f) | NNA_OFF; | |
1829 break; | |
1830 | |
1831 case 0x6: // set NNA note fade | |
1832 a->nna = (a->nna & ~0x3f) | NNA_FADE; | |
1833 break; | |
1834 | |
1835 case 0x7: // disable volume envelope | |
1836 aout->volflg &= ~EF_ON; | |
1837 break; | |
1838 | |
1839 case 0x8: // enable volume envelope | |
1840 aout->volflg |= EF_ON; | |
1841 break; | |
1842 | |
1843 case 0x9: // disable panning envelope | |
1844 aout->panflg &= ~EF_ON; | |
1845 break; | |
1846 | |
1847 case 0xa: // enable panning envelope | |
1848 aout->panflg |= EF_ON; | |
1849 break; | |
1850 | |
1851 case 0xb: // disable pitch envelope | |
1852 aout->pitflg &= ~EF_ON; | |
1853 break; | |
1854 | |
1855 case 0xc: // enable pitch envelope | |
1856 aout->pitflg |= EF_ON; | |
1857 break; | |
1858 } | |
1859 } | |
1860 | |
1861 | |
1862 void Player_HandleTick(void) | |
1863 { | |
1864 MP_VOICE *aout; // current audout (slave of audtmp) it's working on | |
1865 int t, tr, t2, k; | |
1866 ULONG tmpvol, period; | |
1867 UBYTE c; | |
1868 BOOL funky; | |
1869 SAMPLE *s; | |
1870 INSTRUMENT *i; | |
1871 | |
1872 if(isfirst) | |
1873 { // don't handle the very first ticks, this allows the | |
1874 // other hardware to settle down so we don't loose any | |
1875 // starting notes | |
1876 isfirst--; | |
1877 return; | |
1878 } | |
1879 | |
1880 if(pf==NULL || pf->forbid) return; | |
1881 | |
1882 if(++pf->vbtick >= pf->sngspd) | |
1883 { pf->patpos++; | |
1884 pf->vbtick = 0; | |
1885 | |
1886 // process pattern-delay. pf->patdly2 is the counter and pf->patdly | |
1887 // is the command memory. | |
1888 | |
1889 if(pf->patdly) | |
1890 { pf->patdly2 = pf->patdly; | |
1891 pf->patdly = 0; | |
1892 } | |
1893 | |
1894 if(pf->patdly2) | |
1895 { // patterndelay active | |
1896 if(--pf->patdly2) pf->patpos--; // so turn back pf->patpos by 1 | |
1897 } | |
1898 | |
1899 // Do we have to get a new patternpointer ? | |
1900 // (when pf->patpos reaches 64 or when | |
1901 // a patternbreak is active) | |
1902 | |
1903 if(pf->patpos == pf->numrow) pf->posjmp = 3; | |
1904 | |
1905 if(pf->posjmp) | |
1906 { pf->patpos = pf->patbrk; | |
1907 pf->sngpos+=(pf->posjmp-2); | |
1908 pf->patbrk = pf->posjmp = 0; | |
1909 if(pf->sngpos>=pf->numpos) | |
1910 { if(!pf->loop) return; | |
1911 if((pf->sngpos = pf->reppos) == 0) | |
1912 { pf->volume = pf->initvolume; | |
1913 pf->sngspd = pf->initspeed; | |
1914 pf->bpm = pf->inittempo; | |
1915 } | |
1916 } | |
1917 if(pf->sngpos<0) pf->sngpos = pf->numpos-1; | |
1918 } | |
1919 | |
1920 if(!pf->patdly2) | |
1921 { for(t=0; t<pf->numchn; t++) | |
1922 { UBYTE inst; | |
1923 | |
1924 tr = pf->patterns[(pf->positions[pf->sngpos]*pf->numchn)+t]; | |
1925 pf->numrow = pf->pattrows[pf->positions[pf->sngpos]]; | |
1926 | |
1927 mp_channel = t; | |
1928 a = &pf->control[t]; | |
1929 a->row = (tr < pf->numtrk) ? UniFindRow(pf->tracks[tr],pf->patpos) : NULL; | |
1930 a->newsamp = 0; | |
1931 | |
1932 if(a->row==NULL) continue; | |
1933 UniSetRow(a->row); | |
1934 funky = 0; // Funky is set to indicate note or inst change | |
1935 | |
1936 while(c = UniGetByte()) | |
1937 { switch(c) | |
1938 { case UNI_NOTE: | |
1939 funky |= 1; | |
1940 a->anote = UniGetByte(); | |
1941 a->kick = 1; | |
1942 a->start = -1; | |
1943 | |
1944 // retrig tremolo and vibrato waves ? | |
1945 | |
1946 if(!(a->wavecontrol & 0x80)) a->trmpos = 0; | |
1947 if(!(a->wavecontrol & 0x08)) a->vibpos = 0; | |
1948 if(!a->panbwave) a->panbpos = 0; | |
1949 break; | |
1950 | |
1951 case UNI_INSTRUMENT: | |
1952 funky |= 2; | |
1953 inst = UniGetByte(); | |
1954 if(inst >= pf->numins) break; // <- safety valve | |
1955 | |
1956 a->i = (pf->flags & UF_INST) ? &pf->instruments[inst] : NULL; | |
1957 a->retrig = 0; | |
1958 a->s3mtremor = 0; | |
1959 a->sample = inst; | |
1960 break; | |
1961 | |
1962 default: | |
1963 UniSkipOpcode(c); | |
1964 break; | |
1965 } | |
1966 } | |
1967 | |
1968 if(funky) | |
1969 { i = a->i; | |
1970 if(i != NULL) | |
1971 { if(i->samplenumber[a->anote] >= pf->numsmp) continue; | |
1972 s = &pf->samples[i->samplenumber[a->anote]]; | |
1973 a->note = i->samplenote[a->anote]; | |
1974 } else | |
1975 { a->note = a->anote; | |
1976 s = &pf->samples[a->sample]; | |
1977 } | |
1978 | |
1979 if(a->s != s) | |
1980 { a->s = s; | |
1981 a->newsamp = a->period; | |
1982 } | |
1983 | |
1984 // channel or instrument determined panning ? | |
1985 | |
1986 a->panning = pf->panning[t]; | |
1987 if(s->flags & SF_OWNPAN) | |
1988 a->panning = s->panning; | |
1989 else if((i != NULL) && (i->flags & IF_OWNPAN)) | |
1990 a->panning = i->panning; | |
1991 | |
1992 a->handle = s->handle; | |
1993 a->speed = s->speed; | |
1994 | |
1995 if(i != NULL) | |
1996 { if(i->flags & IF_PITCHPAN) | |
1997 a->panning += ((a->anote-i->pitpancenter) * i->pitpansep) / 8; | |
1998 a->pitflg = i->pitflg; | |
1999 a->volflg = i->volflg; | |
2000 a->panflg = i->panflg; | |
2001 a->nna = i->nnatype; | |
2002 a->dca = i->dca; | |
2003 a->dct = i->dct; | |
2004 } else | |
2005 { a->pitflg = 0; | |
2006 a->volflg = 0; | |
2007 a->panflg = 0; | |
2008 a->nna = 0; | |
2009 a->dca = 0; | |
2010 a->dct = 0; | |
2011 } | |
2012 | |
2013 if(funky & 2) | |
2014 { // IT's random volume variations: 0:8 bit fixed, and one bit for sign. | |
2015 a->volume = s->volume; | |
2016 a->tmpvolume = s->volume; | |
2017 if((s != NULL) && (i != NULL)) | |
2018 { a->volume = a->tmpvolume = s->volume + ((s->volume * ((SLONG)i->rvolvar * (SLONG)((rand() & 511)-255))) / 25600); | |
2019 if(a->panning != PAN_SURROUND) a->panning += ((a->panning * ((SLONG)i->rpanvar * (SLONG)((rand() & 511)-255))) / 25600); | |
2020 } | |
2021 } | |
2022 | |
2023 period = GetPeriod(a->note, a->speed); | |
2024 a->wantedperiod = period; | |
2025 a->tmpperiod = period; | |
2026 a->keyoff = KEY_KICK; | |
2027 } | |
2028 } | |
2029 } | |
2030 } | |
2031 | |
2032 // Update effects | |
2033 | |
2034 for(t=0; t<pf->numchn; t++) | |
2035 { mp_channel = t; | |
2036 a = &pf->control[t]; | |
2037 | |
2038 if((aout = a->slave) != NULL) | |
2039 { a->fadevol = aout->fadevol; | |
2040 a->period = aout->period; | |
2041 if(a->kick != 1) a->keyoff = aout->keyoff; | |
2042 } | |
2043 | |
2044 if(a->row == NULL) continue; | |
2045 UniSetRow(a->row); | |
2046 | |
2047 a->ownper = a->ownvol = 0; | |
2048 pt_playeffects(); | |
2049 if(!a->ownper) a->period = a->tmpperiod; | |
2050 if(!a->ownvol) a->volume = a->tmpvolume; | |
2051 | |
2052 if(a->s != NULL) | |
2053 { if(a->i != NULL) | |
2054 a->outvolume = (a->volume * a->s->globvol * a->i->globvol) / 1024; // max val: 256 | |
2055 else | |
2056 a->outvolume = (a->volume * a->s->globvol) / 16; // max val: 256 | |
2057 if(a->outvolume > 256) a->volume = 256; | |
2058 } | |
2059 } | |
2060 | |
2061 | |
2062 a = pf->control; | |
2063 if(pf->flags & UF_NNA) | |
2064 { for(t=0; t<pf->numchn; t++, a++) | |
2065 { if(a->kick == 1) | |
2066 { if(a->slave != NULL) | |
2067 { aout = a->slave; | |
2068 if(aout->nna & 0x3f) | |
2069 { // oh boy, we have to do an NNA | |
2070 // Make sure the old MP_VOICE channel knows it has no master now! | |
2071 | |
2072 a->slave = NULL; // assume the channel is taken by NNA | |
2073 aout->mflag = 0; | |
2074 | |
2075 switch(aout->nna) | |
2076 { case NNA_CONTINUE: | |
2077 break; // continue note, do nothing | |
2078 | |
2079 case NNA_OFF: // note off | |
2080 aout->keyoff |= KEY_OFF; | |
2081 if(!(aout->volflg & EF_ON) || (aout->volflg & EF_LOOP)) | |
2082 aout->keyoff = KEY_KILL; | |
2083 break; | |
2084 | |
2085 case NNA_FADE: | |
2086 aout->keyoff |= KEY_FADE; | |
2087 break; | |
2088 } | |
2089 } | |
2090 } | |
2091 | |
2092 k = 0; | |
2093 if(a->dct != DCT_OFF) | |
2094 { for(t2=0; t2<md_sngchn; t2++) | |
2095 { if(!(Voice_Stopped(t2)) && (pf->voice[t2].masterchn == t) && (a->sample == pf->voice[t2].sample)) | |
2096 { switch(a->dct) | |
2097 { case DCT_NOTE: | |
2098 if(a->note == pf->voice[t2].note) | |
2099 k = 1; | |
2100 break; | |
2101 | |
2102 case DCT_SAMPLE: | |
2103 if(a->handle == pf->voice[t2].handle) | |
2104 k = 1; | |
2105 break; | |
2106 | |
2107 case DCT_INST: | |
2108 k = 1; | |
2109 break; | |
2110 } | |
2111 | |
2112 if(k==1) | |
2113 { k = 0; | |
2114 switch(a->dca) | |
2115 { case DCA_CUT : | |
2116 pf->voice[t2].fadevol = 0; | |
2117 a->slave = &pf->voice[a->slavechn=t2]; | |
2118 break; | |
2119 | |
2120 case DCA_OFF : | |
2121 //a->slave = &pf->voice[newchn]; | |
2122 pf->voice[t2].keyoff |= KEY_OFF; | |
2123 if(!(pf->voice[t2].volflg & EF_ON) || (pf->voice[t2].volflg & EF_LOOP)) | |
2124 pf->voice[t2].keyoff = KEY_KILL; | |
2125 break; | |
2126 | |
2127 case DCA_FADE: | |
2128 //a->slave = &pf->voice[newchn]; | |
2129 pf->voice[t2].keyoff |= KEY_FADE; | |
2130 break; | |
2131 } | |
2132 } | |
2133 } | |
2134 } | |
2135 } // DCT checking | |
2136 } // if a->kick | |
2137 } // for loop | |
2138 } | |
2139 | |
2140 a = pf->control; | |
2141 for(t=0; t<pf->numchn; t++, a++) | |
2142 { int newchn; | |
2143 | |
2144 if(a->notedelay) continue; | |
2145 | |
2146 if(a->kick == 1) | |
2147 { // If no channel was cut above, find an empty or quiet channel here | |
2148 if(pf->flags & UF_NNA) | |
2149 { if(a->slave==NULL) | |
2150 { if((newchn = MP_FindEmptyChannel(t)) != -1) | |
2151 a->slave = &pf->voice[a->slavechn=newchn]; | |
2152 } | |
2153 } else | |
2154 a->slave = &pf->voice[a->slavechn=t]; | |
2155 | |
2156 // Assign parts of MP_VOICE only done for a KICK! | |
2157 | |
2158 if((aout = a->slave) != NULL) | |
2159 { if(aout->mflag && (aout->master!=NULL)) aout->master->slave = NULL; | |
2160 a->slave = aout; | |
2161 aout->master = a; | |
2162 aout->masterchn = t; | |
2163 aout->mflag = 1; | |
2164 } | |
2165 } else | |
2166 { aout = a->slave; | |
2167 } | |
2168 | |
2169 if(aout != NULL) | |
2170 { aout->kick = a->kick; | |
2171 aout->i = a->i; | |
2172 aout->s = a->s; | |
2173 aout->sample = a->sample; | |
2174 aout->handle = a->handle; | |
2175 aout->period = a->period; | |
2176 aout->panning = a->panning; | |
2177 aout->chanvol = a->chanvol; | |
2178 aout->fadevol = a->fadevol; | |
2179 aout->start = a->start; | |
2180 aout->volflg = a->volflg; | |
2181 aout->panflg = a->panflg; | |
2182 aout->pitflg = a->pitflg; | |
2183 aout->volume = a->outvolume; | |
2184 aout->keyoff = a->keyoff; | |
2185 aout->note = a->note; | |
2186 aout->nna = a->nna; | |
2187 } | |
2188 a->kick = 0; | |
2189 | |
2190 } | |
2191 | |
2192 // Now set up the actual hardware channel playback information | |
2193 | |
2194 for(t=0; t<md_sngchn; t++) | |
2195 { SWORD envpan, envvol = 256, envpit = 0; | |
2196 SLONG vibval, vibdpt; | |
2197 | |
2198 aout = &pf->voice[mp_channel = t]; | |
2199 i = aout->i; | |
2200 s = aout->s; | |
2201 | |
2202 if(s==NULL) continue; | |
2203 | |
2204 if(aout->period < 40) aout->period = 40; | |
2205 if(aout->period > 50000) aout->period = 50000; | |
2206 | |
2207 if(aout->kick) | |
2208 { Voice_Play(t,s,(aout->start == -1) ? ((s->flags & SF_UST_LOOP) ? s->loopstart : 0) : aout->start); | |
2209 //aout->keyoff = KEY_KICK; | |
2210 aout->fadevol = 32768; | |
2211 aout->aswppos = 0; | |
2212 | |
2213 if((i != NULL) && (aout->kick != 2)) | |
2214 { StartEnvelope(&aout->venv, aout->volflg, i->volpts, i->volsusbeg, i->volsusend, i->volbeg, i->volend, i->volenv, aout->keyoff); | |
2215 StartEnvelope(&aout->penv, aout->panflg, i->panpts, i->pansusbeg, i->pansusend, i->panbeg, i->panend, i->panenv, aout->keyoff); | |
2216 StartEnvelope(&aout->cenv, aout->pitflg, i->pitpts, i->pitsusbeg, i->pitsusend, i->pitbeg, i->pitend, i->pitenv, aout->keyoff); | |
2217 } | |
2218 aout->kick = 0; | |
2219 } | |
2220 | |
2221 if(i != NULL) | |
2222 { envvol = ProcessEnvelope(&aout->venv,256,aout->keyoff); | |
2223 envpan = ProcessEnvelope(&aout->penv,128,aout->keyoff); | |
2224 envpit = ProcessEnvelope(&aout->cenv,32,aout->keyoff); | |
2225 } | |
2226 | |
2227 tmpvol = aout->fadevol; // max 32768 | |
2228 tmpvol *= aout->chanvol; // * max 64 | |
2229 tmpvol *= aout->volume; // * max 256 | |
2230 tmpvol /= 16384L; // tmpvol is max 32768 | |
2231 aout->totalvol = tmpvol>>2; // totalvolume used to determine samplevolume | |
2232 tmpvol *= envvol; // * max 256 | |
2233 tmpvol *= pf->volume; // * max 128 | |
2234 tmpvol /= 4194304UL; | |
2235 | |
2236 if((aout->masterchn != -1) && pf->control[aout->masterchn].muted) // Channel Muting Line | |
2237 Voice_SetVolume(t,0); | |
2238 else | |
2239 Voice_SetVolume(t,tmpvol); | |
2240 | |
2241 | |
2242 if(aout->panning == PAN_SURROUND) | |
2243 Voice_SetPanning(t, PAN_SURROUND); | |
2244 else | |
2245 { if(aout->penv.flg & EF_ON) | |
2246 Voice_SetPanning(t,DoPan(envpan,aout->panning)); | |
2247 else | |
2248 Voice_SetPanning(t,aout->panning); | |
2249 } | |
2250 | |
2251 if(aout->period && s->vibdepth) | |
2252 { switch(s->vibtype) | |
2253 { case 0: | |
2254 vibval = avibtab[s->avibpos & 127]; | |
2255 if(s->avibpos & 0x80) vibval=-vibval; | |
2256 break; | |
2257 | |
2258 case 1: | |
2259 vibval = 64; | |
2260 if(s->avibpos & 0x80) vibval=-vibval; | |
2261 break; | |
2262 | |
2263 case 2: | |
2264 vibval = 63-(((s->avibpos + 128) & 255) >> 1); | |
2265 break; | |
2266 | |
2267 case 3: | |
2268 vibval = (((s->avibpos + 128) & 255) >> 1) - 64; | |
2269 break; | |
2270 } | |
2271 } | |
2272 | |
2273 if(s->vibflags & AV_IT) | |
2274 { if((aout->aswppos >> 8) < s->vibdepth) | |
2275 { aout->aswppos += s->vibsweep; | |
2276 vibdpt = aout->aswppos; | |
2277 } else | |
2278 vibdpt = s->vibdepth << 8; | |
2279 vibval = (vibval*vibdpt) >> 16; | |
2280 if(aout->mflag) | |
2281 { if(!(pf->flags & UF_LINEAR)) vibval>>=1; | |
2282 aout->period -= vibval; | |
2283 } | |
2284 } else // do XM style auto-vibrato | |
2285 { if(!(aout->keyoff & KEY_OFF)) | |
2286 { if(aout->aswppos < s->vibsweep) | |
2287 { vibdpt = (aout->aswppos*s->vibdepth) / s->vibsweep; | |
2288 aout->aswppos++; | |
2289 } else | |
2290 vibdpt = s->vibdepth; | |
2291 } else | |
2292 { // key-off -> depth becomes 0 if final depth wasn't reached | |
2293 // or stays at final level if depth WAS reached | |
2294 if(aout->aswppos>=s->vibsweep) | |
2295 vibdpt = s->vibdepth; | |
2296 else | |
2297 vibdpt = 0; | |
2298 } | |
2299 vibval = (vibval*vibdpt)>>8; | |
2300 aout->period -= vibval; | |
2301 } | |
2302 | |
2303 // update vibrato position | |
2304 s->avibpos = (s->avibpos+s->vibrate) & 0xff; | |
2305 | |
2306 if(aout->cenv.flg & EF_ON) | |
2307 { envpit = envpit-32; | |
2308 aout->period -= envpit; | |
2309 } | |
2310 | |
2311 Voice_SetFrequency(t,getfrequency(pf->flags,aout->period)); | |
2312 | |
2313 if(aout->fadevol == 0) // check for a dead note (fadevol = 0) | |
2314 Voice_Stop(t); | |
2315 else | |
2316 { // if keyfade, start substracting | |
2317 // fadeoutspeed from fadevol: | |
2318 | |
2319 if((i != NULL) && (aout->keyoff & KEY_FADE)) | |
2320 { if(aout->fadevol >= i->volfade) | |
2321 aout->fadevol -= i->volfade; | |
2322 else | |
2323 aout->fadevol = 0; | |
2324 } | |
2325 } | |
2326 | |
2327 MD_SetBPM(pf->bpm); | |
2328 } | |
2329 } | |
2330 | |
2331 | |
2332 BOOL Player_Init(UNIMOD *mf) | |
2333 { | |
2334 int t; | |
2335 | |
2336 mf->extspd = 1; | |
2337 mf->panflag = 1; | |
2338 mf->loop = 0; | |
2339 | |
2340 mf->pat_reppos = 0; | |
2341 mf->pat_repcnt = 0; | |
2342 mf->sngpos = 0; | |
2343 mf->sngspd = mf->initspeed; | |
2344 mf->volume = mf->initvolume; | |
2345 | |
2346 mf->vbtick = mf->sngspd; | |
2347 mf->patdly = 0; | |
2348 mf->patdly2 = 0; | |
2349 mf->bpm = mf->inittempo; | |
2350 | |
2351 mf->patpos = 0; | |
2352 mf->posjmp = 2; // <- make sure the player fetches the first note | |
2353 mf->patbrk = 0; | |
2354 | |
2355 // Make sure the player doesn't start with garbage: | |
2356 | |
2357 if((mf->control=(MP_CONTROL *)_mm_calloc(mf->numchn,sizeof(MP_CONTROL)))==NULL) return 1; | |
2358 if((mf->voice=(MP_VOICE *)_mm_calloc(md_sngchn,sizeof(MP_VOICE)))==NULL) return 1; | |
2359 | |
2360 for(t=0; t<mf->numchn; t++) | |
2361 { mf->control[t].chanvol = mf->chanvol[t]; | |
2362 mf->control[t].panning = mf->panning[t]; | |
2363 } | |
2364 | |
2365 return 0; | |
2366 } | |
2367 | |
2368 | |
2369 void Player_Exit(UNIMOD *mf) | |
2370 { | |
2371 if(mf==NULL) return; | |
2372 if(mf==pf) | |
2373 { Player_Stop(); | |
2374 pf = NULL; | |
2375 } | |
2376 if(mf->control!=NULL) free(mf->control); | |
2377 if(mf->voice!=NULL) free(mf->voice); | |
2378 mf->control = NULL; | |
2379 mf->voice = NULL; | |
2380 | |
2381 } | |
2382 | |
2383 | |
2384 void Player_SetVolume(int volume) | |
2385 { | |
2386 if(pf==NULL) return; | |
2387 | |
2388 if(volume > 128) volume = 128; | |
2389 if(volume < 0) volume = 0; | |
2390 | |
2391 pf->volume = volume; | |
2392 } | |
2393 | |
2394 | |
2395 UNIMOD *Player_GetUnimod(void) | |
2396 { | |
2397 return pf; | |
2398 } | |
2399 | |
2400 | |
2401 void Player_Start(UNIMOD *mf) | |
2402 { | |
2403 int t; | |
2404 | |
2405 if(!MikMod_Active()) | |
2406 { isfirst = 2; | |
2407 MikMod_EnableOutput(); | |
2408 } | |
2409 | |
2410 if(mf==NULL) return; | |
2411 | |
2412 mf->forbid = 0; | |
2413 if(pf != mf) | |
2414 { // new song is being started, so completely stop out the old one. | |
2415 if(pf!=NULL) pf->forbid = 1; | |
2416 for(t=0; t<md_sngchn; t++) Voice_Stop(t); | |
2417 } | |
2418 | |
2419 pf = mf; | |
2420 } | |
2421 | |
2422 | |
2423 void Player_Stop(void) | |
2424 { | |
2425 if(md_sfxchn==0) MikMod_DisableOutput(); | |
2426 if(pf != NULL) pf->forbid = 1; | |
2427 pf = NULL; | |
2428 } | |
2429 | |
2430 | |
2431 BOOL MP_Playing(UNIMOD *mf) | |
2432 { | |
2433 if((mf==NULL) || (mf!=pf)) return 0; | |
2434 return(!(mf->sngpos>=mf->numpos)); | |
2435 } | |
2436 | |
2437 | |
2438 BOOL Player_Active(void) | |
2439 { | |
2440 if(pf==NULL) return 0; | |
2441 return(!(pf->sngpos>=pf->numpos)); | |
2442 } | |
2443 | |
2444 | |
2445 void MP_NextPosition(UNIMOD *mf) | |
2446 { | |
2447 int t; | |
2448 | |
2449 if(mf==NULL) return; | |
2450 mf->forbid = 1; | |
2451 mf->posjmp = 3; | |
2452 mf->patbrk = 0; | |
2453 mf->vbtick = mf->sngspd; | |
2454 | |
2455 for(t=0; t<md_sngchn; t++) | |
2456 { Voice_Stop(t); | |
2457 mf->voice[t].i = NULL; | |
2458 mf->voice[t].s = NULL; | |
2459 } | |
2460 | |
2461 for(t=0; t<mf->numchn; t++) | |
2462 { mf->control[t].i = NULL; | |
2463 mf->control[t].s = NULL; | |
2464 } | |
2465 mf->forbid = 0; | |
2466 } | |
2467 | |
2468 | |
2469 void Player_NextPosition(void) | |
2470 { | |
2471 MP_NextPosition(pf); | |
2472 } | |
2473 | |
2474 | |
2475 void MP_PrevPosition(UNIMOD *mf) | |
2476 { | |
2477 int t; | |
2478 | |
2479 if(mf==NULL) return; | |
2480 mf->forbid = 1; | |
2481 mf->posjmp = 1; | |
2482 mf->patbrk = 0; | |
2483 mf->vbtick = mf->sngspd; | |
2484 | |
2485 for(t=0; t<md_sngchn; t++) | |
2486 { Voice_Stop(t); | |
2487 mf->voice[t].i = NULL; | |
2488 mf->voice[t].s = NULL; | |
2489 } | |
2490 | |
2491 for(t=0; t<mf->numchn; t++) | |
2492 { mf->control[t].i = NULL; | |
2493 mf->control[t].s = NULL; | |
2494 } | |
2495 | |
2496 mf->forbid = 0; | |
2497 } | |
2498 | |
2499 | |
2500 void Player_PrevPosition(void) | |
2501 { | |
2502 MP_PrevPosition(pf); | |
2503 } | |
2504 | |
2505 | |
2506 void MP_SetPosition(UNIMOD *mf, UWORD pos) | |
2507 { | |
2508 int t; | |
2509 | |
2510 if(mf==NULL) return; | |
2511 mf->forbid = 1; | |
2512 if(pos>=mf->numpos) pos = mf->numpos; | |
2513 mf->posjmp = 2; | |
2514 mf->patbrk = 0; | |
2515 mf->sngpos = pos; | |
2516 mf->vbtick = mf->sngspd; | |
2517 | |
2518 for(t=0; t<md_sngchn; t++) | |
2519 { Voice_Stop(t); | |
2520 mf->voice[t].i = NULL; | |
2521 mf->voice[t].s = NULL; | |
2522 } | |
2523 | |
2524 for(t=0; t<mf->numchn; t++) | |
2525 { mf->control[t].i = NULL; | |
2526 mf->control[t].s = NULL; | |
2527 } | |
2528 | |
2529 mf->forbid = 0; | |
2530 } | |
2531 | |
2532 | |
2533 void Player_SetPosition(UWORD pos) | |
2534 { | |
2535 MP_SetPosition(pf,pos); | |
2536 } | |
2537 | |
2538 | |
2539 void MP_Unmute(UNIMOD *mf, SLONG arg1, ...) | |
2540 { | |
2541 va_list ap; | |
2542 SLONG t, arg2, arg3; | |
2543 | |
2544 va_start(ap,arg1); | |
2545 | |
2546 if(mf != NULL) | |
2547 { switch(arg1) | |
2548 { case MUTE_INCLUSIVE: | |
2549 if((!(arg2=va_arg(ap,SLONG))) && (!(arg3=va_arg(ap,SLONG))) || (arg2 > arg3) || (arg3 >= mf->numchn)) | |
2550 { va_end(ap); | |
2551 return; | |
2552 } | |
2553 for(;arg2<mf->numchn && arg2<=arg3;arg2++) | |
2554 mf->control[arg2].muted = 0; | |
2555 break; | |
2556 | |
2557 case MUTE_EXCLUSIVE: | |
2558 if((!(arg2=va_arg(ap,SLONG))) && (!(arg3=va_arg(ap,SLONG))) || (arg2 > arg3) || (arg3 >= mf->numchn)) | |
2559 { va_end(ap); | |
2560 return; | |
2561 } | |
2562 for(t=0;t<mf->numchn;t++) | |
2563 { if ((t>=arg2) && (t<=arg3)) continue; | |
2564 mf->control[t].muted = 0; | |
2565 } | |
2566 break; | |
2567 | |
2568 default: | |
2569 if(arg1<mf->numchn) mf->control[arg1].muted = 0; | |
2570 break; | |
2571 } | |
2572 } | |
2573 va_end(ap); | |
2574 | |
2575 return; | |
2576 } | |
2577 | |
2578 | |
2579 void Player_Unmute(SLONG arg1, ...) | |
2580 { | |
2581 va_list argptr; | |
2582 MP_Unmute(pf,arg1, argptr); | |
2583 va_end(argptr); | |
2584 } | |
2585 | |
2586 | |
2587 void MP_Mute(UNIMOD *mf, SLONG arg1, ...) | |
2588 { | |
2589 va_list ap; | |
2590 SLONG t, arg2, arg3; | |
2591 | |
2592 va_start(ap,arg1); | |
2593 | |
2594 if(mf != NULL) | |
2595 { switch (arg1) | |
2596 { case MUTE_INCLUSIVE: | |
2597 if ((!(arg2=va_arg(ap,SLONG))) && (!(arg3=va_arg(ap,SLONG))) || (arg2 > arg3) || (arg3 >= mf->numchn)) | |
2598 { va_end(ap); | |
2599 return; | |
2600 } | |
2601 for(;arg2<mf->numchn && arg2<=arg3;arg2++) | |
2602 mf->control[arg2].muted = 1; | |
2603 break; | |
2604 | |
2605 case MUTE_EXCLUSIVE: | |
2606 if ((!(arg2=va_arg(ap,SLONG))) && (!(arg3=va_arg(ap,SLONG))) || (arg2 > arg3) || (arg3 >= mf->numchn)) | |
2607 { va_end(ap); | |
2608 return; | |
2609 } | |
2610 for (t=0; t<mf->numchn; t++) | |
2611 { if ((t>=arg2) && (t<=arg3)) continue; | |
2612 mf->control[t].muted = 1; | |
2613 } | |
2614 break; | |
2615 | |
2616 default: | |
2617 if(arg1<mf->numchn) | |
2618 mf->control[arg1].muted = 1; | |
2619 break; | |
2620 } | |
2621 } | |
2622 va_end(ap); | |
2623 | |
2624 return; | |
2625 } | |
2626 | |
2627 | |
2628 void Player_Mute(SLONG arg1, ...) | |
2629 { | |
2630 va_list argptr; | |
2631 MP_Mute(pf,arg1, argptr); | |
2632 va_end(argptr); | |
2633 } | |
2634 | |
2635 | |
2636 void MP_ToggleMute(UNIMOD *mf, SLONG arg1, ...) | |
2637 { | |
2638 va_list ap; | |
2639 SLONG arg2, arg3; | |
2640 ULONG t; | |
2641 | |
2642 va_start(ap,arg1); | |
2643 | |
2644 if(mf != NULL) | |
2645 { switch (arg1) | |
2646 { case MUTE_INCLUSIVE: | |
2647 if ((!(arg2=va_arg(ap,SLONG))) && (!(arg3=va_arg(ap,SLONG))) || (arg2 > arg3) || (arg3 >= mf->numchn)) | |
2648 { va_end(ap); | |
2649 return; | |
2650 } | |
2651 for(; arg2<mf->numchn && arg2<=arg3; arg2++) | |
2652 mf->control[arg2].muted = (mf->control[arg2].muted) ? 0 : 1; | |
2653 | |
2654 break; | |
2655 | |
2656 case MUTE_EXCLUSIVE: | |
2657 if ((!(arg2=va_arg(ap,SLONG))) && (!(arg3=va_arg(ap,SLONG))) || (arg2 > arg3) || (arg3 >= mf->numchn)) | |
2658 { va_end(ap); | |
2659 return; | |
2660 } | |
2661 for (t=0;t<mf->numchn;t++) | |
2662 { if((t>=arg2) && (t<=arg3)) continue; | |
2663 mf->control[t].muted = (mf->control[t].muted) ? 0 : 1; | |
2664 } | |
2665 break; | |
2666 | |
2667 default: | |
2668 if(arg1<mf->numchn) | |
2669 mf->control[arg1].muted = (mf->control[arg1].muted) ? 0 : 1; | |
2670 break; | |
2671 } | |
2672 } | |
2673 va_end(ap); | |
2674 | |
2675 return; | |
2676 } | |
2677 | |
2678 | |
2679 void Player_ToggleMute(SLONG arg1, ...) | |
2680 { | |
2681 va_list argptr; | |
2682 MP_ToggleMute(pf,arg1, argptr); | |
2683 va_end(argptr); | |
2684 } | |
2685 | |
2686 | |
2687 BOOL MP_Muted(UNIMOD *mf, int chan) | |
2688 { | |
2689 if(mf==NULL) return 1; | |
2690 return (chan<mf->numchn) ? mf->control[chan].muted : 1; | |
2691 } | |
2692 | |
2693 | |
2694 BOOL Player_Muted(int chan) | |
2695 { | |
2696 if(pf==NULL) return 1; | |
2697 return (chan<pf->numchn) ? pf->control[chan].muted : 1; | |
2698 } | |
2699 | |
2700 | |
2701 int MP_GetChannelVoice(UNIMOD *mf, int chan) | |
2702 { | |
2703 if(mf==NULL) return 0; | |
2704 return mf->control[chan].slavechn; | |
2705 } | |
2706 | |
2707 | |
2708 int Player_GetChannelVoice(int chan) | |
2709 { | |
2710 if(pf==NULL) return 0; | |
2711 return pf->control[chan].slavechn; | |
2712 } | |
2713 | |
2714 | |
2715 void Player_TogglePause(void) | |
2716 { | |
2717 if(pf==NULL) return; | |
2718 if(pf->forbid == 1) | |
2719 pf->forbid = 0; | |
2720 else | |
2721 pf->forbid = 1; | |
2722 } | |
2723 | |
2724 | |
2725 // --> The following procedures were taken from UNITRK because they | |
2726 // -> are ProTracker format specific. | |
2727 | |
2728 void UniInstrument(UBYTE ins) | |
2729 // Appends UNI_INSTRUMENT opcode to the unitrk stream. | |
2730 { | |
2731 UniWrite(UNI_INSTRUMENT); | |
2732 UniWrite(ins); | |
2733 } | |
2734 | |
2735 void UniNote(UBYTE note) | |
2736 // Appends UNI_NOTE opcode to the unitrk stream. | |
2737 { | |
2738 UniWrite(UNI_NOTE); | |
2739 UniWrite(note); | |
2740 } | |
2741 | |
2742 void UniPTEffect(UBYTE eff, UBYTE dat) | |
2743 // Appends UNI_PTEFFECTX opcode to the unitrk stream. | |
2744 { | |
2745 if(eff!=0 || dat!=0) // don't write empty effect | |
2746 { UniWrite(UNI_PTEFFECT0+eff); | |
2747 UniWrite(dat); | |
2748 } | |
2749 } | |
2750 | |
2751 void UniVolEffect(UWORD eff, UBYTE dat) | |
2752 // Appends UNI_VOLEFFECT + effect/dat to unistream. | |
2753 { | |
2754 if(eff!=0 || dat!=0) // don't write empty effect | |
2755 { UniWrite(UNI_VOLEFFECTS); | |
2756 UniWrite(eff); UniWrite(dat); | |
2757 } | |
2758 } | |
2759 |