stream.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <algorithm>
  4. #include <cmath>
  5. #include "audio_core/sink.h"
  6. #include "audio_core/sink_details.h"
  7. #include "audio_core/sink_stream.h"
  8. #include "audio_core/stream.h"
  9. #include "common/assert.h"
  10. #include "common/logging/log.h"
  11. #include "common/settings.h"
  12. #include "core/core_timing.h"
  13. namespace AudioCore {
  14. constexpr std::size_t MaxAudioBufferCount{32};
  15. u32 Stream::GetNumChannels() const {
  16. switch (format) {
  17. case Format::Mono16:
  18. return 1;
  19. case Format::Stereo16:
  20. return 2;
  21. case Format::Multi51Channel16:
  22. return 6;
  23. }
  24. UNIMPLEMENTED_MSG("Unimplemented format={}", static_cast<u32>(format));
  25. return {};
  26. }
  27. Stream::Stream(Core::Timing::CoreTiming& core_timing_, u32 sample_rate_, Format format_,
  28. ReleaseCallback&& release_callback_, SinkStream& sink_stream_, std::string&& name_)
  29. : sample_rate{sample_rate_}, format{format_}, release_callback{std::move(release_callback_)},
  30. sink_stream{sink_stream_}, core_timing{core_timing_}, name{std::move(name_)} {
  31. release_event =
  32. Core::Timing::CreateEvent(name, [this](std::uintptr_t, std::chrono::nanoseconds ns_late) {
  33. ReleaseActiveBuffer(ns_late);
  34. });
  35. }
  36. void Stream::Play() {
  37. state = State::Playing;
  38. PlayNextBuffer();
  39. }
  40. void Stream::Stop() {
  41. state = State::Stopped;
  42. UNIMPLEMENTED();
  43. }
  44. bool Stream::Flush() {
  45. const bool had_buffers = !queued_buffers.empty();
  46. while (!queued_buffers.empty()) {
  47. queued_buffers.pop();
  48. }
  49. return had_buffers;
  50. }
  51. void Stream::SetVolume(float volume) {
  52. game_volume = volume;
  53. }
  54. Stream::State Stream::GetState() const {
  55. return state;
  56. }
  57. std::chrono::nanoseconds Stream::GetBufferReleaseNS(const Buffer& buffer) const {
  58. const std::size_t num_samples{buffer.GetSamples().size() / GetNumChannels()};
  59. return std::chrono::nanoseconds((static_cast<u64>(num_samples) * 1000000000ULL) / sample_rate);
  60. }
  61. static void VolumeAdjustSamples(std::vector<s16>& samples, float game_volume) {
  62. const float volume{std::clamp(Settings::Volume() - (1.0f - game_volume), 0.0f, 1.0f)};
  63. if (volume == 1.0f) {
  64. return;
  65. }
  66. // Perceived volume is not the same as the volume level
  67. const float volume_scale_factor = (0.85f * ((volume * volume) - volume)) + volume;
  68. for (auto& sample : samples) {
  69. sample = static_cast<s16>(sample * volume_scale_factor);
  70. }
  71. }
  72. void Stream::PlayNextBuffer(std::chrono::nanoseconds ns_late) {
  73. if (!IsPlaying()) {
  74. // Ensure we are in playing state before playing the next buffer
  75. sink_stream.Flush();
  76. return;
  77. }
  78. if (active_buffer) {
  79. // Do not queue a new buffer if we are already playing a buffer
  80. return;
  81. }
  82. if (queued_buffers.empty()) {
  83. // No queued buffers - we are effectively paused
  84. sink_stream.Flush();
  85. return;
  86. }
  87. active_buffer = queued_buffers.front();
  88. queued_buffers.pop();
  89. auto& samples = active_buffer->GetSamples();
  90. VolumeAdjustSamples(samples, game_volume);
  91. sink_stream.EnqueueSamples(GetNumChannels(), samples);
  92. played_samples += samples.size();
  93. const auto buffer_release_ns = GetBufferReleaseNS(*active_buffer);
  94. // If ns_late is higher than the update rate ignore the delay
  95. if (ns_late > buffer_release_ns) {
  96. ns_late = {};
  97. }
  98. core_timing.ScheduleEvent(buffer_release_ns - ns_late, release_event, {});
  99. }
  100. void Stream::ReleaseActiveBuffer(std::chrono::nanoseconds ns_late) {
  101. ASSERT(active_buffer);
  102. released_buffers.push(std::move(active_buffer));
  103. release_callback();
  104. PlayNextBuffer(ns_late);
  105. }
  106. bool Stream::QueueBuffer(BufferPtr&& buffer) {
  107. if (queued_buffers.size() < MaxAudioBufferCount) {
  108. queued_buffers.push(std::move(buffer));
  109. PlayNextBuffer();
  110. return true;
  111. }
  112. return false;
  113. }
  114. bool Stream::ContainsBuffer([[maybe_unused]] Buffer::Tag tag) const {
  115. UNIMPLEMENTED();
  116. return {};
  117. }
  118. std::vector<Buffer::Tag> Stream::GetTagsAndReleaseBuffers(std::size_t max_count) {
  119. std::vector<Buffer::Tag> tags;
  120. for (std::size_t count = 0; count < max_count && !released_buffers.empty(); ++count) {
  121. if (released_buffers.front()) {
  122. tags.push_back(released_buffers.front()->GetTag());
  123. } else {
  124. ASSERT_MSG(false, "Invalid tag in released_buffers!");
  125. }
  126. released_buffers.pop();
  127. }
  128. return tags;
  129. }
  130. std::vector<Buffer::Tag> Stream::GetTagsAndReleaseBuffers() {
  131. std::vector<Buffer::Tag> tags;
  132. tags.reserve(released_buffers.size());
  133. while (!released_buffers.empty()) {
  134. if (released_buffers.front()) {
  135. tags.push_back(released_buffers.front()->GetTag());
  136. } else {
  137. ASSERT_MSG(false, "Invalid tag in released_buffers!");
  138. }
  139. released_buffers.pop();
  140. }
  141. return tags;
  142. }
  143. } // namespace AudioCore