diff --git a/Source/Core/AudioCommon/Src/DSoundStream.cpp b/Source/Core/AudioCommon/Src/DSoundStream.cpp index dc451eddb7..2e6cd69146 100644 --- a/Source/Core/AudioCommon/Src/DSoundStream.cpp +++ b/Source/Core/AudioCommon/Src/DSoundStream.cpp @@ -111,7 +111,7 @@ void DSound::SoundLoop() int numBytesToRender = FIX128(ModBufferSize(currentPos - lastPos)); if (numBytesToRender >= 256) { - if (numBytesToRender > sizeof(realtimeBuffer) * sizeof(short)) + if (numBytesToRender > sizeof(realtimeBuffer)) PanicAlert("soundThread: too big render call"); m_mixer->Mix(realtimeBuffer, numBytesToRender / 4); WriteDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender); diff --git a/Source/Core/AudioCommon/Src/Mixer.cpp b/Source/Core/AudioCommon/Src/Mixer.cpp index 00b3a2587b..13ccb4b48a 100644 --- a/Source/Core/AudioCommon/Src/Mixer.cpp +++ b/Source/Core/AudioCommon/Src/Mixer.cpp @@ -17,7 +17,6 @@ #include "Atomic.h" - #include "Mixer.h" #include "AudioCommon.h" @@ -41,37 +40,13 @@ unsigned int CMixer::Mix(short* samples, unsigned int numSamples) numLeft = (numLeft > numSamples) ? numSamples : numLeft; // Do re-sampling if needed - if (m_sampleRate == m_dspSampleRate) + if (m_sampleRate == 32000) { for (unsigned int i = 0; i < numLeft * 2; i++) samples[i] = Common::swap16(m_buffer[(m_indexR + i) & INDEX_MASK]); m_indexR += numLeft * 2; } - else if (m_sampleRate < m_dspSampleRate) // If down-sampling needed - { - _dbg_assert_msg_(DSPHLE, !(numSamples % 2), "Number of Samples: %i must be even!", numSamples); - - short *pDest = samples; - int last_l, last_r, cur_l, cur_r; - - for (unsigned int i = 0; i < numLeft * 3 / 2; i++) - { - cur_l = Common::swap16(m_buffer[(m_indexR + i * 2) & INDEX_MASK]); - cur_r = Common::swap16(m_buffer[(m_indexR + i * 2 + 1) & INDEX_MASK]); - - if (i % 3) - { - *pDest++ = (last_l + cur_r) / 2; - *pDest++ = (last_r + cur_r) / 2; - } - - last_l = cur_l; - last_r = cur_r; - } - - m_indexR += numLeft * 2 * 3 / 2; - } - else if (m_sampleRate > m_dspSampleRate) + else { // AyuanX: Up-sampling is not implemented yet PanicAlert("Mixer: Up-sampling is not implemented yet!"); @@ -143,16 +118,8 @@ unsigned int CMixer::Mix(short* samples, unsigned int numSamples) if (numSamples > numLeft) memset(&samples[numLeft * 2], 0, (numSamples - numLeft) * 4); - // Add the HLE sound - if (m_sampleRate < m_dspSampleRate) - { - PanicAlert("Mixer: DSPHLE down-sampling is not implemented yet!\n" - "Usually no game should require this, please report!"); - } - else - { - Premix(samples, numSamples, m_sampleRate); - } + // Add the DSPHLE sound, re-sampling is done inside + Premix(samples, numSamples); // Add the DTK Music if (m_EnableDTKMusic) @@ -161,19 +128,17 @@ unsigned int CMixer::Mix(short* samples, unsigned int numSamples) g_dspInitialize.pGetAudioStreaming(samples, numSamples, m_sampleRate); } - Common::AtomicAdd(m_numSamples, -(int)numLeft); + Common::AtomicAdd(m_numSamples, -(s32)numLeft); return numSamples; } -void CMixer::PushSamples(short *samples, unsigned int num_samples, unsigned int sample_rate) +void CMixer::PushSamples(short *samples, unsigned int num_samples) { // The auto throttle function. This loop will put a ceiling on the CPU MHz. if (m_throttle) { - // AyuanX: Remember to reserve "num_samples * 1.5" free sample space at least! - // Becuse we may do re-sampling later while (Common::AtomicLoad(m_numSamples) >= MAX_SAMPLES - RESERVED_SAMPLES) { if (g_dspInitialize.pEmulatorState) @@ -181,8 +146,12 @@ void CMixer::PushSamples(short *samples, unsigned int num_samples, unsigned int if (*g_dspInitialize.pEmulatorState != 0) break; } - soundStream->Update(); + // Shortcut key for Throttle Skipping + #ifdef _WIN32 + if (GetAsyncKeyState(VK_TAB)) break;; + #endif SLEEP(1); + soundStream->Update(); } } @@ -191,7 +160,7 @@ void CMixer::PushSamples(short *samples, unsigned int num_samples, unsigned int return; // AyuanX: Actual re-sampling work has been moved to sound thread - // to alleviates the workload on main thread + // to alleviate the workload on main thread // and we simply store raw data here to make fast mem copy int over_bytes = num_samples * 4 - (MAX_SAMPLES * 2 - (m_indexW & INDEX_MASK)) * sizeof(short); if (over_bytes > 0) @@ -206,12 +175,7 @@ void CMixer::PushSamples(short *samples, unsigned int num_samples, unsigned int m_indexW += num_samples * 2; - if (m_sampleRate < m_dspSampleRate) - { - // This is kind of tricky :P - num_samples = num_samples * 2 / 3; - } - else if (m_sampleRate > m_dspSampleRate) + if (m_sampleRate != 32000) { PanicAlert("Mixer: Up-sampling is not implemented yet!"); } diff --git a/Source/Core/AudioCommon/Src/Mixer.h b/Source/Core/AudioCommon/Src/Mixer.h index c6e50c4839..a3ebf94185 100644 --- a/Source/Core/AudioCommon/Src/Mixer.h +++ b/Source/Core/AudioCommon/Src/Mixer.h @@ -19,16 +19,16 @@ #define _MIXER_H_ // 16 bit Stereo -#define MAX_SAMPLES (1024 * 4) +#define MAX_SAMPLES (1024 * 8) #define INDEX_MASK (MAX_SAMPLES * 2 - 1) -#define RESERVED_SAMPLES (MAX_SAMPLES / 8) +#define RESERVED_SAMPLES (256) class CMixer { public: - CMixer(unsigned int AISampleRate = 48000, unsigned int DSPSampleRate = 48000) + CMixer(unsigned int AISampleRate = 48000, unsigned int DACSampleRate = 48000) : m_aiSampleRate(AISampleRate) - , m_dspSampleRate(DSPSampleRate) + , m_dacSampleRate(DACSampleRate) , m_bits(16) , m_channels(2) , m_HLEready(false) @@ -36,19 +36,21 @@ public: , m_indexW(0) , m_indexR(0) { - // AyuanX: When sample rate differs, we have to do re-sampling + // AyuanX: The internal (Core & DSP) sample rate is fixed at 32KHz + // So when AI/DAC sample rate differs than 32KHz, we have to do re-sampling // I perfer speed so let's do down-sampling instead of up-sampling // If you like better sound than speed, feel free to implement the up-sampling code - m_sampleRate = (m_aiSampleRate < m_dspSampleRate) ? m_aiSampleRate : m_dspSampleRate; + m_sampleRate = 32000; + NOTICE_LOG(AUDIO_INTERFACE, "Mixer is initialized (AISampleRate:%i, DACSampleRate:%i)", AISampleRate, DACSampleRate); } // Called from audio threads virtual unsigned int Mix(short* samples, unsigned int numSamples); - virtual void Premix(short *samples, unsigned int numSamples, unsigned int sampleRate) {} + virtual void Premix(short *samples, unsigned int numSamples) {} unsigned int GetNumSamples(); // Called from main thread - virtual void PushSamples(short* samples, unsigned int num_samples, unsigned int sample_rate); + virtual void PushSamples(short* samples, unsigned int num_samples); unsigned int GetSampleRate() {return m_sampleRate;} void SetThrottle(bool use) { m_throttle = use;} @@ -62,7 +64,7 @@ public: protected: unsigned int m_sampleRate; unsigned int m_aiSampleRate; - unsigned int m_dspSampleRate; + unsigned int m_dacSampleRate; int m_bits; int m_channels; diff --git a/Source/Core/AudioCommon/Src/NullSoundStream.h b/Source/Core/AudioCommon/Src/NullSoundStream.h index 7fc6aecd88..d5533d0d30 100644 --- a/Source/Core/AudioCommon/Src/NullSoundStream.h +++ b/Source/Core/AudioCommon/Src/NullSoundStream.h @@ -25,7 +25,7 @@ class NullMixer : public CMixer { public: virtual unsigned int Mix(short *samples, unsigned int numSamples) { return 0; } - virtual void PushSamples(short* samples, unsigned int num_samples, unsigned int sample_rate) {} + virtual void PushSamples(short* samples, unsigned int num_samples) {} }; class NullSound : public SoundStream diff --git a/Source/Core/AudioCommon/Src/OpenALStream.h b/Source/Core/AudioCommon/Src/OpenALStream.h index 9a469511b8..57bf2e34b7 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.h +++ b/Source/Core/AudioCommon/Src/OpenALStream.h @@ -35,9 +35,9 @@ #endif // WIN32 // 16 bit Stereo #define SFX_MAX_SOURCE 1 -#define OAL_NUM_BUFFERS 8 +#define OAL_NUM_BUFFERS 16 #define OAL_MAX_SAMPLES 512 // AyuanX: Don't make it too large, as larger buffer means longer delay -#define OAL_THRESHOLD 128 +#define OAL_THRESHOLD 128 // Some games are quite sensitive to delay #endif class OpenALStream: public SoundStream diff --git a/Source/Core/Common/Src/PluginDSP.h b/Source/Core/Common/Src/PluginDSP.h index 8427c32070..4fb658d0a1 100644 --- a/Source/Core/Common/Src/PluginDSP.h +++ b/Source/Core/Common/Src/PluginDSP.h @@ -27,7 +27,7 @@ typedef void (__cdecl* TDSP_WriteMailBox)(bool _CPUMailbox, unsigned short); typedef unsigned short (__cdecl* TDSP_ReadMailBox)(bool _CPUMailbox); typedef unsigned short (__cdecl* TDSP_ReadControlRegister)(); typedef unsigned short (__cdecl* TDSP_WriteControlRegister)(unsigned short); -typedef void (__cdecl *TDSP_SendAIBuffer)(unsigned int address, unsigned int num_samples, unsigned int sample_rate); +typedef void (__cdecl *TDSP_SendAIBuffer)(unsigned int address, unsigned int num_samples); typedef void (__cdecl *TDSP_Update)(int cycles); typedef void (__cdecl *TDSP_StopSoundStream)(); typedef void (__cdecl *TDSP_ClearAudioBuffer)(); diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index 7f7aca9567..bda22970cd 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -700,7 +700,7 @@ void Callback_VideoCopiedToXFB(bool video_update) while (Timer.GetTimeDifference() < wait_frametime * frames) { - if (no_framelimit==0) + if (no_framelimit == 0) Common::SleepCurrentThread(1); } } diff --git a/Source/Core/Core/Src/HW/AudioInterface.cpp b/Source/Core/Core/Src/HW/AudioInterface.cpp index 0452e1c670..edfb20b741 100644 --- a/Source/Core/Core/Src/HW/AudioInterface.cpp +++ b/Source/Core/Core/Src/HW/AudioInterface.cpp @@ -54,13 +54,13 @@ union AICR struct { unsigned PSTAT : 1; // sample counter/playback enable - unsigned AFR : 1; // AI Frequency (0=32khz 1=48khz) + unsigned AIFR : 1; // AI Frequency (0=32khz 1=48khz) unsigned AIINTMSK : 1; // 0=interrupt masked 1=interrupt enabled unsigned AIINT : 1; // audio interrupt status unsigned AIINTVLD : 1; // This bit controls whether AIINT is affected by the AIIT register // matching AISLRCNT. Once set, AIINT will hold unsigned SCRESET : 1; // write to reset counter - unsigned DSPFR : 1; // DSP Frequency (0=48khz 1=32khz) + unsigned DACFR : 1; // DAC Frequency (0=48khz 1=32khz) unsigned :25; }; u32 hex; @@ -90,16 +90,16 @@ struct SAudioRegister // STATE_TO_SAVE static SAudioRegister g_AudioRegister; static u64 g_LastCPUTime = 0; -static unsigned int g_SampleRate = 32000; -static unsigned int g_DSPSampleRate = 32000; +static unsigned int g_AISampleRate = 32000; +static unsigned int g_DACSampleRate = 32000; static u64 g_CPUCyclesPerSample = 0xFFFFFFFFFFFULL; void DoState(PointerWrap &p) { p.Do(g_AudioRegister); p.Do(g_LastCPUTime); - p.Do(g_SampleRate); - p.Do(g_DSPSampleRate); + p.Do(g_AISampleRate); + p.Do(g_DACSampleRate); p.Do(g_CPUCyclesPerSample); } @@ -111,7 +111,7 @@ void ReadStreamBlock(short* _pPCM); void Init() { g_AudioRegister.m_SampleCounter = 0; - g_AudioRegister.m_Control.AFR = 1; + g_AudioRegister.m_Control.AIFR = 1; } void Shutdown() @@ -169,22 +169,22 @@ void Write32(const u32 _Value, const u32 _Address) g_AudioRegister.m_Control.AIINTVLD = tmpAICtrl.AIINTVLD; // Set frequency - if (tmpAICtrl.AFR != g_AudioRegister.m_Control.AFR) + if (tmpAICtrl.AIFR != g_AudioRegister.m_Control.AIFR) { - INFO_LOG(AUDIO_INTERFACE, "Change Freq to %s", tmpAICtrl.AFR ? "48khz":"32khz"); - g_AudioRegister.m_Control.AFR = tmpAICtrl.AFR; + INFO_LOG(AUDIO_INTERFACE, "Change Freq to %s", tmpAICtrl.AIFR ? "48khz":"32khz"); + g_AudioRegister.m_Control.AIFR = tmpAICtrl.AIFR; } // Set DSP frequency - if (tmpAICtrl.DSPFR != g_AudioRegister.m_Control.DSPFR) + if (tmpAICtrl.DACFR != g_AudioRegister.m_Control.DACFR) { - INFO_LOG(AUDIO_INTERFACE, "AI_CONTROL_REGISTER: Change DSPFR Freq to %s", tmpAICtrl.DSPFR ? "48khz":"32khz"); - g_AudioRegister.m_Control.DSPFR = tmpAICtrl.DSPFR; + INFO_LOG(AUDIO_INTERFACE, "AI_CONTROL_REGISTER: Change DSPFR Freq to %s", tmpAICtrl.DACFR ? "48khz":"32khz"); + g_AudioRegister.m_Control.DACFR = tmpAICtrl.DACFR; } - g_SampleRate = tmpAICtrl.AFR ? 48000 : 32000; - g_DSPSampleRate = tmpAICtrl.DSPFR ? 32000 : 48000; + g_AISampleRate = tmpAICtrl.AIFR ? 48000 : 32000; + g_DACSampleRate = tmpAICtrl.DACFR ? 32000 : 48000; - g_CPUCyclesPerSample = SystemTimers::GetTicksPerSecond() / g_SampleRate; + g_CPUCyclesPerSample = SystemTimers::GetTicksPerSecond() / g_AISampleRate; // Streaming counter if (tmpAICtrl.PSTAT != g_AudioRegister.m_Control.PSTAT) @@ -264,10 +264,10 @@ void GenerateAudioInterrupt() UpdateInterrupts(); } -void Callback_GetSampleRate(unsigned int &_AISampleRate, unsigned int &_DSPSampleRate) +void Callback_GetSampleRate(unsigned int &_AISampleRate, unsigned int &_DACSampleRate) { - _AISampleRate = g_SampleRate; - _DSPSampleRate = g_DSPSampleRate; + _AISampleRate = g_AISampleRate; + _DACSampleRate = g_DACSampleRate; } // Callback for the disc streaming @@ -282,12 +282,12 @@ unsigned int Callback_GetStreaming(short* _pDestBuffer, unsigned int _numSamples const int rvolume = g_AudioRegister.m_Volume.rightVolume; - if (g_SampleRate == 48000 && _sampleRate == 32000) + if (g_AISampleRate == 48000 && _sampleRate == 32000) { _dbg_assert_msg_(AUDIO_INTERFACE, !(_numSamples % 2), "Number of Samples: %i must be even!", _numSamples); _numSamples = _numSamples * 3 / 2; } - else if (g_SampleRate == 32000 && _sampleRate == 48000) + else if (g_AISampleRate == 32000 && _sampleRate == 48000) { // AyuanX: Up-sampling is not implemented yet PanicAlert("AUDIO_INTERFACE: Up-sampling is not implemented yet!"); @@ -299,7 +299,7 @@ unsigned int Callback_GetStreaming(short* _pDestBuffer, unsigned int _numSamples if (pos == 0) ReadStreamBlock(pcm); - if (g_SampleRate == 48000 && _sampleRate == 32000) + if (g_AISampleRate == 48000 && _sampleRate == 32000) { if (i % 3) { @@ -393,16 +393,6 @@ void IncreaseSampleCount(const u32 _iAmount) } } -unsigned int GetAISampleRate() -{ - return g_SampleRate; -} - -unsigned int GetDSPSampleRate() -{ - return g_DSPSampleRate; -} - void Update() { // update timer diff --git a/Source/Core/Core/Src/HW/AudioInterface.h b/Source/Core/Core/Src/HW/AudioInterface.h index d37623f4f8..e4cb463b1b 100644 --- a/Source/Core/Core/Src/HW/AudioInterface.h +++ b/Source/Core/Core/Src/HW/AudioInterface.h @@ -34,16 +34,12 @@ void DoState(PointerWrap &p); void Update(); // Called by DSP plugin -void Callback_GetSampleRate(unsigned int &_AISampleRate, unsigned int &_DSPSampleRate); +void Callback_GetSampleRate(unsigned int &_AISampleRate, unsigned int &_DACSampleRate); unsigned int Callback_GetStreaming(short* _pDestBuffer, unsigned int _numSamples, unsigned int _sampleRate = 48000); void Read32(u32& _uReturnValue, const u32 _iAddress); void Write32(const u32 _iValue, const u32 _iAddress); -// Get the audio rates (48000 or 32000 only) -unsigned int GetAISampleRate(); -unsigned int GetDSPSampleRate(); - } // namespace #endif diff --git a/Source/Core/Core/Src/HW/DSP.cpp b/Source/Core/Core/Src/HW/DSP.cpp index ce1046d30c..18bb6a5af8 100644 --- a/Source/Core/Core/Src/HW/DSP.cpp +++ b/Source/Core/Core/Src/HW/DSP.cpp @@ -484,17 +484,17 @@ void UpdateAudioDMA() // AyuanX: let's do it in a bundle to speed up if (g_audioDMA.BlocksLeft == g_audioDMA.AudioDMAControl.NumBlocks) - dsp_plugin->DSP_SendAIBuffer(g_audioDMA.SourceAddress, g_audioDMA.AudioDMAControl.NumBlocks * 8, AudioInterface::GetDSPSampleRate()); + dsp_plugin->DSP_SendAIBuffer(g_audioDMA.SourceAddress, g_audioDMA.AudioDMAControl.NumBlocks * 8); // g_audioDMA.ReadAddress += 32; g_audioDMA.BlocksLeft--; if (g_audioDMA.BlocksLeft == 0) { + GenerateDSPInterrupt(DSP::INT_AID); // g_audioDMA.ReadAddress = g_audioDMA.SourceAddress; g_audioDMA.BlocksLeft = g_audioDMA.AudioDMAControl.NumBlocks; // DEBUG_LOG(DSPLLE, "ADMA read addresses: %08x", g_audioDMA.ReadAddress); - GenerateDSPInterrupt(DSP::INT_AID); } } else diff --git a/Source/Core/Core/Src/HW/SystemTimers.cpp b/Source/Core/Core/Src/HW/SystemTimers.cpp index edfcbe4d4b..db4367b547 100644 --- a/Source/Core/Core/Src/HW/SystemTimers.cpp +++ b/Source/Core/Core/Src/HW/SystemTimers.cpp @@ -112,7 +112,7 @@ int et_Dec; int et_VI; int et_SI; int et_AI; -int et_AudioFifo; +int et_AudioDMA; int et_DSP; int et_IPC_HLE; int et_FakeGPWD; // DC watchdog hack @@ -127,6 +127,9 @@ int // These shouldn't be period controlled either, most likely. DSP_PERIOD, + // This is a fixed value, don't change it + AUDIO_DMA_PERIOD, + // This is completely arbitrary. If we find that we need lower latency, we can just // increase this number. IPC_HLE_PERIOD, @@ -165,12 +168,10 @@ void DSPCallback(u64 userdata, int cyclesLate) CoreTiming::ScheduleEvent(DSP_PERIOD - cyclesLate, et_DSP); } -void AudioFifoCallback(u64 userdata, int cyclesLate) +void AudioDMACallback(u64 userdata, int cyclesLate) { - int period = CPU_CORE_CLOCK / (AudioInterface::GetDSPSampleRate() * 4 / 32); DSP::UpdateAudioDMA(); // Push audio to speakers. - - CoreTiming::ScheduleEvent(period - cyclesLate, et_AudioFifo); + CoreTiming::ScheduleEvent(AUDIO_DMA_PERIOD - cyclesLate, et_AudioDMA); } void IPC_HLE_UpdateCallback(u64 userdata, int cyclesLate) @@ -275,6 +276,9 @@ void Init() // This is the biggest question mark. AI_PERIOD = GetTicksPerSecond() / 80; + // System internal sample rate is fixed at 32KHz + AUDIO_DMA_PERIOD = CPU_CORE_CLOCK / (32000 * 4 / 32); + Common::Timer::IncreaseResolution(); // store and convert localtime at boot to timebase ticks startTimeBaseTicks = (u64)(CPU_CORE_CLOCK / TIMER_RATIO) * (u64)CEXIIPL::GetGCTime(); @@ -284,7 +288,7 @@ void Init() et_VI = CoreTiming::RegisterEvent("VICallback", VICallback); et_SI = CoreTiming::RegisterEvent("SICallback", SICallback); et_DSP = CoreTiming::RegisterEvent("DSPCallback", DSPCallback); - et_AudioFifo = CoreTiming::RegisterEvent("AudioFifoCallback", AudioFifoCallback); + et_AudioDMA = CoreTiming::RegisterEvent("AudioDMACallback", AudioDMACallback); et_IPC_HLE = CoreTiming::RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback); // Always register this. Increases chances of DC/SC save state compatibility. et_FakeGPWD = CoreTiming::RegisterEvent("FakeGPWatchdogCallback", FakeGPWatchdogCallback); @@ -294,7 +298,7 @@ void Init() CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerLine(), et_VI); CoreTiming::ScheduleEvent(DSP_PERIOD, et_DSP); CoreTiming::ScheduleEvent(GetTicksPerSecond() / 60, et_SI); - CoreTiming::ScheduleEvent(CPU_CORE_CLOCK / (32000 * 4 / 32), et_AudioFifo); + CoreTiming::ScheduleEvent(AUDIO_DMA_PERIOD, et_AudioDMA); // For DC watchdog hack if (Core::GetStartupParameter().bCPUThread) diff --git a/Source/Core/DSPCore/Src/DSPCore.h b/Source/Core/DSPCore/Src/DSPCore.h index 970836b265..09fce15e82 100644 --- a/Source/Core/DSPCore/Src/DSPCore.h +++ b/Source/Core/DSPCore/Src/DSPCore.h @@ -141,6 +141,7 @@ // cr (Not g_dsp.r[CR]) bits // See HW/DSP.cpp. #define CR_HALT 0x0004 +#define CR_INIT 0x0400 #define CR_EXTERNAL_INT 0x0002 diff --git a/Source/Core/DolphinWX/Src/ConfigMain.cpp b/Source/Core/DolphinWX/Src/ConfigMain.cpp index fa61fb0837..05abca1ae8 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.cpp +++ b/Source/Core/DolphinWX/Src/ConfigMain.cpp @@ -286,7 +286,7 @@ void CConfigMain::CreateGUIControls() wxT("\nIt can be convenient in a Wii game that already has a cursor.")); WiimoteStatusLEDs->SetToolTip(wxT("Show which wiimotes are connected in the statusbar.")); WiimoteStatusSpeakers->SetToolTip(wxT("Show wiimote speaker status in the statusbar.")); - DSPThread->SetToolTip(wxT("This should be on when using HLE and off when using LLE.")); + DSPThread->SetToolTip(wxT("Run DSPLLE on a dedicate thread, this has no affect on DSPHLE.")); CPUThread->SetToolTip(wxT("This splits the Video and CPU threads, so they can be run on separate cores.") wxT("\nCauses major speed improvements on PCs with more than one core,") wxT("\nbut can also cause occasional crashes/glitches.")); diff --git a/Source/PluginSpecs/pluginspecs_dsp.h b/Source/PluginSpecs/pluginspecs_dsp.h index feb4ec6b3f..5a58cc59d6 100644 --- a/Source/PluginSpecs/pluginspecs_dsp.h +++ b/Source/PluginSpecs/pluginspecs_dsp.h @@ -17,7 +17,7 @@ typedef const char* (*TName)(void); typedef void (*TDebuggerBreak)(void); typedef void (*TGenerateDSPInt)(void); typedef unsigned int (*TAudioGetStreaming)(short* _pDestBuffer, unsigned int _numSamples, unsigned int _sampleRate); -typedef void (*TGetSampleRate)(unsigned int &AISampleRate, unsigned int &DSPSampleRate); +typedef void (*TGetSampleRate)(unsigned int &AISampleRate, unsigned int &DACSampleRate); typedef struct { @@ -98,9 +98,8 @@ EXPORT void CALL DSP_Update(int cycles); // Purpose: This function sends the current AI Buffer to the DSP plugin // input: _Address : Memory-Address // input: _Number : Number of the Samples -// input: _Rate : Sample Rate 32000/48000 // -EXPORT void CALL DSP_SendAIBuffer(unsigned int address, unsigned int num_samples, unsigned int sample_rate); +EXPORT void CALL DSP_SendAIBuffer(unsigned int address, unsigned int num_samples); // __________________________________________________________________________________________________ // Function: DSP_StopSoundStream diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/ConfigDlg.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/ConfigDlg.cpp index ff98a92ce4..fab41cbff3 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/ConfigDlg.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/ConfigDlg.cpp @@ -58,10 +58,9 @@ DSPConfigDialogHLE::DSPConfigDialogHLE(wxWindow *parent, wxWindowID id, const wx m_buttonEnableDTKMusic->SetToolTip(wxT("This is used to play music tracks, like BGM.")); m_buttonEnableThrottle->SetToolTip(wxT("This is used to control game speed by sound throttle.\n") wxT("Disabling this could cause abnormal game speed, such as too fast.\n") - wxT("But sometimes enabling this causes constant noise.")); - + wxT("But sometimes enabling this could cause constant noise.\n") + wxT("\nKeyboard Shortcut : Hold down to instantly disable Throttle.")); m_buttonEnableRE0Fix->SetToolTip(wxT("This fixes audio in Resident Evil Zero and maybe some other games.")); - m_BackendSelection->SetToolTip(wxT("Changing this will have no effect while the emulator is running!")); // Create sizer and add items to dialog diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/HLEMixer.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/HLEMixer.cpp index d810467180..4f3566322d 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/HLEMixer.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/HLEMixer.cpp @@ -20,7 +20,7 @@ #include "DSPHandler.h" #include "HLEMixer.h" -void HLEMixer::Premix(short *samples, unsigned int numSamples, unsigned int sampleRate) +void HLEMixer::Premix(short *samples, unsigned int numSamples) { // if this was called directly from the HLE if (g_Config.m_EnableHLEAudio && IsHLEReady()) diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/HLEMixer.h b/Source/Plugins/Plugin_DSP_HLE/Src/HLEMixer.h index 4687ac4ae4..575ea618e6 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/HLEMixer.h +++ b/Source/Plugins/Plugin_DSP_HLE/Src/HLEMixer.h @@ -6,10 +6,10 @@ class HLEMixer : public CMixer { public: - HLEMixer(unsigned int AISampleRate = 48000, unsigned int DSPSampleRate = 48000) - : CMixer(AISampleRate, DSPSampleRate) {}; + HLEMixer(unsigned int AISampleRate = 48000, unsigned int DACSampleRate = 48000) + : CMixer(AISampleRate, DACSampleRate) {}; - virtual void Premix(short *samples, unsigned int numSamples, unsigned int sampleRate); + virtual void Premix(short *samples, unsigned int numSamples); }; #endif // HLEMIXER_H diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/main.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/main.cpp index 24936857dc..0a1dc4d508 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/main.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/main.cpp @@ -307,9 +307,9 @@ unsigned short DSP_WriteControlRegister(unsigned short _Value) { if (!Temp.DSPHalt && Temp.DSPInit) { - unsigned int AISampleRate, DSPSampleRate; - g_dspInitialize.pGetSampleRate(AISampleRate, DSPSampleRate); - soundStream = AudioCommon::InitSoundStream(new HLEMixer(AISampleRate, DSPSampleRate)); + unsigned int AISampleRate, DACSampleRate; + g_dspInitialize.pGetSampleRate(AISampleRate, DACSampleRate); + soundStream = AudioCommon::InitSoundStream(new HLEMixer(AISampleRate, DACSampleRate)); if(!soundStream) PanicAlert("Error starting up sound stream"); // Mixer is initialized g_InitMixer = true; @@ -334,7 +334,7 @@ void DSP_Update(int cycles) inside Mixer_PushSamples(), 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 DSP_SendAIBuffer(unsigned int address, unsigned int num_samples, unsigned int sample_rate) +void DSP_SendAIBuffer(unsigned int address, unsigned int num_samples) { if (!soundStream) return; @@ -344,9 +344,8 @@ void DSP_SendAIBuffer(unsigned int address, unsigned int num_samples, unsigned i if (pMixer && address) { short* samples = (short*)Memory_Get_Pointer(address); - // sample_rate could be 32khz/48khz here, - // see Core/DSP/DSP.cpp for better information - pMixer->PushSamples(samples, num_samples, sample_rate); + // Internal sample rate is always 32khz + pMixer->PushSamples(samples, num_samples); // FIXME: Write the audio to a file //if (log_ai) diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/DSPConfigDlgLLE.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/DSPConfigDlgLLE.cpp index 8e6499e0e1..376e207016 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/DSPConfigDlgLLE.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/DSPConfigDlgLLE.cpp @@ -39,7 +39,7 @@ DSPConfigDialogLLE::DSPConfigDialogLLE(wxWindow *parent, wxWindowID id, const wx // Create items m_buttonEnableDTKMusic = new wxCheckBox(this, ID_ENABLE_DTK_MUSIC, wxT("Enable DTK Music"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - m_buttonEnableThrottle = new wxCheckBox(this, ID_ENABLE_THROTTLE, wxT("Enable Other Audio (Throttle)"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_buttonEnableThrottle = new wxCheckBox(this, ID_ENABLE_THROTTLE, wxT("Enable Audio Throttle"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); wxStaticText *BackendText = new wxStaticText(this, wxID_ANY, wxT("Audio Backend"), wxDefaultPosition, wxDefaultSize, 0); m_BackendSelection = new wxComboBox(this, ID_BACKEND, wxEmptyString, wxDefaultPosition, wxSize(90, 20), wxArrayBackends, wxCB_READONLY, wxDefaultValidator); @@ -51,10 +51,11 @@ DSPConfigDialogLLE::DSPConfigDialogLLE(wxWindow *parent, wxWindowID id, const wx m_buttonEnableThrottle->SetValue(ac_Config.m_EnableThrottle ? true : false); // Add tooltips - m_buttonEnableDTKMusic->SetToolTip(wxT("This is sometimes used to play music tracks from the disc")); - m_buttonEnableThrottle->SetToolTip(wxT("This is sometimes used together with pre-rendered movies.\n") - wxT("Disabling this also disables the speed throttle which this causes,\n") - wxT("meaning that there will be no upper limit on your FPS.")); + m_buttonEnableDTKMusic->SetToolTip(wxT("This is used to play music tracks, like BGM.")); + m_buttonEnableThrottle->SetToolTip(wxT("This is used to control game speed by sound throttle.\n") + wxT("Disabling this could cause abnormal game speed, such as too fast.\n") + wxT("But sometimes enabling this could cause constant noise.\n") + wxT("\nKeyboard Shortcut : Hold down to instantly disable Throttle.")); m_BackendSelection->SetToolTip(wxT("Changing this will have no effect while the emulator is running!")); // Create sizer and add items to dialog diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp index 854e8e9f13..982fed7deb 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp @@ -263,9 +263,9 @@ u16 DSP_WriteControlRegister(u16 _uFlag) { if (!Temp.DSPHalt && Temp.DSPInit) { - unsigned int AISampleRate, DSPSampleRate; - g_dspInitialize.pGetSampleRate(AISampleRate, DSPSampleRate); - soundStream = AudioCommon::InitSoundStream(new CMixer(AISampleRate, DSPSampleRate)); + unsigned int AISampleRate, DACSampleRate; + g_dspInitialize.pGetSampleRate(AISampleRate, DACSampleRate); + soundStream = AudioCommon::InitSoundStream(new CMixer(AISampleRate, DACSampleRate)); if(!soundStream) PanicAlert("Error starting up sound stream"); // Mixer is initialized g_InitMixer = true; @@ -334,6 +334,8 @@ void DSP_WriteMailboxLow(bool _CPUMailbox, u16 _uLowMail) void DSP_Update(int cycles) { +// Sound stream update job has been handled by AudioDMA routine, which is more efficient +/* // This gets called VERY OFTEN. The soundstream update might be expensive so only do it 200 times per second or something. int cycles_between_ss_update; @@ -350,7 +352,7 @@ void DSP_Update(int cycles) cycle_count -= cycles_between_ss_update; soundStream->Update(); } - +*/ // If we're not on a thread, run cycles here. if (!g_dspInitialize.bOnThread) { @@ -358,7 +360,7 @@ void DSP_Update(int cycles) } } -void DSP_SendAIBuffer(unsigned int address, unsigned int num_samples, unsigned int sample_rate) +void DSP_SendAIBuffer(unsigned int address, unsigned int num_samples) { if (!soundStream) return; @@ -369,7 +371,7 @@ void DSP_SendAIBuffer(unsigned int address, unsigned int num_samples, unsigned i { short* samples = (short*)Memory_Get_Pointer(address); - pMixer->PushSamples(samples, num_samples, sample_rate); + pMixer->PushSamples(samples, num_samples); } soundStream->Update();