HW/AudioInterface: Refactor to class.

This commit is contained in:
Admiral H. Curtiss 2023-03-08 23:26:31 +01:00
parent 2856723bc1
commit d638d2dcb7
No known key found for this signature in database
GPG Key ID: F051B4C4044F33FB
8 changed files with 228 additions and 238 deletions

View File

@ -70,356 +70,277 @@ enum
AID_48KHz = 0
};
enum class SampleRate
{
AI32KHz,
AI48KHz,
};
// AI Control Register
union AICR
{
AICR() = default;
explicit AICR(u32 hex_) : hex{hex_} {}
struct
{
u32 PSTAT : 1; // sample counter/playback enable
u32 AISFR : 1; // AIS Frequency (0=32khz 1=48khz)
u32 AIINTMSK : 1; // 0=interrupt masked 1=interrupt enabled
u32 AIINT : 1; // audio interrupt status
u32 AIINTVLD : 1; // This bit controls whether AIINT is affected by the Interrupt Timing
// register
// matching the sample counter. Once set, AIINT will hold its last value
u32 SCRESET : 1; // write to reset counter
u32 AIDFR : 1; // AID Frequency (0=48khz 1=32khz)
u32 : 25;
};
u32 hex = 0;
};
// AI Volume Register
union AIVR
{
struct
{
u32 left : 8;
u32 right : 8;
u32 : 16;
};
u32 hex = 0;
};
struct AudioInterfaceState::Data
{
// Registers
AICR control;
AIVR volume;
u32 sample_counter = 0;
u32 interrupt_timing = 0;
u64 last_cpu_time = 0;
u64 cpu_cycles_per_sample = 0;
u32 ais_sample_rate_divisor = Mixer::FIXED_SAMPLE_RATE_DIVIDEND / 48000;
u32 aid_sample_rate_divisor = Mixer::FIXED_SAMPLE_RATE_DIVIDEND / 32000;
CoreTiming::EventType* event_type_ai = nullptr;
};
AudioInterfaceState::AudioInterfaceState() : m_data(std::make_unique<Data>())
AudioInterfaceManager::AudioInterfaceManager(Core::System& system)
: m_ais_sample_rate_divisor(Mixer::FIXED_SAMPLE_RATE_DIVIDEND / 48000),
m_aid_sample_rate_divisor(Mixer::FIXED_SAMPLE_RATE_DIVIDEND / 32000), m_system(system)
{
}
AudioInterfaceState::~AudioInterfaceState() = default;
AudioInterfaceManager::~AudioInterfaceManager() = default;
void DoState(PointerWrap& p)
void AudioInterfaceManager::DoState(PointerWrap& p)
{
auto& system = Core::System::GetInstance();
auto& state = system.GetAudioInterfaceState().GetData();
p.Do(m_control);
p.Do(m_volume);
p.Do(m_sample_counter);
p.Do(m_interrupt_timing);
p.Do(m_last_cpu_time);
p.Do(m_ais_sample_rate_divisor);
p.Do(m_aid_sample_rate_divisor);
p.Do(m_cpu_cycles_per_sample);
p.Do(state.control);
p.Do(state.volume);
p.Do(state.sample_counter);
p.Do(state.interrupt_timing);
p.Do(state.last_cpu_time);
p.Do(state.ais_sample_rate_divisor);
p.Do(state.aid_sample_rate_divisor);
p.Do(state.cpu_cycles_per_sample);
SoundStream* sound_stream = system.GetSoundStream();
SoundStream* sound_stream = m_system.GetSoundStream();
sound_stream->GetMixer()->DoState(p);
}
namespace
void AudioInterfaceManager::UpdateInterrupts()
{
void UpdateInterrupts()
{
auto& system = Core::System::GetInstance();
auto& state = system.GetAudioInterfaceState().GetData();
system.GetProcessorInterface().SetInterrupt(ProcessorInterface::INT_CAUSE_AI,
state.control.AIINT & state.control.AIINTMSK);
m_system.GetProcessorInterface().SetInterrupt(ProcessorInterface::INT_CAUSE_AI,
m_control.AIINT & m_control.AIINTMSK);
}
void GenerateAudioInterrupt()
void AudioInterfaceManager::GenerateAudioInterrupt()
{
auto& state = Core::System::GetInstance().GetAudioInterfaceState().GetData();
state.control.AIINT = 1;
m_control.AIINT = 1;
UpdateInterrupts();
}
void IncreaseSampleCount(const u32 amount)
void AudioInterfaceManager::IncreaseSampleCount(const u32 amount)
{
if (!IsPlaying())
return;
auto& system = Core::System::GetInstance();
auto& state = system.GetAudioInterfaceState().GetData();
const u32 old_sample_counter = m_sample_counter + 1;
m_sample_counter += amount;
const u32 old_sample_counter = state.sample_counter + 1;
state.sample_counter += amount;
if ((state.interrupt_timing - old_sample_counter) <= (state.sample_counter - old_sample_counter))
if ((m_interrupt_timing - old_sample_counter) <= (m_sample_counter - old_sample_counter))
{
DEBUG_LOG_FMT(AUDIO_INTERFACE,
"GenerateAudioInterrupt {:08x}:{:08x} at PC {:08x} control.AIINTVLD={}",
state.sample_counter, state.interrupt_timing, system.GetPPCState().pc,
state.control.AIINTVLD);
DEBUG_LOG_FMT(
AUDIO_INTERFACE, "GenerateAudioInterrupt {:08x}:{:08x} at PC {:08x} control.AIINTVLD={}",
m_sample_counter, m_interrupt_timing, m_system.GetPPCState().pc, m_control.AIINTVLD);
GenerateAudioInterrupt();
}
}
int GetAIPeriod()
int AudioInterfaceManager::GetAIPeriod() const
{
auto& state = Core::System::GetInstance().GetAudioInterfaceState().GetData();
u64 period = state.cpu_cycles_per_sample * (state.interrupt_timing - state.sample_counter);
u64 s_period = state.cpu_cycles_per_sample * Mixer::FIXED_SAMPLE_RATE_DIVIDEND /
state.ais_sample_rate_divisor;
u64 period = m_cpu_cycles_per_sample * (m_interrupt_timing - m_sample_counter);
u64 s_period =
m_cpu_cycles_per_sample * Mixer::FIXED_SAMPLE_RATE_DIVIDEND / m_ais_sample_rate_divisor;
if (period == 0)
return static_cast<int>(s_period);
return static_cast<int>(std::min(period, s_period));
}
static void Update(Core::System& system, u64 userdata, s64 cycles_late)
void AudioInterfaceManager::GlobalUpdate(Core::System& system, u64 userdata, s64 cycles_late)
{
system.GetAudioInterface().Update(userdata, cycles_late);
}
void AudioInterfaceManager::Update(u64 userdata, s64 cycles_late)
{
if (!IsPlaying())
return;
auto& state = system.GetAudioInterfaceState().GetData();
auto& core_timing = system.GetCoreTiming();
auto& core_timing = m_system.GetCoreTiming();
const u64 diff = core_timing.GetTicks() - state.last_cpu_time;
if (diff > state.cpu_cycles_per_sample)
const u64 diff = core_timing.GetTicks() - m_last_cpu_time;
if (diff > m_cpu_cycles_per_sample)
{
const u32 samples = static_cast<u32>(diff / state.cpu_cycles_per_sample);
state.last_cpu_time += samples * state.cpu_cycles_per_sample;
const u32 samples = static_cast<u32>(diff / m_cpu_cycles_per_sample);
m_last_cpu_time += samples * m_cpu_cycles_per_sample;
IncreaseSampleCount(samples);
}
core_timing.ScheduleEvent(GetAIPeriod() - cycles_late, state.event_type_ai);
core_timing.ScheduleEvent(GetAIPeriod() - cycles_late, m_event_type_ai);
}
void SetAIDSampleRate(SampleRate sample_rate)
void AudioInterfaceManager::SetAIDSampleRate(SampleRate sample_rate)
{
auto& state = Core::System::GetInstance().GetAudioInterfaceState().GetData();
if (sample_rate == SampleRate::AI32KHz)
{
state.control.AIDFR = AID_32KHz;
state.aid_sample_rate_divisor = Get32KHzSampleRateDivisor();
m_control.AIDFR = AID_32KHz;
m_aid_sample_rate_divisor = Get32KHzSampleRateDivisor();
}
else
{
state.control.AIDFR = AID_48KHz;
state.aid_sample_rate_divisor = Get48KHzSampleRateDivisor();
m_control.AIDFR = AID_48KHz;
m_aid_sample_rate_divisor = Get48KHzSampleRateDivisor();
}
SoundStream* sound_stream = Core::System::GetInstance().GetSoundStream();
sound_stream->GetMixer()->SetDMAInputSampleRateDivisor(state.aid_sample_rate_divisor);
SoundStream* sound_stream = m_system.GetSoundStream();
sound_stream->GetMixer()->SetDMAInputSampleRateDivisor(m_aid_sample_rate_divisor);
}
void SetAISSampleRate(SampleRate sample_rate)
void AudioInterfaceManager::SetAISSampleRate(SampleRate sample_rate)
{
auto& state = Core::System::GetInstance().GetAudioInterfaceState().GetData();
if (sample_rate == SampleRate::AI32KHz)
{
state.control.AISFR = AIS_32KHz;
state.ais_sample_rate_divisor = Get32KHzSampleRateDivisor();
m_control.AISFR = AIS_32KHz;
m_ais_sample_rate_divisor = Get32KHzSampleRateDivisor();
}
else
{
state.control.AISFR = AIS_48KHz;
state.ais_sample_rate_divisor = Get48KHzSampleRateDivisor();
m_control.AISFR = AIS_48KHz;
m_ais_sample_rate_divisor = Get48KHzSampleRateDivisor();
}
state.cpu_cycles_per_sample = static_cast<u64>(SystemTimers::GetTicksPerSecond()) *
state.ais_sample_rate_divisor / Mixer::FIXED_SAMPLE_RATE_DIVIDEND;
SoundStream* sound_stream = Core::System::GetInstance().GetSoundStream();
sound_stream->GetMixer()->SetStreamInputSampleRateDivisor(state.ais_sample_rate_divisor);
m_cpu_cycles_per_sample = static_cast<u64>(SystemTimers::GetTicksPerSecond()) *
m_ais_sample_rate_divisor / Mixer::FIXED_SAMPLE_RATE_DIVIDEND;
SoundStream* sound_stream = m_system.GetSoundStream();
sound_stream->GetMixer()->SetStreamInputSampleRateDivisor(m_ais_sample_rate_divisor);
}
} // namespace
void Init()
void AudioInterfaceManager::Init()
{
auto& system = Core::System::GetInstance();
auto& core_timing = system.GetCoreTiming();
auto& state = system.GetAudioInterfaceState().GetData();
state.control.hex = 0;
m_control.hex = 0;
SetAISSampleRate(SampleRate::AI48KHz);
SetAIDSampleRate(SampleRate::AI32KHz);
state.volume.hex = 0;
state.sample_counter = 0;
state.interrupt_timing = 0;
m_volume.hex = 0;
m_sample_counter = 0;
m_interrupt_timing = 0;
state.last_cpu_time = 0;
m_last_cpu_time = 0;
state.event_type_ai = core_timing.RegisterEvent("AICallback", Update);
m_event_type_ai = m_system.GetCoreTiming().RegisterEvent("AICallback", GlobalUpdate);
}
void Shutdown()
void AudioInterfaceManager::Shutdown()
{
}
void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
void AudioInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
{
auto& state = Core::System::GetInstance().GetAudioInterfaceState().GetData();
mmio->Register(
base | AI_CONTROL_REGISTER, MMIO::DirectRead<u32>(&state.control.hex),
base | AI_CONTROL_REGISTER, MMIO::DirectRead<u32>(&m_control.hex),
MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
const AICR tmp_ai_ctrl(val);
auto& core_timing = system.GetCoreTiming();
auto& state_ = system.GetAudioInterfaceState().GetData();
if (state_.control.AIINTMSK != tmp_ai_ctrl.AIINTMSK)
auto& ai = system.GetAudioInterface();
if (ai.m_control.AIINTMSK != tmp_ai_ctrl.AIINTMSK)
{
DEBUG_LOG_FMT(AUDIO_INTERFACE, "Change AIINTMSK to {}", tmp_ai_ctrl.AIINTMSK);
state_.control.AIINTMSK = tmp_ai_ctrl.AIINTMSK;
ai.m_control.AIINTMSK = tmp_ai_ctrl.AIINTMSK;
}
if (state_.control.AIINTVLD != tmp_ai_ctrl.AIINTVLD)
if (ai.m_control.AIINTVLD != tmp_ai_ctrl.AIINTVLD)
{
DEBUG_LOG_FMT(AUDIO_INTERFACE, "Change AIINTVLD to {}", tmp_ai_ctrl.AIINTVLD);
state_.control.AIINTVLD = tmp_ai_ctrl.AIINTVLD;
ai.m_control.AIINTVLD = tmp_ai_ctrl.AIINTVLD;
}
// Set frequency of streaming audio
if (tmp_ai_ctrl.AISFR != state_.control.AISFR)
if (tmp_ai_ctrl.AISFR != ai.m_control.AISFR)
{
// AISFR rates below are intentionally inverted wrt yagcd
DEBUG_LOG_FMT(AUDIO_INTERFACE, "Change AISFR to {}",
tmp_ai_ctrl.AISFR ? "48khz" : "32khz");
SetAISSampleRate(tmp_ai_ctrl.AISFR ? SampleRate::AI48KHz : SampleRate::AI32KHz);
ai.SetAISSampleRate(tmp_ai_ctrl.AISFR ? SampleRate::AI48KHz : SampleRate::AI32KHz);
}
// Set frequency of DMA
if (tmp_ai_ctrl.AIDFR != state_.control.AIDFR)
if (tmp_ai_ctrl.AIDFR != ai.m_control.AIDFR)
{
DEBUG_LOG_FMT(AUDIO_INTERFACE, "Change AIDFR to {}",
tmp_ai_ctrl.AIDFR ? "32khz" : "48khz");
SetAIDSampleRate(tmp_ai_ctrl.AIDFR ? SampleRate::AI32KHz : SampleRate::AI48KHz);
ai.SetAIDSampleRate(tmp_ai_ctrl.AIDFR ? SampleRate::AI32KHz : SampleRate::AI48KHz);
}
// Streaming counter
if (tmp_ai_ctrl.PSTAT != state_.control.PSTAT)
if (tmp_ai_ctrl.PSTAT != ai.m_control.PSTAT)
{
DEBUG_LOG_FMT(AUDIO_INTERFACE, "{} streaming audio",
tmp_ai_ctrl.PSTAT ? "start" : "stop");
state_.control.PSTAT = tmp_ai_ctrl.PSTAT;
state_.last_cpu_time = core_timing.GetTicks();
ai.m_control.PSTAT = tmp_ai_ctrl.PSTAT;
ai.m_last_cpu_time = core_timing.GetTicks();
core_timing.RemoveEvent(state_.event_type_ai);
core_timing.ScheduleEvent(GetAIPeriod(), state_.event_type_ai);
core_timing.RemoveEvent(ai.m_event_type_ai);
core_timing.ScheduleEvent(ai.GetAIPeriod(), ai.m_event_type_ai);
}
// AI Interrupt
if (tmp_ai_ctrl.AIINT)
{
DEBUG_LOG_FMT(AUDIO_INTERFACE, "Clear AIS Interrupt");
state_.control.AIINT = 0;
ai.m_control.AIINT = 0;
}
// Sample Count Reset
if (tmp_ai_ctrl.SCRESET)
{
DEBUG_LOG_FMT(AUDIO_INTERFACE, "Reset AIS sample counter");
state_.sample_counter = 0;
ai.m_sample_counter = 0;
state_.last_cpu_time = core_timing.GetTicks();
ai.m_last_cpu_time = core_timing.GetTicks();
}
UpdateInterrupts();
ai.UpdateInterrupts();
}));
mmio->Register(base | AI_VOLUME_REGISTER, MMIO::DirectRead<u32>(&state.volume.hex),
mmio->Register(base | AI_VOLUME_REGISTER, MMIO::DirectRead<u32>(&m_volume.hex),
MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
auto& state_ = system.GetAudioInterfaceState().GetData();
state_.volume.hex = val;
auto& ai = system.GetAudioInterface();
ai.m_volume.hex = val;
SoundStream* sound_stream = system.GetSoundStream();
sound_stream->GetMixer()->SetStreamingVolume(state_.volume.left,
state_.volume.right);
sound_stream->GetMixer()->SetStreamingVolume(ai.m_volume.left,
ai.m_volume.right);
}));
mmio->Register(base | AI_SAMPLE_COUNTER, MMIO::ComplexRead<u32>([](Core::System& system, u32) {
auto& state_ = system.GetAudioInterfaceState().GetData();
auto& ai = system.GetAudioInterface();
const u64 cycles_streamed =
IsPlaying() ? (system.GetCoreTiming().GetTicks() - state_.last_cpu_time) :
state_.last_cpu_time;
return state_.sample_counter +
static_cast<u32>(cycles_streamed / state_.cpu_cycles_per_sample);
ai.IsPlaying() ? (system.GetCoreTiming().GetTicks() - ai.m_last_cpu_time) :
ai.m_last_cpu_time;
return ai.m_sample_counter +
static_cast<u32>(cycles_streamed / ai.m_cpu_cycles_per_sample);
}),
MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
auto& core_timing = system.GetCoreTiming();
auto& state_ = system.GetAudioInterfaceState().GetData();
state_.sample_counter = val;
state_.last_cpu_time = core_timing.GetTicks();
core_timing.RemoveEvent(state_.event_type_ai);
core_timing.ScheduleEvent(GetAIPeriod(), state_.event_type_ai);
auto& ai = system.GetAudioInterface();
ai.m_sample_counter = val;
ai.m_last_cpu_time = core_timing.GetTicks();
core_timing.RemoveEvent(ai.m_event_type_ai);
core_timing.ScheduleEvent(ai.GetAIPeriod(), ai.m_event_type_ai);
}));
mmio->Register(base | AI_INTERRUPT_TIMING, MMIO::DirectRead<u32>(&state.interrupt_timing),
mmio->Register(base | AI_INTERRUPT_TIMING, MMIO::DirectRead<u32>(&m_interrupt_timing),
MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
auto& core_timing = system.GetCoreTiming();
auto& state_ = system.GetAudioInterfaceState().GetData();
auto& ai = system.GetAudioInterface();
DEBUG_LOG_FMT(AUDIO_INTERFACE, "AI_INTERRUPT_TIMING={:08x} at PC: {:08x}", val,
system.GetPPCState().pc);
state_.interrupt_timing = val;
core_timing.RemoveEvent(state_.event_type_ai);
core_timing.ScheduleEvent(GetAIPeriod(), state_.event_type_ai);
ai.m_interrupt_timing = val;
core_timing.RemoveEvent(ai.m_event_type_ai);
core_timing.ScheduleEvent(ai.GetAIPeriod(), ai.m_event_type_ai);
}));
}
void GenerateAISInterrupt()
void AudioInterfaceManager::GenerateAISInterrupt()
{
GenerateAudioInterrupt();
}
bool IsPlaying()
bool AudioInterfaceManager::IsPlaying() const
{
auto& state = Core::System::GetInstance().GetAudioInterfaceState().GetData();
return (state.control.PSTAT == 1);
return (m_control.PSTAT == 1);
}
u32 GetAIDSampleRateDivisor()
u32 AudioInterfaceManager::GetAIDSampleRateDivisor() const
{
auto& state = Core::System::GetInstance().GetAudioInterfaceState().GetData();
return state.aid_sample_rate_divisor;
return m_aid_sample_rate_divisor;
}
u32 GetAISSampleRateDivisor()
u32 AudioInterfaceManager::GetAISSampleRateDivisor() const
{
auto& state = Core::System::GetInstance().GetAudioInterfaceState().GetData();
return state.ais_sample_rate_divisor;
return m_ais_sample_rate_divisor;
}
u32 Get32KHzSampleRateDivisor()
u32 AudioInterfaceManager::Get32KHzSampleRateDivisor() const
{
return Get48KHzSampleRateDivisor() * 3 / 2;
}
u32 Get48KHzSampleRateDivisor()
u32 AudioInterfaceManager::Get48KHzSampleRateDivisor() const
{
return (SConfig::GetInstance().bWii ? 1125 : 1124) * 2;
}

