diff --git a/Source/Core/AudioCommon/AudioCommon.cpp b/Source/Core/AudioCommon/AudioCommon.cpp index 9ac53eb118..c476fe6a5c 100644 --- a/Source/Core/AudioCommon/AudioCommon.cpp +++ b/Source/Core/AudioCommon/AudioCommon.cpp @@ -26,8 +26,13 @@ SoundStream *soundStream = nullptr; namespace AudioCommon { - SoundStream *InitSoundStream(CMixer *mixer, void *hWnd) + SoundStream *InitSoundStream(void *hWnd) { + unsigned int AISampleRate, DACSampleRate; + AudioInterface::Callback_GetSampleRate(AISampleRate, DACSampleRate); + delete soundStream; + CMixer *mixer = new CMixer(AISampleRate, DACSampleRate, 48000); + // TODO: possible memleak with mixer std::string backend = SConfig::GetInstance().sBackend; @@ -128,15 +133,6 @@ namespace AudioCommon return backends; } - bool UseJIT() - { - if (!Movie::IsDSPHLE() && Movie::IsPlayingInput() && Movie::IsConfigSaved()) - { - return true; - } - return SConfig::GetInstance().m_DSPEnableJIT; - } - void PauseAndLock(bool doLock, bool unpauseOnUnlock) { if (soundStream) @@ -163,4 +159,25 @@ namespace AudioCommon soundStream->SetVolume(SConfig::GetInstance().m_Volume); } } + + void ClearAudioBuffer(bool mute) + { + if (soundStream) + soundStream->Clear(mute); + } + + void SendAIBuffer(short *samples, unsigned int num_samples) + { + if (!soundStream) + return; + + CMixer* pMixer = soundStream->GetMixer(); + + if (pMixer && samples) + { + pMixer->PushSamples(samples, num_samples); + } + + soundStream->Update(); + } } diff --git a/Source/Core/AudioCommon/AudioCommon.h b/Source/Core/AudioCommon/AudioCommon.h index 054c0fe47e..4fd4b6a965 100644 --- a/Source/Core/AudioCommon/AudioCommon.h +++ b/Source/Core/AudioCommon/AudioCommon.h @@ -12,37 +12,13 @@ class CMixer; extern SoundStream *soundStream; -// UDSPControl -union UDSPControl -{ - u16 Hex; - struct - { - u16 DSPReset : 1; // Write 1 to reset and waits for 0 - u16 DSPAssertInt : 1; - u16 DSPHalt : 1; - - u16 AI : 1; - u16 AI_mask : 1; - u16 ARAM : 1; - u16 ARAM_mask : 1; - u16 DSP : 1; - u16 DSP_mask : 1; - - u16 ARAM_DMAState : 1; // DSPGetDMAStatus() uses this flag - u16 DSPInitCode : 1; - u16 DSPInit : 1; // DSPInit() writes to this flag - u16 pad : 4; - }; - UDSPControl(u16 _Hex = 0) : Hex(_Hex) {} -}; - namespace AudioCommon { - SoundStream *InitSoundStream(CMixer *mixer, void *hWnd); + SoundStream *InitSoundStream(void *hWnd); void ShutdownSoundStream(); std::vector GetSoundBackends(); - bool UseJIT(); void PauseAndLock(bool doLock, bool unpauseOnUnlock=true); void UpdateSoundStream(); + void ClearAudioBuffer(bool mute); + void SendAIBuffer(short* samples, unsigned int num_samples); } diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index a4184797a6..a4d4a6fdda 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -410,6 +410,8 @@ void EmuThread() } + AudioCommon::InitSoundStream(g_pWindowHandle); + // The hardware is initialized. g_bHwInit = true; @@ -507,6 +509,7 @@ void EmuThread() Pad::Shutdown(); Wiimote::Shutdown(); g_video_backend->Shutdown(); + AudioCommon::ShutdownSoundStream(); } // Set or get the running state diff --git a/Source/Core/Core/DSPEmulator.h b/Source/Core/Core/DSPEmulator.h index 71a12635e8..49e086ff6f 100644 --- a/Source/Core/Core/DSPEmulator.h +++ b/Source/Core/Core/DSPEmulator.h @@ -4,7 +4,6 @@ #pragma once -#include "AudioCommon/SoundStream.h" #include "Common/ChunkFile.h" class DSPEmulator @@ -26,15 +25,9 @@ public: virtual unsigned short DSP_ReadMailBoxLow(bool _CPUMailbox) = 0; virtual unsigned short DSP_ReadControlRegister() = 0; virtual unsigned short DSP_WriteControlRegister(unsigned short) = 0; - virtual void DSP_SendAIBuffer(unsigned int address, unsigned int num_samples) = 0; virtual void DSP_Update(int cycles) = 0; virtual void DSP_StopSoundStream() = 0; - virtual void DSP_ClearAudioBuffer(bool mute) = 0; virtual u32 DSP_UpdateRate() = 0; - -protected: - SoundStream *soundStream; - void *m_hWnd; }; DSPEmulator *CreateDSPEmulator(bool HLE); diff --git a/Source/Core/Core/HW/CPU.cpp b/Source/Core/Core/HW/CPU.cpp index 13717b395c..613974b675 100644 --- a/Source/Core/Core/HW/CPU.cpp +++ b/Source/Core/Core/HW/CPU.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 // Refer to the license.txt file included. +#include "AudioCommon/AudioCommon.h" + #include "Common/Common.h" #include "Common/Thread.h" @@ -112,14 +114,14 @@ void CCPU::EnableStepping(const bool _bStepping) PowerPC::Pause(); m_StepEvent.Reset(); g_video_backend->EmuStateChange(EMUSTATE_CHANGE_PAUSE); - DSP::GetDSPEmulator()->DSP_ClearAudioBuffer(true); + AudioCommon::ClearAudioBuffer(true); } else { PowerPC::Start(); m_StepEvent.Set(); g_video_backend->EmuStateChange(EMUSTATE_CHANGE_PLAY); - DSP::GetDSPEmulator()->DSP_ClearAudioBuffer(false); + AudioCommon::ClearAudioBuffer(false); } } diff --git a/Source/Core/Core/HW/DSP.cpp b/Source/Core/Core/HW/DSP.cpp index 858f7ff748..2394243396 100644 --- a/Source/Core/Core/HW/DSP.cpp +++ b/Source/Core/Core/HW/DSP.cpp @@ -23,6 +23,8 @@ // the just used buffer through the AXList (or whatever it might be called in // Nintendo games). +#include "AudioCommon/AudioCommon.h" + #include "Common/MemoryUtil.h" #include "Core/ConfigManager.h" @@ -76,34 +78,6 @@ union UARAMCount }; }; -// UDSPControl -#define DSP_CONTROL_MASK 0x0C07 -union UDSPControl -{ - u16 Hex; - struct - { - // DSP Control - u16 DSPReset : 1; // Write 1 to reset and waits for 0 - u16 DSPAssertInt : 1; - u16 DSPHalt : 1; - // Interrupt for DMA to the AI/speakers - u16 AID : 1; - u16 AID_mask : 1; - // ARAM DMA interrupt - u16 ARAM : 1; - u16 ARAM_mask : 1; - // DSP DMA interrupt - u16 DSP : 1; - u16 DSP_mask : 1; - // Other ??? - u16 DMAState : 1; // DSPGetDMAStatus() uses this flag. __ARWaitForDMA() uses it too...maybe it's just general DMA flag - u16 unk3 : 1; - u16 DSPInit : 1; // DSPInit() writes to this flag - u16 pad : 4; - }; -}; - // DSPState struct DSPState { @@ -394,7 +368,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) if (tmpControl.DSP) g_dspState.DSPControl.DSP = 0; // unknown - g_dspState.DSPControl.unk3 = tmpControl.unk3; + g_dspState.DSPControl.DSPInitCode = tmpControl.DSPInitCode; g_dspState.DSPControl.pad = tmpControl.pad; if (g_dspState.DSPControl.pad != 0) { @@ -510,7 +484,9 @@ void UpdateAudioDMA() if (g_audioDMA.BlocksLeft == 0) { - dsp_emulator->DSP_SendAIBuffer(g_audioDMA.SourceAddress, 8*g_audioDMA.AudioDMAControl.NumBlocks); + void *address = Memory::GetPointer(g_audioDMA.SourceAddress); + unsigned samples = 8 * g_audioDMA.AudioDMAControl.NumBlocks; + AudioCommon::SendAIBuffer((short*)address, samples); GenerateDSPInterrupt(DSP::INT_AID); g_audioDMA.BlocksLeft = g_audioDMA.AudioDMAControl.NumBlocks; g_audioDMA.ReadAddress = g_audioDMA.SourceAddress; @@ -520,7 +496,7 @@ void UpdateAudioDMA() { // Send silence. Yeah, it's a bit of a waste to sample rate convert // silence. or hm. Maybe we shouldn't do this :) - dsp_emulator->DSP_SendAIBuffer(0, AudioInterface::GetAIDSampleRate()); + AudioCommon::SendAIBuffer(0, AudioInterface::GetAIDSampleRate()); } } diff --git a/Source/Core/Core/HW/DSP.h b/Source/Core/Core/HW/DSP.h index 2a9475a210..293a4a6733 100644 --- a/Source/Core/Core/HW/DSP.h +++ b/Source/Core/Core/HW/DSP.h @@ -27,6 +27,35 @@ enum ARAM_MASK = 0x00FFFFFF, }; +// UDSPControl +#define DSP_CONTROL_MASK 0x0C07 +union UDSPControl +{ + u16 Hex; + struct + { + // DSP Control + u16 DSPReset : 1; // Write 1 to reset and waits for 0 + u16 DSPAssertInt : 1; + u16 DSPHalt : 1; + // Interrupt for DMA to the AI/speakers + u16 AID : 1; + u16 AID_mask : 1; + // ARAM DMA interrupt + u16 ARAM : 1; + u16 ARAM_mask : 1; + // DSP DMA interrupt + u16 DSP : 1; + u16 DSP_mask : 1; + // Other ??? + u16 DMAState : 1; // DSPGetDMAStatus() uses this flag. __ARWaitForDMA() uses it too...maybe it's just general DMA flag + u16 DSPInitCode : 1; // Indicator that the DSP was initialized? + u16 DSPInit : 1; // DSPInit() writes to this flag + u16 pad : 4; + }; + UDSPControl(u16 _Hex = 0) : Hex(_Hex) {} +}; + void Init(bool hle); void Shutdown(); diff --git a/Source/Core/Core/HW/DSPHLE/DSPHLE.cpp b/Source/Core/Core/HW/DSPHLE/DSPHLE.cpp index 4156f578de..de7d39919b 100644 --- a/Source/Core/Core/HW/DSPHLE/DSPHLE.cpp +++ b/Source/Core/Core/HW/DSPHLE/DSPHLE.cpp @@ -19,8 +19,6 @@ DSPHLE::DSPHLE() { - m_InitMixer = false; - soundStream = nullptr; } // Mailbox utility @@ -43,7 +41,6 @@ struct DSPState bool DSPHLE::Initialize(void *hWnd, bool bWii, bool bDSPThread) { - m_hWnd = hWnd; m_bWii = bWii; m_pUCode = nullptr; m_lastUCode = nullptr; @@ -54,7 +51,6 @@ bool DSPHLE::Initialize(void *hWnd, bool bWii, bool bDSPThread) m_DSPControl.DSPHalt = 1; m_DSPControl.DSPInit = 1; - m_InitMixer = false; m_dspState.Reset(); return true; @@ -66,7 +62,6 @@ void DSPHLE::DSP_StopSoundStream() void DSPHLE::Shutdown() { - AudioCommon::ShutdownSoundStream(); } void DSPHLE::DSP_Update(int cycles) @@ -139,23 +134,6 @@ void DSPHLE::DoState(PointerWrap &p) p.SetMode(PointerWrap::MODE_VERIFY); return; } - bool prevInitMixer = m_InitMixer; - p.Do(m_InitMixer); - if (prevInitMixer != m_InitMixer && p.GetMode() == PointerWrap::MODE_READ) - { - if (m_InitMixer) - { - InitMixer(); - AudioCommon::PauseAndLock(true); - } - else - { - AudioCommon::PauseAndLock(false); - soundStream->Stop(); - delete soundStream; - soundStream = nullptr; - } - } p.DoPOD(m_DSPControl); p.DoPOD(m_dspState); @@ -260,28 +238,10 @@ void DSPHLE::DSP_WriteMailBoxLow(bool _CPUMailbox, unsigned short _Value) } } -void DSPHLE::InitMixer() -{ - unsigned int AISampleRate, DACSampleRate; - AudioInterface::Callback_GetSampleRate(AISampleRate, DACSampleRate); - delete soundStream; - soundStream = AudioCommon::InitSoundStream(new CMixer(AISampleRate, DACSampleRate, 48000), m_hWnd); - if (!soundStream) PanicAlert("Error starting up sound stream"); - // Mixer is initialized - m_InitMixer = true; -} - // Other DSP fuctions u16 DSPHLE::DSP_WriteControlRegister(unsigned short _Value) { - UDSPControl Temp(_Value); - if (!m_InitMixer) - { - if (!Temp.DSPHalt) - { - InitMixer(); - } - } + DSP::UDSPControl Temp(_Value); if (Temp.DSPReset) { @@ -304,34 +264,6 @@ u16 DSPHLE::DSP_ReadControlRegister() return m_DSPControl.Hex; } - -// The reason that we don't disable this entire -// function when Other Audio is disabled is that then we can't turn it back on -// again once the game has started. -void DSPHLE::DSP_SendAIBuffer(unsigned int address, unsigned int num_samples) -{ - if (!soundStream) - return; - - CMixer* pMixer = soundStream->GetMixer(); - - if (pMixer && address) - { - short* samples = (short*)HLEMemory_Get_Pointer(address); - pMixer->PushSamples(samples, num_samples); - } - - soundStream->Update(); -} - -void DSPHLE::DSP_ClearAudioBuffer(bool mute) -{ - if (soundStream) - soundStream->Clear(mute); -} - void DSPHLE::PauseAndLock(bool doLock, bool unpauseOnUnlock) { - if (doLock || unpauseOnUnlock) - DSP_ClearAudioBuffer(doLock); } diff --git a/Source/Core/Core/HW/DSPHLE/DSPHLE.h b/Source/Core/Core/HW/DSPHLE/DSPHLE.h index dbd305dda2..21ef5da87c 100644 --- a/Source/Core/Core/HW/DSPHLE/DSPHLE.h +++ b/Source/Core/Core/HW/DSPHLE/DSPHLE.h @@ -4,10 +4,8 @@ #pragma once -#include "AudioCommon/AudioCommon.h" -#include "AudioCommon/SoundStream.h" - #include "Core/DSPEmulator.h" +#include "Core/HW/DSP.h" #include "Core/HW/DSPHLE/MailHandler.h" class UCodeInterface; @@ -29,10 +27,8 @@ public: virtual unsigned short DSP_ReadMailBoxLow(bool _CPUMailbox) override; virtual unsigned short DSP_ReadControlRegister() override; virtual unsigned short DSP_WriteControlRegister(unsigned short) override; - virtual void DSP_SendAIBuffer(unsigned int address, unsigned int num_samples) override; virtual void DSP_Update(int cycles) override; virtual void DSP_StopSoundStream() override; - virtual void DSP_ClearAudioBuffer(bool mute) override; virtual u32 DSP_UpdateRate() override; CMailHandler& AccessMailHandler() { return m_MailHandler; } @@ -44,13 +40,10 @@ public: private: void SendMailToDSP(u32 _uMail); - void InitMixer(); // Declarations and definitions bool m_bWii; - bool m_InitMixer; - // Fake mailbox utility struct DSPState { @@ -73,7 +66,7 @@ private: UCodeInterface* m_pUCode; UCodeInterface* m_lastUCode; - UDSPControl m_DSPControl; + DSP::UDSPControl m_DSPControl; CMailHandler m_MailHandler; bool m_bHalt; diff --git a/Source/Core/Core/HW/DSPLLE/DSPLLE.cpp b/Source/Core/Core/HW/DSPLLE/DSPLLE.cpp index 420d5dc84d..697e69586d 100644 --- a/Source/Core/Core/HW/DSPLLE/DSPLLE.cpp +++ b/Source/Core/Core/HW/DSPLLE/DSPLLE.cpp @@ -2,9 +2,6 @@ // Licensed under GPLv2 // Refer to the license.txt file included. -#include "AudioCommon/AudioCommon.h" -#include "AudioCommon/Mixer.h" - #include "Common/Atomic.h" #include "Common/ChunkFile.h" #include "Common/Common.h" @@ -33,8 +30,6 @@ DSPLLE::DSPLLE() { - soundStream = nullptr; - m_InitMixer = false; m_bIsRunning = false; m_cycle_count = 0; } @@ -80,24 +75,6 @@ void DSPLLE::DoState(PointerWrap &p) p.Do(cyclesLeft); p.Do(init_hax); p.Do(m_cycle_count); - - bool prevInitMixer = m_InitMixer; - p.Do(m_InitMixer); - if (prevInitMixer != m_InitMixer && p.GetMode() == PointerWrap::MODE_READ) - { - if (m_InitMixer) - { - InitMixer(); - AudioCommon::PauseAndLock(true); - } - else - { - AudioCommon::PauseAndLock(false); - soundStream->Stop(); - delete soundStream; - soundStream = nullptr; - } - } } // Regular thread @@ -131,10 +108,8 @@ void DSPLLE::dsp_thread(DSPLLE *dsp_lle) bool DSPLLE::Initialize(void *hWnd, bool bWii, bool bDSPThread) { - m_hWnd = hWnd; m_bWii = bWii; m_bDSPThread = bDSPThread; - m_InitMixer = false; std::string irom_file = File::GetUserPath(D_GCUSER_IDX) + DSP_IROM; std::string coef_file = File::GetUserPath(D_GCUSER_IDX) + DSP_COEF; @@ -143,7 +118,9 @@ bool DSPLLE::Initialize(void *hWnd, bool bWii, bool bDSPThread) irom_file = File::GetSysDirectory() + GC_SYS_DIR DIR_SEP DSP_IROM; if (!File::Exists(coef_file)) coef_file = File::GetSysDirectory() + GC_SYS_DIR DIR_SEP DSP_COEF; - if (!DSPCore_Init(irom_file, coef_file, AudioCommon::UseJIT())) + + bool use_jit = SConfig::GetInstance().m_DSPEnableJIT; + if (!DSPCore_Init(irom_file, coef_file, use_jit)) return false; g_dsp.cpu_ram = Memory::GetPointer(0); @@ -175,31 +152,11 @@ void DSPLLE::DSP_StopSoundStream() void DSPLLE::Shutdown() { - AudioCommon::ShutdownSoundStream(); DSPCore_Shutdown(); } -void DSPLLE::InitMixer() -{ - unsigned int AISampleRate, DACSampleRate; - AudioInterface::Callback_GetSampleRate(AISampleRate, DACSampleRate); - delete soundStream; - soundStream = AudioCommon::InitSoundStream(new CMixer(AISampleRate, DACSampleRate, 48000), m_hWnd); - if (!soundStream) PanicAlert("Error starting up sound stream"); - // Mixer is initialized - m_InitMixer = true; -} - u16 DSPLLE::DSP_WriteControlRegister(u16 _uFlag) { - UDSPControl Temp(_uFlag); - if (!m_InitMixer) - { - if (!Temp.DSPHalt) - { - InitMixer(); - } - } DSPInterpreter::WriteCR(_uFlag); // Check if the CPU has set an external interrupt (CR_EXTERNAL_INT) @@ -323,34 +280,8 @@ u32 DSPLLE::DSP_UpdateRate() return 12600; // TO BE TWEAKED } -void DSPLLE::DSP_SendAIBuffer(unsigned int address, unsigned int num_samples) -{ - if (!soundStream) - return; - - CMixer *pMixer = soundStream->GetMixer(); - - if (pMixer && address) - { - address &= (address & 0x10000000) ? 0x13ffffff : 0x01ffffff; - const short *samples = (const short *)&g_dsp.cpu_ram[address]; - pMixer->PushSamples(samples, num_samples); - } - - soundStream->Update(); -} - -void DSPLLE::DSP_ClearAudioBuffer(bool mute) -{ - if (soundStream) - soundStream->Clear(mute); -} - void DSPLLE::PauseAndLock(bool doLock, bool unpauseOnUnlock) { - if (doLock || unpauseOnUnlock) - DSP_ClearAudioBuffer(doLock); - if (doLock) m_csDSPThreadActive.lock(); else diff --git a/Source/Core/Core/HW/DSPLLE/DSPLLE.h b/Source/Core/Core/HW/DSPLLE/DSPLLE.h index f7acbbf3f9..10381ae8c5 100644 --- a/Source/Core/Core/HW/DSPLLE/DSPLLE.h +++ b/Source/Core/Core/HW/DSPLLE/DSPLLE.h @@ -4,7 +4,6 @@ #pragma once -#include "AudioCommon/SoundStream.h" #include "Common/Thread.h" #include "Core/DSPEmulator.h" @@ -28,19 +27,15 @@ public: virtual unsigned short DSP_ReadMailBoxLow(bool _CPUMailbox) override; virtual unsigned short DSP_ReadControlRegister() override; virtual unsigned short DSP_WriteControlRegister(unsigned short) override; - virtual void DSP_SendAIBuffer(unsigned int address, unsigned int num_samples) override; virtual void DSP_Update(int cycles) override; virtual void DSP_StopSoundStream() override; - virtual void DSP_ClearAudioBuffer(bool mute) override; virtual u32 DSP_UpdateRate() override; private: static void dsp_thread(DSPLLE* lpParameter); - void InitMixer(); std::thread m_hDSPThread; std::mutex m_csDSPThreadActive; - bool m_InitMixer; bool m_bWii; bool m_bDSPThread; bool m_bIsRunning; diff --git a/Source/Core/DolphinWX/ConfigMain.cpp b/Source/Core/DolphinWX/ConfigMain.cpp index 3f1812420f..61297f6e37 100644 --- a/Source/Core/DolphinWX/ConfigMain.cpp +++ b/Source/Core/DolphinWX/ConfigMain.cpp @@ -23,6 +23,8 @@ #include #include +#include "AudioCommon/AudioCommon.h" + #include "Common/Common.h" #include "Common/CommonPaths.h" #include "Common/FileSearch.h"