summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author- <nemo@alice.(none)>2013-05-09 17:54:45 +0200
committer- <nemo@alice.(none)>2013-05-09 17:54:45 +0200
commit774815a97901fe9d5ce2767a8c479c52a5ad0ce8 (patch)
tree325793f2c2f76d2efe3af3d980005d074af035f8
parenta4d73c0cb2321bd61bd31d2922ae469389e5825e (diff)
Lazy load of audio. Unloads when there's nothing else to do.
m---------hugin0
-rw-r--r--src/audiofile.cc120
-rw-r--r--src/audiofile.h49
-rw-r--r--src/drumgizmo.cc15
-rw-r--r--src/drumkitloader.cc126
-rw-r--r--src/drumkitloader.h7
6 files changed, 270 insertions, 47 deletions
diff --git a/hugin b/hugin
-Subproject 782fe184b558070bca926bdeb38c48ea1657854
+Subproject 2630860e6bc935c3daacec186e080eddcc79fe3
diff --git a/src/audiofile.cc b/src/audiofile.cc
index 5a9cdb5..c9641dc 100644
--- a/src/audiofile.cc
+++ b/src/audiofile.cc
@@ -33,15 +33,23 @@
#include <hugin.hpp>
+#define LAZYLOAD
+
AudioFile::AudioFile(std::string filename)
{
is_loaded = false;
//printf("new AudioFile %p\n", this);
this->filename = filename;
+ locked = false;
data = NULL;
size = 0;
-
+//#ifdef LAZY_LOAD
+ fh = NULL;
+ preloaded_data = NULL;
+ completely_loaded = false;
+//#endif/*LAZYLOAD*/
+ ref_count = 0;
magic = this;
//load();
@@ -61,15 +69,116 @@ bool AudioFile::isValid()
void AudioFile::unload()
{
- if(data) {
+ if(data == preloaded_data) {
delete data;
data = NULL;
size = 0;
}
+ else {
+ size = 0;
+ delete data;
+ data = NULL;
+ delete preloaded_data;
+ preloaded_data = NULL;
+ }
+ sf_close(this->fh);
+}
+
+#define SIZE 512*4
+void AudioFile::init() {
+ printf("Initializing %p\n", this);
+ if(data) {
+ printf("\t already initialized\n");
+ return;
+ }
+
+ SF_INFO sf_info;
+ SNDFILE *fh = sf_open(filename.c_str(), SFM_READ, &sf_info);
+ if(!fh) {
+ printf("SNDFILE Error (%s): %s\n", filename.c_str(), sf_strerror(fh));
+ return;
+ }
+
+ int size = SIZE;
+
+ sample_t* data = new sample_t[size];
+
+ size = sf_read_float(fh, data, size);
+
+ printf("Lazy loaded %d samples\n", size);
+ sf_close(fh);
+
+ mutex.lock();
+ this->data = data;
+ this->size = size;
+ this->preloaded_data = data;
+ this->is_loaded = true;
+ this->fh = fh;
+// if(sf_info.frames <= size) {
+// printf("Sample completely loaded\n");
+// completely_loaded = true;
+// }
+ mutex.unlock();
+}
+
+void AudioFile::loadNext()
+{
+ if(this->data != this->preloaded_data) {
+ printf("Already completely loaded %p\n", this);
+ return;
+ }
+
+ SF_INFO sf_info;
+ SNDFILE *fh = sf_open(filename.c_str(), SFM_READ, &sf_info);
+// SF_INFO sf_info = this->sf_info;
+// SNDFILE *fh = this->fh;
+ if(!fh) {
+ printf("SNDFILE Error (%s): %s\n", filename.c_str(), sf_strerror(fh));
+ return;
+ }
+
+// sf_seek(fh, 0, SEEK_SET) ;
+
+ int size = sf_info.frames;
+
+ sample_t* data = new sample_t[size];
+
+ size = sf_read_float(fh, data, size);
+
+ printf("Finished loading %d samples %p\n", size, this);
+ sf_close(fh);
+
+ mutex.lock();
+ this->data = data;
+ this->size = size;
+ mutex.unlock();
+}
+
+void AudioFile::reset() {
+ printf("Resetting audio file %p\n", this);
+ if(this->data == this->preloaded_data) {
+ printf("\tNot completely loaded - skipping %p\n", this);
+ return;
+ }
+
+ mutex.lock();
+ sample_t* old_data = data;
+ this->size = SIZE;
+ this->data = this->preloaded_data;
+// if() {
+ printf("Deleting data %p\n", this);
+ delete old_data;
+// }
+ mutex.unlock();
}
void AudioFile::load()
{
+#ifdef LAZYLOAD
+ init();
+ return;
+#endif
+
if(data) return;
SF_INFO sf_info;
@@ -78,11 +187,14 @@ void AudioFile::load()
printf("SNDFILE Error (%s): %s\n", filename.c_str(), sf_strerror(fh));
return;
}
-
+
size = sf_info.frames;
+
data = new sample_t[size];
- sf_read_float(fh, data, size);
+ size = sf_read_float(fh, data, size);
+
+ printf("Loaded %d samples %p\n", size, this);
sf_close(fh);
diff --git a/src/audiofile.h b/src/audiofile.h
index e4b8410..d203781 100644
--- a/src/audiofile.h
+++ b/src/audiofile.h
@@ -29,10 +29,44 @@
#include <string>
#include <map>
+#include <vector>
+
+#include <sndfile.h>
#include "mutex.h"
#include "audio.h"
+#if 0
+ Plan for lazy loading of audio (Brainstorming)
+ * Encapsulate data array?
+ - Speed issues?
+ - Other suggestion
+ * Trigger on read begin and read done
+ - readnext(instrument)?
+ * size_t current latest loaded sample
+ * run in own thread? threads in drumgizmo??
+ - Add soundfile-loader-class which run in its own thread
+ * Add pre-loading constant
+ * Pointer to pos in audio stream (maybe just last position read)
+ * Strategy for how to handle pre-loading of remaining file
+ - Is it acceptable only to handle sequential reading of data (no random access)?
+
+ Thread A Thread B
+
+ :preload constant (user defined)
+ :speed modifier constant (in which time must
+ sample n be loaded relative to trigger time)
+ ---------- ------
+ | Loader | <------- Trigger load of InstrumentSample n --------- | DG |
+ ---------- ------
+ Load (int- right most loaded sample --> If current sample pos loaded
+ | --------- | |
+ Wave Into --> | SndFile | <----- Read data (directly from array)
+ ---------
+#endif/*0*/
+
+#define LAZYLOAD
+
class AudioFile {
public:
AudioFile(std::string filename);
@@ -43,12 +77,25 @@ public:
bool isLoaded();
- sample_t *data;
size_t size;
+
+ sample_t *data;
std::string filename;
+ bool locked;
+#ifdef LAZYLOAD
+ SF_INFO sf_info;
+ SNDFILE *fh;
+ bool completely_loaded;
+ void init();
+ void reset();
+ void loadNext();
+ sample_t* preloaded_data;
+#endif/*LAZYLOAD*/
+
bool isValid();
+ int ref_count;
private:
void *magic;
diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc
index 72b3811..df2fd31 100644
--- a/src/drumgizmo.cc
+++ b/src/drumgizmo.cc
@@ -331,6 +331,10 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples)
while(j != kit.channels.end()) {
Channel &ch = *j;
AudioFile *af = s->getAudioFile(&ch);
+ if(af) {
+ printf("Requesting preparing of audio file\n");
+ loader.prepare(af);
+ }
if(af == NULL || !af->isValid()) {
//printf("Missing AudioFile.\n");
} else {
@@ -364,6 +368,7 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples)
}
if(buf) {
memset(buf, 0, nsamples * sizeof(sample_t));
+
getSamples(c, pos, buf, nsamples);
if(!internal) oe->run(c, samples, nsamples);
}
@@ -426,8 +431,9 @@ void DrumGizmo::getSamples(int ch, int pos, sample_t *s, size_t sz)
if(evt->rampdown == NO_RAMPDOWN) {
#ifdef SSE
- size_t optend = ((end - n) / N) * N + n;
- for(; n < optend; n += N) {
+// printf("%d\n", evt->t); fflush(stdout);
+ size_t optend = ((end - n) / N) * N + n;
+ for(; n < optend; n += N) {
*(vNsf*)&(s[n]) += *(vNsf*)&(af->data[evt->t]);
evt->t += N;
}
@@ -446,7 +452,10 @@ void DrumGizmo::getSamples(int ch, int pos, sample_t *s, size_t sz)
}
- if(evt->t >= af->size) removeevent = true;
+ if(evt->t >= af->size) {
+ removeevent = true;
+ loader.reset(af);
+ }
}
break;
}
diff --git a/src/drumkitloader.cc b/src/drumkitloader.cc
index 79d000a..6516c7d 100644
--- a/src/drumkitloader.cc
+++ b/src/drumkitloader.cc
@@ -82,14 +82,40 @@ void DrumKitLoader::loadKit(DrumKit *kit)
semaphore.post();
}
+void DrumKitLoader::prepare(AudioFile* af) {
+ printf("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();
+}
+
+void DrumKitLoader::reset(AudioFile* af) {
+ mutex.lock();
+ af->ref_count--;
+ reset_queue.push_back(af);
+ mutex.unlock();
+ semaphore.post();
+}
+
void DrumKitLoader::thread_main()
{
while(1) {
DEBUG(loader, "before sem\n");
+
semaphore.wait();
+
DEBUG(loader, "after sem\n");
fflush(stdout);
+
if(quitit) return;
if(skipit) {
@@ -98,66 +124,88 @@ void DrumKitLoader::thread_main()
continue;
}
- unsigned int count = 0;
+ if(!load_queue.empty()) {
+ printf("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();
+ }
+ else { // Initialize drum kit
+ printf("Initializing drum kit\n");
+ unsigned int count = 0;
- if(kit && !kit->isValid()) goto finish;
+ 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;
+ { // 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;
- count += instr->audiofiles.size();
- i++;
+ 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;
+ { // 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;
+ if(instr && !instr->isValid()) goto finish;
- std::vector<AudioFile*>::iterator a = instr->audiofiles.begin();
- while(a != instr->audiofiles.end()) {
+ 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;
+ AudioFile *af = *a;
- if(af && !af->isValid()) goto finish;
+ if(af && !af->isValid()) goto finish;
- af->load();
- loaded++;
+ af->load();
+
+ loaded++;
- LoadStatusMessage *ls = new LoadStatusMessage();
- ls->number_of_files = count;
- ls->numer_of_files_loaded = loaded;
- ls->current_file = af->filename;
- drumgizmo->sendGUIMessage(ls);
+ LoadStatusMessage *ls = new LoadStatusMessage();
+ ls->number_of_files = count;
+ ls->numer_of_files_loaded = loaded;
+ ls->current_file = af->filename;
+ drumgizmo->sendGUIMessage(ls);
- a++;
+ a++;
- if(skipit) goto finish;
- }
+ if(skipit) goto finish;
+ }
- i++;
+ i++;
+ }
}
- }
- mutex.lock();
- is_done = true;
- mutex.unlock();
+ mutex.lock();
+ is_done = true;
+ mutex.unlock();
- finish:
- continue;
+ finish:
+ continue;
+ }
}
}
diff --git a/src/drumkitloader.h b/src/drumkitloader.h
index 50b8236..9d14638 100644
--- a/src/drumkitloader.h
+++ b/src/drumkitloader.h
@@ -28,6 +28,7 @@
#define __DRUMGIZMO_DRUMKITLOADER_H__
#include <string>
+#include <list>
#include "thread.h"
#include "semaphore.h"
@@ -43,6 +44,9 @@ public:
~DrumKitLoader();
void loadKit(DrumKit *kit);
+
+ void prepare(AudioFile* af);
+ void reset(AudioFile* af);
void thread_main();
@@ -60,6 +64,9 @@ private:
Mutex mutex;
volatile bool quitit;
volatile bool skipit;
+ std::list<AudioFile*> load_queue;
+ std::list<AudioFile*> reset_queue;
+ std::map<AudioFile*, int> ref_count;
};
#endif/*__DRUMGIZMO_DRUMKITLOADER_H__*/