From b0e2fc1a4724ed153d3ffebb04e67faff50766d5 Mon Sep 17 00:00:00 2001 From: falkTX Date: Mon, 15 Mar 2021 11:09:48 +0000 Subject: [PATCH] eg-sampler: add resampling via libsamplerate --- plugins/eg-sampler.lv2/sampler.c | 36 +++++++++++++++++++++++++++++--- plugins/eg-sampler.lv2/wscript | 1 + 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/plugins/eg-sampler.lv2/sampler.c b/plugins/eg-sampler.lv2/sampler.c index 9675003d..21a28c8d 100644 --- a/plugins/eg-sampler.lv2/sampler.c +++ b/plugins/eg-sampler.lv2/sampler.c @@ -34,6 +34,7 @@ #include "lv2/worker/worker.h" #include +#include #include #include @@ -80,6 +81,7 @@ typedef struct { bool activated; bool gain_changed; bool sample_changed; + int sample_rate; } Sampler; /** @@ -120,7 +122,7 @@ convert_to_mono(float *data, sf_count_t num_input_frames, uint32_t channels) not modified. */ static Sample* -load_sample(LV2_Log_Logger* logger, const char* path) +load_sample(LV2_Log_Logger* logger, const char* path, int sample_rate) { lv2_log_trace(logger, "Loading %s\n", path); @@ -154,6 +156,33 @@ load_sample(LV2_Log_Logger* logger, const char* path) info->channels = 1; } + if (info->samplerate != sample_rate) { + lv2_log_trace(logger, "Converting sample rate..\n"); + + const double src_ratio = (double)sample_rate/(double)info->samplerate; + const int output_size = ceil(info->frames * src_ratio); + float* const output_buffer = malloc(sizeof(float) * output_size); + + SRC_DATA src_data; + src_data.data_in = data; + src_data.data_out = output_buffer; + src_data.input_frames = info->frames; + src_data.output_frames = output_size; + src_data.src_ratio = src_ratio; + + if (src_simple(&src_data, SRC_SINC_BEST_QUALITY, 1) != 0) { + lv2_log_error(logger, "Sample rate conversion failed, eg-sampler will use unconverted sample\n"); + free(output_buffer); + } else { + // set new amount of frames + info->frames = src_data.output_frames_gen; + // swap buffers + free(data); + data = output_buffer; + lv2_log_trace(logger, "Conversion finished\n"); + } + } + // Fill sample struct and return it sample->data = data; sample->path = (char*)malloc(path_len + 1); @@ -204,7 +233,7 @@ work(LV2_Handle instance, } // Load sample. - Sample* sample = load_sample(&self->logger, path); + Sample* sample = load_sample(&self->logger, path, self->sample_rate); if (sample) { // Send new sample to run() to be applied respond(handle, sizeof(Sample*), &sample); @@ -298,6 +327,7 @@ instantiate(const LV2_Descriptor* descriptor, self->gain = 1.0f; self->gain_dB = 0.0f; + self->sample_rate = (int)rate; return (LV2_Handle)self; } @@ -585,7 +615,7 @@ restore(LV2_Handle instance, if (!self->activated || !schedule) { // No scheduling available, load sample immediately lv2_log_trace(&self->logger, "Synchronous restore\n"); - Sample* sample = load_sample(&self->logger, path); + Sample* sample = load_sample(&self->logger, path, self->sample_rate); if (sample) { free_sample(self, self->sample); self->sample = sample; diff --git a/plugins/eg-sampler.lv2/wscript b/plugins/eg-sampler.lv2/wscript index 8c640c10..4d9debc6 100644 --- a/plugins/eg-sampler.lv2/wscript +++ b/plugins/eg-sampler.lv2/wscript @@ -22,6 +22,7 @@ def configure(conf): conf.check_pkg('lv2 >= 1.2.1', uselib_store='LV2') conf.check_pkg('sndfile >= 1.0.0', uselib_store='SNDFILE') + conf.check_pkg('samplerate >= 0.1.0', uselib_store='SAMPLERATE') conf.check_pkg('gtk+-2.0 >= 2.18.0', uselib_store='GTK2', system=True,