diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj index e1080d4256..ef7648e3d8 100644 --- a/BizHawk.Emulation/BizHawk.Emulation.csproj +++ b/BizHawk.Emulation/BizHawk.Emulation.csproj @@ -350,6 +350,7 @@ + diff --git a/BizHawk.Emulation/Consoles/Nintendo/Gameboy/Gambatte.cs b/BizHawk.Emulation/Consoles/Nintendo/Gameboy/Gambatte.cs index 79e3629ebe..b9ed9d68f6 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/Gameboy/Gambatte.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/Gameboy/Gambatte.cs @@ -441,12 +441,13 @@ namespace BizHawk.Emulation.Consoles.GB int soundbuffcontains = 0; Sound.Utilities.SpeexResampler resampler; - Sound.MetaspuSoundProvider metaspu; + ISoundProvider metaspu; void InitSound() { - metaspu = new Sound.MetaspuSoundProvider(Sound.ESynchMethod.ESynchMethod_V); + var metaspu = new Sound.MetaspuSoundProvider(Sound.ESynchMethod.ESynchMethod_V); resampler = new Sound.Utilities.SpeexResampler(2, 2097152, 44100, 2097152, 44100, metaspu.buffer.enqueue_samples); + this.metaspu = new Sound.Utilities.DCFilter(metaspu);// metaspu; } void DisposeSound() diff --git a/BizHawk.Emulation/Sound/Utilities/DCFilter.cs b/BizHawk.Emulation/Sound/Utilities/DCFilter.cs new file mode 100644 index 0000000000..e2575c6ce1 --- /dev/null +++ b/BizHawk.Emulation/Sound/Utilities/DCFilter.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BizHawk.Emulation.Sound.Utilities +{ + /// + /// implements a DC block filter on top of an ISoundProvider. rather simple. + /// + public class DCFilter : ISoundProvider + { + /* + * A note about accuracy: + * + * DCFilter can be added to the final output of any console, and this change will be faithful to the original hardware. + * Analog output hardware ALWAYS has dc blocking caps. + */ + + ISoundProvider input; + + int sumL = 0; + int sumR = 0; + + Queue buffer; + + const int depth = 65536; + + public DCFilter(ISoundProvider input) + { + this.input = input; + this.buffer = new Queue(depth * 2); + for (int i = 0; i < depth * 2; i++) + buffer.Enqueue(0); + } + + /// + /// returns the original sound provider (in case you lost it). + /// after calling, the DCFilter is no longer valid + /// + /// + public ISoundProvider Detatch() + { + var ret = input; + input = null; + return ret; + } + + public void GetSamples(short[] samples) + { + + input.GetSamples(samples); + + for (int i = 0; i < samples.Length; i += 2) + { + sumL -= buffer.Dequeue(); + sumR -= buffer.Dequeue(); + short L = samples[i]; + short R = samples[i + 1]; + sumL += L; + sumR += R; + buffer.Enqueue(L); + buffer.Enqueue(R); + int bigL = L - (sumL >> 16); // / depth; + int bigR = R - (sumR >> 16); // / depth; + // check for clipping + if (bigL > 32767) + samples[i] = 32767; + else if (bigL < -32768) + samples[i] = -32768; + else + samples[i] = (short)bigL; + if (bigR > 32767) + samples[i + 1] = 32767; + else if (bigR < -32768) + samples[i + 1] = -32768; + else + samples[i + 1] = (short)bigR; + + } + } + + public void DiscardSamples() + { + input.DiscardSamples(); + } + + public int MaxVolume + { + get + { + return input.MaxVolume; + } + set + { + input.MaxVolume = value; + } + } + } +}