audio_renderer.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. // Copyright 2018 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <limits>
  5. #include <vector>
  6. #include "audio_core/audio_out.h"
  7. #include "audio_core/audio_renderer.h"
  8. #include "audio_core/common.h"
  9. #include "audio_core/info_updater.h"
  10. #include "audio_core/voice_context.h"
  11. #include "common/logging/log.h"
  12. #include "core/hle/kernel/writable_event.h"
  13. #include "core/memory.h"
  14. #include "core/settings.h"
  15. namespace {
  16. [[nodiscard]] static constexpr s16 ClampToS16(s32 value) {
  17. return static_cast<s16>(std::clamp(value, s32{std::numeric_limits<s16>::min()},
  18. s32{std::numeric_limits<s16>::max()}));
  19. }
  20. [[nodiscard]] static constexpr s16 Mix2To1(s16 l_channel, s16 r_channel) {
  21. // Mix 50% from left and 50% from right channel
  22. constexpr float l_mix_amount = 50.0f / 100.0f;
  23. constexpr float r_mix_amount = 50.0f / 100.0f;
  24. return ClampToS16(static_cast<s32>((static_cast<float>(l_channel) * l_mix_amount) +
  25. (static_cast<float>(r_channel) * r_mix_amount)));
  26. }
  27. [[nodiscard]] static constexpr std::tuple<s16, s16> Mix6To2(s16 fl_channel, s16 fr_channel,
  28. s16 fc_channel,
  29. [[maybe_unused]] s16 lf_channel,
  30. s16 bl_channel, s16 br_channel) {
  31. // Front channels are mixed 36.94%, Center channels are mixed to be 26.12% & the back channels
  32. // are mixed to be 36.94%
  33. constexpr float front_mix_amount = 36.94f / 100.0f;
  34. constexpr float center_mix_amount = 26.12f / 100.0f;
  35. constexpr float back_mix_amount = 36.94f / 100.0f;
  36. // Mix 50% from left and 50% from right channel
  37. const auto left = front_mix_amount * static_cast<float>(fl_channel) +
  38. center_mix_amount * static_cast<float>(fc_channel) +
  39. back_mix_amount * static_cast<float>(bl_channel);
  40. const auto right = front_mix_amount * static_cast<float>(fr_channel) +
  41. center_mix_amount * static_cast<float>(fc_channel) +
  42. back_mix_amount * static_cast<float>(br_channel);
  43. return {ClampToS16(static_cast<s32>(left)), ClampToS16(static_cast<s32>(right))};
  44. }
  45. [[nodiscard]] static constexpr std::tuple<s16, s16> Mix6To2WithCoefficients(
  46. s16 fl_channel, s16 fr_channel, s16 fc_channel, s16 lf_channel, s16 bl_channel, s16 br_channel,
  47. const std::array<float_le, 4>& coeff) {
  48. const auto left =
  49. static_cast<float>(fl_channel) * coeff[0] + static_cast<float>(fc_channel) * coeff[1] +
  50. static_cast<float>(lf_channel) * coeff[2] + static_cast<float>(bl_channel) * coeff[0];
  51. const auto right =
  52. static_cast<float>(fr_channel) * coeff[0] + static_cast<float>(fc_channel) * coeff[1] +
  53. static_cast<float>(lf_channel) * coeff[2] + static_cast<float>(br_channel) * coeff[0];
  54. return {ClampToS16(static_cast<s32>(left)), ClampToS16(static_cast<s32>(right))};
  55. }
  56. } // namespace
  57. namespace AudioCore {
  58. AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, Core::Memory::Memory& memory_,
  59. AudioCommon::AudioRendererParameter params,
  60. std::shared_ptr<Kernel::WritableEvent> buffer_event,
  61. std::size_t instance_number)
  62. : worker_params{params}, buffer_event{buffer_event},
  63. memory_pool_info(params.effect_count + params.voice_count * 4),
  64. voice_context(params.voice_count), effect_context(params.effect_count), mix_context(),
  65. sink_context(params.sink_count), splitter_context(),
  66. voices(params.voice_count), memory{memory_},
  67. command_generator(worker_params, voice_context, mix_context, splitter_context, effect_context,
  68. memory) {
  69. behavior_info.SetUserRevision(params.revision);
  70. splitter_context.Initialize(behavior_info, params.splitter_count,
  71. params.num_splitter_send_channels);
  72. mix_context.Initialize(behavior_info, params.submix_count + 1, params.effect_count);
  73. audio_out = std::make_unique<AudioCore::AudioOut>();
  74. stream =
  75. audio_out->OpenStream(core_timing, params.sample_rate, AudioCommon::STREAM_NUM_CHANNELS,
  76. fmt::format("AudioRenderer-Instance{}", instance_number),
  77. [=]() { buffer_event->Signal(); });
  78. audio_out->StartStream(stream);
  79. QueueMixedBuffer(0);
  80. QueueMixedBuffer(1);
  81. QueueMixedBuffer(2);
  82. QueueMixedBuffer(3);
  83. }
  84. AudioRenderer::~AudioRenderer() = default;
  85. u32 AudioRenderer::GetSampleRate() const {
  86. return worker_params.sample_rate;
  87. }
  88. u32 AudioRenderer::GetSampleCount() const {
  89. return worker_params.sample_count;
  90. }
  91. u32 AudioRenderer::GetMixBufferCount() const {
  92. return worker_params.mix_buffer_count;
  93. }
  94. Stream::State AudioRenderer::GetStreamState() const {
  95. return stream->GetState();
  96. }
  97. ResultCode AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_params,
  98. std::vector<u8>& output_params) {
  99. InfoUpdater info_updater{input_params, output_params, behavior_info};
  100. if (!info_updater.UpdateBehaviorInfo(behavior_info)) {
  101. LOG_ERROR(Audio, "Failed to update behavior info input parameters");
  102. return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
  103. }
  104. if (!info_updater.UpdateMemoryPools(memory_pool_info)) {
  105. LOG_ERROR(Audio, "Failed to update memory pool parameters");
  106. return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
  107. }
  108. if (!info_updater.UpdateVoiceChannelResources(voice_context)) {
  109. LOG_ERROR(Audio, "Failed to update voice channel resource parameters");
  110. return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
  111. }
  112. if (!info_updater.UpdateVoices(voice_context, memory_pool_info, 0)) {
  113. LOG_ERROR(Audio, "Failed to update voice parameters");
  114. return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
  115. }
  116. // TODO(ogniK): Deal with stopped audio renderer but updates still taking place
  117. if (!info_updater.UpdateEffects(effect_context, true)) {
  118. LOG_ERROR(Audio, "Failed to update effect parameters");
  119. return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
  120. }
  121. if (behavior_info.IsSplitterSupported()) {
  122. if (!info_updater.UpdateSplitterInfo(splitter_context)) {
  123. LOG_ERROR(Audio, "Failed to update splitter parameters");
  124. return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
  125. }
  126. }
  127. const auto mix_result = info_updater.UpdateMixes(mix_context, worker_params.mix_buffer_count,
  128. splitter_context, effect_context);
  129. if (mix_result.IsError()) {
  130. LOG_ERROR(Audio, "Failed to update mix parameters");
  131. return mix_result;
  132. }
  133. // TODO(ogniK): Sinks
  134. if (!info_updater.UpdateSinks(sink_context)) {
  135. LOG_ERROR(Audio, "Failed to update sink parameters");
  136. return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
  137. }
  138. // TODO(ogniK): Performance buffer
  139. if (!info_updater.UpdatePerformanceBuffer()) {
  140. LOG_ERROR(Audio, "Failed to update performance buffer parameters");
  141. return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
  142. }
  143. if (!info_updater.UpdateErrorInfo(behavior_info)) {
  144. LOG_ERROR(Audio, "Failed to update error info");
  145. return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
  146. }
  147. if (behavior_info.IsElapsedFrameCountSupported()) {
  148. if (!info_updater.UpdateRendererInfo(elapsed_frame_count)) {
  149. LOG_ERROR(Audio, "Failed to update renderer info");
  150. return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
  151. }
  152. }
  153. // TODO(ogniK): Statistics
  154. if (!info_updater.WriteOutputHeader()) {
  155. LOG_ERROR(Audio, "Failed to write output header");
  156. return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
  157. }
  158. // TODO(ogniK): Check when all sections are implemented
  159. if (!info_updater.CheckConsumedSize()) {
  160. LOG_ERROR(Audio, "Audio buffers were not consumed!");
  161. return AudioCommon::Audren::ERR_INVALID_PARAMETERS;
  162. }
  163. ReleaseAndQueueBuffers();
  164. return RESULT_SUCCESS;
  165. }
  166. void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) {
  167. command_generator.PreCommand();
  168. // Clear mix buffers before our next operation
  169. command_generator.ClearMixBuffers();
  170. // If the splitter is not in use, sort our mixes
  171. if (!splitter_context.UsingSplitter()) {
  172. mix_context.SortInfo();
  173. }
  174. // Sort our voices
  175. voice_context.SortInfo();
  176. // Handle samples
  177. command_generator.GenerateVoiceCommands();
  178. command_generator.GenerateSubMixCommands();
  179. command_generator.GenerateFinalMixCommands();
  180. command_generator.PostCommand();
  181. // Base sample size
  182. std::size_t BUFFER_SIZE{worker_params.sample_count};
  183. // Samples
  184. std::vector<s16> buffer(BUFFER_SIZE * stream->GetNumChannels());
  185. // Make sure to clear our samples
  186. std::memset(buffer.data(), 0, buffer.size() * sizeof(s16));
  187. if (sink_context.InUse()) {
  188. const auto stream_channel_count = stream->GetNumChannels();
  189. const auto buffer_offsets = sink_context.OutputBuffers();
  190. const auto channel_count = buffer_offsets.size();
  191. const auto& final_mix = mix_context.GetFinalMixInfo();
  192. const auto& in_params = final_mix.GetInParams();
  193. std::vector<s32*> mix_buffers(channel_count);
  194. for (std::size_t i = 0; i < channel_count; i++) {
  195. mix_buffers[i] =
  196. command_generator.GetMixBuffer(in_params.buffer_offset + buffer_offsets[i]);
  197. }
  198. for (std::size_t i = 0; i < BUFFER_SIZE; i++) {
  199. if (channel_count == 1) {
  200. const auto sample = ClampToS16(mix_buffers[0][i]);
  201. // Place sample in all channels
  202. for (u32 channel = 0; channel < stream_channel_count; channel++) {
  203. buffer[i * stream_channel_count + channel] = sample;
  204. }
  205. if (stream_channel_count == 6) {
  206. // Output stream has a LF channel, mute it!
  207. buffer[i * stream_channel_count + 3] = 0;
  208. }
  209. } else if (channel_count == 2) {
  210. const auto l_sample = ClampToS16(mix_buffers[0][i]);
  211. const auto r_sample = ClampToS16(mix_buffers[1][i]);
  212. if (stream_channel_count == 1) {
  213. buffer[i * stream_channel_count + 0] = Mix2To1(l_sample, r_sample);
  214. } else if (stream_channel_count == 2) {
  215. buffer[i * stream_channel_count + 0] = l_sample;
  216. buffer[i * stream_channel_count + 1] = r_sample;
  217. } else if (stream_channel_count == 6) {
  218. buffer[i * stream_channel_count + 0] = l_sample;
  219. buffer[i * stream_channel_count + 1] = r_sample;
  220. // Combine both left and right channels to the center channel
  221. buffer[i * stream_channel_count + 2] = Mix2To1(l_sample, r_sample);
  222. buffer[i * stream_channel_count + 4] = l_sample;
  223. buffer[i * stream_channel_count + 5] = r_sample;
  224. }
  225. } else if (channel_count == 6) {
  226. const auto fl_sample = ClampToS16(mix_buffers[0][i]);
  227. const auto fr_sample = ClampToS16(mix_buffers[1][i]);
  228. const auto fc_sample = ClampToS16(mix_buffers[2][i]);
  229. const auto lf_sample = ClampToS16(mix_buffers[3][i]);
  230. const auto bl_sample = ClampToS16(mix_buffers[4][i]);
  231. const auto br_sample = ClampToS16(mix_buffers[5][i]);
  232. if (stream_channel_count == 1) {
  233. // Games seem to ignore the center channel half the time, we use the front left
  234. // and right channel for mixing as that's where majority of the audio goes
  235. buffer[i * stream_channel_count + 0] = Mix2To1(fl_sample, fr_sample);
  236. } else if (stream_channel_count == 2) {
  237. // Mix all channels into 2 channels
  238. if (sink_context.HasDownMixingCoefficients()) {
  239. const auto [left, right] = Mix6To2WithCoefficients(
  240. fl_sample, fr_sample, fc_sample, lf_sample, bl_sample, br_sample,
  241. sink_context.GetDownmixCoefficients());
  242. buffer[i * stream_channel_count + 0] = left;
  243. buffer[i * stream_channel_count + 1] = right;
  244. } else {
  245. const auto [left, right] = Mix6To2(fl_sample, fr_sample, fc_sample,
  246. lf_sample, bl_sample, br_sample);
  247. buffer[i * stream_channel_count + 0] = left;
  248. buffer[i * stream_channel_count + 1] = right;
  249. }
  250. } else if (stream_channel_count == 6) {
  251. // Pass through
  252. buffer[i * stream_channel_count + 0] = fl_sample;
  253. buffer[i * stream_channel_count + 1] = fr_sample;
  254. buffer[i * stream_channel_count + 2] = fc_sample;
  255. buffer[i * stream_channel_count + 3] = lf_sample;
  256. buffer[i * stream_channel_count + 4] = bl_sample;
  257. buffer[i * stream_channel_count + 5] = br_sample;
  258. }
  259. }
  260. }
  261. }
  262. audio_out->QueueBuffer(stream, tag, std::move(buffer));
  263. elapsed_frame_count++;
  264. voice_context.UpdateStateByDspShared();
  265. }
  266. void AudioRenderer::ReleaseAndQueueBuffers() {
  267. const auto released_buffers{audio_out->GetTagsAndReleaseBuffers(stream)};
  268. for (const auto& tag : released_buffers) {
  269. QueueMixedBuffer(tag);
  270. }
  271. }
  272. } // namespace AudioCore