View File

@ -5,11 +5,17 @@
#pragma once
#include <memory>
#include "Common/CommonTypes.h"
class PointerWrap;
namespace Core
{
class System;
}
namespace CoreTiming
{
struct EventType;
}
namespace MMIO
{
class Mapping;
@ -17,38 +23,98 @@ class Mapping;
namespace AudioInterface
{
class AudioInterfaceState
class AudioInterfaceManager
{
public:
AudioInterfaceState();
AudioInterfaceState(const AudioInterfaceState&) = delete;
AudioInterfaceState(AudioInterfaceState&&) = delete;
AudioInterfaceState& operator=(const AudioInterfaceState&) = delete;
AudioInterfaceState& operator=(AudioInterfaceState&&) = delete;
~AudioInterfaceState();
AudioInterfaceManager(Core::System& system);
AudioInterfaceManager(const AudioInterfaceManager&) = delete;
AudioInterfaceManager(AudioInterfaceManager&&) = delete;
AudioInterfaceManager& operator=(const AudioInterfaceManager&) = delete;
AudioInterfaceManager& operator=(AudioInterfaceManager&&) = delete;
~AudioInterfaceManager();
struct Data;
Data& GetData() { return *m_data; }
void Init();
void Shutdown();
void DoState(PointerWrap& p);
bool IsPlaying() const;
void RegisterMMIO(MMIO::Mapping* mmio, u32 base);
// Get the audio rate divisors (divisors for 48KHz or 32KHz only)
// Mixer::FIXED_SAMPLE_RATE_DIVIDEND will be the dividend used for these divisors
u32 GetAIDSampleRateDivisor() const;
u32 GetAISSampleRateDivisor() const;
u32 Get32KHzSampleRateDivisor() const;
u32 Get48KHzSampleRateDivisor() const;
void GenerateAISInterrupt();
private:
std::unique_ptr<Data> m_data;
enum class SampleRate
{
AI32KHz,
AI48KHz,
};
// AI Control Register
union AICR
{
AICR() = default;
explicit AICR(u32 hex_) : hex{hex_} {}
struct
{
u32 PSTAT : 1; // sample counter/playback enable
u32 AISFR : 1; // AIS Frequency (0=32khz 1=48khz)
u32 AIINTMSK : 1; // 0=interrupt masked 1=interrupt enabled
u32 AIINT : 1; // audio interrupt status
u32 AIINTVLD : 1; // This bit controls whether AIINT is affected by the Interrupt Timing
// register
// matching the sample counter. Once set, AIINT will hold its last value
u32 SCRESET : 1; // write to reset counter
u32 AIDFR : 1; // AID Frequency (0=48khz 1=32khz)
u32 : 25;
};
u32 hex = 0;
};
// AI Volume Register
union AIVR
{
struct
{
u32 left : 8;
u32 right : 8;
u32 : 16;
};
u32 hex = 0;
};
void UpdateInterrupts();
void GenerateAudioInterrupt();
void IncreaseSampleCount(const u32 amount);
int GetAIPeriod() const;
void SetAIDSampleRate(SampleRate sample_rate);
void SetAISSampleRate(SampleRate sample_rate);
void Update(u64 userdata, s64 cycles_late);
static void GlobalUpdate(Core::System& system, u64 userdata, s64 cycles_late);
// Registers
AICR m_control;
AIVR m_volume;
u32 m_sample_counter = 0;
u32 m_interrupt_timing = 0;
u64 m_last_cpu_time = 0;
u64 m_cpu_cycles_per_sample = 0;
u32 m_ais_sample_rate_divisor = 0;
u32 m_aid_sample_rate_divisor = 0;
CoreTiming::EventType* m_event_type_ai = nullptr;
Core::System& m_system;
};
void Init();
void Shutdown();
void DoState(PointerWrap& p);
bool IsPlaying();
void RegisterMMIO(MMIO::Mapping* mmio, u32 base);
// Get the audio rate divisors (divisors for 48KHz or 32KHz only)
// Mixer::FIXED_SAMPLE_RATE_DIVIDEND will be the dividend used for these divisors
u32 GetAIDSampleRateDivisor();
u32 GetAISSampleRateDivisor();
u32 Get32KHzSampleRateDivisor();
u32 Get48KHzSampleRateDivisor();
void GenerateAISInterrupt();
} // namespace AudioInterface

View File

@ -311,11 +311,12 @@ static void DTKStreamingCallback(DIInterruptType interrupt_type, const std::vect
{
auto& system = Core::System::GetInstance();
auto& state = system.GetDVDInterfaceState().GetData();
auto& ai = system.GetAudioInterface();
// Actual games always set this to 48 KHz
// but let's make sure to use GetAISSampleRateDivisor()
// just in case it changes to 32 KHz
const u32 sample_rate_divisor = AudioInterface::GetAISSampleRateDivisor();
const u32 sample_rate_divisor = ai.GetAISSampleRateDivisor();
// Determine which audio data to read next.
@ -334,7 +335,7 @@ static void DTKStreamingCallback(DIInterruptType interrupt_type, const std::vect
SoundStream* sound_stream = system.GetSoundStream();
sound_stream->GetMixer()->PushStreamingSamples(temp_pcm.data(), state.pending_samples);
if (state.stream && AudioInterface::IsPlaying())
if (state.stream && ai.IsPlaying())
{
read_offset = state.audio_position;
read_length = AdvanceDTK(maximum_samples, &state.pending_samples);

View File

@ -40,7 +40,7 @@ void Init(const Sram* override_sram)
State::Init();
// Init the whole Hardware
AudioInterface::Init();
system.GetAudioInterface().Init();
VideoInterface::Init();
SerialInterface::Init();
system.GetProcessorInterface().Init();
@ -80,7 +80,7 @@ void Shutdown()
system.GetHSP().Shutdown();
ExpansionInterface::Shutdown();
SerialInterface::Shutdown();
AudioInterface::Shutdown();
system.GetAudioInterface().Shutdown();
State::Shutdown();
system.GetCoreTiming().Shutdown();
@ -107,7 +107,7 @@ void DoState(PointerWrap& p)
p.DoMarker("GPFifo");
ExpansionInterface::DoState(p);
p.DoMarker("ExpansionInterface");
AudioInterface::DoState(p);
system.GetAudioInterface().DoState(p);
p.DoMarker("AudioInterface");
system.GetHSP().DoState(p);
p.DoMarker("HSP");

View File

@ -58,14 +58,14 @@ void MemoryManager::InitMMIO(bool is_wii)
DVDInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0C006000, false);
SerialInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0C006400);
ExpansionInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0C006800);
AudioInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0C006C00);
system.GetAudioInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0C006C00);
if (is_wii)
{
IOS::RegisterMMIO(m_mmio_mapping.get(), 0x0D000000);
DVDInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0D006000, true);
SerialInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0D006400);
ExpansionInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0D006800);
AudioInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0D006C00);
system.GetAudioInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0D006C00);
}
}

