diff --git a/src/audio_core/hle/mixers.cpp b/src/audio_core/hle/mixers.cpp index 3acb44dab..cfa96818e 100644 --- a/src/audio_core/hle/mixers.cpp +++ b/src/audio_core/hle/mixers.cpp @@ -33,34 +33,34 @@ void Mixers::ParseConfig(DspConfiguration& config) { return; } - if (config.mixer1_enabled_dirty) { - config.mixer1_enabled_dirty.Assign(0); - state.mixer1_enabled = config.mixer1_enabled != 0; - LOG_TRACE(Audio_DSP, "mixers mixer1_enabled = {}", config.mixer1_enabled); + if (config.aux_bus_enable[0]) { + config.aux_bus_enable_0_dirty.Assign(0); + state.aux_bus_enable[0] = config.aux_bus_enable[0] != 0; + LOG_TRACE(Audio_DSP, "mixers aux_bus_enable[0] = {}", config.aux_bus_enable[0]); } - if (config.mixer2_enabled_dirty) { - config.mixer2_enabled_dirty.Assign(0); - state.mixer2_enabled = config.mixer2_enabled != 0; - LOG_TRACE(Audio_DSP, "mixers mixer2_enabled = {}", config.mixer2_enabled); + if (config.aux_bus_enable[1]) { + config.aux_bus_enable_1_dirty.Assign(0); + state.aux_bus_enable[1] = config.aux_bus_enable[1] != 0; + LOG_TRACE(Audio_DSP, "mixers aux_bus_enable[1] = {}", config.aux_bus_enable[1]); } - if (config.volume_0_dirty) { - config.volume_0_dirty.Assign(0); - state.intermediate_mixer_volume[0] = config.volume[0]; - LOG_TRACE(Audio_DSP, "mixers volume[0] = {}", config.volume[0]); + if (config.master_volume) { + config.master_volume_dirty.Assign(0); + state.intermediate_mixer_volume[0] = config.master_volume; + LOG_TRACE(Audio_DSP, "mixers master_volume = {}", config.master_volume); } - if (config.volume_1_dirty) { - config.volume_1_dirty.Assign(0); - state.intermediate_mixer_volume[1] = config.volume[1]; - LOG_TRACE(Audio_DSP, "mixers volume[1] = {}", config.volume[1]); + if (config.aux_return_volume[0]) { + config.aux_return_volume_0_dirty.Assign(0); + state.intermediate_mixer_volume[1] = config.aux_return_volume[0]; + LOG_TRACE(Audio_DSP, "mixers aux_return_volume[0] = {}", config.aux_return_volume[0]); } - if (config.volume_2_dirty) { - config.volume_2_dirty.Assign(0); - state.intermediate_mixer_volume[2] = config.volume[2]; - LOG_TRACE(Audio_DSP, "mixers volume[2] = {}", config.volume[2]); + if (config.aux_return_volume[1]) { + config.aux_return_volume_1_dirty.Assign(0); + state.intermediate_mixer_volume[2] = config.aux_return_volume[1]; + LOG_TRACE(Audio_DSP, "mixers aux_return_volume[1] = {}", config.aux_return_volume[1]); } if (config.output_format_dirty) { @@ -137,7 +137,7 @@ void Mixers::AuxReturn(const IntermediateMixSamples& read_samples) { // NOTE: read_samples.mix{1,2}.pcm32 annoyingly have their dimensions in reverse order to // QuadFrame32. - if (state.mixer1_enabled) { + if (state.aux_bus_enable[0]) { for (std::size_t sample = 0; sample < samples_per_frame; sample++) { for (std::size_t channel = 0; channel < 4; channel++) { state.intermediate_mix_buffer[1][sample][channel] = @@ -146,7 +146,7 @@ void Mixers::AuxReturn(const IntermediateMixSamples& read_samples) { } } - if (state.mixer2_enabled) { + if (state.aux_bus_enable[1]) { for (std::size_t sample = 0; sample < samples_per_frame; sample++) { for (std::size_t channel = 0; channel < 4; channel++) { state.intermediate_mix_buffer[2][sample][channel] = @@ -163,7 +163,7 @@ void Mixers::AuxSend(IntermediateMixSamples& write_samples, state.intermediate_mix_buffer[0] = input[0]; - if (state.mixer1_enabled) { + if (state.aux_bus_enable[0]) { for (std::size_t sample = 0; sample < samples_per_frame; sample++) { for (std::size_t channel = 0; channel < 4; channel++) { write_samples.mix1.pcm32[channel][sample] = input[1][sample][channel]; @@ -173,7 +173,7 @@ void Mixers::AuxSend(IntermediateMixSamples& write_samples, state.intermediate_mix_buffer[1] = input[1]; } - if (state.mixer2_enabled) { + if (state.aux_bus_enable[1]) { for (std::size_t sample = 0; sample < samples_per_frame; sample++) { for (std::size_t channel = 0; channel < 4; channel++) { write_samples.mix2.pcm32[channel][sample] = input[2][sample][channel]; @@ -187,6 +187,8 @@ void Mixers::AuxSend(IntermediateMixSamples& write_samples, void Mixers::MixCurrentFrame() { current_frame.fill({}); + // TODO(SachinV): This is probably not accurate, based on symbols from FE:Fates, + // state.intermediate_mixer_volume[0] represents the master volume for (std::size_t mix = 0; mix < 3; mix++) { DownmixAndMixIntoCurrentFrame(state.intermediate_mixer_volume[mix], state.intermediate_mix_buffer[mix]); diff --git a/src/audio_core/hle/mixers.h b/src/audio_core/hle/mixers.h index 5043be38c..9fecfcbe2 100644 --- a/src/audio_core/hle/mixers.h +++ b/src/audio_core/hle/mixers.h @@ -34,8 +34,7 @@ private: struct { std::array intermediate_mixer_volume = {}; - bool mixer1_enabled = false; - bool mixer2_enabled = false; + std::array aux_bus_enable = {}; std::array intermediate_mix_buffer = {}; OutputFormat output_format = OutputFormat::Stereo; @@ -60,8 +59,7 @@ private: void serialize(Archive& ar, const unsigned int) { ar& current_frame; ar& state.intermediate_mixer_volume; - ar& state.mixer1_enabled; - ar& state.mixer2_enabled; + ar& state.aux_bus_enable; ar& state.intermediate_mix_buffer; ar& state.output_format; } diff --git a/src/audio_core/hle/shared_memory.h b/src/audio_core/hle/shared_memory.h index 43bf1df69..d49bce785 100644 --- a/src/audio_core/hle/shared_memory.h +++ b/src/audio_core/hle/shared_memory.h @@ -141,7 +141,7 @@ struct SourceConfiguration { BitField<25, 1, u32> gain_0_dirty; BitField<26, 1, u32> gain_1_dirty; BitField<27, 1, u32> gain_2_dirty; - BitField<28, 1, u32> sync_dirty; + BitField<28, 1, u32> sync_count_dirty; BitField<29, 1, u32> reset_flag; BitField<30, 1, u32> embedded_buffer_dirty; }; @@ -251,7 +251,7 @@ struct SourceConfiguration { u32_dsp loop_related; u8 enable; INSERT_PADDING_BYTES(1); - u16_le sync; ///< Application-side sync (See also: SourceStatus::sync) + u16_le sync_count; ///< Application-side sync count (See also: SourceStatus::sync_count) u32_dsp play_position; ///< Position. (Units: number of samples) INSERT_PADDING_DSPWORDS(2); @@ -313,9 +313,9 @@ struct SourceStatus { struct Status { u8 is_enabled; ///< Is this channel enabled? (Doesn't have to be playing anything.) u8 current_buffer_id_dirty; ///< Non-zero when current_buffer_id changes - u16_le sync; ///< Is set by the DSP to the value of SourceConfiguration::sync - u32_dsp buffer_position; ///< Number of samples into the current buffer - u16_le current_buffer_id; ///< Updated when a buffer finishes playing + u16_le sync_count; ///< Is set by the DSP to the value of SourceConfiguration::sync_count + u32_dsp buffer_position; ///< Number of samples into the current buffer + u16_le current_buffer_id; ///< Updated when a buffer finishes playing INSERT_PADDING_DSPWORDS(1); }; @@ -329,27 +329,35 @@ struct DspConfiguration { union { u32_le dirty_raw; - BitField<8, 1, u32> mixer1_enabled_dirty; - BitField<9, 1, u32> mixer2_enabled_dirty; + BitField<6, 1, u32> aux_front_bypass_0_dirty; + BitField<7, 1, u32> aux_front_bypass_1_dirty; + BitField<8, 1, u32> aux_bus_enable_0_dirty; + BitField<9, 1, u32> aux_bus_enable_1_dirty; BitField<10, 1, u32> delay_effect_0_dirty; BitField<11, 1, u32> delay_effect_1_dirty; BitField<12, 1, u32> reverb_effect_0_dirty; BitField<13, 1, u32> reverb_effect_1_dirty; - BitField<16, 1, u32> volume_0_dirty; + BitField<15, 1, u32> output_buffer_count_dirty; + BitField<16, 1, u32> master_volume_dirty; - BitField<24, 1, u32> volume_1_dirty; - BitField<25, 1, u32> volume_2_dirty; + BitField<24, 1, u32> aux_return_volume_0_dirty; + BitField<25, 1, u32> aux_return_volume_1_dirty; BitField<26, 1, u32> output_format_dirty; - BitField<27, 1, u32> limiter_enabled_dirty; + BitField<27, 1, u32> clipping_mode_dirty; BitField<28, 1, u32> headphones_connected_dirty; + BitField<29, 1, u32> surround_depth_dirty; + BitField<30, 1, u32> surround_speaker_position_dirty; + BitField<31, 1, u32> rear_ratio_dirty; }; /// The DSP has three intermediate audio mixers. This controls the volume level (0.0-1.0) for /// each at the final mixer. - float_le volume[3]; + float_le master_volume; + std::array aux_return_volume; - INSERT_PADDING_DSPWORDS(3); + u16_le output_buffer_count; + INSERT_PADDING_DSPWORDS(2); enum class OutputFormat : u16_le { Mono = 0, @@ -359,12 +367,15 @@ struct DspConfiguration { OutputFormat output_format; - u16_le limiter_enabled; ///< Not sure of the exact gain equation for the limiter. + u16_le clipping_mode; ///< Not sure of the exact gain equation for the limiter. u16_le headphones_connected; ///< Application updates the DSP on headphone status. - INSERT_PADDING_DSPWORDS(4); ///< TODO: Surround sound related - INSERT_PADDING_DSPWORDS(2); ///< TODO: Intermediate mixer 1/2 related - u16_le mixer1_enabled; - u16_le mixer2_enabled; + + u16_le surround_depth; + u16_le surround_speaker_position; + INSERT_PADDING_DSPWORDS(1); ///< TODO: Surround sound related + u16_le rear_ratio; + std::array aux_front_bypass; + std::array aux_bus_enable; /** * This is delay with feedback. @@ -406,11 +417,19 @@ struct DspConfiguration { ReverbEffect reverb_effect[2]; - INSERT_PADDING_DSPWORDS(4); + u16_le sync_mode; + INSERT_PADDING_DSPWORDS(1); + union { + u32_le dirty2_raw; + + BitField<16, 1, u32> sync_mode_dirty; + }; }; ASSERT_DSP_STRUCT(DspConfiguration, 196); ASSERT_DSP_STRUCT(DspConfiguration::DelayEffect, 20); ASSERT_DSP_STRUCT(DspConfiguration::ReverbEffect, 52); +static_assert(offsetof(DspConfiguration, sync_mode) == 0xBC); +static_assert(offsetof(DspConfiguration, dirty2_raw) == 0xC0); struct AdpcmCoefficients { /// Coefficients are signed fixed point with 11 fractional bits. diff --git a/src/audio_core/hle/source.cpp b/src/audio_core/hle/source.cpp index 24bbbbf6f..bb723716c 100644 --- a/src/audio_core/hle/source.cpp +++ b/src/audio_core/hle/source.cpp @@ -72,10 +72,10 @@ void Source::ParseConfig(SourceConfiguration::Configuration& config, LOG_TRACE(Audio_DSP, "source_id={} enable={}", source_id, state.enabled); } - if (config.sync_dirty) { - config.sync_dirty.Assign(0); - state.sync = config.sync; - LOG_TRACE(Audio_DSP, "source_id={} sync={}", source_id, state.sync); + if (config.sync_count_dirty) { + config.sync_count_dirty.Assign(0); + state.sync_count = config.sync_count; + LOG_TRACE(Audio_DSP, "source_id={} sync={}", source_id, state.sync_count); } if (config.rate_multiplier_dirty) { @@ -432,7 +432,7 @@ SourceStatus::Status Source::GetCurrentStatus() { state.buffer_update = false; ret.current_buffer_id = state.current_buffer_id; ret.buffer_position = state.current_sample_number; - ret.sync = state.sync; + ret.sync_count = state.sync_count; return ret; } diff --git a/src/audio_core/hle/source.h b/src/audio_core/hle/source.h index 0e5d9869a..10ebb0090 100644 --- a/src/audio_core/hle/source.h +++ b/src/audio_core/hle/source.h @@ -121,7 +121,7 @@ private: // State variables bool enabled = false; - u16 sync = 0; + u16 sync_count = 0; // Mixing @@ -164,7 +164,7 @@ private: template void serialize(Archive& ar, const unsigned int) { ar& enabled; - ar& sync; + ar& sync_count; ar& gain; ar& input_queue; ar& mono_or_stereo;