summaryrefslogtreecommitdiff
path: root/src/audio_core/effect_context.cpp
diff options
context:
space:
mode:
authorGravatar David Marcec2020-08-17 01:23:55 +1000
committerGravatar David Marcec2020-08-17 01:23:55 +1000
commit80ac1331b545d993aa7c205dc24f8b20a4d6d44e (patch)
treef0b1138935e239ff7c5766fc26bc259b375ae712 /src/audio_core/effect_context.cpp
parentDisable biquad filter (diff)
downloadyuzu-80ac1331b545d993aa7c205dc24f8b20a4d6d44e.tar.gz
yuzu-80ac1331b545d993aa7c205dc24f8b20a4d6d44e.tar.xz
yuzu-80ac1331b545d993aa7c205dc24f8b20a4d6d44e.zip
Preliminary effects
Diffstat (limited to 'src/audio_core/effect_context.cpp')
-rw-r--r--src/audio_core/effect_context.cpp271
1 files changed, 263 insertions, 8 deletions
diff --git a/src/audio_core/effect_context.cpp b/src/audio_core/effect_context.cpp
index 2497d2f32..adfec3df5 100644
--- a/src/audio_core/effect_context.cpp
+++ b/src/audio_core/effect_context.cpp
@@ -6,6 +6,12 @@
6#include "audio_core/effect_context.h" 6#include "audio_core/effect_context.h"
7 7
8namespace AudioCore { 8namespace AudioCore {
9namespace {
10bool ValidChannelCountForEffect(s32 channel_count) {
11 return channel_count == 1 || channel_count == 2 || channel_count == 4 || channel_count == 6;
12}
13} // namespace
14
9EffectContext::EffectContext(std::size_t effect_count) : effect_count(effect_count) { 15EffectContext::EffectContext(std::size_t effect_count) : effect_count(effect_count) {
10 effects.reserve(effect_count); 16 effects.reserve(effect_count);
11 std::generate_n(std::back_inserter(effects), effect_count, 17 std::generate_n(std::back_inserter(effects), effect_count,
@@ -21,24 +27,273 @@ EffectBase* EffectContext::GetInfo(std::size_t i) {
21 return effects.at(i).get(); 27 return effects.at(i).get();
22} 28}
23 29
30EffectBase* EffectContext::RetargetEffect(std::size_t i, EffectType effect) {
31 switch (effect) {
32 case EffectType::Invalid:
33 effects[i] = std::make_unique<EffectStubbed>();
34 break;
35 case EffectType::BufferMixer:
36 effects[i] = std::make_unique<EffectBufferMixer>();
37 break;
38 case EffectType::Aux:
39 effects[i] = std::make_unique<EffectAuxInfo>();
40 break;
41 case EffectType::Delay:
42 effects[i] = std::make_unique<EffectDelay>();
43 break;
44 case EffectType::Reverb:
45 effects[i] = std::make_unique<EffectReverb>();
46 break;
47 case EffectType::I3dl2Reverb:
48 effects[i] = std::make_unique<EffectI3dl2Reverb>();
49 break;
50 case EffectType::BiquadFilter:
51 effects[i] = std::make_unique<EffectBiquadFilter>();
52 break;
53 default:
54 UNREACHABLE_MSG("Unimplemented effect {}", effect);
55 effects[i] = std::make_unique<EffectStubbed>();
56 }
57 return GetInfo(i);
58}
59
24const EffectBase* EffectContext::GetInfo(std::size_t i) const { 60const EffectBase* EffectContext::GetInfo(std::size_t i) const {
25 return effects.at(i).get(); 61 return effects.at(i).get();
26} 62}
27 63
28EffectStubbed::EffectStubbed() : EffectBase::EffectBase() {} 64EffectStubbed::EffectStubbed() : EffectBase::EffectBase(EffectType::Invalid) {}
29EffectStubbed::~EffectStubbed() = default; 65EffectStubbed::~EffectStubbed() = default;
30 66
31void EffectStubbed::Update(EffectInfo::InParams& in_params) { 67void EffectStubbed::Update(EffectInfo::InParams& in_params) {}
32 if (in_params.is_new) { 68void EffectStubbed::UpdateForCommandGeneration() {}
33 usage = UsageStatus::New;
34 }
35}
36 69
37EffectBase::EffectBase() = default; 70EffectBase::EffectBase(EffectType effect_type) : effect_type(effect_type) {}
38EffectBase::~EffectBase() = default; 71EffectBase::~EffectBase() = default;
39 72
40UsageStatus EffectBase::GetUsage() const { 73UsageState EffectBase::GetUsage() const {
41 return usage; 74 return usage;
42} 75}
43 76
77EffectType EffectBase::GetType() const {
78 return effect_type;
79}
80
81bool EffectBase::IsEnabled() const {
82 return enabled;
83}
84
85s32 EffectBase::GetMixID() const {
86 return mix_id;
87}
88
89s32 EffectBase::GetProcessingOrder() const {
90 return processing_order;
91}
92
93EffectI3dl2Reverb::EffectI3dl2Reverb() : EffectGeneric::EffectGeneric(EffectType::I3dl2Reverb) {}
94EffectI3dl2Reverb::~EffectI3dl2Reverb() = default;
95
96void EffectI3dl2Reverb::Update(EffectInfo::InParams& in_params) {
97 auto& internal_params = GetParams();
98 const auto* reverb_params = reinterpret_cast<I3dl2ReverbParams*>(in_params.raw.data());
99 if (!ValidChannelCountForEffect(reverb_params->max_channels)) {
100 UNREACHABLE_MSG("Invalid reverb max channel count {}", reverb_params->max_channels);
101 return;
102 }
103
104 const auto last_status = internal_params.status;
105 mix_id = in_params.mix_id;
106 processing_order = in_params.processing_order;
107 internal_params = *reverb_params;
108 if (!ValidChannelCountForEffect(reverb_params->channel_count)) {
109 internal_params.channel_count = internal_params.max_channels;
110 }
111 enabled = in_params.is_enabled;
112 if (last_status != ParameterStatus::Updated) {
113 internal_params.status = last_status;
114 }
115
116 if (in_params.is_new || skipped) {
117 usage = UsageState::Initialized;
118 internal_params.status = ParameterStatus::Initialized;
119 skipped = in_params.buffer_address == 0 || in_params.buffer_size == 0;
120 }
121}
122
123void EffectI3dl2Reverb::UpdateForCommandGeneration() {
124 if (enabled) {
125 usage = UsageState::Running;
126 } else {
127 usage = UsageState::Stopped;
128 }
129 GetParams().status = ParameterStatus::Updated;
130}
131
132EffectBiquadFilter::EffectBiquadFilter() : EffectGeneric::EffectGeneric(EffectType::BiquadFilter) {}
133EffectBiquadFilter::~EffectBiquadFilter() = default;
134
135void EffectBiquadFilter::Update(EffectInfo::InParams& in_params) {
136 auto& internal_params = GetParams();
137 const auto* biquad_params = reinterpret_cast<BiquadFilterParams*>(in_params.raw.data());
138 mix_id = in_params.mix_id;
139 processing_order = in_params.processing_order;
140 internal_params = *biquad_params;
141 enabled = in_params.is_enabled;
142}
143
144void EffectBiquadFilter::UpdateForCommandGeneration() {
145 if (enabled) {
146 usage = UsageState::Running;
147 } else {
148 usage = UsageState::Stopped;
149 }
150 GetParams().status = ParameterStatus::Updated;
151}
152
153EffectAuxInfo::EffectAuxInfo() : EffectGeneric::EffectGeneric(EffectType::Aux) {}
154EffectAuxInfo::~EffectAuxInfo() = default;
155
156void EffectAuxInfo::Update(EffectInfo::InParams& in_params) {
157 const auto* aux_params = reinterpret_cast<AuxInfo*>(in_params.raw.data());
158 mix_id = in_params.mix_id;
159 processing_order = in_params.processing_order;
160 GetParams() = *aux_params;
161 enabled = in_params.is_enabled;
162
163 if (in_params.is_new || skipped) {
164 skipped = aux_params->send_buffer_info == 0 || aux_params->return_buffer_info == 0;
165 if (skipped) {
166 return;
167 }
168
169 // There's two AuxInfos which are an identical size, the first one is managed by the cpu,
170 // the second is managed by the dsp. All we care about is managing the DSP one
171 send_info = aux_params->send_buffer_info + sizeof(AuxInfoDSP);
172 send_buffer = aux_params->send_buffer_info + (sizeof(AuxInfoDSP) * 2);
173
174 recv_info = aux_params->return_buffer_info + sizeof(AuxInfoDSP);
175 recv_buffer = aux_params->return_buffer_info + (sizeof(AuxInfoDSP) * 2);
176 }
177}
178
179void EffectAuxInfo::UpdateForCommandGeneration() {
180 if (enabled) {
181 usage = UsageState::Running;
182 } else {
183 usage = UsageState::Stopped;
184 }
185}
186
187const VAddr EffectAuxInfo::GetSendInfo() const {
188 return send_info;
189}
190
191const VAddr EffectAuxInfo::GetSendBuffer() const {
192 return send_buffer;
193}
194
195const VAddr EffectAuxInfo::GetRecvInfo() const {
196 return recv_info;
197}
198
199const VAddr EffectAuxInfo::GetRecvBuffer() const {
200 return recv_buffer;
201}
202
203EffectDelay::EffectDelay() : EffectGeneric::EffectGeneric(EffectType::Delay) {}
204EffectDelay::~EffectDelay() = default;
205
206void EffectDelay::Update(EffectInfo::InParams& in_params) {
207 const auto* delay_params = reinterpret_cast<DelayParams*>(in_params.raw.data());
208 auto& internal_params = GetParams();
209 if (!ValidChannelCountForEffect(delay_params->max_channels)) {
210 return;
211 }
212
213 const auto last_status = internal_params.status;
214 mix_id = in_params.mix_id;
215 processing_order = in_params.processing_order;
216 internal_params = *delay_params;
217 if (!ValidChannelCountForEffect(delay_params->channels)) {
218 internal_params.channels = internal_params.max_channels;
219 }
220 enabled = in_params.is_enabled;
221
222 if (last_status != ParameterStatus::Updated) {
223 internal_params.status = last_status;
224 }
225
226 if (in_params.is_new || skipped) {
227 usage = UsageState::Initialized;
228 internal_params.status = ParameterStatus::Initialized;
229 skipped = in_params.buffer_address == 0 || in_params.buffer_size == 0;
230 }
231}
232
233void EffectDelay::UpdateForCommandGeneration() {
234 if (enabled) {
235 usage = UsageState::Running;
236 } else {
237 usage = UsageState::Stopped;
238 }
239 GetParams().status = ParameterStatus::Updated;
240}
241
242EffectBufferMixer::EffectBufferMixer() : EffectGeneric::EffectGeneric(EffectType::BufferMixer) {}
243EffectBufferMixer::~EffectBufferMixer() = default;
244
245void EffectBufferMixer::Update(EffectInfo::InParams& in_params) {
246 mix_id = in_params.mix_id;
247 processing_order = in_params.processing_order;
248 GetParams() = *reinterpret_cast<BufferMixerParams*>(in_params.raw.data());
249 enabled = in_params.is_enabled;
250}
251
252void EffectBufferMixer::UpdateForCommandGeneration() {
253 if (enabled) {
254 usage = UsageState::Running;
255 } else {
256 usage = UsageState::Stopped;
257 }
258}
259
260EffectReverb::EffectReverb() : EffectGeneric::EffectGeneric(EffectType::Reverb) {}
261EffectReverb::~EffectReverb() = default;
262
263void EffectReverb::Update(EffectInfo::InParams& in_params) {
264 const auto* reverb_params = reinterpret_cast<ReverbParams*>(in_params.raw.data());
265 auto& internal_params = GetParams();
266 if (!ValidChannelCountForEffect(reverb_params->max_channels)) {
267 return;
268 }
269
270 const auto last_status = internal_params.status;
271 mix_id = in_params.mix_id;
272 processing_order = in_params.processing_order;
273 internal_params = *reverb_params;
274 if (!ValidChannelCountForEffect(reverb_params->channels)) {
275 internal_params.channels = internal_params.max_channels;
276 }
277 enabled = in_params.is_enabled;
278
279 if (last_status != ParameterStatus::Updated) {
280 internal_params.status = last_status;
281 }
282
283 if (in_params.is_new || skipped) {
284 usage = UsageState::Initialized;
285 internal_params.status = ParameterStatus::Initialized;
286 skipped = in_params.buffer_address == 0 || in_params.buffer_size == 0;
287 }
288}
289
290void EffectReverb::UpdateForCommandGeneration() {
291 if (enabled) {
292 usage = UsageState::Running;
293 } else {
294 usage = UsageState::Stopped;
295 }
296 GetParams().status = ParameterStatus::Updated;
297}
298
44} // namespace AudioCore 299} // namespace AudioCore