|
Joined: Feb 2008
Posts: 107
Senior Member
|
Senior Member
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/000eky4bEDIT: 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
Last edited by Deunan Knute; 07/18/08 12:36 PM.
|
|
|
|
Joined: Feb 2008
Posts: 107
Senior Member
|
Senior Member
Joined: Feb 2008
Posts: 107 |
Bingo. Update aica.c with this modified decoder and all DSP problems will go away
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
Very Senior Member
|
OP
Very Senior Member
Joined: Mar 2001
Posts: 17,234 Likes: 260 |
Nice
|
|
|
|
Joined: May 2008
Posts: 2
Member
|
Member
Joined: May 2008
Posts: 2 |
|
|
|
|
Joined: Mar 2001
Posts: 17,234 Likes: 260
Very Senior Member
|
OP
Very Senior Member
Joined: Mar 2001
Posts: 17,234 Likes: 260 |
Now there's a cart-ahead-of-the-horse moment
|
|
|
|
Joined: Feb 2008
Posts: 107
Senior Member
|
Senior Member
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" Don't you just love rediscovering the wheel again...
|
|
|
|
Joined: Mar 2001
Posts: 17,234 Likes: 260
Very Senior Member
|
OP
Very Senior Member
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
Member
|
Member
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.
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
Very Senior Member
|
OP
Very Senior Member
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
Very Senior Member
|
OP
Very Senior Member
Joined: Mar 2001
Posts: 17,234 Likes: 260 |
An updated SDK has been posted. Thanks everyone.
|
|
|
1 members (1 invisible),
210
guests, and
0
robots. |
Key:
Admin,
Global Mod,
Mod
|
|
Forums9
Topics9,328
Posts122,128
Members5,074
|
Most Online1,283 Dec 21st, 2022
|
|
These forums are sponsored by Superior Solitaire, an ad-free card game collection for macOS and iOS. Download it today!
|
|
|
|