summaryrefslogtreecommitdiff
path: root/src/audio_core/voice_context.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio_core/voice_context.h')
-rw-r--r--src/audio_core/voice_context.h302
1 files changed, 0 insertions, 302 deletions
diff --git a/src/audio_core/voice_context.h b/src/audio_core/voice_context.h
deleted file mode 100644
index 259220dc7..000000000
--- a/src/audio_core/voice_context.h
+++ /dev/null
@@ -1,302 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <array>
7#include "audio_core/algorithm/interpolate.h"
8#include "audio_core/codec.h"
9#include "audio_core/common.h"
10#include "common/bit_field.h"
11#include "common/common_funcs.h"
12#include "common/common_types.h"
13
14namespace Core::Memory {
15class Memory;
16}
17
18namespace AudioCore {
19
20class BehaviorInfo;
21class VoiceContext;
22
23enum class SampleFormat : u8 {
24 Invalid = 0,
25 Pcm8 = 1,
26 Pcm16 = 2,
27 Pcm24 = 3,
28 Pcm32 = 4,
29 PcmFloat = 5,
30 Adpcm = 6,
31};
32
33enum class PlayState : u8 {
34 Started = 0,
35 Stopped = 1,
36 Paused = 2,
37};
38
39enum class ServerPlayState {
40 Play = 0,
41 Stop = 1,
42 RequestStop = 2,
43 Paused = 3,
44};
45
46struct BiquadFilterParameter {
47 bool enabled{};
48 INSERT_PADDING_BYTES(1);
49 std::array<s16, 3> numerator{};
50 std::array<s16, 2> denominator{};
51};
52static_assert(sizeof(BiquadFilterParameter) == 0xc, "BiquadFilterParameter is an invalid size");
53
54struct WaveBuffer {
55 u64_le buffer_address{};
56 u64_le buffer_size{};
57 s32_le start_sample_offset{};
58 s32_le end_sample_offset{};
59 u8 is_looping{};
60 u8 end_of_stream{};
61 u8 sent_to_server{};
62 INSERT_PADDING_BYTES(1);
63 s32 loop_count{};
64 u64 context_address{};
65 u64 context_size{};
66 u32 loop_start_sample{};
67 u32 loop_end_sample{};
68};
69static_assert(sizeof(WaveBuffer) == 0x38, "WaveBuffer is an invalid size");
70
71struct ServerWaveBuffer {
72 VAddr buffer_address{};
73 std::size_t buffer_size{};
74 s32 start_sample_offset{};
75 s32 end_sample_offset{};
76 bool is_looping{};
77 bool end_of_stream{};
78 VAddr context_address{};
79 std::size_t context_size{};
80 s32 loop_count{};
81 u32 loop_start_sample{};
82 u32 loop_end_sample{};
83 bool sent_to_dsp{true};
84};
85
86struct BehaviorFlags {
87 BitField<0, 1, u16> is_played_samples_reset_at_loop_point;
88 BitField<1, 1, u16> is_pitch_and_src_skipped;
89};
90static_assert(sizeof(BehaviorFlags) == 0x4, "BehaviorFlags is an invalid size");
91
92struct ADPCMContext {
93 u16 header;
94 s16 yn1;
95 s16 yn2;
96};
97static_assert(sizeof(ADPCMContext) == 0x6, "ADPCMContext is an invalid size");
98
99struct VoiceState {
100 s64 played_sample_count;
101 s32 offset;
102 s32 wave_buffer_index;
103 std::array<bool, AudioCommon::MAX_WAVE_BUFFERS> is_wave_buffer_valid;
104 s32 wave_buffer_consumed;
105 std::array<s32, AudioCommon::MAX_SAMPLE_HISTORY> sample_history;
106 s32 fraction;
107 VAddr context_address;
108 Codec::ADPCM_Coeff coeff;
109 ADPCMContext context;
110 std::array<s64, 2> biquad_filter_state;
111 std::array<s32, AudioCommon::MAX_MIX_BUFFERS> previous_samples;
112 u32 external_context_size;
113 bool is_external_context_used;
114 bool voice_dropped;
115 s32 loop_count;
116};
117
118class VoiceChannelResource {
119public:
120 struct InParams {
121 s32_le id{};
122 std::array<float_le, AudioCommon::MAX_MIX_BUFFERS> mix_volume{};
123 bool in_use{};
124 INSERT_PADDING_BYTES(11);
125 };
126 static_assert(sizeof(InParams) == 0x70, "InParams is an invalid size");
127};
128
129class ServerVoiceChannelResource {
130public:
131 explicit ServerVoiceChannelResource(s32 id_);
132 ~ServerVoiceChannelResource();
133
134 bool InUse() const;
135 float GetCurrentMixVolumeAt(std::size_t i) const;
136 float GetLastMixVolumeAt(std::size_t i) const;
137 void Update(VoiceChannelResource::InParams& in_params);
138 void UpdateLastMixVolumes();
139
140 const std::array<float, AudioCommon::MAX_MIX_BUFFERS>& GetCurrentMixVolume() const;
141 const std::array<float, AudioCommon::MAX_MIX_BUFFERS>& GetLastMixVolume() const;
142
143private:
144 s32 id{};
145 std::array<float, AudioCommon::MAX_MIX_BUFFERS> mix_volume{};
146 std::array<float, AudioCommon::MAX_MIX_BUFFERS> last_mix_volume{};
147 bool in_use{};
148};
149
150class VoiceInfo {
151public:
152 struct InParams {
153 s32_le id{};
154 u32_le node_id{};
155 u8 is_new{};
156 u8 is_in_use{};
157 PlayState play_state{};
158 SampleFormat sample_format{};
159 s32_le sample_rate{};
160 s32_le priority{};
161 s32_le sorting_order{};
162 s32_le channel_count{};
163 float_le pitch{};
164 float_le volume{};
165 std::array<BiquadFilterParameter, 2> biquad_filter{};
166 s32_le wave_buffer_count{};
167 s16_le wave_buffer_head{};
168 INSERT_PADDING_BYTES(6);
169 u64_le additional_params_address{};
170 u64_le additional_params_size{};
171 s32_le mix_id{};
172 s32_le splitter_info_id{};
173 std::array<WaveBuffer, 4> wave_buffer{};
174 std::array<u32_le, 6> voice_channel_resource_ids{};
175 // TODO(ogniK): Remaining flags
176 u8 is_voice_drop_flag_clear_requested{};
177 u8 wave_buffer_flush_request_count{};
178 INSERT_PADDING_BYTES(2);
179 BehaviorFlags behavior_flags{};
180 INSERT_PADDING_BYTES(16);
181 };
182 static_assert(sizeof(InParams) == 0x170, "InParams is an invalid size");
183
184 struct OutParams {
185 u64_le played_sample_count{};
186 u32_le wave_buffer_consumed{};
187 u8 voice_dropped{};
188 INSERT_PADDING_BYTES(3);
189 };
190 static_assert(sizeof(OutParams) == 0x10, "OutParams is an invalid size");
191};
192
193class ServerVoiceInfo {
194public:
195 struct InParams {
196 bool in_use{};
197 bool is_new{};
198 bool should_depop{};
199 SampleFormat sample_format{};
200 s32 sample_rate{};
201 s32 channel_count{};
202 s32 id{};
203 s32 node_id{};
204 s32 mix_id{};
205 ServerPlayState current_playstate{};
206 ServerPlayState last_playstate{};
207 s32 priority{};
208 s32 sorting_order{};
209 float pitch{};
210 float volume{};
211 float last_volume{};
212 std::array<BiquadFilterParameter, AudioCommon::MAX_BIQUAD_FILTERS> biquad_filter{};
213 s32 wave_buffer_count{};
214 s16 wave_buffer_head{};
215 INSERT_PADDING_BYTES(2);
216 BehaviorFlags behavior_flags{};
217 VAddr additional_params_address{};
218 std::size_t additional_params_size{};
219 std::array<ServerWaveBuffer, AudioCommon::MAX_WAVE_BUFFERS> wave_buffer{};
220 std::array<s32, AudioCommon::MAX_CHANNEL_COUNT> voice_channel_resource_id{};
221 s32 splitter_info_id{};
222 u8 wave_buffer_flush_request_count{};
223 bool voice_drop_flag{};
224 bool buffer_mapped{};
225 std::array<bool, AudioCommon::MAX_BIQUAD_FILTERS> was_biquad_filter_enabled{};
226 };
227
228 struct OutParams {
229 s64 played_sample_count{};
230 s32 wave_buffer_consumed{};
231 };
232
233 ServerVoiceInfo();
234 ~ServerVoiceInfo();
235 void Initialize();
236 void UpdateParameters(const VoiceInfo::InParams& voice_in, BehaviorInfo& behavior_info);
237 void UpdateWaveBuffers(const VoiceInfo::InParams& voice_in,
238 std::array<VoiceState*, AudioCommon::MAX_CHANNEL_COUNT>& voice_states,
239 BehaviorInfo& behavior_info);
240 void UpdateWaveBuffer(ServerWaveBuffer& out_wavebuffer, const WaveBuffer& in_wave_buffer,
241 SampleFormat sample_format, bool is_buffer_valid,
242 BehaviorInfo& behavior_info);
243 void WriteOutStatus(VoiceInfo::OutParams& voice_out, VoiceInfo::InParams& voice_in,
244 std::array<VoiceState*, AudioCommon::MAX_CHANNEL_COUNT>& voice_states);
245
246 const InParams& GetInParams() const;
247 InParams& GetInParams();
248
249 const OutParams& GetOutParams() const;
250 OutParams& GetOutParams();
251
252 bool ShouldSkip() const;
253 bool UpdateForCommandGeneration(VoiceContext& voice_context);
254 void ResetResources(VoiceContext& voice_context);
255 bool UpdateParametersForCommandGeneration(
256 std::array<VoiceState*, AudioCommon::MAX_CHANNEL_COUNT>& dsp_voice_states);
257 void FlushWaveBuffers(u8 flush_count,
258 std::array<VoiceState*, AudioCommon::MAX_CHANNEL_COUNT>& dsp_voice_states,
259 s32 channel_count);
260 void SetWaveBufferCompleted(VoiceState& dsp_state, const ServerWaveBuffer& wave_buffer);
261
262private:
263 std::vector<s16> stored_samples;
264 InParams in_params{};
265 OutParams out_params{};
266
267 bool HasValidWaveBuffer(const VoiceState* state) const;
268};
269
270class VoiceContext {
271public:
272 explicit VoiceContext(std::size_t voice_count_);
273 ~VoiceContext();
274
275 std::size_t GetVoiceCount() const;
276 ServerVoiceChannelResource& GetChannelResource(std::size_t i);
277 const ServerVoiceChannelResource& GetChannelResource(std::size_t i) const;
278 VoiceState& GetState(std::size_t i);
279 const VoiceState& GetState(std::size_t i) const;
280 VoiceState& GetDspSharedState(std::size_t i);
281 const VoiceState& GetDspSharedState(std::size_t i) const;
282 ServerVoiceInfo& GetInfo(std::size_t i);
283 const ServerVoiceInfo& GetInfo(std::size_t i) const;
284 ServerVoiceInfo& GetSortedInfo(std::size_t i);
285 const ServerVoiceInfo& GetSortedInfo(std::size_t i) const;
286
287 s32 DecodePcm16(s32* output_buffer, ServerWaveBuffer* wave_buffer, s32 channel,
288 s32 channel_count, s32 buffer_offset, s32 sample_count,
289 Core::Memory::Memory& memory);
290 void SortInfo();
291 void UpdateStateByDspShared();
292
293private:
294 std::size_t voice_count{};
295 std::vector<ServerVoiceChannelResource> voice_channel_resources{};
296 std::vector<VoiceState> voice_states{};
297 std::vector<VoiceState> dsp_voice_states{};
298 std::vector<ServerVoiceInfo> voice_info{};
299 std::vector<ServerVoiceInfo*> sorted_voice_info{};
300};
301
302} // namespace AudioCore