From 42953944da1261584d56405128c6eb3c0e9e7da0 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sun, 1 May 2016 21:36:04 +0200 Subject: The last loader thread stuff. --- src/audioinputengine.h | 26 ++++---- src/audioinputenginemidi.cc | 88 ++++++++++++++------------ src/audioinputenginemidi.h | 47 +++++++------- src/chresampler.cc | 9 ++- src/chresampler.h | 4 +- src/drumgizmo.cc | 87 ++------------------------ src/drumgizmo.h | 13 ++-- src/drumkitloader.cc | 147 +++++++++++++++++++++++++++++++------------- src/drumkitloader.h | 25 +++++--- src/midimapper.cc | 14 +++-- src/midimapper.h | 12 +++- 11 files changed, 239 insertions(+), 233 deletions(-) (limited to 'src') diff --git a/src/audioinputengine.h b/src/audioinputengine.h index 1701864..bb7131c 100644 --- a/src/audioinputengine.h +++ b/src/audioinputengine.h @@ -24,8 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_AUDIOINPUTENGINE_H__ -#define __DRUMGIZMO_AUDIOINPUTENGINE_H__ +#pragma once #include #include @@ -34,22 +33,19 @@ #include "instrument.h" -class AudioInputEngine { +class AudioInputEngine +{ public: - virtual ~AudioInputEngine() {} + virtual ~AudioInputEngine() = default; - virtual bool isMidiEngine() const { return false; } + virtual bool init(const Instruments& instruments) = 0; - virtual bool init(const Instruments& instruments) = 0; + virtual void setParm(const std::string& parm, const std::string& value) = 0; - virtual void setParm(const std::string& parm, const std::string& value) = 0; + virtual bool start() = 0; + virtual void stop() = 0; - virtual bool start() = 0; - virtual void stop() = 0; - - virtual void pre() = 0; - virtual void run(size_t pos, size_t len, std::vector& events) = 0; - virtual void post() = 0; + virtual void pre() = 0; + virtual void run(size_t pos, size_t len, std::vector& events) = 0; + virtual void post() = 0; }; - -#endif/*__DRUMGIZMO_AUDIOINPUTENGINE_H__*/ diff --git a/src/audioinputenginemidi.cc b/src/audioinputenginemidi.cc index ea632fe..3ac2a96 100644 --- a/src/audioinputenginemidi.cc +++ b/src/audioinputenginemidi.cc @@ -33,55 +33,65 @@ #include AudioInputEngineMidi::AudioInputEngineMidi() - : refs(REFSFILE) + : refs(REFSFILE) { - is_valid = false; + is_valid = false; } -bool AudioInputEngineMidi::loadMidiMap(const std::string& file, const Instruments& instruments) +bool AudioInputEngineMidi::loadMidiMap(const std::string& file, + const Instruments& instruments) { - std::string f = file; - - if(refs.load()) { - if(file.size() > 1 && file[0] == '@') { - f = refs.getValue(file.substr(1)); - } - } else { - ERR(drumkitparser, "Error reading refs.conf"); - } - - midimap = ""; - is_valid = false; - - DEBUG(mmap, "loadMidiMap(%s, i.size() == %d)\n", f.c_str(), - (int)instruments.size()); - - if(f == "") return false; - - MidiMapParser p; - if(p.parseFile(f)) { - return false; - } - - mmap.clear(); - mmap.midimap = p.midimap; - - for(size_t i = 0; i < instruments.size(); i++) { - mmap.instrmap[instruments[i]->getName()] = i; - } - - midimap = file; - is_valid = true; - - return true; + std::string f = file; + + if(refs.load()) + { + if(file.size() > 1 && file[0] == '@') + { + f = refs.getValue(file.substr(1)); + } + } + else + { + ERR(drumkitparser, "Error reading refs.conf"); + } + + midimap = ""; + is_valid = false; + + DEBUG(mmap, "loadMidiMap(%s, i.size() == %d)\n", f.c_str(), + (int)instruments.size()); + + if(f == "") + { + return false; + } + + MidiMapParser midimap_parser; + if(midimap_parser.parseFile(f)) + { + return false; + } + + instrmap_t instrmap; + for(size_t i = 0; i < instruments.size(); i++) + { + instrmap[instruments[i]->getName()] = i; + } + + mmap.swap(instrmap, midimap_parser.midimap); + + midimap = file; + is_valid = true; + + return true; } std::string AudioInputEngineMidi::getMidimapFile() const { - return midimap; + return midimap; } bool AudioInputEngineMidi::isValid() const { - return is_valid; + return is_valid; } diff --git a/src/audioinputenginemidi.h b/src/audioinputenginemidi.h index b892750..ed01395 100644 --- a/src/audioinputenginemidi.h +++ b/src/audioinputenginemidi.h @@ -24,48 +24,43 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_AUDIOINPUTENGINEMIDI_H__ -#define __DRUMGIZMO_AUDIOINPUTENGINEMIDI_H__ - -#include "audioinputengine.h" +#pragma once #include +#include "audioinputengine.h" #include "midimapper.h" #include "instrument.h" - #include "configfile.h" -class AudioInputEngineMidi : public AudioInputEngine { +class AudioInputEngineMidi + : public AudioInputEngine +{ public: - AudioInputEngineMidi(); - virtual ~AudioInputEngineMidi() {} - - bool isMidiEngine() const { return true; } + AudioInputEngineMidi(); + virtual ~AudioInputEngineMidi() = default; - virtual bool init(const Instruments &instruments) = 0; + virtual bool init(const Instruments &instruments) = 0; - virtual void setParm(const std::string& parm, const std::string& value) = 0; + virtual void setParm(const std::string& parm, const std::string& value) = 0; - virtual bool start() = 0; - virtual void stop() = 0; + virtual bool start() = 0; + virtual void stop() = 0; - virtual void pre() = 0; - virtual void run(size_t pos, size_t len, std::vector& events) = 0; - virtual void post() = 0; + virtual void pre() = 0; + virtual void run(size_t pos, size_t len, std::vector& events) = 0; + virtual void post() = 0; - bool loadMidiMap(const std::string& file, const Instruments& i); + bool loadMidiMap(const std::string& file, const Instruments& i); - std::string getMidimapFile() const; + std::string getMidimapFile() const; - bool isValid() const; + bool isValid() const; protected: - MidiMapper mmap; - std::string midimap; - bool is_valid; + MidiMapper mmap; + std::string midimap; + bool is_valid; - ConfigFile refs; + ConfigFile refs; }; - -#endif/*__DRUMGIZMO_AUDIOINPUTENGINEMIDI_H__*/ diff --git a/src/chresampler.cc b/src/chresampler.cc index 5118d8f..d759d78 100644 --- a/src/chresampler.cc +++ b/src/chresampler.cc @@ -53,9 +53,7 @@ public: }; CHResampler::CHResampler() - : prv{std::make_unique()} - , input_fs{44100} - , output_fs{44100} + : prv{std::make_unique()} { #if defined(SRC) prv->state = nullptr; @@ -64,6 +62,11 @@ CHResampler::CHResampler() void CHResampler::setup(double input_fs, double output_fs) { + if((input_fs == 0.0) || (output_fs == 0.0)) + { + return; + } + int nchan = 1; // always mono this->input_fs = input_fs; diff --git a/src/chresampler.h b/src/chresampler.h index 262e5cb..bbe2521 100644 --- a/src/chresampler.h +++ b/src/chresampler.h @@ -60,7 +60,7 @@ private: class Prv; std::unique_ptr prv; - double input_fs; - double output_fs; + double input_fs{44100}; + double output_fs{44100}; #endif /*WITH_RESAMPLER*/ }; diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index 66d071d..893b536 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -40,6 +40,8 @@ #include #include +#include + #include "drumkitparser.h" #include "audioinputenginemidi.h" #include "configparser.h" @@ -48,7 +50,7 @@ DrumGizmo::DrumGizmo(Settings& settings, AudioOutputEngine *o, AudioInputEngine *i) - : loader(settings) + : loader(settings, kit, *i, resampler) , oe(o) , ie(i) , kit() @@ -67,57 +69,6 @@ DrumGizmo::~DrumGizmo() audioCache.deinit(); // stop thread } -bool DrumGizmo::loadkit(std::string file) -{ - settings.drumkit_load_status.store(LoadStatus::Idle); - - if(file == "") - { - settings.drumkit_load_status.store(LoadStatus::Error); - return false; - } - - DEBUG(drumgizmo, "loadkit(%s)\n", file.c_str()); - - // Remove all queue AudioFiles from loader before we actually delete them. - loader.skip(); - - // Delete all Channels, Instruments, Samples and AudioFiles. - kit.clear(); - - settings.drumkit_load_status.store(LoadStatus::Loading); - - DrumKitParser parser(settings, kit); - if(parser.parseFile(file)) - { - ERR(drumgizmo, "Drumkit parser failed: %s\n", file.c_str()); - settings.drumkit_load_status.store(LoadStatus::Error); - return false; - } - - // TODO: Re-introduce when the code has been moved to the loader thread. - //// Check if there is enough free RAM to load the drumkit. - //if(!memchecker.enoughFreeMemory(kit)) - //{ - // printf("WARNING: " - // "There doesn't seem to be enough RAM available to load the kit.\n" - // "Trying to load it anyway...\n"); - //} - - loader.loadKit(&kit); - -#ifdef WITH_RESAMPLER - for(auto& chresampler: resampler) - { - chresampler.setup(kit.getSamplerate(), settings.samplerate.load()); - } -#endif/*WITH_RESAMPLER*/ - - DEBUG(loadkit, "loadkit: Success\n"); - - return true; -} - bool DrumGizmo::init() { if(!ie->init(kit.instruments)) @@ -194,32 +145,6 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples) { setFrameSize(nsamples); - // TODO: Move this to DrumKitLoader thread. - if(getter.drumkit_file.hasChanged()) - { - loadkit(getter.drumkit_file.getValue()); - } - - // TODO: Move this to DrumKitLoader thread. - if(getter.midimap_file.hasChanged()) - { - auto ie_midi = dynamic_cast(ie); - if(ie_midi) - { - settings.midimap_load_status.store(LoadStatus::Loading); - bool ret = ie_midi->loadMidiMap(getter.midimap_file.getValue(), - kit.instruments); - if(ret) - { - settings.midimap_load_status.store(LoadStatus::Done); - } - else - { - settings.midimap_load_status.store(LoadStatus::Error); - } - } - } - ie->pre(); oe->pre(nsamples); @@ -524,10 +449,10 @@ float str2float(std::string a) std::string DrumGizmo::configString() { std::string mmapfile; - if(ie->isMidiEngine()) + auto midiEngine = dynamic_cast(ie); + if(midiEngine) { - AudioInputEngineMidi *aim = (AudioInputEngineMidi*)ie; - mmapfile = aim->getMidimapFile(); + mmapfile = midiEngine->getMidimapFile(); } return diff --git a/src/drumgizmo.h b/src/drumgizmo.h index 3e734b5..eb89050 100644 --- a/src/drumgizmo.h +++ b/src/drumgizmo.h @@ -28,13 +28,13 @@ #include #include +#include #include "audiooutputengine.h" #include "audioinputengine.h" #include "events.h" #include "audiofile.h" #include "drumkit.h" -#include "memchecker.h" #include "drumkitloader.h" #include "audiocache.h" #include "mutex.h" @@ -52,8 +52,6 @@ public: AudioOutputEngine *outputengine, AudioInputEngine *inputengine); virtual ~DrumGizmo(); - bool loadkit(std::string kitfile); - bool init(); void run(int endpos); @@ -73,9 +71,9 @@ public: void setFreeWheel(bool freewheel); private: - static const int MAX_NUM_CHANNELS = 64; - static const int RESAMPLER_OUTPUT_BUFFER = 4096; - static const int RESAMPLER_INPUT_BUFFER = 64; + static constexpr int MAX_NUM_CHANNELS = 64; + static constexpr int RESAMPLER_OUTPUT_BUFFER = 4096; + static constexpr int RESAMPLER_INPUT_BUFFER = 64; protected: DrumKitLoader loader; @@ -87,7 +85,7 @@ protected: std::list< Event* > activeevents[MAX_NUM_CHANNELS]; - CHResampler resampler[MAX_NUM_CHANNELS]; + std::array resampler; sample_t resampler_output_buffer[MAX_NUM_CHANNELS][RESAMPLER_OUTPUT_BUFFER]; sample_t resampler_input_buffer[MAX_NUM_CHANNELS][RESAMPLER_INPUT_BUFFER]; @@ -95,7 +93,6 @@ protected: AudioCache audioCache; DrumKit kit; - MemChecker memchecker; InputProcessor input_processor; size_t framesize; diff --git a/src/drumkitloader.cc b/src/drumkitloader.cc index 3a0e096..ec86e77 100644 --- a/src/drumkitloader.cc +++ b/src/drumkitloader.cc @@ -32,11 +32,16 @@ #include "drumkitparser.h" #include "drumgizmo.h" +#include "audioinputenginemidi.h" -DrumKitLoader::DrumKitLoader(Settings& settings) - : framesize(0) - , settings(settings) +DrumKitLoader::DrumKitLoader(Settings& settings, DrumKit& kit, + AudioInputEngine& ie, + std::array& resampler) + : settings(settings) , getter(settings) + , kit(kit) + , ie(ie) + , resampler(resampler) { run(); run_semaphore.wait(); // Wait for the thread to actually start. @@ -55,73 +60,112 @@ DrumKitLoader::~DrumKitLoader() DEBUG(loader, "~DrumKitLoader() post\n"); } -void DrumKitLoader::stop() +bool DrumKitLoader::loadkit(const std::string& file) { + settings.drumkit_load_status.store(LoadStatus::Idle); + + if(file == "") { - std::lock_guard guard(mutex); - load_queue.clear(); + settings.drumkit_load_status.store(LoadStatus::Error); + return false; } - running = false; - semaphore.post(); - wait_stop(); -} + DEBUG(drumgizmo, "loadkit(%s)\n", file.c_str()); -void DrumKitLoader::skip() -{ - std::lock_guard guard(mutex); - load_queue.clear(); -} + // Remove all queue AudioFiles from loader before we actually delete them. + skip(); -void DrumKitLoader::setFrameSize(size_t framesize) -{ - std::lock_guard guard(mutex); - this->framesize = framesize; - framesize_semaphore.post(); // Signal that the framesize has been set. -} + // Delete all Channels, Instruments, Samples and AudioFiles. + kit.clear(); -bool DrumKitLoader::isDone() -{ - std::lock_guard guard(mutex); - return load_queue.size() == 0; + settings.drumkit_load_status.store(LoadStatus::Loading); + + DrumKitParser parser(settings, kit); + if(parser.parseFile(file)) + { + ERR(drumgizmo, "Drumkit parser failed: %s\n", file.c_str()); + settings.drumkit_load_status.store(LoadStatus::Error); + return false; + } + + // Check if there is enough free RAM to load the drumkit. + if(!memchecker.enoughFreeMemory(kit)) + { + printf("WARNING: " + "There doesn't seem to be enough RAM available to load the kit.\n" + "Trying to load it anyway...\n"); + } + + loadKit(&kit); + +#ifdef WITH_RESAMPLER + for(auto& chresampler: resampler) + { + chresampler.setup(kit.getSamplerate(), settings.samplerate.load()); + } +#endif/*WITH_RESAMPLER*/ + + + DEBUG(loadkit, "loadkit: Success\n"); + + return true; } void DrumKitLoader::loadKit(DrumKit *kit) { - std::lock_guard guard(mutex); +// std::lock_guard guard(mutex); DEBUG(loader, "Create AudioFile queue from DrumKit\n"); - std::size_t total_num_audiofiles = 0;// For UI Progress Messages + settings.number_of_files_loaded.store(0); // Count total number of files that need loading: + settings.number_of_files.store(0); for(auto instr : kit->instruments) { - total_num_audiofiles += instr->audiofiles.size(); + settings.number_of_files.fetch_add(instr->audiofiles.size()); } - settings.number_of_files.store(total_num_audiofiles); - // Now actually queue them for loading: for(auto instr : kit->instruments) { - std::vector::iterator af = instr->audiofiles.begin(); - while(af != instr->audiofiles.end()) + for(auto audiofile : instr->audiofiles) { - AudioFile *audiofile = *af; load_queue.push_back(audiofile); - af++; } } - loaded = 0; // For UI Progress Messages - DEBUG(loader, "Queued %d (size: %d) AudioFiles for loading.\n", - (int)total_num_audiofiles, (int)load_queue.size()); + (int)settings.number_of_files.load(), (int)load_queue.size()); semaphore.post(); // Start loader loop. } +void DrumKitLoader::stop() +{ + { + std::lock_guard guard(mutex); + load_queue.clear(); + } + + running = false; + semaphore.post(); + wait_stop(); +} + +void DrumKitLoader::skip() +{ + std::lock_guard guard(mutex); + load_queue.clear(); +} + +void DrumKitLoader::setFrameSize(size_t framesize) +{ + std::lock_guard guard(mutex); + this->framesize = framesize; + framesize_semaphore.post(); // Signal that the framesize has been set. +} + void DrumKitLoader::thread_main() { running = true; @@ -144,14 +188,31 @@ void DrumKitLoader::thread_main() semaphore.wait(std::chrono::milliseconds(1000)); } + bool newKit = false; if(getter.drumkit_file.hasChanged()) { - //std::cout << "RELOAD DRUMKIT!" << std::endl; + loadkit(getter.drumkit_file.getValue()); + newKit = true; } - if(getter.midimap_file.hasChanged()) + if(getter.midimap_file.hasChanged() || newKit) { - //std::cout << "RELOAD MIDIMAP!" << std::endl; + auto ie_midi = dynamic_cast(&ie); + std::cout << "ie_midi: " << (void*)ie_midi << std::endl; + if(ie_midi) + { + settings.midimap_load_status.store(LoadStatus::Loading); + bool ret = ie_midi->loadMidiMap(getter.midimap_file.getValue(), + kit.instruments); + if(ret) + { + settings.midimap_load_status.store(LoadStatus::Done); + } + else + { + settings.midimap_load_status.store(LoadStatus::Error); + } + } } std::string filename; @@ -178,11 +239,9 @@ void DrumKitLoader::thread_main() audiofile->load(preload_size); } - ++loaded; - - settings.number_of_files_loaded.store(loaded); + settings.number_of_files_loaded.fetch_add(1); - if(settings.number_of_files.load() == loaded) + if(settings.number_of_files.load() == settings.number_of_files_loaded.load()) { settings.drumkit_load_status.store(LoadStatus::Done); } diff --git a/src/drumkitloader.h b/src/drumkitloader.h index 3fd7ec1..01b4f06 100644 --- a/src/drumkitloader.h +++ b/src/drumkitloader.h @@ -36,6 +36,9 @@ #include "drumkit.h" #include "settings.h" +#include "audioinputengine.h" +#include "chresampler.h" +#include "memchecker.h" //! This class is responsible for loading the drumkits in its own thread. //! All interaction calls are simply modifying queues and not doing any @@ -47,41 +50,45 @@ class DrumKitLoader { public: //! The constrcutor starts the loader thread. - DrumKitLoader(Settings& settings); + DrumKitLoader(Settings& settings, DrumKit& kit, AudioInputEngine& ie, + std::array& resampler); //! The destructor signals the thread to stop and waits to merge before //! returning (ie. deleting the object will garantuee that the thread has //! been stopped). ~DrumKitLoader(); - //! Signal the loader to start loading all audio files contained in kit. + bool loadkit(const std::string& file); + + //! Signal the loader to start loading all audio files contained in the kit. //! All other AudioFiles in queue will be removed before the new ones are //! scheduled. void loadKit(DrumKit *kit); - void thread_main(); - - //! Simply reports if the load queue is empty (i.e. all AudioFiles has been - //! loaded). - bool isDone(); - //! Signal the loader to stop and wait until it has. void stop(); //! Skip all queued AudioFiles. void skip(); + //! Set the framesize which will be used to preloading samples in next + //! loadKit call. void setFrameSize(size_t framesize); protected: + void thread_main(); + Semaphore run_semaphore; Semaphore semaphore; Semaphore framesize_semaphore; std::mutex mutex; volatile bool running{false}; std::list load_queue; - std::size_t loaded{0}; std::size_t framesize{0}; Settings& settings; SettingsGetter getter; + DrumKit& kit; + AudioInputEngine& ie; + std::array& resampler; + MemChecker memchecker; }; diff --git a/src/midimapper.cc b/src/midimapper.cc index 05f69e5..ab3d8d7 100644 --- a/src/midimapper.cc +++ b/src/midimapper.cc @@ -28,20 +28,26 @@ int MidiMapper::lookup(int note) { + std::lock_guard guard(mutex); + if(midimap.find(note) == midimap.end()) { return -1; } - std::string instr = midimap[note]; + + const std::string& instr = midimap[note]; if(instrmap.find(instr) == instrmap.end()) { return -1; } + return instrmap[instr]; } -void MidiMapper::clear() +void MidiMapper::swap(instrmap_t& instrmap, midimap_t& midimap) { - midimap.clear(); - instrmap.clear(); + std::lock_guard guard(mutex); + + std::swap(this->instrmap, instrmap); + std::swap(this->midimap, midimap); } diff --git a/src/midimapper.h b/src/midimapper.h index 1887013..ea836e3 100644 --- a/src/midimapper.h +++ b/src/midimapper.h @@ -28,6 +28,8 @@ #include #include +#include +#include "mutex.h" typedef std::map midimap_t; typedef std::map instrmap_t; @@ -35,10 +37,16 @@ typedef std::map instrmap_t; class MidiMapper { public: - void clear(); - + //! Lookup note in map and return its index. + //! \returns -1 if not found or the note index. int lookup(int note); + //! Set new map sets. + void swap(instrmap_t& instrmap, midimap_t& midimap); + +private: instrmap_t instrmap; midimap_t midimap; + + std::mutex mutex; }; -- cgit v1.2.3