summaryrefslogtreecommitdiffstats
path: root/src/audio_core/renderer/effect/effect_info_base.h
blob: b49503409a874e3ef33dbecebd21ec73e73335a4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <array>

#include "audio_core/common/common.h"
#include "audio_core/renderer/behavior/behavior_info.h"
#include "audio_core/renderer/effect/effect_result_state.h"
#include "audio_core/renderer/memory/address_info.h"
#include "audio_core/renderer/memory/pool_mapper.h"
#include "common/common_types.h"

namespace AudioCore::Renderer {
/**
 * Base of all effects. Holds various data and functions used for all derived effects.
 * Should not be used directly.
 */
class EffectInfoBase {
public:
    enum class Type : u8 {
        Invalid,
        Mix,
        Aux,
        Delay,
        Reverb,
        I3dl2Reverb,
        BiquadFilter,
        LightLimiter,
        Capture,
        Compressor,
    };

    enum class UsageState {
        Invalid,
        New,
        Enabled,
        Disabled,
    };

    enum class OutStatus : u8 {
        Invalid,
        New,
        Initialized,
        Used,
        Removed,
    };

    enum class ParameterState : u8 {
        Initialized,
        Updating,
        Updated,
    };

    struct InParameterVersion1 {
        /* 0x00 */ Type type;
        /* 0x01 */ bool is_new;
        /* 0x02 */ bool enabled;
        /* 0x04 */ u32 mix_id;
        /* 0x08 */ CpuAddr workbuffer;
        /* 0x10 */ CpuAddr workbuffer_size;
        /* 0x18 */ u32 process_order;
        /* 0x1C */ char unk1C[0x4];
        /* 0x20 */ std::array<u8, 0xA0> specific;
    };
    static_assert(sizeof(InParameterVersion1) == 0xC0,
                  "EffectInfoBase::InParameterVersion1 has the wrong size!");

    struct InParameterVersion2 {
        /* 0x00 */ Type type;
        /* 0x01 */ bool is_new;
        /* 0x02 */ bool enabled;
        /* 0x04 */ u32 mix_id;
        /* 0x08 */ CpuAddr workbuffer;
        /* 0x10 */ CpuAddr workbuffer_size;
        /* 0x18 */ u32 process_order;
        /* 0x1C */ char unk1C[0x4];
        /* 0x20 */ std::array<u8, 0xA0> specific;
    };
    static_assert(sizeof(InParameterVersion2) == 0xC0,
                  "EffectInfoBase::InParameterVersion2 has the wrong size!");

    struct OutStatusVersion1 {
        /* 0x00 */ OutStatus state;
        /* 0x01 */ char unk01[0xF];
    };
    static_assert(sizeof(OutStatusVersion1) == 0x10,
                  "EffectInfoBase::OutStatusVersion1 has the wrong size!");

    struct OutStatusVersion2 {
        /* 0x00 */ OutStatus state;
        /* 0x01 */ char unk01[0xF];
        /* 0x10 */ EffectResultState result_state;
    };
    static_assert(sizeof(OutStatusVersion2) == 0x90,
                  "EffectInfoBase::OutStatusVersion2 has the wrong size!");

    struct State {
        std::array<u8, 0x500> buffer;
    };
    static_assert(sizeof(State) == 0x500, "EffectInfoBase::State has the wrong size!");

    EffectInfoBase() {
        Cleanup();
    }

    virtual ~EffectInfoBase() = default;

    /**
     * Cleanup this effect, resetting it to a starting state.
     */
    void Cleanup() {
        type = Type::Invalid;
        enabled = false;
        mix_id = UnusedMixId;
        process_order = InvalidProcessOrder;
        buffer_unmapped = false;
        parameter = {};
        for (auto& workbuffer : workbuffers) {
            workbuffer.Setup(CpuAddr(0), 0);
        }
    }

    /**
     * Forcibly unmap all assigned workbuffers from the AudioRenderer.
     *
     * @param pool_mapper - Mapper to unmap the buffers.
     */
    void ForceUnmapBuffers(const PoolMapper& pool_mapper) {
        for (auto& workbuffer : workbuffers) {
            if (workbuffer.GetReference(false) != 0) {
                pool_mapper.ForceUnmapPointer(workbuffer);
            }
        }
    }

