Core/AudioCommon: Move FIXED_SAMPLE_RATE_DIVIDEND from Mixer to AudioInterface.

This commit is contained in:
Jordan Woyak 2025-04-03 14:59:31 -05:00
parent 61ab662733
commit 54e32dec66
10 changed files with 64 additions and 73 deletions

View file

@ -66,7 +66,7 @@ void Mixer::MixerFifo::Mix(s16* samples, std::size_t num_samples)
constexpr DT_s FADE_OUT_RC = DT_s(0.064);
const u64 out_sample_rate = m_mixer->m_output_sample_rate;
u64 in_sample_rate = FIXED_SAMPLE_RATE_DIVIDEND / m_input_sample_rate_divisor;
u64 in_sample_rate = m_input_sample_rate;
const float emulation_speed = m_mixer->m_config_emulation_speed;
if (0 < emulation_speed && emulation_speed != 1.0)
@ -225,10 +225,10 @@ void Mixer::PushSamples(const s16* samples, std::size_t num_samples)
m_dma_mixer.PushSamples(samples, num_samples);
if (m_log_dsp_audio)
{
const s32 sample_rate_divisor = m_dma_mixer.GetInputSampleRateDivisor();
const s32 sample_rate = m_dma_mixer.GetInputSampleRate();
auto volume = m_dma_mixer.GetVolume();
m_wave_writer_dsp.AddStereoSamplesBE(samples, static_cast<u32>(num_samples),
sample_rate_divisor, volume.first, volume.second);
m_wave_writer_dsp.AddStereoSamplesBE(samples, static_cast<u32>(num_samples), sample_rate,
volume.first, volume.second);
}
}
@ -237,15 +237,14 @@ void Mixer::PushStreamingSamples(const s16* samples, std::size_t num_samples)
m_streaming_mixer.PushSamples(samples, num_samples);
if (m_log_dtk_audio)
{
const s32 sample_rate_divisor = m_streaming_mixer.GetInputSampleRateDivisor();
const s32 sample_rate = m_streaming_mixer.GetInputSampleRate();
auto volume = m_streaming_mixer.GetVolume();
m_wave_writer_dtk.AddStereoSamplesBE(samples, static_cast<u32>(num_samples),
sample_rate_divisor, volume.first, volume.second);
m_wave_writer_dtk.AddStereoSamplesBE(samples, static_cast<u32>(num_samples), sample_rate,
volume.first, volume.second);
}
}
void Mixer::PushWiimoteSpeakerSamples(const s16* samples, std::size_t num_samples,
u32 sample_rate_divisor)
void Mixer::PushWiimoteSpeakerSamples(const s16* samples, std::size_t num_samples, u32 sample_rate)
{
// Max 20 bytes/speaker report, may be 4-bit ADPCM so multiply by 2
static constexpr std::size_t MAX_SPEAKER_SAMPLES = 20 * 2;
@ -256,7 +255,7 @@ void Mixer::PushWiimoteSpeakerSamples(const s16* samples, std::size_t num_sample
MAX_SPEAKER_SAMPLES);
if (num_samples <= MAX_SPEAKER_SAMPLES)
{
m_wiimote_speaker_mixer.SetInputSampleRateDivisor(sample_rate_divisor);
m_wiimote_speaker_mixer.SetInputSampleRate(sample_rate);
for (std::size_t i = 0; i < num_samples; ++i)
{
@ -297,19 +296,19 @@ void Mixer::PushGBASamples(std::size_t device_number, const s16* samples, std::s
m_gba_mixers[device_number].PushSamples(samples, num_samples);
}
void Mixer::SetDMAInputSampleRateDivisor(u32 rate_divisor)
void Mixer::SetDMAInputSampleRate(u32 sample_rate)
{
m_dma_mixer.SetInputSampleRateDivisor(rate_divisor);
m_dma_mixer.SetInputSampleRate(sample_rate);
}
void Mixer::SetStreamInputSampleRateDivisor(u32 rate_divisor)
void Mixer::SetStreamInputSampleRate(u32 sample_rate)
{
m_streaming_mixer.SetInputSampleRateDivisor(rate_divisor);
m_streaming_mixer.SetInputSampleRate(sample_rate);
}
void Mixer::SetGBAInputSampleRateDivisors(std::size_t device_number, u32 rate_divisor)
void Mixer::SetGBAInputSampleRate(std::size_t device_number, u32 sample_rate)
{
m_gba_mixers[device_number].SetInputSampleRateDivisor(rate_divisor);
m_gba_mixers[device_number].SetInputSampleRate(sample_rate);
}
void Mixer::SetStreamingVolume(u32 lvolume, u32 rvolume)
@ -332,7 +331,7 @@ void Mixer::StartLogDTKAudio(const std::string& filename)
{
if (!m_log_dtk_audio)
{
bool success = m_wave_writer_dtk.Start(filename, m_streaming_mixer.GetInputSampleRateDivisor());
bool success = m_wave_writer_dtk.Start(filename, m_streaming_mixer.GetInputSampleRate());
if (success)
{
m_log_dtk_audio = true;
@ -369,7 +368,7 @@ void Mixer::StartLogDSPAudio(const std::string& filename)
{
if (!m_log_dsp_audio)
{
bool success = m_wave_writer_dsp.Start(filename, m_dma_mixer.GetInputSampleRateDivisor());
bool success = m_wave_writer_dsp.Start(filename, m_dma_mixer.GetInputSampleRate());
if (success)
{
m_log_dsp_audio = true;
@ -411,19 +410,19 @@ void Mixer::RefreshConfig()
void Mixer::MixerFifo::DoState(PointerWrap& p)
{
p.Do(m_input_sample_rate_divisor);
p.Do(m_input_sample_rate);
p.Do(m_LVolume);
p.Do(m_RVolume);
}
void Mixer::MixerFifo::SetInputSampleRateDivisor(u32 rate_divisor)
void Mixer::MixerFifo::SetInputSampleRate(u32 sample_rate)
{
m_input_sample_rate_divisor = rate_divisor;
m_input_sample_rate = sample_rate;
}
u32 Mixer::MixerFifo::GetInputSampleRateDivisor() const
u32 Mixer::MixerFifo::GetInputSampleRate() const
{
return m_input_sample_rate_divisor;
return m_input_sample_rate;
}
void Mixer::MixerFifo::SetVolume(u32 lvolume, u32 rvolume)

View file

@ -3,7 +3,6 @@
#pragma once
#include <algorithm>
#include <array>
#include <atomic>
#include <bit>
@ -31,16 +30,15 @@ public:
// Called from main thread
void PushSamples(const s16* samples, std::size_t num_samples);
void PushStreamingSamples(const s16* samples, std::size_t num_samples);
void PushWiimoteSpeakerSamples(const s16* samples, std::size_t num_samples,
u32 sample_rate_divisor);
void PushWiimoteSpeakerSamples(const s16* samples, std::size_t num_samples, u32 sample_rate);
void PushSkylanderPortalSamples(const u8* samples, std::size_t num_samples);
void PushGBASamples(std::size_t device_number, const s16* samples, std::size_t num_samples);
u32 GetSampleRate() const { return m_output_sample_rate; }
void SetDMAInputSampleRateDivisor(u32 rate_divisor);
void SetStreamInputSampleRateDivisor(u32 rate_divisor);
void SetGBAInputSampleRateDivisors(std::size_t device_number, u32 rate_divisor);
void SetDMAInputSampleRate(u32 sample_rate);
void SetStreamInputSampleRate(u32 sample_rate);
void SetGBAInputSampleRate(std::size_t device_number, u32 sample_rate);
void SetStreamingVolume(u32 lvolume, u32 rvolume);
void SetWiimoteSpeakerVolume(u32 lvolume, u32 rvolume);
@ -52,9 +50,6 @@ public:
void StartLogDSPAudio(const std::string& filename);
void StopLogDSPAudio();
// 54000000 doesn't work here as it doesn't evenly divide with 32000, but 108000000 does
static constexpr u64 FIXED_SAMPLE_RATE_DIVIDEND = 54000000 * 2;
private:
const std::size_t SURROUND_CHANNELS = 6;
@ -98,22 +93,21 @@ private:
using Granule = std::array<StereoPair, GRANULE_SIZE>;
public:
MixerFifo(Mixer* mixer, u32 sample_rate_divisor, bool little_endian)
: m_mixer(mixer), m_input_sample_rate_divisor(sample_rate_divisor),
m_little_endian(little_endian)
MixerFifo(Mixer* mixer, u32 sample_rate, bool little_endian)
: m_mixer(mixer), m_input_sample_rate(sample_rate), m_little_endian(little_endian)
{
}
void DoState(PointerWrap& p);
void PushSamples(const s16* samples, std::size_t num_samples);
void Mix(s16* samples, std::size_t num_samples);
void SetInputSampleRateDivisor(u32 rate_divisor);
u32 GetInputSampleRateDivisor() const;
void SetInputSampleRate(u32 sample_rate);
u32 GetInputSampleRate() const;
void SetVolume(u32 lvolume, u32 rvolume);
std::pair<s32, s32> GetVolume() const;
private:
Mixer* m_mixer;
u32 m_input_sample_rate_divisor;
u32 m_input_sample_rate;
bool m_little_endian;
Granule m_next_buffer{};
@ -141,14 +135,12 @@ private:
void RefreshConfig();
MixerFifo m_dma_mixer{this, FIXED_SAMPLE_RATE_DIVIDEND / 32000, false};
MixerFifo m_streaming_mixer{this, FIXED_SAMPLE_RATE_DIVIDEND / 48000, false};
MixerFifo m_wiimote_speaker_mixer{this, FIXED_SAMPLE_RATE_DIVIDEND / 3000, true};
MixerFifo m_skylander_portal_mixer{this, FIXED_SAMPLE_RATE_DIVIDEND / 8000, true};
std::array<MixerFifo, 4> m_gba_mixers{MixerFifo{this, FIXED_SAMPLE_RATE_DIVIDEND / 48000, true},
MixerFifo{this, FIXED_SAMPLE_RATE_DIVIDEND / 48000, true},
MixerFifo{this, FIXED_SAMPLE_RATE_DIVIDEND / 48000, true},
MixerFifo{this, FIXED_SAMPLE_RATE_DIVIDEND / 48000, true}};
MixerFifo m_dma_mixer{this, 32000, false};
MixerFifo m_streaming_mixer{this, 48000, false};
MixerFifo m_wiimote_speaker_mixer{this, 3000, true};
MixerFifo m_skylander_portal_mixer{this, 8000, true};
std::array<MixerFifo, 4> m_gba_mixers{MixerFifo{this, 48000, true}, MixerFifo{this, 48000, true},
MixerFifo{this, 48000, true}, MixerFifo{this, 48000, true}};
u32 m_output_sample_rate;
AudioCommon::SurroundDecoder m_surround_decoder;

View file

@ -7,7 +7,6 @@
#include <fmt/format.h>
#include "AudioCommon/Mixer.h"
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#include "Common/IOFile.h"
@ -16,7 +15,6 @@
#include "Common/StringUtil.h"
#include "Common/Swap.h"
#include "Core/Config/MainSettings.h"
#include "Core/ConfigManager.h"
constexpr size_t WaveFileWriter::BUFFER_SIZE;
@ -29,7 +27,7 @@ WaveFileWriter::~WaveFileWriter()
Stop();
}
bool WaveFileWriter::Start(const std::string& filename, u32 sample_rate_divisor)
bool WaveFileWriter::Start(const std::string& filename, u32 sample_rate)
{
// Ask to delete file
if (File::Exists(filename))
@ -68,7 +66,7 @@ bool WaveFileWriter::Start(const std::string& filename, u32 sample_rate_divisor)
if (basename.empty())
SplitPath(filename, nullptr, &basename, nullptr);
current_sample_rate_divisor = sample_rate_divisor;
current_sample_rate = sample_rate;
// -----------------
// Write file header
@ -81,7 +79,6 @@ bool WaveFileWriter::Start(const std::string& filename, u32 sample_rate_divisor)
Write(16); // size of fmt block
Write(0x00020001); // two channels, uncompressed
const u32 sample_rate = Mixer::FIXED_SAMPLE_RATE_DIVIDEND / sample_rate_divisor;
Write(sample_rate);
Write(sample_rate * 2 * 2); // two channels, 16bit
@ -117,8 +114,8 @@ void WaveFileWriter::Write4(const char* ptr)
file.WriteBytes(ptr, 4);
}
void WaveFileWriter::AddStereoSamplesBE(const short* sample_data, u32 count,
u32 sample_rate_divisor, int l_volume, int r_volume)
void WaveFileWriter::AddStereoSamplesBE(const short* sample_data, u32 count, u32 sample_rate,
int l_volume, int r_volume)
{
if (!file)
{
@ -157,14 +154,14 @@ void WaveFileWriter::AddStereoSamplesBE(const short* sample_data, u32 count,
conv_buffer[2 * i + 1] = conv_buffer[2 * i + 1] * r_volume / 256;
}
if (sample_rate_divisor != current_sample_rate_divisor)
if (sample_rate != current_sample_rate)
{
Stop();
file_index++;
const std::string filename =
fmt::format("{}{}{}.wav", File::GetUserPath(D_DUMPAUDIO_IDX), basename, file_index);
Start(filename, sample_rate_divisor);
current_sample_rate_divisor = sample_rate_divisor;
Start(filename, sample_rate);
current_sample_rate = sample_rate;
}
file.WriteBytes(conv_buffer.data(), count * 4);

View file

@ -30,13 +30,13 @@ public:
WaveFileWriter(WaveFileWriter&&) = delete;
WaveFileWriter& operator=(WaveFileWriter&&) = delete;
bool Start(const std::string& filename, u32 sample_rate_divisor);
bool Start(const std::string& filename, u32 sample_rate);
void Stop();
void SetSkipSilence(bool skip) { skip_silence = skip; }
// big endian
void AddStereoSamplesBE(const short* sample_data, u32 count, u32 sample_rate_divisor,
int l_volume, int r_volume);
void AddStereoSamplesBE(const short* sample_data, u32 count, u32 sample_rate, int l_volume,
int r_volume);
u32 GetAudioSize() const { return audio_size; }
private:
@ -50,7 +50,7 @@ private:
u32 file_index = 0;
u32 audio_size = 0;
u32 current_sample_rate_divisor;
u32 current_sample_rate;
std::array<short, BUFFER_SIZE> conv_buffer{};
bool skip_silence = false;

View file

@ -71,8 +71,8 @@ enum
};
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)
: m_ais_sample_rate_divisor(FIXED_SAMPLE_RATE_DIVIDEND / 48000),
m_aid_sample_rate_divisor(FIXED_SAMPLE_RATE_DIVIDEND / 32000), m_system(system)
{
}
@ -125,8 +125,7 @@ void AudioInterfaceManager::IncreaseSampleCount(const u32 amount)
int AudioInterfaceManager::GetAIPeriod() const
{
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;
u64 s_period = m_cpu_cycles_per_sample * 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));
@ -168,7 +167,8 @@ void AudioInterfaceManager::SetAIDSampleRate(SampleRate sample_rate)
}
SoundStream* sound_stream = m_system.GetSoundStream();
sound_stream->GetMixer()->SetDMAInputSampleRateDivisor(m_aid_sample_rate_divisor);
sound_stream->GetMixer()->SetDMAInputSampleRate(FIXED_SAMPLE_RATE_DIVIDEND /
m_aid_sample_rate_divisor);
}
void AudioInterfaceManager::SetAISSampleRate(SampleRate sample_rate)
@ -185,9 +185,10 @@ void AudioInterfaceManager::SetAISSampleRate(SampleRate sample_rate)
}
m_cpu_cycles_per_sample = static_cast<u64>(m_system.GetSystemTimers().GetTicksPerSecond()) *
m_ais_sample_rate_divisor / Mixer::FIXED_SAMPLE_RATE_DIVIDEND;
m_ais_sample_rate_divisor / FIXED_SAMPLE_RATE_DIVIDEND;
SoundStream* sound_stream = m_system.GetSoundStream();
sound_stream->GetMixer()->SetStreamInputSampleRateDivisor(m_ais_sample_rate_divisor);
sound_stream->GetMixer()->SetStreamInputSampleRate(FIXED_SAMPLE_RATE_DIVIDEND /
m_ais_sample_rate_divisor);
}
void AudioInterfaceManager::Init()

View file

@ -23,6 +23,9 @@ class Mapping;
namespace AudioInterface
{
// 54000000 doesn't work here as it doesn't evenly divide with 32000, but 108000000 does
static constexpr u64 FIXED_SAMPLE_RATE_DIVIDEND = 54000000 * 2;
enum class SampleRate
{
AI32KHz,

View file

@ -237,7 +237,7 @@ void DVDInterface::DTKStreamingCallback(DIInterruptType interrupt_type,
// Read the next chunk of audio data asynchronously.
s64 ticks_to_dtk = m_system.GetSystemTimers().GetTicksPerSecond() * s64(m_pending_blocks) *
StreamADPCM::SAMPLES_PER_BLOCK * sample_rate_divisor /
Mixer::FIXED_SAMPLE_RATE_DIVIDEND;
AudioInterface::FIXED_SAMPLE_RATE_DIVIDEND;
ticks_to_dtk -= cycles_late;
if (read_length > 0)
{

View file

@ -407,8 +407,7 @@ void Core::SetSampleRates()
blip_set_rates(m_core->getAudioChannel(m_core, 1), m_core->frequency(m_core), SAMPLE_RATE);
SoundStream* sound_stream = m_system.GetSoundStream();
sound_stream->GetMixer()->SetGBAInputSampleRateDivisors(
m_device_number, Mixer::FIXED_SAMPLE_RATE_DIVIDEND / SAMPLE_RATE);
sound_stream->GetMixer()->SetGBAInputSampleRate(m_device_number, SAMPLE_RATE);
}
void Core::AddCallbacks()

View file

@ -85,7 +85,7 @@ static int GetAudioDMACallbackPeriod(u32 cpu_core_clock, u32 aid_sample_rate_div
{
// System internal sample rate is fixed at 32KHz * 4 (16bit Stereo) / 32 bytes DMA
return static_cast<u64>(cpu_core_clock) * aid_sample_rate_divisor /
(Mixer::FIXED_SAMPLE_RATE_DIVIDEND * 4 / 32);
(AudioInterface::FIXED_SAMPLE_RATE_DIVIDEND * 4 / 32);
}
void SystemTimersManager::AudioDMACallback(Core::System& system, u64 userdata, s64 cycles_late)

View file

@ -133,8 +133,8 @@ void SpeakerLogic::SpeakerData(const u8* data, int length, float speaker_pan)
// ADPCM sample rate is thought to be x2.(3000 x2 = 6000).
const unsigned int sample_rate = sample_rate_dividend / reg_data.sample_rate;
sound_stream->GetMixer()->PushWiimoteSpeakerSamples(
samples.data(), sample_length, Mixer::FIXED_SAMPLE_RATE_DIVIDEND / (sample_rate * 2));
sound_stream->GetMixer()->PushWiimoteSpeakerSamples(samples.data(), sample_length,
sample_rate * 2);
}
void SpeakerLogic::Reset()