aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Audio/Adpcm/AdpcmDecoder.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-07-14 23:57:41 -0300
committerGitHub <noreply@github.com>2018-07-14 23:57:41 -0300
commit98c6ceede564eda4aed528e51219a9b0d6bea1c4 (patch)
tree2fabe99e761098b6cafb49fb0ab4e90f6f9ef106 /Ryujinx.Audio/Adpcm/AdpcmDecoder.cs
parentbe31f5b46d16f0f8730d9a9ec71f938eee97524a (diff)
Audio Renderer improvements (#210)
* Partial voice implementation on audio renderer * Implemented audren resampler (based on original impl) * Fix BiquadFilter struct * Pause audio playback on last stream buffer * Split audren/audout files into separate folders, some minor cleanup * Use AudioRendererParameter on GetWorkBufferSize aswell * Bump audren version to REV4, name a few things, increase sample buffer size * Remove useless new lines
Diffstat (limited to 'Ryujinx.Audio/Adpcm/AdpcmDecoder.cs')
-rw-r--r--Ryujinx.Audio/Adpcm/AdpcmDecoder.cs91
1 files changed, 91 insertions, 0 deletions
diff --git a/Ryujinx.Audio/Adpcm/AdpcmDecoder.cs b/Ryujinx.Audio/Adpcm/AdpcmDecoder.cs
new file mode 100644
index 00000000..24455b41
--- /dev/null
+++ b/Ryujinx.Audio/Adpcm/AdpcmDecoder.cs
@@ -0,0 +1,91 @@
+namespace Ryujinx.Audio.Adpcm
+{
+ public static class AdpcmDecoder
+ {
+ private const int SamplesPerFrame = 14;
+ private const int BytesPerFrame = 8;
+
+ public static int[] Decode(byte[] Buffer, AdpcmDecoderContext Context)
+ {
+ int Samples = GetSamplesCountFromSize(Buffer.Length);
+
+ int[] Pcm = new int[Samples * 2];
+
+ short History0 = Context.History0;
+ short History1 = Context.History1;
+
+ int InputOffset = 0;
+ int OutputOffset = 0;
+
+ while (InputOffset < Buffer.Length)
+ {
+ byte Header = Buffer[InputOffset++];
+
+ int Scale = 0x800 << (Header & 0xf);
+
+ int CoeffIndex = (Header >> 4) & 7;
+
+ short Coeff0 = Context.Coefficients[CoeffIndex * 2 + 0];
+ short Coeff1 = Context.Coefficients[CoeffIndex * 2 + 1];
+
+ int FrameSamples = SamplesPerFrame;
+
+ if (FrameSamples > Samples)
+ {
+ FrameSamples = Samples;
+ }
+
+ int Value = 0;
+
+ for (int SampleIndex = 0; SampleIndex < FrameSamples; SampleIndex++)
+ {
+ int Sample;
+
+ if ((SampleIndex & 1) == 0)
+ {
+ Value = Buffer[InputOffset++];
+
+ Sample = (Value << 24) >> 28;
+ }
+ else
+ {
+ Sample = (Value << 28) >> 28;
+ }
+
+ int Prediction = Coeff0 * History0 + Coeff1 * History1;
+
+ Sample = (Sample * Scale + Prediction + 0x400) >> 11;
+
+ short SaturatedSample = DspUtils.Saturate(Sample);
+
+ History1 = History0;
+ History0 = SaturatedSample;
+
+ Pcm[OutputOffset++] = SaturatedSample;
+ Pcm[OutputOffset++] = SaturatedSample;
+ }
+
+ Samples -= FrameSamples;
+ }
+
+ Context.History0 = History0;
+ Context.History1 = History1;
+
+ return Pcm;
+ }
+
+ public static long GetSizeFromSamplesCount(int SamplesCount)
+ {
+ int Frames = SamplesCount / SamplesPerFrame;
+
+ return Frames * BytesPerFrame;
+ }
+
+ public static int GetSamplesCountFromSize(long Size)
+ {
+ int Frames = (int)(Size / BytesPerFrame);
+
+ return Frames * SamplesPerFrame;
+ }
+ }
+} \ No newline at end of file