diff --git a/Source/Core/Core/Src/HW/AudioInterface.cpp b/Source/Core/Core/Src/HW/AudioInterface.cpp index 0a33e7c773..15e1f0bb29 100644 --- a/Source/Core/Core/Src/HW/AudioInterface.cpp +++ b/Source/Core/Core/Src/HW/AudioInterface.cpp @@ -145,6 +145,8 @@ static void GenerateAudioInterrupt(); static void UpdateInterrupts(); static void IncreaseSampleCount(const u32 _uAmount); void ReadStreamBlock(s16* _pPCM); +u64 GetAIPeriod(); +int et_AI; void Init() { @@ -159,6 +161,8 @@ void Init() g_AISSampleRate = 48000; g_AIDSampleRate = 32000; + + et_AI = CoreTiming::RegisterEvent("AICallback", Update); } void Shutdown() @@ -178,11 +182,8 @@ void Read32(u32& _rReturnValue, const u32 _Address) break; case AI_SAMPLE_COUNTER: + Update(0, 0); _rReturnValue = m_SampleCounter; - // HACK - AI SRC init will do while (oldval == sample_counter) {} - // in order to pass this, we need to increment the counter whenever read - if (m_Control.PSTAT) - m_SampleCounter++; break; case AI_INTERRUPT_TIMING: @@ -236,6 +237,9 @@ void Write32(const u32 _Value, const u32 _Address) // Tell Drive Interface to start/stop streaming DVDInterface::g_bStream = tmpAICtrl.PSTAT; + + CoreTiming::RemoveEvent(et_AI); + CoreTiming::ScheduleEvent(((int)GetAIPeriod() / 2), et_AI); } // AI Interrupt @@ -271,6 +275,8 @@ void Write32(const u32 _Value, const u32 _Address) case AI_INTERRUPT_TIMING: m_InterruptTiming = _Value; + CoreTiming::RemoveEvent(et_AI); + CoreTiming::ScheduleEvent(((int)GetAIPeriod() / 2), et_AI); DEBUG_LOG(AUDIO_INTERFACE, "Set interrupt: %08x samples", m_InterruptTiming); break; @@ -448,7 +454,7 @@ unsigned int GetAIDSampleRate() return g_AIDSampleRate; } -void Update() +void Update(u64 userdata, int cyclesLate) { if (m_Control.PSTAT) { @@ -458,8 +464,17 @@ void Update() const u32 Samples = static_cast(Diff / g_CPUCyclesPerSample); g_LastCPUTime += Samples * g_CPUCyclesPerSample; IncreaseSampleCount(Samples); - } + } + CoreTiming::ScheduleEvent(((int)GetAIPeriod() / 2) - cyclesLate, et_AI); } } +u64 GetAIPeriod() +{ + u64 period = g_CPUCyclesPerSample * m_InterruptTiming; + if (period == 0) + period = 32000 * g_CPUCyclesPerSample; + return period; +} + } // end of namespace AudioInterface diff --git a/Source/Core/Core/Src/HW/AudioInterface.h b/Source/Core/Core/Src/HW/AudioInterface.h index 1504198621..06fd3aec79 100644 --- a/Source/Core/Core/Src/HW/AudioInterface.h +++ b/Source/Core/Core/Src/HW/AudioInterface.h @@ -31,7 +31,7 @@ void Init(); void Shutdown(); void DoState(PointerWrap &p); -void Update(); +void Update(u64 userdata, int cyclesLate); // Called by DSP emulator void Callback_GetSampleRate(unsigned int &_AISampleRate, unsigned int &_DACSampleRate); diff --git a/Source/Core/Core/Src/HW/DSP.cpp b/Source/Core/Core/Src/HW/DSP.cpp index 0ff8e2db49..78f8ab5ed0 100644 --- a/Source/Core/Core/Src/HW/DSP.cpp +++ b/Source/Core/Core/Src/HW/DSP.cpp @@ -47,6 +47,7 @@ #include "../PowerPC/PowerPC.h" #include "../ConfigManager.h" #include "../DSPEmulator.h" +#include "SystemTimers.h" namespace DSP { @@ -152,7 +153,7 @@ struct AudioDMA SourceAddress = 0; ReadAddress = 0; AudioDMAControl.Hex = 0; - BlocksLeft = 0; + BlocksLeft = 1; } }; @@ -355,7 +356,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) // AI case AUDIO_DMA_BLOCKS_LEFT: - _uReturnValue = g_audioDMA.BlocksLeft > 0 ? g_audioDMA.BlocksLeft - 1 : 0; // AUDIO_DMA_BLOCKS_LEFT is zero based + _uReturnValue = g_audioDMA.BlocksLeft; break; case AUDIO_DMA_START_LO: @@ -665,7 +666,7 @@ void UpdateDSPSlice(int cycles) { // This happens at 4 khz, since 32 bytes at 4khz = 4 bytes at 32 khz (16bit stereo pcm) void UpdateAudioDMA() { - if (g_audioDMA.AudioDMAControl.Enable && g_audioDMA.BlocksLeft) + if (g_audioDMA.AudioDMAControl.Enable && g_audioDMA.BlocksLeft > -1) { // Read audio at g_audioDMA.ReadAddress in RAM and push onto an // external audio fifo in the emulator, to be mixed with the disc @@ -675,7 +676,7 @@ void UpdateAudioDMA() g_audioDMA.BlocksLeft--; g_audioDMA.ReadAddress += 32; - if (g_audioDMA.BlocksLeft == 0) + if (g_audioDMA.BlocksLeft == -1) { dsp_emulator->DSP_SendAIBuffer(g_audioDMA.SourceAddress, 8*g_audioDMA.AudioDMAControl.NumBlocks); GenerateDSPInterrupt(DSP::INT_AID); @@ -687,7 +688,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()); + dsp_emulator->DSP_SendAIBuffer(0, AudioInterface::GetAIDSampleRate()); } } diff --git a/Source/Core/Core/Src/HW/SystemTimers.cpp b/Source/Core/Core/Src/HW/SystemTimers.cpp index 10f5e3204e..27ba4a62f9 100644 --- a/Source/Core/Core/Src/HW/SystemTimers.cpp +++ b/Source/Core/Core/Src/HW/SystemTimers.cpp @@ -110,7 +110,6 @@ enum int et_Dec; int et_VI; int et_SI; -int et_AI; int et_CP; int et_AudioDMA; int et_DSP; @@ -120,9 +119,6 @@ int et_PatchEngine; // PatchEngine updates every 1/60th of a second by default // These are badly educated guesses // Feel free to experiment. Set these in Init below. int - // This one should simply be determined by the increasing counter in AI. - AI_PERIOD, - // These shouldn't be period controlled either, most likely. DSP_PERIOD, @@ -148,12 +144,6 @@ u32 ConvertMillisecondsToTicks(u32 _Milliseconds) return GetTicksPerSecond() / 1000 * _Milliseconds; } -void AICallback(u64 userdata, int cyclesLate) -{ - AudioInterface::Update(); - CoreTiming::ScheduleEvent(AI_PERIOD - cyclesLate, et_AI); -} - // DSP/CPU timeslicing. void DSPCallback(u64 userdata, int cyclesLate) { @@ -277,9 +267,6 @@ void Init() if (DSP::GetDSPEmulator()->IsLLE()) DSP_PERIOD = 12000; // TO BE TWEAKED - // This is the biggest question mark. - AI_PERIOD = GetTicksPerSecond() / 80; - // System internal sample rate is fixed at 32KHz * 4 (16bit Stereo) / 32 bytes DMA AUDIO_DMA_PERIOD = CPU_CORE_CLOCK / (AudioInterface::GetAIDSampleRate() * 4 / 32); @@ -295,7 +282,6 @@ void Init() CoreTiming::SetFakeDecStartTicks(CoreTiming::GetTicks()); et_Dec = CoreTiming::RegisterEvent("DecCallback", DecrementerCallback); - et_AI = CoreTiming::RegisterEvent("AICallback", AICallback); et_VI = CoreTiming::RegisterEvent("VICallback", VICallback); et_SI = CoreTiming::RegisterEvent("SICallback", SICallback); if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSyncGPU) @@ -305,7 +291,6 @@ void Init() et_IPC_HLE = CoreTiming::RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback); et_PatchEngine = CoreTiming::RegisterEvent("PatchEngine", PatchEngineCallback); - CoreTiming::ScheduleEvent(AI_PERIOD, et_AI); CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerLine(), et_VI); CoreTiming::ScheduleEvent(DSP_PERIOD, et_DSP); CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_SI);