    /**
     * Check if this effect is enabled.
     *
     * @return True if effect is enabled, otherwise false.
     */
    bool IsEnabled() const {
        return enabled;
    }

    /**
     * Check if this effect should not be generated.
     *
     * @return True if effect should be skipped, otherwise false.
     */
    bool ShouldSkip() const {
        return buffer_unmapped;
    }

    /**
     * Get the type of this effect.
     *
     * @return The type of this effect. See EffectInfoBase::Type
     */
    Type GetType() const {
        return type;
    }

    /**
     * Set the type of this effect.
     *
     * @param type_ - The new type of this effect.
     */
    void SetType(const Type type_) {
        type = type_;
    }

    /**
     * Get the mix id of this effect.
     *
     * @return Mix id of this effect.
     */
    s32 GetMixId() const {
        return mix_id;
    }

    /**
     * Get the processing order of this effect.
     *
     * @return Process order of this effect.
     */
    s32 GetProcessingOrder() const {
        return process_order;
    }

    /**
     * Get this effect's parameter data.
     *
     * @return Pointer to the parameter, must be cast to the correct type.
     */
    u8* GetParameter() {
        return parameter.data();
    }

    /**
     * Get this effect's parameter data.
     *
     * @return Pointer to the parameter, must be cast to the correct type.
     */
    u8* GetStateBuffer() {
        return state.data();
    }

    /**
     * Set this effect's usage state.
     *
     * @param usage - new usage state of this effect.
     */
    void SetUsage(const UsageState usage) {
        usage_state = usage;
    }

    /**
     * Check if this effects need to have its workbuffer information updated.
     * Version 1.
     *
     * @param params - Input parameters.
     * @return True if workbuffers need updating, otherwise false.
     */
    bool ShouldUpdateWorkBufferInfo(const InParameterVersion1& params) const {
        return buffer_unmapped || params.is_new;
    }

    /**
     * Check if this effects need to have its workbuffer information updated.
     * Version 2.
     *
     * @param params - Input parameters.
     * @return True if workbuffers need updating, otherwise false.
     */
    bool ShouldUpdateWorkBufferInfo(const InParameterVersion2& params) const {
        return buffer_unmapped || params.is_new;
    }

    /**
     * Get the current usage state of this effect.
     *
     * @return The current usage state.
     */
    UsageState GetUsage() const {
        return usage_state;
    }

    /**
     * Write the current state. Version 1.
     *
     * @param out_status      - Status to write.
     * @param renderer_active - Is the AudioRenderer active?
     */
    void StoreStatus(OutStatusVersion1& out_status, const bool renderer_active) const {
        if (renderer_active) {
            if (usage_state != UsageState::Disabled) {
                out_status.state = OutStatus::Used;
            } else {
                out_status.state = OutStatus::Removed;
            }
        } else if (usage_state == UsageState::New) {
            out_status.state = OutStatus::Used;
        } else {
            out_status.state = OutStatus::Removed;
        }
    }

    /**
     * Write the current state. Version 2.
     *
     * @param out_status      - Status to write.
     * @param renderer_active - Is the AudioRenderer active?
     */
    void StoreStatus(OutStatusVersion2& out_status, const bool renderer_active) const {
        if (renderer_active) {
            if (usage_state != UsageState::Disabled) {
                out_status.state = OutStatus::Used;
            } else {
                out_status.state = OutStatus::Removed;
            }
        } else if (usage_state == UsageState::New) {
            out_status.state = OutStatus::Used;
        } else {
            out_status.state = OutStatus::Removed;
        }
    }

    /**
     * Update the info with new parameters, version 1.
     *
     * @param error_info  - Used to write call result code.
     * @param params      - New parameters to update the info with.
     * @param pool_mapper - Pool for mapping buffers.
     */
    virtual void Update(BehaviorInfo::ErrorInfo& error_info,
                        [[maybe_unused]] const InParameterVersion1& params,
                        [[maybe_unused]] const PoolMapper& pool_mapper) {
        error_info.error_code = ResultSuccess;
        error_info.address = CpuAddr(0);
    }

