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 }