From 502def7f71efb78170bd0d5fed7e4cae1112120a Mon Sep 17 00:00:00 2001 From: Bonta <40473493+Bonta0@users.noreply.github.com> Date: Sun, 4 Jul 2021 12:44:56 +0200 Subject: [PATCH] Mixer: Support GBA samples mixing --- Source/Core/AudioCommon/Mixer.cpp | 41 +++++++++++++++++++++++++------ Source/Core/AudioCommon/Mixer.h | 18 +++++++++++--- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/Source/Core/AudioCommon/Mixer.cpp b/Source/Core/AudioCommon/Mixer.cpp index ae8ba47d00..e50d90b32b 100644 --- a/Source/Core/AudioCommon/Mixer.cpp +++ b/Source/Core/AudioCommon/Mixer.cpp @@ -47,6 +47,8 @@ void Mixer::DoState(PointerWrap& p) m_dma_mixer.DoState(p); m_streaming_mixer.DoState(p); m_wiimote_speaker_mixer.DoState(p); + for (auto& mixer : m_gba_mixers) + mixer.DoState(p); } // Executed from sound stream thread @@ -93,20 +95,24 @@ unsigned int Mixer::MixerFifo::Mix(short* samples, unsigned int numSamples, s32 lvolume = m_LVolume.load(); s32 rvolume = m_RVolume.load(); + const auto read_buffer = [this](auto index) { + return m_little_endian ? m_buffer[index] : Common::swap16(m_buffer[index]); + }; + // TODO: consider a higher-quality resampling algorithm. for (; currentSample < numSamples * 2 && ((indexW - indexR) & INDEX_MASK) > 2; currentSample += 2) { u32 indexR2 = indexR + 2; // next sample - s16 l1 = Common::swap16(m_buffer[indexR & INDEX_MASK]); // current - s16 l2 = Common::swap16(m_buffer[indexR2 & INDEX_MASK]); // next + s16 l1 = read_buffer(indexR & INDEX_MASK); // current + s16 l2 = read_buffer(indexR2 & INDEX_MASK); // next int sampleL = ((l1 << 16) + (l2 - l1) * (u16)m_frac) >> 16; sampleL = (sampleL * lvolume) >> 8; sampleL += samples[currentSample + 1]; samples[currentSample + 1] = std::clamp(sampleL, -32767, 32767); - s16 r1 = Common::swap16(m_buffer[(indexR + 1) & INDEX_MASK]); // current - s16 r2 = Common::swap16(m_buffer[(indexR2 + 1) & INDEX_MASK]); // next + s16 r1 = read_buffer((indexR + 1) & INDEX_MASK); // current + s16 r2 = read_buffer((indexR2 + 1) & INDEX_MASK); // next int sampleR = ((r1 << 16) + (r2 - r1) * (u16)m_frac) >> 16; sampleR = (sampleR * rvolume) >> 8; sampleR += samples[currentSample]; @@ -122,8 +128,8 @@ unsigned int Mixer::MixerFifo::Mix(short* samples, unsigned int numSamples, // Padding short s[2]; - s[0] = Common::swap16(m_buffer[(indexR - 1) & INDEX_MASK]); - s[1] = Common::swap16(m_buffer[(indexR - 2) & INDEX_MASK]); + s[0] = read_buffer((indexR - 1) & INDEX_MASK); + s[1] = read_buffer((indexR - 2) & INDEX_MASK); s[0] = (s[0] * rvolume) >> 8; s[1] = (s[1] * lvolume) >> 8; for (; currentSample < numSamples * 2; currentSample += 2) @@ -158,6 +164,8 @@ unsigned int Mixer::Mix(short* samples, unsigned int num_samples) m_dma_mixer.Mix(m_scratch_buffer.data(), available_samples, false); m_streaming_mixer.Mix(m_scratch_buffer.data(), available_samples, false); m_wiimote_speaker_mixer.Mix(m_scratch_buffer.data(), available_samples, false); + for (auto& mixer : m_gba_mixers) + mixer.Mix(m_scratch_buffer.data(), available_samples, false); if (!m_is_stretching) { @@ -172,6 +180,8 @@ unsigned int Mixer::Mix(short* samples, unsigned int num_samples) m_dma_mixer.Mix(samples, num_samples, true); m_streaming_mixer.Mix(samples, num_samples, true); m_wiimote_speaker_mixer.Mix(samples, num_samples, true); + for (auto& mixer : m_gba_mixers) + mixer.Mix(samples, num_samples, true); m_is_stretching = false; } @@ -258,14 +268,19 @@ void Mixer::PushWiimoteSpeakerSamples(const short* samples, unsigned int num_sam for (unsigned int i = 0; i < num_samples; ++i) { - samples_stereo[i * 2] = Common::swap16(samples[i]); - samples_stereo[i * 2 + 1] = Common::swap16(samples[i]); + samples_stereo[i * 2] = samples[i]; + samples_stereo[i * 2 + 1] = samples[i]; } m_wiimote_speaker_mixer.PushSamples(samples_stereo, num_samples); } } +void Mixer::PushGBASamples(int device_number, const short* samples, unsigned int num_samples) +{ + m_gba_mixers[device_number].PushSamples(samples, num_samples); +} + void Mixer::SetDMAInputSampleRate(unsigned int rate) { m_dma_mixer.SetInputSampleRate(rate); @@ -276,6 +291,11 @@ void Mixer::SetStreamInputSampleRate(unsigned int rate) m_streaming_mixer.SetInputSampleRate(rate); } +void Mixer::SetGBAInputSampleRates(int device_number, unsigned int rate) +{ + m_gba_mixers[device_number].SetInputSampleRate(rate); +} + void Mixer::SetStreamingVolume(unsigned int lvolume, unsigned int rvolume) { m_streaming_mixer.SetVolume(lvolume, rvolume); @@ -286,6 +306,11 @@ void Mixer::SetWiimoteSpeakerVolume(unsigned int lvolume, unsigned int rvolume) m_wiimote_speaker_mixer.SetVolume(lvolume, rvolume); } +void Mixer::SetGBAVolume(int device_number, unsigned int lvolume, unsigned int rvolume) +{ + m_gba_mixers[device_number].SetVolume(lvolume, rvolume); +} + void Mixer::StartLogDTKAudio(const std::string& filename) { if (!m_log_dtk_audio) diff --git a/Source/Core/AudioCommon/Mixer.h b/Source/Core/AudioCommon/Mixer.h index 36630c7013..2a1a62ba4f 100644 --- a/Source/Core/AudioCommon/Mixer.h +++ b/Source/Core/AudioCommon/Mixer.h @@ -30,11 +30,17 @@ public: void PushStreamingSamples(const short* samples, unsigned int num_samples); void PushWiimoteSpeakerSamples(const short* samples, unsigned int num_samples, unsigned int sample_rate); + void PushGBASamples(int device_number, const short* samples, unsigned int num_samples); + unsigned int GetSampleRate() const { return m_sampleRate; } + void SetDMAInputSampleRate(unsigned int rate); void SetStreamInputSampleRate(unsigned int rate); + void SetGBAInputSampleRates(int device_number, unsigned int rate); + void SetStreamingVolume(unsigned int lvolume, unsigned int rvolume); void SetWiimoteSpeakerVolume(unsigned int lvolume, unsigned int rvolume); + void SetGBAVolume(int device_number, unsigned int lvolume, unsigned int rvolume); void StartLogDTKAudio(const std::string& filename); void StopLogDTKAudio(); @@ -57,7 +63,8 @@ private: class MixerFifo final { public: - MixerFifo(Mixer* mixer, unsigned sample_rate) : m_mixer(mixer), m_input_sample_rate(sample_rate) + MixerFifo(Mixer* mixer, unsigned sample_rate, bool little_endian) + : m_mixer(mixer), m_input_sample_rate(sample_rate), m_little_endian(little_endian) { } void DoState(PointerWrap& p); @@ -71,6 +78,7 @@ private: private: Mixer* m_mixer; unsigned m_input_sample_rate; + bool m_little_endian; std::array m_buffer{}; std::atomic m_indexW{0}; std::atomic m_indexR{0}; @@ -81,9 +89,11 @@ private: u32 m_frac = 0; }; - MixerFifo m_dma_mixer{this, 32000}; - MixerFifo m_streaming_mixer{this, 48000}; - MixerFifo m_wiimote_speaker_mixer{this, 3000}; + MixerFifo m_dma_mixer{this, 32000, false}; + MixerFifo m_streaming_mixer{this, 48000, false}; + MixerFifo m_wiimote_speaker_mixer{this, 3000, true}; + std::array m_gba_mixers{MixerFifo{this, 48000, true}, MixerFifo{this, 48000, true}, + MixerFifo{this, 48000, true}, MixerFifo{this, 48000, true}}; unsigned int m_sampleRate; bool m_is_stretching = false;