diff --git a/Source/Core/AudioCommon/Mixer.cpp b/Source/Core/AudioCommon/Mixer.cpp index 2b785ffaf4..fa43baeb99 100644 --- a/Source/Core/AudioCommon/Mixer.cpp +++ b/Source/Core/AudioCommon/Mixer.cpp @@ -99,9 +99,6 @@ unsigned int CMixer::Mix(short* samples, unsigned int numSamples, bool consider_ // Flush cached variable Common::AtomicStore(m_indexR, indexR); - // Add the DSPHLE sound, re-sampling is done inside - Premix(samples, numSamples); - // Add the DTK Music // Re-sampling is done inside AudioInterface::Callback_GetStreaming(samples, numSamples, m_sampleRate); diff --git a/Source/Core/AudioCommon/Mixer.h b/Source/Core/AudioCommon/Mixer.h index a892618cca..f7fcdbf14b 100644 --- a/Source/Core/AudioCommon/Mixer.h +++ b/Source/Core/AudioCommon/Mixer.h @@ -26,7 +26,6 @@ public: , m_dacSampleRate(DACSampleRate) , m_bits(16) , m_channels(2) - , m_HLEready(false) , m_logAudio(0) , m_indexW(0) , m_indexR(0) @@ -45,7 +44,6 @@ public: // Called from audio threads virtual unsigned int Mix(short* samples, unsigned int numSamples, bool consider_framelimit = true); - virtual void Premix(short * /*samples*/, unsigned int /*numSamples*/) {} // Called from main thread virtual void PushSamples(const short* samples, unsigned int num_samples); @@ -53,11 +51,6 @@ public: void SetThrottle(bool use) { m_throttle = use;} - // TODO: do we need this - bool IsHLEReady() const { return m_HLEready;} - void SetHLEReady(bool ready) { m_HLEready = ready;} - // --------------------- - virtual void StartLogAudio(const std::string& filename) { @@ -102,7 +95,6 @@ protected: WaveFileWriter g_wave_writer; - bool m_HLEready; bool m_logAudio; bool m_throttle; diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index cae1a15d10..58e67b3cd7 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -78,7 +78,6 @@ set(SRCS ActionReplay.cpp HW/DSPHLE/UCodes/UCode_Zelda_ADPCM.cpp HW/DSPHLE/UCodes/UCode_Zelda_Voice.cpp HW/DSPHLE/UCodes/UCode_Zelda_Synth.cpp - HW/DSPHLE/HLEMixer.cpp HW/DSPHLE/MailHandler.cpp HW/DSPHLE/DSPHLE.cpp HW/DSPLLE/DSPDebugInterface.cpp diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index f91087c3d2..e2b02f8a82 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -106,7 +106,6 @@ - @@ -305,7 +304,6 @@ - diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index 34264a07cf..af927b7b9f 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -347,9 +347,6 @@ HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE - - HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE - HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE @@ -873,9 +870,6 @@ HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE - - HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE - HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE diff --git a/Source/Core/Core/HW/DSPHLE/DSPHLE.cpp b/Source/Core/Core/HW/DSPHLE/DSPHLE.cpp index 0bdffb70a2..eb7ca52ab8 100644 --- a/Source/Core/Core/HW/DSPHLE/DSPHLE.cpp +++ b/Source/Core/Core/HW/DSPHLE/DSPHLE.cpp @@ -15,7 +15,6 @@ #include "Core/HW/SystemTimers.h" #include "Core/HW/VideoInterface.h" #include "Core/HW/DSPHLE/DSPHLE.h" -#include "Core/HW/DSPHLE/HLEMixer.h" #include "Core/HW/DSPHLE/UCodes/UCodes.h" DSPHLE::DSPHLE() @@ -266,7 +265,7 @@ void DSPHLE::InitMixer() unsigned int AISampleRate, DACSampleRate; AudioInterface::Callback_GetSampleRate(AISampleRate, DACSampleRate); delete soundStream; - soundStream = AudioCommon::InitSoundStream(new HLEMixer(this, AISampleRate, DACSampleRate, 48000), m_hWnd); + soundStream = AudioCommon::InitSoundStream(new CMixer(AISampleRate, DACSampleRate, 48000), m_hWnd); if (!soundStream) PanicAlert("Error starting up sound stream"); // Mixer is initialized m_InitMixer = true; diff --git a/Source/Core/Core/HW/DSPHLE/HLEMixer.cpp b/Source/Core/Core/HW/DSPHLE/HLEMixer.cpp deleted file mode 100644 index d1d51c4c85..0000000000 --- a/Source/Core/Core/HW/DSPHLE/HLEMixer.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#include "Core/HW/DSPHLE/DSPHLE.h" -#include "Core/HW/DSPHLE/HLEMixer.h" -#include "Core/HW/DSPHLE/UCodes/UCodes.h" - -void HLEMixer::Premix(short *samples, unsigned int numSamples) -{ - // if this was called directly from the HLE - if (IsHLEReady()) - { - IUCode *pUCode = m_DSPHLE->GetUCode(); - if (pUCode && samples) - pUCode->MixAdd(samples, numSamples); - } -} - diff --git a/Source/Core/Core/HW/DSPHLE/HLEMixer.h b/Source/Core/Core/HW/DSPHLE/HLEMixer.h deleted file mode 100644 index 135bfe97b8..0000000000 --- a/Source/Core/Core/HW/DSPHLE/HLEMixer.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#pragma once - -#include "AudioCommon/AudioCommon.h" -#include "AudioCommon/Mixer.h" - -class DSPHLE; - -class HLEMixer : public CMixer -{ -public: - HLEMixer(DSPHLE *dsp_hle, unsigned int AISampleRate = 48000, unsigned int DACSampleRate = 48000, unsigned int BackendSampleRate = 32000) - : CMixer(AISampleRate, DACSampleRate, BackendSampleRate), m_DSPHLE(dsp_hle) {}; - - virtual void Premix(short *samples, unsigned int numSamples) override; -private: - DSPHLE *m_DSPHLE; -}; diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/UCode_AX.cpp b/Source/Core/Core/HW/DSPHLE/UCodes/UCode_AX.cpp index f7eea84f22..379da8bab4 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/UCode_AX.cpp +++ b/Source/Core/Core/HW/DSPHLE/UCodes/UCode_AX.cpp @@ -16,30 +16,16 @@ CUCode_AX::CUCode_AX(DSPHLE* dsp_hle, u32 crc) : IUCode(dsp_hle, crc) , m_work_available(false) , m_cmdlist_size(0) - , m_run_on_thread(false) { WARN_LOG(DSPHLE, "Instantiating CUCode_AX: crc=%08x", crc); m_rMailHandler.PushMail(DSP_INIT); DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP); LoadResamplingCoefficients(); - - // DSP HLE on thread is always disabled because it causes audio - // issues/glitching (different timing characteristics). m_run_on_thread is - // always false. - if (m_run_on_thread) - m_axthread = std::thread(SpawnAXThread, this); } CUCode_AX::~CUCode_AX() { - if (m_run_on_thread) - { - m_cmdlist_size = (u16)-1; // Special value to signal end - NotifyAXThread(); - m_axthread.join(); - } - m_rMailHandler.Clear(); } @@ -80,32 +66,6 @@ void CUCode_AX::LoadResamplingCoefficients() m_coeffs_available = true; } -void CUCode_AX::SpawnAXThread(CUCode_AX* self) -{ - self->AXThread(); -} - -void CUCode_AX::AXThread() -{ - while (true) - { - { - std::unique_lock lk(m_cmdlist_mutex); - while (m_cmdlist_size == 0) - m_cmdlist_cv.wait(lk); - } - - if (m_cmdlist_size == (u16)-1) // End of thread signal - break; - - m_processing.lock(); - HandleCommandList(); - m_cmdlist_size = 0; - SignalWorkEnd(); - m_processing.unlock(); - } -} - void CUCode_AX::SignalWorkEnd() { // Signal end of processing @@ -113,20 +73,6 @@ void CUCode_AX::SignalWorkEnd() DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP); } -void CUCode_AX::NotifyAXThread() -{ - std::unique_lock lk(m_cmdlist_mutex); - m_cmdlist_cv.notify_one(); -} - -void CUCode_AX::StartWorking() -{ - if (m_run_on_thread) - NotifyAXThread(); - else - m_work_available = true; -} - void CUCode_AX::HandleCommandList() { // Temp variables for addresses computation @@ -660,15 +606,10 @@ void CUCode_AX::HandleMail(u32 mail) bool set_next_is_cmdlist = false; - // Wait for DSP processing to be done before answering any mail. This is - // safe to do because it matches what the DSP does on real hardware: there - // is no interrupt when a mail from CPU is received. - m_processing.lock(); - if (next_is_cmdlist) { CopyCmdList(mail, cmdlist_size); - StartWorking(); + m_work_available = true; } else if (m_UploadSetupInProgress) { @@ -682,7 +623,6 @@ void CUCode_AX::HandleMail(u32 mail) } else if (mail == MAIL_NEW_UCODE) { - soundStream->GetMixer()->SetHLEReady(false); m_UploadSetupInProgress = true; } else if (mail == MAIL_RESET) @@ -705,7 +645,6 @@ void CUCode_AX::HandleMail(u32 mail) ERROR_LOG(DSPHLE, "Unknown mail sent to AX::HandleMail: %08x", mail); } - m_processing.unlock(); next_is_cmdlist = set_next_is_cmdlist; } @@ -722,12 +661,6 @@ void CUCode_AX::CopyCmdList(u32 addr, u16 size) m_cmdlist_size = size; } -void CUCode_AX::MixAdd(short* out_buffer, int nsamples) -{ - // Should never be called: we do not set HLE as ready. - // We accurately send samples to RAM instead of directly to the mixer. -} - void CUCode_AX::Update(int cycles) { // Used for UCode switching. @@ -767,8 +700,6 @@ void CUCode_AX::DoAXState(PointerWrap& p) void CUCode_AX::DoState(PointerWrap& p) { - std::lock_guard lk(m_processing); - DoStateShared(p); DoAXState(p); } diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/UCode_AX.h b/Source/Core/Core/HW/DSPHLE/UCodes/UCode_AX.h index ede8ef6aa3..f29c14659b 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/UCode_AX.h +++ b/Source/Core/Core/HW/DSPHLE/UCodes/UCode_AX.h @@ -56,15 +56,10 @@ public: virtual ~CUCode_AX(); virtual void HandleMail(u32 mail) override; - virtual void MixAdd(short* out_buffer, int nsamples) override; virtual void Update(int cycles) override; virtual void DoState(PointerWrap& p) override; u32 GetUpdateMs() override; - // Needed because StdThread.h std::thread implem does not support member - // pointers. TODO(delroth): obsolete. - static void SpawnAXThread(CUCode_AX* self); - protected: enum MailType { @@ -92,19 +87,8 @@ protected: // This flag is set if there is anything to process. bool m_work_available; - // Volatile because it's set by HandleMail and accessed in - // HandleCommandList, which are running in two different threads. - volatile u16 m_cmdlist[512]; - volatile u32 m_cmdlist_size; - - bool m_run_on_thread; - - // Sync objects - std::mutex m_processing; - std::condition_variable m_cmdlist_cv; - std::mutex m_cmdlist_mutex; - - std::thread m_axthread; + u16 m_cmdlist[512]; + u32 m_cmdlist_size; // Table of coefficients for polyphase sample rate conversion. // The coefficients aren't always available (they are part of the DSP DROM) @@ -125,16 +109,6 @@ protected: // Apply updates to a PB. Generic, used in AX GC and AX Wii. void ApplyUpdatesForMs(int curr_ms, u16* pb, u16* num_updates, u16* updates); - // Signal that we should start handling a command list. Dispatches to the - // AX thread if using a thread, else just sets a boolean flag. - void StartWorking(); - - // Send a notification to the AX thread to tell it a new cmdlist addr is - // available for processing. - void NotifyAXThread(); - - void AXThread(); - virtual void HandleCommandList(); void SignalWorkEnd(); diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/UCode_AXWii.cpp b/Source/Core/Core/HW/DSPHLE/UCodes/UCode_AXWii.cpp index 8ebef6e80e..9655f99a36 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/UCode_AXWii.cpp +++ b/Source/Core/Core/HW/DSPHLE/UCodes/UCode_AXWii.cpp @@ -667,8 +667,6 @@ u32 CUCode_AXWii::GetUpdateMs() void CUCode_AXWii::DoState(PointerWrap &p) { - std::lock_guard lk(m_processing); - DoStateShared(p); DoAXState(p); diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/UCode_Zelda.cpp b/Source/Core/Core/HW/DSPHLE/UCodes/UCode_Zelda.cpp index 62c67d7927..ffd50d6b63 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/UCode_Zelda.cpp +++ b/Source/Core/Core/HW/DSPHLE/UCodes/UCode_Zelda.cpp @@ -130,11 +130,13 @@ void CUCode_Zelda::HandleMail_LightVersion(u32 _uMail) if (m_bSyncCmdPending) { DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP); + + MixAudio(); + m_CurBuffer++; if (m_CurBuffer == m_NumBuffers) { - soundStream->GetMixer()->SetHLEReady(true); m_bSyncCmdPending = false; DEBUG_LOG(DSPHLE, "Update the SoundThread to be in sync"); } @@ -189,6 +191,8 @@ void CUCode_Zelda::HandleMail_SMSVersion(u32 _uMail) m_NumSyncMail = 0; m_bSyncInProgress = false; + MixAudio(); + m_CurBuffer++; m_rMailHandler.PushMail(DSP_SYNC); @@ -200,7 +204,6 @@ void CUCode_Zelda::HandleMail_SMSVersion(u32 _uMail) m_rMailHandler.PushMail(DSP_FRAME_END); // DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP); - soundStream->GetMixer()->SetHLEReady(true); DEBUG_LOG(DSPHLE, "Update the SoundThread to be in sync"); // soundStream->Update(); //do it in this thread to avoid sync problems @@ -292,30 +295,12 @@ void CUCode_Zelda::HandleMail_NormalVersion(u32 _uMail) m_SyncFlags[n] = _uMail & 0xFFFF; m_bSyncInProgress = false; - // Normally, we should mix to the buffers used by the game. - // We don't do it currently for a simple reason: - // if the game runs fast all the time, then it's OK, - // but if it runs slow, sound can become choppy. - // This problem won't happen when mixing to the buffer - // provided by MixAdd(), because the size of this buffer - // is automatically adjusted if the game runs slow. -#if 0 - if (m_SyncFlags[n] & 0x8000) - { - for (; m_CurVoice < m_MaxVoice; m_CurVoice++) - { - if (m_CurVoice >= m_NumVoices) - break; - - MixVoice(m_CurVoice); - } - } - else -#endif - m_CurVoice = m_MaxVoice; + m_CurVoice = m_MaxVoice; if (m_CurVoice >= m_NumVoices) { + MixAudio(); + m_CurBuffer++; m_rMailHandler.PushMail(DSP_SYNC); @@ -330,7 +315,6 @@ void CUCode_Zelda::HandleMail_NormalVersion(u32 _uMail) m_rMailHandler.PushMail(DSP_FRAME_END); //g_dspInitialize.pGenerateDSPInterrupt(); - soundStream->GetMixer()->SetHLEReady(true); DEBUG_LOG(DSPHLE, "Update the SoundThread to be in sync"); // soundStream->Update(); //do it in this thread to avoid sync problems @@ -392,7 +376,6 @@ void CUCode_Zelda::HandleMail_NormalVersion(u32 _uMail) case 0x0001: // accepts params to either dma to iram and/or dram (used for hotbooting a new ucode) // TODO find a better way to protect from HLEMixer? - soundStream->GetMixer()->SetHLEReady(false); m_UploadSetupInProgress = true; return; @@ -484,8 +467,8 @@ void CUCode_Zelda::ExecuteList() // Addresses for right & left buffers in main memory // Each buffer is 160 bytes long. The number of (both left & right) buffers // is set by the first mail of the list. - m_RightBuffersAddr = Read32() & 0x7FFFFFFF; m_LeftBuffersAddr = Read32() & 0x7FFFFFFF; + m_RightBuffersAddr = Read32() & 0x7FFFFFFF; DEBUG_LOG(DSPHLE, "DsyncFrame"); // These alternate between three sets of mixing buffers. They are all three fairly near, @@ -559,9 +542,6 @@ u32 CUCode_Zelda::GetUpdateMs() void CUCode_Zelda::DoState(PointerWrap &p) { - // It's bad if we try to save during Mix() - std::lock_guard lk(m_csMix); - p.Do(m_AFCCoefTable); p.Do(m_MiscTable); diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/UCode_Zelda.h b/Source/Core/Core/HW/DSPHLE/UCodes/UCode_Zelda.h index eab6de743f..e3818a20bf 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/UCode_Zelda.h +++ b/Source/Core/Core/HW/DSPHLE/UCodes/UCode_Zelda.h @@ -125,9 +125,7 @@ public: void HandleMail_LightVersion(u32 _uMail); void HandleMail_SMSVersion(u32 _uMail); void HandleMail_NormalVersion(u32 _uMail); - void Update(int cycles) override; - void MixAdd(short* buffer, int size) override; void CopyPBsFromRAM(); void CopyPBsToRAM(); @@ -291,4 +289,6 @@ private: // Renders a voice and mixes it into LeftBuffer, RightBuffer void RenderAddVoice(ZeldaVoicePB& PB, s32* _LeftBuffer, s32* _RightBuffer, int _Size); + + void MixAudio(); }; diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/UCode_Zelda_Voice.cpp b/Source/Core/Core/HW/DSPHLE/UCodes/UCode_Zelda_Voice.cpp index 4393a48f0c..723a0aca98 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/UCode_Zelda_Voice.cpp +++ b/Source/Core/Core/HW/DSPHLE/UCodes/UCode_Zelda_Voice.cpp @@ -49,9 +49,7 @@ void CUCode_Zelda::WritebackVoicePB(u32 _Addr, ZeldaVoicePB& PB) int CUCode_Zelda::ConvertRatio(int pb_ratio) { - float _ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate(); - u32 _ratio = (pb_ratio << 16); - return (u64)((_ratio * _ratioFactor) * 16) >> 16; + return pb_ratio * 16; } int CUCode_Zelda::SizeForResampling(ZeldaVoicePB &PB, int size, int ratio) { @@ -739,17 +737,13 @@ ContinueWithBlock: } } -// size is in stereo samples. -void CUCode_Zelda::MixAdd(short *_Buffer, int _Size) +void CUCode_Zelda::MixAudio() { - std::lock_guard lk(m_csMix); - // Safety check - if (_Size > 256 * 1024 - 8) - _Size = 256 * 1024 - 8; + const int BufferSamples = 5 * 16; // Final mix buffers - memset(m_LeftBuffer, 0, _Size * sizeof(s32)); - memset(m_RightBuffer, 0, _Size * sizeof(s32)); + memset(m_LeftBuffer, 0, BufferSamples * sizeof(s32)); + memset(m_RightBuffer, 0, BufferSamples * sizeof(s32)); // For each PB... for (u32 i = 0; i < m_NumVoices; i++) @@ -769,22 +763,24 @@ void CUCode_Zelda::MixAdd(short *_Buffer, int _Size) if (pb.KeyOff != 0) continue; - RenderAddVoice(pb, m_LeftBuffer, m_RightBuffer, _Size); + RenderAddVoice(pb, m_LeftBuffer, m_RightBuffer, BufferSamples); WritebackVoicePB(m_VoicePBsAddr + (i * 0x180), pb); } // Post processing, final conversion. - for (int i = 0; i < _Size; i++) + s16* left_buffer = (s16*)HLEMemory_Get_Pointer(m_LeftBuffersAddr); + s16* right_buffer = (s16*)HLEMemory_Get_Pointer(m_RightBuffersAddr); + left_buffer += m_CurBuffer * BufferSamples; + right_buffer += m_CurBuffer * BufferSamples; + for (int i = 0; i < BufferSamples; i++) { - s32 left = (s32)_Buffer[0] + m_LeftBuffer[i]; - s32 right = (s32)_Buffer[1] + m_RightBuffer[i]; + s32 left = m_LeftBuffer[i]; + s32 right = m_RightBuffer[i]; MathUtil::Clamp(&left, -32768, 32767); - _Buffer[0] = (short)left; + left_buffer[i] = Common::swap16((short)left); MathUtil::Clamp(&right, -32768, 32767); - _Buffer[1] = (short)right; - - _Buffer += 2; + right_buffer[i] = Common::swap16((short)right); } } diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/UCodes.h b/Source/Core/Core/HW/DSPHLE/UCodes/UCodes.h index 73bf8795fb..d011d91370 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/UCodes.h +++ b/Source/Core/Core/HW/DSPHLE/UCodes/UCodes.h @@ -77,7 +77,6 @@ public: // Cycles are out of the 81/121mhz the DSP runs at. virtual void Update(int cycles) = 0; - virtual void MixAdd(short* buffer, int size) {} virtual u32 GetUpdateMs() = 0; virtual void DoState(PointerWrap &p) { DoStateShared(p); } @@ -95,7 +94,6 @@ protected: void DoStateShared(PointerWrap &p); CMailHandler& m_rMailHandler; - std::mutex m_csMix; enum EDSP_Codes {