View File

@ -105,7 +105,8 @@ void DSPCallback(Core::System& system, u64 userdata, s64 cyclesLate)
int GetAudioDMACallbackPeriod()
{
// System internal sample rate is fixed at 32KHz * 4 (16bit Stereo) / 32 bytes DMA
return static_cast<u64>(s_cpu_core_clock) * AudioInterface::GetAIDSampleRateDivisor() /
auto& system = Core::System::GetInstance();
return static_cast<u64>(s_cpu_core_clock) * system.GetAudioInterface().GetAIDSampleRateDivisor() /
(Mixer::FIXED_SAMPLE_RATE_DIVIDEND * 4 / 32);
}

View File

@ -36,7 +36,8 @@ namespace Core
struct System::Impl
{
explicit Impl(System& system)
: m_core_timing(system), m_gp_fifo(system), m_ppc_state(PowerPC::ppcState)
: m_audio_interface(system), m_core_timing(system), m_gp_fifo(system),
m_ppc_state(PowerPC::ppcState)
{
}
@ -44,7 +45,7 @@ struct System::Impl
bool m_sound_stream_running = false;
bool m_audio_dump_started = false;
AudioInterface::AudioInterfaceState m_audio_interface_state;
AudioInterface::AudioInterfaceManager m_audio_interface;
CoreTiming::CoreTimingManager m_core_timing;
CommandProcessor::CommandProcessorManager m_command_processor;
CPU::CPUManager m_cpu;
@ -112,9 +113,9 @@ void System::SetAudioDumpStarted(bool started)
m_impl->m_audio_dump_started = started;
}
AudioInterface::AudioInterfaceState& System::GetAudioInterfaceState() const
AudioInterface::AudioInterfaceManager& System::GetAudioInterface() const
{
return m_impl->m_audio_interface_state;
return m_impl->m_audio_interface;
}
CPU::CPUManager& System::GetCPU() const

View File

@ -13,7 +13,7 @@ class VertexShaderManager;
namespace AudioInterface
{
class AudioInterfaceState;
class AudioInterfaceManager;
};
namespace CPU
{
@ -122,7 +122,7 @@ public:
bool IsAudioDumpStarted() const;
void SetAudioDumpStarted(bool started);
AudioInterface::AudioInterfaceState& GetAudioInterfaceState() const;
AudioInterface::AudioInterfaceManager& GetAudioInterface() const;
CPU::CPUManager& GetCPU() const;
CoreTiming::CoreTimingManager& GetCoreTiming() const;
CommandProcessor::CommandProcessorManager& GetCommandProcessor() const;