command_generator.cpp 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976
  1. // Copyright 2020 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "audio_core/algorithm/interpolate.h"
  5. #include "audio_core/command_generator.h"
  6. #include "audio_core/effect_context.h"
  7. #include "audio_core/mix_context.h"
  8. #include "audio_core/voice_context.h"
  9. #include "core/memory.h"
  10. namespace AudioCore {
  11. namespace {
  12. constexpr std::size_t MIX_BUFFER_SIZE = 0x3f00;
  13. constexpr std::size_t SCALED_MIX_BUFFER_SIZE = MIX_BUFFER_SIZE << 15ULL;
  14. template <std::size_t N>
  15. void ApplyMix(s32* output, const s32* input, s32 gain, s32 sample_count) {
  16. for (std::size_t i = 0; i < static_cast<std::size_t>(sample_count); i += N) {
  17. for (std::size_t j = 0; j < N; j++) {
  18. output[i + j] +=
  19. static_cast<s32>((static_cast<s64>(input[i + j]) * gain + 0x4000) >> 15);
  20. }
  21. }
  22. }
  23. s32 ApplyMixRamp(s32* output, const s32* input, float gain, float delta, s32 sample_count) {
  24. s32 x = 0;
  25. for (s32 i = 0; i < sample_count; i++) {
  26. x = static_cast<s32>(static_cast<float>(input[i]) * gain);
  27. output[i] += x;
  28. gain += delta;
  29. }
  30. return x;
  31. }
  32. void ApplyGain(s32* output, const s32* input, s32 gain, s32 delta, s32 sample_count) {
  33. for (s32 i = 0; i < sample_count; i++) {
  34. output[i] = static_cast<s32>((static_cast<s64>(input[i]) * gain + 0x4000) >> 15);
  35. gain += delta;
  36. }
  37. }
  38. void ApplyGainWithoutDelta(s32* output, const s32* input, s32 gain, s32 sample_count) {
  39. for (s32 i = 0; i < sample_count; i++) {
  40. output[i] = static_cast<s32>((static_cast<s64>(input[i]) * gain + 0x4000) >> 15);
  41. }
  42. }
  43. s32 ApplyMixDepop(s32* output, s32 first_sample, s32 delta, s32 sample_count) {
  44. const bool positive = first_sample > 0;
  45. auto final_sample = std::abs(first_sample);
  46. for (s32 i = 0; i < sample_count; i++) {
  47. final_sample = static_cast<s32>((static_cast<s64>(final_sample) * delta) >> 15);
  48. if (positive) {
  49. output[i] += final_sample;
  50. } else {
  51. output[i] -= final_sample;
  52. }
  53. }
  54. if (positive) {
  55. return final_sample;
  56. } else {
  57. return -final_sample;
  58. }
  59. }
  60. } // namespace
  61. CommandGenerator::CommandGenerator(AudioCommon::AudioRendererParameter& worker_params,
  62. VoiceContext& voice_context, MixContext& mix_context,
  63. SplitterContext& splitter_context, EffectContext& effect_context,
  64. Core::Memory::Memory& memory)
  65. : worker_params(worker_params), voice_context(voice_context), mix_context(mix_context),
  66. splitter_context(splitter_context), effect_context(effect_context), memory(memory),
  67. mix_buffer((worker_params.mix_buffer_count + AudioCommon::MAX_CHANNEL_COUNT) *
  68. worker_params.sample_count),
  69. sample_buffer(MIX_BUFFER_SIZE),
  70. depop_buffer((worker_params.mix_buffer_count + AudioCommon::MAX_CHANNEL_COUNT) *
  71. worker_params.sample_count) {}
  72. CommandGenerator::~CommandGenerator() = default;
  73. void CommandGenerator::ClearMixBuffers() {
  74. std::fill(mix_buffer.begin(), mix_buffer.end(), 0);
  75. std::fill(sample_buffer.begin(), sample_buffer.end(), 0);
  76. // std::fill(depop_buffer.begin(), depop_buffer.end(), 0);
  77. }
  78. void CommandGenerator::GenerateVoiceCommands() {
  79. if (dumping_frame) {
  80. LOG_DEBUG(Audio, "(DSP_TRACE) GenerateVoiceCommands");
  81. }
  82. // Grab all our voices
  83. const auto voice_count = voice_context.GetVoiceCount();
  84. for (std::size_t i = 0; i < voice_count; i++) {
  85. auto& voice_info = voice_context.GetSortedInfo(i);
  86. // Update voices and check if we should queue them
  87. if (voice_info.ShouldSkip() || !voice_info.UpdateForCommandGeneration(voice_context)) {
  88. continue;
  89. }
  90. // Queue our voice
  91. GenerateVoiceCommand(voice_info);
  92. }
  93. // Update our splitters
  94. splitter_context.UpdateInternalState();
  95. }
  96. void CommandGenerator::GenerateVoiceCommand(ServerVoiceInfo& voice_info) {
  97. auto& in_params = voice_info.GetInParams();
  98. const auto channel_count = in_params.channel_count;
  99. for (s32 channel = 0; channel < channel_count; channel++) {
  100. const auto resource_id = in_params.voice_channel_resource_id[channel];
  101. auto& dsp_state = voice_context.GetDspSharedState(resource_id);
  102. auto& channel_resource = voice_context.GetChannelResource(resource_id);
  103. // Decode our samples for our channel
  104. GenerateDataSourceCommand(voice_info, dsp_state, channel);
  105. if (in_params.should_depop) {
  106. in_params.last_volume = 0.0f;
  107. } else if (in_params.splitter_info_id != AudioCommon::NO_SPLITTER ||
  108. in_params.mix_id != AudioCommon::NO_MIX) {
  109. // Apply a biquad filter if needed
  110. GenerateBiquadFilterCommandForVoice(voice_info, dsp_state,
  111. worker_params.mix_buffer_count, channel);
  112. // Base voice volume ramping
  113. GenerateVolumeRampCommand(in_params.last_volume, in_params.volume, channel,
  114. in_params.node_id);
  115. in_params.last_volume = in_params.volume;
  116. if (in_params.mix_id != AudioCommon::NO_MIX) {
  117. // If we're using a mix id
  118. auto& mix_info = mix_context.GetInfo(in_params.mix_id);
  119. const auto& dest_mix_params = mix_info.GetInParams();
  120. // Voice Mixing
  121. GenerateVoiceMixCommand(
  122. channel_resource.GetCurrentMixVolume(), channel_resource.GetLastMixVolume(),
  123. dsp_state, dest_mix_params.buffer_offset, dest_mix_params.buffer_count,
  124. worker_params.mix_buffer_count + channel, in_params.node_id);
  125. // Update last mix volumes
  126. channel_resource.UpdateLastMixVolumes();
  127. } else if (in_params.splitter_info_id != AudioCommon::NO_SPLITTER) {
  128. s32 base = channel;
  129. while (auto* destination_data =
  130. GetDestinationData(in_params.splitter_info_id, base)) {
  131. base += channel_count;
  132. if (!destination_data->IsConfigured()) {
  133. continue;
  134. }
  135. if (destination_data->GetMixId() >= mix_context.GetCount()) {
  136. continue;
  137. }
  138. const auto& mix_info = mix_context.GetInfo(destination_data->GetMixId());
  139. const auto& dest_mix_params = mix_info.GetInParams();
  140. GenerateVoiceMixCommand(
  141. destination_data->CurrentMixVolumes(), destination_data->LastMixVolumes(),
  142. dsp_state, dest_mix_params.buffer_offset, dest_mix_params.buffer_count,
  143. worker_params.mix_buffer_count + channel, in_params.node_id);
  144. destination_data->MarkDirty();
  145. }
  146. }
  147. // Update biquad filter enabled states
  148. for (std::size_t i = 0; i < AudioCommon::MAX_BIQUAD_FILTERS; i++) {
  149. in_params.was_biquad_filter_enabled[i] = in_params.biquad_filter[i].enabled;
  150. }
  151. }
  152. }
  153. }
  154. void CommandGenerator::GenerateSubMixCommands() {
  155. const auto mix_count = mix_context.GetCount();
  156. for (std::size_t i = 0; i < mix_count; i++) {
  157. auto& mix_info = mix_context.GetSortedInfo(i);
  158. const auto& in_params = mix_info.GetInParams();
  159. if (!in_params.in_use || in_params.mix_id == AudioCommon::FINAL_MIX) {
  160. continue;
  161. }
  162. GenerateSubMixCommand(mix_info);
  163. }
  164. }
  165. void CommandGenerator::GenerateFinalMixCommands() {
  166. GenerateFinalMixCommand();
  167. }
  168. void CommandGenerator::PreCommand() {
  169. if (!dumping_frame) {
  170. return;
  171. }
  172. for (std::size_t i = 0; i < splitter_context.GetInfoCount(); i++) {
  173. const auto& base = splitter_context.GetInfo(i);
  174. std::string graph = fmt::format("b[{}]", i);
  175. auto* head = base.GetHead();
  176. while (head != nullptr) {
  177. graph += fmt::format("->{}", head->GetMixId());
  178. head = head->GetNextDestination();
  179. }
  180. LOG_DEBUG(Audio, "(DSP_TRACE) SplitterGraph splitter_info={}, {}", i, graph);
  181. }
  182. }
  183. void CommandGenerator::PostCommand() {
  184. if (!dumping_frame) {
  185. return;
  186. }
  187. dumping_frame = false;
  188. }
  189. void CommandGenerator::GenerateDataSourceCommand(ServerVoiceInfo& voice_info, VoiceState& dsp_state,
  190. s32 channel) {
  191. auto& in_params = voice_info.GetInParams();
  192. const auto depop = in_params.should_depop;
  193. if (depop) {
  194. if (in_params.mix_id != AudioCommon::NO_MIX) {
  195. auto& mix_info = mix_context.GetInfo(in_params.mix_id);
  196. const auto& mix_in = mix_info.GetInParams();
  197. GenerateDepopPrepareCommand(dsp_state, mix_in.buffer_count, mix_in.buffer_offset);
  198. } else if (in_params.splitter_info_id != AudioCommon::NO_SPLITTER) {
  199. s32 index{};
  200. while (const auto* destination =
  201. GetDestinationData(in_params.splitter_info_id, index++)) {
  202. if (!destination->IsConfigured()) {
  203. continue;
  204. }
  205. auto& mix_info = mix_context.GetInfo(destination->GetMixId());
  206. const auto& mix_in = mix_info.GetInParams();
  207. GenerateDepopPrepareCommand(dsp_state, mix_in.buffer_count, mix_in.buffer_offset);
  208. }
  209. }
  210. } else {
  211. switch (in_params.sample_format) {
  212. case SampleFormat::Pcm16:
  213. DecodeFromWaveBuffers(voice_info, GetChannelMixBuffer(channel), dsp_state, channel,
  214. worker_params.sample_rate, worker_params.sample_count,
  215. in_params.node_id);
  216. break;
  217. case SampleFormat::Adpcm:
  218. ASSERT(channel == 0 && in_params.channel_count == 1);
  219. DecodeFromWaveBuffers(voice_info, GetChannelMixBuffer(0), dsp_state, 0,
  220. worker_params.sample_rate, worker_params.sample_count,
  221. in_params.node_id);
  222. break;
  223. default:
  224. UNREACHABLE_MSG("Unimplemented sample format={}", in_params.sample_format);
  225. }
  226. }
  227. }
  228. void CommandGenerator::GenerateBiquadFilterCommandForVoice(ServerVoiceInfo& voice_info,
  229. VoiceState& dsp_state,
  230. s32 mix_buffer_count, s32 channel) {
  231. for (std::size_t i = 0; i < AudioCommon::MAX_BIQUAD_FILTERS; i++) {
  232. const auto& in_params = voice_info.GetInParams();
  233. auto& biquad_filter = in_params.biquad_filter[i];
  234. // Check if biquad filter is actually used
  235. if (!biquad_filter.enabled) {
  236. continue;
  237. }
  238. // Reinitialize our biquad filter state if it was enabled previously
  239. if (!in_params.was_biquad_filter_enabled[i]) {
  240. dsp_state.biquad_filter_state.fill(0);
  241. }
  242. // Generate biquad filter
  243. // GenerateBiquadFilterCommand(mix_buffer_count, biquad_filter,
  244. // dsp_state.biquad_filter_state,
  245. // mix_buffer_count + channel, mix_buffer_count +
  246. // channel, worker_params.sample_count,
  247. // voice_info.GetInParams().node_id);
  248. }
  249. }
  250. void AudioCore::CommandGenerator::GenerateBiquadFilterCommand(
  251. s32 mix_buffer, const BiquadFilterParameter& params, std::array<s64, 2>& state,
  252. std::size_t input_offset, std::size_t output_offset, s32 sample_count, s32 node_id) {
  253. if (dumping_frame) {
  254. LOG_DEBUG(Audio,
  255. "(DSP_TRACE) GenerateBiquadFilterCommand node_id={}, "
  256. "input_mix_buffer={}, output_mix_buffer={}",
  257. node_id, input_offset, output_offset);
  258. }
  259. const auto* input = GetMixBuffer(input_offset);
  260. auto* output = GetMixBuffer(output_offset);
  261. // Biquad filter parameters
  262. const auto [n0, n1, n2] = params.numerator;
  263. const auto [d0, d1] = params.denominator;
  264. // Biquad filter states
  265. auto [s0, s1] = state;
  266. constexpr s64 int32_min = std::numeric_limits<s32>::min();
  267. constexpr s64 int32_max = std::numeric_limits<s32>::max();
  268. for (int i = 0; i < sample_count; ++i) {
  269. const auto sample = static_cast<s64>(input[i]);
  270. const auto f = (sample * n0 + s0 + 0x4000) >> 15;
  271. const auto y = std::clamp(f, int32_min, int32_max);
  272. s0 = sample * n1 + y * d0 + s1;
  273. s1 = sample * n2 + y * d1;
  274. output[i] = static_cast<s32>(y);
  275. }
  276. state = {s0, s1};
  277. }
  278. void CommandGenerator::GenerateDepopPrepareCommand(VoiceState& dsp_state,
  279. std::size_t mix_buffer_count,
  280. std::size_t mix_buffer_offset) {
  281. for (std::size_t i = 0; i < mix_buffer_count; i++) {
  282. auto& sample = dsp_state.previous_samples[i];
  283. if (sample != 0) {
  284. depop_buffer[mix_buffer_offset + i] += sample;
  285. sample = 0;
  286. }
  287. }
  288. }
  289. void CommandGenerator::GenerateDepopForMixBuffersCommand(std::size_t mix_buffer_count,
  290. std::size_t mix_buffer_offset,
  291. s32 sample_rate) {
  292. const std::size_t end_offset =
  293. std::min(mix_buffer_offset + mix_buffer_count, GetTotalMixBufferCount());
  294. const s32 delta = sample_rate == 48000 ? 0x7B29 : 0x78CB;
  295. for (std::size_t i = mix_buffer_offset; i < end_offset; i++) {
  296. if (depop_buffer[i] == 0) {
  297. continue;
  298. }
  299. depop_buffer[i] =
  300. ApplyMixDepop(GetMixBuffer(i), depop_buffer[i], delta, worker_params.sample_count);
  301. }
  302. }
  303. void CommandGenerator::GenerateEffectCommand(ServerMixInfo& mix_info) {
  304. const std::size_t effect_count = effect_context.GetCount();
  305. const auto buffer_offset = mix_info.GetInParams().buffer_offset;
  306. for (std::size_t i = 0; i < effect_count; i++) {
  307. const auto index = mix_info.GetEffectOrder(i);
  308. if (index == AudioCommon::NO_EFFECT_ORDER) {
  309. break;
  310. }
  311. auto* info = effect_context.GetInfo(index);
  312. const auto type = info->GetType();
  313. // TODO(ogniK): Finish remaining effects
  314. switch (type) {
  315. case EffectType::Aux:
  316. GenerateAuxCommand(buffer_offset, info, info->IsEnabled());
  317. break;
  318. case EffectType::I3dl2Reverb:
  319. GenerateI3dl2ReverbEffectCommand(buffer_offset, info, info->IsEnabled());
  320. break;
  321. case EffectType::BiquadFilter:
  322. GenerateBiquadFilterEffectCommand(buffer_offset, info, info->IsEnabled());
  323. break;
  324. default:
  325. break;
  326. }
  327. info->UpdateForCommandGeneration();
  328. }
  329. }
  330. void CommandGenerator::GenerateI3dl2ReverbEffectCommand(s32 mix_buffer_offset, EffectBase* info,
  331. bool enabled) {
  332. if (!enabled) {
  333. return;
  334. }
  335. const auto& params = dynamic_cast<EffectI3dl2Reverb*>(info)->GetParams();
  336. const auto channel_count = params.channel_count;
  337. for (s32 i = 0; i < channel_count; i++) {
  338. // TODO(ogniK): Actually implement reverb
  339. if (params.input[i] != params.output[i]) {
  340. const auto* input = GetMixBuffer(mix_buffer_offset + params.input[i]);
  341. auto* output = GetMixBuffer(mix_buffer_offset + params.output[i]);
  342. ApplyMix<1>(output, input, 32768, worker_params.sample_count);
  343. }
  344. }
  345. }
  346. void CommandGenerator::GenerateBiquadFilterEffectCommand(s32 mix_buffer_offset, EffectBase* info,
  347. bool enabled) {
  348. if (!enabled) {
  349. return;
  350. }
  351. const auto& params = dynamic_cast<EffectBiquadFilter*>(info)->GetParams();
  352. const auto channel_count = params.channel_count;
  353. for (s32 i = 0; i < channel_count; i++) {
  354. // TODO(ogniK): Actually implement biquad filter
  355. if (params.input[i] != params.output[i]) {
  356. const auto* input = GetMixBuffer(mix_buffer_offset + params.input[i]);
  357. auto* output = GetMixBuffer(mix_buffer_offset + params.output[i]);
  358. ApplyMix<1>(output, input, 32768, worker_params.sample_count);
  359. }
  360. }
  361. }
  362. void CommandGenerator::GenerateAuxCommand(s32 mix_buffer_offset, EffectBase* info, bool enabled) {
  363. auto aux = dynamic_cast<EffectAuxInfo*>(info);
  364. const auto& params = aux->GetParams();
  365. if (aux->GetSendBuffer() != 0 && aux->GetRecvBuffer() != 0) {
  366. const auto max_channels = params.count;
  367. u32 offset{};
  368. for (u32 channel = 0; channel < max_channels; channel++) {
  369. u32 write_count = 0;
  370. if (channel == (max_channels - 1)) {
  371. write_count = offset + worker_params.sample_count;
  372. }
  373. const auto input_index = params.input_mix_buffers[channel] + mix_buffer_offset;
  374. const auto output_index = params.output_mix_buffers[channel] + mix_buffer_offset;
  375. if (enabled) {
  376. AuxInfoDSP send_info{};
  377. AuxInfoDSP recv_info{};
  378. memory.ReadBlock(aux->GetSendInfo(), &send_info, sizeof(AuxInfoDSP));
  379. memory.ReadBlock(aux->GetRecvInfo(), &recv_info, sizeof(AuxInfoDSP));
  380. WriteAuxBuffer(send_info, aux->GetSendBuffer(), params.sample_count,
  381. GetMixBuffer(input_index), worker_params.sample_count, offset,
  382. write_count);
  383. memory.WriteBlock(aux->GetSendInfo(), &send_info, sizeof(AuxInfoDSP));
  384. const auto samples_read = ReadAuxBuffer(
  385. recv_info, aux->GetRecvBuffer(), params.sample_count,
  386. GetMixBuffer(output_index), worker_params.sample_count, offset, write_count);
  387. memory.WriteBlock(aux->GetRecvInfo(), &recv_info, sizeof(AuxInfoDSP));
  388. if (samples_read != worker_params.sample_count &&
  389. samples_read <= params.sample_count) {
  390. std::memset(GetMixBuffer(output_index), 0, params.sample_count - samples_read);
  391. }
  392. } else {
  393. AuxInfoDSP empty{};
  394. memory.WriteBlock(aux->GetSendInfo(), &empty, sizeof(AuxInfoDSP));
  395. memory.WriteBlock(aux->GetRecvInfo(), &empty, sizeof(AuxInfoDSP));
  396. if (output_index != input_index) {
  397. std::memcpy(GetMixBuffer(output_index), GetMixBuffer(input_index),
  398. worker_params.sample_count * sizeof(s32));
  399. }
  400. }
  401. offset += worker_params.sample_count;
  402. }
  403. }
  404. }
  405. ServerSplitterDestinationData* CommandGenerator::GetDestinationData(s32 splitter_id, s32 index) {
  406. if (splitter_id == AudioCommon::NO_SPLITTER) {
  407. return nullptr;
  408. }
  409. return splitter_context.GetDestinationData(splitter_id, index);
  410. }
  411. s32 CommandGenerator::WriteAuxBuffer(AuxInfoDSP& dsp_info, VAddr send_buffer, u32 max_samples,
  412. const s32* data, u32 sample_count, u32 write_offset,
  413. u32 write_count) {
  414. if (max_samples == 0) {
  415. return 0;
  416. }
  417. u32 offset = dsp_info.write_offset + write_offset;
  418. if (send_buffer == 0 || offset > max_samples) {
  419. return 0;
  420. }
  421. std::size_t data_offset{};
  422. u32 remaining = sample_count;
  423. while (remaining > 0) {
  424. // Get position in buffer
  425. const auto base = send_buffer + (offset * sizeof(u32));
  426. const auto samples_to_grab = std::min(max_samples - offset, remaining);
  427. // Write to output
  428. memory.WriteBlock(base, (data + data_offset), samples_to_grab * sizeof(u32));
  429. offset = (offset + samples_to_grab) % max_samples;
  430. remaining -= samples_to_grab;
  431. data_offset += samples_to_grab;
  432. }
  433. if (write_count != 0) {
  434. dsp_info.write_offset = (dsp_info.write_offset + write_count) % max_samples;
  435. }
  436. return sample_count;
  437. }
  438. s32 CommandGenerator::ReadAuxBuffer(AuxInfoDSP& recv_info, VAddr recv_buffer, u32 max_samples,
  439. s32* out_data, u32 sample_count, u32 read_offset,
  440. u32 read_count) {
  441. if (max_samples == 0) {
  442. return 0;
  443. }
  444. u32 offset = recv_info.read_offset + read_offset;
  445. if (recv_buffer == 0 || offset > max_samples) {
  446. return 0;
  447. }
  448. u32 remaining = sample_count;
  449. while (remaining > 0) {
  450. const auto base = recv_buffer + (offset * sizeof(u32));
  451. const auto samples_to_grab = std::min(max_samples - offset, remaining);
  452. std::vector<s32> buffer(samples_to_grab);
  453. memory.ReadBlock(base, buffer.data(), buffer.size() * sizeof(u32));
  454. std::memcpy(out_data, buffer.data(), buffer.size() * sizeof(u32));
  455. out_data += samples_to_grab;
  456. offset = (offset + samples_to_grab) % max_samples;
  457. remaining -= samples_to_grab;
  458. }
  459. if (read_count != 0) {
  460. recv_info.read_offset = (recv_info.read_offset + read_count) % max_samples;
  461. }
  462. return sample_count;
  463. }
  464. void CommandGenerator::GenerateVolumeRampCommand(float last_volume, float current_volume,
  465. s32 channel, s32 node_id) {
  466. const auto last = static_cast<s32>(last_volume * 32768.0f);
  467. const auto current = static_cast<s32>(current_volume * 32768.0f);
  468. const auto delta = static_cast<s32>((static_cast<float>(current) - static_cast<float>(last)) /
  469. static_cast<float>(worker_params.sample_count));
  470. if (dumping_frame) {
  471. LOG_DEBUG(Audio,
  472. "(DSP_TRACE) GenerateVolumeRampCommand node_id={}, input={}, output={}, "
  473. "last_volume={}, current_volume={}",
  474. node_id, GetMixChannelBufferOffset(channel), GetMixChannelBufferOffset(channel),
  475. last_volume, current_volume);
  476. }
  477. // Apply generic gain on samples
  478. ApplyGain(GetChannelMixBuffer(channel), GetChannelMixBuffer(channel), last, delta,
  479. worker_params.sample_count);
  480. }
  481. void CommandGenerator::GenerateVoiceMixCommand(const MixVolumeBuffer& mix_volumes,
  482. const MixVolumeBuffer& last_mix_volumes,
  483. VoiceState& dsp_state, s32 mix_buffer_offset,
  484. s32 mix_buffer_count, s32 voice_index, s32 node_id) {
  485. // Loop all our mix buffers
  486. for (s32 i = 0; i < mix_buffer_count; i++) {
  487. if (last_mix_volumes[i] != 0.0f || mix_volumes[i] != 0.0f) {
  488. const auto delta = static_cast<float>((mix_volumes[i] - last_mix_volumes[i])) /
  489. static_cast<float>(worker_params.sample_count);
  490. if (dumping_frame) {
  491. LOG_DEBUG(Audio,
  492. "(DSP_TRACE) GenerateVoiceMixCommand node_id={}, input={}, "
  493. "output={}, last_volume={}, current_volume={}",
  494. node_id, voice_index, mix_buffer_offset + i, last_mix_volumes[i],
  495. mix_volumes[i]);
  496. }
  497. dsp_state.previous_samples[i] =
  498. ApplyMixRamp(GetMixBuffer(mix_buffer_offset + i), GetMixBuffer(voice_index),
  499. last_mix_volumes[i], delta, worker_params.sample_count);
  500. } else {
  501. dsp_state.previous_samples[i] = 0;
  502. }
  503. }
  504. }
  505. void CommandGenerator::GenerateSubMixCommand(ServerMixInfo& mix_info) {
  506. if (dumping_frame) {
  507. LOG_DEBUG(Audio, "(DSP_TRACE) GenerateSubMixCommand");
  508. }
  509. auto& in_params = mix_info.GetInParams();
  510. GenerateDepopForMixBuffersCommand(in_params.buffer_count, in_params.buffer_offset,
  511. in_params.sample_rate);
  512. GenerateEffectCommand(mix_info);
  513. GenerateMixCommands(mix_info);
  514. }
  515. void CommandGenerator::GenerateMixCommands(ServerMixInfo& mix_info) {
  516. if (!mix_info.HasAnyConnection()) {
  517. return;
  518. }
  519. const auto& in_params = mix_info.GetInParams();
  520. if (in_params.dest_mix_id != AudioCommon::NO_MIX) {
  521. const auto& dest_mix = mix_context.GetInfo(in_params.dest_mix_id);
  522. const auto& dest_in_params = dest_mix.GetInParams();
  523. const auto buffer_count = in_params.buffer_count;
  524. for (s32 i = 0; i < buffer_count; i++) {
  525. for (s32 j = 0; j < dest_in_params.buffer_count; j++) {
  526. const auto mixed_volume = in_params.volume * in_params.mix_volume[i][j];
  527. if (mixed_volume != 0.0f) {
  528. GenerateMixCommand(dest_in_params.buffer_offset + j,
  529. in_params.buffer_offset + i, mixed_volume,
  530. in_params.node_id);
  531. }
  532. }
  533. }
  534. } else if (in_params.splitter_id != AudioCommon::NO_SPLITTER) {
  535. s32 base{};
  536. while (const auto* destination_data = GetDestinationData(in_params.splitter_id, base++)) {
  537. if (!destination_data->IsConfigured()) {
  538. continue;
  539. }
  540. const auto& dest_mix = mix_context.GetInfo(destination_data->GetMixId());
  541. const auto& dest_in_params = dest_mix.GetInParams();
  542. const auto mix_index = (base - 1) % in_params.buffer_count + in_params.buffer_offset;
  543. for (std::size_t i = 0; i < dest_in_params.buffer_count; i++) {
  544. const auto mixed_volume = in_params.volume * destination_data->GetMixVolume(i);
  545. if (mixed_volume != 0.0f) {
  546. GenerateMixCommand(dest_in_params.buffer_offset + i, mix_index, mixed_volume,
  547. in_params.node_id);
  548. }
  549. }
  550. }
  551. }
  552. }
  553. void CommandGenerator::GenerateMixCommand(std::size_t output_offset, std::size_t input_offset,
  554. float volume, s32 node_id) {
  555. if (dumping_frame) {
  556. LOG_DEBUG(Audio,
  557. "(DSP_TRACE) GenerateMixCommand node_id={}, input={}, output={}, volume={}",
  558. node_id, input_offset, output_offset, volume);
  559. }
  560. auto* output = GetMixBuffer(output_offset);
  561. const auto* input = GetMixBuffer(input_offset);
  562. const s32 gain = static_cast<s32>(volume * 32768.0f);
  563. // Mix with loop unrolling
  564. if (worker_params.sample_count % 4 == 0) {
  565. ApplyMix<4>(output, input, gain, worker_params.sample_count);
  566. } else if (worker_params.sample_count % 2 == 0) {
  567. ApplyMix<2>(output, input, gain, worker_params.sample_count);
  568. } else {
  569. ApplyMix<1>(output, input, gain, worker_params.sample_count);
  570. }
  571. }
  572. void CommandGenerator::GenerateFinalMixCommand() {
  573. if (dumping_frame) {
  574. LOG_DEBUG(Audio, "(DSP_TRACE) GenerateFinalMixCommand");
  575. }
  576. auto& mix_info = mix_context.GetFinalMixInfo();
  577. const auto in_params = mix_info.GetInParams();
  578. GenerateDepopForMixBuffersCommand(in_params.buffer_count, in_params.buffer_offset,
  579. in_params.sample_rate);
  580. GenerateEffectCommand(mix_info);
  581. for (s32 i = 0; i < in_params.buffer_count; i++) {
  582. const s32 gain = static_cast<s32>(in_params.volume * 32768.0f);
  583. if (dumping_frame) {
  584. LOG_DEBUG(
  585. Audio,
  586. "(DSP_TRACE) ApplyGainWithoutDelta node_id={}, input={}, output={}, volume={}",
  587. in_params.node_id, in_params.buffer_offset + i, in_params.buffer_offset + i,
  588. in_params.volume);
  589. }
  590. ApplyGainWithoutDelta(GetMixBuffer(in_params.buffer_offset + i),
  591. GetMixBuffer(in_params.buffer_offset + i), gain,
  592. worker_params.sample_count);
  593. }
  594. }
  595. s32 CommandGenerator::DecodePcm16(ServerVoiceInfo& voice_info, VoiceState& dsp_state,
  596. s32 sample_count, s32 channel, std::size_t mix_offset) {
  597. auto& in_params = voice_info.GetInParams();
  598. const auto& wave_buffer = in_params.wave_buffer[dsp_state.wave_buffer_index];
  599. if (wave_buffer.buffer_address == 0) {
  600. return 0;
  601. }
  602. if (wave_buffer.buffer_size == 0) {
  603. return 0;
  604. }
  605. if (wave_buffer.end_sample_offset < wave_buffer.start_sample_offset) {
  606. return 0;
  607. }
  608. const auto samples_remaining =
  609. (wave_buffer.end_sample_offset - wave_buffer.start_sample_offset) - dsp_state.offset;
  610. const auto start_offset =
  611. ((wave_buffer.start_sample_offset + dsp_state.offset) * in_params.channel_count) *
  612. sizeof(s16);
  613. const auto buffer_pos = wave_buffer.buffer_address + start_offset;
  614. const auto samples_processed = std::min(sample_count, samples_remaining);
  615. if (in_params.channel_count == 1) {
  616. std::vector<s16> buffer(samples_processed);
  617. memory.ReadBlock(buffer_pos, buffer.data(), buffer.size() * sizeof(s16));
  618. for (std::size_t i = 0; i < buffer.size(); i++) {
  619. sample_buffer[mix_offset + i] = buffer[i];
  620. }
  621. } else {
  622. const auto channel_count = in_params.channel_count;
  623. std::vector<s16> buffer(samples_processed * channel_count);
  624. memory.ReadBlock(buffer_pos, buffer.data(), buffer.size() * sizeof(s16));
  625. for (std::size_t i = 0; i < samples_processed; i++) {
  626. sample_buffer[mix_offset + i] = buffer[i * channel_count + channel];
  627. }
  628. }
  629. return samples_processed;
  630. }
  631. s32 CommandGenerator::DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_state,
  632. s32 sample_count, s32 channel, std::size_t mix_offset) {
  633. auto& in_params = voice_info.GetInParams();
  634. const auto& wave_buffer = in_params.wave_buffer[dsp_state.wave_buffer_index];
  635. if (wave_buffer.buffer_address == 0) {
  636. return 0;
  637. }
  638. if (wave_buffer.buffer_size == 0) {
  639. return 0;
  640. }
  641. if (wave_buffer.end_sample_offset < wave_buffer.start_sample_offset) {
  642. return 0;
  643. }
  644. constexpr std::array<int, 16> SIGNED_NIBBLES = {
  645. {0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1}};
  646. constexpr std::size_t FRAME_LEN = 8;
  647. constexpr std::size_t NIBBLES_PER_SAMPLE = 16;
  648. constexpr std::size_t SAMPLES_PER_FRAME = 14;
  649. auto frame_header = dsp_state.context.header;
  650. s32 idx = (frame_header >> 4) & 0xf;
  651. s32 scale = frame_header & 0xf;
  652. s16 yn1 = dsp_state.context.yn1;
  653. s16 yn2 = dsp_state.context.yn2;
  654. Codec::ADPCM_Coeff coeffs;
  655. memory.ReadBlock(in_params.additional_params_address, coeffs.data(),
  656. sizeof(Codec::ADPCM_Coeff));
  657. s32 coef1 = coeffs[idx * 2];
  658. s32 coef2 = coeffs[idx * 2 + 1];
  659. const auto samples_remaining =
  660. (wave_buffer.end_sample_offset - wave_buffer.start_sample_offset) - dsp_state.offset;
  661. const auto samples_processed = std::min(sample_count, samples_remaining);
  662. const auto sample_pos = wave_buffer.start_sample_offset + dsp_state.offset;
  663. const auto samples_remaining_in_frame = sample_pos % SAMPLES_PER_FRAME;
  664. auto position_in_frame = ((sample_pos / SAMPLES_PER_FRAME) * NIBBLES_PER_SAMPLE) +
  665. samples_remaining_in_frame + (samples_remaining_in_frame != 0 ? 2 : 0);
  666. const auto decode_sample = [&](const int nibble) -> s16 {
  667. const int xn = nibble * (1 << scale);
  668. // We first transform everything into 11 bit fixed point, perform the second order
  669. // digital filter, then transform back.
  670. // 0x400 == 0.5 in 11 bit fixed point.
  671. // Filter: y[n] = x[n] + 0.5 + c1 * y[n-1] + c2 * y[n-2]
  672. int val = ((xn << 11) + 0x400 + coef1 * yn1 + coef2 * yn2) >> 11;
  673. // Clamp to output range.
  674. val = std::clamp<s32>(val, -32768, 32767);
  675. // Advance output feedback.
  676. yn2 = yn1;
  677. yn1 = val;
  678. return static_cast<s16>(val);
  679. };
  680. std::size_t buffer_offset{};
  681. std::vector<u8> buffer(
  682. std::max((samples_processed / FRAME_LEN) * SAMPLES_PER_FRAME, FRAME_LEN));
  683. memory.ReadBlock(wave_buffer.buffer_address + (position_in_frame / 2), buffer.data(),
  684. buffer.size());
  685. std::size_t cur_mix_offset = mix_offset;
  686. auto remaining_samples = samples_processed;
  687. while (remaining_samples > 0) {
  688. if (position_in_frame % NIBBLES_PER_SAMPLE == 0) {
  689. // Read header
  690. frame_header = buffer[buffer_offset++];
  691. idx = (frame_header >> 4) & 0xf;
  692. scale = frame_header & 0xf;
  693. coef1 = coeffs[idx * 2];
  694. coef2 = coeffs[idx * 2 + 1];
  695. position_in_frame += 2;
  696. // Decode entire frame
  697. if (remaining_samples >= SAMPLES_PER_FRAME) {
  698. for (std::size_t i = 0; i < SAMPLES_PER_FRAME / 2; i++) {
  699. // Sample 1
  700. const s32 s0 = SIGNED_NIBBLES[buffer[buffer_offset] >> 4];
  701. const s32 s1 = SIGNED_NIBBLES[buffer[buffer_offset++] & 0xf];
  702. const s16 sample_1 = decode_sample(s0);
  703. const s16 sample_2 = decode_sample(s1);
  704. sample_buffer[cur_mix_offset++] = sample_1;
  705. sample_buffer[cur_mix_offset++] = sample_2;
  706. }
  707. remaining_samples -= SAMPLES_PER_FRAME;
  708. position_in_frame += SAMPLES_PER_FRAME;
  709. continue;
  710. }
  711. }
  712. // Decode mid frame
  713. s32 current_nibble = buffer[buffer_offset];
  714. if (position_in_frame++ & 0x1) {
  715. current_nibble &= 0xf;
  716. buffer_offset++;
  717. } else {
  718. current_nibble >>= 4;
  719. }
  720. const s16 sample = decode_sample(SIGNED_NIBBLES[current_nibble]);
  721. sample_buffer[cur_mix_offset++] = sample;
  722. remaining_samples--;
  723. }
  724. dsp_state.context.header = frame_header;
  725. dsp_state.context.yn1 = yn1;
  726. dsp_state.context.yn2 = yn2;
  727. return samples_processed;
  728. }
  729. s32* CommandGenerator::GetMixBuffer(std::size_t index) {
  730. return mix_buffer.data() + (index * worker_params.sample_count);
  731. }
  732. const s32* CommandGenerator::GetMixBuffer(std::size_t index) const {
  733. return mix_buffer.data() + (index * worker_params.sample_count);
  734. }
  735. std::size_t CommandGenerator::GetMixChannelBufferOffset(s32 channel) const {
  736. return worker_params.mix_buffer_count + channel;
  737. }
  738. std::size_t CommandGenerator::GetTotalMixBufferCount() const {
  739. return worker_params.mix_buffer_count + AudioCommon::MAX_CHANNEL_COUNT;
  740. }
  741. s32* CommandGenerator::GetChannelMixBuffer(s32 channel) {
  742. return GetMixBuffer(worker_params.mix_buffer_count + channel);
  743. }
  744. const s32* CommandGenerator::GetChannelMixBuffer(s32 channel) const {
  745. return GetMixBuffer(worker_params.mix_buffer_count + channel);
  746. }
  747. void CommandGenerator::DecodeFromWaveBuffers(ServerVoiceInfo& voice_info, s32* output,
  748. VoiceState& dsp_state, s32 channel,
  749. s32 target_sample_rate, s32 sample_count,
  750. s32 node_id) {
  751. auto& in_params = voice_info.GetInParams();
  752. if (dumping_frame) {
  753. LOG_DEBUG(Audio,
  754. "(DSP_TRACE) DecodeFromWaveBuffers, node_id={}, channel={}, "
  755. "format={}, sample_count={}, sample_rate={}, mix_id={}, splitter_id={}",
  756. node_id, channel, in_params.sample_format, sample_count, in_params.sample_rate,
  757. in_params.mix_id, in_params.splitter_info_id);
  758. }
  759. ASSERT_OR_EXECUTE(output != nullptr, { return; });
  760. const auto resample_rate = static_cast<s32>(
  761. static_cast<float>(in_params.sample_rate) / static_cast<float>(target_sample_rate) *
  762. static_cast<float>(static_cast<s32>(in_params.pitch * 32768.0f)));
  763. auto* output_base = output;
  764. if ((dsp_state.fraction + sample_count * resample_rate) > (SCALED_MIX_BUFFER_SIZE - 4ULL)) {
  765. return;
  766. }
  767. auto min_required_samples =
  768. std::min(static_cast<s32>(SCALED_MIX_BUFFER_SIZE) - dsp_state.fraction, resample_rate);
  769. if (min_required_samples >= sample_count) {
  770. min_required_samples = sample_count;
  771. }
  772. std::size_t temp_mix_offset{};
  773. bool is_buffer_completed{false};
  774. auto samples_remaining = sample_count;
  775. while (samples_remaining > 0 && !is_buffer_completed) {
  776. const auto samples_to_output = std::min(samples_remaining, min_required_samples);
  777. const auto samples_to_read = (samples_to_output * resample_rate + dsp_state.fraction) >> 15;
  778. if (!in_params.behavior_flags.is_pitch_and_src_skipped) {
  779. // Append sample histtory for resampler
  780. for (std::size_t i = 0; i < AudioCommon::MAX_SAMPLE_HISTORY; i++) {
  781. sample_buffer[temp_mix_offset + i] = dsp_state.sample_history[i];
  782. }
  783. temp_mix_offset += 4;
  784. }
  785. s32 samples_read{};
  786. while (samples_read < samples_to_read) {
  787. const auto& wave_buffer = in_params.wave_buffer[dsp_state.wave_buffer_index];
  788. // No more data can be read
  789. if (!dsp_state.is_wave_buffer_valid[dsp_state.wave_buffer_index]) {
  790. is_buffer_completed = true;
  791. break;
  792. }
  793. if (in_params.sample_format == SampleFormat::Adpcm && dsp_state.offset == 0 &&
  794. wave_buffer.context_address != 0 && wave_buffer.context_size != 0) {
  795. // TODO(ogniK): ADPCM loop context
  796. }
  797. s32 samples_decoded{0};
  798. switch (in_params.sample_format) {
  799. case SampleFormat::Pcm16:
  800. samples_decoded = DecodePcm16(voice_info, dsp_state, samples_to_read - samples_read,
  801. channel, temp_mix_offset);
  802. break;
  803. case SampleFormat::Adpcm:
  804. samples_decoded = DecodeAdpcm(voice_info, dsp_state, samples_to_read - samples_read,
  805. channel, temp_mix_offset);
  806. break;
  807. default:
  808. UNREACHABLE_MSG("Unimplemented sample format={}", in_params.sample_format);
  809. }
  810. temp_mix_offset += samples_decoded;
  811. samples_read += samples_decoded;
  812. dsp_state.offset += samples_decoded;
  813. dsp_state.played_sample_count += samples_decoded;
  814. if (dsp_state.offset >=
  815. (wave_buffer.end_sample_offset - wave_buffer.start_sample_offset) ||
  816. samples_decoded == 0) {
  817. // Reset our sample offset
  818. dsp_state.offset = 0;
  819. if (wave_buffer.is_looping) {
  820. if (samples_decoded == 0) {
  821. // End of our buffer
  822. is_buffer_completed = true;
  823. break;
  824. }
  825. if (in_params.behavior_flags.is_played_samples_reset_at_loop_point.Value()) {
  826. dsp_state.played_sample_count = 0;
  827. }
  828. } else {
  829. // Update our wave buffer states
  830. dsp_state.is_wave_buffer_valid[dsp_state.wave_buffer_index] = false;
  831. dsp_state.wave_buffer_consumed++;
  832. dsp_state.wave_buffer_index =
  833. (dsp_state.wave_buffer_index + 1) % AudioCommon::MAX_WAVE_BUFFERS;
  834. if (wave_buffer.end_of_stream) {
  835. dsp_state.played_sample_count = 0;
  836. }
  837. }
  838. }
  839. }
  840. if (in_params.behavior_flags.is_pitch_and_src_skipped.Value()) {
  841. // No need to resample
  842. std::memcpy(output, sample_buffer.data(), samples_read * sizeof(s32));
  843. } else {
  844. std::fill(sample_buffer.begin() + temp_mix_offset,
  845. sample_buffer.begin() + temp_mix_offset + (samples_to_read - samples_read),
  846. 0);
  847. AudioCore::Resample(output, sample_buffer.data(), resample_rate, dsp_state.fraction,
  848. samples_to_output);
  849. // Resample
  850. for (std::size_t i = 0; i < AudioCommon::MAX_SAMPLE_HISTORY; i++) {
  851. dsp_state.sample_history[i] = sample_buffer[samples_to_read + i];
  852. }
  853. }
  854. output += samples_to_output;
  855. samples_remaining -= samples_to_output;
  856. }
  857. }
  858. } // namespace AudioCore