summaryrefslogtreecommitdiff
path: root/src/audio_core/audio_renderer.cpp
diff options
context:
space:
mode:
authorGravatar David Marcec2020-04-22 13:03:58 +1000
committerGravatar bunnei2020-05-11 12:56:15 -0400
commit9de860a419853bbaf913c07b1aae239c91c56d9e (patch)
tree4de5b795d79a751d258e1b07c5c054cae7bc1f3d /src/audio_core/audio_renderer.cpp
parentMerge pull request #3896 from jroweboy/remove-clang-format-check-from-patreon (diff)
downloadyuzu-9de860a419853bbaf913c07b1aae239c91c56d9e.tar.gz
yuzu-9de860a419853bbaf913c07b1aae239c91c56d9e.tar.xz
yuzu-9de860a419853bbaf913c07b1aae239c91c56d9e.zip
audio_renderer: Better voice mixing and 6 channel downmixing
Supersedes #3738 and #3321
Diffstat (limited to 'src/audio_core/audio_renderer.cpp')
-rw-r--r--src/audio_core/audio_renderer.cpp96
1 files changed, 85 insertions, 11 deletions
diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp
index d18ef6940..f54ce48c5 100644
--- a/src/audio_core/audio_renderer.cpp
+++ b/src/audio_core/audio_renderer.cpp
@@ -37,9 +37,11 @@ public:
37 } 37 }
38 38
39 void SetWaveIndex(std::size_t index); 39 void SetWaveIndex(std::size_t index);
40 std::vector<s16> DequeueSamples(std::size_t sample_count, Core::Memory::Memory& memory); 40 std::vector<s16> DequeueSamples(std::size_t sample_count, Core::Memory::Memory& memory,
41 std::array<VoiceResourceInformation*, 6> voice_resources);
41 void UpdateState(); 42 void UpdateState();
42 void RefreshBuffer(Core::Memory::Memory& memory); 43 void RefreshBuffer(Core::Memory::Memory& memory,
44 std::array<VoiceResourceInformation*, 6> voice_resources);
43 45
44private: 46private:
45 bool is_in_use{}; 47 bool is_in_use{};
@@ -79,7 +81,7 @@ AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, Core::Memory
79 std::shared_ptr<Kernel::WritableEvent> buffer_event, 81 std::shared_ptr<Kernel::WritableEvent> buffer_event,
80 std::size_t instance_number) 82 std::size_t instance_number)
81 : worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count), 83 : worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count),
82 effects(params.effect_count), memory{memory_} { 84 voice_resources(params.voice_count), effects(params.effect_count), memory{memory_} {
83 behavior_info.SetUserRevision(params.revision); 85 behavior_info.SetUserRevision(params.revision);
84 audio_out = std::make_unique<AudioCore::AudioOut>(); 86 audio_out = std::make_unique<AudioCore::AudioOut>();
85 stream = audio_out->OpenStream(core_timing, STREAM_SAMPLE_RATE, STREAM_NUM_CHANNELS, 87 stream = audio_out->OpenStream(core_timing, STREAM_SAMPLE_RATE, STREAM_NUM_CHANNELS,
@@ -127,6 +129,12 @@ ResultVal<std::vector<u8>> AudioRenderer::UpdateAudioRenderer(const std::vector<
127 input_params.data() + sizeof(UpdateDataHeader) + config.behavior_size, 129 input_params.data() + sizeof(UpdateDataHeader) + config.behavior_size,
128 memory_pool_count * sizeof(MemoryPoolInfo)); 130 memory_pool_count * sizeof(MemoryPoolInfo));
129 131
132 // Copy voice resources
133 const std::size_t voice_resource_offset{sizeof(UpdateDataHeader) + config.behavior_size +
134 config.memory_pools_size};
135 std::memcpy(voice_resources.data(), input_params.data() + voice_resource_offset,
136 sizeof(VoiceResourceInformation) * voice_resources.size());
137
130 // Copy VoiceInfo structs 138 // Copy VoiceInfo structs
131 std::size_t voice_offset{sizeof(UpdateDataHeader) + config.behavior_size + 139 std::size_t voice_offset{sizeof(UpdateDataHeader) + config.behavior_size +
132 config.memory_pools_size + config.voice_resource_size}; 140 config.memory_pools_size + config.voice_resource_size};
@@ -220,14 +228,15 @@ void AudioRenderer::VoiceState::SetWaveIndex(std::size_t index) {
220 is_refresh_pending = true; 228 is_refresh_pending = true;
221} 229}
222 230
223std::vector<s16> AudioRenderer::VoiceState::DequeueSamples(std::size_t sample_count, 231std::vector<s16> AudioRenderer::VoiceState::DequeueSamples(
224 Core::Memory::Memory& memory) { 232 std::size_t sample_count, Core::Memory::Memory& memory,
233 std::array<VoiceResourceInformation*, 6> voice_resources) {
225 if (!IsPlaying()) { 234 if (!IsPlaying()) {
226 return {}; 235 return {};
227 } 236 }
228 237
229 if (is_refresh_pending) { 238 if (is_refresh_pending) {
230 RefreshBuffer(memory); 239 RefreshBuffer(memory, voice_resources);
231 } 240 }
232 241
233 const std::size_t max_size{samples.size() - offset}; 242 const std::size_t max_size{samples.size() - offset};
@@ -271,7 +280,8 @@ void AudioRenderer::VoiceState::UpdateState() {
271 is_in_use = info.is_in_use; 280 is_in_use = info.is_in_use;
272} 281}
273 282
274void AudioRenderer::VoiceState::RefreshBuffer(Core::Memory::Memory& memory) { 283void AudioRenderer::VoiceState::RefreshBuffer(
284 Core::Memory::Memory& memory, std::array<VoiceResourceInformation*, 6> voice_resources) {
275 const auto wave_buffer_address = info.wave_buffer[wave_index].buffer_addr; 285 const auto wave_buffer_address = info.wave_buffer[wave_index].buffer_addr;
276 const auto wave_buffer_size = info.wave_buffer[wave_index].buffer_sz; 286 const auto wave_buffer_size = info.wave_buffer[wave_index].buffer_sz;
277 std::vector<s16> new_samples(wave_buffer_size / sizeof(s16)); 287 std::vector<s16> new_samples(wave_buffer_size / sizeof(s16));
@@ -296,17 +306,75 @@ void AudioRenderer::VoiceState::RefreshBuffer(Core::Memory::Memory& memory) {
296 } 306 }
297 307
298 switch (info.channel_count) { 308 switch (info.channel_count) {
299 case 1: 309 case 1: {
300 // 1 channel is upsampled to 2 channel 310 // 1 channel is upsampled to 2 channel
301 samples.resize(new_samples.size() * 2); 311 samples.resize(new_samples.size() * 2);
312
302 for (std::size_t index = 0; index < new_samples.size(); ++index) { 313 for (std::size_t index = 0; index < new_samples.size(); ++index) {
303 samples[index * 2] = new_samples[index]; 314 auto sample = static_cast<float>(new_samples[index]);
304 samples[index * 2 + 1] = new_samples[index]; 315 if (voice_resources[0]->in_use) {
316 sample *= voice_resources[0]->mix_volumes[0];
317 }
318
319 samples[index * 2] = static_cast<s16>(sample);
320 samples[index * 2 + 1] = static_cast<s16>(sample);
305 } 321 }
306 break; 322 break;
323 }
307 case 2: { 324 case 2: {
308 // 2 channel is played as is 325 // 2 channel is played as is
309 samples = std::move(new_samples); 326 samples = std::move(new_samples);
327 const std::size_t sample_count = (samples.size() / 2);
328 for (std::size_t index = 0; index < sample_count; ++index) {
329 const std::size_t index_l = index * 2;
330 const std::size_t index_r = index * 2 + 1;
331
332 auto sample_l = static_cast<float>(samples[index_l]);
333 auto sample_r = static_cast<float>(samples[index_r]);
334
335 if (voice_resources[0]->in_use) {
336 sample_l *= voice_resources[0]->mix_volumes[0];
337 }
338
339 if (voice_resources[1]->in_use) {
340 sample_l *= voice_resources[1]->mix_volumes[1];
341 }
342
343 samples[index_l] = static_cast<s16>(sample_l);
344 samples[index_r] = static_cast<s16>(sample_r);
345 }
346 break;
347 }
348 case 6: {
349 samples.resize((new_samples.size() / 6) * 2);
350 const std::size_t sample_count = samples.size() / 2;
351
352 for (std::size_t index = 0; index < sample_count; ++index) {
353 auto FL = static_cast<float>(new_samples[index * 6]);
354 auto FR = static_cast<float>(new_samples[index * 6 + 1]);
355 auto FC = static_cast<float>(new_samples[index * 6 + 2]);
356 auto BL = static_cast<float>(new_samples[index * 6 + 4]);
357 auto BR = static_cast<float>(new_samples[index * 6 + 5]);
358
359 if (voice_resources[0]->in_use) {
360 FL *= voice_resources[0]->mix_volumes[0];
361 }
362 if (voice_resources[1]->in_use) {
363 FR *= voice_resources[1]->mix_volumes[1];
364 }
365 if (voice_resources[2]->in_use) {
366 FC *= voice_resources[2]->mix_volumes[2];
367 }
368 if (voice_resources[4]->in_use) {
369 BL *= voice_resources[4]->mix_volumes[4];
370 }
371 if (voice_resources[5]->in_use) {
372 BR *= voice_resources[5]->mix_volumes[5];
373 }
374
375 samples[index * 2] = static_cast<s16>(0.3694f * FL + 0.2612f * FC + 0.3694f * BL);
376 samples[index * 2 + 1] = static_cast<s16>(0.3694f * FR + 0.2612f * FC + 0.3694f * BR);
377 }
310 break; 378 break;
311 } 379 }
312 default: 380 default:
@@ -352,11 +420,17 @@ void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) {
352 if (!voice.IsPlaying()) { 420 if (!voice.IsPlaying()) {
353 continue; 421 continue;
354 } 422 }
423 std::array<VoiceResourceInformation*, 6> resources{};
424 for (u32 channel = 0; channel < voice.GetInfo().channel_count; channel++) {
425 const auto channel_resource_id = voice.GetInfo().voice_channel_resource_ids[channel];
426 resources[channel] = &voice_resources[channel_resource_id];
427 }
355 428
356 std::size_t offset{}; 429 std::size_t offset{};
357 s64 samples_remaining{BUFFER_SIZE}; 430 s64 samples_remaining{BUFFER_SIZE};
358 while (samples_remaining > 0) { 431 while (samples_remaining > 0) {
359 const std::vector<s16> samples{voice.DequeueSamples(samples_remaining, memory)}; 432 const std::vector<s16> samples{
433 voice.DequeueSamples(samples_remaining, memory, resources)};
360 434
361 if (samples.empty()) { 435 if (samples.empty()) {
362 break; 436 break;