From cb220c27929600ff7a1980bbe421290e39b2eddc Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sat, 26 Jan 2013 08:42:18 +0100 Subject: Background loader for audio files. --- src/Makefile.am.drumgizmo | 3 ++ src/audiofile.cc | 21 ++++++++- src/audiofile.h | 7 +++ src/drumgizmo.cc | 79 +++++++++++++++++++++++--------- src/drumgizmo.h | 14 ++++-- src/drumkitloader.cc | 114 ++++++++++++++++++++++++++++++++++++++++++++++ src/drumkitloader.h | 57 +++++++++++++++++++++++ src/semaphore.cc | 109 ++++++++++++++++++++++++++++++++++++++++++++ src/semaphore.h | 44 ++++++++++++++++++ 9 files changed, 422 insertions(+), 26 deletions(-) create mode 100644 src/drumkitloader.cc create mode 100644 src/drumkitloader.h create mode 100644 src/semaphore.cc create mode 100644 src/semaphore.h (limited to 'src') diff --git a/src/Makefile.am.drumgizmo b/src/Makefile.am.drumgizmo index 98f1b82..54de5e3 100644 --- a/src/Makefile.am.drumgizmo +++ b/src/Makefile.am.drumgizmo @@ -5,6 +5,7 @@ DRUMGIZMO_SOURCES = \ $(top_srcdir)/src/configuration.cc \ $(top_srcdir)/src/drumgizmo.cc \ $(top_srcdir)/src/drumkit.cc \ + $(top_srcdir)/src/drumkitloader.cc \ $(top_srcdir)/src/drumkitparser.cc \ $(top_srcdir)/src/events.cc \ $(top_srcdir)/src/instrument.cc \ @@ -14,7 +15,9 @@ DRUMGIZMO_SOURCES = \ $(top_srcdir)/src/mutex.cc \ $(top_srcdir)/src/path.cc \ $(top_srcdir)/src/sample.cc \ + $(top_srcdir)/src/semaphore.cc \ $(top_srcdir)/src/saxparser.cc \ + $(top_srcdir)/src/thread.cc \ $(top_srcdir)/src/velocity.cc DRUMGIZMO_LIBS = $(SNDFILE_LIBS) $(EXPAT_LIBS) \ No newline at end of file diff --git a/src/audiofile.cc b/src/audiofile.cc index 018b7fb..1927034 100644 --- a/src/audiofile.cc +++ b/src/audiofile.cc @@ -31,15 +31,18 @@ #include +#include + AudioFile::AudioFile(std::string filename) { + is_loaded = false; //printf("new AudioFile %p\n", this); this->filename = filename; data = NULL; size = 0; - load(); + //load(); } AudioFile::~AudioFile() @@ -74,5 +77,21 @@ void AudioFile::load() sf_read_float(fh, data, size); sf_close(fh); + + mutex.lock(); + is_loaded = true; + mutex.unlock(); + + DEBUG(audiofile, "Loading of %s completed.\n", filename.c_str()); } +bool AudioFile::isLoaded() +{ + bool l; + + mutex.lock(); + l = is_loaded; + mutex.unlock(); + + return l; +} diff --git a/src/audiofile.h b/src/audiofile.h index 53fe2a7..17ff651 100644 --- a/src/audiofile.h +++ b/src/audiofile.h @@ -30,6 +30,7 @@ #include #include +#include "mutex.h" #include "audio.h" class AudioFile { @@ -40,10 +41,16 @@ public: void load(); void unload(); + bool isLoaded(); + sample_t *data; size_t size; std::string filename; + +private: + Mutex mutex; + bool is_loaded; }; #endif/*__DRUMGIZMO_AUDIOFILE_H__*/ diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index 7af13d2..ec03d76 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -34,11 +34,14 @@ #include +#include + #include "drumkitparser.h" DrumGizmo::DrumGizmo(AudioOutputEngine *o, AudioInputEngine *i) : oe(o), ie(i) { + loader.run(); // Start drumkit loader thread. } DrumGizmo::~DrumGizmo() @@ -58,21 +61,20 @@ std::string DrumGizmo::drumkitfile() return kitfile; } -bool DrumGizmo::loadkit(const std::string &kitfile) +bool DrumGizmo::loadkit(std::string file) { - this->kitfile = kitfile; - kit = DrumKit(); + this->kitfile = file; + + DEBUG(drumgizmo, "loadkit(%s)\n", kitfile.c_str()); + DrumKitParser parser(kitfile, kit); - if(parser.parse()) return false; - /* - Instruments::iterator i = kit.instruments.begin(); - while(i != kit.instruments.end()) { - Instrument &instr = i->second; - InstrumentParser iparser(instr.file, instr); - if(iparser.parse()) return false; - i++; + if(parser.parse()) { + ERR(drumgizmo, "Drumkit parser failed: %s\n", kitfile.c_str()); + return false; } - */ + + loader.loadKit(&kit); + return true; } @@ -97,10 +99,30 @@ bool DrumGizmo::init(bool preload) bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples) { +#if 0 + DEBUG(drumgizmo, "loader.isDone() = %d", (int)loader.isDone()); + if(!loader.isDone()) { + /* + // return false; + ie->pre(); + oe->pre(nsamples); + size_t nev; + event_t *evs = ie->run(pos, nsamples, &nev); + free(evs); + // memset(samples, 0, nsamples); + for(size_t i = 0; i < nsamples / 2; i++) samples[i] = sin(pos + i); + for(size_t c = 0; c < 16; c++) oe->run(c, samples, nsamples); + ie->post(); + oe->post(nsamples); + pos += nsamples; + */ + return true; + } +#endif + ie->pre(); oe->pre(nsamples); - // // Read new events // @@ -125,14 +147,14 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples) } if(i == NULL) { - printf("Missing Instrument %d.\n", evs[e].instrument); + ERR(drumgizmo, "Missing Instrument %d.\n", evs[e].instrument); continue; } Sample *s = i->sample(evs[e].velocity, evs[e].offset + pos); if(s == NULL) { - printf("Missing Sample.\n"); + ERR(drumgizmo, "Missing Sample.\n"); continue; } @@ -143,7 +165,7 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples) if(af == NULL) { //printf("Missing AudioFile.\n"); } else { - //printf("Adding event %d.\n", evs[e].offset); + DEBUG(drumgizmo, "Adding event %d.\n", evs[e].offset); Event *evt = new EventSample(ch.num, 1.0, af); evt->offset = evs[e].offset + pos; activeevents[ch.num].push_back(evt); @@ -222,7 +244,8 @@ void DrumGizmo::getSamples(int ch, int pos, sample_t *s, size_t sz) { EventSample *evt = (EventSample *)event; AudioFile *af = evt->file; - af->load(); // Make sure it is loaded. + //af->load(); // Make sure it is loaded. + if(!af->isLoaded()) continue; size_t n = 0; if(evt->offset > (size_t)pos) n = evt->offset - pos; @@ -332,17 +355,29 @@ public: return values[name]; } + void parseError(char *buf, size_t len, std::string error, int lineno) + { + std::string buffer; + buffer.append(buf, len); + ERR(configparser, "sax parser error '%s' at line %d. " + "Buffer: [%d bytes]<%s>\n", + error.c_str(), lineno, len, buffer.c_str()); + } + std::map values; std::string *str; }; -void DrumGizmo::setConfigString(std::string cfg) +bool DrumGizmo::setConfigString(std::string cfg) { - printf("Load config: %s\n", cfg.c_str()); + DEBUG(config, "Load config: %s\n", cfg.c_str()); std::string dkf; ConfigParser p; - p.parse(cfg); + if(p.parse(cfg)) { + ERR(drumgizmo, "Config parse error.\n"); + return false; + } midimapfile = p.value("midimapfile"); @@ -372,9 +407,11 @@ void DrumGizmo::setConfigString(std::string cfg) } if(drumkitfile() != p.value("drumkitfile")) { - loadkit(p.values["drumkitfile"]); + if(!loadkit(p.values["drumkitfile"])) return false; init(true); } + + return true; } #ifdef TEST_DRUMGIZMO diff --git a/src/drumgizmo.h b/src/drumgizmo.h index a3ad3ca..e79dad0 100644 --- a/src/drumgizmo.h +++ b/src/drumgizmo.h @@ -37,6 +37,10 @@ #include "audiofile.h" #include "drumkit.h" +#include "drumkitloader.h" + +#include "mutex.h" + #define MAX_NUM_CHANNELS 512 class DrumGizmo { @@ -45,7 +49,7 @@ public: AudioInputEngine *inputengine); ~DrumGizmo(); - bool loadkit(const std::string &kitfile); + bool loadkit(std::string kitfile); std::string drumkitfile(); bool init(bool preload = true); @@ -59,11 +63,15 @@ public: bool isRunning() { return is_running; } std::string configString(); - void setConfigString(std::string cfg); + bool setConfigString(std::string cfg); std::string midimapfile; + std::string kitfile; private: + DrumKitLoader loader; + + Mutex mutex; bool is_running; AudioOutputEngine *oe; @@ -77,8 +85,6 @@ private: public: #endif DrumKit kit; - - std::string kitfile; }; diff --git a/src/drumkitloader.cc b/src/drumkitloader.cc new file mode 100644 index 0000000..9f514d0 --- /dev/null +++ b/src/drumkitloader.cc @@ -0,0 +1,114 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * drumkitloader.cc + * + * Thu Jan 17 20:54:14 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "drumkitloader.h" + +#include + +#include "drumkitparser.h" + +DrumKitLoader::DrumKitLoader() +{ + is_done = false; + quitit = false; +} + +DrumKitLoader::~DrumKitLoader() +{ + quitit = true; + semaphore.post(); + wait_stop(); +} + +bool DrumKitLoader::isDone() +{ + bool done; + + mutex.lock(); + done = is_done; + mutex.unlock(); + + return done; +} + +void DrumKitLoader::loadKit(DrumKit *kit) +{ + this->kit = kit; + + mutex.lock(); + is_done = false; + mutex.unlock(); + + semaphore.post(); +} + + +void DrumKitLoader::thread_main() +{ + while(1) { + DEBUG(loader, "before sem\n"); + semaphore.wait(); + DEBUG(loader, "after sem\n"); + + if(quitit) return; + + Instruments::iterator i = kit->instruments.begin(); + while(i != kit->instruments.end()) { + Instrument *instr = *i; + + std::vector::iterator a = instr->audiofiles.begin(); + while(a != instr->audiofiles.end()) { + // usleep(10000); + AudioFile *af = *a; + af->load(); + a++; + } + + i++; + } + + mutex.lock(); + is_done = true; + mutex.unlock(); + } +} + +#ifdef TEST_DRUMKITLOADER +//Additional dependency files +//deps: +//Required cflags (autoconf vars may be used) +//cflags: +//Required link options (autoconf vars may be used) +//libs: +#include "test.h" + +TEST_BEGIN; + +// TODO: Put some testcode here (see test.h for usable macros). + +TEST_END; + +#endif/*TEST_DRUMKITLOADER*/ diff --git a/src/drumkitloader.h b/src/drumkitloader.h new file mode 100644 index 0000000..c308761 --- /dev/null +++ b/src/drumkitloader.h @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * drumkitloader.h + * + * Thu Jan 17 20:54:13 CET 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_DRUMKITLOADER_H__ +#define __DRUMGIZMO_DRUMKITLOADER_H__ + +#include + +#include "thread.h" +#include "semaphore.h" +#include "mutex.h" + +#include "drumkit.h" + +class DrumKitLoader : public Thread { +public: + DrumKitLoader(); + ~DrumKitLoader(); + + void loadKit(DrumKit *kit); + + void thread_main(); + + bool isDone(); + +private: + Semaphore semaphore; + DrumKit *kit; + bool is_done; + Mutex mutex; + bool quitit; +}; + +#endif/*__DRUMGIZMO_DRUMKITLOADER_H__*/ diff --git a/src/semaphore.cc b/src/semaphore.cc new file mode 100644 index 0000000..d43835a --- /dev/null +++ b/src/semaphore.cc @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * semaphore.cc + * + * Sat Oct 8 17:44:13 CEST 2005 + * Copyright 2005 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Pracro. + * + * Pracro is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Pracro is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Pracro; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "semaphore.h" + +#include + +#ifdef WIN32 +#include +#else +#include +#endif + +struct semaphore_private_t { +#ifdef WIN32 + HANDLE semaphore; +#else + sem_t semaphore; +#endif +}; + +Semaphore::Semaphore() +{ + DEBUG(semaphore, "Create\n"); + + prv = new struct semaphore_private_t(); + +#ifdef WIN32 + prv->semaphore = CreateSemaphore(NULL, // default security attributes + 0, // initial count + 100000, // maximum count + NULL); // unnamed semaphore +#else + sem_init(&prv->semaphore, 0, 0); +#endif +} + +Semaphore::~Semaphore() +{ + DEBUG(semaphore, "Delete\n"); + +#ifdef WIN32 + CloseHandle(prv->semaphore); +#else + sem_destroy(&prv->semaphore); +#endif + + if(prv) delete prv; +} + +void Semaphore::post() +{ + DEBUG(semaphore, "Post\n"); + +#ifdef WIN32 + ReleaseSemaphore(prv->semaphore, 1, NULL); +#else + sem_post(&prv->semaphore); +#endif +} + +void Semaphore::wait() +{ + DEBUG(semaphore, "Wait\n"); + +#ifdef WIN32 + WaitForSingleObject(prv->semaphore, INFINITE); +#else + sem_wait(&prv->semaphore); +#endif +} + +#ifdef TEST_SEMAPHORE +//deps: +//cflags: -I.. $(PTHREAD_CFLAGS) +//libs: $(PTHREAD_LIBS) +#include + +TEST_BEGIN; + +// TODO: Put some testcode here (see test.h for usable macros). +TEST_TRUE(false, "No tests yet!"); + +TEST_END; + +#endif/*TEST_SEMAPHORE*/ diff --git a/src/semaphore.h b/src/semaphore.h new file mode 100644 index 0000000..7f8a6ff --- /dev/null +++ b/src/semaphore.h @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * semaphore.h + * + * Sat Oct 8 17:44:13 CEST 2005 + * Copyright 2005 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Pracro. + * + * Pracro is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Pracro is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Pracro; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __PRACRO_SEMAPHORE_H__ +#define __PRACRO_SEMAPHORE_H__ + +struct semaphore_private_t; + +class Semaphore { +public: + Semaphore(); + ~Semaphore(); + + void post(); + void wait(); + +private: + struct semaphore_private_t *prv; +}; + +#endif/*__PRACRO_SEMAPHORE_H__*/ -- cgit v1.2.3