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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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
ftol(float f,long * a)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
ftol(float f,long * a)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!
docell4(void * c,float modulator)132 void docell4 (void *c, float modulator) { }
docell3(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 }
docell2(void * c,float modulator)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 }
docell1(void * c,float modulator)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 }
docell0(void * c,float modulator)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};
cellon(long i,long j,celltype * c,unsigned char iscarrier)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
cellfreq(signed long i,signed long j,celltype * c)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;
adlibinit(long dasamplerate,long danumspeakers,long dabytespersample)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 
adlib0(long i,long v)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;
clipit8(float f,long a)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 
clipit16(float f,long a)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
clipit8(float f,unsigned char * a)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 
clipit16(float f,short * a)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 
adlibsetvolume(int i)439 void adlibsetvolume(int i) {
440     AMPSCALE=i;
441 }
442 
adlibgetsample(unsigned char * sndptr,long numbytes)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 }
601