summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/audio_core/sink/cubeb_sink.cpp7
-rw-r--r--src/audio_core/sink/sink_details.cpp4
-rw-r--r--src/core/hle/service/audio/hwopus.cpp49
-rw-r--r--src/core/hle/service/audio/hwopus.h5
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h10
5 files changed, 63 insertions, 12 deletions
diff --git a/src/audio_core/sink/cubeb_sink.cpp b/src/audio_core/sink/cubeb_sink.cpp
index 04d98a865..bbb598bc5 100644
--- a/src/audio_core/sink/cubeb_sink.cpp
+++ b/src/audio_core/sink/cubeb_sink.cpp
@@ -364,7 +364,7 @@ bool IsCubebSuitable() {
364 } 364 }
365#endif 365#endif
366 366
367 // Test min latency 367 // Get min latency
368 cubeb_stream_params params{}; 368 cubeb_stream_params params{};
369 params.rate = TargetSampleRate; 369 params.rate = TargetSampleRate;
370 params.channels = 2; 370 params.channels = 2;
@@ -380,11 +380,6 @@ bool IsCubebSuitable() {
380 } 380 }
381 latency = std::max(latency, TargetSampleCount * 2); 381 latency = std::max(latency, TargetSampleCount * 2);
382 382
383 if (latency > TargetSampleCount * 3) {
384 LOG_ERROR(Audio_Sink, "Cubeb latency is too high, it is not suitable.");
385 return false;
386 }
387
388 // Test opening a device with standard parameters 383 // Test opening a device with standard parameters
389 cubeb_devid output_device{0}; 384 cubeb_devid output_device{0};
390 cubeb_devid input_device{0}; 385 cubeb_devid input_device{0};
diff --git a/src/audio_core/sink/sink_details.cpp b/src/audio_core/sink/sink_details.cpp
index 6bec8ee7c..7c9a4e3ac 100644
--- a/src/audio_core/sink/sink_details.cpp
+++ b/src/audio_core/sink/sink_details.cpp
@@ -83,8 +83,8 @@ const SinkDetails& GetOutputSinkDetails(Settings::AudioEngine sink_id) {
83 break; 83 break;
84 } 84 }
85 } 85 }
86 LOG_ERROR(Service_Audio, "Auto-selecting the {} backend", 86 LOG_INFO(Service_Audio, "Auto-selecting the {} backend",
87 Settings::CanonicalizeEnum(iter->id)); 87 Settings::CanonicalizeEnum(iter->id));
88 } else { 88 } else {
89 if (iter != std::end(sink_details) && !iter->is_suitable()) { 89 if (iter != std::end(sink_details) && !iter->is_suitable()) {
90 LOG_ERROR(Service_Audio, "Selected backend {} is not suitable, falling back to null", 90 LOG_ERROR(Service_Audio, "Selected backend {} is not suitable, falling back to null",
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp
index fa77007f3..4a8276ed1 100644
--- a/src/core/hle/service/audio/hwopus.cpp
+++ b/src/core/hle/service/audio/hwopus.cpp
@@ -174,7 +174,7 @@ public:
174 {6, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleavedWithPerfAndResetOld"}, 174 {6, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleavedWithPerfAndResetOld"},
175 {7, nullptr, "DecodeInterleavedForMultiStreamWithPerfAndResetOld"}, 175 {7, nullptr, "DecodeInterleavedForMultiStreamWithPerfAndResetOld"},
176 {8, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleaved"}, 176 {8, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleaved"},
177 {9, nullptr, "DecodeInterleavedForMultiStream"}, 177 {9, &IHardwareOpusDecoderManager::DecodeInterleavedForMultiStream, "DecodeInterleavedForMultiStream"},
178 }; 178 };
179 // clang-format on 179 // clang-format on
180 180
@@ -206,6 +206,16 @@ private:
206 decoder_state.DecodeInterleaved(ctx, OpusDecoderState::PerfTime::Enabled, extra_behavior); 206 decoder_state.DecodeInterleaved(ctx, OpusDecoderState::PerfTime::Enabled, extra_behavior);
207 } 207 }
208 208
209 void DecodeInterleavedForMultiStream(HLERequestContext& ctx) {
210 LOG_DEBUG(Audio, "called");
211
212 IPC::RequestParser rp{ctx};
213 const auto extra_behavior = rp.Pop<bool>() ? OpusDecoderState::ExtraBehavior::ResetContext
214 : OpusDecoderState::ExtraBehavior::None;
215
216 decoder_state.DecodeInterleaved(ctx, OpusDecoderState::PerfTime::Enabled, extra_behavior);
217 }
218
209 OpusDecoderState decoder_state; 219 OpusDecoderState decoder_state;
210}; 220};
211 221
@@ -354,6 +364,40 @@ void HwOpus::OpenHardwareOpusDecoderEx(HLERequestContext& ctx) {
354 system, OpusDecoderState{std::move(decoder), sample_rate, channel_count}); 364 system, OpusDecoderState{std::move(decoder), sample_rate, channel_count});
355} 365}
356 366
367void HwOpus::OpenHardwareOpusDecoderForMultiStreamEx(HLERequestContext& ctx) {
368 OpusMultiStreamParametersEx params;
369 std::memcpy(&params, ctx.ReadBuffer().data(), ctx.GetReadBufferSize());
370
371 const auto& sample_rate = params.sample_rate;
372 const auto& channel_count = params.channel_count;
373
374 LOG_INFO(
375 Audio,
376 "called with sample_rate={}, channel_count={}, number_streams={}, number_stereo_streams={}",
377 sample_rate, channel_count, params.number_streams, params.number_stereo_streams);
378
379 ASSERT_MSG(sample_rate == 48000 || sample_rate == 24000 || sample_rate == 16000 ||
380 sample_rate == 12000 || sample_rate == 8000,
381 "Invalid sample rate");
382
383 int error = 0;
384 OpusDecoderPtr decoder{opus_multistream_decoder_create(
385 sample_rate, static_cast<int>(channel_count), params.number_streams,
386 params.number_stereo_streams, params.channel_mappings.data(), &error)};
387 if (error != OPUS_OK || decoder == nullptr) {
388 LOG_ERROR(Audio, "Failed to create Opus decoder (error={}).", error);
389 IPC::ResponseBuilder rb{ctx, 2};
390 // TODO(ogniK): Use correct error code
391 rb.Push(ResultUnknown);
392 return;
393 }
394
395 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
396 rb.Push(ResultSuccess);
397 rb.PushIpcInterface<IHardwareOpusDecoderManager>(
398 system, OpusDecoderState{std::move(decoder), sample_rate, channel_count});
399}
400
357HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} { 401HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} {
358 static const FunctionInfo functions[] = { 402 static const FunctionInfo functions[] = {
359 {0, &HwOpus::OpenHardwareOpusDecoder, "OpenHardwareOpusDecoder"}, 403 {0, &HwOpus::OpenHardwareOpusDecoder, "OpenHardwareOpusDecoder"},
@@ -362,7 +406,8 @@ HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} {
362 {3, nullptr, "GetWorkBufferSizeForMultiStream"}, 406 {3, nullptr, "GetWorkBufferSizeForMultiStream"},
363 {4, &HwOpus::OpenHardwareOpusDecoderEx, "OpenHardwareOpusDecoderEx"}, 407 {4, &HwOpus::OpenHardwareOpusDecoderEx, "OpenHardwareOpusDecoderEx"},
364 {5, &HwOpus::GetWorkBufferSizeEx, "GetWorkBufferSizeEx"}, 408 {5, &HwOpus::GetWorkBufferSizeEx, "GetWorkBufferSizeEx"},
365 {6, nullptr, "OpenHardwareOpusDecoderForMultiStreamEx"}, 409 {6, &HwOpus::OpenHardwareOpusDecoderForMultiStreamEx,
410 "OpenHardwareOpusDecoderForMultiStreamEx"},
366 {7, &HwOpus::GetWorkBufferSizeForMultiStreamEx, "GetWorkBufferSizeForMultiStreamEx"}, 411 {7, &HwOpus::GetWorkBufferSizeForMultiStreamEx, "GetWorkBufferSizeForMultiStreamEx"},
367 {8, nullptr, "GetWorkBufferSizeExEx"}, 412 {8, nullptr, "GetWorkBufferSizeExEx"},
368 {9, nullptr, "GetWorkBufferSizeForMultiStreamExEx"}, 413 {9, nullptr, "GetWorkBufferSizeForMultiStreamExEx"},
diff --git a/src/core/hle/service/audio/hwopus.h b/src/core/hle/service/audio/hwopus.h
index ece65c02c..91d9998ac 100644
--- a/src/core/hle/service/audio/hwopus.h
+++ b/src/core/hle/service/audio/hwopus.h
@@ -18,8 +18,10 @@ struct OpusMultiStreamParametersEx {
18 u32 number_stereo_streams; 18 u32 number_stereo_streams;
19 u32 use_large_frame_size; 19 u32 use_large_frame_size;
20 u32 padding; 20 u32 padding;
21 std::array<u32, 64> channel_mappings; 21 std::array<u8, 0x100> channel_mappings;
22}; 22};
23static_assert(sizeof(OpusMultiStreamParametersEx) == 0x118,
24 "OpusMultiStreamParametersEx has incorrect size");
23 25
24class HwOpus final : public ServiceFramework<HwOpus> { 26class HwOpus final : public ServiceFramework<HwOpus> {
25public: 27public:
@@ -29,6 +31,7 @@ public:
29private: 31private:
30 void OpenHardwareOpusDecoder(HLERequestContext& ctx); 32 void OpenHardwareOpusDecoder(HLERequestContext& ctx);
31 void OpenHardwareOpusDecoderEx(HLERequestContext& ctx); 33 void OpenHardwareOpusDecoderEx(HLERequestContext& ctx);
34 void OpenHardwareOpusDecoderForMultiStreamEx(HLERequestContext& ctx);
32 void GetWorkBufferSize(HLERequestContext& ctx); 35 void GetWorkBufferSize(HLERequestContext& ctx);
33 void GetWorkBufferSizeEx(HLERequestContext& ctx); 36 void GetWorkBufferSizeEx(HLERequestContext& ctx);
34 void GetWorkBufferSizeForMultiStreamEx(HLERequestContext& ctx); 37 void GetWorkBufferSizeForMultiStreamEx(HLERequestContext& ctx);
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index f0f450edb..8be7bd594 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -289,8 +289,11 @@ std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainBuffer(GPUVAddr gpu_ad
289 MarkWrittenBuffer(buffer_id, *cpu_addr, size); 289 MarkWrittenBuffer(buffer_id, *cpu_addr, size);
290 break; 290 break;
291 case ObtainBufferOperation::DiscardWrite: { 291 case ObtainBufferOperation::DiscardWrite: {
292 IntervalType interval{*cpu_addr, size}; 292 VAddr cpu_addr_start = Common::AlignDown(*cpu_addr, 64);
293 VAddr cpu_addr_end = Common::AlignUp(*cpu_addr + size, 64);
294 IntervalType interval{cpu_addr_start, cpu_addr_end};
293 ClearDownload(interval); 295 ClearDownload(interval);
296 common_ranges.subtract(interval);
294 break; 297 break;
295 } 298 }
296 default: 299 default:
@@ -1159,6 +1162,11 @@ void BufferCache<P>::UpdateDrawIndirect() {
1159 .size = static_cast<u32>(size), 1162 .size = static_cast<u32>(size),
1160 .buffer_id = FindBuffer(*cpu_addr, static_cast<u32>(size)), 1163 .buffer_id = FindBuffer(*cpu_addr, static_cast<u32>(size)),
1161 }; 1164 };
1165 VAddr cpu_addr_start = Common::AlignDown(*cpu_addr, 64);
1166 VAddr cpu_addr_end = Common::AlignUp(*cpu_addr + size, 64);
1167 IntervalType interval{cpu_addr_start, cpu_addr_end};
1168 ClearDownload(interval);
1169 common_ranges.subtract(interval);
1162 }; 1170 };
1163 if (current_draw_indirect->include_count) { 1171 if (current_draw_indirect->include_count) {
1164 update(current_draw_indirect->count_start_address, sizeof(u32), 1172 update(current_draw_indirect->count_start_address, sizeof(u32),