    /**
     * Update the info with new parameters, version 2.
     *
     * @param error_info  - Used to write call result code.
     * @param params      - New parameters to update the info with.
     * @param pool_mapper - Pool for mapping buffers.
     */
    virtual void Update(BehaviorInfo::ErrorInfo& error_info,
                        [[maybe_unused]] const InParameterVersion2& params,
                        [[maybe_unused]] const PoolMapper& pool_mapper) {
        error_info.error_code = ResultSuccess;
        error_info.address = CpuAddr(0);
    }

    /**
     * Update the info after command generation. Usually only changes its state.
     */
    virtual void UpdateForCommandGeneration() {}

    /**
     * Initialize a new result state. Version 2 only, unused.
     *
     * @param result_state - Result state to initialize.
     */
    virtual void InitializeResultState([[maybe_unused]] EffectResultState& result_state) {}

    /**
     * Update the host-side state with the ADSP-side state. Version 2 only, unused.
     *
     * @param cpu_state - Host-side result state to update.
     * @param dsp_state - AudioRenderer-side result state to update from.
     */
    virtual void UpdateResultState([[maybe_unused]] EffectResultState& cpu_state,
                                   [[maybe_unused]] EffectResultState& dsp_state) {}

    /**
     * Get a workbuffer assigned to this effect with the given index.
     *
     * @param index - Workbuffer index.
     * @return Address of the buffer.
     */
    virtual CpuAddr GetWorkbuffer([[maybe_unused]] s32 index) {
        return 0;
    }

    /**
     * Get the first workbuffer assigned to this effect.
     *
     * @param index - Workbuffer index. Unused.
     * @return Address of the buffer.
     */
    CpuAddr GetSingleBuffer([[maybe_unused]] const s32 index) {
        if (enabled) {
            return workbuffers[0].GetReference(true);
        }

        if (usage_state != UsageState::Disabled) {
            const auto ref{workbuffers[0].GetReference(false)};
            const auto size{workbuffers[0].GetSize()};
            if (ref != 0 && size > 0) {
                // Invalidate DSP cache
            }
        }
        return 0;
    }

    /**
     * Get the send buffer info, used by Aux and Capture.
     *
     * @return Address of the buffer info.
     */
    CpuAddr GetSendBufferInfo() const {
        return send_buffer_info;
    }

    /**
     * Get the send buffer, used by Aux and Capture.
     *
     * @return Address of the buffer.
     */
    CpuAddr GetSendBuffer() const {
        return send_buffer;
    }

    /**
     * Get the return buffer info, used by Aux and Capture.
     *
     * @return Address of the buffer info.
     */
    CpuAddr GetReturnBufferInfo() const {
        return return_buffer_info;
    }

    /**
     * Get the return buffer, used by Aux and Capture.
     *
     * @return Address of the buffer.
     */
    CpuAddr GetReturnBuffer() const {
        return return_buffer;
    }

protected:
    /// Type of this effect. May be changed
    Type type{Type::Invalid};
    /// Is this effect enabled?
    bool enabled{};
    /// Are this effect's buffers unmapped?
    bool buffer_unmapped{};
    /// Current usage state
    UsageState usage_state{UsageState::Invalid};
    /// Mix id of this effect
    s32 mix_id{UnusedMixId};
    /// Process order of this effect
    s32 process_order{InvalidProcessOrder};
    /// Workbuffers assigned to this effect
    std::array<AddressInfo, 2> workbuffers{AddressInfo(CpuAddr(0), 0), AddressInfo(CpuAddr(0), 0)};
    /// Aux/Capture buffer info for reading
    CpuAddr send_buffer_info{};
    /// Aux/Capture buffer for reading
    CpuAddr send_buffer{};
    /// Aux/Capture buffer info for writing
    CpuAddr return_buffer_info{};
    /// Aux/Capture buffer for writing
    CpuAddr return_buffer{};
    /// Parameters of this effect
    std::array<u8, sizeof(InParameterVersion2)> parameter{};
    /// State of this effect used by the AudioRenderer across calls
    std::array<u8, sizeof(State)> state{};
};

} // namespace AudioCore::Renderer