diff options
Diffstat (limited to 'src/audio_core/audio_renderer.cpp')
| -rw-r--r-- | src/audio_core/audio_renderer.cpp | 64 |
1 files changed, 52 insertions, 12 deletions
diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp index a75cd3be5..83b75e61f 100644 --- a/src/audio_core/audio_renderer.cpp +++ b/src/audio_core/audio_renderer.cpp | |||
| @@ -3,9 +3,12 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "audio_core/algorithm/interpolate.h" | 5 | #include "audio_core/algorithm/interpolate.h" |
| 6 | #include "audio_core/audio_out.h" | ||
| 6 | #include "audio_core/audio_renderer.h" | 7 | #include "audio_core/audio_renderer.h" |
| 8 | #include "audio_core/codec.h" | ||
| 7 | #include "common/assert.h" | 9 | #include "common/assert.h" |
| 8 | #include "common/logging/log.h" | 10 | #include "common/logging/log.h" |
| 11 | #include "core/hle/kernel/event.h" | ||
| 9 | #include "core/memory.h" | 12 | #include "core/memory.h" |
| 10 | 13 | ||
| 11 | namespace AudioCore { | 14 | namespace AudioCore { |
| @@ -13,6 +16,41 @@ namespace AudioCore { | |||
| 13 | constexpr u32 STREAM_SAMPLE_RATE{48000}; | 16 | constexpr u32 STREAM_SAMPLE_RATE{48000}; |
| 14 | constexpr u32 STREAM_NUM_CHANNELS{2}; | 17 | constexpr u32 STREAM_NUM_CHANNELS{2}; |
| 15 | 18 | ||
| 19 | class AudioRenderer::VoiceState { | ||
| 20 | public: | ||
| 21 | bool IsPlaying() const { | ||
| 22 | return is_in_use && info.play_state == PlayState::Started; | ||
| 23 | } | ||
| 24 | |||
| 25 | const VoiceOutStatus& GetOutStatus() const { | ||
| 26 | return out_status; | ||
| 27 | } | ||
| 28 | |||
| 29 | const VoiceInfo& GetInfo() const { | ||
| 30 | return info; | ||
| 31 | } | ||
| 32 | |||
| 33 | VoiceInfo& Info() { | ||
| 34 | return info; | ||
| 35 | } | ||
| 36 | |||
| 37 | void SetWaveIndex(std::size_t index); | ||
| 38 | std::vector<s16> DequeueSamples(std::size_t sample_count); | ||
| 39 | void UpdateState(); | ||
| 40 | void RefreshBuffer(); | ||
| 41 | |||
| 42 | private: | ||
| 43 | bool is_in_use{}; | ||
| 44 | bool is_refresh_pending{}; | ||
| 45 | std::size_t wave_index{}; | ||
| 46 | std::size_t offset{}; | ||
| 47 | Codec::ADPCMState adpcm_state{}; | ||
| 48 | InterpolationState interp_state{}; | ||
| 49 | std::vector<s16> samples; | ||
| 50 | VoiceOutStatus out_status{}; | ||
| 51 | VoiceInfo info{}; | ||
| 52 | }; | ||
| 53 | |||
| 16 | AudioRenderer::AudioRenderer(AudioRendererParameter params, | 54 | AudioRenderer::AudioRenderer(AudioRendererParameter params, |
| 17 | Kernel::SharedPtr<Kernel::Event> buffer_event) | 55 | Kernel::SharedPtr<Kernel::Event> buffer_event) |
| 18 | : worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count) { | 56 | : worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count) { |
| @@ -27,6 +65,8 @@ AudioRenderer::AudioRenderer(AudioRendererParameter params, | |||
| 27 | QueueMixedBuffer(2); | 65 | QueueMixedBuffer(2); |
| 28 | } | 66 | } |
| 29 | 67 | ||
| 68 | AudioRenderer::~AudioRenderer() = default; | ||
| 69 | |||
| 30 | u32 AudioRenderer::GetSampleRate() const { | 70 | u32 AudioRenderer::GetSampleRate() const { |
| 31 | return worker_params.sample_rate; | 71 | return worker_params.sample_rate; |
| 32 | } | 72 | } |
| @@ -52,8 +92,8 @@ std::vector<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_ | |||
| 52 | memory_pool_count * sizeof(MemoryPoolInfo)); | 92 | memory_pool_count * sizeof(MemoryPoolInfo)); |
| 53 | 93 | ||
| 54 | // Copy VoiceInfo structs | 94 | // Copy VoiceInfo structs |
| 55 | size_t offset{sizeof(UpdateDataHeader) + config.behavior_size + config.memory_pools_size + | 95 | std::size_t offset{sizeof(UpdateDataHeader) + config.behavior_size + config.memory_pools_size + |
| 56 | config.voice_resource_size}; | 96 | config.voice_resource_size}; |
| 57 | for (auto& voice : voices) { | 97 | for (auto& voice : voices) { |
| 58 | std::memcpy(&voice.Info(), input_params.data() + offset, sizeof(VoiceInfo)); | 98 | std::memcpy(&voice.Info(), input_params.data() + offset, sizeof(VoiceInfo)); |
| 59 | offset += sizeof(VoiceInfo); | 99 | offset += sizeof(VoiceInfo); |
| @@ -72,7 +112,7 @@ std::vector<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_ | |||
| 72 | 112 | ||
| 73 | // Update memory pool state | 113 | // Update memory pool state |
| 74 | std::vector<MemoryPoolEntry> memory_pool(memory_pool_count); | 114 | std::vector<MemoryPoolEntry> memory_pool(memory_pool_count); |
| 75 | for (size_t index = 0; index < memory_pool.size(); ++index) { | 115 | for (std::size_t index = 0; index < memory_pool.size(); ++index) { |
| 76 | if (mem_pool_info[index].pool_state == MemoryPoolStates::RequestAttach) { | 116 | if (mem_pool_info[index].pool_state == MemoryPoolStates::RequestAttach) { |
| 77 | memory_pool[index].state = MemoryPoolStates::Attached; | 117 | memory_pool[index].state = MemoryPoolStates::Attached; |
| 78 | } else if (mem_pool_info[index].pool_state == MemoryPoolStates::RequestDetach) { | 118 | } else if (mem_pool_info[index].pool_state == MemoryPoolStates::RequestDetach) { |
| @@ -93,7 +133,7 @@ std::vector<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_ | |||
| 93 | response_data.memory_pools_size); | 133 | response_data.memory_pools_size); |
| 94 | 134 | ||
| 95 | // Copy output voice status | 135 | // Copy output voice status |
| 96 | size_t voice_out_status_offset{sizeof(UpdateDataHeader) + response_data.memory_pools_size}; | 136 | std::size_t voice_out_status_offset{sizeof(UpdateDataHeader) + response_data.memory_pools_size}; |
| 97 | for (const auto& voice : voices) { | 137 | for (const auto& voice : voices) { |
| 98 | std::memcpy(output_params.data() + voice_out_status_offset, &voice.GetOutStatus(), | 138 | std::memcpy(output_params.data() + voice_out_status_offset, &voice.GetOutStatus(), |
| 99 | sizeof(VoiceOutStatus)); | 139 | sizeof(VoiceOutStatus)); |
| @@ -103,12 +143,12 @@ std::vector<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_ | |||
| 103 | return output_params; | 143 | return output_params; |
| 104 | } | 144 | } |
| 105 | 145 | ||
| 106 | void AudioRenderer::VoiceState::SetWaveIndex(size_t index) { | 146 | void AudioRenderer::VoiceState::SetWaveIndex(std::size_t index) { |
| 107 | wave_index = index & 3; | 147 | wave_index = index & 3; |
| 108 | is_refresh_pending = true; | 148 | is_refresh_pending = true; |
| 109 | } | 149 | } |
| 110 | 150 | ||
| 111 | std::vector<s16> AudioRenderer::VoiceState::DequeueSamples(size_t sample_count) { | 151 | std::vector<s16> AudioRenderer::VoiceState::DequeueSamples(std::size_t sample_count) { |
| 112 | if (!IsPlaying()) { | 152 | if (!IsPlaying()) { |
| 113 | return {}; | 153 | return {}; |
| 114 | } | 154 | } |
| @@ -117,9 +157,9 @@ std::vector<s16> AudioRenderer::VoiceState::DequeueSamples(size_t sample_count) | |||
| 117 | RefreshBuffer(); | 157 | RefreshBuffer(); |
| 118 | } | 158 | } |
| 119 | 159 | ||
| 120 | const size_t max_size{samples.size() - offset}; | 160 | const std::size_t max_size{samples.size() - offset}; |
| 121 | const size_t dequeue_offset{offset}; | 161 | const std::size_t dequeue_offset{offset}; |
| 122 | size_t size{sample_count * STREAM_NUM_CHANNELS}; | 162 | std::size_t size{sample_count * STREAM_NUM_CHANNELS}; |
| 123 | if (size > max_size) { | 163 | if (size > max_size) { |
| 124 | size = max_size; | 164 | size = max_size; |
| 125 | } | 165 | } |
| @@ -184,7 +224,7 @@ void AudioRenderer::VoiceState::RefreshBuffer() { | |||
| 184 | case 1: | 224 | case 1: |
| 185 | // 1 channel is upsampled to 2 channel | 225 | // 1 channel is upsampled to 2 channel |
| 186 | samples.resize(new_samples.size() * 2); | 226 | samples.resize(new_samples.size() * 2); |
| 187 | for (size_t index = 0; index < new_samples.size(); ++index) { | 227 | for (std::size_t index = 0; index < new_samples.size(); ++index) { |
| 188 | samples[index * 2] = new_samples[index]; | 228 | samples[index * 2] = new_samples[index]; |
| 189 | samples[index * 2 + 1] = new_samples[index]; | 229 | samples[index * 2 + 1] = new_samples[index]; |
| 190 | } | 230 | } |
| @@ -210,7 +250,7 @@ static constexpr s16 ClampToS16(s32 value) { | |||
| 210 | } | 250 | } |
| 211 | 251 | ||
| 212 | void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) { | 252 | void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) { |
| 213 | constexpr size_t BUFFER_SIZE{512}; | 253 | constexpr std::size_t BUFFER_SIZE{512}; |
| 214 | std::vector<s16> buffer(BUFFER_SIZE * stream->GetNumChannels()); | 254 | std::vector<s16> buffer(BUFFER_SIZE * stream->GetNumChannels()); |
| 215 | 255 | ||
| 216 | for (auto& voice : voices) { | 256 | for (auto& voice : voices) { |
| @@ -218,7 +258,7 @@ void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) { | |||
| 218 | continue; | 258 | continue; |
| 219 | } | 259 | } |
| 220 | 260 | ||
| 221 | size_t offset{}; | 261 | std::size_t offset{}; |
| 222 | s64 samples_remaining{BUFFER_SIZE}; | 262 | s64 samples_remaining{BUFFER_SIZE}; |
| 223 | while (samples_remaining > 0) { | 263 | while (samples_remaining > 0) { |
| 224 | const std::vector<s16> samples{voice.DequeueSamples(samples_remaining)}; | 264 | const std::vector<s16> samples{voice.DequeueSamples(samples_remaining)}; |