aica: save quantization and last sample when entering loop for normal adpcm

This commit is contained in:
Flyinghead 2019-09-06 13:53:01 +02:00
parent 7287b3816b
commit d1c3d31259
1 changed files with 48 additions and 17 deletions

View File

@ -290,11 +290,18 @@ struct ChannelEx
{
//used in adpcm decoding
s32 last_quant;
//SampleType prev_sample;
// Saved quantization and previous sample used in PCMS mode 2 (yamaha ADPCM)
s32 loopstart_quant;
SampleType loopstart_prev_sample;
bool in_loop;
void Reset(ChannelEx* ch)
{
last_quant=127;
//prev_sample=0;
loopstart_quant = 0;
loopstart_prev_sample = 0;
in_loop = false;
ch->s0=0;
}
} adpcm;
@ -773,7 +780,9 @@ __forceinline void StepDecodeSample(ChannelEx* ch,u32 CA)
s16* sptr16=(s16*)ch->SA;
s8* sptr8=(s8*)sptr16;
u8* uptr8=(u8*)sptr16;
u32 next_addr = CA + 1 >= ch->loop.LEA ? ch->loop.LSA : CA + 1;
u32 next_addr = CA + 1;
if (next_addr >= ch->loop.LEA)
next_addr = ch->loop.LSA;
SampleType s0,s1;
switch(PCMS)
@ -807,24 +816,44 @@ __forceinline void StepDecodeSample(ChannelEx* ch,u32 CA)
case 2:
case 3:
{
//u32 offs=CA;
u8 ad1 = uptr8[CA >> 1];
u8 ad2 = uptr8[next_addr >> 1];
u8 sf=(CA&1)*4;
ad1>>=sf;
ad2>>=4-sf;
ad1&=0xF;
ad2&=0xF;
ad1 >>= (CA & 1) * 4;
ad2 >>= (next_addr & 1) * 4;
s32 q=ch->adpcm.last_quant;
s0=DecodeADPCM(ad1,ch->s0,q);
ch->adpcm.last_quant=q;
ad1 &= 0xF;
ad2 &= 0xF;
s32 q = ch->adpcm.last_quant;
if (PCMS == 2 && CA == ch->loop.LSA)
{
if (!ch->adpcm.in_loop)
{
ch->adpcm.in_loop = true;
ch->adpcm.loopstart_quant = q;
ch->adpcm.loopstart_prev_sample = ch->s0;
}
else
{
q = ch->adpcm.loopstart_quant;
ch->s0 = ch->adpcm.loopstart_prev_sample;
}
}
s0 = DecodeADPCM(ad1, ch->s0, q);
ch->adpcm.last_quant = q;
if (last)
s1=DecodeADPCM(ad2,s0,q);
{
SampleType prev = s0;
if (PCMS == 2 && next_addr == ch->loop.LSA && ch->adpcm.in_loop)
{
q = ch->adpcm.loopstart_quant;
prev = ch->adpcm.loopstart_prev_sample;
}
s1 = DecodeADPCM(ad2, prev, q);
}
else
s1=0;
s1 = 0;
}
break;
}
@ -855,13 +884,13 @@ void StreamStep(ChannelEx* ch)
u32 ca_t=CA;
if (PCMS==3)
ca_t&=~3; //adpcm "stream" mode needs this ...
ca_t&=~3; // in adpcm "stream" mode, LEA and LSA are supposed to be 4-sample aligned
// but some games don't respect this rule
if (LPSLNK)
{
if ((ch->AEG.state==EG_Attack) && (CA>=ch->loop.LSA))
{
step_printf("[%d]LPSLNK : Switching to EG_Decay1 %X", ch->ChannelNumber, ch->AEG.GetValue());
ch->SetAegState(EG_Decay1);
}
@ -873,6 +902,8 @@ void StreamStep(ChannelEx* ch)
CA = ch->loop.LSA;
if (LPCTL == 0)
ch->disable();
else
step_printf("[%d]LPCTL : Looping LSA %x LEA %x", ch->ChannelNumber, ch->loop.LSA, ch->loop.LEA);
}
ch->CA=CA;