Fix resampler issue, do a little performance tuning

custom
jacqueline 2 years ago
parent 49f82d2f3d
commit 6c99f9f2fe
  1. 9
      src/audio/fatfs_audio_input.cpp
  2. 8
      src/audio/i2s_audio_output.cpp
  3. 33
      src/audio/resample.cpp
  4. 2
      src/audio/sink_mixer.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_(),

@ -117,19 +117,11 @@ auto I2SAudioOutput::AdjustVolumeDown() -> bool {
auto I2SAudioOutput::PrepareFormat(const StreamInfo::Pcm& orig)
-> StreamInfo::Pcm {
/*
return StreamInfo::Pcm{
.channels = std::min<uint8_t>(orig.channels, 2),
.bits_per_sample = std::clamp<uint8_t>(orig.bits_per_sample, 16, 32),
.sample_rate = std::clamp<uint32_t>(orig.sample_rate, 8000, 96000),
};
*/
return StreamInfo::Pcm{
.channels = std::min<uint8_t>(orig.channels, 2),
.bits_per_sample = 16,
//.sample_rate = std::clamp<uint32_t>(orig.sample_rate, 8000, 96000),
.sample_rate = 44100,
};
}
auto I2SAudioOutput::Configure(const StreamInfo::Pcm& pcm) -> void {

@ -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<float, kTapsPerFilter> Filter;
static std::array<Filter, kNumFilters + 1> sFilters{};
@ -64,12 +64,15 @@ auto Resampler::Process(cpp::span<const sample::Sample> 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<const sample::Sample> 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});

@ -195,7 +195,7 @@ auto SinkMixer::Resample(InputStream& in, OutputStream& out) -> bool {
out.data_as<sample::Sample>(), 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;
}

Loading…
Cancel
Save