diff options
Diffstat (limited to 'src/audio_core')
| -rw-r--r-- | src/audio_core/algorithm/filter.cpp | 12 | ||||
| -rw-r--r-- | src/audio_core/algorithm/filter.h | 4 | ||||
| -rw-r--r-- | src/audio_core/algorithm/interpolate.cpp | 12 | ||||
| -rw-r--r-- | src/audio_core/algorithm/interpolate.h | 4 | ||||
| -rw-r--r-- | src/audio_core/audio_out.cpp | 3 | ||||
| -rw-r--r-- | src/audio_core/audio_out.h | 2 | ||||
| -rw-r--r-- | src/audio_core/audio_renderer.cpp | 64 | ||||
| -rw-r--r-- | src/audio_core/audio_renderer.h | 51 | ||||
| -rw-r--r-- | src/audio_core/codec.cpp | 20 | ||||
| -rw-r--r-- | src/audio_core/codec.h | 2 | ||||
| -rw-r--r-- | src/audio_core/cubeb_sink.cpp | 31 | ||||
| -rw-r--r-- | src/audio_core/null_sink.h | 2 | ||||
| -rw-r--r-- | src/audio_core/stream.cpp | 9 | ||||
| -rw-r--r-- | src/audio_core/stream.h | 13 | ||||
| -rw-r--r-- | src/audio_core/time_stretch.cpp | 7 | ||||
| -rw-r--r-- | src/audio_core/time_stretch.h | 3 |
16 files changed, 129 insertions, 110 deletions
diff --git a/src/audio_core/algorithm/filter.cpp b/src/audio_core/algorithm/filter.cpp index 9fcd0614d..f65bf64f7 100644 --- a/src/audio_core/algorithm/filter.cpp +++ b/src/audio_core/algorithm/filter.cpp | |||
| @@ -35,12 +35,12 @@ Filter::Filter(double a0, double a1, double a2, double b0, double b1, double b2) | |||
| 35 | : a1(a1 / a0), a2(a2 / a0), b0(b0 / a0), b1(b1 / a0), b2(b2 / a0) {} | 35 | : a1(a1 / a0), a2(a2 / a0), b0(b0 / a0), b1(b1 / a0), b2(b2 / a0) {} |
| 36 | 36 | ||
| 37 | void Filter::Process(std::vector<s16>& signal) { | 37 | void Filter::Process(std::vector<s16>& signal) { |
| 38 | const size_t num_frames = signal.size() / 2; | 38 | const std::size_t num_frames = signal.size() / 2; |
| 39 | for (size_t i = 0; i < num_frames; i++) { | 39 | for (std::size_t i = 0; i < num_frames; i++) { |
| 40 | std::rotate(in.begin(), in.end() - 1, in.end()); | 40 | std::rotate(in.begin(), in.end() - 1, in.end()); |
| 41 | std::rotate(out.begin(), out.end() - 1, out.end()); | 41 | std::rotate(out.begin(), out.end() - 1, out.end()); |
| 42 | 42 | ||
| 43 | for (size_t ch = 0; ch < channel_count; ch++) { | 43 | for (std::size_t ch = 0; ch < channel_count; ch++) { |
| 44 | in[0][ch] = signal[i * channel_count + ch]; | 44 | in[0][ch] = signal[i * channel_count + ch]; |
| 45 | 45 | ||
| 46 | out[0][ch] = b0 * in[0][ch] + b1 * in[1][ch] + b2 * in[2][ch] - a1 * out[1][ch] - | 46 | out[0][ch] = b0 * in[0][ch] + b1 * in[1][ch] + b2 * in[2][ch] - a1 * out[1][ch] - |
| @@ -54,14 +54,14 @@ void Filter::Process(std::vector<s16>& signal) { | |||
| 54 | /// Calculates the appropriate Q for each biquad in a cascading filter. | 54 | /// Calculates the appropriate Q for each biquad in a cascading filter. |
| 55 | /// @param total_count The total number of biquads to be cascaded. | 55 | /// @param total_count The total number of biquads to be cascaded. |
| 56 | /// @param index 0-index of the biquad to calculate the Q value for. | 56 | /// @param index 0-index of the biquad to calculate the Q value for. |
| 57 | static double CascadingBiquadQ(size_t total_count, size_t index) { | 57 | static double CascadingBiquadQ(std::size_t total_count, std::size_t index) { |
| 58 | const double pole = M_PI * (2 * index + 1) / (4.0 * total_count); | 58 | const double pole = M_PI * (2 * index + 1) / (4.0 * total_count); |
| 59 | return 1.0 / (2.0 * std::cos(pole)); | 59 | return 1.0 / (2.0 * std::cos(pole)); |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | CascadingFilter CascadingFilter::LowPass(double cutoff, size_t cascade_size) { | 62 | CascadingFilter CascadingFilter::LowPass(double cutoff, std::size_t cascade_size) { |
| 63 | std::vector<Filter> cascade(cascade_size); | 63 | std::vector<Filter> cascade(cascade_size); |
| 64 | for (size_t i = 0; i < cascade_size; i++) { | 64 | for (std::size_t i = 0; i < cascade_size; i++) { |
| 65 | cascade[i] = Filter::LowPass(cutoff, CascadingBiquadQ(cascade_size, i)); | 65 | cascade[i] = Filter::LowPass(cutoff, CascadingBiquadQ(cascade_size, i)); |
| 66 | } | 66 | } |
| 67 | return CascadingFilter{std::move(cascade)}; | 67 | return CascadingFilter{std::move(cascade)}; |
diff --git a/src/audio_core/algorithm/filter.h b/src/audio_core/algorithm/filter.h index a41beef98..3546d149b 100644 --- a/src/audio_core/algorithm/filter.h +++ b/src/audio_core/algorithm/filter.h | |||
| @@ -30,7 +30,7 @@ public: | |||
| 30 | void Process(std::vector<s16>& signal); | 30 | void Process(std::vector<s16>& signal); |
| 31 | 31 | ||
| 32 | private: | 32 | private: |
| 33 | static constexpr size_t channel_count = 2; | 33 | static constexpr std::size_t channel_count = 2; |
| 34 | 34 | ||
| 35 | /// Coefficients are in normalized form (a0 = 1.0). | 35 | /// Coefficients are in normalized form (a0 = 1.0). |
| 36 | double a1, a2, b0, b1, b2; | 36 | double a1, a2, b0, b1, b2; |
| @@ -46,7 +46,7 @@ public: | |||
| 46 | /// Creates a cascading low-pass filter. | 46 | /// Creates a cascading low-pass filter. |
| 47 | /// @param cutoff Determines the cutoff frequency. A value from 0.0 to 1.0. | 47 | /// @param cutoff Determines the cutoff frequency. A value from 0.0 to 1.0. |
| 48 | /// @param cascade_size Number of biquads in cascade. | 48 | /// @param cascade_size Number of biquads in cascade. |
| 49 | static CascadingFilter LowPass(double cutoff, size_t cascade_size); | 49 | static CascadingFilter LowPass(double cutoff, std::size_t cascade_size); |
| 50 | 50 | ||
| 51 | /// Passthrough. | 51 | /// Passthrough. |
| 52 | CascadingFilter(); | 52 | CascadingFilter(); |
diff --git a/src/audio_core/algorithm/interpolate.cpp b/src/audio_core/algorithm/interpolate.cpp index 11459821f..3aea9b0f2 100644 --- a/src/audio_core/algorithm/interpolate.cpp +++ b/src/audio_core/algorithm/interpolate.cpp | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | namespace AudioCore { | 14 | namespace AudioCore { |
| 15 | 15 | ||
| 16 | /// The Lanczos kernel | 16 | /// The Lanczos kernel |
| 17 | static double Lanczos(size_t a, double x) { | 17 | static double Lanczos(std::size_t a, double x) { |
| 18 | if (x == 0.0) | 18 | if (x == 0.0) |
| 19 | return 1.0; | 19 | return 1.0; |
| 20 | const double px = M_PI * x; | 20 | const double px = M_PI * x; |
| @@ -37,15 +37,15 @@ std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input, | |||
| 37 | } | 37 | } |
| 38 | state.nyquist.Process(input); | 38 | state.nyquist.Process(input); |
| 39 | 39 | ||
| 40 | constexpr size_t taps = InterpolationState::lanczos_taps; | 40 | constexpr std::size_t taps = InterpolationState::lanczos_taps; |
| 41 | const size_t num_frames = input.size() / 2; | 41 | const std::size_t num_frames = input.size() / 2; |
| 42 | 42 | ||
| 43 | std::vector<s16> output; | 43 | std::vector<s16> output; |
| 44 | output.reserve(static_cast<size_t>(input.size() / ratio + 4)); | 44 | output.reserve(static_cast<std::size_t>(input.size() / ratio + 4)); |
| 45 | 45 | ||
| 46 | double& pos = state.position; | 46 | double& pos = state.position; |
| 47 | auto& h = state.history; | 47 | auto& h = state.history; |
| 48 | for (size_t i = 0; i < num_frames; ++i) { | 48 | for (std::size_t i = 0; i < num_frames; ++i) { |
| 49 | std::rotate(h.begin(), h.end() - 1, h.end()); | 49 | std::rotate(h.begin(), h.end() - 1, h.end()); |
| 50 | h[0][0] = input[i * 2 + 0]; | 50 | h[0][0] = input[i * 2 + 0]; |
| 51 | h[0][1] = input[i * 2 + 1]; | 51 | h[0][1] = input[i * 2 + 1]; |
| @@ -53,7 +53,7 @@ std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input, | |||
| 53 | while (pos <= 1.0) { | 53 | while (pos <= 1.0) { |
| 54 | double l = 0.0; | 54 | double l = 0.0; |
| 55 | double r = 0.0; | 55 | double r = 0.0; |
| 56 | for (size_t j = 0; j < h.size(); j++) { | 56 | for (std::size_t j = 0; j < h.size(); j++) { |
| 57 | l += Lanczos(taps, pos + j - taps + 1) * h[j][0]; | 57 | l += Lanczos(taps, pos + j - taps + 1) * h[j][0]; |
| 58 | r += Lanczos(taps, pos + j - taps + 1) * h[j][1]; | 58 | r += Lanczos(taps, pos + j - taps + 1) * h[j][1]; |
| 59 | } | 59 | } |
diff --git a/src/audio_core/algorithm/interpolate.h b/src/audio_core/algorithm/interpolate.h index c79c2eef4..edbd6460f 100644 --- a/src/audio_core/algorithm/interpolate.h +++ b/src/audio_core/algorithm/interpolate.h | |||
| @@ -12,8 +12,8 @@ | |||
| 12 | namespace AudioCore { | 12 | namespace AudioCore { |
| 13 | 13 | ||
| 14 | struct InterpolationState { | 14 | struct InterpolationState { |
| 15 | static constexpr size_t lanczos_taps = 4; | 15 | static constexpr std::size_t lanczos_taps = 4; |
| 16 | static constexpr size_t history_size = lanczos_taps * 2 - 1; | 16 | static constexpr std::size_t history_size = lanczos_taps * 2 - 1; |
| 17 | 17 | ||
| 18 | double current_ratio = 0.0; | 18 | double current_ratio = 0.0; |
| 19 | CascadingFilter nyquist; | 19 | CascadingFilter nyquist; |
diff --git a/src/audio_core/audio_out.cpp b/src/audio_core/audio_out.cpp index 12632a95c..0c8f5b18e 100644 --- a/src/audio_core/audio_out.cpp +++ b/src/audio_core/audio_out.cpp | |||
| @@ -39,7 +39,8 @@ StreamPtr AudioOut::OpenStream(u32 sample_rate, u32 num_channels, std::string&& | |||
| 39 | sink->AcquireSinkStream(sample_rate, num_channels, name), std::move(name)); | 39 | sink->AcquireSinkStream(sample_rate, num_channels, name), std::move(name)); |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | std::vector<Buffer::Tag> AudioOut::GetTagsAndReleaseBuffers(StreamPtr stream, size_t max_count) { | 42 | std::vector<Buffer::Tag> AudioOut::GetTagsAndReleaseBuffers(StreamPtr stream, |
| 43 | std::size_t max_count) { | ||
| 43 | return stream->GetTagsAndReleaseBuffers(max_count); | 44 | return stream->GetTagsAndReleaseBuffers(max_count); |
| 44 | } | 45 | } |
| 45 | 46 | ||
diff --git a/src/audio_core/audio_out.h b/src/audio_core/audio_out.h index 39b7e656b..df9607ac7 100644 --- a/src/audio_core/audio_out.h +++ b/src/audio_core/audio_out.h | |||
| @@ -25,7 +25,7 @@ public: | |||
| 25 | Stream::ReleaseCallback&& release_callback); | 25 | Stream::ReleaseCallback&& release_callback); |
| 26 | 26 | ||
| 27 | /// Returns a vector of recently released buffers specified by tag for the specified stream | 27 | /// Returns a vector of recently released buffers specified by tag for the specified stream |
| 28 | std::vector<Buffer::Tag> GetTagsAndReleaseBuffers(StreamPtr stream, size_t max_count); | 28 | std::vector<Buffer::Tag> GetTagsAndReleaseBuffers(StreamPtr stream, std::size_t max_count); |
| 29 | 29 | ||
| 30 | /// Starts an audio stream for playback | 30 | /// Starts an audio stream for playback |
| 31 | void StartStream(StreamPtr stream); | 31 | void StartStream(StreamPtr stream); |
diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp index a75cd3be5..83b75e61f 100644 --- a/src/audio_core/audio_renderer.cpp +++ b/src/audio_core/audio_renderer.cpp | |||
| @@ -3,9 +3,12 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "audio_core/algorithm/interpolate.h" | 5 | #include "audio_core/algorithm/interpolate.h" |
| 6 | #include "audio_core/audio_out.h" | ||
| 6 | #include "audio_core/audio_renderer.h" | 7 | #include "audio_core/audio_renderer.h" |
| 8 | #include "audio_core/codec.h" | ||
| 7 | #include "common/assert.h" | 9 | #include "common/assert.h" |
| 8 | #include "common/logging/log.h" | 10 | #include "common/logging/log.h" |
| 11 | #include "core/hle/kernel/event.h" | ||
| 9 | #include "core/memory.h" | 12 | #include "core/memory.h" |
| 10 | 13 | ||
| 11 | namespace AudioCore { | 14 | namespace AudioCore { |
| @@ -13,6 +16,41 @@ namespace AudioCore { | |||
| 13 | constexpr u32 STREAM_SAMPLE_RATE{48000}; | 16 | constexpr u32 STREAM_SAMPLE_RATE{48000}; |
| 14 | constexpr u32 STREAM_NUM_CHANNELS{2}; | 17 | constexpr u32 STREAM_NUM_CHANNELS{2}; |
| 15 | 18 | ||
| 19 | class AudioRenderer::VoiceState { | ||
| 20 | public: | ||
| 21 | bool IsPlaying() const { | ||
| 22 | return is_in_use && info.play_state == PlayState::Started; | ||
| 23 | } | ||
| 24 | |||
| 25 | const VoiceOutStatus& GetOutStatus() const { | ||
| 26 | return out_status; | ||
| 27 | } | ||
| 28 | |||
| 29 | const VoiceInfo& GetInfo() const { | ||
| 30 | return info; | ||
| 31 | } | ||
| 32 | |||
| 33 | VoiceInfo& Info() { | ||
| 34 | return info; | ||
| 35 | } | ||
| 36 | |||
| 37 | void SetWaveIndex(std::size_t index); | ||
| 38 | std::vector<s16> DequeueSamples(std::size_t sample_count); | ||
| 39 | void UpdateState(); | ||
| 40 | void RefreshBuffer(); | ||
| 41 | |||
| 42 | private: | ||
| 43 | bool is_in_use{}; | ||
| 44 | bool is_refresh_pending{}; | ||
| 45 | std::size_t wave_index{}; | ||
| 46 | std::size_t offset{}; | ||
| 47 | Codec::ADPCMState adpcm_state{}; | ||
| 48 | InterpolationState interp_state{}; | ||
| 49 | std::vector<s16> samples; | ||
| 50 | VoiceOutStatus out_status{}; | ||
| 51 | VoiceInfo info{}; | ||
| 52 | }; | ||
| 53 | |||
| 16 | AudioRenderer::AudioRenderer(AudioRendererParameter params, | 54 | AudioRenderer::AudioRenderer(AudioRendererParameter params, |
| 17 | Kernel::SharedPtr<Kernel::Event> buffer_event) | 55 | Kernel::SharedPtr<Kernel::Event> buffer_event) |
| 18 | : worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count) { | 56 | : worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count) { |
| @@ -27,6 +65,8 @@ AudioRenderer::AudioRenderer(AudioRendererParameter params, | |||
| 27 | QueueMixedBuffer(2); | 65 | QueueMixedBuffer(2); |
| 28 | } | 66 | } |
| 29 | 67 | ||
| 68 | AudioRenderer::~AudioRenderer() = default; | ||
| 69 | |||
| 30 | u32 AudioRenderer::GetSampleRate() const { | 70 | u32 AudioRenderer::GetSampleRate() const { |
| 31 | return worker_params.sample_rate; | 71 | return worker_params.sample_rate; |
| 32 | } | 72 | } |
| @@ -52,8 +92,8 @@ std::vector<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_ | |||
| 52 | memory_pool_count * sizeof(MemoryPoolInfo)); | 92 | memory_pool_count * sizeof(MemoryPoolInfo)); |
| 53 | 93 | ||
| 54 | // Copy VoiceInfo structs | 94 | // Copy VoiceInfo structs |
| 55 | size_t offset{sizeof(UpdateDataHeader) + config.behavior_size + config.memory_pools_size + | 95 | std::size_t offset{sizeof(UpdateDataHeader) + config.behavior_size + config.memory_pools_size + |
| 56 | config.voice_resource_size}; | 96 | config.voice_resource_size}; |
| 57 | for (auto& voice : voices) { | 97 | for (auto& voice : voices) { |
| 58 | std::memcpy(&voice.Info(), input_params.data() + offset, sizeof(VoiceInfo)); | 98 | std::memcpy(&voice.Info(), input_params.data() + offset, sizeof(VoiceInfo)); |
| 59 | offset += sizeof(VoiceInfo); | 99 | offset += sizeof(VoiceInfo); |
| @@ -72,7 +112,7 @@ std::vector<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_ | |||
| 72 | 112 | ||
| 73 | // Update memory pool state | 113 | // Update memory pool state |
| 74 | std::vector<MemoryPoolEntry> memory_pool(memory_pool_count); | 114 | std::vector<MemoryPoolEntry> memory_pool(memory_pool_count); |
| 75 | for (size_t index = 0; index < memory_pool.size(); ++index) { | 115 | for (std::size_t index = 0; index < memory_pool.size(); ++index) { |
| 76 | if (mem_pool_info[index].pool_state == MemoryPoolStates::RequestAttach) { | 116 | if (mem_pool_info[index].pool_state == MemoryPoolStates::RequestAttach) { |
| 77 | memory_pool[index].state = MemoryPoolStates::Attached; | 117 | memory_pool[index].state = MemoryPoolStates::Attached; |
| 78 | } else if (mem_pool_info[index].pool_state == MemoryPoolStates::RequestDetach) { | 118 | } else if (mem_pool_info[index].pool_state == MemoryPoolStates::RequestDetach) { |
| @@ -93,7 +133,7 @@ std::vector<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_ | |||
| 93 | response_data.memory_pools_size); | 133 | response_data.memory_pools_size); |
| 94 | 134 | ||
| 95 | // Copy output voice status | 135 | // Copy output voice status |
| 96 | size_t voice_out_status_offset{sizeof(UpdateDataHeader) + response_data.memory_pools_size}; | 136 | std::size_t voice_out_status_offset{sizeof(UpdateDataHeader) + response_data.memory_pools_size}; |
| 97 | for (const auto& voice : voices) { | 137 | for (const auto& voice : voices) { |
| 98 | std::memcpy(output_params.data() + voice_out_status_offset, &voice.GetOutStatus(), | 138 | std::memcpy(output_params.data() + voice_out_status_offset, &voice.GetOutStatus(), |
| 99 | sizeof(VoiceOutStatus)); | 139 | sizeof(VoiceOutStatus)); |
| @@ -103,12 +143,12 @@ std::vector<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_ | |||
| 103 | return output_params; | 143 | return output_params; |
| 104 | } | 144 | } |
| 105 | 145 | ||
| 106 | void AudioRenderer::VoiceState::SetWaveIndex(size_t index) { | 146 | void AudioRenderer::VoiceState::SetWaveIndex(std::size_t index) { |
| 107 | wave_index = index & 3; | 147 | wave_index = index & 3; |
| 108 | is_refresh_pending = true; | 148 | is_refresh_pending = true; |
| 109 | } | 149 | } |
| 110 | 150 | ||
| 111 | std::vector<s16> AudioRenderer::VoiceState::DequeueSamples(size_t sample_count) { | 151 | std::vector<s16> AudioRenderer::VoiceState::DequeueSamples(std::size_t sample_count) { |
| 112 | if (!IsPlaying()) { | 152 | if (!IsPlaying()) { |
| 113 | return {}; | 153 | return {}; |
| 114 | } | 154 | } |
| @@ -117,9 +157,9 @@ std::vector<s16> AudioRenderer::VoiceState::DequeueSamples(size_t sample_count) | |||
| 117 | RefreshBuffer(); | 157 | RefreshBuffer(); |
| 118 | } | 158 | } |
| 119 | 159 | ||
| 120 | const size_t max_size{samples.size() - offset}; | 160 | const std::size_t max_size{samples.size() - offset}; |
| 121 | const size_t dequeue_offset{offset}; | 161 | const std::size_t dequeue_offset{offset}; |
| 122 | size_t size{sample_count * STREAM_NUM_CHANNELS}; | 162 | std::size_t size{sample_count * STREAM_NUM_CHANNELS}; |
| 123 | if (size > max_size) { | 163 | if (size > max_size) { |
| 124 | size = max_size; | 164 | size = max_size; |
| 125 | } | 165 | } |
| @@ -184,7 +224,7 @@ void AudioRenderer::VoiceState::RefreshBuffer() { | |||
| 184 | case 1: | 224 | case 1: |
| 185 | // 1 channel is upsampled to 2 channel | 225 | // 1 channel is upsampled to 2 channel |
| 186 | samples.resize(new_samples.size() * 2); | 226 | samples.resize(new_samples.size() * 2); |
| 187 | for (size_t index = 0; index < new_samples.size(); ++index) { | 227 | for (std::size_t index = 0; index < new_samples.size(); ++index) { |
| 188 | samples[index * 2] = new_samples[index]; | 228 | samples[index * 2] = new_samples[index]; |
| 189 | samples[index * 2 + 1] = new_samples[index]; | 229 | samples[index * 2 + 1] = new_samples[index]; |
| 190 | } | 230 | } |
| @@ -210,7 +250,7 @@ static constexpr s16 ClampToS16(s32 value) { | |||
| 210 | } | 250 | } |
| 211 | 251 | ||
| 212 | void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) { | 252 | void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) { |
| 213 | constexpr size_t BUFFER_SIZE{512}; | 253 | constexpr std::size_t BUFFER_SIZE{512}; |
| 214 | std::vector<s16> buffer(BUFFER_SIZE * stream->GetNumChannels()); | 254 | std::vector<s16> buffer(BUFFER_SIZE * stream->GetNumChannels()); |
| 215 | 255 | ||
| 216 | for (auto& voice : voices) { | 256 | for (auto& voice : voices) { |
| @@ -218,7 +258,7 @@ void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) { | |||
| 218 | continue; | 258 | continue; |
| 219 | } | 259 | } |
| 220 | 260 | ||
| 221 | size_t offset{}; | 261 | std::size_t offset{}; |
| 222 | s64 samples_remaining{BUFFER_SIZE}; | 262 | s64 samples_remaining{BUFFER_SIZE}; |
| 223 | while (samples_remaining > 0) { | 263 | while (samples_remaining > 0) { |
| 224 | const std::vector<s16> samples{voice.DequeueSamples(samples_remaining)}; | 264 | const std::vector<s16> samples{voice.DequeueSamples(samples_remaining)}; |
diff --git a/src/audio_core/audio_renderer.h b/src/audio_core/audio_renderer.h index 6d069d693..2c4f5ab75 100644 --- a/src/audio_core/audio_renderer.h +++ b/src/audio_core/audio_renderer.h | |||
| @@ -8,16 +8,20 @@ | |||
| 8 | #include <memory> | 8 | #include <memory> |
| 9 | #include <vector> | 9 | #include <vector> |
| 10 | 10 | ||
| 11 | #include "audio_core/algorithm/interpolate.h" | ||
| 12 | #include "audio_core/audio_out.h" | ||
| 13 | #include "audio_core/codec.h" | ||
| 14 | #include "audio_core/stream.h" | 11 | #include "audio_core/stream.h" |
| 12 | #include "common/common_funcs.h" | ||
| 15 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 16 | #include "common/swap.h" | 14 | #include "common/swap.h" |
| 17 | #include "core/hle/kernel/event.h" | 15 | #include "core/hle/kernel/object.h" |
| 16 | |||
| 17 | namespace Kernel { | ||
| 18 | class Event; | ||
| 19 | } | ||
| 18 | 20 | ||
| 19 | namespace AudioCore { | 21 | namespace AudioCore { |
| 20 | 22 | ||
| 23 | class AudioOut; | ||
| 24 | |||
| 21 | enum class PlayState : u8 { | 25 | enum class PlayState : u8 { |
| 22 | Started = 0, | 26 | Started = 0, |
| 23 | Stopped = 1, | 27 | Stopped = 1, |
| @@ -158,6 +162,8 @@ static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has wrong size | |||
| 158 | class AudioRenderer { | 162 | class AudioRenderer { |
| 159 | public: | 163 | public: |
| 160 | AudioRenderer(AudioRendererParameter params, Kernel::SharedPtr<Kernel::Event> buffer_event); | 164 | AudioRenderer(AudioRendererParameter params, Kernel::SharedPtr<Kernel::Event> buffer_event); |
| 165 | ~AudioRenderer(); | ||
| 166 | |||
| 161 | std::vector<u8> UpdateAudioRenderer(const std::vector<u8>& input_params); | 167 | std::vector<u8> UpdateAudioRenderer(const std::vector<u8>& input_params); |
| 162 | void QueueMixedBuffer(Buffer::Tag tag); | 168 | void QueueMixedBuffer(Buffer::Tag tag); |
| 163 | void ReleaseAndQueueBuffers(); | 169 | void ReleaseAndQueueBuffers(); |
| @@ -166,45 +172,12 @@ public: | |||
| 166 | u32 GetMixBufferCount() const; | 172 | u32 GetMixBufferCount() const; |
| 167 | 173 | ||
| 168 | private: | 174 | private: |
| 169 | class VoiceState { | 175 | class VoiceState; |
| 170 | public: | ||
| 171 | bool IsPlaying() const { | ||
| 172 | return is_in_use && info.play_state == PlayState::Started; | ||
| 173 | } | ||
| 174 | |||
| 175 | const VoiceOutStatus& GetOutStatus() const { | ||
| 176 | return out_status; | ||
| 177 | } | ||
| 178 | |||
| 179 | const VoiceInfo& GetInfo() const { | ||
| 180 | return info; | ||
| 181 | } | ||
| 182 | |||
| 183 | VoiceInfo& Info() { | ||
| 184 | return info; | ||
| 185 | } | ||
| 186 | |||
| 187 | void SetWaveIndex(size_t index); | ||
| 188 | std::vector<s16> DequeueSamples(size_t sample_count); | ||
| 189 | void UpdateState(); | ||
| 190 | void RefreshBuffer(); | ||
| 191 | |||
| 192 | private: | ||
| 193 | bool is_in_use{}; | ||
| 194 | bool is_refresh_pending{}; | ||
| 195 | size_t wave_index{}; | ||
| 196 | size_t offset{}; | ||
| 197 | Codec::ADPCMState adpcm_state{}; | ||
| 198 | InterpolationState interp_state{}; | ||
| 199 | std::vector<s16> samples; | ||
| 200 | VoiceOutStatus out_status{}; | ||
| 201 | VoiceInfo info{}; | ||
| 202 | }; | ||
| 203 | 176 | ||
| 204 | AudioRendererParameter worker_params; | 177 | AudioRendererParameter worker_params; |
| 205 | Kernel::SharedPtr<Kernel::Event> buffer_event; | 178 | Kernel::SharedPtr<Kernel::Event> buffer_event; |
| 206 | std::vector<VoiceState> voices; | 179 | std::vector<VoiceState> voices; |
| 207 | std::unique_ptr<AudioCore::AudioOut> audio_out; | 180 | std::unique_ptr<AudioOut> audio_out; |
| 208 | AudioCore::StreamPtr stream; | 181 | AudioCore::StreamPtr stream; |
| 209 | }; | 182 | }; |
| 210 | 183 | ||
diff --git a/src/audio_core/codec.cpp b/src/audio_core/codec.cpp index c3021403f..454de798b 100644 --- a/src/audio_core/codec.cpp +++ b/src/audio_core/codec.cpp | |||
| @@ -8,27 +8,27 @@ | |||
| 8 | 8 | ||
| 9 | namespace AudioCore::Codec { | 9 | namespace AudioCore::Codec { |
| 10 | 10 | ||
| 11 | std::vector<s16> DecodeADPCM(const u8* const data, size_t size, const ADPCM_Coeff& coeff, | 11 | std::vector<s16> DecodeADPCM(const u8* const data, std::size_t size, const ADPCM_Coeff& coeff, |
| 12 | ADPCMState& state) { | 12 | ADPCMState& state) { |
| 13 | // GC-ADPCM with scale factor and variable coefficients. | 13 | // GC-ADPCM with scale factor and variable coefficients. |
| 14 | // Frames are 8 bytes long containing 14 samples each. | 14 | // Frames are 8 bytes long containing 14 samples each. |
| 15 | // Samples are 4 bits (one nibble) long. | 15 | // Samples are 4 bits (one nibble) long. |
| 16 | 16 | ||
| 17 | constexpr size_t FRAME_LEN = 8; | 17 | constexpr std::size_t FRAME_LEN = 8; |
| 18 | constexpr size_t SAMPLES_PER_FRAME = 14; | 18 | constexpr std::size_t SAMPLES_PER_FRAME = 14; |
| 19 | constexpr std::array<int, 16> SIGNED_NIBBLES = { | 19 | constexpr std::array<int, 16> SIGNED_NIBBLES = { |
| 20 | {0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1}}; | 20 | {0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1}}; |
| 21 | 21 | ||
| 22 | const size_t sample_count = (size / FRAME_LEN) * SAMPLES_PER_FRAME; | 22 | const std::size_t sample_count = (size / FRAME_LEN) * SAMPLES_PER_FRAME; |
| 23 | const size_t ret_size = | 23 | const std::size_t ret_size = |
| 24 | sample_count % 2 == 0 ? sample_count : sample_count + 1; // Ensure multiple of two. | 24 | sample_count % 2 == 0 ? sample_count : sample_count + 1; // Ensure multiple of two. |
| 25 | std::vector<s16> ret(ret_size); | 25 | std::vector<s16> ret(ret_size); |
| 26 | 26 | ||
| 27 | int yn1 = state.yn1, yn2 = state.yn2; | 27 | int yn1 = state.yn1, yn2 = state.yn2; |
| 28 | 28 | ||
| 29 | const size_t NUM_FRAMES = | 29 | const std::size_t NUM_FRAMES = |
| 30 | (sample_count + (SAMPLES_PER_FRAME - 1)) / SAMPLES_PER_FRAME; // Round up. | 30 | (sample_count + (SAMPLES_PER_FRAME - 1)) / SAMPLES_PER_FRAME; // Round up. |
| 31 | for (size_t framei = 0; framei < NUM_FRAMES; framei++) { | 31 | for (std::size_t framei = 0; framei < NUM_FRAMES; framei++) { |
| 32 | const int frame_header = data[framei * FRAME_LEN]; | 32 | const int frame_header = data[framei * FRAME_LEN]; |
| 33 | const int scale = 1 << (frame_header & 0xF); | 33 | const int scale = 1 << (frame_header & 0xF); |
| 34 | const int idx = (frame_header >> 4) & 0x7; | 34 | const int idx = (frame_header >> 4) & 0x7; |
| @@ -53,9 +53,9 @@ std::vector<s16> DecodeADPCM(const u8* const data, size_t size, const ADPCM_Coef | |||
| 53 | return static_cast<s16>(val); | 53 | return static_cast<s16>(val); |
| 54 | }; | 54 | }; |
| 55 | 55 | ||
| 56 | size_t outputi = framei * SAMPLES_PER_FRAME; | 56 | std::size_t outputi = framei * SAMPLES_PER_FRAME; |
| 57 | size_t datai = framei * FRAME_LEN + 1; | 57 | std::size_t datai = framei * FRAME_LEN + 1; |
| 58 | for (size_t i = 0; i < SAMPLES_PER_FRAME && outputi < sample_count; i += 2) { | 58 | for (std::size_t i = 0; i < SAMPLES_PER_FRAME && outputi < sample_count; i += 2) { |
| 59 | const s16 sample1 = decode_sample(SIGNED_NIBBLES[data[datai] >> 4]); | 59 | const s16 sample1 = decode_sample(SIGNED_NIBBLES[data[datai] >> 4]); |
| 60 | ret[outputi] = sample1; | 60 | ret[outputi] = sample1; |
| 61 | outputi++; | 61 | outputi++; |
diff --git a/src/audio_core/codec.h b/src/audio_core/codec.h index 3f845c42c..ef2ce01a8 100644 --- a/src/audio_core/codec.h +++ b/src/audio_core/codec.h | |||
| @@ -38,7 +38,7 @@ using ADPCM_Coeff = std::array<s16, 16>; | |||
| 38 | * @param state ADPCM state, this is updated with new state | 38 | * @param state ADPCM state, this is updated with new state |
| 39 | * @return Decoded stereo signed PCM16 data, sample_count in length | 39 | * @return Decoded stereo signed PCM16 data, sample_count in length |
| 40 | */ | 40 | */ |
| 41 | std::vector<s16> DecodeADPCM(const u8* const data, size_t size, const ADPCM_Coeff& coeff, | 41 | std::vector<s16> DecodeADPCM(const u8* const data, std::size_t size, const ADPCM_Coeff& coeff, |
| 42 | ADPCMState& state); | 42 | ADPCMState& state); |
| 43 | 43 | ||
| 44 | }; // namespace AudioCore::Codec | 44 | }; // namespace AudioCore::Codec |
diff --git a/src/audio_core/cubeb_sink.cpp b/src/audio_core/cubeb_sink.cpp index 79155a7a0..392039688 100644 --- a/src/audio_core/cubeb_sink.cpp +++ b/src/audio_core/cubeb_sink.cpp | |||
| @@ -63,8 +63,8 @@ public: | |||
| 63 | // Downsample 6 channels to 2 | 63 | // Downsample 6 channels to 2 |
| 64 | std::vector<s16> buf; | 64 | std::vector<s16> buf; |
| 65 | buf.reserve(samples.size() * num_channels / source_num_channels); | 65 | buf.reserve(samples.size() * num_channels / source_num_channels); |
| 66 | for (size_t i = 0; i < samples.size(); i += source_num_channels) { | 66 | for (std::size_t i = 0; i < samples.size(); i += source_num_channels) { |
| 67 | for (size_t ch = 0; ch < num_channels; ch++) { | 67 | for (std::size_t ch = 0; ch < num_channels; ch++) { |
| 68 | buf.push_back(samples[i + ch]); | 68 | buf.push_back(samples[i + ch]); |
| 69 | } | 69 | } |
| 70 | } | 70 | } |
| @@ -75,7 +75,7 @@ public: | |||
| 75 | queue.Push(samples); | 75 | queue.Push(samples); |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | size_t SamplesInQueue(u32 num_channels) const override { | 78 | std::size_t SamplesInQueue(u32 num_channels) const override { |
| 79 | if (!ctx) | 79 | if (!ctx) |
| 80 | return 0; | 80 | return 0; |
| 81 | 81 | ||
| @@ -119,10 +119,10 @@ CubebSink::CubebSink(std::string target_device_name) { | |||
| 119 | LOG_WARNING(Audio_Sink, "Audio output device enumeration not supported"); | 119 | LOG_WARNING(Audio_Sink, "Audio output device enumeration not supported"); |
| 120 | } else { | 120 | } else { |
| 121 | const auto collection_end{collection.device + collection.count}; | 121 | const auto collection_end{collection.device + collection.count}; |
| 122 | const auto device{std::find_if(collection.device, collection_end, | 122 | const auto device{ |
| 123 | [&](const cubeb_device_info& device) { | 123 | std::find_if(collection.device, collection_end, [&](const cubeb_device_info& info) { |
| 124 | return target_device_name == device.friendly_name; | 124 | return target_device_name == info.friendly_name; |
| 125 | })}; | 125 | })}; |
| 126 | if (device != collection_end) { | 126 | if (device != collection_end) { |
| 127 | output_device = device->devid; | 127 | output_device = device->devid; |
| 128 | } | 128 | } |
| @@ -159,15 +159,16 @@ long CubebSinkStream::DataCallback(cubeb_stream* stream, void* user_data, const | |||
| 159 | return {}; | 159 | return {}; |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | const size_t num_channels = impl->GetNumChannels(); | 162 | const std::size_t num_channels = impl->GetNumChannels(); |
| 163 | const size_t samples_to_write = num_channels * num_frames; | 163 | const std::size_t samples_to_write = num_channels * num_frames; |
| 164 | size_t samples_written; | 164 | std::size_t samples_written; |
| 165 | 165 | ||
| 166 | if (Settings::values.enable_audio_stretching) { | 166 | if (Settings::values.enable_audio_stretching) { |
| 167 | const std::vector<s16> in{impl->queue.Pop()}; | 167 | const std::vector<s16> in{impl->queue.Pop()}; |
| 168 | const size_t num_in{in.size() / num_channels}; | 168 | const std::size_t num_in{in.size() / num_channels}; |
| 169 | s16* const out{reinterpret_cast<s16*>(buffer)}; | 169 | s16* const out{reinterpret_cast<s16*>(buffer)}; |
| 170 | const size_t out_frames = impl->time_stretch.Process(in.data(), num_in, out, num_frames); | 170 | const std::size_t out_frames = |
| 171 | impl->time_stretch.Process(in.data(), num_in, out, num_frames); | ||
| 171 | samples_written = out_frames * num_channels; | 172 | samples_written = out_frames * num_channels; |
| 172 | 173 | ||
| 173 | if (impl->should_flush) { | 174 | if (impl->should_flush) { |
| @@ -184,7 +185,7 @@ long CubebSinkStream::DataCallback(cubeb_stream* stream, void* user_data, const | |||
| 184 | } | 185 | } |
| 185 | 186 | ||
| 186 | // Fill the rest of the frames with last_frame | 187 | // Fill the rest of the frames with last_frame |
| 187 | for (size_t i = samples_written; i < samples_to_write; i += num_channels) { | 188 | for (std::size_t i = samples_written; i < samples_to_write; i += num_channels) { |
| 188 | std::memcpy(buffer + i * sizeof(s16), &impl->last_frame[0], num_channels * sizeof(s16)); | 189 | std::memcpy(buffer + i * sizeof(s16), &impl->last_frame[0], num_channels * sizeof(s16)); |
| 189 | } | 190 | } |
| 190 | 191 | ||
| @@ -197,7 +198,7 @@ std::vector<std::string> ListCubebSinkDevices() { | |||
| 197 | std::vector<std::string> device_list; | 198 | std::vector<std::string> device_list; |
| 198 | cubeb* ctx; | 199 | cubeb* ctx; |
| 199 | 200 | ||
| 200 | if (cubeb_init(&ctx, "Citra Device Enumerator", nullptr) != CUBEB_OK) { | 201 | if (cubeb_init(&ctx, "yuzu Device Enumerator", nullptr) != CUBEB_OK) { |
| 201 | LOG_CRITICAL(Audio_Sink, "cubeb_init failed"); | 202 | LOG_CRITICAL(Audio_Sink, "cubeb_init failed"); |
| 202 | return {}; | 203 | return {}; |
| 203 | } | 204 | } |
| @@ -206,7 +207,7 @@ std::vector<std::string> ListCubebSinkDevices() { | |||
| 206 | if (cubeb_enumerate_devices(ctx, CUBEB_DEVICE_TYPE_OUTPUT, &collection) != CUBEB_OK) { | 207 | if (cubeb_enumerate_devices(ctx, CUBEB_DEVICE_TYPE_OUTPUT, &collection) != CUBEB_OK) { |
| 207 | LOG_WARNING(Audio_Sink, "Audio output device enumeration not supported"); | 208 | LOG_WARNING(Audio_Sink, "Audio output device enumeration not supported"); |
| 208 | } else { | 209 | } else { |
| 209 | for (size_t i = 0; i < collection.count; i++) { | 210 | for (std::size_t i = 0; i < collection.count; i++) { |
| 210 | const cubeb_device_info& device = collection.device[i]; | 211 | const cubeb_device_info& device = collection.device[i]; |
| 211 | if (device.friendly_name) { | 212 | if (device.friendly_name) { |
| 212 | device_list.emplace_back(device.friendly_name); | 213 | device_list.emplace_back(device.friendly_name); |
diff --git a/src/audio_core/null_sink.h b/src/audio_core/null_sink.h index 2ed0c83b6..a78d78893 100644 --- a/src/audio_core/null_sink.h +++ b/src/audio_core/null_sink.h | |||
| @@ -22,7 +22,7 @@ private: | |||
| 22 | struct NullSinkStreamImpl final : SinkStream { | 22 | struct NullSinkStreamImpl final : SinkStream { |
| 23 | void EnqueueSamples(u32 /*num_channels*/, const std::vector<s16>& /*samples*/) override {} | 23 | void EnqueueSamples(u32 /*num_channels*/, const std::vector<s16>& /*samples*/) override {} |
| 24 | 24 | ||
| 25 | size_t SamplesInQueue(u32 /*num_channels*/) const override { | 25 | std::size_t SamplesInQueue(u32 /*num_channels*/) const override { |
| 26 | return 0; | 26 | return 0; |
| 27 | } | 27 | } |
| 28 | 28 | ||
diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp index 84dcdd98d..449db2416 100644 --- a/src/audio_core/stream.cpp +++ b/src/audio_core/stream.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | #include "audio_core/sink.h" | 8 | #include "audio_core/sink.h" |
| 9 | #include "audio_core/sink_details.h" | 9 | #include "audio_core/sink_details.h" |
| 10 | #include "audio_core/sink_stream.h" | ||
| 10 | #include "audio_core/stream.h" | 11 | #include "audio_core/stream.h" |
| 11 | #include "common/assert.h" | 12 | #include "common/assert.h" |
| 12 | #include "common/logging/log.h" | 13 | #include "common/logging/log.h" |
| @@ -17,7 +18,7 @@ | |||
| 17 | 18 | ||
| 18 | namespace AudioCore { | 19 | namespace AudioCore { |
| 19 | 20 | ||
| 20 | constexpr size_t MaxAudioBufferCount{32}; | 21 | constexpr std::size_t MaxAudioBufferCount{32}; |
| 21 | 22 | ||
| 22 | u32 Stream::GetNumChannels() const { | 23 | u32 Stream::GetNumChannels() const { |
| 23 | switch (format) { | 24 | switch (format) { |
| @@ -52,7 +53,7 @@ void Stream::Stop() { | |||
| 52 | } | 53 | } |
| 53 | 54 | ||
| 54 | s64 Stream::GetBufferReleaseCycles(const Buffer& buffer) const { | 55 | s64 Stream::GetBufferReleaseCycles(const Buffer& buffer) const { |
| 55 | const size_t num_samples{buffer.GetSamples().size() / GetNumChannels()}; | 56 | const std::size_t num_samples{buffer.GetSamples().size() / GetNumChannels()}; |
| 56 | return CoreTiming::usToCycles((static_cast<u64>(num_samples) * 1000000) / sample_rate); | 57 | return CoreTiming::usToCycles((static_cast<u64>(num_samples) * 1000000) / sample_rate); |
| 57 | } | 58 | } |
| 58 | 59 | ||
| @@ -122,9 +123,9 @@ bool Stream::ContainsBuffer(Buffer::Tag tag) const { | |||
| 122 | return {}; | 123 | return {}; |
| 123 | } | 124 | } |
| 124 | 125 | ||
| 125 | std::vector<Buffer::Tag> Stream::GetTagsAndReleaseBuffers(size_t max_count) { | 126 | std::vector<Buffer::Tag> Stream::GetTagsAndReleaseBuffers(std::size_t max_count) { |
| 126 | std::vector<Buffer::Tag> tags; | 127 | std::vector<Buffer::Tag> tags; |
| 127 | for (size_t count = 0; count < max_count && !released_buffers.empty(); ++count) { | 128 | for (std::size_t count = 0; count < max_count && !released_buffers.empty(); ++count) { |
| 128 | tags.push_back(released_buffers.front()->GetTag()); | 129 | tags.push_back(released_buffers.front()->GetTag()); |
| 129 | released_buffers.pop(); | 130 | released_buffers.pop(); |
| 130 | } | 131 | } |
diff --git a/src/audio_core/stream.h b/src/audio_core/stream.h index 049b92ca9..27db1112f 100644 --- a/src/audio_core/stream.h +++ b/src/audio_core/stream.h | |||
| @@ -11,13 +11,16 @@ | |||
| 11 | #include <queue> | 11 | #include <queue> |
| 12 | 12 | ||
| 13 | #include "audio_core/buffer.h" | 13 | #include "audio_core/buffer.h" |
| 14 | #include "audio_core/sink_stream.h" | ||
| 15 | #include "common/assert.h" | ||
| 16 | #include "common/common_types.h" | 14 | #include "common/common_types.h" |
| 17 | #include "core/core_timing.h" | 15 | |
| 16 | namespace CoreTiming { | ||
| 17 | struct EventType; | ||
| 18 | } | ||
| 18 | 19 | ||
| 19 | namespace AudioCore { | 20 | namespace AudioCore { |
| 20 | 21 | ||
| 22 | class SinkStream; | ||
| 23 | |||
| 21 | /** | 24 | /** |
| 22 | * Represents an audio stream, which is a sequence of queued buffers, to be outputed by AudioOut | 25 | * Represents an audio stream, which is a sequence of queued buffers, to be outputed by AudioOut |
| 23 | */ | 26 | */ |
| @@ -49,7 +52,7 @@ public: | |||
| 49 | bool ContainsBuffer(Buffer::Tag tag) const; | 52 | bool ContainsBuffer(Buffer::Tag tag) const; |
| 50 | 53 | ||
| 51 | /// Returns a vector of recently released buffers specified by tag | 54 | /// Returns a vector of recently released buffers specified by tag |
| 52 | std::vector<Buffer::Tag> GetTagsAndReleaseBuffers(size_t max_count); | 55 | std::vector<Buffer::Tag> GetTagsAndReleaseBuffers(std::size_t max_count); |
| 53 | 56 | ||
| 54 | /// Returns true if the stream is currently playing | 57 | /// Returns true if the stream is currently playing |
| 55 | bool IsPlaying() const { | 58 | bool IsPlaying() const { |
| @@ -57,7 +60,7 @@ public: | |||
| 57 | } | 60 | } |
| 58 | 61 | ||
| 59 | /// Returns the number of queued buffers | 62 | /// Returns the number of queued buffers |
| 60 | size_t GetQueueSize() const { | 63 | std::size_t GetQueueSize() const { |
| 61 | return queued_buffers.size(); | 64 | return queued_buffers.size(); |
| 62 | } | 65 | } |
| 63 | 66 | ||
diff --git a/src/audio_core/time_stretch.cpp b/src/audio_core/time_stretch.cpp index da094c46b..fc14151da 100644 --- a/src/audio_core/time_stretch.cpp +++ b/src/audio_core/time_stretch.cpp | |||
| @@ -26,7 +26,8 @@ void TimeStretcher::Flush() { | |||
| 26 | m_sound_touch.flush(); | 26 | m_sound_touch.flush(); |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | size_t TimeStretcher::Process(const s16* in, size_t num_in, s16* out, size_t num_out) { | 29 | std::size_t TimeStretcher::Process(const s16* in, std::size_t num_in, s16* out, |
| 30 | std::size_t num_out) { | ||
| 30 | const double time_delta = static_cast<double>(num_out) / m_sample_rate; // seconds | 31 | const double time_delta = static_cast<double>(num_out) / m_sample_rate; // seconds |
| 31 | 32 | ||
| 32 | // We were given actual_samples number of samples, and num_samples were requested from us. | 33 | // We were given actual_samples number of samples, and num_samples were requested from us. |
| @@ -61,8 +62,8 @@ size_t TimeStretcher::Process(const s16* in, size_t num_in, s16* out, size_t num | |||
| 61 | LOG_DEBUG(Audio, "{:5}/{:5} ratio:{:0.6f} backlog:{:0.6f}", num_in, num_out, m_stretch_ratio, | 62 | LOG_DEBUG(Audio, "{:5}/{:5} ratio:{:0.6f} backlog:{:0.6f}", num_in, num_out, m_stretch_ratio, |
| 62 | backlog_fullness); | 63 | backlog_fullness); |
| 63 | 64 | ||
| 64 | m_sound_touch.putSamples(in, num_in); | 65 | m_sound_touch.putSamples(in, static_cast<u32>(num_in)); |
| 65 | return m_sound_touch.receiveSamples(out, num_out); | 66 | return m_sound_touch.receiveSamples(out, static_cast<u32>(num_out)); |
| 66 | } | 67 | } |
| 67 | 68 | ||
| 68 | } // namespace AudioCore | 69 | } // namespace AudioCore |
diff --git a/src/audio_core/time_stretch.h b/src/audio_core/time_stretch.h index 7e39e695e..decd760f1 100644 --- a/src/audio_core/time_stretch.h +++ b/src/audio_core/time_stretch.h | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | ||
| 8 | #include <cstddef> | 7 | #include <cstddef> |
| 9 | #include <SoundTouch.h> | 8 | #include <SoundTouch.h> |
| 10 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| @@ -20,7 +19,7 @@ public: | |||
| 20 | /// @param out Output sample buffer | 19 | /// @param out Output sample buffer |
| 21 | /// @param num_out Desired number of output frames in `out` | 20 | /// @param num_out Desired number of output frames in `out` |
| 22 | /// @returns Actual number of frames written to `out` | 21 | /// @returns Actual number of frames written to `out` |
| 23 | size_t Process(const s16* in, size_t num_in, s16* out, size_t num_out); | 22 | std::size_t Process(const s16* in, std::size_t num_in, s16* out, std::size_t num_out); |
| 24 | 23 | ||
| 25 | void Clear(); | 24 | void Clear(); |
| 26 | 25 | ||