summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2013-01-26 08:42:18 +0100
committerBent Bisballe Nyeng <deva@aasimon.org>2013-01-26 08:42:18 +0100
commitcb220c27929600ff7a1980bbe421290e39b2eddc (patch)
treeba817c8081e21f0bbd1bfe7042e7ce962bf2e35f
parent06842ff2d9c727fe46f5da82ae1e43e74be6e588 (diff)
Background loader for audio files.
-rw-r--r--src/Makefile.am.drumgizmo3
-rw-r--r--src/audiofile.cc21
-rw-r--r--src/audiofile.h7
-rw-r--r--src/drumgizmo.cc79
-rw-r--r--src/drumgizmo.h14
-rw-r--r--src/drumkitloader.cc114
-rw-r--r--src/drumkitloader.h57
-rw-r--r--src/semaphore.cc109
-rw-r--r--src/semaphore.h44
9 files changed, 422 insertions, 26 deletions
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 <sndfile.h>
+#include <hugin.hpp>
+
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 <string>
#include <map>
+#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 <string.h>
+#include <hugin.hpp>
+
#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<std::string, std::string> 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 <hugin.hpp>
+
+#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<AudioFile*>::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 <string>
+
+#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 <hugin.hpp>
+
+#ifdef WIN32
+#include <windows.h>
+#else
+#include </usr/include/semaphore.h>
+#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.h>
+
+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__*/