From 6879ae2ab05831faaa04cd2299ca3347ba4d085d Mon Sep 17 00:00:00 2001 From: brummer10 Date: Sat, 3 Aug 2024 18:23:21 +0200 Subject: [PATCH] Fix issue #17 Loading IR seems to create DC issues --- Ratatouille/ParallelThread.h | 4 +- Ratatouille/Ratatouille.cpp | 24 +++++--- Ratatouille/fftconvolver.cc | 105 +++++++++++++++++++++++++++++++++++ Ratatouille/fftconvolver.h | 48 +++++++++++++++- 4 files changed, 171 insertions(+), 10 deletions(-) diff --git a/Ratatouille/ParallelThread.h b/Ratatouille/ParallelThread.h index a510b57..5b7f0c1 100644 --- a/Ratatouille/ParallelThread.h +++ b/Ratatouille/ParallelThread.h @@ -145,7 +145,7 @@ class ParallelThread while (!getState()) { pthread_mutex_lock(&pWaitProc); if (pthread_cond_timedwait(&pProcCond, &pWaitProc, getTimeOut()) == ETIMEDOUT) { - pthread_mutex_unlock(&pWaitProc);; + pthread_mutex_unlock(&pWaitProc); maxDuration +=1; //fprintf(stderr, "%s wait for process %i\n", threadName.c_str(), maxDuration); if (maxDuration > 2) { @@ -179,7 +179,7 @@ class ParallelThread while (pWait.load(std::memory_order_acquire)) { pthread_mutex_lock(&pWaitProc); if (pthread_cond_timedwait(&pProcCond, &pWaitProc, getTimeOut()) == ETIMEDOUT) { - pthread_mutex_unlock(&pWaitProc);; + pthread_mutex_unlock(&pWaitProc); maxDuration +=1; //fprintf(stderr, "%s wait for data %i\n", threadName.c_str(), maxDuration); if (maxDuration > 5) { diff --git a/Ratatouille/Ratatouille.cpp b/Ratatouille/Ratatouille.cpp index 5623749..5605f8f 100644 --- a/Ratatouille/Ratatouille.cpp +++ b/Ratatouille/Ratatouille.cpp @@ -107,8 +107,8 @@ class Xratatouille cdeleay::Dsp* cdelay; ModelerSelector slotA; ModelerSelector slotB; - DoubleThreadConvolver conv; - DoubleThreadConvolver conv1; + SingleThreadConvolver conv; + SingleThreadConvolver conv1; ParallelThread xrworker; ParallelThread pro; DenormalProtection MXCSR; @@ -237,8 +237,8 @@ Xratatouille::Xratatouille() : cdelay(cdeleay::plugin()), slotA(&Sync), slotB(&Sync), - conv(DoubleThreadConvolver()), - conv1(DoubleThreadConvolver()), + conv(SingleThreadConvolver()), + conv1(SingleThreadConvolver()), rt_prio(0), rt_policy(0), input0(NULL), @@ -300,7 +300,6 @@ void Xratatouille::init_dsp_(uint32_t rate) if (!rt_policy) rt_policy = 1; //SCHED_FIFO; pro.setThreadName("RT"); pro.setPriority(rt_prio, rt_policy); - pro.process.set<&Xratatouille::processSlotB>(*this); model_file = "None"; model_file1 = "None"; @@ -693,6 +692,7 @@ void Xratatouille::run_dsp_(uint32_t n_samples) // process slot B in parallel _bufb = bufb; if (_neuralB.load(std::memory_order_acquire) && pro.getProcess()) { + pro.process.set<&Xratatouille::processSlotB>(*this); pro.runProcess(); } else { processSlotB(); @@ -739,13 +739,23 @@ void Xratatouille::run_dsp_(uint32_t n_samples) memcpy(bufa, output0, n_samples*sizeof(float)); memcpy(bufb, output0, n_samples*sizeof(float)); + // process conv1 in parallel + _bufb = bufb; + if (!_execute.load(std::memory_order_acquire) && conv1.is_runnable()) { + if (pro.getProcess()) { + pro.process.set<&Xratatouille::processConv1>(*this); + pro.runProcess(); + } else { + processConv1(); + } + } // process conv if (!_execute.load(std::memory_order_acquire) && conv.is_runnable()) conv.compute(n_samples, bufa, bufa); - // process conv1 + // wait for parallel processed conv1 when needed if (!_execute.load(std::memory_order_acquire) && conv1.is_runnable()) - conv1.compute(n_samples, bufb, bufb); + pro.processWait(); // mix output when needed if ((!_execute.load(std::memory_order_acquire) && conv.is_runnable()) && conv1.is_runnable()) { diff --git a/Ratatouille/fftconvolver.cc b/Ratatouille/fftconvolver.cc index 8495d9d..054f9ca 100644 --- a/Ratatouille/fftconvolver.cc +++ b/Ratatouille/fftconvolver.cc @@ -236,3 +236,108 @@ void DoubleThreadConvolver::compute(int32_t count, float* input, float* output) { if (ready) process(input, output, count); } + +/**************************************************************** + ** SingleThreadConvolver + */ + +bool SingleThreadConvolver::get_buffer(std::string fname, float **buffer, uint32_t *rate, int *asize) +{ + Audiofile audio; + if (audio.open_read(fname)) { + fprintf(stderr, "Unable to open %s\n", fname.c_str() ); + *buffer = 0; + return false; + } + *rate = audio.rate(); + *asize = audio.size(); + const int limit = 2000000; // arbitrary size limit + if (*asize > limit) { + fprintf(stderr, "too many samples (%i), truncated to %i\n" + , audio.size(), limit); + *asize = limit; + } + if (*asize * audio.chan() == 0) { + fprintf(stderr, "No samples found\n"); + *buffer = 0; + audio.close(); + return false; + } + float* cbuffer = new float[*asize * audio.chan()]; + if (audio.read(cbuffer, *asize) != static_cast(*asize)) { + delete[] cbuffer; + fprintf(stderr, "Error reading file\n"); + *buffer = 0; + audio.close(); + return false; + } + if (audio.chan() > 1) { + //fprintf(stderr,"only taking first channel of %i channels in impulse response\n", audio.chan()); + float *abuffer = new float[*asize]; + for (int i = 0; i < *asize; i++) { + abuffer[i] = cbuffer[i * audio.chan()]; + } + delete[] cbuffer; + cbuffer = NULL; + cbuffer = abuffer; + } + *buffer = cbuffer; + audio.close(); + if (*rate != samplerate) { + *buffer = resamp.process(*rate, *asize, *buffer, samplerate, asize); + if (!*buffer) { + printf("no buffer\n"); + return false; + } + //fprintf(stderr, "FFTConvolver: resampled from %i to %i\n", *rate, samplerate); + } + return true; +} + +void SingleThreadConvolver::normalize(float* buffer, int asize) { + if (!norm) return; + double gain = 0.0; + // get gain factor from file buffer + for (int i = 0; i < asize; i++) { + double v = buffer[i] ; + gain += v*v; + } + // apply gain factor when needed + if (gain != 0.0) { + gain = 1.0 / gain; + + for (int i = 0; i < asize; i++) { + buffer[i] *= gain; + } + } +} + +void SingleThreadConvolver::set_normalisation(uint32_t norm_) { + norm = norm_; +} + +bool SingleThreadConvolver::configure(std::string fname, float gain, unsigned int delay, unsigned int offset, + unsigned int length, unsigned int size, unsigned int bufsize) +{ + filename = fname; + float* abuf = NULL; + uint32_t arate = 0; + int asize = 0; + if (!get_buffer(fname, &abuf, &arate, &asize)) { + return false; + } + normalize(abuf, asize); + + if (init(1024, abuf, asize)) { + ready = true; + delete[] abuf; + return true; + } + delete[] abuf; + return false; +} + +void SingleThreadConvolver::compute(int32_t count, float* input, float* output) +{ + if (ready) process(input, output, count); +} diff --git a/Ratatouille/fftconvolver.h b/Ratatouille/fftconvolver.h index ef26399..a7ec237 100644 --- a/Ratatouille/fftconvolver.h +++ b/Ratatouille/fftconvolver.h @@ -144,7 +144,53 @@ class DoubleThreadConvolver: public fftconvolver::TwoStageFFTConvolver std::string filename; ParallelThread pro; std::atomic setWait; - std::chrono::microseconds timeoutPeriod; + bool get_buffer(std::string fname, float **buffer, uint32_t* rate, int* size); + void normalize(float* buffer, int asize); +}; + +class SingleThreadConvolver: public fftconvolver::FFTConvolver +{ +public: + bool start(int32_t policy, int32_t priority) { + return ready;} + + void set_normalisation(uint32_t norm); + + bool configure(std::string fname, float gain, unsigned int delay, unsigned int offset, + unsigned int length, unsigned int size, unsigned int bufsize); + + void compute(int32_t count, float* input, float *output); + + bool checkstate() { return true;} + + inline void set_not_runnable() { ready = false;} + + inline bool is_runnable() { return ready;} + + inline void set_buffersize(uint32_t sz) { buffersize = sz;} + + inline void set_samplerate(uint32_t sr) { samplerate = sr;} + + int stop_process() { + ready = false; + return 0;} + + int cleanup () { + reset(); + return 0;} + + SingleThreadConvolver() + : resamp(), ready(false), samplerate(0) { norm = 0;} + + ~SingleThreadConvolver() { reset();} + +private: + gx_resample::BufferResampler resamp; + volatile bool ready; + uint32_t buffersize; + uint32_t samplerate; + uint32_t norm; + std::string filename; bool get_buffer(std::string fname, float **buffer, uint32_t* rate, int* size); void normalize(float* buffer, int asize); };