summaryrefslogtreecommitdiff
path: root/src/audio_core/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio_core/common')
-rw-r--r--src/audio_core/common/audio_renderer_parameter.h60
-rw-r--r--src/audio_core/common/common.h138
-rw-r--r--src/audio_core/common/feature_support.h105
-rw-r--r--src/audio_core/common/wave_buffer.h35
-rw-r--r--src/audio_core/common/workbuffer_allocator.h100
5 files changed, 438 insertions, 0 deletions
diff --git a/src/audio_core/common/audio_renderer_parameter.h b/src/audio_core/common/audio_renderer_parameter.h
new file mode 100644
index 000000000..2f62c383b
--- /dev/null
+++ b/src/audio_core/common/audio_renderer_parameter.h
@@ -0,0 +1,60 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <span>
7
8#include "audio_core/renderer/behavior/behavior_info.h"
9#include "audio_core/renderer/memory/memory_pool_info.h"
10#include "audio_core/renderer/upsampler/upsampler_manager.h"
11#include "common/common_types.h"
12
13namespace AudioCore {
14/**
15 * Execution mode of the audio renderer.
16 * Only Auto is currently supported.
17 */
18enum class ExecutionMode : u8 {
19 Auto,
20 Manual,
21};
22
23/**
24 * Parameters from the game, passed to the audio renderer for initialisation.
25 */
26struct AudioRendererParameterInternal {
27 /* 0x00 */ u32 sample_rate;
28 /* 0x04 */ u32 sample_count;
29 /* 0x08 */ u32 mixes;
30 /* 0x0C */ u32 sub_mixes;
31 /* 0x10 */ u32 voices;
32 /* 0x14 */ u32 sinks;
33 /* 0x18 */ u32 effects;
34 /* 0x1C */ u32 perf_frames;
35 /* 0x20 */ u16 voice_drop_enabled;
36 /* 0x22 */ u8 rendering_device;
37 /* 0x23 */ ExecutionMode execution_mode;
38 /* 0x24 */ u32 splitter_infos;
39 /* 0x28 */ s32 splitter_destinations;
40 /* 0x2C */ u32 external_context_size;
41 /* 0x30 */ u32 revision;
42 /* 0x34 */ char unk34[0x4];
43};
44static_assert(sizeof(AudioRendererParameterInternal) == 0x38,
45 "AudioRendererParameterInternal has the wrong size!");
46
47/**
48 * Context for rendering, contains a bunch of useful fields for the command generator.
49 */
50struct AudioRendererSystemContext {
51 s32 session_id;
52 s8 channels;
53 s16 mix_buffer_count;
54 AudioRenderer::BehaviorInfo* behavior;
55 std::span<s32> depop_buffer;
56 AudioRenderer::UpsamplerManager* upsampler_manager;
57 AudioRenderer::MemoryPoolInfo* memory_pool_info;
58};
59
60} // namespace AudioCore
diff --git a/src/audio_core/common/common.h b/src/audio_core/common/common.h
new file mode 100644
index 000000000..6abd9be45
--- /dev/null
+++ b/src/audio_core/common/common.h
@@ -0,0 +1,138 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <numeric>
7#include <span>
8
9#include "common/assert.h"
10#include "common/common_funcs.h"
11#include "common/common_types.h"
12
13namespace AudioCore {
14using CpuAddr = std::uintptr_t;
15
16enum class PlayState : u8 {
17 Started,
18 Stopped,
19 Paused,
20};
21
22enum class SrcQuality : u8 {
23 Medium,
24 High,
25 Low,
26};
27
28enum class SampleFormat : u8 {
29 Invalid,
30 PcmInt8,
31 PcmInt16,
32 PcmInt24,
33 PcmInt32,
34 PcmFloat,
35 Adpcm,
36};
37
38enum class SessionTypes {
39 AudioIn,
40 AudioOut,
41 FinalOutputRecorder,
42};
43
44enum class Channels : u32 {
45 FrontLeft,
46 FrontRight,
47 Center,
48 LFE,
49 BackLeft,
50 BackRight,
51};
52
53// These are used by Delay, Reverb and I3dl2Reverb prior to Revision 11.
54enum class OldChannels : u32 {
55 FrontLeft,
56 FrontRight,
57 BackLeft,
58 BackRight,
59 Center,
60 LFE,
61};
62
63constexpr u32 BufferCount = 32;
64
65constexpr u32 MaxRendererSessions = 2;
66constexpr u32 TargetSampleCount = 240;
67constexpr u32 TargetSampleRate = 48'000;
68constexpr u32 MaxChannels = 6;
69constexpr u32 MaxMixBuffers = 24;
70constexpr u32 MaxWaveBuffers = 4;
71constexpr s32 LowestVoicePriority = 0xFF;
72constexpr s32 HighestVoicePriority = 0;
73constexpr u32 BufferAlignment = 0x40;
74constexpr u32 WorkbufferAlignment = 0x1000;
75constexpr s32 FinalMixId = 0;
76constexpr s32 InvalidDistanceFromFinalMix = std::numeric_limits<s32>::min();
77constexpr s32 UnusedSplitterId = -1;
78constexpr s32 UnusedMixId = std::numeric_limits<s32>::max();
79constexpr u32 InvalidNodeId = 0xF0000000;
80constexpr s32 InvalidProcessOrder = -1;
81constexpr u32 MaxBiquadFilters = 2;
82constexpr u32 MaxEffects = 256;
83
84constexpr bool IsChannelCountValid(u16 channel_count) {
85 return channel_count <= 6 &&
86 (channel_count == 1 || channel_count == 2 || channel_count == 4 || channel_count == 6);
87}
88
89constexpr void UseOldChannelMapping(std::span<s16> inputs, std::span<s16> outputs) {
90 constexpr auto old_center{static_cast<u32>(OldChannels::Center)};
91 constexpr auto new_center{static_cast<u32>(Channels::Center)};
92 constexpr auto old_lfe{static_cast<u32>(OldChannels::LFE)};
93 constexpr auto new_lfe{static_cast<u32>(Channels::LFE)};
94
95 auto center{inputs[old_center]};
96 auto lfe{inputs[old_lfe]};
97 inputs[old_center] = inputs[new_center];
98 inputs[old_lfe] = inputs[new_lfe];
99 inputs[new_center] = center;
100 inputs[new_lfe] = lfe;
101
102 center = outputs[old_center];
103 lfe = outputs[old_lfe];
104 outputs[old_center] = outputs[new_center];
105 outputs[old_lfe] = outputs[new_lfe];
106 outputs[new_center] = center;
107 outputs[new_lfe] = lfe;
108}
109
110constexpr u32 GetSplitterInParamHeaderMagic() {
111 return Common::MakeMagic('S', 'N', 'D', 'H');
112}
113
114constexpr u32 GetSplitterInfoMagic() {
115 return Common::MakeMagic('S', 'N', 'D', 'I');
116}
117
118constexpr u32 GetSplitterSendDataMagic() {
119 return Common::MakeMagic('S', 'N', 'D', 'D');
120}
121
122constexpr size_t GetSampleFormatByteSize(SampleFormat format) {
123 switch (format) {
124 case SampleFormat::PcmInt8:
125 return 1;
126 case SampleFormat::PcmInt16:
127 return 2;
128 case SampleFormat::PcmInt24:
129 return 3;
130 case SampleFormat::PcmInt32:
131 case SampleFormat::PcmFloat:
132 return 4;
133 default:
134 return 2;
135 }
136}
137
138} // namespace AudioCore
diff --git a/src/audio_core/common/feature_support.h b/src/audio_core/common/feature_support.h
new file mode 100644
index 000000000..55c9e690d
--- /dev/null
+++ b/src/audio_core/common/feature_support.h
@@ -0,0 +1,105 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <map>
7#include <ranges>
8#include <tuple>
9
10#include "common/assert.h"
11#include "common/common_funcs.h"
12#include "common/common_types.h"
13
14namespace AudioCore {
15constexpr u32 CurrentRevision = 11;
16
17enum class SupportTags {
18 CommandProcessingTimeEstimatorVersion4,
19 CommandProcessingTimeEstimatorVersion3,
20 CommandProcessingTimeEstimatorVersion2,
21 MultiTapBiquadFilterProcessing,
22 EffectInfoVer2,
23 WaveBufferVer2,
24 BiquadFilterFloatProcessing,
25 VolumeMixParameterPrecisionQ23,
26 MixInParameterDirtyOnlyUpdate,
27 BiquadFilterEffectStateClearBugFix,
28 VoicePlayedSampleCountResetAtLoopPoint,
29 VoicePitchAndSrcSkipped,
30 SplitterBugFix,
31 FlushVoiceWaveBuffers,
32 ElapsedFrameCount,
33 AudioRendererVariadicCommandBufferSize,
34 PerformanceMetricsDataFormatVersion2,
35 AudioRendererProcessingTimeLimit80Percent,
36 AudioRendererProcessingTimeLimit75Percent,
37 AudioRendererProcessingTimeLimit70Percent,
38 AdpcmLoopContextBugFix,
39 Splitter,
40 LongSizePreDelay,
41 AudioUsbDeviceOutput,
42 DeviceApiVersion2,
43 DelayChannelMappingChange,
44 ReverbChannelMappingChange,
45 I3dl2ReverbChannelMappingChange,
46
47 // Not a real tag, just here to get the count.
48 Size
49};
50
51constexpr u32 GetRevisionNum(u32 user_revision) {
52 if (user_revision >= 0x100) {
53 user_revision -= Common::MakeMagic('R', 'E', 'V', '0');
54 user_revision >>= 24;
55 }
56 return user_revision;
57};
58
59constexpr bool CheckFeatureSupported(SupportTags tag, u32 user_revision) {
60 constexpr std::array<std::pair<SupportTags, u32>, static_cast<u32>(SupportTags::Size)> features{
61 {
62 {SupportTags::AudioRendererProcessingTimeLimit70Percent, 1},
63 {SupportTags::Splitter, 2},
64 {SupportTags::AdpcmLoopContextBugFix, 2},
65 {SupportTags::LongSizePreDelay, 3},
66 {SupportTags::AudioUsbDeviceOutput, 4},
67 {SupportTags::AudioRendererProcessingTimeLimit75Percent, 4},
68 {SupportTags::VoicePlayedSampleCountResetAtLoopPoint, 5},
69 {SupportTags::VoicePitchAndSrcSkipped, 5},
70 {SupportTags::SplitterBugFix, 5},
71 {SupportTags::FlushVoiceWaveBuffers, 5},
72 {SupportTags::ElapsedFrameCount, 5},
73 {SupportTags::AudioRendererProcessingTimeLimit80Percent, 5},
74 {SupportTags::AudioRendererVariadicCommandBufferSize, 5},
75 {SupportTags::PerformanceMetricsDataFormatVersion2, 5},
76 {SupportTags::CommandProcessingTimeEstimatorVersion2, 5},
77 {SupportTags::BiquadFilterEffectStateClearBugFix, 6},
78 {SupportTags::BiquadFilterFloatProcessing, 7},
79 {SupportTags::VolumeMixParameterPrecisionQ23, 7},
80 {SupportTags::MixInParameterDirtyOnlyUpdate, 7},
81 {SupportTags::WaveBufferVer2, 8},
82 {SupportTags::CommandProcessingTimeEstimatorVersion3, 8},
83 {SupportTags::EffectInfoVer2, 9},
84 {SupportTags::CommandProcessingTimeEstimatorVersion4, 10},
85 {SupportTags::MultiTapBiquadFilterProcessing, 10},
86 {SupportTags::DelayChannelMappingChange, 11},
87 {SupportTags::ReverbChannelMappingChange, 11},
88 {SupportTags::I3dl2ReverbChannelMappingChange, 11},
89 }};
90
91 const auto& feature =
92 std::ranges::find_if(features, [tag](const auto& entry) { return entry.first == tag; });
93 if (feature == features.cend()) {
94 LOG_ERROR(Service_Audio, "Invalid SupportTag {}!", static_cast<u32>(tag));
95 return false;
96 }
97 user_revision = GetRevisionNum(user_revision);
98 return (*feature).second <= user_revision;
99}
100
101constexpr bool CheckValidRevision(u32 user_revision) {
102 return GetRevisionNum(user_revision) <= CurrentRevision;
103};
104
105} // namespace AudioCore
diff --git a/src/audio_core/common/wave_buffer.h b/src/audio_core/common/wave_buffer.h
new file mode 100644
index 000000000..fc478ef79
--- /dev/null
+++ b/src/audio_core/common/wave_buffer.h
@@ -0,0 +1,35 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "common/common_types.h"
7
8namespace AudioCore {
9
10struct WaveBufferVersion1 {
11 CpuAddr buffer;
12 u64 buffer_size;
13 u32 start_offset;
14 u32 end_offset;
15 bool loop;
16 bool stream_ended;
17 CpuAddr context;
18 u64 context_size;
19};
20
21struct WaveBufferVersion2 {
22 CpuAddr buffer;
23 CpuAddr context;
24 u64 buffer_size;
25 u64 context_size;
26 u32 start_offset;
27 u32 end_offset;
28 u32 loop_start_offset;
29 u32 loop_end_offset;
30 s32 loop_count;
31 bool loop;
32 bool stream_ended;
33};
34
35} // namespace AudioCore
diff --git a/src/audio_core/common/workbuffer_allocator.h b/src/audio_core/common/workbuffer_allocator.h
new file mode 100644
index 000000000..fb89f97fe
--- /dev/null
+++ b/src/audio_core/common/workbuffer_allocator.h
@@ -0,0 +1,100 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <span>
7
8#include "common/alignment.h"
9#include "common/assert.h"
10#include "common/common_types.h"
11
12namespace AudioCore {
13/**
14 * Responsible for allocating up a workbuffer into multiple pieces.
15 * Takes in a buffer and size (it does not own them), and allocates up the buffer via Allocate.
16 */
17class WorkbufferAllocator {
18public:
19 explicit WorkbufferAllocator(std::span<u8> buffer_, u64 size_)
20 : buffer{reinterpret_cast<u64>(buffer_.data())}, size{size_} {}
21
22 /**
23 * Allocate the given count of T elements, aligned to alignment.
24 *
25 * @param count - The number of elements to allocate.
26 * @param alignment - The required starting alignment.
27 * @return Non-owning container of allocated elements.
28 */
29 template <typename T>
30 std::span<T> Allocate(u64 count, u64 alignment) {
31 u64 out{0};
32 u64 byte_size{count * sizeof(T)};
33
34 if (byte_size > 0) {
35 auto current{buffer + offset};
36 auto aligned_buffer{Common::AlignUp(current, alignment)};
37 if (aligned_buffer + byte_size <= buffer + size) {
38 out = aligned_buffer;
39 offset = byte_size - buffer + aligned_buffer;
40 } else {
41 LOG_ERROR(
42 Service_Audio,
43 "Allocated buffer was too small to hold new alloc.\nAllocator size={:08X}, "
44 "offset={:08X}.\nAttempting to allocate {:08X} with alignment={:02X}",
45 size, offset, byte_size, alignment);
46 count = 0;
47 }
48 }
49
50 return std::span<T>(reinterpret_cast<T*>(out), count);
51 }
52
53 /**
54 * Align the current offset to the given alignment.
55 *
56 * @param alignment - The required starting alignment.
57 */
58 void Align(u64 alignment) {
59 auto current{buffer + offset};
60 auto aligned_buffer{Common::AlignUp(current, alignment)};
61 offset = 0 - buffer + aligned_buffer;
62 }
63
64 /**
65 * Get the current buffer offset.
66 *
67 * @return The current allocating offset.
68 */
69 u64 GetCurrentOffset() const {
70 return offset;
71 }
72
73 /**
74 * Get the current buffer size.
75 *
76 * @return The size of the current buffer.
77 */
78 u64 GetSize() const {
79 return size;
80 }
81
82 /**
83 * Get the remaining size that can be allocated.
84 *
85 * @return The remaining size left in the buffer.
86 */
87 u64 GetRemainingSize() const {
88 return size - offset;
89 }
90
91private:
92 /// The buffer into which we are allocating.
93 u64 buffer;
94 /// Size of the buffer we're allocating to.
95 u64 size;
96 /// Current offset into the buffer, an error will be thrown if it exceeds size.
97 u64 offset{};
98};
99
100} // namespace AudioCore