Previous Thread
Next Thread
Print Thread
Page 29 of 55 1 2 27 28 29 30 31 54 55
Joined: Feb 2008
Posts: 107
D
Senior Member
Offline
Senior Member
D
Joined: Feb 2008
Posts: 107
Going back to that DSP issue - now, after a few more hours of tests, I'm pretty much convinced this isn't about DSP but rather ADPCM.
See, the DSP works just fine with 8- and 16-bit samples being input:
- it works for Saturn tunes
- it breaks only certain Dreamcast tunes
- hissing/clipping only occurs when ADPCM samples are being routed through DSP

All DSP does (in short) is take the input wave, modify it a bit and add it back time-shifted. However if the output saturates and stays like that it will distort or even mute all sounds during final mixing pass. Non-ADPCM samples eventually integrate to zero, so the adder never overflows. But ADPCM samples seem to have a bias and tend to dive into negative numbers and stay there (loop jumps recover a bit, but not completly). And it's exactly what upsets the DSP - you can test that by inverting the sign of ADPCM samples being written to MIXS. It will create exactly the same output wave but mirrored around time axis. Reducing ADPCM dynamic range (from -/+ 32768 to let's say 24000) helps, but you can still see the output swinging rather then being symmetric.

I'm trying to figure out what's wrong with the decoder and why does it introduce the bias, but not much luck so far. Maybe I'm missing something obvious?
kingshriek, if you have some time could you please look into that as well? All you need to do is extract some raw ADPCM data and convert it to WAV, then view it under some sound editor like Audacity. You should see the problem right away. You can use soa-367-04-00.minidsf as it starts with ADPCM and exibits the symptoms.
I can provide you with longer streams if you want - dialog lines from Soul Reaver. It's very obvious on those:
http://pics.livejournal.com/dknute/pic/000eky4b

EDIT:
Well, I haven't found this to be a problem in a while... anyway - shifting is the culprit. -1 >> 3 is still -1, whereas -1 / 8 is zero. It's consistent with the fact that the bias is towards negative values. I'll see if +1 trick will work and test it further and get back to you smile

Last edited by Deunan Knute; 07/18/08 12:36 PM.
Joined: Feb 2008
Posts: 107
D
Senior Member
Offline
Senior Member
D
Joined: Feb 2008
Posts: 107
Bingo. Update aica.c with this modified decoder and all DSP problems will go away smile

Code
signed short inline DecodeADPCM(int *PrevSignal, unsigned char Delta, int *PrevQuant)
{
	int x = *PrevQuant * quant_mul [Delta & 15];
        x = *PrevSignal + ((int)(x + ((UINT32)x >> 29)) >> 3);
	*PrevSignal=ICLIP16(x);
	*PrevQuant=(*PrevQuant*TableQuant[Delta&7])>>ADPCMSHIFT;
	*PrevQuant=(*PrevQuant<0x7f)?0x7f:((*PrevQuant>0x6000)?0x6000:*PrevQuant);
	return *PrevSignal;
}


Joined: Mar 2001
Posts: 17,234
Likes: 260
R
Very Senior Member
OP Online Content
Very Senior Member
R
Joined: Mar 2001
Posts: 17,234
Likes: 260
Nice smile

Joined: May 2008
Posts: 2
K
Member
Offline
Member
K
Joined: May 2008
Posts: 2
Great! in_aodsf updated.

http://foobar2000.xrea.jp/up/

Joined: Mar 2001
Posts: 17,234
Likes: 260
R
Very Senior Member
OP Online Content
Very Senior Member
R
Joined: Mar 2001
Posts: 17,234
Likes: 260
Now there's a cart-ahead-of-the-horse moment wink

Joined: Feb 2008
Posts: 107
D
Senior Member
Offline
Senior Member
D
Joined: Feb 2008
Posts: 107
You know what's funny? Since this ADPCM decoder originates in Yamaha YMZ280B driver I peeked into MAME sources today, being sure it has the same bug. And it doesn't, Aaron Giles coded it with "/8" and not ">>3" smile
Don't you just love rediscovering the wheel again...

