summaryrefslogtreecommitdiff
path: root/src/audio_core/audio_renderer.cpp
diff options
context:
space:
mode:
authorGravatar Kelebek12021-06-26 23:04:40 +0100
committerGravatar Kelebek12021-07-01 06:01:01 +0100
commitb455043e45737345fe73d118947db1684bd248ea (patch)
treec05414e81eff4b012bd1b33076fb60da16aace54 /src/audio_core/audio_renderer.cpp
parentDecouple audio processing and run at variable rate (diff)
downloadyuzu-b455043e45737345fe73d118947db1684bd248ea.tar.gz
yuzu-b455043e45737345fe73d118947db1684bd248ea.tar.xz
yuzu-b455043e45737345fe73d118947db1684bd248ea.zip
Fix XC2/VOEZ crashing, add audio looping and a few misc fixes
Diffstat (limited to 'src/audio_core/audio_renderer.cpp')
-rw-r--r--src/audio_core/audio_renderer.cpp130
1 files changed, 63 insertions, 67 deletions
diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp
index 0757cd804..ccd5ca6cc 100644
--- a/src/audio_core/audio_renderer.cpp
+++ b/src/audio_core/audio_renderer.cpp
@@ -129,87 +129,85 @@ Stream::State AudioRenderer::GetStreamState() const {
129 129
130ResultCode AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_params, 130ResultCode AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_params,
131 std::vector<u8>& output_params) { 131 std::vector<u8>& output_params) {
132 { 132 std::scoped_lock lock{mutex};
133 std::scoped_lock lock{mutex}; 133 InfoUpdater info_updater{input_params, output_params, behavior_info};
134 InfoUpdater info_updater{input_params, output_params, behavior_info};
135 134
136 if (!info_updater.UpdateBehaviorInfo(behavior_info)) { 135 if (!info_updater.UpdateBehaviorInfo(behavior_info)) {
137 LOG_ERROR(Audio, "Failed to update behavior info input parameters"); 136 LOG_ERROR(Audio, "Failed to update behavior info input parameters");
138 return AudioCommon::Audren::ERR_INVALID_PARAMETERS; 137 return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
139 } 138 }
140 139
141 if (!info_updater.UpdateMemoryPools(memory_pool_info)) { 140 if (!info_updater.UpdateMemoryPools(memory_pool_info)) {
142 LOG_ERROR(Audio, "Failed to update memory pool parameters"); 141 LOG_ERROR(Audio, "Failed to update memory pool parameters");
143 return AudioCommon::Audren::ERR_INVALID_PARAMETERS; 142 return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
144 } 143 }
145 144
146 if (!info_updater.UpdateVoiceChannelResources(voice_context)) { 145 if (!info_updater.UpdateVoiceChannelResources(voice_context)) {
147 LOG_ERROR(Audio, "Failed to update voice channel resource parameters"); 146 LOG_ERROR(Audio, "Failed to update voice channel resource parameters");
148 return AudioCommon::Audren::ERR_INVALID_PARAMETERS; 147 return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
149 } 148 }
150 149
151 if (!info_updater.UpdateVoices(voice_context, memory_pool_info, 0)) { 150 if (!info_updater.UpdateVoices(voice_context, memory_pool_info, 0)) {
152 LOG_ERROR(Audio, "Failed to update voice parameters"); 151 LOG_ERROR(Audio, "Failed to update voice parameters");
153 return AudioCommon::Audren::ERR_INVALID_PARAMETERS; 152 return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
154 } 153 }
155 154
156 // TODO(ogniK): Deal with stopped audio renderer but updates still taking place 155 // TODO(ogniK): Deal with stopped audio renderer but updates still taking place
157 if (!info_updater.UpdateEffects(effect_context, true)) { 156 if (!info_updater.UpdateEffects(effect_context, true)) {
158 LOG_ERROR(Audio, "Failed to update effect parameters"); 157 LOG_ERROR(Audio, "Failed to update effect parameters");
158 return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
159 }
160
161 if (behavior_info.IsSplitterSupported()) {
162 if (!info_updater.UpdateSplitterInfo(splitter_context)) {
163 LOG_ERROR(Audio, "Failed to update splitter parameters");
159 return AudioCommon::Audren::ERR_INVALID_PARAMETERS; 164 return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
160 } 165 }
166 }
161 167
162 if (behavior_info.IsSplitterSupported()) { 168 const auto mix_result = info_updater.UpdateMixes(mix_context, worker_params.mix_buffer_count,
163 if (!info_updater.UpdateSplitterInfo(splitter_context)) { 169 splitter_context, effect_context);
164 LOG_ERROR(Audio, "Failed to update splitter parameters");
165 return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
166 }
167 }
168 170
169 const auto mix_result = info_updater.UpdateMixes( 171 if (mix_result.IsError()) {
170 mix_context, worker_params.mix_buffer_count, splitter_context, effect_context); 172 LOG_ERROR(Audio, "Failed to update mix parameters");
173 return mix_result;
174 }
171 175
172 if (mix_result.IsError()) { 176 // TODO(ogniK): Sinks
173 LOG_ERROR(Audio, "Failed to update mix parameters"); 177 if (!info_updater.UpdateSinks(sink_context)) {
174 return mix_result; 178 LOG_ERROR(Audio, "Failed to update sink parameters");
175 } 179 return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
180 }
176 181
177 // TODO(ogniK): Sinks 182 // TODO(ogniK): Performance buffer
178 if (!info_updater.UpdateSinks(sink_context)) { 183 if (!info_updater.UpdatePerformanceBuffer()) {
179 LOG_ERROR(Audio, "Failed to update sink parameters"); 184 LOG_ERROR(Audio, "Failed to update performance buffer parameters");
180 return AudioCommon::Audren::ERR_INVALID_PARAMETERS; 185 return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
181 } 186 }
182 187
183 // TODO(ogniK): Performance buffer 188 if (!info_updater.UpdateErrorInfo(behavior_info)) {
184 if (!info_updater.UpdatePerformanceBuffer()) { 189 LOG_ERROR(Audio, "Failed to update error info");
185 LOG_ERROR(Audio, "Failed to update performance buffer parameters"); 190 return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
186 return AudioCommon::Audren::ERR_INVALID_PARAMETERS; 191 }
187 }
188 192
189 if (!info_updater.UpdateErrorInfo(behavior_info)) { 193 if (behavior_info.IsElapsedFrameCountSupported()) {
190 LOG_ERROR(Audio, "Failed to update error info"); 194 if (!info_updater.UpdateRendererInfo(elapsed_frame_count)) {
195 LOG_ERROR(Audio, "Failed to update renderer info");
191 return AudioCommon::Audren::ERR_INVALID_PARAMETERS; 196 return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
192 } 197 }
198 }
199 // TODO(ogniK): Statistics
193 200
194 if (behavior_info.IsElapsedFrameCountSupported()) { 201 if (!info_updater.WriteOutputHeader()) {
195 if (!info_updater.UpdateRendererInfo(elapsed_frame_count)) { 202 LOG_ERROR(Audio, "Failed to write output header");
196 LOG_ERROR(Audio, "Failed to update renderer info"); 203 return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
197 return AudioCommon::Audren::ERR_INVALID_PARAMETERS; 204 }
198 }
199 }
200 // TODO(ogniK): Statistics
201
202 if (!info_updater.WriteOutputHeader()) {
203 LOG_ERROR(Audio, "Failed to write output header");
204 return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
205 }
206 205
207 // TODO(ogniK): Check when all sections are implemented 206 // TODO(ogniK): Check when all sections are implemented
208 207
209 if (!info_updater.CheckConsumedSize()) { 208 if (!info_updater.CheckConsumedSize()) {
210 LOG_ERROR(Audio, "Audio buffers were not consumed!"); 209 LOG_ERROR(Audio, "Audio buffers were not consumed!");
211 return AudioCommon::Audren::ERR_INVALID_PARAMETERS; 210 return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
212 }
213 } 211 }
214 return ResultSuccess; 212 return ResultSuccess;
215} 213}
@@ -234,10 +232,8 @@ void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) {
234 command_generator.PostCommand(); 232 command_generator.PostCommand();
235 // Base sample size 233 // Base sample size
236 std::size_t BUFFER_SIZE{worker_params.sample_count}; 234 std::size_t BUFFER_SIZE{worker_params.sample_count};
237 // Samples 235 // Samples, making sure to clear
238 std::vector<s16> buffer(BUFFER_SIZE * stream->GetNumChannels()); 236 std::vector<s16> buffer(BUFFER_SIZE * stream->GetNumChannels(), 0);
239 // Make sure to clear our samples
240 std::memset(buffer.data(), 0, buffer.size() * sizeof(s16));
241 237
242 if (sink_context.InUse()) { 238 if (sink_context.InUse()) {
243 const auto stream_channel_count = stream->GetNumChannels(); 239 const auto stream_channel_count = stream->GetNumChannels();