From 6c99f9f2fee0928987fe944c8ed29878064df87a Mon Sep 17 00:00:00 2001 From: jacqueline Date: Tue, 8 Aug 2023 11:36:10 +1000 Subject: [PATCH] Fix resampler issue, do a little performance tuning --- src/audio/fatfs_audio_input.cpp | 9 ++++++--- src/audio/i2s_audio_output.cpp | 12 ++---------- src/audio/resample.cpp | 33 +++++++++++++++++++++++++-------- src/audio/sink_mixer.cpp | 2 +- 4 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/audio/fatfs_audio_input.cpp b/src/audio/fatfs_audio_input.cpp index 0c3ef20d..73586f09 100644 --- a/src/audio/fatfs_audio_input.cpp +++ b/src/audio/fatfs_audio_input.cpp @@ -30,6 +30,7 @@ #include "freertos/portmacro.h" #include "freertos/projdefs.h" #include "future_fetcher.hpp" +#include "idf_additions.h" #include "span.hpp" #include "stream_info.hpp" #include "tag_parser.hpp" @@ -40,8 +41,8 @@ static const char* kTag = "SRC"; namespace audio { -static constexpr UINT kFileBufferSize = 4096 * 2; -static constexpr UINT kStreamerBufferSize = 4096; +static constexpr UINT kFileBufferSize = 8 * 1024; +static constexpr UINT kStreamerBufferSize = 64 * 1024; static StreamBufferHandle_t sForwardDest = nullptr; @@ -143,7 +144,9 @@ FatfsAudioInput::FatfsAudioInput( : IAudioSource(), tag_parser_(tag_parser), has_data_(xSemaphoreCreateBinary()), - streamer_buffer_(xStreamBufferCreate(kStreamerBufferSize, 1)), + streamer_buffer_(xStreamBufferCreateWithCaps(kStreamerBufferSize, + 1, + MALLOC_CAP_SPIRAM)), streamer_(new FileStreamer(streamer_buffer_, has_data_)), input_buffer_(new RawStream(kFileBufferSize)), source_mutex_(), diff --git a/src/audio/i2s_audio_output.cpp b/src/audio/i2s_audio_output.cpp index e8aa8975..e53dbe2a 100644 --- a/src/audio/i2s_audio_output.cpp +++ b/src/audio/i2s_audio_output.cpp @@ -117,18 +117,10 @@ auto I2SAudioOutput::AdjustVolumeDown() -> bool { auto I2SAudioOutput::PrepareFormat(const StreamInfo::Pcm& orig) -> StreamInfo::Pcm { - /* -return StreamInfo::Pcm{ - .channels = std::min(orig.channels, 2), - .bits_per_sample = std::clamp(orig.bits_per_sample, 16, 32), - .sample_rate = std::clamp(orig.sample_rate, 8000, 96000), -}; - */ return StreamInfo::Pcm{ .channels = std::min(orig.channels, 2), - .bits_per_sample = 16, - //.sample_rate = std::clamp(orig.sample_rate, 8000, 96000), - .sample_rate = 44100, + .bits_per_sample = std::clamp(orig.bits_per_sample, 16, 32), + .sample_rate = std::clamp(orig.sample_rate, 8000, 96000), }; } diff --git a/src/audio/resample.cpp b/src/audio/resample.cpp index aa4c8f2a..7accd0a1 100644 --- a/src/audio/resample.cpp +++ b/src/audio/resample.cpp @@ -17,8 +17,8 @@ namespace audio { static constexpr char kTag[] = "resample"; static constexpr double kLowPassRatio = 0.5; -static constexpr size_t kNumFilters = 8; -static constexpr size_t kTapsPerFilter = 8; +static constexpr size_t kNumFilters = 64; +static constexpr size_t kTapsPerFilter = 16; typedef std::array Filter; static std::array sFilters{}; @@ -64,12 +64,15 @@ auto Resampler::Process(cpp::span input, size_t input_frames = input.size() / num_channels_; size_t output_frames = output.size() / num_channels_; - int half_taps = kTapsPerFilter / 2, i; + int half_taps = kTapsPerFilter / 2; while (output_frames > 0) { if (output_offset_ >= input_index_ - half_taps) { if (input_frames > 0) { + // Check whether the channel buffers will overflow with the addition of + // this sample. If so, we need to move the remaining contents back to + // the beginning of the buffer. if (input_index_ == channel_buffer_size_) { - for (i = 0; i < num_channels_; ++i) { + for (int i = 0; i < num_channels_; ++i) { memmove(channel_buffers_[i], channel_buffers_[i] + channel_buffer_size_ - kTapsPerFilter, kTapsPerFilter * sizeof(float)); @@ -79,21 +82,23 @@ auto Resampler::Process(cpp::span input, input_index_ -= channel_buffer_size_ - kTapsPerFilter; } - for (i = 0; i < num_channels_; ++i) { + for (int i = 0; i < num_channels_; ++i) { channel_buffers_[i][input_index_] = sample::ToFloat(input[samples_used++]); } input_index_++; input_frames--; - } else + } else { break; + } } else { - for (i = 0; i < num_channels_; i++) { + for (int i = 0; i < num_channels_; i++) { output[samples_produced++] = sample::FromFloat(Subsample(i)); } output_offset_ += (1.0f / factor_); + output_frames--; } } @@ -160,8 +165,20 @@ auto Resampler::Subsample(int channel) -> float { source = source.subspan(offset_integral); float offset_fractional = output_offset_ - offset_integral; - int filter_index = offset_fractional * kNumFilters; + /* +// no interpolate +size_t filter_index = std::floor(offset_fractional * kNumFilters + 0.5f); +//ESP_LOGI(kTag, "selected filter %u of %u", filter_index, kNumFilters); +int start_offset = kTapsPerFilter / 2 + 1; +//ESP_LOGI(kTag, "using offset of %i, length %u", start_offset, kTapsPerFilter); + +return ApplyFilter( + sFilters[filter_index], + {source.data() - start_offset, kTapsPerFilter}); + */ + offset_fractional *= kNumFilters; + int filter_index = std::floor(offset_fractional); sum1 = ApplyFilter(sFilters[filter_index], {source.data() - kTapsPerFilter / 2 + 1, kTapsPerFilter}); diff --git a/src/audio/sink_mixer.cpp b/src/audio/sink_mixer.cpp index a2bf229b..5a5a8616 100644 --- a/src/audio/sink_mixer.cpp +++ b/src/audio/sink_mixer.cpp @@ -195,7 +195,7 @@ auto SinkMixer::Resample(InputStream& in, OutputStream& out) -> bool { out.data_as(), false); in.consume(res.first * sizeof(sample::Sample)); - out.add(res.first * sizeof(sample::Sample)); + out.add(res.second * sizeof(sample::Sample)); return res.first == 0 && res.second == 0; }