Joined: Mar 2001
Posts: 17,234
Likes: 260
R
Very Senior Member
OP Online Content
Very Senior Member
R
Joined: Mar 2001
Posts: 17,234
Likes: 260
Premature optimization, all evil, etc.

Plus on Northwood-core Pentium 4s the /8 is faster than the >>3 :-)

Joined: Jul 2008
Posts: 5
A
Member
Offline
Member
A
Joined: Jul 2008
Posts: 5
Interpolation algorithm uses neighbor sample - so we can optimize
ADPCM channel process to use last decoded values. We can rid of "nxt*" variables and second adpcm decode cycles (will speed up ADPCM a little bit). Following diff against aosdk 1.4.1 shows my assumption.

Code
diff -Nru aosdk_base/eng_dsf/aica.c aosdk/eng_dsf/aica.c
--- aosdk_base/eng_dsf/aica.c	2008-03-07 21:21:32.000000000 +0300
+++ aosdk/eng_dsf/aica.c	2008-07-27 23:05:18.596041500 +0400
@@ -125,12 +125,10 @@
 	struct _LFO ALFO;		//Amplitude LFO
 	int slot;
 	int cur_sample;       //current ADPCM sample
-	int nxt_sample;       //next ADPCM sample
 	int cur_quant;        //current ADPCM step
-	int nxt_quant;        //next ADPCM step
-	int curstep, nxtstep;
+	int curstep;
 	int cur_lpquant, cur_lpsample, cur_lpstep;
-	UINT8 *adbase, *nxtbase, *adlpbase;
+	UINT8 *adbase, *adlpbase;
 	UINT8 mslc;			// monitored?
 };
 
@@ -431,10 +429,9 @@
 		UINT8 *base;
 		UINT32 curstep, steps_to_go;
 
-		slot->curstep = slot->nxtstep = 0;
-		slot->adbase = slot->nxtbase = (unsigned char *) (AICA->AICARAM+((SA(slot))&0x7fffff));
+		slot->curstep = 0;
+		slot->adbase = (unsigned char *) (AICA->AICARAM+((SA(slot))&0x7fffff));
 		InitADPCM(&(slot->cur_sample), &(slot->cur_quant));
-		InitADPCM(&(slot->nxt_sample), &(slot->nxt_quant));
 		InitADPCM(&(slot->cur_lpsample), &(slot->cur_lpquant));
 
 		// walk to the ADPCM state at LSA
@@ -956,7 +953,6 @@
 	UINT32 addr1,addr2,addr_select;                                   // current and next sample addresses
 	UINT32 *addr[2]      = {&addr1, &addr2};                          // used for linear interpolation
 	UINT32 *slot_addr[2] = {&(slot->cur_addr), &(slot->nxt_addr)};    //
-	int    *adpcm_sample[2] = {&(slot->cur_sample), &(slot->nxt_sample)};
 
 	if(SSCTL(slot)!=0)	//no FM or noise yet
 		return 0;
@@ -1007,12 +1003,16 @@
 		UINT8 *p1=(unsigned char *) (AICA->AICARAM+((SA(slot)+(addr1>>1))&0x7fffff));
 		UINT8 *p2=(unsigned char *) (AICA->AICARAM+((SA(slot)+(addr2>>1))&0x7fffff));
 		INT32 s;
+		int cur_sample;       //current ADPCM sample
+		int nxt_sample;       //next ADPCM sample
 		INT32 fpart=slot->cur_addr&((1<<SHIFT)-1);
