summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar David2020-04-21 12:57:30 +1000
committerGravatar GitHub2020-04-20 22:57:30 -0400
commit11c63ca969f39481ccf75c204e21948f4fb41efa (patch)
treeedd0a3efd2515e42c9f6a820888fcd77df29460b /src
parentMerge pull request #3695 from ReinUsesLisp/default-attributes (diff)
downloadyuzu-11c63ca969f39481ccf75c204e21948f4fb41efa.tar.gz
yuzu-11c63ca969f39481ccf75c204e21948f4fb41efa.tar.xz
yuzu-11c63ca969f39481ccf75c204e21948f4fb41efa.zip
audio_renderer: Preliminary BehaviorInfo (#3736)
* audio_renderer: Preliminary BehaviorInfo * clang format * Fixed IsRevisionSupported * fixed IsValidRevision * Fixed logic error & spelling errors & crash * Addressed issues
Diffstat (limited to 'src')
-rw-r--r--src/audio_core/CMakeLists.txt3
-rw-r--r--src/audio_core/audio_renderer.cpp32
-rw-r--r--src/audio_core/audio_renderer.h5
-rw-r--r--src/audio_core/behavior_info.cpp100
-rw-r--r--src/audio_core/behavior_info.h66
-rw-r--r--src/audio_core/common.h47
-rw-r--r--src/core/hle/service/audio/audren_u.cpp9
7 files changed, 249 insertions, 13 deletions
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt
index c381dbe1d..5ef38a337 100644
--- a/src/audio_core/CMakeLists.txt
+++ b/src/audio_core/CMakeLists.txt
@@ -7,9 +7,12 @@ add_library(audio_core STATIC
7 audio_out.h 7 audio_out.h
8 audio_renderer.cpp 8 audio_renderer.cpp
9 audio_renderer.h 9 audio_renderer.h
10 behavior_info.cpp
11 behavior_info.h
10 buffer.h 12 buffer.h
11 codec.cpp 13 codec.cpp
12 codec.h 14 codec.h
15 common.h
13 null_sink.h 16 null_sink.h
14 sink.h 17 sink.h
15 sink_details.cpp 18 sink_details.cpp
diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp
index 7a9dc61d4..d18ef6940 100644
--- a/src/audio_core/audio_renderer.cpp
+++ b/src/audio_core/audio_renderer.cpp
@@ -6,6 +6,7 @@
6#include "audio_core/audio_out.h" 6#include "audio_core/audio_out.h"
7#include "audio_core/audio_renderer.h" 7#include "audio_core/audio_renderer.h"
8#include "audio_core/codec.h" 8#include "audio_core/codec.h"
9#include "audio_core/common.h"
9#include "common/assert.h" 10#include "common/assert.h"
10#include "common/logging/log.h" 11#include "common/logging/log.h"
11#include "core/core.h" 12#include "core/core.h"
@@ -79,7 +80,7 @@ AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, Core::Memory
79 std::size_t instance_number) 80 std::size_t instance_number)
80 : worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count), 81 : worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count),
81 effects(params.effect_count), memory{memory_} { 82 effects(params.effect_count), memory{memory_} {
82 83 behavior_info.SetUserRevision(params.revision);
83 audio_out = std::make_unique<AudioCore::AudioOut>(); 84 audio_out = std::make_unique<AudioCore::AudioOut>();
84 stream = audio_out->OpenStream(core_timing, STREAM_SAMPLE_RATE, STREAM_NUM_CHANNELS, 85 stream = audio_out->OpenStream(core_timing, STREAM_SAMPLE_RATE, STREAM_NUM_CHANNELS,
85 fmt::format("AudioRenderer-Instance{}", instance_number), 86 fmt::format("AudioRenderer-Instance{}", instance_number),
@@ -109,17 +110,17 @@ Stream::State AudioRenderer::GetStreamState() const {
109 return stream->GetState(); 110 return stream->GetState();
110} 111}
111 112
112static constexpr u32 VersionFromRevision(u32_le rev) { 113ResultVal<std::vector<u8>> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_params) {
113 // "REV7" -> 7
114 return ((rev >> 24) & 0xff) - 0x30;
115}
116
117std::vector<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_params) {
118 // Copy UpdateDataHeader struct 114 // Copy UpdateDataHeader struct
119 UpdateDataHeader config{}; 115 UpdateDataHeader config{};
120 std::memcpy(&config, input_params.data(), sizeof(UpdateDataHeader)); 116 std::memcpy(&config, input_params.data(), sizeof(UpdateDataHeader));
121 u32 memory_pool_count = worker_params.effect_count + (worker_params.voice_count * 4); 117 u32 memory_pool_count = worker_params.effect_count + (worker_params.voice_count * 4);
122 118
119 if (!behavior_info.UpdateInput(input_params, sizeof(UpdateDataHeader))) {
120 LOG_ERROR(Audio, "Failed to update behavior info input parameters");
121 return Audren::ERR_INVALID_PARAMETERS;
122 }
123
123 // Copy MemoryPoolInfo structs 124 // Copy MemoryPoolInfo structs
124 std::vector<MemoryPoolInfo> mem_pool_info(memory_pool_count); 125 std::vector<MemoryPoolInfo> mem_pool_info(memory_pool_count);
125 std::memcpy(mem_pool_info.data(), 126 std::memcpy(mem_pool_info.data(),
@@ -173,8 +174,7 @@ std::vector<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_
173 // Copy output header 174 // Copy output header
174 UpdateDataHeader response_data{worker_params}; 175 UpdateDataHeader response_data{worker_params};
175 std::vector<u8> output_params(response_data.total_size); 176 std::vector<u8> output_params(response_data.total_size);
176 const auto audren_revision = VersionFromRevision(config.revision); 177 if (behavior_info.IsElapsedFrameCountSupported()) {
177 if (audren_revision >= 5) {
178 response_data.frame_count = 0x10; 178 response_data.frame_count = 0x10;
179 response_data.total_size += 0x10; 179 response_data.total_size += 0x10;
180 } 180 }
@@ -200,7 +200,19 @@ std::vector<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_
200 sizeof(EffectOutStatus)); 200 sizeof(EffectOutStatus));
201 effect_out_status_offset += sizeof(EffectOutStatus); 201 effect_out_status_offset += sizeof(EffectOutStatus);
202 } 202 }
203 return output_params; 203
204 // Update behavior info output
205 const std::size_t behavior_out_status_offset{
206 sizeof(UpdateDataHeader) + response_data.memory_pools_size + response_data.voices_size +
207 response_data.effects_size + response_data.sinks_size +
208 response_data.performance_manager_size};
209
210 if (!behavior_info.UpdateOutput(output_params, behavior_out_status_offset)) {
211 LOG_ERROR(Audio, "Failed to update behavior info output parameters");
212 return Audren::ERR_INVALID_PARAMETERS;
213 }
214
215 return MakeResult(output_params);
204} 216}
205 217
206void AudioRenderer::VoiceState::SetWaveIndex(std::size_t index) { 218void AudioRenderer::VoiceState::SetWaveIndex(std::size_t index) {
diff --git a/src/audio_core/audio_renderer.h b/src/audio_core/audio_renderer.h
index 62faf9f19..b42770fae 100644
--- a/src/audio_core/audio_renderer.h
+++ b/src/audio_core/audio_renderer.h
@@ -8,11 +8,13 @@
8#include <memory> 8#include <memory>
9#include <vector> 9#include <vector>
10 10
11#include "audio_core/behavior_info.h"
11#include "audio_core/stream.h" 12#include "audio_core/stream.h"
12#include "common/common_funcs.h" 13#include "common/common_funcs.h"
13#include "common/common_types.h" 14#include "common/common_types.h"
14#include "common/swap.h" 15#include "common/swap.h"
15#include "core/hle/kernel/object.h" 16#include "core/hle/kernel/object.h"
17#include "core/hle/result.h"
16 18
17namespace Core::Timing { 19namespace Core::Timing {
18class CoreTiming; 20class CoreTiming;
@@ -226,7 +228,7 @@ public:
226 std::shared_ptr<Kernel::WritableEvent> buffer_event, std::size_t instance_number); 228 std::shared_ptr<Kernel::WritableEvent> buffer_event, std::size_t instance_number);
227 ~AudioRenderer(); 229 ~AudioRenderer();
228 230
229 std::vector<u8> UpdateAudioRenderer(const std::vector<u8>& input_params); 231 ResultVal<std::vector<u8>> UpdateAudioRenderer(const std::vector<u8>& input_params);
230 void QueueMixedBuffer(Buffer::Tag tag); 232 void QueueMixedBuffer(Buffer::Tag tag);
231 void ReleaseAndQueueBuffers(); 233 void ReleaseAndQueueBuffers();
232 u32 GetSampleRate() const; 234 u32 GetSampleRate() const;
@@ -237,6 +239,7 @@ public:
237private: 239private:
238 class EffectState; 240 class EffectState;
239 class VoiceState; 241 class VoiceState;
242 BehaviorInfo behavior_info{};
240 243
241 AudioRendererParameter worker_params; 244 AudioRendererParameter worker_params;
242 std::shared_ptr<Kernel::WritableEvent> buffer_event; 245 std::shared_ptr<Kernel::WritableEvent> buffer_event;
diff --git a/src/audio_core/behavior_info.cpp b/src/audio_core/behavior_info.cpp
new file mode 100644
index 000000000..94b7a3bf1
--- /dev/null
+++ b/src/audio_core/behavior_info.cpp
@@ -0,0 +1,100 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <cstring>
6#include "audio_core/behavior_info.h"
7#include "audio_core/common.h"
8#include "common/logging/log.h"
9
10namespace AudioCore {
11
12BehaviorInfo::BehaviorInfo() : process_revision(CURRENT_PROCESS_REVISION) {}
13BehaviorInfo::~BehaviorInfo() = default;
14
15bool BehaviorInfo::UpdateInput(const std::vector<u8>& buffer, std::size_t offset) {
16 if (!CanConsumeBuffer(buffer.size(), offset, sizeof(InParams))) {
17 LOG_ERROR(Audio, "Buffer is an invalid size!");
18 return false;
19 }
20 InParams params{};
21 std::memcpy(&params, buffer.data() + offset, sizeof(InParams));
22
23 if (!IsValidRevision(params.revision)) {
24 LOG_ERROR(Audio, "Invalid input revision, revision=0x{:08X}", params.revision);
25 return false;
26 }
27
28 if (user_revision != params.revision) {
29 LOG_ERROR(Audio,
30 "User revision differs from input revision, expecting 0x{:08X} but got 0x{:08X}",
31 user_revision, params.revision);
32 return false;
33 }
34
35 ClearError();
36 UpdateFlags(params.flags);
37
38 // TODO(ogniK): Check input params size when InfoUpdater is used
39
40 return true;
41}
42
43bool BehaviorInfo::UpdateOutput(std::vector<u8>& buffer, std::size_t offset) {
44 if (!CanConsumeBuffer(buffer.size(), offset, sizeof(OutParams))) {
45 LOG_ERROR(Audio, "Buffer is an invalid size!");
46 return false;
47 }
48
49 OutParams params{};
50 std::memcpy(params.errors.data(), errors.data(), sizeof(ErrorInfo) * errors.size());
51 params.error_count = static_cast<u32_le>(error_count);
52 std::memcpy(buffer.data() + offset, &params, sizeof(OutParams));
53 return true;
54}
55
56void BehaviorInfo::ClearError() {
57 error_count = 0;
58}
59
60void BehaviorInfo::UpdateFlags(u64_le dest_flags) {
61 flags = dest_flags;
62}
63
64void BehaviorInfo::SetUserRevision(u32_le revision) {
65 user_revision = revision;
66}
67
68bool BehaviorInfo::IsAdpcmLoopContextBugFixed() const {
69 return IsRevisionSupported(2, user_revision);
70}
71
72bool BehaviorInfo::IsSplitterSupported() const {
73 return IsRevisionSupported(2, user_revision);
74}
75
76bool BehaviorInfo::IsLongSizePreDelaySupported() const {
77 return IsRevisionSupported(3, user_revision);
78}
79
80bool BehaviorInfo::IsAudioRenererProcessingTimeLimit80PercentSupported() const {
81 return IsRevisionSupported(5, user_revision);
82}
83
84bool BehaviorInfo::IsAudioRenererProcessingTimeLimit75PercentSupported() const {
85 return IsRevisionSupported(4, user_revision);
86}
87
88bool BehaviorInfo::IsAudioRenererProcessingTimeLimit70PercentSupported() const {
89 return IsRevisionSupported(1, user_revision);
90}
91
92bool BehaviorInfo::IsElapsedFrameCountSupported() const {
93 return IsRevisionSupported(5, user_revision);
94}
95
96bool BehaviorInfo::IsMemoryPoolForceMappingEnabled() const {
97 return (flags & 1) != 0;
98}
99
100} // namespace AudioCore
diff --git a/src/audio_core/behavior_info.h b/src/audio_core/behavior_info.h
new file mode 100644
index 000000000..c5e91ab39
--- /dev/null
+++ b/src/audio_core/behavior_info.h
@@ -0,0 +1,66 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8
9#include <vector>
10#include "common/common_funcs.h"
11#include "common/common_types.h"
12#include "common/swap.h"
13
14namespace AudioCore {
15class BehaviorInfo {
16public:
17 explicit BehaviorInfo();
18 ~BehaviorInfo();
19
20 bool UpdateInput(const std::vector<u8>& buffer, std::size_t offset);
21 bool UpdateOutput(std::vector<u8>& buffer, std::size_t offset);
22
23 void ClearError();
24 void UpdateFlags(u64_le dest_flags);
25 void SetUserRevision(u32_le revision);
26
27 bool IsAdpcmLoopContextBugFixed() const;
28 bool IsSplitterSupported() const;
29 bool IsLongSizePreDelaySupported() const;
30 bool IsAudioRenererProcessingTimeLimit80PercentSupported() const;
31 bool IsAudioRenererProcessingTimeLimit75PercentSupported() const;
32 bool IsAudioRenererProcessingTimeLimit70PercentSupported() const;
33 bool IsElapsedFrameCountSupported() const;
34 bool IsMemoryPoolForceMappingEnabled() const;
35
36private:
37 u32_le process_revision{};
38 u32_le user_revision{};
39 u64_le flags{};
40
41 struct ErrorInfo {
42 u32_le result{};
43 INSERT_PADDING_WORDS(1);
44 u64_le result_info{};
45 };
46 static_assert(sizeof(ErrorInfo) == 0x10, "ErrorInfo is an invalid size");
47
48 std::array<ErrorInfo, 10> errors{};
49 std::size_t error_count{};
50
51 struct InParams {
52 u32_le revision{};
53 u32_le padding{};
54 u64_le flags{};
55 };
56 static_assert(sizeof(InParams) == 0x10, "InParams is an invalid size");
57
58 struct OutParams {
59 std::array<ErrorInfo, 10> errors{};
60 u32_le error_count{};
61 INSERT_PADDING_BYTES(12);
62 };
63 static_assert(sizeof(OutParams) == 0xb0, "OutParams is an invalid size");
64};
65
66} // namespace AudioCore
diff --git a/src/audio_core/common.h b/src/audio_core/common.h
new file mode 100644
index 000000000..98478b66b
--- /dev/null
+++ b/src/audio_core/common.h
@@ -0,0 +1,47 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6#include "common/common_funcs.h"
7#include "common/common_types.h"
8#include "common/swap.h"
9#include "core/hle/result.h"
10
11namespace AudioCore {
12namespace Audren {
13constexpr ResultCode ERR_INVALID_PARAMETERS{ErrorModule::Audio, 41};
14}
15
16constexpr u32_le CURRENT_PROCESS_REVISION = Common::MakeMagic('R', 'E', 'V', '8');
17
18static constexpr u32 VersionFromRevision(u32_le rev) {
19 // "REV7" -> 7
20 return ((rev >> 24) & 0xff) - 0x30;
21}
22
23static constexpr bool IsRevisionSupported(u32 required, u32_le user_revision) {
24 const auto base = VersionFromRevision(user_revision);
25 return required <= base;
26}
27
28static constexpr bool IsValidRevision(u32_le revision) {
29 const auto base = VersionFromRevision(revision);
30 constexpr auto max_rev = VersionFromRevision(CURRENT_PROCESS_REVISION);
31 return base <= max_rev;
32}
33
34static constexpr bool CanConsumeBuffer(std::size_t size, std::size_t offset, std::size_t required) {
35 if (offset > size) {
36 return false;
37 }
38 if (size < required) {
39 return false;
40 }
41 if ((size - offset) < required) {
42 return false;
43 }
44 return true;
45}
46
47} // namespace AudioCore
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 07dd2caec..d8359abaa 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -94,9 +94,14 @@ private:
94 void RequestUpdateImpl(Kernel::HLERequestContext& ctx) { 94 void RequestUpdateImpl(Kernel::HLERequestContext& ctx) {
95 LOG_DEBUG(Service_Audio, "(STUBBED) called"); 95 LOG_DEBUG(Service_Audio, "(STUBBED) called");
96 96
97 ctx.WriteBuffer(renderer->UpdateAudioRenderer(ctx.ReadBuffer())); 97 auto result = renderer->UpdateAudioRenderer(ctx.ReadBuffer());
98
99 if (result.Succeeded()) {
100 ctx.WriteBuffer(result.Unwrap());
101 }
102
98 IPC::ResponseBuilder rb{ctx, 2}; 103 IPC::ResponseBuilder rb{ctx, 2};
99 rb.Push(RESULT_SUCCESS); 104 rb.Push(result.Code());
100 } 105 }
101 106
102 void Start(Kernel::HLERequestContext& ctx) { 107 void Start(Kernel::HLERequestContext& ctx) {