From 400959b536180cf8912f06dd80b4de077d8f8c74 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Mon, 6 Aug 2018 20:20:08 +0200 Subject: New resampler implementation. --- src/drumgizmo.cc | 124 ++++++++++++++++++++++++++++----------------------- src/drumgizmo.h | 16 ++++--- src/drumkit.cc | 4 +- src/drumkit.h | 4 +- src/drumkitloader.cc | 7 --- src/drumkitloader.h | 3 +- 6 files changed, 83 insertions(+), 75 deletions(-) diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index 5a201af..e7ebe5a 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -43,7 +43,7 @@ DrumGizmo::DrumGizmo(Settings& settings, AudioOutputEngine& o, AudioInputEngine& i) - : loader(settings, kit, i, resamplers, rand, audio_cache) + : loader(settings, kit, i, rand, audio_cache) , oe(o) , ie(i) , audio_cache(settings) @@ -54,6 +54,7 @@ DrumGizmo::DrumGizmo(Settings& settings, audio_cache.init(10000); // start thread events.reserve(1000); loader.init(); + setSamplerate(44100.0f); } DrumGizmo::~DrumGizmo() @@ -81,12 +82,6 @@ void DrumGizmo::setFrameSize(size_t framesize) { settings.buffer_size.store(framesize); - // If we are resampling override the frame size. - if(resamplers.isActive() && enable_resampling) - { - framesize = RESAMPLER_INPUT_BUFFER; - } - if(this->framesize != framesize) { DEBUG(drumgizmo, "New framesize: %d\n", (int)framesize); @@ -119,6 +114,12 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples) enable_resampling = settings_getter.enable_resampling.getValue(); } + if(settings_getter.drumkit_samplerate.hasChanged()) + { + settings_getter.drumkit_samplerate.getValue(); // stage new value + setSamplerate(settings.samplerate.load()); + } + setFrameSize(nsamples); setFreeWheel(ie.isFreewheeling() && oe.isFreewheeling()); @@ -132,7 +133,7 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples) ie.run(pos, nsamples, events); - double resample_ratio = resamplers.getRatio(); + double resample_ratio = ratio; if(enable_resampling == false) { resample_ratio = 1.0; @@ -150,10 +151,10 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples) // // Write audio // -#ifdef WITH_RESAMPLER - if(!enable_resampling || !resamplers.isActive()) // No resampling needed + if(!enable_resampling || ratio == 1.0) { -#endif + // No resampling needed + for(size_t c = 0; c < kit.channels.size(); ++c) { sample_t *buf = samples; @@ -176,55 +177,46 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples) } } } -#ifdef WITH_RESAMPLER } else { // Resampling needed - - // - // NOTE: Channels must be processed one buffer at a time on all channels in - // parallel - NOT all buffers on one channel and then all buffer on the next - // one since this would mess up the event queue (it would jump back and - // forth in time) - // - - // Prepare output buffer + size_t kitpos = pos * ratio; for(size_t c = 0; c < kit.channels.size(); ++c) { - resamplers[c].setOutputSamples(resampler_output_buffer[c], nsamples); - } + sample_t *buf = samples; + bool internal = false; + if(oe.getBuffer(c)) + { + buf = oe.getBuffer(c); + internal = true; + } - // Process channel data - size_t kitpos = pos * resamplers.getRatio(); - size_t insize = sizeof(resampler_input_buffer[0]) / sizeof(sample_t); + zita[c].out_data = buf; + zita[c].out_count = nsamples; - while(resamplers.getOutputSampleCount() > 0) - { - for(size_t c = 0; c < kit.channels.size(); ++c) + if(zita[c].inp_count > 0) { - if(resamplers[c].getInputSampleCount() == 0) - { - sample_t *sin = resampler_input_buffer[c]; - memset(resampler_input_buffer[c], 0, - sizeof(resampler_input_buffer[c])); - getSamples(c, kitpos, sin, insize); - - resamplers[c].setInputSamples(sin, insize); - } - resamplers[c].process(); + // Samples left from last iteration, process that one first + zita[c].process(); } - kitpos += insize; - } - // Write output data to output engine. - for(size_t c = 0; c < kit.channels.size(); ++c) - { - oe.run(c, resampler_output_buffer[c], nsamples); - } + std::memset(_resampler_input_buffer[c], 0, + sizeof(_resampler_input_buffer[c])); + + zita[c].inp_data = _resampler_input_buffer[c]; + std::size_t sample_count = + std::ceil((nsamples - (nsamples - zita[c].out_count)) * ratio); + getSamples(c, kitpos, zita[c].inp_data, sample_count); + zita[c].inp_count = sample_count; + zita[c].process(); + if(!internal) + { + oe.run(c, samples, nsamples); + } + } } -#endif/*WITH_RESAMPLER*/ ie.post(); oe.post(nsamples); @@ -395,28 +387,50 @@ void DrumGizmo::stop() std::size_t DrumGizmo::getLatency() const { auto latency = input_processor.getLatency(); - if(enable_resampling) + if(enable_resampling && ratio != 0.0) { - latency += resamplers.getLatency(); + // TODO: + latency += zita[0].inpsize(); // resampler latency } return latency; } -int DrumGizmo::samplerate() +float DrumGizmo::samplerate() { return settings.samplerate.load(); } -void DrumGizmo::setSamplerate(int samplerate) +void DrumGizmo::setSamplerate(float samplerate) { - DEBUG(dgeditor, "%s samplerate: %d\n", __PRETTY_FUNCTION__, samplerate); + DEBUG(dgeditor, "%s samplerate: %f\n", __PRETTY_FUNCTION__, samplerate); settings.samplerate.store(samplerate); // Notify input engine of the samplerate change. ie.setSampleRate(samplerate); -#ifdef WITH_RESAMPLER - resamplers.setup(kit.getSamplerate(), settings.samplerate.load()); -#endif/*WITH_RESAMPLER*/ + auto input_fs = kit.getSamplerate(); + auto output_fs = samplerate; + ratio = input_fs / output_fs; + settings.resamplig_recommended.store(ratio != 1.0); + + for(int c = 0; c < MAX_NUM_CHANNELS; ++c) + { + zita[c].reset(); + auto nchan = 1u; // mono + auto hlen = 72u; // 16 ≤ hlen ≤ 96 + zita[c].setup(input_fs, output_fs, nchan, hlen); + + // Prefill + auto null_size = zita[c].inpsize() - 1;// / 2 - 1; + zita[c].inp_data = nullptr; + zita[c].inp_count = null_size; + + constexpr auto sz = 4096 * 16; + sample_t s[sz]; + zita[c].out_data = s; + zita[c].out_count = sz; + + zita[c].process(); + } } diff --git a/src/drumgizmo.h b/src/drumgizmo.h index 0f2c20e..2f74062 100644 --- a/src/drumgizmo.h +++ b/src/drumgizmo.h @@ -30,6 +30,8 @@ #include #include +#include + #include "audiooutputengine.h" #include "audioinputengine.h" #include "events.h" @@ -37,7 +39,6 @@ #include "drumkit.h" #include "drumkitloader.h" #include "audiocache.h" -#include "chresampler.h" #include "settings.h" #include "inputprocessor.h" @@ -62,8 +63,8 @@ public: //! Get the current engine latency in samples. std::size_t getLatency() const; - int samplerate(); - void setSamplerate(int samplerate); + float samplerate(); + void setSamplerate(float samplerate); void setFrameSize(size_t framesize); @@ -74,7 +75,7 @@ public: private: static constexpr int MAX_NUM_CHANNELS = 64; static constexpr int RESAMPLER_OUTPUT_BUFFER = 4096; - static constexpr int RESAMPLER_INPUT_BUFFER = 64; + static constexpr int RESAMPLER_INPUT_BUFFER = 2048;//64; protected: DrumKitLoader loader; @@ -84,9 +85,6 @@ protected: std::list< Event* > activeevents[MAX_NUM_CHANNELS]; - Resamplers resamplers; - sample_t resampler_output_buffer[MAX_NUM_CHANNELS][RESAMPLER_OUTPUT_BUFFER]; - sample_t resampler_input_buffer[MAX_NUM_CHANNELS][RESAMPLER_INPUT_BUFFER]; bool enable_resampling{true}; std::map audiofiles; @@ -103,4 +101,8 @@ protected: SettingsGetter settings_getter; Random rand; + Resampler zita[MAX_NUM_CHANNELS]; + sample_t _resampler_input_buffer[MAX_NUM_CHANNELS][4096 * 8]; + double ratio = 1.0; + }; diff --git a/src/drumkit.cc b/src/drumkit.cc index e557de1..61fabf6 100644 --- a/src/drumkit.cc +++ b/src/drumkit.cc @@ -45,7 +45,7 @@ void DrumKit::clear() _name = ""; _description = ""; - _samplerate = 44100; + _samplerate = 44100.0f; } bool DrumKit::isValid() const @@ -73,7 +73,7 @@ VersionStr DrumKit::getVersion() const return _version; } -std::size_t DrumKit::getSamplerate() const +float DrumKit::getSamplerate() const { return _samplerate; } diff --git a/src/drumkit.h b/src/drumkit.h index 0ea5e26..ae3a49b 100644 --- a/src/drumkit.h +++ b/src/drumkit.h @@ -53,7 +53,7 @@ public: bool isValid() const; - std::size_t getSamplerate() const; + float getSamplerate() const; //! Get the number of audio files (as in single channel) in this drumkit. std::size_t getNumberOfFiles() const; @@ -67,7 +67,7 @@ private: std::string _name; std::string _description; - std::size_t _samplerate{0}; + float _samplerate{44100.0f}; VersionStr _version; }; diff --git a/src/drumkitloader.cc b/src/drumkitloader.cc index e6f4c45..246e79b 100644 --- a/src/drumkitloader.cc +++ b/src/drumkitloader.cc @@ -36,14 +36,12 @@ DrumKitLoader::DrumKitLoader(Settings& settings, DrumKit& kit, AudioInputEngine& ie, - Resamplers& resamplers, Random& rand, AudioCache& audio_cache) : settings(settings) , getter(settings) , kit(kit) , ie(ie) - , resamplers(resamplers) , rand(rand) , audio_cache(audio_cache) { @@ -136,11 +134,6 @@ bool DrumKitLoader::loadkit(const std::string& file) loadKit(&kit); -#ifdef WITH_RESAMPLER - resamplers.setup(kit.getSamplerate(), settings.samplerate.load()); -#endif/*WITH_RESAMPLER*/ - settings.resamplig_recommended.store(resamplers.isActive()); - DEBUG(loadkit, "loadkit: Success\n"); return true; diff --git a/src/drumkitloader.h b/src/drumkitloader.h index 82ab4b5..2758a98 100644 --- a/src/drumkitloader.h +++ b/src/drumkitloader.h @@ -50,7 +50,7 @@ class DrumKitLoader { public: DrumKitLoader(Settings& settings, DrumKit& kit, AudioInputEngine& ie, - Resamplers& resamplers, Random& rand, AudioCache& audio_cache); + Random& rand, AudioCache& audio_cache); ~DrumKitLoader(); @@ -89,7 +89,6 @@ protected: SettingsGetter getter; DrumKit& kit; AudioInputEngine& ie; - Resamplers& resamplers; //MemChecker memchecker; Random& rand; AudioCache& audio_cache; -- cgit v1.2.3