summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2013-10-06 13:10:00 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2013-10-06 13:10:00 +0200
commit88a906395ba7d33ae563e70d8b94c855e3b5a573 (patch)
treeb0fa632b4c59d276b292407f79ee07aa9ef8dab8
parent5727436afe5a8b1b60d99863cfc939ee50d4c17e (diff)
Refactoring of AudioFile loading and message passing from engine to gui and vice versa.
-rw-r--r--plugingui/plugingui.cc2
-rw-r--r--src/audiofile.cc174
-rw-r--r--src/audiofile.h9
-rw-r--r--src/drumgizmo.cc25
-rw-r--r--src/drumkitloader.cc208
-rw-r--r--src/drumkitloader.h51
-rw-r--r--src/messagehandler.cc7
-rw-r--r--src/messagereceiver.cc3
-rw-r--r--src/messagereceiver.h1
-rw-r--r--src/semaphore.cc11
-rw-r--r--src/semaphore.h3
11 files changed, 228 insertions, 266 deletions
diff --git a/plugingui/plugingui.cc b/plugingui/plugingui.cc
index 4f16b34..e452965 100644
--- a/plugingui/plugingui.cc
+++ b/plugingui/plugingui.cc
@@ -153,7 +153,7 @@ void closeClick(void *ptr)
*/
PluginGUI::PluginGUI()
- : MessageReceiver(MSGRCV_UI)
+ : MessageReceiver(MSGRCV_UI), sem("plugingui")
{
windowClosedHandler = NULL;
changeMidimapHandler = NULL;
diff --git a/src/audiofile.cc b/src/audiofile.cc
index 4ac1f94..858edd7 100644
--- a/src/audiofile.cc
+++ b/src/audiofile.cc
@@ -37,8 +37,6 @@
#include "configuration.h"
-#define LAZYLOAD
-
AudioFile::AudioFile(std::string filename)
{
is_loaded = false;
@@ -46,8 +44,11 @@ AudioFile::AudioFile(std::string filename)
data = NULL;
size = 0;
+
+#ifdef LAZYLOAD
preloaded_data = NULL;
- ref_count = 0;
+#endif/*LAZYLOAD*/
+
magic = this;
}
@@ -64,21 +65,104 @@ bool AudioFile::isValid()
void AudioFile::unload()
{
+ // Make sure we don't unload the object while loading it...
MutexAutolock l(mutex);
+
+ is_loaded = false;
+
+#ifdef LAZYLOAD
if(data == preloaded_data) {
delete[] data;
data = NULL;
size = 0;
- }
- else {
+ } else {
size = 0;
delete[] data;
data = NULL;
delete preloaded_data;
preloaded_data = NULL;
}
+#else
+ delete[] data;
+ data = NULL;
+ size = 0;
+#endif/*LAZYLOAD*/
+}
+
+void AudioFile::load(int num_samples)
+{
+ // Make sure we don't unload the object while loading it...
+ MutexAutolock l(mutex);
+
+ /*
+ Lazy load of drum kits
+ init();
+ return;
+ */
+
+ if(data) return;
+
+ SF_INFO sf_info;
+ SNDFILE *fh = sf_open(filename.c_str(), SFM_READ, &sf_info);
+ if(!fh) {
+ ERR(audiofile,"SNDFILE Error (%s): %s\n",
+ filename.c_str(), sf_strerror(fh));
+ return;
+ }
+
+ size = sf_info.frames;
+
+ double ratio = (double)Conf::samplerate / (double)sf_info.samplerate;
+
+ if(num_samples != ALL_SAMPLES) {
+ // Make sure we read enough samples, even after conversion.
+ num_samples /= ratio;
+ if((int)size > num_samples) size = num_samples;
+ }
+
+ sample_t* data = new sample_t[size];
+ size = sf_read_float(fh, data, size);
+
+ DEBUG(audiofile,"Loaded %d samples %p\n", size, this);
+
+ sf_close(fh);
+
+ if(Conf::samplerate != sf_info.samplerate) {
+ // Resample data...
+ size_t osize = size * ratio;
+ sample_t *odata = new sample_t[osize];
+
+ SRC_DATA src;
+ src.data_in = data;
+ src.input_frames = size;
+
+ src.data_out = odata;
+ src.output_frames = osize;
+
+ src.src_ratio = ratio;
+
+ // Do the conversion
+ src_simple(&src, SRC_SINC_BEST_QUALITY, 1);
+
+ delete[] data;
+ data = odata;
+ size = src.output_frames;
+
+ DEBUG(audiofile,"Converted into %d samples %p\n", size, this);
+ }
+
+ this->data = data;
+ is_loaded = true;
+
+ //DEBUG(audiofile, "Loading of %s completed.\n", filename.c_str());
+}
+
+bool AudioFile::isLoaded()
+{
+ return is_loaded;
}
+#ifdef LAZYLOAD
#define SIZE 512*4
void AudioFile::init()
{
@@ -173,82 +257,4 @@ void AudioFile::reset()
delete old_data;
mutex.unlock();
}
-
-void AudioFile::load(int num_samples)
-{
- /*
- Lazy load of drum kits
- init();
- return;
- */
-
- if(data) return;
-
- SF_INFO sf_info;
- SNDFILE *fh = sf_open(filename.c_str(), SFM_READ, &sf_info);
- if(!fh) {
- ERR(audiofile,"SNDFILE Error (%s): %s\n",
- filename.c_str(), sf_strerror(fh));
- return;
- }
-
- size = sf_info.frames;
-
- double ratio = (double)Conf::samplerate / (double)sf_info.samplerate;
-
- if(num_samples != ALL_SAMPLES) {
- // Make sure we read enough samples, even after conversion.
- num_samples /= ratio;
- if((int)size > num_samples) size = num_samples;
- }
-
- sample_t* data = new sample_t[size];
- size = sf_read_float(fh, data, size);
-
- DEBUG(audiofile,"Loaded %d samples %p\n", size, this);
-
- sf_close(fh);
-
- if(Conf::samplerate != sf_info.samplerate) {
- // Resample data...
- size_t osize = size * ratio;
- sample_t *odata = new sample_t[osize];
-
- SRC_DATA src;
- src.data_in = data;
- src.input_frames = size;
-
- src.data_out = odata;
- src.output_frames = osize;
-
- src.src_ratio = ratio;
-
- // Do the conversion
- src_simple(&src, SRC_SINC_BEST_QUALITY, 1);
-
- delete[] data;
- data = odata;
- size = src.output_frames;
-
- DEBUG(audiofile,"Converted into %d samples %p\n", size, this);
- }
-
-
- mutex.lock();
- this->data = data;
- 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;
-}
+#endif
diff --git a/src/audiofile.h b/src/audiofile.h
index 20ffdf3..8a190c1 100644
--- a/src/audiofile.h
+++ b/src/audiofile.h
@@ -36,7 +36,7 @@
#include "mutex.h"
#include "audio.h"
-#if 0
+/*
Plan for lazy loading of audio (Brainstorming)
* Encapsulate data array?
- Speed issues?
@@ -63,9 +63,9 @@
| --------- | |
Wave Into --> | SndFile | <----- Read data (directly from array)
---------
-#endif/*0*/
+*/
-#define LAZYLOAD
+//#define LAZYLOAD
#define ALL_SAMPLES -1
@@ -95,13 +95,12 @@ public:
#endif/*LAZYLOAD*/
bool isValid();
- int ref_count;
Mutex mutex;
private:
void *magic;
- bool is_loaded;
+ volatile bool is_loaded;
};
#endif/*__DRUMGIZMO_AUDIOFILE_H__*/
diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc
index b99687d..c4ef194 100644
--- a/src/drumgizmo.cc
+++ b/src/drumgizmo.cc
@@ -43,21 +43,13 @@
DrumGizmo::DrumGizmo(AudioOutputEngine *o, AudioInputEngine *i)
: MessageReceiver(MSGRCV_ENGINE),
- loader(this), oe(o), ie(i)
+ loader(), oe(o), ie(i)
{
- loader.run(); // Start drumkit loader thread.
}
DrumGizmo::~DrumGizmo()
{
- /*
- AudioFiles::iterator i = audiofiles.begin();
- while(i != audiofiles.end()) {
- AudioFile *audiofile = i->second;
- delete audiofile;
- i++;
- }
- */
+ DEBUG(drumgizmo, "!");
loader.stop();
}
@@ -75,8 +67,10 @@ bool DrumGizmo::loadkit(std::string file)
DEBUG(drumgizmo, "loadkit(%s)\n", kitfile.c_str());
+ // Remove all queue AudioFiles from loader before we actually delete them.
loader.skip();
+ // Delete all Channels, Instruments, Samples and AudioFiles.
kit.clear();
DrumKitParser parser(kitfile, kit);
@@ -94,16 +88,7 @@ bool DrumGizmo::loadkit(std::string file)
bool DrumGizmo::init(bool preload)
{
- if(preload) {
- /*
- AudioFiles::iterator i = audiofiles.begin();
- while(i != audiofiles.end()) {
- AudioFile *audiofile = i->second;
- audiofile->load();
- i++;
- }
- */
- }
+ (void)preload;
if(!ie->init(kit.instruments)) return false;
if(!oe->init(kit.channels)) return false;
diff --git a/src/drumkitloader.cc b/src/drumkitloader.cc
index a7a8989..69f656b 100644
--- a/src/drumkitloader.cc
+++ b/src/drumkitloader.cc
@@ -31,185 +31,129 @@
#include "drumkitparser.h"
#include "drumgizmo.h"
-DrumKitLoader::DrumKitLoader(DrumGizmo *dg)
+DrumKitLoader::DrumKitLoader()
+ : semaphore("drumkitloader")
{
- drumgizmo = dg;
- is_done = false;
- quitit = false;
- skipit = false;
+ running = true;
+ run();
}
DrumKitLoader::~DrumKitLoader()
{
- if(!quitit) {
+ if(running) {
stop();
}
}
void DrumKitLoader::stop()
{
- quitit = true;
+ {
+ MutexAutolock l(mutex);
+ load_queue.clear();
+ }
+
+ running = false;
semaphore.post();
wait_stop();
}
void DrumKitLoader::skip()
{
- skipit = true;
- semaphore.post();
- skip_semaphore.wait();
+ MutexAutolock l(mutex);
+ load_queue.clear();
}
bool DrumKitLoader::isDone()
{
- bool done;
-
- mutex.lock();
- done = is_done;
- mutex.unlock();
-
- return done;
+ MutexAutolock l(mutex);
+ return load_queue.size() == 0;
}
void DrumKitLoader::loadKit(DrumKit *kit)
{
- this->kit = kit;
-
- mutex.lock();
- is_done = false;
- mutex.unlock();
-
- semaphore.post();
-}
+ MutexAutolock l(mutex);
-void DrumKitLoader::prepare(AudioFile* af)
-{
- DEBUG(loader, "Preparing audiofile %p (%d in queue)\n",
- af, load_queue.size());
- mutex.lock();
- af->ref_count++;
- load_queue.push_back(af);
-// if(ref_count.find(af) == ref_count.end()) {
-// ref_count[af]++;
-// }
-// else {
-// ref_count[af] = 0;
-// }
- mutex.unlock();
- semaphore.post();
-}
+ DEBUG(loader, "Create AudioFile queue from DrumKit\n");
-void DrumKitLoader::reset(AudioFile* af)
-{
- mutex.lock();
- af->ref_count--;
- reset_queue.push_back(af);
- mutex.unlock();
- semaphore.post();
-}
+ total_num_audiofiles = 0;// For UI Progress Messages
-void DrumKitLoader::thread_main()
-{
- while(1) {
- DEBUG(loader, "before sem\n");
+ { // Count total number of files that need loading:
+ Instruments::iterator i = kit->instruments.begin();
+ while(i != kit->instruments.end()) {
+ Instrument *instr = *i;
+ total_num_audiofiles += instr->audiofiles.size();
+ i++;
+ }
+ }
- semaphore.wait();
+ { // Now actually queue them for loading:
+ Instruments::iterator i = kit->instruments.begin();
+ while(i != kit->instruments.end()) {
+ Instrument *instr = *i;
+
+ std::vector<AudioFile*>::iterator af = instr->audiofiles.begin();
+ while(af != instr->audiofiles.end()) {
+ AudioFile *audiofile = *af;
+ load_queue.push_back(audiofile);
+ af++;
+ }
+
+ i++;
+ }
+ }
- DEBUG(loader, "after sem\n");
- fflush(stdout);
+ loaded = 0; // For UI Progress Messages
+ DEBUG(loader, "Queued %d (size: %d) AudioFiles for loading.\n",
+ total_num_audiofiles, load_queue.size());
- if(quitit) return;
+ semaphore.post(); // Start loader loop.
+}
- if(skipit) {
- skip_semaphore.post();
- skipit = false;
- continue;
+void DrumKitLoader::thread_main()
+{
+ while(running) {
+ size_t size;
+ {
+ MutexAutolock l(mutex);
+ size = load_queue.size();
}
- if(!load_queue.empty()) {
- DEBUG(loader, "Loading remaining of audio file\n");
- AudioFile* af = load_queue.front();
- mutex.lock();
- load_queue.pop_front();
- mutex.unlock();
- af->loadNext();
- }
- else if(!reset_queue.empty()) {
- AudioFile* af = reset_queue.front();
- mutex.lock();
- if(af->ref_count <= 0) {
- af->reset();
- af->ref_count = 0;
- }
- reset_queue.pop_front();
- mutex.unlock();
+ // Only sleep if queue is empty.
+ if(size == 0) {
+ //DEBUG(loader, "Wait for sem");
+ semaphore.wait();
+ //DEBUG(loader, "Sem enter");
}
- else { // Initialize drum kit
- DEBUG(loader, "Initializing drum kit\n");
- unsigned int count = 0;
-
- if(kit && !kit->isValid()) goto finish;
- { // Count total number of files that need loading:
- Instruments::iterator i = kit->instruments.begin();
- while(i != kit->instruments.end()) {
- Instrument *instr = *i;
- if(instr && !instr->isValid()) goto finish;
+ AudioFile *audiofile = NULL;
- count += instr->audiofiles.size();
- i++;
- }
- }
-
- { // Now actually load them:
- unsigned int loaded = 0;
- Instruments::iterator i = kit->instruments.begin();
- while(i != kit->instruments.end()) {
- Instrument *instr = *i;
-
- if(instr && !instr->isValid()) goto finish;
+ {
+ MutexAutolock l(mutex);
+ if(load_queue.size() == 0) continue;
+ audiofile = load_queue.front();
+ load_queue.pop_front();
+ }
- std::vector<AudioFile*>::iterator a = instr->audiofiles.begin();
- while(a != instr->audiofiles.end()) {
#if 0
#ifdef WIN32
- SleepEx(5000, FALSE);
+ SleepEx(5000, FALSE);
#else
- usleep(5000);
+ usleep(5000);
#endif/*WIN32*/
#endif
- AudioFile *af = *a;
-
- if(af && !af->isValid()) goto finish;
-
- af->load();
-
- loaded++;
-
- LoadStatusMessage *ls = new LoadStatusMessage();
- ls->number_of_files = count;
- ls->numer_of_files_loaded = loaded;
- ls->current_file = af->filename;
- msghandler.sendMessage(MSGRCV_UI, ls);
-
- a++;
-
- if(skipit) goto finish;
- }
-
- i++;
- }
- }
- mutex.lock();
- is_done = true;
- mutex.unlock();
+ audiofile->load();
+ loaded++;
- finish:
- continue;
- }
+ LoadStatusMessage *ls = new LoadStatusMessage();
+ ls->number_of_files = total_num_audiofiles;
+ ls->numer_of_files_loaded = loaded;
+ ls->current_file = audiofile->filename;
+ msghandler.sendMessage(MSGRCV_UI, ls);
}
+
+ DEBUG(loader, "Loader thread finished.");
}
#ifdef TEST_DRUMKITLOADER
diff --git a/src/drumkitloader.h b/src/drumkitloader.h
index 9d14638..be24812 100644
--- a/src/drumkitloader.h
+++ b/src/drumkitloader.h
@@ -36,37 +36,62 @@
#include "drumkit.h"
-class DrumGizmo;
-
+/**
+ * This class is responsible for loading the drumkits in its own thread.
+ * All interaction calls are simply modifying queues and not doing any
+ * work in-sync with the caller.
+ * This means that if loadKit(...) is called, one cannot assume that the
+ * drumkit has actually been loaded when the call returns.
+ */
class DrumKitLoader : public Thread {
public:
- DrumKitLoader(DrumGizmo *drumgizmo);
+ /**
+ * The constrcutor starts the loader thread.
+ */
+ DrumKitLoader();
+
+ /**
+ * 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.
+ * All other AudioFiles in queue will be removed before the new ones are
+ * scheduled.
+ */
void loadKit(DrumKit *kit);
- void prepare(AudioFile* af);
- void reset(AudioFile* af);
+ // I have no idea what this does..
+ //void reset(AudioFile* af);
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();
private:
- DrumGizmo *drumgizmo;
Semaphore semaphore;
- Semaphore skip_semaphore;
- DrumKit *kit;
- bool is_done;
Mutex mutex;
- volatile bool quitit;
- volatile bool skipit;
+ volatile bool running;
std::list<AudioFile*> load_queue;
- std::list<AudioFile*> reset_queue;
- std::map<AudioFile*, int> ref_count;
+ size_t total_num_audiofiles;
+ size_t loaded;
};
#endif/*__DRUMGIZMO_DRUMKITLOADER_H__*/
diff --git a/src/messagehandler.cc b/src/messagehandler.cc
index dcaf5f1..52a89a5 100644
--- a/src/messagehandler.cc
+++ b/src/messagehandler.cc
@@ -73,16 +73,17 @@ bool MessageHandler::sendMessage(message_receiver_id_t id, Message* msg)
//DEBUG(msghandler, "Sending message to id %d\n", id);
MessageReceiver *receiver = receivers[id];
-
+ /* // This code causes sporadic segfaults on windows.
if(msg->processing_mode() == Message::FilterMultiple) {
Message *pmsg;
+ MutexAutolock lock(receiver->message_mutex); // Make peek/receive atomic.
while( (pmsg = receiver->peekMessage()) != NULL) {
- if(pmsg->type() != Message::LoadStatus) break;
+ if(pmsg->type() != msg->type()) break;
// Remove all old messages with same type.
delete receiver->receiveMessage();
}
}
-
+ */
receiver->sendMessage(msg);
return true;
}
diff --git a/src/messagereceiver.cc b/src/messagereceiver.cc
index f391aad..a24482b 100644
--- a/src/messagereceiver.cc
+++ b/src/messagereceiver.cc
@@ -47,7 +47,6 @@ void MessageReceiver::sendMessage(Message *msg)
Message *MessageReceiver::receiveMessage()
{
- MutexAutolock l(message_mutex);
Message *msg = NULL;
if(message_queue.size()) {
msg = message_queue.front();
@@ -58,7 +57,6 @@ Message *MessageReceiver::receiveMessage()
Message *MessageReceiver::peekMessage()
{
- MutexAutolock l(message_mutex);
Message *msg = NULL;
if(message_queue.size()) {
msg = message_queue.front();
@@ -68,6 +66,7 @@ Message *MessageReceiver::peekMessage()
void MessageReceiver::handleMessages(size_t max)
{
+ MutexAutolock l(message_mutex);
bool process_all = false;
if(max == 0) process_all = true;
diff --git a/src/messagereceiver.h b/src/messagereceiver.h
index 4185f29..2794091 100644
--- a/src/messagereceiver.h
+++ b/src/messagereceiver.h
@@ -34,6 +34,7 @@
#include "messagehandler.h"
class MessageReceiver {
+ friend class MessageHandler;
public:
MessageReceiver(message_receiver_id_t id);
~MessageReceiver();
diff --git a/src/semaphore.cc b/src/semaphore.cc
index d43835a..5d90c55 100644
--- a/src/semaphore.cc
+++ b/src/semaphore.cc
@@ -42,9 +42,10 @@ struct semaphore_private_t {
#endif
};
-Semaphore::Semaphore()
+Semaphore::Semaphore(const char *name)
{
- DEBUG(semaphore, "Create\n");
+ this->name = name;
+ DEBUG(semaphore, "Create [%s]\n", name);
prv = new struct semaphore_private_t();
@@ -60,7 +61,7 @@ Semaphore::Semaphore()
Semaphore::~Semaphore()
{
- DEBUG(semaphore, "Delete\n");
+ DEBUG(semaphore, "Delete [%s]\n", name);
#ifdef WIN32
CloseHandle(prv->semaphore);
@@ -73,7 +74,7 @@ Semaphore::~Semaphore()
void Semaphore::post()
{
- DEBUG(semaphore, "Post\n");
+ DEBUG(semaphore, "Post [%s]\n", name);
#ifdef WIN32
ReleaseSemaphore(prv->semaphore, 1, NULL);
@@ -84,7 +85,7 @@ void Semaphore::post()
void Semaphore::wait()
{
- DEBUG(semaphore, "Wait\n");
+ DEBUG(semaphore, "Wait [%s]\n", name);
#ifdef WIN32
WaitForSingleObject(prv->semaphore, INFINITE);
diff --git a/src/semaphore.h b/src/semaphore.h
index 7f8a6ff..7e39f5a 100644
--- a/src/semaphore.h
+++ b/src/semaphore.h
@@ -31,7 +31,7 @@ struct semaphore_private_t;
class Semaphore {
public:
- Semaphore();
+ Semaphore(const char *name = "");
~Semaphore();
void post();
@@ -39,6 +39,7 @@ public:
private:
struct semaphore_private_t *prv;
+ const char *name;
};
#endif/*__PRACRO_SEMAPHORE_H__*/