audio_renderer.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. // Copyright 2018 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "audio_core/audio_renderer.h"
  5. #include "common/assert.h"
  6. #include "common/logging/log.h"
  7. #include "core/memory.h"
  8. namespace AudioCore {
  9. constexpr u32 STREAM_SAMPLE_RATE{48000};
  10. constexpr u32 STREAM_NUM_CHANNELS{2};
  11. AudioRenderer::AudioRenderer(AudioRendererParameter params,
  12. Kernel::SharedPtr<Kernel::Event> buffer_event)
  13. : worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count) {
  14. audio_core = std::make_unique<AudioCore::AudioOut>();
  15. stream = audio_core->OpenStream(STREAM_SAMPLE_RATE, STREAM_NUM_CHANNELS, "AudioRenderer",
  16. [=]() { buffer_event->Signal(); });
  17. audio_core->StartStream(stream);
  18. QueueMixedBuffer(0);
  19. QueueMixedBuffer(1);
  20. QueueMixedBuffer(2);
  21. }
  22. u32 AudioRenderer::GetSampleRate() const {
  23. return worker_params.sample_rate;
  24. }
  25. u32 AudioRenderer::GetSampleCount() const {
  26. return worker_params.sample_count;
  27. }
  28. u32 AudioRenderer::GetMixBufferCount() const {
  29. return worker_params.mix_buffer_count;
  30. }
  31. std::vector<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_params) {
  32. // Copy UpdateDataHeader struct
  33. UpdateDataHeader config{};
  34. std::memcpy(&config, input_params.data(), sizeof(UpdateDataHeader));
  35. u32 memory_pool_count = worker_params.effect_count + (worker_params.voice_count * 4);
  36. // Copy MemoryPoolInfo structs
  37. std::vector<MemoryPoolInfo> mem_pool_info(memory_pool_count);
  38. std::memcpy(mem_pool_info.data(),
  39. input_params.data() + sizeof(UpdateDataHeader) + config.behavior_size,
  40. memory_pool_count * sizeof(MemoryPoolInfo));
  41. // Copy VoiceInfo structs
  42. size_t offset{sizeof(UpdateDataHeader) + config.behavior_size + config.memory_pools_size +
  43. config.voice_resource_size};
  44. for (auto& voice : voices) {
  45. std::memcpy(&voice.Info(), input_params.data() + offset, sizeof(VoiceInfo));
  46. offset += sizeof(VoiceInfo);
  47. }
  48. // Update voices
  49. for (auto& voice : voices) {
  50. voice.UpdateState();
  51. if (!voice.GetInfo().is_in_use) {
  52. continue;
  53. }
  54. if (voice.GetInfo().is_new) {
  55. voice.SetWaveIndex(voice.GetInfo().wave_buffer_head);
  56. }
  57. }
  58. // Update memory pool state
  59. std::vector<MemoryPoolEntry> memory_pool(memory_pool_count);
  60. for (size_t index = 0; index < memory_pool.size(); ++index) {
  61. if (mem_pool_info[index].pool_state == MemoryPoolStates::RequestAttach) {
  62. memory_pool[index].state = MemoryPoolStates::Attached;
  63. } else if (mem_pool_info[index].pool_state == MemoryPoolStates::RequestDetach) {
  64. memory_pool[index].state = MemoryPoolStates::Detached;
  65. }
  66. }
  67. // Release previous buffers and queue next ones for playback
  68. ReleaseAndQueueBuffers();
  69. // Copy output header
  70. UpdateDataHeader response_data{worker_params};
  71. std::vector<u8> output_params(response_data.total_size);
  72. std::memcpy(output_params.data(), &response_data, sizeof(UpdateDataHeader));
  73. // Copy output memory pool entries
  74. std::memcpy(output_params.data() + sizeof(UpdateDataHeader), memory_pool.data(),
  75. response_data.memory_pools_size);
  76. // Copy output voice status
  77. size_t voice_out_status_offset{sizeof(UpdateDataHeader) + response_data.memory_pools_size};
  78. for (const auto& voice : voices) {
  79. std::memcpy(output_params.data() + voice_out_status_offset, &voice.GetOutStatus(),
  80. sizeof(VoiceOutStatus));
  81. voice_out_status_offset += sizeof(VoiceOutStatus);
  82. }
  83. return output_params;
  84. }
  85. void AudioRenderer::VoiceState::SetWaveIndex(size_t index) {
  86. wave_index = index & 3;
  87. is_refresh_pending = true;
  88. }
  89. std::vector<s16> AudioRenderer::VoiceState::DequeueSamples(size_t sample_count) {
  90. if (!IsPlaying()) {
  91. return {};
  92. }
  93. if (is_refresh_pending) {
  94. RefreshBuffer();
  95. }
  96. const size_t max_size{samples.size() - offset};
  97. const size_t dequeue_offset{offset};
  98. size_t size{sample_count * STREAM_NUM_CHANNELS};
  99. if (size > max_size) {
  100. size = max_size;
  101. }
  102. out_status.played_sample_count += size / STREAM_NUM_CHANNELS;
  103. offset += size;
  104. const auto& wave_buffer{info.wave_buffer[wave_index]};
  105. if (offset == samples.size()) {
  106. offset = 0;
  107. if (!wave_buffer.is_looping) {
  108. SetWaveIndex(wave_index + 1);
  109. }
  110. out_status.wave_buffer_consumed++;
  111. if (wave_buffer.end_of_stream) {
  112. info.play_state = PlayState::Paused;
  113. }
  114. }
  115. return {samples.begin() + dequeue_offset, samples.begin() + dequeue_offset + size};
  116. }
  117. void AudioRenderer::VoiceState::UpdateState() {
  118. if (is_in_use && !info.is_in_use) {
  119. // No longer in use, reset state
  120. is_refresh_pending = true;
  121. wave_index = 0;
  122. offset = 0;
  123. out_status = {};
  124. }
  125. is_in_use = info.is_in_use;
  126. }
  127. void AudioRenderer::VoiceState::RefreshBuffer() {
  128. std::vector<s16> new_samples(info.wave_buffer[wave_index].buffer_sz / sizeof(s16));
  129. Memory::ReadBlock(info.wave_buffer[wave_index].buffer_addr, new_samples.data(),
  130. info.wave_buffer[wave_index].buffer_sz);
  131. switch (static_cast<Codec::PcmFormat>(info.sample_format)) {
  132. case Codec::PcmFormat::Int16: {
  133. // PCM16 is played as-is
  134. break;
  135. }
  136. case Codec::PcmFormat::Adpcm: {
  137. // Decode ADPCM to PCM16
  138. Codec::ADPCM_Coeff coeffs;
  139. Memory::ReadBlock(info.additional_params_addr, coeffs.data(), sizeof(Codec::ADPCM_Coeff));
  140. new_samples = Codec::DecodeADPCM(reinterpret_cast<u8*>(new_samples.data()),
  141. new_samples.size() * sizeof(s16), coeffs, adpcm_state);
  142. break;
  143. }
  144. default:
  145. LOG_CRITICAL(Audio, "Unimplemented sample_format={}", info.sample_format);
  146. UNREACHABLE();
  147. break;
  148. }
  149. switch (info.channel_count) {
  150. case 1:
  151. // 1 channel is upsampled to 2 channel
  152. samples.resize(new_samples.size() * 2);
  153. for (size_t index = 0; index < new_samples.size(); ++index) {
  154. samples[index * 2] = new_samples[index];
  155. samples[index * 2 + 1] = new_samples[index];
  156. }
  157. break;
  158. case 2: {
  159. // 2 channel is played as is
  160. samples = std::move(new_samples);
  161. break;
  162. }
  163. default:
  164. LOG_CRITICAL(Audio, "Unimplemented channel_count={}", info.channel_count);
  165. UNREACHABLE();
  166. break;
  167. }
  168. is_refresh_pending = false;
  169. }
  170. static constexpr s16 ClampToS16(s32 value) {
  171. return static_cast<s16>(std::clamp(value, -32768, 32767));
  172. }
  173. void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) {
  174. constexpr size_t BUFFER_SIZE{512};
  175. std::vector<s16> buffer(BUFFER_SIZE * stream->GetNumChannels());
  176. for (auto& voice : voices) {
  177. if (!voice.IsPlaying()) {
  178. continue;
  179. }
  180. size_t offset{};
  181. s64 samples_remaining{BUFFER_SIZE};
  182. while (samples_remaining > 0) {
  183. const std::vector<s16> samples{voice.DequeueSamples(samples_remaining)};
  184. if (samples.empty()) {
  185. break;
  186. }
  187. samples_remaining -= samples.size();
  188. for (const auto& sample : samples) {
  189. const s32 buffer_sample{buffer[offset]};
  190. buffer[offset++] =
  191. ClampToS16(buffer_sample + static_cast<s32>(sample * voice.GetInfo().volume));
  192. }
  193. }
  194. }
  195. audio_core->QueueBuffer(stream, tag, std::move(buffer));
  196. }
  197. void AudioRenderer::ReleaseAndQueueBuffers() {
  198. const auto released_buffers{audio_core->GetTagsAndReleaseBuffers(stream, 2)};
  199. for (const auto& tag : released_buffers) {
  200. QueueMixedBuffer(tag);
  201. }
  202. }
  203. } // namespace AudioCore