summaryrefslogtreecommitdiff
path: root/src/audio_core/hle/mixers.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio_core/hle/mixers.cpp')
-rw-r--r--src/audio_core/hle/mixers.cpp65
1 files changed, 38 insertions, 27 deletions
diff --git a/src/audio_core/hle/mixers.cpp b/src/audio_core/hle/mixers.cpp
index 18335f7f0..a661a7b27 100644
--- a/src/audio_core/hle/mixers.cpp
+++ b/src/audio_core/hle/mixers.cpp
@@ -20,11 +20,9 @@ void Mixers::Reset() {
20 state = {}; 20 state = {};
21} 21}
22 22
23DspStatus Mixers::Tick(DspConfiguration& config, 23DspStatus Mixers::Tick(DspConfiguration& config, const IntermediateMixSamples& read_samples,
24 const IntermediateMixSamples& read_samples, 24 IntermediateMixSamples& write_samples,
25 IntermediateMixSamples& write_samples, 25 const std::array<QuadFrame32, 3>& input) {
26 const std::array<QuadFrame32, 3>& input)
27{
28 ParseConfig(config); 26 ParseConfig(config);
29 27
30 AuxReturn(read_samples); 28 AuxReturn(read_samples);
@@ -73,13 +71,15 @@ void Mixers::ParseConfig(DspConfiguration& config) {
73 if (config.output_format_dirty) { 71 if (config.output_format_dirty) {
74 config.output_format_dirty.Assign(0); 72 config.output_format_dirty.Assign(0);
75 state.output_format = config.output_format; 73 state.output_format = config.output_format;
76 LOG_TRACE(Audio_DSP, "mixers output_format = %zu", static_cast<size_t>(config.output_format)); 74 LOG_TRACE(Audio_DSP, "mixers output_format = %zu",
75 static_cast<size_t>(config.output_format));
77 } 76 }
78 77
79 if (config.headphones_connected_dirty) { 78 if (config.headphones_connected_dirty) {
80 config.headphones_connected_dirty.Assign(0); 79 config.headphones_connected_dirty.Assign(0);
81 // Do nothing. 80 // Do nothing.
82 // (Note: Whether headphones are connected does affect coefficients used for surround sound.) 81 // (Note: Whether headphones are connected does affect coefficients used for surround
82 // sound.)
83 LOG_TRACE(Audio_DSP, "mixers headphones_connected=%hu", config.headphones_connected); 83 LOG_TRACE(Audio_DSP, "mixers headphones_connected=%hu", config.headphones_connected);
84 } 84 }
85 85
@@ -94,11 +94,10 @@ static s16 ClampToS16(s32 value) {
94 return static_cast<s16>(MathUtil::Clamp(value, -32768, 32767)); 94 return static_cast<s16>(MathUtil::Clamp(value, -32768, 32767));
95} 95}
96 96
97static std::array<s16, 2> AddAndClampToS16(const std::array<s16, 2>& a, const std::array<s16, 2>& b) { 97static std::array<s16, 2> AddAndClampToS16(const std::array<s16, 2>& a,
98 return { 98 const std::array<s16, 2>& b) {
99 ClampToS16(static_cast<s32>(a[0]) + static_cast<s32>(b[0])), 99 return {ClampToS16(static_cast<s32>(a[0]) + static_cast<s32>(b[0])),
100 ClampToS16(static_cast<s32>(a[1]) + static_cast<s32>(b[1])) 100 ClampToS16(static_cast<s32>(a[1]) + static_cast<s32>(b[1]))};
101 };
102} 101}
103 102
104void Mixers::DownmixAndMixIntoCurrentFrame(float gain, const QuadFrame32& samples) { 103void Mixers::DownmixAndMixIntoCurrentFrame(float gain, const QuadFrame32& samples) {
@@ -106,27 +105,33 @@ void Mixers::DownmixAndMixIntoCurrentFrame(float gain, const QuadFrame32& sample
106 105
107 switch (state.output_format) { 106 switch (state.output_format) {
108 case OutputFormat::Mono: 107 case OutputFormat::Mono:
109 std::transform(current_frame.begin(), current_frame.end(), samples.begin(), current_frame.begin(), 108 std::transform(
110 [gain](const std::array<s16, 2>& accumulator, const std::array<s32, 4>& sample) -> std::array<s16, 2> { 109 current_frame.begin(), current_frame.end(), samples.begin(), current_frame.begin(),
110 [gain](const std::array<s16, 2>& accumulator,
111 const std::array<s32, 4>& sample) -> std::array<s16, 2> {
111 // Downmix to mono 112 // Downmix to mono
112 s16 mono = ClampToS16(static_cast<s32>((gain * sample[0] + gain * sample[1] + gain * sample[2] + gain * sample[3]) / 2)); 113 s16 mono = ClampToS16(static_cast<s32>(
114 (gain * sample[0] + gain * sample[1] + gain * sample[2] + gain * sample[3]) /
115 2));
113 // Mix into current frame 116 // Mix into current frame
114 return AddAndClampToS16(accumulator, { mono, mono }); 117 return AddAndClampToS16(accumulator, {mono, mono});
115 }); 118 });
116 return; 119 return;
117 120
118 case OutputFormat::Surround: 121 case OutputFormat::Surround:
119 // TODO(merry): Implement surround sound. 122 // TODO(merry): Implement surround sound.
120 // fallthrough 123 // fallthrough
121 124
122 case OutputFormat::Stereo: 125 case OutputFormat::Stereo:
123 std::transform(current_frame.begin(), current_frame.end(), samples.begin(), current_frame.begin(), 126 std::transform(
124 [gain](const std::array<s16, 2>& accumulator, const std::array<s32, 4>& sample) -> std::array<s16, 2> { 127 current_frame.begin(), current_frame.end(), samples.begin(), current_frame.begin(),
128 [gain](const std::array<s16, 2>& accumulator,
129 const std::array<s32, 4>& sample) -> std::array<s16, 2> {
125 // Downmix to stereo 130 // Downmix to stereo
126 s16 left = ClampToS16(static_cast<s32>(gain * sample[0] + gain * sample[2])); 131 s16 left = ClampToS16(static_cast<s32>(gain * sample[0] + gain * sample[2]));
127 s16 right = ClampToS16(static_cast<s32>(gain * sample[1] + gain * sample[3])); 132 s16 right = ClampToS16(static_cast<s32>(gain * sample[1] + gain * sample[3]));
128 // Mix into current frame 133 // Mix into current frame
129 return AddAndClampToS16(accumulator, { left, right }); 134 return AddAndClampToS16(accumulator, {left, right});
130 }); 135 });
131 return; 136 return;
132 } 137 }
@@ -135,12 +140,14 @@ void Mixers::DownmixAndMixIntoCurrentFrame(float gain, const QuadFrame32& sample
135} 140}
136 141
137void Mixers::AuxReturn(const IntermediateMixSamples& read_samples) { 142void Mixers::AuxReturn(const IntermediateMixSamples& read_samples) {
138 // NOTE: read_samples.mix{1,2}.pcm32 annoyingly have their dimensions in reverse order to QuadFrame32. 143 // NOTE: read_samples.mix{1,2}.pcm32 annoyingly have their dimensions in reverse order to
144 // QuadFrame32.
139 145
140 if (state.mixer1_enabled) { 146 if (state.mixer1_enabled) {
141 for (size_t sample = 0; sample < samples_per_frame; sample++) { 147 for (size_t sample = 0; sample < samples_per_frame; sample++) {
142 for (size_t channel = 0; channel < 4; channel++) { 148 for (size_t channel = 0; channel < 4; channel++) {
143 state.intermediate_mix_buffer[1][sample][channel] = read_samples.mix1.pcm32[channel][sample]; 149 state.intermediate_mix_buffer[1][sample][channel] =
150 read_samples.mix1.pcm32[channel][sample];
144 } 151 }
145 } 152 }
146 } 153 }
@@ -148,14 +155,17 @@ void Mixers::AuxReturn(const IntermediateMixSamples& read_samples) {
148 if (state.mixer2_enabled) { 155 if (state.mixer2_enabled) {
149 for (size_t sample = 0; sample < samples_per_frame; sample++) { 156 for (size_t sample = 0; sample < samples_per_frame; sample++) {
150 for (size_t channel = 0; channel < 4; channel++) { 157 for (size_t channel = 0; channel < 4; channel++) {
151 state.intermediate_mix_buffer[2][sample][channel] = read_samples.mix2.pcm32[channel][sample]; 158 state.intermediate_mix_buffer[2][sample][channel] =
159 read_samples.mix2.pcm32[channel][sample];
152 } 160 }
153 } 161 }
154 } 162 }
155} 163}
156 164
157void Mixers::AuxSend(IntermediateMixSamples& write_samples, const std::array<QuadFrame32, 3>& input) { 165void Mixers::AuxSend(IntermediateMixSamples& write_samples,
158 // NOTE: read_samples.mix{1,2}.pcm32 annoyingly have their dimensions in reverse order to QuadFrame32. 166 const std::array<QuadFrame32, 3>& input) {
167 // NOTE: read_samples.mix{1,2}.pcm32 annoyingly have their dimensions in reverse order to
168 // QuadFrame32.
159 169
160 state.intermediate_mix_buffer[0] = input[0]; 170 state.intermediate_mix_buffer[0] = input[0];
161 171
@@ -184,7 +194,8 @@ void Mixers::MixCurrentFrame() {
184 current_frame.fill({}); 194 current_frame.fill({});
185 195
186 for (size_t mix = 0; mix < 3; mix++) { 196 for (size_t mix = 0; mix < 3; mix++) {
187 DownmixAndMixIntoCurrentFrame(state.intermediate_mixer_volume[mix], state.intermediate_mix_buffer[mix]); 197 DownmixAndMixIntoCurrentFrame(state.intermediate_mixer_volume[mix],
198 state.intermediate_mix_buffer[mix]);
188 } 199 }
189 200
190 // TODO(merry): Compressor. (We currently assume a disabled compressor.) 201 // TODO(merry): Compressor. (We currently assume a disabled compressor.)