Mercurial > audlegacy-plugins
comparison src/Input/adplug/core/adlibemu.c @ 0:13389e613d67 trunk
[svn] - initial import of audacious-plugins tree (lots to do)
author | nenolod |
---|---|
date | Mon, 18 Sep 2006 01:11:49 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:13389e613d67 |
---|---|
1 /* | |
2 * ADLIBEMU.C | |
3 * Copyright (C) 1998-2001 Ken Silverman | |
4 * Ken Silverman's official web site: "http://www.advsys.net/ken" | |
5 * | |
6 * This library is free software; you can redistribute it and/or | |
7 * modify it under the terms of the GNU Lesser General Public | |
8 * License as published by the Free Software Foundation; either | |
9 * version 2.1 of the License, or (at your option) any later version. | |
10 * | |
11 * This library is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 * Lesser General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU Lesser General Public | |
17 * License along with this library; if not, write to the Free Software | |
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
19 */ | |
20 | |
21 /* | |
22 This file is a digital Adlib emulator for OPL2 and possibly OPL3 | |
23 | |
24 Features that could be added in a future version: | |
25 - Amplitude and Frequency Vibrato Bits (not hard, but a big speed hit) | |
26 - Global Keyboard Split Number Bit (need to research this one some more) | |
27 - 2nd Adlib chip for OPL3 (simply need to make my cell array bigger) | |
28 - Advanced connection modes of OPL3 (Just need to add more "docell" cases) | |
29 - L/R Stereo bits of OPL3 (Need adlibgetsample to return stereo) | |
30 | |
31 Features that aren't worth supporting: | |
32 - Anything related to adlib timers&interrupts (Sorry - I always used IRQ0) | |
33 - Composite sine wave mode (CSM) (Supported only on ancient cards) | |
34 | |
35 I'm not sure about a few things in my code: | |
36 - Attack curve. What function is this anyway? I chose to use an order-3 | |
37 polynomial to approximate but this doesn't seem right. | |
38 - Attack/Decay/Release constants - my constants may not be exact | |
39 - What should ADJUSTSPEED be? | |
40 - Haven't verified that Global Keyboard Split Number Bit works yet | |
41 - Some of the drums don't always sound right. It's pretty hard to guess | |
42 the exact waveform of drums when you look at random data which is | |
43 slightly randomized due to digital ADC recording. | |
44 - Adlib seems to have a lot more treble than my emulator does. I'm not | |
45 sure if this is simply unfixable due to the sound blaster's different | |
46 filtering on FM and digital playback or if it's a serious bug in my | |
47 code. | |
48 */ | |
49 | |
50 #include <math.h> | |
51 #include <string.h> | |
52 | |
53 #if !defined(max) && !defined(__cplusplus) | |
54 #define max(a,b) (((a) > (b)) ? (a) : (b)) | |
55 #endif | |
56 #if !defined(min) && !defined(__cplusplus) | |
57 #define min(a,b) (((a) < (b)) ? (a) : (b)) | |
58 #endif | |
59 | |
60 #define PI 3.141592653589793 | |
61 #define MAXCELLS 18 | |
62 #define WAVPREC 2048 | |
63 | |
64 static float AMPSCALE=(8192.0); | |
65 #define FRQSCALE (49716/512.0) | |
66 | |
67 //Constants for Ken's Awe32, on a PII-266 (Ken says: Use these for KSM's!) | |
68 #define MODFACTOR 4.0 //How much of modulator cell goes into carrier | |
69 #define MFBFACTOR 1.0 //How much feedback goes back into modulator | |
70 #define ADJUSTSPEED 0.75 //0<=x<=1 Simulate finite rate of change of state | |
71 | |
72 //Constants for Ken's Awe64G, on a P-133 | |
73 //#define MODFACTOR 4.25 //How much of modulator cell goes into carrier | |
74 //#define MFBFACTOR 0.5 //How much feedback goes back into modulator | |
75 //#define ADJUSTSPEED 0.85 //0<=x<=1 Simulate finite rate of change of state | |
76 | |
77 typedef struct | |
78 { | |
79 float val, t, tinc, vol, sustain, amp, mfb; | |
80 float a0, a1, a2, a3, decaymul, releasemul; | |
81 short *waveform; | |
82 long wavemask; | |
83 void (*cellfunc)(void *, float); | |
84 unsigned char flags, dum0, dum1, dum2; | |
85 } celltype; | |
86 | |
87 static long numspeakers, bytespersample; | |
88 static float recipsamp; | |
89 static celltype cell[MAXCELLS]; | |
90 static signed short wavtable[WAVPREC*3]; | |
91 static float kslmul[4] = {0.0,0.5,0.25,1.0}; | |
92 static float frqmul[16] = {.5,1,2,3,4,5,6,7,8,9,10,10,12,12,15,15}, nfrqmul[16]; | |
93 static unsigned char adlibreg[256], ksl[8][16]; | |
94 static unsigned char modulatorbase[9] = {0,1,2,8,9,10,16,17,18}; | |
95 static unsigned char odrumstat = 0; | |
96 static unsigned char base2cell[22] = {0,1,2,0,1,2,0,0,3,4,5,3,4,5,0,0,6,7,8,6,7,8}; | |
97 | |
98 float lvol[9] = {1,1,1,1,1,1,1,1,1}; //Volume multiplier on left speaker | |
99 float rvol[9] = {1,1,1,1,1,1,1,1,1}; //Volume multiplier on right speaker | |
100 long lplc[9] = {0,0,0,0,0,0,0,0,0}; //Samples to delay on left speaker | |
101 long rplc[9] = {0,0,0,0,0,0,0,0,0}; //Samples to delay on right speaker | |
102 | |
103 long nlvol[9], nrvol[9]; | |
104 long nlplc[9], nrplc[9]; | |
105 long rend = 0; | |
106 #define FIFOSIZ 256 | |
107 static float *rptr[9], *nrptr[9]; | |
108 static float rbuf[9][FIFOSIZ*2]; | |
109 static float snd[FIFOSIZ*2]; | |
110 | |
111 #ifndef USING_ASM | |
112 #define _inline | |
113 #endif | |
114 | |
115 #ifdef USING_ASM | |
116 static _inline void ftol (float f, long *a) | |
117 { | |
118 _asm | |
119 { | |
120 mov eax, a | |
121 fld f | |
122 fistp dword ptr [eax] | |
123 } | |
124 } | |
125 #else | |
126 static void ftol(float f, long *a) { | |
127 *a=f; | |
128 } | |
129 #endif | |
130 | |
131 #define ctc ((celltype *)c) //A rare attempt to make code easier to read! | |
132 void docell4 (void *c, float modulator) { } | |
133 void docell3 (void *c, float modulator) | |
134 { | |
135 long i; | |
136 | |
137 ftol(ctc->t+modulator,&i); | |
138 ctc->t += ctc->tinc; | |
139 ctc->val += (ctc->amp*ctc->vol*((float)ctc->waveform[i&ctc->wavemask])-ctc->val)*ADJUSTSPEED; | |
140 } | |
141 void docell2 (void *c, float modulator) | |
142 { | |
143 long i; | |
144 | |
145 ftol(ctc->t+modulator,&i); | |
146 | |
147 if (*(long *)&ctc->amp <= 0x37800000) | |
148 { | |
149 ctc->amp = 0; | |
150 ctc->cellfunc = docell4; | |
151 } | |
152 ctc->amp *= ctc->releasemul; | |
153 | |
154 ctc->t += ctc->tinc; | |
155 ctc->val += (ctc->amp*ctc->vol*((float)ctc->waveform[i&ctc->wavemask])-ctc->val)*ADJUSTSPEED; | |
156 } | |
157 void docell1 (void *c, float modulator) | |
158 { | |
159 long i; | |
160 | |
161 ftol(ctc->t+modulator,&i); | |
162 | |
163 if ((*(long *)&ctc->amp) <= (*(long *)&ctc->sustain)) | |
164 { | |
165 if (ctc->flags&32) | |
166 { | |
167 ctc->amp = ctc->sustain; | |
168 ctc->cellfunc = docell3; | |
169 } | |
170 else | |
171 ctc->cellfunc = docell2; | |
172 } | |
173 else | |
174 ctc->amp *= ctc->decaymul; | |
175 | |
176 ctc->t += ctc->tinc; | |
177 ctc->val += (ctc->amp*ctc->vol*((float)ctc->waveform[i&ctc->wavemask])-ctc->val)*ADJUSTSPEED; | |
178 } | |
179 void docell0 (void *c, float modulator) | |
180 { | |
181 long i; | |
182 | |
183 ftol(ctc->t+modulator,&i); | |
184 | |
185 ctc->amp = ((ctc->a3*ctc->amp + ctc->a2)*ctc->amp + ctc->a1)*ctc->amp + ctc->a0; | |
186 if ((*(long *)&ctc->amp) > 0x3f800000) | |
187 { | |
188 ctc->amp = 1; | |
189 ctc->cellfunc = docell1; | |
190 } | |
191 | |
192 ctc->t += ctc->tinc; | |
193 ctc->val += (ctc->amp*ctc->vol*((float)ctc->waveform[i&ctc->wavemask])-ctc->val)*ADJUSTSPEED; | |
194 } | |
195 | |
196 | |
197 static long waveform[8] = {WAVPREC,WAVPREC>>1,WAVPREC,(WAVPREC*3)>>2,0,0,(WAVPREC*5)>>2,WAVPREC<<1}; | |
198 static long wavemask[8] = {WAVPREC-1,WAVPREC-1,(WAVPREC>>1)-1,(WAVPREC>>1)-1,WAVPREC-1,((WAVPREC*3)>>2)-1,WAVPREC>>1,WAVPREC-1}; | |
199 static long wavestart[8] = {0,WAVPREC>>1,0,WAVPREC>>2,0,0,0,WAVPREC>>3}; | |
200 static float attackconst[4] = {1/2.82624,1/2.25280,1/1.88416,1/1.59744}; | |
201 static float decrelconst[4] = {1/39.28064,1/31.41608,1/26.17344,1/22.44608}; | |
202 void cellon (long i, long j, celltype *c, unsigned char iscarrier) | |
203 { | |
204 long frn, oct, toff; | |
205 float f; | |
206 | |
207 frn = ((((long)adlibreg[i+0xb0])&3)<<8) + (long)adlibreg[i+0xa0]; | |
208 oct = ((((long)adlibreg[i+0xb0])>>2)&7); | |
209 toff = (oct<<1) + ((frn>>9)&((frn>>8)|(((adlibreg[8]>>6)&1)^1))); | |
210 if (!(adlibreg[j+0x20]&16)) toff >>= 2; | |
211 | |
212 f = pow(2.0,(adlibreg[j+0x60]>>4)+(toff>>2)-1)*attackconst[toff&3]*recipsamp; | |
213 c->a0 = .0377*f; c->a1 = 10.73*f+1; c->a2 = -17.57*f; c->a3 = 7.42*f; | |
214 f = -7.4493*decrelconst[toff&3]*recipsamp; | |
215 c->decaymul = pow(2.0,f*pow(2.0,(adlibreg[j+0x60]&15)+(toff>>2))); | |
216 c->releasemul = pow(2.0,f*pow(2.0,(adlibreg[j+0x80]&15)+(toff>>2))); | |
217 c->wavemask = wavemask[adlibreg[j+0xe0]&7]; | |
218 c->waveform = &wavtable[waveform[adlibreg[j+0xe0]&7]]; | |
219 if (!(adlibreg[1]&0x20)) c->waveform = &wavtable[WAVPREC]; | |
220 c->t = wavestart[adlibreg[j+0xe0]&7]; | |
221 c->flags = adlibreg[j+0x20]; | |
222 c->cellfunc = docell0; | |
223 c->tinc = (float)(frn<<oct)*nfrqmul[adlibreg[j+0x20]&15]; | |
224 c->vol = pow(2.0,((float)(adlibreg[j+0x40]&63) + | |
225 (float)kslmul[adlibreg[j+0x40]>>6]*ksl[oct][frn>>6]) * -.125 - 14); | |
226 c->sustain = pow(2.0,(float)(adlibreg[j+0x80]>>4) * -.5); | |
227 if (!iscarrier) c->amp = 0; | |
228 c->mfb = pow(2.0,((adlibreg[i+0xc0]>>1)&7)+5)*(WAVPREC/2048.0)*MFBFACTOR; | |
229 if (!(adlibreg[i+0xc0]&14)) c->mfb = 0; | |
230 c->val = 0; | |
231 } | |
232 | |
233 //This function (and bug fix) written by Chris Moeller | |
234 void cellfreq (signed long i, signed long j, celltype *c) | |
235 { | |
236 long frn, oct; | |
237 | |
238 frn = ((((long)adlibreg[i+0xb0])&3)<<8) + (long)adlibreg[i+0xa0]; | |
239 oct = ((((long)adlibreg[i+0xb0])>>2)&7); | |
240 | |
241 c->tinc = (float)(frn<<oct)*nfrqmul[adlibreg[j+0x20]&15]; | |
242 c->vol = pow(2.0,((float)(adlibreg[j+0x40]&63) + | |
243 (float)kslmul[adlibreg[j+0x40]>>6]*ksl[oct][frn>>6]) * -.125 - 14); | |
244 } | |
245 | |
246 static long initfirstime = 0; | |
247 void adlibinit (long dasamplerate, long danumspeakers, long dabytespersample) | |
248 { | |
249 long i, j, frn, oct; | |
250 | |
251 memset((void *)adlibreg,0,sizeof(adlibreg)); | |
252 memset((void *)cell,0,sizeof(celltype)*MAXCELLS); | |
253 memset((void *)rbuf,0,sizeof(rbuf)); | |
254 rend = 0; odrumstat = 0; | |
255 | |
256 for(i=0;i<MAXCELLS;i++) | |
257 { | |
258 cell[i].cellfunc = docell4; | |
259 cell[i].amp = 0; | |
260 cell[i].vol = 0; | |
261 cell[i].t = 0; | |
262 cell[i].tinc = 0; | |
263 cell[i].wavemask = 0; | |
264 cell[i].waveform = &wavtable[WAVPREC]; | |
265 } | |
266 | |
267 numspeakers = danumspeakers; | |
268 bytespersample = dabytespersample; | |
269 | |
270 recipsamp = 1.0 / (float)dasamplerate; | |
271 for(i=15;i>=0;i--) nfrqmul[i] = frqmul[i]*recipsamp*FRQSCALE*(WAVPREC/2048.0); | |
272 | |
273 if (!initfirstime) | |
274 { | |
275 initfirstime = 1; | |
276 | |
277 for(i=0;i<(WAVPREC>>1);i++) | |
278 { | |
279 wavtable[i] = | |
280 wavtable[(i<<1) +WAVPREC] = (signed short)(16384*sin((float)((i<<1) )*PI*2/WAVPREC)); | |
281 wavtable[(i<<1)+1+WAVPREC] = (signed short)(16384*sin((float)((i<<1)+1)*PI*2/WAVPREC)); | |
282 } | |
283 for(i=0;i<(WAVPREC>>3);i++) | |
284 { | |
285 wavtable[i+(WAVPREC<<1)] = wavtable[i+(WAVPREC>>3)]-16384; | |
286 wavtable[i+((WAVPREC*17)>>3)] = wavtable[i+(WAVPREC>>2)]+16384; | |
287 } | |
288 | |
289 //[table in book]*8/3 | |
290 ksl[7][0] = 0; ksl[7][1] = 24; ksl[7][2] = 32; ksl[7][3] = 37; | |
291 ksl[7][4] = 40; ksl[7][5] = 43; ksl[7][6] = 45; ksl[7][7] = 47; | |
292 ksl[7][8] = 48; for(i=9;i<16;i++) ksl[7][i] = i+41; | |
293 for(j=6;j>=0;j--) | |
294 for(i=0;i<16;i++) | |
295 { | |
296 oct = (long)ksl[j+1][i]-8; if (oct < 0) oct = 0; | |
297 ksl[j][i] = (unsigned char)oct; | |
298 } | |
299 } | |
300 else | |
301 { | |
302 for(i=0;i<9;i++) | |
303 { | |
304 frn = ((((long)adlibreg[i+0xb0])&3)<<8) + (long)adlibreg[i+0xa0]; | |
305 oct = ((((long)adlibreg[i+0xb0])>>2)&7); | |
306 cell[i].tinc = (float)(frn<<oct)*nfrqmul[adlibreg[modulatorbase[i]+0x20]&15]; | |
307 } | |
308 } | |
309 } | |
310 | |
311 void adlib0 (long i, long v) | |
312 { | |
313 unsigned char tmp = adlibreg[i]; | |
314 adlibreg[i] = v; | |
315 | |
316 if (i == 0xbd) | |
317 { | |
318 if ((v&16) > (odrumstat&16)) //BassDrum | |
319 { | |
320 cellon(6,16,&cell[6],0); | |
321 cellon(6,19,&cell[15],1); | |
322 cell[15].vol *= 2; | |
323 } | |
324 if ((v&8) > (odrumstat&8)) //Snare | |
325 { | |
326 cellon(16,20,&cell[16],0); | |
327 cell[16].tinc *= 2*(nfrqmul[adlibreg[17+0x20]&15] / nfrqmul[adlibreg[20+0x20]&15]); | |
328 if (((adlibreg[20+0xe0]&7) >= 3) && ((adlibreg[20+0xe0]&7) <= 5)) cell[16].vol = 0; | |
329 cell[16].vol *= 2; | |
330 } | |
331 if ((v&4) > (odrumstat&4)) //TomTom | |
332 { | |
333 cellon(8,18,&cell[8],0); | |
334 cell[8].vol *= 2; | |
335 } | |
336 if ((v&2) > (odrumstat&2)) //Cymbal | |
337 { | |
338 cellon(17,21,&cell[17],0); | |
339 | |
340 cell[17].wavemask = wavemask[5]; | |
341 cell[17].waveform = &wavtable[waveform[5]]; | |
342 cell[17].tinc *= 16; cell[17].vol *= 2; | |
343 | |
344 //cell[17].waveform = &wavtable[WAVPREC]; cell[17].wavemask = 0; | |
345 //if (((adlibreg[21+0xe0]&7) == 0) || ((adlibreg[21+0xe0]&7) == 6)) | |
346 // cell[17].waveform = &wavtable[(WAVPREC*7)>>2]; | |
347 //if (((adlibreg[21+0xe0]&7) == 2) || ((adlibreg[21+0xe0]&7) == 3)) | |
348 // cell[17].waveform = &wavtable[(WAVPREC*5)>>2]; | |
349 } | |
350 if ((v&1) > (odrumstat&1)) //Hihat | |
351 { | |
352 cellon(7,17,&cell[7],0); | |
353 if (((adlibreg[17+0xe0]&7) == 1) || ((adlibreg[17+0xe0]&7) == 4) || | |
354 ((adlibreg[17+0xe0]&7) == 5) || ((adlibreg[17+0xe0]&7) == 7)) cell[7].vol = 0; | |
355 if ((adlibreg[17+0xe0]&7) == 6) { cell[7].wavemask = 0; cell[7].waveform = &wavtable[(WAVPREC*7)>>2]; } | |
356 } | |
357 | |
358 odrumstat = v; | |
359 } | |
360 else if (((unsigned)(i-0x40) < (unsigned)22) && ((i&7) < 6)) | |
361 { | |
362 if ((i&7) < 3) // Modulator | |
363 cellfreq(base2cell[i-0x40],i-0x40,&cell[base2cell[i-0x40]]); | |
364 else // Carrier | |
365 cellfreq(base2cell[i-0x40],i-0x40,&cell[base2cell[i-0x40]+9]); | |
366 } | |
367 else if ((unsigned)(i-0xa0) < (unsigned)9) | |
368 { | |
369 cellfreq(i-0xa0,modulatorbase[i-0xa0],&cell[i-0xa0]); | |
370 cellfreq(i-0xa0,modulatorbase[i-0xa0]+3,&cell[i-0xa0+9]); | |
371 } | |
372 else if ((unsigned)(i-0xb0) < (unsigned)9) | |
373 { | |
374 if ((v&32) > (tmp&32)) | |
375 { | |
376 cellon(i-0xb0,modulatorbase[i-0xb0],&cell[i-0xb0],0); | |
377 cellon(i-0xb0,modulatorbase[i-0xb0]+3,&cell[i-0xb0+9],1); | |
378 } | |
379 else if ((v&32) < (tmp&32)) | |
380 cell[i-0xb0].cellfunc = cell[i-0xb0+9].cellfunc = docell2; | |
381 cellfreq(i-0xb0,modulatorbase[i-0xb0],&cell[i-0xb0]); | |
382 cellfreq(i-0xb0,modulatorbase[i-0xb0]+3,&cell[i-0xb0+9]); | |
383 } | |
384 | |
385 //outdata(i,v); | |
386 } | |
387 | |
388 #ifdef USING_ASM | |
389 static long fpuasm; | |
390 static float fakeadd = 8388608.0+128.0; | |
391 static _inline void clipit8 (float f, long a) | |
392 { | |
393 _asm | |
394 { | |
395 mov edi, a | |
396 fld dword ptr f | |
397 fadd dword ptr fakeadd | |
398 fstp dword ptr fpuasm | |
399 mov eax, fpuasm | |
400 test eax, 0x007fff00 | |
401 jz short skipit | |
402 shr eax, 16 | |
403 xor eax, -1 | |
404 skipit: mov byte ptr [edi], al | |
405 } | |
406 } | |
407 | |
408 static _inline void clipit16 (float f, long a) | |
409 { | |
410 _asm | |
411 { | |
412 mov eax, a | |
413 fld dword ptr f | |
414 fist word ptr [eax] | |
415 cmp word ptr [eax], 0x8000 | |
416 jne short skipit2 | |
417 fst dword ptr [fpuasm] | |
418 cmp fpuasm, 0x80000000 | |
419 sbb word ptr [eax], 0 | |
420 skipit2: fstp st | |
421 } | |
422 } | |
423 #else | |
424 static void clipit8(float f,unsigned char *a) { | |
425 f/=256.0; | |
426 f+=128.0; | |
427 if (f>254.5) *a=255; | |
428 else if (f<0.5) *a=0; | |
429 else *a=f; | |
430 } | |
431 | |
432 static void clipit16(float f,short *a) { | |
433 if (f>32766.5) *a=32767; | |
434 else if (f<-32767.5) *a=-32768; | |
435 else *a=f; | |
436 } | |
437 #endif | |
438 | |
439 void adlibsetvolume(int i) { | |
440 AMPSCALE=i; | |
441 } | |
442 | |
443 void adlibgetsample (unsigned char *sndptr, long numbytes) | |
444 { | |
445 long i, j, k=0, ns, endsamples, rptrs, numsamples; | |
446 celltype *cptr; | |
447 float f; | |
448 short *sndptr2=(short *)sndptr; | |
449 | |
450 numsamples = (numbytes>>(numspeakers+bytespersample-2)); | |
451 | |
452 if (bytespersample == 1) f = AMPSCALE/256.0; else f = AMPSCALE; | |
453 if (numspeakers == 1) | |
454 { | |
455 nlvol[0] = lvol[0]*f; | |
456 for(i=0;i<9;i++) rptr[i] = &rbuf[0][0]; | |
457 rptrs = 1; | |
458 } | |
459 else | |
460 { | |
461 rptrs = 0; | |
462 for(i=0;i<9;i++) | |
463 { | |
464 if ((!i) || (lvol[i] != lvol[i-1]) || (rvol[i] != rvol[i-1]) || | |
465 (lplc[i] != lplc[i-1]) || (rplc[i] != rplc[i-1])) | |
466 { | |
467 nlvol[rptrs] = lvol[i]*f; | |
468 nrvol[rptrs] = rvol[i]*f; | |
469 nlplc[rptrs] = rend-min(max(lplc[i],0),FIFOSIZ); | |
470 nrplc[rptrs] = rend-min(max(rplc[i],0),FIFOSIZ); | |
471 rptrs++; | |
472 } | |
473 rptr[i] = &rbuf[rptrs-1][0]; | |
474 } | |
475 } | |
476 | |
477 | |
478 //CPU time used to be somewhat less when emulator was only mono! | |
479 // Because of no delay fifos! | |
480 | |
481 for(ns=0;ns<numsamples;ns+=endsamples) | |
482 { | |
483 endsamples = min(FIFOSIZ*2-rend,FIFOSIZ); | |
484 endsamples = min(endsamples,numsamples-ns); | |
485 | |
486 for(i=0;i<9;i++) | |
487 nrptr[i] = &rptr[i][rend]; | |
488 for(i=0;i<rptrs;i++) | |
489 memset((void *)&rbuf[i][rend],0,endsamples*sizeof(float)); | |
490 | |
491 if (adlibreg[0xbd]&0x20) | |
492 { | |
493 //BassDrum (j=6) | |
494 if (cell[15].cellfunc != docell4) | |
495 { | |
496 if (adlibreg[0xc6]&1) | |
497 { | |
498 for(i=0;i<endsamples;i++) | |
499 { | |
500 (cell[15].cellfunc)((void *)&cell[15],0.0); | |
501 nrptr[6][i] += cell[15].val; | |
502 } | |
503 } | |
504 else | |
505 { | |
506 for(i=0;i<endsamples;i++) | |
507 { | |
508 (cell[6].cellfunc)((void *)&cell[6],cell[6].val*cell[6].mfb); | |
509 (cell[15].cellfunc)((void *)&cell[15],cell[6].val*WAVPREC*MODFACTOR); | |
510 nrptr[6][i] += cell[15].val; | |
511 } | |
512 } | |
513 } | |
514 | |
515 //Snare/Hihat (j=7), Cymbal/TomTom (j=8) | |
516 if ((cell[7].cellfunc != docell4) || (cell[8].cellfunc != docell4) || (cell[16].cellfunc != docell4) || (cell[17].cellfunc != docell4)) | |
517 { | |
518 for(i=0;i<endsamples;i++) | |
519 { | |
520 k = k*1664525+1013904223; | |
521 (cell[16].cellfunc)((void *)&cell[16],k&((WAVPREC>>1)-1)); //Snare | |
522 (cell[7].cellfunc)((void *)&cell[7],k&(WAVPREC-1)); //Hihat | |
523 (cell[17].cellfunc)((void *)&cell[17],k&((WAVPREC>>3)-1)); //Cymbal | |
524 (cell[8].cellfunc)((void *)&cell[8],0.0); //TomTom | |
525 nrptr[7][i] += cell[7].val + cell[16].val; | |
526 nrptr[8][i] += cell[8].val + cell[17].val; | |
527 } | |
528 } | |
529 } | |
530 for(j=9-1;j>=0;j--) | |
531 { | |
532 if ((adlibreg[0xbd]&0x20) && (j >= 6) && (j < 9)) continue; | |
533 | |
534 cptr = &cell[j]; k = j; | |
535 if (adlibreg[0xc0+k]&1) | |
536 { | |
537 if ((cptr[9].cellfunc == docell4) && (cptr->cellfunc == docell4)) continue; | |
538 for(i=0;i<endsamples;i++) | |
539 { | |
540 (cptr->cellfunc)((void *)cptr,cptr->val*cptr->mfb); | |
541 (cptr->cellfunc)((void *)&cptr[9],0); | |
542 nrptr[j][i] += cptr[9].val + cptr->val; | |
543 } | |
544 } | |
545 else | |
546 { | |
547 if (cptr[9].cellfunc == docell4) continue; | |
548 for(i=0;i<endsamples;i++) | |
549 { | |
550 (cptr->cellfunc)((void *)cptr,cptr->val*cptr->mfb); | |
551 (cptr[9].cellfunc)((void *)&cptr[9],cptr->val*WAVPREC*MODFACTOR); | |
552 nrptr[j][i] += cptr[9].val; | |
553 } | |
554 } | |
555 } | |
556 | |
557 if (numspeakers == 1) | |
558 { | |
559 if (bytespersample == 1) | |
560 { | |
561 for(i=endsamples-1;i>=0;i--) | |
562 clipit8(nrptr[0][i]*nlvol[0],sndptr+1); | |
563 } | |
564 else | |
565 { | |
566 for(i=endsamples-1;i>=0;i--) | |
567 clipit16(nrptr[0][i]*nlvol[0],sndptr2+i); | |
568 } | |
569 } | |
570 else | |
571 { | |
572 memset((void *)snd,0,endsamples*sizeof(float)*2); | |
573 for(j=0;j<rptrs;j++) | |
574 { | |
575 for(i=0;i<endsamples;i++) | |
576 { | |
577 snd[(i<<1) ] += rbuf[j][(nlplc[j]+i)&(FIFOSIZ*2-1)]*nlvol[j]; | |
578 snd[(i<<1)+1] += rbuf[j][(nrplc[j]+i)&(FIFOSIZ*2-1)]*nrvol[j]; | |
579 } | |
580 nlplc[j] += endsamples; | |
581 nrplc[j] += endsamples; | |
582 } | |
583 | |
584 if (bytespersample == 1) | |
585 { | |
586 for(i=(endsamples<<1)-1;i>=0;i--) | |
587 clipit8(snd[i],sndptr+i); | |
588 } | |
589 else | |
590 { | |
591 for(i=(endsamples<<1)-1;i>=0;i--) | |
592 clipit16(snd[i],sndptr2+i); | |
593 } | |
594 } | |
595 | |
596 sndptr = sndptr+(numspeakers*endsamples); | |
597 sndptr2 = sndptr2+(numspeakers*endsamples); | |
598 rend = ((rend+endsamples)&(FIFOSIZ*2-1)); | |
599 } | |
600 } |