summaryrefslogtreecommitdiffstats
path: root/src/audio_core/renderer/command/command_generator.h
blob: b3cd7b408f109558ed420411d2457cfeb287940d (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
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <span>

#include "audio_core/renderer/command/commands.h"
#include "audio_core/renderer/performance/performance_manager.h"
#include "common/common_types.h"

namespace AudioCore {
struct AudioRendererSystemContext;

namespace AudioRenderer {
class CommandBuffer;
struct CommandListHeader;
class VoiceContext;
class MixContext;
class EffectContext;
class SplitterContext;
class SinkContext;
class BehaviorInfo;
class VoiceInfo;
struct VoiceState;
class MixInfo;
class SinkInfoBase;

/**
 * Generates all commands to build up a command list, which are sent to the AudioRender for
 * processing.
 */
class CommandGenerator {
public:
    explicit CommandGenerator(CommandBuffer& command_buffer,
                              const CommandListHeader& command_list_header,
                              const AudioRendererSystemContext& render_context,
                              VoiceContext& voice_context, MixContext& mix_context,
                              EffectContext& effect_context, SinkContext& sink_context,
                              SplitterContext& splitter_context,
                              PerformanceManager* performance_manager);

    /**
     * Calculate the buffer size needed for commands.
     *
     * @param behavior - Used to check what features are enabled.
     * @param params    - Input rendering parameters for numbers of voices/mixes/sinks etc.
     */
    static u64 CalculateCommandBufferSize(const BehaviorInfo& behavior,
                                          const AudioRendererParameterInternal& params) {
        u64 size{0};

        // Effects
        size += params.effects * sizeof(EffectInfoBase);

        // Voices
        u64 voice_size{0};
        if (behavior.IsWaveBufferVer2Supported()) {
            voice_size = std::max(std::max(sizeof(AdpcmDataSourceVersion2Command),
                                           sizeof(PcmInt16DataSourceVersion2Command)),
                                  sizeof(PcmFloatDataSourceVersion2Command));
        } else {
            voice_size = std::max(std::max(sizeof(AdpcmDataSourceVersion1Command),
                                           sizeof(PcmInt16DataSourceVersion1Command)),
                                  sizeof(PcmFloatDataSourceVersion1Command));
        }
        voice_size += sizeof(BiquadFilterCommand) * MaxBiquadFilters;
        voice_size += sizeof(VolumeRampCommand);
        voice_size += sizeof(MixRampGroupedCommand);

        size += params.voices * (params.splitter_infos * sizeof(DepopPrepareCommand) + voice_size);

        // Sub mixes
        size += sizeof(DepopForMixBuffersCommand) +
                (sizeof(MixCommand) * MaxMixBuffers) * MaxMixBuffers;

        // Final mix
        size += sizeof(DepopForMixBuffersCommand) + sizeof(VolumeCommand) * MaxMixBuffers;

        // Splitters
        size += params.splitter_destinations * sizeof(MixRampCommand) * MaxMixBuffers;

        // Sinks
        size +=
            params.sinks * std::max(sizeof(DeviceSinkCommand), sizeof(CircularBufferSinkCommand));

        // Performance
        size += (params.effects + params.voices + params.sinks + params.sub_mixes + 1 +
                 PerformanceManager::MaxDetailEntries) *
                sizeof(PerformanceCommand);
        return size;
    }

    /**
     * Get the current command buffer used to generate commands.
     *
     * @return The command buffer.
     */
    CommandBuffer& GetCommandBuffer() {
        return command_buffer;
    }

    /**
     * Get the current performance manager,
     *
     * @return The performance manager. May be nullptr.
     */
    PerformanceManager* GetPerformanceManager() {
        return performance_manager;
    }

    /**
     * Generate a data source command.
     * These are the basis for all audio output.
     *
     * @param voice_info  - Generate the command from this voice.
     * @param voice_state - State used by the AudioRenderer across calls.
     * @param channel     - Channel index to generate the command into.
     */
    void GenerateDataSourceCommand(VoiceInfo& voice_info, const VoiceState& voice_state,
                                   s8 channel);

    /**
     * Generate voice mixing commands.
     * These are used to mix buffers together, to mix one input to many outputs,
     * and also used as copy commands to move data around and prevent it being accidentally
     * overwritten, e.g by another data source command into the same channel.
     *
     * @param mix_volumes      - Current volumes of the mix.
     * @param prev_mix_volumes - Previous volumes of the mix.
     * @param voice_state      - State used by the AudioRenderer across calls.
     * @param output_index     - Output mix buffer index.
     * @param buffer_count     - Number of active mix buffers.
     * @param input_index      - Input mix buffer index.
     * @param node_id          - Node id of the voice this command is generated for.
     */
    void GenerateVoiceMixCommand(std::span<const f32> mix_volumes,
                                 std::span<const f32> prev_mix_volumes,
                                 const VoiceState& voice_state, s16 output_index, s16 buffer_count,
                                 s16 input_index, s32 node_id);

    /**
     * Generate a biquad filter command for a voice.
     *
     * @param voice_info   - Voice info this command is generated from.
     * @param voice_state  - State used by the AudioRenderer across calls.
     * @param buffer_count - Number of active mix buffers.
     * @param channel      - Channel index of this command.
     * @param node_id      - Node id of the voice this command is generated for.
     */
    void GenerateBiquadFilterCommandForVoice(VoiceInfo& voice_info, const VoiceState& voice_state,
                                             s16 buffer_count, s8 channel, s32 node_id);

    /**
     * Generate commands for a voice.
     * Includes a data source, biquad filter, volume and mixing.
     *
     * @param voice_info - Voice info these commands are generated from.
     */
    void GenerateVoiceCommand(VoiceInfo& voice_info);

    /**
     * Generate commands for all voices.
     */
    void GenerateVoiceCommands();

    /**
     * Generate a mixing command.
     *
     * @param buffer_offset    - Base mix buffer offset to use.
     * @param effect_info_base - BufferMixer effect info.
     * @param node_id          - Node id of the mix this command is generated for.
     */
    void GenerateBufferMixerCommand(s16 buffer_offset, EffectInfoBase& effect_info_base,
                                    s32 node_id);

    /**
     * Generate a delay effect command.
     *
     * @param buffer_offset    - Base mix buffer offset to use.
     * @param effect_info_base - Delay effect info.
     * @param node_id          - Node id of the mix this command is generated for.
     */
    void GenerateDelayCommand(s16 buffer_offset, EffectInfoBase& effect_info_base, s32 node_id);

    /**
     * Generate a reverb effect command.
     *
     * @param buffer_offset                 - Base mix buffer offset to use.
     * @param effect_info_base              - Reverb effect info.
     * @param node_id                       - Node id of the mix this command is generated for.
     * @param long_size_pre_delay_supported - Use a longer pre-delay time before reverb starts.
     */
    void GenerateReverbCommand(s16 buffer_offset, EffectInfoBase& effect_info_base, s32 node_id,
                               bool long_size_pre_delay_supported);

    /**
     * Generate an I3DL2 reverb effect command.
     *
     * @param buffer_offset - Base mix buffer offset to use.
     * @param effect_info   - I3DL2Reverb effect info.
     * @param node_id       - Node id of the mix this command is generated for.
     */
    void GenerateI3dl2ReverbEffectCommand(s16 buffer_offset, EffectInfoBase& effect_info,
                                          s32 node_id);

    /**
     * Generate an aux effect command.
     *
     * @param buffer_offset - Base mix buffer offset to use.
     * @param effect_info   - Aux effect info.
     * @param node_id       - Node id of the mix this command is generated for.
     */
    void GenerateAuxCommand(s16 buffer_offset, EffectInfoBase& effect_info, s32 node_id);

    /**
     * Generate a biquad filter effect command.
     *
     * @param buffer_offset - Base mix buffer offset to use.
     * @param effect_info   - Aux effect info.
     * @param node_id       - Node id of the mix this command is generated for.
     */
    void GenerateBiquadFilterEffectCommand(s16 buffer_offset, EffectInfoBase& effect_info,
                                           s32 node_id);

    /**
     * Generate a light limiter effect command.
     *
     * @param buffer_offset - Base mix buffer offset to use.
     * @param effect_info   - Limiter effect info.
     * @param node_id       - Node id of the mix this command is generated for.
     * @param effect_index  - Index for the statistics state.
     */
    void GenerateLightLimiterEffectCommand(s16 buffer_offset, EffectInfoBase& effect_info,
                                           s32 node_id, u32 effect_index);

    /**
     * Generate a capture effect command.
     * Writes a mix buffer back to game memory.
     *
     * @param buffer_offset - Base mix buffer offset to use.
     * @param effect_info   - Capture effect info.
     * @param node_id       - Node id of the mix this command is generated for.
     */
    void GenerateCaptureCommand(s16 buffer_offset, EffectInfoBase& effect_info, s32 node_id);

    /**
     * Generate a compressor effect command.
     *
     * @param buffer_offset - Base mix buffer offset to use.
     * @param effect_info   - Compressor effect info.
     * @param node_id       - Node id of the mix this command is generated for.
     */
    void GenerateCompressorCommand(s16 buffer_offset, EffectInfoBase& effect_info, s32 node_id);

    /**
     * Generate all effect commands for a mix.
     *
     * @param mix_info - Mix to generate effects from.
     */
    void GenerateEffectCommand(MixInfo& mix_info);

    /**
     * Generate all mix commands.
     *
     * @param mix_info - Mix to generate effects from.
     */
    void GenerateMixCommands(MixInfo& mix_info);

    /**
     * Generate a submix command.
     * Generates all effects and all mixing commands.
     *
     * @param mix_info - Mix to generate effects from.
     */
    void GenerateSubMixCommand(MixInfo& mix_info);

    /**
     * Generate all submix command.
     */
    void GenerateSubMixCommands();

    /**
     * Generate the final mix.
     */
    void GenerateFinalMixCommand();

    /**
     * Generate the final mix commands.
     */
    void GenerateFinalMixCommands();

    /**
     * Generate all sink commands.
     */
    void GenerateSinkCommands();

    /**
     * Generate a sink command.
     * Sends samples out to the backend, or a game-supplied circular buffer.
     *
     * @param buffer_offset - Base mix buffer offset to use.
     * @param sink_info     - Sink info to generate the commands from.
     */
    void GenerateSinkCommand(s16 buffer_offset, SinkInfoBase& sink_info);

    /**
     * Generate a device sink command.
     * Sends samples out to the backend.
     *
     * @param buffer_offset - Base mix buffer offset to use.
     * @param sink_info     - Sink info to generate the commands from.
     */
    void GenerateDeviceSinkCommand(s16 buffer_offset, SinkInfoBase& sink_info);

    /**
     * Generate a performance command.
     * Used to report performance metrics of the AudioRenderer back to the game.
     *
     * @param node_id         - Node ID of the mix this command is generated for
     * @param state           - Output state of the generated performance command
     * @param entry_addresses - Addresses to be written
     */
    void GeneratePerformanceCommand(s32 node_id, PerformanceState state,
                                    const PerformanceEntryAddresses& entry_addresses);

private:
    /// Commands will be written by this buffer
    CommandBuffer& command_buffer;
    /// Header information for the commands generated
    const CommandListHeader& command_header;
    /// Various things to control generation
    const AudioRendererSystemContext& render_context;
    /// Used for generating voices
    VoiceContext& voice_context;
    /// Used for generating mixes
    MixContext& mix_context;
    /// Used for generating effects
    EffectContext& effect_context;
    /// Used for generating sinks
    SinkContext& sink_context;
    /// Used for generating submixes
    SplitterContext& splitter_context;
    /// Used for generating performance
    PerformanceManager* performance_manager;
};

} // namespace AudioRenderer
} // namespace AudioCore