-		UINT32 steps_to_go = addr1, curstep = slot->curstep;
+		UINT32 steps_to_go = addr2, curstep = slot->curstep;
 
 		if (slot->adbase)
 		{
-			// seek to the current sample
+			cur_sample = slot->cur_sample; // may already contains current decoded sample 
+
+			// seek to the interpolation sample
 			while (curstep < steps_to_go)
 			{
 				int shift1, delta1;
@@ -1024,33 +1024,15 @@
 				{
 					base++;
 				}
+				if (curstep == addr1)
+					cur_sample = slot->cur_sample;
 			}
+			nxt_sample = slot->cur_sample;
 
 			slot->adbase = base;
 			slot->curstep = curstep;
 
-			base = slot->nxtbase;
-			curstep = slot->nxtstep;
-			steps_to_go = addr2;
-
-			// seek to the interpolation sample
-			while (curstep < steps_to_go)
-			{
-				int shift1, delta1;
-				shift1 = 4*((curstep&1));
-				delta1 = (*base>>shift1)&0xf;
-				DecodeADPCM(&(slot->nxt_sample),delta1,&(slot->nxt_quant));
-				curstep++;
-				if (!(curstep & 1))
-				{
-					base++;
-				}
-			}
-
-			slot->nxtbase = base;
-			slot->nxtstep = curstep;
-
-			s=(int) slot->cur_sample*((1<<SHIFT)-fpart)+(int) slot->nxt_sample*fpart;
+			s=(int)cur_sample*((1<<SHIFT)-fpart)+(int)nxt_sample*fpart;
 		}
 		else
 		{
@@ -1093,7 +1075,7 @@
 				rem_addr = *slot_addr[addr_select] - (LEA(slot)<<SHIFT);
 				*slot_addr[addr_select]=(LSA(slot)<<SHIFT) + rem_addr;
 
-				if(PCMS(slot)>=2 && addr_select==0)
+				if(PCMS(slot)>=2)
 				{
 					// restore the state @ LSA - the sampler will naturally walk to (LSA + remainder)
 					slot->adbase = &AICA->AICARAM[SA(slot)+(LSA(slot)/2)];
@@ -1106,16 +1088,6 @@
 
 //					printf("Looping: slot_addr %x LSA %x LEA %x step %x base %x\n", *slot_addr[addr_select]>>SHIFT, LSA(slot), LEA(slot), slot->curstep, slot->adbase);
 				}
-				else if(PCMS(slot)>=2 && addr_select==1)
-				{
-					slot->nxtbase = &AICA->AICARAM[SA(slot)+(LSA(slot)/2)];
-					slot->nxtstep = LSA(slot);
-					if (PCMS(slot) == 2)
-					{
-						slot->nxt_sample = slot->cur_lpsample;
-						slot->nxt_quant = slot->cur_lpquant;
-					}
-				}
 			}
 			break;
 		}


Last edited by ajax16384; 07/27/08 07:06 PM.
Joined: Mar 2001
Posts: 17,234
Likes: 260
R
Very Senior Member
OP Online Content
Very Senior Member
R
Joined: Mar 2001
Posts: 17,234
Likes: 260
DK: Just got back to my computer after a ton of vacation (had a laptop but no source to test out). The sound quality improvement from that change is amazing and the samples no longer "float" with a DC offset :-)

Ajax: Thanks. I don't see much real-world CPU improvement but the code cleanup is well worth it.

Joined: Mar 2001
Posts: 17,234
Likes: 260
R
Very Senior Member
OP Online Content
Very Senior Member
R
Joined: Mar 2001
Posts: 17,234
Likes: 260
An updated SDK has been posted. Thanks everyone.

Page 29 of 55 1 2 27 28 29 30 31 54 55

Moderated by  R. Belmont, Richard Bannister 

Link Copied to Clipboard
Who's Online Now
1 members (1 invisible), 210 guests, and 0 robots.
Key: Admin, Global Mod, Mod
ShoutChat
Comment Guidelines: Do post respectful and insightful comments. Don't flame, hate, spam.
Forum Statistics
Forums9
Topics9,328
Posts122,128
Members5,074
Most Online1,283
Dec 21st, 2022
Our Sponsor
These forums are sponsored by Superior Solitaire, an ad-free card game collection for macOS and iOS. Download it today!

Superior Solitaire
Forum hosted by www.retrogamesformac.com