With the SCSP EG in pretty good shape, I have turned to fix some of the remaining issues in the DSP. The main fix I put in was support for the input effect mixer which fixes many of the dry/wet balance issues. I put in floating point support as well for ring-buffer read/writes. This fixes popping issues when the DSP initially reads from the ring-buffer, which most driver versions initialize to 0x6000 (the DSP floating-point representation of zero).

I also noticed that the EG_Update() function can possibly return a negative value in the DECAY1 state, which would potentially cause a segfault when later used as an index for table lookup (and if it doesn't, the output from it would probably sound very bad). I fixed this by adding a clamp to zero in the DECAY1 state.

I also took a brief look at LFO code and noticed that the saw PLFO was mistakenly set to a triangle waveform, so I fixed that too.

Patch against AO SDK 1.1.2:

Code:
diff -Nru aosdk_base/eng_ssf/scsp.c aosdk/eng_ssf/scsp.c
--- aosdk_base/eng_ssf/scsp.c	2007-12-02 10:27:02.000000000 -0800
+++ aosdk/eng_ssf/scsp.c	2007-12-09 04:09:59.000000000 -0800
@@ -351,6 +351,8 @@
 			break;
 		case DECAY1:
 			slot->EG.volume-=slot->EG.D1R;
+			if(slot->EG.volume<=0)
+				slot->EG.volume=0;
 			if(slot->EG.volume>>(EG_SHIFT+5)<slot->EG.DL)
 				slot->EG.state=DECAY2;
 			break;
@@ -1222,12 +1224,13 @@
 				++SCSP->BUFPTR;
 				SCSP->BUFPTR&=63;
 #ifdef USEDSP
-				SCSPDSP_SetSample(&SCSP->DSP,sample>>SHIFT,ISEL(slot),IMXL(slot));
+				Enc=((TL(slot))<<0x0)|((IMXL(slot))<<0xd);
+				SCSPDSP_SetSample(&SCSP->DSP,(sample*SCSP->LPANTABLE[Enc])>>SHIFT,ISEL(slot),IMXL(slot));
 #endif
 				Enc=((TL(slot))<<0x0)|((DIPAN(slot))<<0x8)|((DISDL(slot))<<0xd);
 				{
-					smpl+=(sample*SCSP->LPANTABLE[Enc])>>(SHIFT-1);
-					smpr+=(sample*SCSP->RPANTABLE[Enc])>>(SHIFT-1);
+					smpl+=(sample*SCSP->LPANTABLE[Enc])>>SHIFT;
+					smpr+=(sample*SCSP->RPANTABLE[Enc])>>SHIFT;
 				}
 			}
 
@@ -1240,14 +1243,14 @@
 			struct _SLOT *slot=SCSP->Slots+i;
 			if(EFSDL(slot))
 			{
-				unsigned short Enc=(TL(slot))|((EFPAN(slot))<<0x8)|((EFSDL(slot))<<0xd);
-				smpl+=(SCSP->DSP.EFREG[i]*SCSP->LPANTABLE[Enc])>>(SHIFT-4);
-				smpr+=(SCSP->DSP.EFREG[i]*SCSP->RPANTABLE[Enc])>>(SHIFT-4);
+				unsigned short Enc=((EFPAN(slot))<<0x8)|((EFSDL(slot))<<0xd);
+				smpl+=(SCSP->DSP.EFREG[i]*SCSP->LPANTABLE[Enc])>>SHIFT;
+				smpr+=(SCSP->DSP.EFREG[i]*SCSP->RPANTABLE[Enc])>>SHIFT;
 			}
 		}
 
-		*bufl++ = ICLIP16(smpl>>3);
-		*bufr++ = ICLIP16(smpr>>3);
+		*bufl++ = ICLIP16(smpl>>2);
+		*bufr++ = ICLIP16(smpr>>2);
 
 		SCSP_TimersAddTicks(SCSP, 1);
 		CheckPendingIRQ(SCSP);
diff -Nru aosdk_base/eng_ssf/scspdsp.c aosdk/eng_ssf/scspdsp.c
--- aosdk_base/eng_ssf/scspdsp.c	2007-10-26 19:43:40.000000000 -0700
+++ aosdk/eng_ssf/scspdsp.c	2007-12-09 03:58:38.000000000 -0800
@@ -7,19 +7,49 @@
 
 static UINT16 PACK(INT32 val)
 {
-	//cut to 16 bits
-	INT32 f=((UINT32 ) val)>>8;
-	return f;
+	UINT32 temp;
+	int sign,exponent,k;
+
+	sign = (val >> 23) & 0x1;
+	temp = (val ^ (val << 1)) & 0xFFFFFF;
+	exponent = 0;
+	for (k=0; k<12; k++)
+	{
+		if (temp & 0x800000)
+			break;
+		temp <<= 1;
+		exponent += 1;
+	}
+	if (exponent < 12)
+		val = (val << exponent) & 0x3FFFFF;
+	else
+		val <<= 11;
+	val >>= 11;
+	val |= sign << 15;
+	val |= exponent << 11;
+
+	return (UINT16)val;
 }
 
 static INT32 UNPACK(UINT16 val)
 {
-	INT32 r=val<<8;
-	r<<=8;
-	r>>=8;
-	//if(r&0x00800000)
-	//  r|=0xFF000000;
-	return r;
+	int sign,exponent,mantissa;
+	INT32 uval;
+
+	sign = (val >> 15) & 0x1;
+	exponent = (val >> 11) & 0xF;
+	mantissa = val & 0x7FF;
+	uval = mantissa << 11;
+	if (exponent > 11)
+		exponent = 11;
+	else
+		uval |= (sign ^ 1) << 22;
+	uval |= sign << 23;
+	uval <<= 8;
+	uval >>= 8;
+	uval >>= exponent;
+
+	return uval;
 }
 
 void SCSPDSP_Init(struct _SCSPDSP *DSP)
@@ -126,7 +156,7 @@
 		if(IRA<=0x1f)
 			INPUTS=DSP->MEMS[IRA];
 		else if(IRA<=0x2F)
-			INPUTS=DSP->MIXS[IRA-0x20]<<8;	//MIXS is 16 bit
+			INPUTS=DSP->MIXS[IRA-0x20]<<4;	//MIXS is 20 bit
 		else if(IRA<=0x31)
 			INPUTS=0;
 
@@ -298,7 +328,7 @@
 void SCSPDSP_SetSample(struct _SCSPDSP *DSP,INT32 sample,int SEL,int MXL)
 {
 	//DSP->MIXS[SEL]+=sample<<(MXL+1)/*7*/;
-	DSP->MIXS[SEL]+=sample<<7;
+	DSP->MIXS[SEL]+=sample;
 //  if(MXL)
 //      int a=1;
 }
diff -Nru aosdk_base/eng_ssf/scsplfo.c aosdk/eng_ssf/scsplfo.c
--- aosdk_base/eng_ssf/scsplfo.c	2007-10-26 19:43:36.000000000 -0700
+++ aosdk/eng_ssf/scsplfo.c	2007-12-08 07:01:00.000000000 -0800
@@ -47,7 +47,7 @@
 		if(i<128)
 			p=i;
 		else
-			p=255-i;    
+			p=i-256;    
 		ALFO_SAW[i]=a;
 		PLFO_SAW[i]=p;
 	


Changes:
- Added effect in mixer
- Added DSP floating-point support
- Added bounds check to the DECAY1 EG output
- Fixed the saw PLFO waveform