summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/audio_core/command_generator.cpp123
-rw-r--r--src/audio_core/command_generator.h8
2 files changed, 101 insertions, 30 deletions
diff --git a/src/audio_core/command_generator.cpp b/src/audio_core/command_generator.cpp
index 0c3b278ea..8f89292be 100644
--- a/src/audio_core/command_generator.cpp
+++ b/src/audio_core/command_generator.cpp
@@ -46,6 +46,24 @@ void ApplyGainWithoutDelta(s32* output, const s32* input, s32 gain, s32 sample_c
46 } 46 }
47} 47}
48 48
49s32 ApplyMixDepop(s32* output, s32 first_sample, s32 delta, s32 sample_count) {
50 const bool positive = first_sample > 0;
51 auto final_sample = std::abs(first_sample);
52 for (s32 i = 0; i < sample_count; i++) {
53 final_sample = static_cast<s32>((static_cast<s64>(final_sample) * delta) >> 15);
54 if (positive) {
55 output[i] += final_sample;
56 } else {
57 output[i] -= final_sample;
58 }
59 }
60 if (positive) {
61 return final_sample;
62 } else {
63 return -final_sample;
64 }
65}
66
49} // namespace 67} // namespace
50 68
51CommandGenerator::CommandGenerator(AudioCommon::AudioRendererParameter& worker_params, 69CommandGenerator::CommandGenerator(AudioCommon::AudioRendererParameter& worker_params,
@@ -55,12 +73,15 @@ CommandGenerator::CommandGenerator(AudioCommon::AudioRendererParameter& worker_p
55 splitter_context(splitter_context), memory(memory), 73 splitter_context(splitter_context), memory(memory),
56 mix_buffer((worker_params.mix_buffer_count + AudioCommon::MAX_CHANNEL_COUNT) * 74 mix_buffer((worker_params.mix_buffer_count + AudioCommon::MAX_CHANNEL_COUNT) *
57 worker_params.sample_count), 75 worker_params.sample_count),
58 sample_buffer(MIX_BUFFER_SIZE) {} 76 sample_buffer(MIX_BUFFER_SIZE),
77 depop_buffer((worker_params.mix_buffer_count + AudioCommon::MAX_CHANNEL_COUNT) *
78 worker_params.sample_count) {}
59CommandGenerator::~CommandGenerator() = default; 79CommandGenerator::~CommandGenerator() = default;
60 80
61void CommandGenerator::ClearMixBuffers() { 81void CommandGenerator::ClearMixBuffers() {
62 std::fill(mix_buffer.begin(), mix_buffer.end(), 0); 82 std::fill(mix_buffer.begin(), mix_buffer.end(), 0);
63 std::fill(sample_buffer.begin(), sample_buffer.end(), 0); 83 std::fill(sample_buffer.begin(), sample_buffer.end(), 0);
84 // std::fill(depop_buffer.begin(), depop_buffer.end(), 0);
64} 85}
65 86
66void CommandGenerator::GenerateVoiceCommands() { 87void CommandGenerator::GenerateVoiceCommands() {
@@ -195,32 +216,39 @@ void CommandGenerator::GenerateDataSourceCommand(ServerVoiceInfo& voice_info, Vo
195 auto& in_params = voice_info.GetInParams(); 216 auto& in_params = voice_info.GetInParams();
196 const auto depop = in_params.should_depop; 217 const auto depop = in_params.should_depop;
197 218
198 if (in_params.mix_id != AudioCommon::NO_MIX) {
199 [[maybe_unused]] auto& mix_info = mix_context.GetInfo(in_params.mix_id);
200 // mix_info.
201 // TODO(ogniK): Depop to destination mix
202 } else if (in_params.splitter_info_id != AudioCommon::NO_SPLITTER) {
203 // TODO(ogniK): Depop to splitter
204 }
205
206 if (depop) { 219 if (depop) {
207 return; 220 if (in_params.mix_id != AudioCommon::NO_MIX) {
208 } 221 auto& mix_info = mix_context.GetInfo(in_params.mix_id);
209 222 const auto& mix_in = mix_info.GetInParams();
210 switch (in_params.sample_format) { 223 GenerateDepopPrepareCommand(dsp_state, mix_in.buffer_count, mix_in.buffer_offset);
211 case SampleFormat::Pcm16: 224 } else if (in_params.splitter_info_id != AudioCommon::NO_SPLITTER) {
212 DecodeFromWaveBuffers(voice_info, GetChannelMixBuffer(channel), dsp_state, channel, 225 s32 index{};
213 worker_params.sample_rate, worker_params.sample_count, 226 while (const auto* destination =
214 in_params.node_id); 227 GetDestinationData(in_params.splitter_info_id, index++)) {
215 break; 228 if (!destination->IsConfigured()) {
216 case SampleFormat::Adpcm: 229 continue;
217 ASSERT(channel == 0 && in_params.channel_count == 1); 230 }
218 DecodeFromWaveBuffers(voice_info, GetChannelMixBuffer(0), dsp_state, 0, 231 auto& mix_info = mix_context.GetInfo(destination->GetMixId());
219 worker_params.sample_rate, worker_params.sample_count, 232 const auto& mix_in = mix_info.GetInParams();
220 in_params.node_id); 233 GenerateDepopPrepareCommand(dsp_state, mix_in.buffer_count, mix_in.buffer_offset);
221 break; 234 }
222 default: 235 }
223 UNREACHABLE_MSG("Unimplemented sample format={}", in_params.sample_format); 236 } else {
237 switch (in_params.sample_format) {
238 case SampleFormat::Pcm16:
239 DecodeFromWaveBuffers(voice_info, GetChannelMixBuffer(channel), dsp_state, channel,
240 worker_params.sample_rate, worker_params.sample_count,
241 in_params.node_id);
242 break;
243 case SampleFormat::Adpcm:
244 ASSERT(channel == 0 && in_params.channel_count == 1);
245 DecodeFromWaveBuffers(voice_info, GetChannelMixBuffer(0), dsp_state, 0,
246 worker_params.sample_rate, worker_params.sample_count,
247 in_params.node_id);
248 break;
249 default:
250 UNREACHABLE_MSG("Unimplemented sample format={}", in_params.sample_format);
251 }
224 } 252 }
225} 253}
226 254
@@ -281,6 +309,34 @@ void AudioCore::CommandGenerator::GenerateBiquadFilterCommand(
281 state = {s0, s1}; 309 state = {s0, s1};
282} 310}
283 311
312void CommandGenerator::GenerateDepopPrepareCommand(VoiceState& dsp_state,
313 std::size_t mix_buffer_count,
314 std::size_t mix_buffer_offset) {
315 for (std::size_t i = 0; i < mix_buffer_count; i++) {
316 auto& sample = dsp_state.previous_samples[i];
317 if (sample != 0) {
318 depop_buffer[mix_buffer_offset + i] += sample;
319 sample = 0;
320 }
321 }
322}
323
324void CommandGenerator::GenerateDepopForMixBuffersCommand(std::size_t mix_buffer_count,
325 std::size_t mix_buffer_offset,
326 s32 sample_rate) {
327 const std::size_t end_offset =
328 std::min(mix_buffer_offset + mix_buffer_count, GetTotalMixBufferCount());
329 const s32 delta = sample_rate == 48000 ? 0x7B29 : 0x78CB;
330 for (std::size_t i = mix_buffer_offset; i < end_offset; i++) {
331 if (depop_buffer[i] == 0) {
332 continue;
333 }
334
335 depop_buffer[i] =
336 ApplyMixDepop(GetMixBuffer(i), depop_buffer[i], delta, worker_params.sample_count);
337 }
338}
339
284ServerSplitterDestinationData* CommandGenerator::GetDestinationData(s32 splitter_id, s32 index) { 340ServerSplitterDestinationData* CommandGenerator::GetDestinationData(s32 splitter_id, s32 index) {
285 if (splitter_id == AudioCommon::NO_SPLITTER) { 341 if (splitter_id == AudioCommon::NO_SPLITTER) {
286 return nullptr; 342 return nullptr;
@@ -338,7 +394,9 @@ void CommandGenerator::GenerateSubMixCommand(ServerMixInfo& mix_info) {
338 if (dumping_frame) { 394 if (dumping_frame) {
339 LOG_DEBUG(Audio, "(DSP_TRACE) GenerateSubMixCommand"); 395 LOG_DEBUG(Audio, "(DSP_TRACE) GenerateSubMixCommand");
340 } 396 }
341 // TODO(ogniK): Depop 397 auto& in_params = mix_info.GetInParams();
398 GenerateDepopForMixBuffersCommand(in_params.buffer_count, in_params.buffer_offset,
399 in_params.sample_rate);
342 // TODO(ogniK): Effects 400 // TODO(ogniK): Effects
343 GenerateMixCommands(mix_info); 401 GenerateMixCommands(mix_info);
344} 402}
@@ -412,10 +470,13 @@ void CommandGenerator::GenerateFinalMixCommand() {
412 if (dumping_frame) { 470 if (dumping_frame) {
413 LOG_DEBUG(Audio, "(DSP_TRACE) GenerateFinalMixCommand"); 471 LOG_DEBUG(Audio, "(DSP_TRACE) GenerateFinalMixCommand");
414 } 472 }
415 // TODO(ogniK): Depop
416 // TODO(ogniK): Effects
417 auto& mix_info = mix_context.GetFinalMixInfo(); 473 auto& mix_info = mix_context.GetFinalMixInfo();
418 const auto in_params = mix_info.GetInParams(); 474 const auto in_params = mix_info.GetInParams();
475
476 GenerateDepopForMixBuffersCommand(in_params.buffer_count, in_params.buffer_offset,
477 in_params.sample_rate);
478 // TODO(ogniK): Effects
479
419 for (s32 i = 0; i < in_params.buffer_count; i++) { 480 for (s32 i = 0; i < in_params.buffer_count; i++) {
420 const s32 gain = static_cast<s32>(in_params.volume * 32768.0f); 481 const s32 gain = static_cast<s32>(in_params.volume * 32768.0f);
421 if (dumping_frame) { 482 if (dumping_frame) {
@@ -541,6 +602,10 @@ std::size_t CommandGenerator::GetMixChannelBufferOffset(s32 channel) const {
541 return worker_params.mix_buffer_count + channel; 602 return worker_params.mix_buffer_count + channel;
542} 603}
543 604
605std::size_t CommandGenerator::GetTotalMixBufferCount() const {
606 return worker_params.mix_buffer_count + AudioCommon::MAX_CHANNEL_COUNT;
607}
608
544s32* CommandGenerator::GetChannelMixBuffer(s32 channel) { 609s32* CommandGenerator::GetChannelMixBuffer(s32 channel) {
545 return GetMixBuffer(worker_params.mix_buffer_count + channel); 610 return GetMixBuffer(worker_params.mix_buffer_count + channel);
546} 611}
diff --git a/src/audio_core/command_generator.h b/src/audio_core/command_generator.h
index 3f49c1303..656ad8143 100644
--- a/src/audio_core/command_generator.h
+++ b/src/audio_core/command_generator.h
@@ -43,6 +43,8 @@ public:
43 const s32* GetMixBuffer(std::size_t index) const; 43 const s32* GetMixBuffer(std::size_t index) const;
44 std::size_t GetMixChannelBufferOffset(s32 channel) const; 44 std::size_t GetMixChannelBufferOffset(s32 channel) const;
45 45
46 std::size_t GetTotalMixBufferCount() const;
47
46private: 48private:
47 void GenerateDataSourceCommand(ServerVoiceInfo& voice_info, VoiceState& dsp_state, s32 channel); 49 void GenerateDataSourceCommand(ServerVoiceInfo& voice_info, VoiceState& dsp_state, s32 channel);
48 void GenerateBiquadFilterCommandForVoice(ServerVoiceInfo& voice_info, VoiceState& dsp_state, 50 void GenerateBiquadFilterCommandForVoice(ServerVoiceInfo& voice_info, VoiceState& dsp_state,
@@ -61,7 +63,10 @@ private:
61 void GenerateBiquadFilterCommand(s32 mix_buffer, const BiquadFilterParameter& params, 63 void GenerateBiquadFilterCommand(s32 mix_buffer, const BiquadFilterParameter& params,
62 std::array<s64, 2>& state, std::size_t input_offset, 64 std::array<s64, 2>& state, std::size_t input_offset,
63 std::size_t output_offset, s32 sample_count, s32 node_id); 65 std::size_t output_offset, s32 sample_count, s32 node_id);
64 void GenerateDepopPrepareCommand(VoiceState& dsp_state); 66 void GenerateDepopPrepareCommand(VoiceState& dsp_state, std::size_t mix_buffer_count,
67 std::size_t mix_buffer_offset);
68 void GenerateDepopForMixBuffersCommand(std::size_t mix_buffer_count,
69 std::size_t mix_buffer_offset, s32 sample_rate);
65 ServerSplitterDestinationData* GetDestinationData(s32 splitter_id, s32 index); 70 ServerSplitterDestinationData* GetDestinationData(s32 splitter_id, s32 index);
66 71
67 // DSP Code 72 // DSP Code
@@ -79,6 +84,7 @@ private:
79 Core::Memory::Memory& memory; 84 Core::Memory::Memory& memory;
80 std::vector<s32> mix_buffer{}; 85 std::vector<s32> mix_buffer{};
81 std::vector<s32> sample_buffer{}; 86 std::vector<s32> sample_buffer{};
87 std::vector<s32> depop_buffer{};
82 bool dumping_frame{false}; 88 bool dumping_frame{false};
83}; 89};
84} // namespace AudioCore 90} // namespace AudioCore