mirror of
https://github.com/emu-russia/pureikyubu.git
synced 2025-04-02 10:42:15 -04:00
72 lines
1.5 KiB
C++
72 lines
1.5 KiB
C++
// DSP PCM/ADPCM Decoder
|
|
|
|
#include "pch.h"
|
|
|
|
using namespace Debug;
|
|
|
|
#define my_max(a,b) (((a) > (b)) ? (a) : (b))
|
|
#define my_min(a,b) (((a) < (b)) ? (a) : (b))
|
|
|
|
namespace DSP
|
|
{
|
|
uint16_t Dsp16::DecodeAdpcm(uint16_t in)
|
|
{
|
|
int64_t yn = 0;
|
|
int64_t out = 0;
|
|
int outputMode = (Accel.Fmt >> 4) & 3;
|
|
|
|
switch ((Accel.Fmt >> 2) & 3)
|
|
{
|
|
case 0:
|
|
{
|
|
int pred = (Accel.AdpcmPds >> 4) & 7;
|
|
int scale = Accel.AdpcmPds & 0xf;
|
|
int16_t gain = 1 << scale;
|
|
|
|
if (scale > 0xc)
|
|
scale = 0xc;
|
|
|
|
int16_t xn = in << 11;
|
|
if (xn & 0x4000)
|
|
xn |= 0x8000;
|
|
|
|
yn = (int64_t)(int32_t)(int16_t)Accel.AdpcmYn1 * (int64_t)(int32_t)(int16_t)Accel.AdpcmCoef[2 * pred]
|
|
+ (int64_t)(int32_t)(int16_t)Accel.AdpcmYn2 * (int64_t)(int32_t)(int16_t)Accel.AdpcmCoef[2 * pred + 1] +
|
|
(int64_t)(int32_t)xn * gain;
|
|
|
|
Accel.AdpcmYn2 = Accel.AdpcmYn1;
|
|
Accel.AdpcmYn1 = (uint16_t)(yn >> 11);
|
|
break;
|
|
}
|
|
|
|
case 1:
|
|
yn = (int64_t)(int32_t)((int16_t)(in << 8)) * Accel.AdpcmGan;
|
|
break;
|
|
|
|
case 2:
|
|
yn = (int64_t)(int32_t)(int16_t)in * Accel.AdpcmGan;
|
|
break;
|
|
}
|
|
|
|
switch (outputMode)
|
|
{
|
|
case 0:
|
|
out = yn >> 11;
|
|
out = my_max(-0x8000, my_min(out, 0x7FFF));
|
|
break;
|
|
case 1:
|
|
out = yn & 0xffff;
|
|
break;
|
|
case 2:
|
|
out = (yn >> 16);
|
|
break;
|
|
case 3:
|
|
Halt("DSP: Unsupported Decoder output mode\n");
|
|
break;
|
|
}
|
|
|
|
//Report(Channel::DSP, "0x%08X = 0x%04X\n", (Accel.CurrAddress.addr & 0x07FF'FFFF) - 1, (uint16_t)out);
|
|
|
|
return (uint16_t)out;
|
|
}
|
|
}
|