summaryrefslogtreecommitdiff
path: root/src/audio_core/renderer/sink
diff options
context:
space:
mode:
authorGravatar Kelebek12022-07-16 23:48:45 +0100
committerGravatar Kelebek12022-07-22 01:11:32 +0100
commit458da8a94877677f086f06cdeecf959ec4283a33 (patch)
tree583166d77602ad90a0d552f37de8729ad80fd6c1 /src/audio_core/renderer/sink
parentMerge pull request #8598 from Link4565/recv-dontwait (diff)
downloadyuzu-458da8a94877677f086f06cdeecf959ec4283a33.tar.gz
yuzu-458da8a94877677f086f06cdeecf959ec4283a33.tar.xz
yuzu-458da8a94877677f086f06cdeecf959ec4283a33.zip
Project Andio
Diffstat (limited to 'src/audio_core/renderer/sink')
-rw-r--r--src/audio_core/renderer/sink/circular_buffer_sink_info.cpp76
-rw-r--r--src/audio_core/renderer/sink/circular_buffer_sink_info.h41
-rw-r--r--src/audio_core/renderer/sink/device_sink_info.cpp57
-rw-r--r--src/audio_core/renderer/sink/device_sink_info.h40
-rw-r--r--src/audio_core/renderer/sink/sink_context.cpp21
-rw-r--r--src/audio_core/renderer/sink/sink_context.h47
-rw-r--r--src/audio_core/renderer/sink/sink_info_base.cpp51
-rw-r--r--src/audio_core/renderer/sink/sink_info_base.h177
8 files changed, 510 insertions, 0 deletions
diff --git a/src/audio_core/renderer/sink/circular_buffer_sink_info.cpp b/src/audio_core/renderer/sink/circular_buffer_sink_info.cpp
new file mode 100644
index 000000000..d91f10402
--- /dev/null
+++ b/src/audio_core/renderer/sink/circular_buffer_sink_info.cpp
@@ -0,0 +1,76 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "audio_core/renderer/memory/pool_mapper.h"
5#include "audio_core/renderer/sink/circular_buffer_sink_info.h"
6#include "audio_core/renderer/upsampler/upsampler_manager.h"
7
8namespace AudioCore::AudioRenderer {
9
10CircularBufferSinkInfo::CircularBufferSinkInfo() {
11 state.fill(0);
12 parameter.fill(0);
13 type = Type::CircularBufferSink;
14
15 auto state_{reinterpret_cast<CircularBufferState*>(state.data())};
16 state_->address_info.Setup(0, 0);
17}
18
19void CircularBufferSinkInfo::CleanUp() {
20 auto state_{reinterpret_cast<DeviceState*>(state.data())};
21
22 if (state_->upsampler_info) {
23 state_->upsampler_info->manager->Free(state_->upsampler_info);
24 state_->upsampler_info = nullptr;
25 }
26
27 parameter.fill(0);
28 type = Type::Invalid;
29}
30
31void CircularBufferSinkInfo::Update(BehaviorInfo::ErrorInfo& error_info, OutStatus& out_status,
32 const InParameter& in_params, const PoolMapper& pool_mapper) {
33 const auto buffer_params{
34 reinterpret_cast<const CircularBufferInParameter*>(&in_params.circular_buffer)};
35 auto current_params{reinterpret_cast<CircularBufferInParameter*>(parameter.data())};
36 auto current_state{reinterpret_cast<CircularBufferState*>(state.data())};
37
38 if (in_use == buffer_params->in_use && !buffer_unmapped) {
39 error_info.error_code = ResultSuccess;
40 error_info.address = CpuAddr(0);
41 out_status.writeOffset = current_state->last_pos2;
42 return;
43 }
44
45 node_id = in_params.node_id;
46 in_use = in_params.in_use;
47
48 if (in_use) {
49 buffer_unmapped =
50 !pool_mapper.TryAttachBuffer(error_info, current_state->address_info,
51 buffer_params->cpu_address, buffer_params->size);
52 *current_params = *buffer_params;
53 } else {
54 *current_params = *buffer_params;
55 }
56 out_status.writeOffset = current_state->last_pos2;
57}
58
59void CircularBufferSinkInfo::UpdateForCommandGeneration() {
60 if (in_use) {
61 auto params{reinterpret_cast<CircularBufferInParameter*>(parameter.data())};
62 auto state_{reinterpret_cast<CircularBufferState*>(state.data())};
63
64 const auto pos{state_->current_pos};
65 state_->last_pos2 = state_->last_pos;
66 state_->last_pos = pos;
67
68 state_->current_pos += static_cast<s32>(params->input_count * params->sample_count *
69 GetSampleFormatByteSize(SampleFormat::PcmInt16));
70 if (params->size > 0) {
71 state_->current_pos %= params->size;
72 }
73 }
74}
75
76} // namespace AudioCore::AudioRenderer
diff --git a/src/audio_core/renderer/sink/circular_buffer_sink_info.h b/src/audio_core/renderer/sink/circular_buffer_sink_info.h
new file mode 100644
index 000000000..3356213ea
--- /dev/null
+++ b/src/audio_core/renderer/sink/circular_buffer_sink_info.h
@@ -0,0 +1,41 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "audio_core/renderer/sink/sink_info_base.h"
7#include "common/common_types.h"
8
9namespace AudioCore::AudioRenderer {
10/**
11 * Info for a circular buffer sink.
12 */
13class CircularBufferSinkInfo : public SinkInfoBase {
14public:
15 CircularBufferSinkInfo();
16
17 /**
18 * Clean up for info, resetting it to a default state.
19 */
20 void CleanUp() override;
21
22 /**
23 * Update the info according to parameters, and write the current state to out_status.
24 *
25 * @param error_info - Output error code.
26 * @param out_status - Output status.
27 * @param in_params - Input parameters.
28 * @param pool_mapper - Used to map the circular buffer.
29 */
30 void Update(BehaviorInfo::ErrorInfo& error_info, OutStatus& out_status,
31 const InParameter& in_params, const PoolMapper& pool_mapper) override;
32
33 /**
34 * Update the circular buffer on command generation, incrementing its current offsets.
35 */
36 void UpdateForCommandGeneration() override;
37};
38static_assert(sizeof(CircularBufferSinkInfo) <= sizeof(SinkInfoBase),
39 "CircularBufferSinkInfo is too large!");
40
41} // namespace AudioCore::AudioRenderer
diff --git a/src/audio_core/renderer/sink/device_sink_info.cpp b/src/audio_core/renderer/sink/device_sink_info.cpp
new file mode 100644
index 000000000..b7b3d6f1d
--- /dev/null
+++ b/src/audio_core/renderer/sink/device_sink_info.cpp
@@ -0,0 +1,57 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "audio_core/renderer/sink/device_sink_info.h"
5#include "audio_core/renderer/upsampler/upsampler_manager.h"
6
7namespace AudioCore::AudioRenderer {
8
9DeviceSinkInfo::DeviceSinkInfo() {
10 state.fill(0);
11 parameter.fill(0);
12 type = Type::DeviceSink;
13}
14
15void DeviceSinkInfo::CleanUp() {
16 auto state_{reinterpret_cast<DeviceState*>(state.data())};
17
18 if (state_->upsampler_info) {
19 state_->upsampler_info->manager->Free(state_->upsampler_info);
20 state_->upsampler_info = nullptr;
21 }
22
23 parameter.fill(0);
24 type = Type::Invalid;
25}
26
27void DeviceSinkInfo::Update(BehaviorInfo::ErrorInfo& error_info, OutStatus& out_status,
28 const InParameter& in_params,
29 [[maybe_unused]] const PoolMapper& pool_mapper) {
30
31 const auto device_params{reinterpret_cast<const DeviceInParameter*>(&in_params.device)};
32 auto current_params{reinterpret_cast<DeviceInParameter*>(parameter.data())};
33
34 if (in_use == in_params.in_use) {
35 current_params->downmix_enabled = device_params->downmix_enabled;
36 current_params->downmix_coeff = device_params->downmix_coeff;
37 } else {
38 type = in_params.type;
39 in_use = in_params.in_use;
40 node_id = in_params.node_id;
41 *current_params = *device_params;
42 }
43
44 auto current_state{reinterpret_cast<DeviceState*>(state.data())};
45
46 for (size_t i = 0; i < current_state->downmix_coeff.size(); i++) {
47 current_state->downmix_coeff[i] = current_params->downmix_coeff[i];
48 }
49
50 std::memset(&out_status, 0, sizeof(OutStatus));
51 error_info.error_code = ResultSuccess;
52 error_info.address = CpuAddr(0);
53}
54
55void DeviceSinkInfo::UpdateForCommandGeneration() {}
56
57} // namespace AudioCore::AudioRenderer
diff --git a/src/audio_core/renderer/sink/device_sink_info.h b/src/audio_core/renderer/sink/device_sink_info.h
new file mode 100644
index 000000000..a1c441454
--- /dev/null
+++ b/src/audio_core/renderer/sink/device_sink_info.h
@@ -0,0 +1,40 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "audio_core/renderer/sink/sink_info_base.h"
7#include "common/common_types.h"
8
9namespace AudioCore::AudioRenderer {
10/**
11 * Info for a device sink.
12 */
13class DeviceSinkInfo : public SinkInfoBase {
14public:
15 DeviceSinkInfo();
16
17 /**
18 * Clean up for info, resetting it to a default state.
19 */
20 void CleanUp() override;
21
22 /**
23 * Update the info according to parameters, and write the current state to out_status.
24 *
25 * @param error_info - Output error code.
26 * @param out_status - Output status.
27 * @param in_params - Input parameters.
28 * @param pool_mapper - Unused.
29 */
30 void Update(BehaviorInfo::ErrorInfo& error_info, OutStatus& out_status,
31 const InParameter& in_params, const PoolMapper& pool_mapper) override;
32
33 /**
34 * Update the device sink on command generation, unused.
35 */
36 void UpdateForCommandGeneration() override;
37};
38static_assert(sizeof(DeviceSinkInfo) <= sizeof(SinkInfoBase), "DeviceSinkInfo is too large!");
39
40} // namespace AudioCore::AudioRenderer
diff --git a/src/audio_core/renderer/sink/sink_context.cpp b/src/audio_core/renderer/sink/sink_context.cpp
new file mode 100644
index 000000000..634bc1cf9
--- /dev/null
+++ b/src/audio_core/renderer/sink/sink_context.cpp
@@ -0,0 +1,21 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "audio_core/renderer/sink/sink_context.h"
5
6namespace AudioCore::AudioRenderer {
7
8void SinkContext::Initialize(std::span<SinkInfoBase> sink_infos_, const u32 sink_count_) {
9 sink_infos = sink_infos_;
10 sink_count = sink_count_;
11}
12
13SinkInfoBase* SinkContext::GetInfo(const u32 index) {
14 return &sink_infos[index];
15}
16
17u32 SinkContext::GetCount() const {
18 return sink_count;
19}
20
21} // namespace AudioCore::AudioRenderer
diff --git a/src/audio_core/renderer/sink/sink_context.h b/src/audio_core/renderer/sink/sink_context.h
new file mode 100644
index 000000000..185572e29
--- /dev/null
+++ b/src/audio_core/renderer/sink/sink_context.h
@@ -0,0 +1,47 @@
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/sink/sink_info_base.h"
9#include "common/common_types.h"
10
11namespace AudioCore::AudioRenderer {
12/**
13 * Manages output sinks.
14 */
15class SinkContext {
16public:
17 /**
18 * Initialize the sink context.
19 *
20 * @param sink_infos - Workbuffer for the sinks.
21 * @param sink_count - Number of sinks in the buffer.
22 */
23 void Initialize(std::span<SinkInfoBase> sink_infos, u32 sink_count);
24
25 /**
26 * Get a given index's info.
27 *
28 * @param index - Sink index to get.
29 * @return The sink info base for the given index.
30 */
31 SinkInfoBase* GetInfo(u32 index);
32
33 /**
34 * Get the current number of sinks.
35 *
36 * @return The number of sinks.
37 */
38 u32 GetCount() const;
39
40private:
41 /// Buffer of sink infos
42 std::span<SinkInfoBase> sink_infos{};
43 /// Number of sinks in the buffer
44 u32 sink_count{};
45};
46
47} // namespace AudioCore::AudioRenderer
diff --git a/src/audio_core/renderer/sink/sink_info_base.cpp b/src/audio_core/renderer/sink/sink_info_base.cpp
new file mode 100644
index 000000000..4279beaa0
--- /dev/null
+++ b/src/audio_core/renderer/sink/sink_info_base.cpp
@@ -0,0 +1,51 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "audio_core/renderer/memory/pool_mapper.h"
5#include "audio_core/renderer/sink/sink_info_base.h"
6
7namespace AudioCore::AudioRenderer {
8
9void SinkInfoBase::CleanUp() {
10 type = Type::Invalid;
11}
12
13void SinkInfoBase::Update(BehaviorInfo::ErrorInfo& error_info, OutStatus& out_status,
14 [[maybe_unused]] const InParameter& in_params,
15 [[maybe_unused]] const PoolMapper& pool_mapper) {
16 std::memset(&out_status, 0, sizeof(OutStatus));
17 error_info.error_code = ResultSuccess;
18 error_info.address = CpuAddr(0);
19}
20
21void SinkInfoBase::UpdateForCommandGeneration() {}
22
23SinkInfoBase::DeviceState* SinkInfoBase::GetDeviceState() {
24 return reinterpret_cast<DeviceState*>(state.data());
25}
26
27SinkInfoBase::Type SinkInfoBase::GetType() const {
28 return type;
29}
30
31bool SinkInfoBase::IsUsed() const {
32 return in_use;
33}
34
35bool SinkInfoBase::ShouldSkip() const {
36 return buffer_unmapped;
37}
38
39u32 SinkInfoBase::GetNodeId() const {
40 return node_id;
41}
42
43u8* SinkInfoBase::GetState() {
44 return state.data();
45}
46
47u8* SinkInfoBase::GetParameter() {
48 return parameter.data();
49}
50
51} // namespace AudioCore::AudioRenderer
diff --git a/src/audio_core/renderer/sink/sink_info_base.h b/src/audio_core/renderer/sink/sink_info_base.h
new file mode 100644
index 000000000..a1b855f20
--- /dev/null
+++ b/src/audio_core/renderer/sink/sink_info_base.h
@@ -0,0 +1,177 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <array>
7
8#include "audio_core/common/common.h"
9#include "audio_core/renderer/behavior/behavior_info.h"
10#include "audio_core/renderer/memory/address_info.h"
11#include "common/common_types.h"
12#include "common/fixed_point.h"
13
14namespace AudioCore::AudioRenderer {
15struct UpsamplerInfo;
16class PoolMapper;
17
18/**
19 * Base for the circular buffer and device sinks, holding their states for the AudioRenderer and
20 * their parametetrs for generating sink commands.
21 */
22class SinkInfoBase {
23public:
24 enum class Type : u8 {
25 Invalid,
26 DeviceSink,
27 CircularBufferSink,
28 };
29
30 struct DeviceInParameter {
31 /* 0x000 */ char name[0x100];
32 /* 0x100 */ u32 input_count;
33 /* 0x104 */ std::array<s8, MaxChannels> inputs;
34 /* 0x10A */ char unk10A[0x1];
35 /* 0x10B */ bool downmix_enabled;
36 /* 0x10C */ std::array<f32, 4> downmix_coeff;
37 };
38 static_assert(sizeof(DeviceInParameter) == 0x11C, "DeviceInParameter has the wrong size!");
39
40 struct DeviceState {
41 /* 0x00 */ UpsamplerInfo* upsampler_info;
42 /* 0x08 */ std::array<Common::FixedPoint<16, 16>, 4> downmix_coeff;
43 /* 0x18 */ char unk18[0x18];
44 };
45 static_assert(sizeof(DeviceState) == 0x30, "DeviceState has the wrong size!");
46
47 struct CircularBufferInParameter {
48 /* 0x00 */ u64 cpu_address;
49 /* 0x08 */ u32 size;
50 /* 0x0C */ u32 input_count;
51 /* 0x10 */ u32 sample_count;
52 /* 0x14 */ u32 previous_pos;
53 /* 0x18 */ SampleFormat format;
54 /* 0x1C */ std::array<s8, MaxChannels> inputs;
55 /* 0x22 */ bool in_use;
56 /* 0x23 */ char unk23[0x5];
57 };
58 static_assert(sizeof(CircularBufferInParameter) == 0x28,
59 "CircularBufferInParameter has the wrong size!");
60
61 struct CircularBufferState {
62 /* 0x00 */ u32 last_pos2;
63 /* 0x04 */ s32 current_pos;
64 /* 0x08 */ u32 last_pos;
65 /* 0x0C */ char unk0C[0x4];
66 /* 0x10 */ AddressInfo address_info;
67 };
68 static_assert(sizeof(CircularBufferState) == 0x30, "CircularBufferState has the wrong size!");
69
70 struct InParameter {
71 /* 0x000 */ Type type;
72 /* 0x001 */ bool in_use;
73 /* 0x004 */ u32 node_id;
74 /* 0x008 */ char unk08[0x18];
75 union {
76 /* 0x020 */ DeviceInParameter device;
77 /* 0x020 */ CircularBufferInParameter circular_buffer;
78 };
79 };
80 static_assert(sizeof(InParameter) == 0x140, "SinkInfoBase::InParameter has the wrong size!");
81
82 struct OutStatus {
83 /* 0x00 */ u32 writeOffset;
84 /* 0x04 */ char unk04[0x1C];
85 }; // size == 0x20
86 static_assert(sizeof(OutStatus) == 0x20, "SinkInfoBase::OutStatus has the wrong size!");
87
88 virtual ~SinkInfoBase() = default;
89
90 /**
91 * Clean up for info, resetting it to a default state.
92 */
93 virtual void CleanUp();
94
95 /**
96 * Update the info according to parameters, and write the current state to out_status.
97 *
98 * @param error_info - Output error code.
99 * @param out_status - Output status.
100 * @param in_params - Input parameters.
101 * @param pool_mapper - Used to map the circular buffer.
102 */
103 virtual void Update(BehaviorInfo::ErrorInfo& error_info, OutStatus& out_status,
104 [[maybe_unused]] const InParameter& in_params,
105 [[maybe_unused]] const PoolMapper& pool_mapper);
106
107 /**
108 * Update the circular buffer on command generation, incrementing its current offsets.
109 */
110 virtual void UpdateForCommandGeneration();
111
112 /**
113 * Get the state as a device sink.
114 *
115 * @return Device state.
116 */
117 DeviceState* GetDeviceState();
118
119 /**
120 * Get the type of this sink.
121 *
122 * @return Either Device, Circular, or Invalid.
123 */
124 Type GetType() const;
125
126 /**
127 * Check if this sink is in use.
128 *
129 * @return True if used, otherwise false.
130 */
131 bool IsUsed() const;
132
133 /**
134 * Check if this sink should be skipped for updates.
135 *
136 * @return True if it should be skipped, otherwise false.
137 */
138 bool ShouldSkip() const;
139
140 /**
141 * Get the node if of this sink.
142 *
143 * @return Node id for this sink.
144 */
145 u32 GetNodeId() const;
146
147 /**
148 * Get the state of this sink.
149 *
150 * @return Pointer to the state, must be cast to the correct type.
151 */
152 u8* GetState();
153
154 /**
155 * Get the parameters of this sink.
156 *
157 * @return Pointer to the parameters, must be cast to the correct type.
158 */
159 u8* GetParameter();
160
161protected:
162 /// Type of this sink
163 Type type{Type::Invalid};
164 /// Is this sink in use?
165 bool in_use{};
166 /// Is this sink's buffer unmapped? Circular only
167 bool buffer_unmapped{};
168 /// Node id for this sink
169 u32 node_id{};
170 /// State buffer for this sink
171 std::array<u8, std::max(sizeof(DeviceState), sizeof(CircularBufferState))> state{};
172 /// Parameter buffer for this sink
173 std::array<u8, std::max(sizeof(DeviceInParameter), sizeof(CircularBufferInParameter))>
174 parameter{};
175};
176
177} // namespace AudioCore::AudioRenderer