summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2016-01-28 14:58:41 +0100
committerBent Bisballe Nyeng <deva@aasimon.org>2016-01-28 14:58:41 +0100
commit413c0703722835e48b98b85b8ded32f1f43555bb (patch)
tree9d195d00c020ed96e1a5ad2a10ed8e044d7623a9 /src
parent2087facd3727c52069ad65c5b791f24cba3101a2 (diff)
Style fixes
Diffstat (limited to 'src')
-rw-r--r--src/audiofile.cc279
-rw-r--r--src/audiofile.h74
-rw-r--r--src/drumgizmo.cc1264
-rw-r--r--src/drumgizmo.h62
-rw-r--r--src/drumkitloader.cc231
-rw-r--r--src/drumkitloader.h87
6 files changed, 879 insertions, 1118 deletions
diff --git a/src/audiofile.cc b/src/audiofile.cc
index 5ceff59..e9b5976 100644
--- a/src/audiofile.cc
+++ b/src/audiofile.cc
@@ -38,225 +38,116 @@
#include "configuration.h"
-AudioFile::AudioFile(std::string filename, int filechannel)
+AudioFile::AudioFile(const std::string& filename, int filechannel)
{
- is_loaded = false;
- this->filename = filename;
- this->filechannel = filechannel;
+ is_loaded = false;
+ this->filename = filename;
+ this->filechannel = filechannel;
- data = NULL;
- size = 0;
+ data = nullptr;
+ size = 0;
-#ifdef LAZYLOAD
- preloaded_data = NULL;
-#endif/*LAZYLOAD*/
-
- magic = this;
+ magic = this;
}
AudioFile::~AudioFile()
{
- magic = NULL;
- unload();
+ magic = nullptr;
+ unload();
}
bool AudioFile::isValid()
{
- return this == magic;
+ return this == magic;
}
void AudioFile::unload()
{
- // Make sure we don't unload the object while loading it...
- MutexAutolock l(mutex);
+ // Make sure we don't unload the object while loading it...
+ MutexAutolock l(mutex);
- is_loaded = false;
+ is_loaded = false;
-#ifdef LAZYLOAD
- if(data == preloaded_data) {
- delete[] data;
- data = NULL;
- size = 0;
- } else {
- size = 0;
- delete[] data;
- data = NULL;
- delete preloaded_data;
- preloaded_data = NULL;
- }
-#else
- delete[] data;
- data = NULL;
- size = 0;
-#endif/*LAZYLOAD*/
+ delete[] data;
+ data = nullptr;
+ size = 0;
}
#define BUFFER_SIZE 4092
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;
- }
-
- if(num_samples == ALL_SAMPLES) {
- num_samples = sf_info.frames;
- }
-
- size = sf_info.frames;
- preloadedsize = sf_info.frames;
-
- if(preloadedsize > (size_t)num_samples) {
- preloadedsize = num_samples;
- }
-
- sample_t* data = new sample_t[preloadedsize];
- if(sf_info.channels == 1) {
- preloadedsize = sf_read_float(fh, data, preloadedsize);
- } else {
- // check filechannel exists
- if(filechannel >= sf_info.channels) {
- filechannel = sf_info.channels - 1;
- }
- sample_t buffer[BUFFER_SIZE];
- int readsize = BUFFER_SIZE / sf_info.channels;
- int totalread = 0;
- int read;
- do {
- read = sf_readf_float(fh, buffer, readsize);
- for (int i = 0; (i < read) && (totalread < num_samples); i++) {
- data[totalread++] = buffer[i * sf_info.channels + filechannel];
- }
- } while( (read > 0) &&
- (totalread < (int)preloadedsize) &&
- (totalread < num_samples) );
- // set data size to total bytes read
- preloadedsize = totalread;
- }
-
- DEBUG(audiofile,"Loaded %d samples %p\n", (int)preloadedsize, this);
-
- sf_close(fh);
-
- this->data = data;
- is_loaded = true;
-
- //DEBUG(audiofile, "Loading of %s completed.\n", filename.c_str());
+ // Make sure we don't unload the object while loading it...
+ MutexAutolock l(mutex);
+
+ 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;
+ }
+
+ if(num_samples == ALL_SAMPLES)
+ {
+ num_samples = sf_info.frames;
+ }
+
+ size = sf_info.frames;
+ preloadedsize = sf_info.frames;
+
+ if(preloadedsize > (size_t)num_samples)
+ {
+ preloadedsize = num_samples;
+ }
+
+ sample_t* data = new sample_t[preloadedsize];
+ if(sf_info.channels == 1)
+ {
+ preloadedsize = sf_read_float(fh, data, preloadedsize);
+ }
+ else
+ {
+ // check filechannel exists
+ if(filechannel >= sf_info.channels)
+ {
+ filechannel = sf_info.channels - 1;
+ }
+
+ sample_t buffer[BUFFER_SIZE];
+ int readsize = BUFFER_SIZE / sf_info.channels;
+ int totalread = 0;
+ int read;
+
+ do
+ {
+ read = sf_readf_float(fh, buffer, readsize);
+ for(int i = 0; (i < read) && (totalread < num_samples); ++i)
+ {
+ data[totalread++] = buffer[i * sf_info.channels + filechannel];
+ }
+ }
+ while( (read > 0) &&
+ (totalread < (int)preloadedsize) &&
+ (totalread < num_samples) );
+
+ // set data size to total bytes read
+ preloadedsize = totalread;
+ }
+
+ sf_close(fh);
+
+ this->data = data;
+ is_loaded = true;
}
bool AudioFile::isLoaded()
{
- return is_loaded;
-}
-
-#ifdef LAZYLOAD
-#define SIZE 512*4
-void AudioFile::init()
-{
- //DEBUG(audiofile,"Initializing %p\n", this);
- if(data) {
- //DEBUG(audiofile,"\t already initialized\n");
- 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;
- }
-
- int size = SIZE;
-
- sample_t* data = new sample_t[size];
-
- size = sf_read_float(fh, data, size);
-
- //DEBUG(audiofile,"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;
- mutex.unlock();
-}
-
-void AudioFile::loadNext()
-{
- if(this->data != this->preloaded_data) {
- //DEBUG(audiofile,"Already completely loaded %p\n", this);
- 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;
- }
-
- int r;
-// int size_accum = 0;
- sample_t* data = new sample_t[sf_info.frames];
- memcpy(data, this->preloaded_data, this->size * sizeof(sample_t));
- this->data = data;
- sf_seek(fh, this->size, SEEK_SET);
-// sample_t* data_buf = new sample_t[SIZE];
- while(this->size < sf_info.frames) {
- //DEBUG(audiofile,"Accumulated %d of %llu\n", size_accum, sf_info.frames);
- //if( (r = sf_read_float(fh, data_buf, SIZE)) < 0) {
- if( (r = sf_read_float(fh, &data[this->size], SIZE)) < 0) {
- ERR(audiofile,"Error reading sound file\n");
- break;
- }
- //size_accum += r;
- //memcpy(data+size_accum, data_buf, sizeof(sample_t) * r);
- this->size += r;
- }
- //delete data_buf;
-
- //DEBUG(audiofile,"Finished loading %d samples %p\n", size, this);
- sf_close(fh);
-
- //mutex.lock();
- //this->data = data;
- //this->size = size;
- //mutex.unlock();
-}
-
-void AudioFile::reset()
-{
- //DEBUG(audiofile,"Resetting audio file %p\n", this);
- if(this->data == this->preloaded_data) {
- //DEBUG(audiofile,"\tNot completely loaded - skipping %p\n", this);
- return;
- }
-
- mutex.lock();
- volatile sample_t* old_data = data;
- this->size = SIZE;
- this->data = this->preloaded_data;
- //DEBUG(audiofile,"Deleting data %p\n", this);
- delete old_data;
- mutex.unlock();
+ return is_loaded;
}
-#endif
diff --git a/src/audiofile.h b/src/audiofile.h
index aefb8d6..3ca8b97 100644
--- a/src/audiofile.h
+++ b/src/audiofile.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_AUDIOFILE_H__
-#define __DRUMGIZMO_AUDIOFILE_H__
+#pragma once
#include <string>
#include <map>
@@ -36,74 +35,31 @@
#include "mutex.h"
#include "audio.h"
-/*
- 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)
- ---------
-*/
-
-//#define LAZYLOAD
-
#define ALL_SAMPLES -1
class AudioFile {
public:
- AudioFile(std::string filename, int filechannel);
- ~AudioFile();
-
- void load(int num_samples = ALL_SAMPLES);
- void unload();
+ AudioFile(const std::string& filename, int filechannel);
+ ~AudioFile();
- bool isLoaded();
+ void load(int num_samples = ALL_SAMPLES);
+ void unload();
- volatile size_t size; // Full size of the file
- volatile size_t preloadedsize; // Number of samples preloaded (in data)
- sample_t *data;
+ bool isLoaded();
- std::string filename;
+ volatile size_t size{0}; // Full size of the file
+ volatile size_t preloadedsize{0}; // Number of samples preloaded (in data)
+ sample_t *data{nullptr};
-#ifdef LAZYLOAD
-// SF_INFO sf_info;
-// SNDFILE *fh;
-// bool completely_loaded;
- void init();
- void reset();
- void loadNext();
- sample_t* preloaded_data;
-#endif/*LAZYLOAD*/
+ std::string filename;
- bool isValid();
+ bool isValid();
- Mutex mutex;
+ Mutex mutex;
- int filechannel;
+ int filechannel;
private:
- void *magic;
- volatile bool is_loaded;
+ void *magic;
+ volatile bool is_loaded;
};
-
-#endif/*__DRUMGIZMO_AUDIOFILE_H__*/
diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc
index 3dc1306..26b8e65 100644
--- a/src/drumgizmo.cc
+++ b/src/drumgizmo.cc
@@ -46,346 +46,403 @@
#include "nolocale.h"
DrumGizmo::DrumGizmo(AudioOutputEngine *o, AudioInputEngine *i)
- : MessageReceiver(MSGRCV_ENGINE)
- , loader()
- , oe(o)
- , ie(i)
- , framesize(0)
- , freewheel(false)
+ : MessageReceiver(MSGRCV_ENGINE)
+ , loader()
+ , oe(o)
+ , ie(i)
+ , framesize(0)
+ , freewheel(false)
{
- is_stopping = false;
- audioCache.init(1000); // start thread
+ is_stopping = false;
+ audioCache.init(1000); // start thread
}
DrumGizmo::~DrumGizmo()
{
- audioCache.deinit(); // stop thread
+ audioCache.deinit(); // stop thread
}
bool DrumGizmo::loadkit(std::string file)
{
- if(file == "") return 1;
+ if(file == "")
+ {
+ return 1;
+ }
- DEBUG(drumgizmo, "loadkit(%s)\n", file.c_str());
+ DEBUG(drumgizmo, "loadkit(%s)\n", file.c_str());
- // Remove all queue AudioFiles from loader before we actually delete them.
- loader.skip();
+ // Remove all queue AudioFiles from loader before we actually delete them.
+ loader.skip();
- // Delete all Channels, Instruments, Samples and AudioFiles.
- kit.clear();
+ // Delete all Channels, Instruments, Samples and AudioFiles.
+ kit.clear();
- DrumKitParser parser(file, kit);
- if(parser.parse()) {
- ERR(drumgizmo, "Drumkit parser failed: %s\n", file.c_str());
- return false;
- }
+ DrumKitParser parser(file, kit);
+ if(parser.parse())
+ {
+ ERR(drumgizmo, "Drumkit parser failed: %s\n", file.c_str());
+ return false;
+ }
- loader.loadKit(&kit);
+ loader.loadKit(&kit);
#ifdef WITH_RESAMPLER
- for(int i = 0; i < MAX_NUM_CHANNELS; i++) {
- resampler[i].setup(kit.samplerate(), Conf::samplerate);
- }
+ for(int i = 0; i < MAX_NUM_CHANNELS; ++i)
+ {
+ resampler[i].setup(kit.samplerate(), Conf::samplerate);
+ }
#endif/*WITH_RESAMPLER*/
- DEBUG(loadkit, "loadkit: Success\n");
+ DEBUG(loadkit, "loadkit: Success\n");
- return true;
+ return true;
}
bool DrumGizmo::init()
{
- if(!ie->init(kit.instruments)) return false;
- if(!oe->init(kit.channels)) return false;
+ if(!ie->init(kit.instruments))
+ {
+ return false;
+ }
- return true;
+ if(!oe->init(kit.channels))
+ {
+ return false;
+ }
+
+ return true;
}
void DrumGizmo::handleMessage(Message *msg)
{
- DEBUG(msg, "got message.");
- switch(msg->type()) {
- case Message::LoadDrumKit:
- {
- DEBUG(msg, "got LoadDrumKitMessage message.");
- LoadDrumKitMessage *m = (LoadDrumKitMessage*)msg;
- loadkit(m->drumkitfile);
- //init(true);
- }
- break;
- case Message::LoadMidimap:
- DEBUG(msg, "got LoadMidimapMessage message.");
- if(!ie->isMidiEngine()) break;
- {
- AudioInputEngineMidi *aim = (AudioInputEngineMidi*)ie;
- LoadMidimapMessage *m = (LoadMidimapMessage*)msg;
- bool ret = aim->loadMidiMap(m->midimapfile, kit.instruments);
-
- LoadStatusMessageMidimap *ls = new LoadStatusMessageMidimap();
- ls->success = ret;
- msghandler.sendMessage(MSGRCV_UI, ls);
- }
- break;
- case Message::EngineSettingsMessage:
- {
- bool mmap_loaded = false;
- std::string mmapfile;
- if(ie->isMidiEngine()) {
- AudioInputEngineMidi *aim = (AudioInputEngineMidi*)ie;
- mmapfile = aim->midimapFile();
- mmap_loaded = aim->isValid();
- }
-
- EngineSettingsMessage *msg = new EngineSettingsMessage();
- msg->midimapfile = mmapfile;
- msg->midimap_loaded = mmap_loaded;
- msg->drumkitfile = kit.file();
- msg->drumkit_loaded = loader.isDone();
- msg->enable_velocity_modifier = Conf::enable_velocity_modifier;
- msg->velocity_modifier_falloff = Conf::velocity_modifier_falloff;
- msg->velocity_modifier_weight = Conf::velocity_modifier_weight;
- msg->enable_velocity_randomiser = Conf::enable_velocity_randomiser;
- msg->velocity_randomiser_weight = Conf::velocity_randomiser_weight;
- msghandler.sendMessage(MSGRCV_UI, msg);
- }
- break;
- case Message::ChangeSettingMessage:
- {
- ChangeSettingMessage *ch = (ChangeSettingMessage*)msg;
- switch(ch->name) {
- case ChangeSettingMessage::enable_velocity_modifier:
- Conf::enable_velocity_modifier = ch->value;
- break;
- case ChangeSettingMessage::velocity_modifier_weight:
- Conf::velocity_modifier_weight = ch->value;
- break;
- case ChangeSettingMessage::velocity_modifier_falloff:
- Conf::velocity_modifier_falloff = ch->value;
- break;
- }
- }
- break;
- default:
- break;
- }
+ DEBUG(msg, "got message.");
+ switch(msg->type()) {
+ case Message::LoadDrumKit:
+ {
+ DEBUG(msg, "got LoadDrumKitMessage message.");
+ LoadDrumKitMessage *m = (LoadDrumKitMessage*)msg;
+ loadkit(m->drumkitfile);
+ //init(true);
+ }
+ break;
+ case Message::LoadMidimap:
+ DEBUG(msg, "got LoadMidimapMessage message.");
+ if(!ie->isMidiEngine())
+ {
+ break;
+ }
+ {
+ AudioInputEngineMidi *aim = (AudioInputEngineMidi*)ie;
+ LoadMidimapMessage *m = (LoadMidimapMessage*)msg;
+ bool ret = aim->loadMidiMap(m->midimapfile, kit.instruments);
+
+ LoadStatusMessageMidimap *ls = new LoadStatusMessageMidimap();
+ ls->success = ret;
+ msghandler.sendMessage(MSGRCV_UI, ls);
+ }
+ break;
+ case Message::EngineSettingsMessage:
+ {
+ bool mmap_loaded = false;
+ std::string mmapfile;
+ if(ie->isMidiEngine())
+ {
+ AudioInputEngineMidi *aim = (AudioInputEngineMidi*)ie;
+ mmapfile = aim->midimapFile();
+ mmap_loaded = aim->isValid();
+ }
+
+ EngineSettingsMessage *msg = new EngineSettingsMessage();
+ msg->midimapfile = mmapfile;
+ msg->midimap_loaded = mmap_loaded;
+ msg->drumkitfile = kit.file();
+ msg->drumkit_loaded = loader.isDone();
+ msg->enable_velocity_modifier = Conf::enable_velocity_modifier;
+ msg->velocity_modifier_falloff = Conf::velocity_modifier_falloff;
+ msg->velocity_modifier_weight = Conf::velocity_modifier_weight;
+ msg->enable_velocity_randomiser = Conf::enable_velocity_randomiser;
+ msg->velocity_randomiser_weight = Conf::velocity_randomiser_weight;
+ msghandler.sendMessage(MSGRCV_UI, msg);
+ }
+ break;
+ case Message::ChangeSettingMessage:
+ {
+ ChangeSettingMessage *ch = (ChangeSettingMessage*)msg;
+ switch(ch->name) {
+ case ChangeSettingMessage::enable_velocity_modifier:
+ Conf::enable_velocity_modifier = ch->value;
+ break;
+ case ChangeSettingMessage::velocity_modifier_weight:
+ Conf::velocity_modifier_weight = ch->value;
+ break;
+ case ChangeSettingMessage::velocity_modifier_falloff:
+ Conf::velocity_modifier_falloff = ch->value;
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
}
void DrumGizmo::setFrameSize(size_t framesize)
{
- // If we are resampling override the frame size.
- if(resampler[0].ratio() != 1) {
- framesize = RESAMPLER_INPUT_BUFFER;
- }
-
- if(this->framesize != framesize) {
- DEBUG(drumgizmo, "New framesize: %d\n", (int)framesize);
-
- this->framesize = framesize;
-
- // Update framesize in drumkitloader and cachemanager:
- loader.setFrameSize(framesize);
- audioCache.setFrameSize(framesize);
- }
+ // If we are resampling override the frame size.
+ if(resampler[0].ratio() != 1)
+ {
+ framesize = RESAMPLER_INPUT_BUFFER;
+ }
+
+ if(this->framesize != framesize)
+ {
+ DEBUG(drumgizmo, "New framesize: %d\n", (int)framesize);
+
+ this->framesize = framesize;
+
+ // Update framesize in drumkitloader and cachemanager:
+ loader.setFrameSize(framesize);
+ audioCache.setFrameSize(framesize);
+ }
}
void DrumGizmo::setFreeWheel(bool freewheel)
{
- // Freewheel = true means that we are bouncing and therefore running faster
- // than realtime.
- if(freewheel != this->freewheel) {
- this->freewheel = freewheel;
- audioCache.setAsyncMode(!freewheel);
- }
+ // Freewheel = true means that we are bouncing and therefore running faster
+ // than realtime.
+ if(freewheel != this->freewheel)
+ {
+ this->freewheel = freewheel;
+ audioCache.setAsyncMode(!freewheel);
+ }
}
bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples)
{
- setFrameSize(nsamples);
-
- // Handle engine messages, at most one in each iteration:
- handleMessages(1);
-
- ie->pre();
- oe->pre(nsamples);
-
- //
- // Read new events
- //
-
- //DEBUG(engine, "Number of active events: %d\n", activeevents[0].size());
-
- size_t nev;
- event_t *evs = ie->run(pos, nsamples, &nev);
-
- for(size_t e = 0; e < nev; e++) {
- if(evs[e].type == TYPE_ONSET) {
- Instrument *i = NULL;
- int d = evs[e].instrument;
- /*
- Instruments::iterator it = kit.instruments.begin();
- while(d-- && it != kit.instruments.end()) {
- i = &(it->second);
- it++;
- }
- */
-
- if(!kit.isValid()) continue;
-
- if(d < (int)kit.instruments.size()) {
- i = kit.instruments[d];
- }
-
- if(i == NULL || !i->isValid()) {
- ERR(drumgizmo, "Missing Instrument %d.\n", evs[e].instrument);
- continue;
- }
-
- if(i->group() != "") {
- // Add event to ramp down all existing events with the same groupname.
- Channels::iterator j = kit.channels.begin();
- while(j != kit.channels.end()) {
- Channel &ch = *j;
- std::list< Event* >::iterator evs = activeevents[ch.num].begin();
- while(evs != activeevents[ch.num].end()) {
- Event *ev = *evs;
- if(ev->type() == Event::sample) {
- EventSample *sev = (EventSample*)ev;
- if(sev->group == i->group() && sev->instrument != i) {
- sev->rampdown = 3000; // Ramp down 3000 samples
- // TODO: This must be configurable at some point...
- // ... perhaps even by instrument (ie. in the xml file)
- sev->ramp_start = sev->rampdown;
- }
- }
- evs++;
- }
- j++;
- }
- }
-
- Sample *s = i->sample(evs[e].velocity, evs[e].offset + pos);
-
- if(s == NULL) {
- ERR(drumgizmo, "Missing Sample.\n");
- continue;
- }
-
- Channels::iterator j = kit.channels.begin();
- while(j != kit.channels.end()) {
- Channel &ch = *j;
- AudioFile *af = s->getAudioFile(&ch);
- if(af) {
- // LAZYLOAD:
- // DEBUG(drumgizmo,"Requesting preparing of audio file\n");
- // loader.prepare(af);
- }
- if(af == NULL || !af->isValid()) {
- //DEBUG(drumgizmo,"Missing AudioFile.\n");
- } else {
- //DEBUG(drumgizmo, "Adding event %d.\n", evs[e].offset);
- Event *evt = new EventSample(ch.num, 1.0, af, i->group(), i);
- evt->offset = (evs[e].offset + pos) * resampler[0].ratio();
- activeevents[ch.num].push_back(evt);
- }
- j++;
- }
- }
-
- if(evs[e].type == TYPE_STOP) {
- is_stopping = true;
- }
-
- if(is_stopping) {
- // Count the number of active events.
- int num_active_events = 0;
- Channels::iterator j = kit.channels.begin();
- while(j != kit.channels.end()) {
- Channel &ch = *j;
- num_active_events += activeevents[ch.num].size();
- j++;
- }
-
- if(num_active_events == 0) {
- // No more active events - now we can stop the engine.
- return false;
- }
- }
-
- }
-
- free(evs);
-
- //
- // Write audio
- //
+ setFrameSize(nsamples);
+
+ // Handle engine messages, at most one in each iteration:
+ handleMessages(1);
+
+ ie->pre();
+ oe->pre(nsamples);
+
+ //
+ // Read new events
+ //
+
+ //DEBUG(engine, "Number of active events: %d\n", activeevents[0].size());
+
+ size_t nev;
+ event_t *evs = ie->run(pos, nsamples, &nev);
+
+ for(size_t e = 0; e < nev; ++e)
+ {
+ if(evs[e].type == TYPE_ONSET)
+ {
+ Instrument *i = nullptr;
+ int d = evs[e].instrument;
+ /*
+ Instruments::iterator it = kit.instruments.begin();
+ while(d-- && it != kit.instruments.end())
+ {
+ i = &(it->second);
+ ++it;
+ }
+ */
+
+ if(!kit.isValid())
+ {
+ continue;
+ }
+
+ if(d < (int)kit.instruments.size())
+ {
+ i = kit.instruments[d];
+ }
+
+ if(i == nullptr || !i->isValid())
+ {
+ ERR(drumgizmo, "Missing Instrument %d.\n", evs[e].instrument);
+ continue;
+ }
+
+ if(i->group() != "")
+ {
+ // Add event to ramp down all existing events with the same groupname.
+ Channels::iterator j = kit.channels.begin();
+ while(j != kit.channels.end())
+ {
+ Channel &ch = *j;
+ std::list< Event* >::iterator evs = activeevents[ch.num].begin();
+ while(evs != activeevents[ch.num].end())
+ {
+ Event *ev = *evs;
+ if(ev->type() == Event::sample)
+ {
+ EventSample *sev = (EventSample*)ev;
+ if(sev->group == i->group() && sev->instrument != i)
+ {
+ sev->rampdown = 3000; // Ramp down 3000 samples
+ // TODO: This must be configurable at some point...
+ // ... perhaps even by instrument (ie. in the xml file)
+ sev->ramp_start = sev->rampdown;
+ }
+ }
+ ++evs;
+ }
+ ++j;
+ }
+ }
+
+ Sample *s = i->sample(evs[e].velocity, evs[e].offset + pos);
+
+ if(s == nullptr)
+ {
+ ERR(drumgizmo, "Missing Sample.\n");
+ continue;
+ }
+
+ Channels::iterator j = kit.channels.begin();
+ while(j != kit.channels.end())
+ {
+ Channel &ch = *j;
+ AudioFile *af = s->getAudioFile(&ch);
+ if(af)
+ {
+ // LAZYLOAD:
+ // DEBUG(drumgizmo,"Requesting preparing of audio file\n");
+ // loader.prepare(af);
+ }
+ if(af == nullptr || !af->isValid())
+ {
+ //DEBUG(drumgizmo,"Missing AudioFile.\n");
+ }
+ else
+ {
+ //DEBUG(drumgizmo, "Adding event %d.\n", evs[e].offset);
+ Event *evt = new EventSample(ch.num, 1.0, af, i->group(), i);
+ evt->offset = (evs[e].offset + pos) * resampler[0].ratio();
+ activeevents[ch.num].push_back(evt);
+ }
+ ++j;
+ }
+ }
+
+ if(evs[e].type == TYPE_STOP)
+ {
+ is_stopping = true;
+ }
+
+ if(is_stopping)
+ {
+ // Count the number of active events.
+ int num_active_events = 0;
+ Channels::iterator j = kit.channels.begin();
+ while(j != kit.channels.end())
+ {
+ Channel &ch = *j;
+ num_active_events += activeevents[ch.num].size();
+ ++j;
+ }
+
+ if(num_active_events == 0)
+ {
+ // No more active events - now we can stop the engine.
+ return false;
+ }
+ }
+
+ }
+
+ free(evs);
+
+ //
+ // Write audio
+ //
#ifdef WITH_RESAMPLER
- if(Conf::enable_resampling == false ||
- resampler[0].ratio() == 1.0) { // No resampling needed
+ if((Conf::enable_resampling == false) ||
+ (resampler[0].ratio() == 1.0)) // No resampling needed
+ {
#endif
- for(size_t c = 0; c < kit.channels.size(); c++) {
- sample_t *buf = samples;
- bool internal = false;
- if(oe->getBuffer(c)) {
- buf = oe->getBuffer(c);
- internal = true;
- }
- if(buf) {
- memset(buf, 0, nsamples * sizeof(sample_t));
-
- getSamples(c, pos, buf, nsamples);
-
- if(!internal) oe->run(c, samples, nsamples);
- }
- }
+ for(size_t c = 0; c < kit.channels.size(); ++c)
+ {
+ sample_t *buf = samples;
+ bool internal = false;
+ if(oe->getBuffer(c))
+ {
+ buf = oe->getBuffer(c);
+ internal = true;
+ }
+
+ if(buf)
+ {
+ memset(buf, 0, nsamples * sizeof(sample_t));
+
+ getSamples(c, pos, buf, nsamples);
+
+ if(!internal)
+ {
+ oe->run(c, samples, nsamples);
+ }
+ }
+ }
#ifdef WITH_RESAMPLER
- } else {
- // Resampling needed
-
- //
- // NOTE: Channels must be processed one buffer at a time on all channels in
- // parallel - NOT all buffers on one channel and then all buffer on the next
- // one since this would mess up the event queue (it would jump back and forth
- // in time)
- //
-
- // Prepare output buffer
- for(size_t c = 0; c < kit.channels.size(); c++) {
- resampler[c].setOutputSamples(resampler_output_buffer[c], nsamples);
- }
-
- // Process channel data
- size_t kitpos = pos * resampler[0].ratio();
- size_t insize = sizeof(resampler_input_buffer[0]) / sizeof(sample_t);
-
- while(resampler[0].getOutputSampleCount() > 0) {
- for(size_t c = 0; c < kit.channels.size(); c++) {
- if(resampler[c].getInputSampleCount() == 0) {
- sample_t *sin = resampler_input_buffer[c];
- memset(resampler_input_buffer[c], 0,
- sizeof(resampler_input_buffer[c]));
- getSamples(c, kitpos, sin, insize);
-
- resampler[c].setInputSamples(sin, insize);
- }
- resampler[c].process();
- }
- kitpos += insize;
- }
-
- // Write output data to output engine.
- for(size_t c = 0; c < kit.channels.size(); c++) {
- oe->run(c, resampler_output_buffer[c], nsamples);
- }
-
- }
+ }
+ else
+ {
+ // Resampling needed
+
+ //
+ // NOTE: Channels must be processed one buffer at a time on all channels in
+ // parallel - NOT all buffers on one channel and then all buffer on the next
+ // one since this would mess up the event queue (it would jump back and
+ // forth in time)
+ //
+
+ // Prepare output buffer
+ for(size_t c = 0; c < kit.channels.size(); ++c)
+ {
+ resampler[c].setOutputSamples(resampler_output_buffer[c], nsamples);
+ }
+
+ // Process channel data
+ size_t kitpos = pos * resampler[0].ratio();
+ size_t insize = sizeof(resampler_input_buffer[0]) / sizeof(sample_t);
+
+ while(resampler[0].getOutputSampleCount() > 0)
+ {
+ for(size_t c = 0; c < kit.channels.size(); ++c)
+ {
+ if(resampler[c].getInputSampleCount() == 0)
+ {
+ sample_t *sin = resampler_input_buffer[c];
+ memset(resampler_input_buffer[c], 0,
+ sizeof(resampler_input_buffer[c]));
+ getSamples(c, kitpos, sin, insize);
+
+ resampler[c].setInputSamples(sin, insize);
+ }
+ resampler[c].process();
+ }
+ kitpos += insize;
+ }
+
+ // Write output data to output engine.
+ for(size_t c = 0; c < kit.channels.size(); ++c)
+ {
+ oe->run(c, resampler_output_buffer[c], nsamples);
+ }
+
+ }
#endif/*WITH_RESAMPLER*/
-
- ie->post();
- oe->post(nsamples);
-
- pos += nsamples;
- return true;
+ ie->post();
+ oe->post(nsamples);
+
+ pos += nsamples;
+
+ return true;
}
#undef SSE // SSE broken for now ... so disable it.
@@ -396,423 +453,278 @@ typedef float vNsf __attribute__ ((vector_size(sizeof(sample_t)*N)));
void DrumGizmo::getSamples(int ch, int pos, sample_t *s, size_t sz)
{
- std::list< Event* >::iterator i = activeevents[ch].begin();
- for(; i != activeevents[ch].end(); ++i) {
- bool removeevent = false;
-
- Event *event = *i;
-
- Event::type_t type = event->type();
- switch(type) {
- case Event::sample:
- {
- EventSample *evt = (EventSample *)event;
- AudioFile *af = evt->file;
-
- if(!af->isLoaded() || !af->isValid() || s == NULL) {
- removeevent = true;
- break;
- }
-
- // Don't handle event now is is scheduled for a future iteration?
- if(evt->offset > (pos + sz)) {
- continue;
- }
-
- if(evt->cache_id == CACHE_NOID) {
- size_t initial_chunksize = (pos + sz) - evt->offset;
- evt->buffer = audioCache.open(af, initial_chunksize,
- af->filechannel, evt->cache_id);
- evt->buffer_size = initial_chunksize;
- }
-
- {
- MutexAutolock l(af->mutex);
-
- size_t n = 0; // default start point is 0.
-
- // If we are not at offset 0 in current buffer:
- if(evt->offset > (size_t)pos) {
- n = evt->offset - pos;
- }
-
- size_t end = sz; // default end point is the end of the buffer.
-
- // Find the end point intra-buffer
- if((evt->t + end - n) > af->size) {
- end = af->size - evt->t + n;
- }
-
- // This should not be necessary but make absolutely sure that we do
- // not write over the end of the buffer.
- if(end > sz) {
- end = sz;
- }
-
- size_t t = 0; // Internal buffer counter
- if(evt->rampdown == NO_RAMPDOWN) {
+ std::list< Event* >::iterator i = activeevents[ch].begin();
+ for(; i != activeevents[ch].end(); ++i)
+ {
+ bool removeevent = false;
+
+ Event *event = *i;
+
+ Event::type_t type = event->type();
+ switch(type) {
+ case Event::sample:
+ {
+ EventSample *evt = (EventSample *)event;
+ AudioFile *af = evt->file;
+
+ if(!af->isLoaded() || !af->isValid() || (s == nullptr))
+ {
+ removeevent = true;
+ break;
+ }
+
+ // Don't handle event now is is scheduled for a future iteration?
+ if(evt->offset > (pos + sz))
+ {
+ continue;
+ }
+
+ if(evt->cache_id == CACHE_NOID)
+ {
+ size_t initial_chunksize = (pos + sz) - evt->offset;
+ evt->buffer = audioCache.open(af, initial_chunksize,
+ af->filechannel, evt->cache_id);
+ evt->buffer_size = initial_chunksize;
+ }
+
+ {
+ MutexAutolock l(af->mutex);
+
+ size_t n = 0; // default start point is 0.
+
+ // If we are not at offset 0 in current buffer:
+ if(evt->offset > (size_t)pos)
+ {
+ n = evt->offset - pos;
+ }
+
+ size_t end = sz; // default end point is the end of the buffer.
+
+ // Find the end point intra-buffer
+ if((evt->t + end - n) > af->size)
+ {
+ end = af->size - evt->t + n;
+ }
+
+ // This should not be necessary but make absolutely sure that we do
+ // not write over the end of the buffer.
+ if(end > sz)
+ {
+ end = sz;
+ }
+
+ size_t t = 0; // Internal buffer counter
+ if(evt->rampdown == NO_RAMPDOWN)
+ {
#ifdef SSE
- size_t optend = ((end - n) / N) * N + n;
-
- // Force source addr to be 16 byte aligned... (might skip 1 or 2 samples)
- while((size_t)&evt->buffer[t] % 16) {
- ++t;
- }
-
- for(; (n < optend) && (t < evt->buffer_size); n += N) {
- *(vNsf*)&(s[n]) += *(vNsf*)&(evt->buffer[t]);
- t += N;
- }
+ size_t optend = ((end - n) / N) * N + n;
+
+ // Force source addr to be 16 byte aligned...
+ // (might skip 1 or 2 samples)
+ while((size_t)&evt->buffer[t] % 16)
+ {
+ ++t;
+ }
+
+ for(; (n < optend) && (t < evt->buffer_size); n += N)
+ {
+ *(vNsf*)&(s[n]) += *(vNsf*)&(evt->buffer[t]);
+ t += N;
+ }
#endif
- for(; (n < end) && (t < evt->buffer_size); n++) {
- s[n] += evt->buffer[t];
- t++;
- }
- } else { // Ramp down in progress.
- for(; (n < end) && (t < evt->buffer_size) && evt->rampdown; n++) {
- float scale = (float)evt->rampdown/(float)evt->ramp_start;
- s[n] += evt->buffer[t] * scale;
- t++;
- evt->rampdown--;
- }
- }
-
- evt->t += evt->buffer_size; // Add internal buffer counter to "global" event counter.
-
- if((evt->t < af->size) && (evt->rampdown != 0)) {
- evt->buffer = audioCache.next(evt->cache_id, evt->buffer_size);
- } else {
- removeevent = true;
- }
-
- if(removeevent) {
- audioCache.close(evt->cache_id);
- }
- }
- }
- break;
- }
-
- if(removeevent) {
- delete event;
- i = activeevents[ch].erase(i);
- continue;
- }
- }
+ for(; (n < end) && (t < evt->buffer_size); ++n)
+ {
+ s[n] += evt->buffer[t];
+ ++t;
+ }
+ }
+ else
+ { // Ramp down in progress.
+ for(; (n < end) && (t < evt->buffer_size) && evt->rampdown; ++n)
+ {
+ float scale = (float)evt->rampdown/(float)evt->ramp_start;
+ s[n] += evt->buffer[t] * scale;
+ ++t;
+ evt->rampdown--;
+ }
+ }
+
+ // Add internal buffer counter to "global" event counter.
+ evt->t += evt->buffer_size;
+
+ if((evt->t < af->size) && (evt->rampdown != 0))
+ {
+ evt->buffer = audioCache.next(evt->cache_id, evt->buffer_size);
+ }
+ else
+ {
+ removeevent = true;
+ }
+
+ if(removeevent)
+ {
+ audioCache.close(evt->cache_id);
+ }
+ }
+ }
+ break;
+ }
+
+ if(removeevent)
+ {
+ delete event;
+ i = activeevents[ch].erase(i);
+ continue;
+ }
+ }
}
void DrumGizmo::stop()
{
- // engine.stop();
+ // engine.stop();
}
int DrumGizmo::samplerate()
{
- return Conf::samplerate;
+ return Conf::samplerate;
}
void DrumGizmo::setSamplerate(int samplerate)
{
DEBUG(dgeditor, "%s samplerate: %d\n", __PRETTY_FUNCTION__, samplerate);
- Conf::samplerate = samplerate;
+ Conf::samplerate = samplerate;
#ifdef WITH_RESAMPLER
- for(int i = 0; i < MAX_NUM_CHANNELS; i++) {
- resampler[i].setup(kit.samplerate(), Conf::samplerate);
- }
- if(resampler[0].ratio() != 1) {
- setFrameSize(RESAMPLER_INPUT_BUFFER);
- }
+ for(int i = 0; i < MAX_NUM_CHANNELS; ++i)
+ {
+ resampler[i].setup(kit.samplerate(), Conf::samplerate);
+ }
+ if(resampler[0].ratio() != 1)
+ {
+ setFrameSize(RESAMPLER_INPUT_BUFFER);
+ }
#endif/*WITH_RESAMPLER*/
-
}
std::string float2str(float a)
{
- char buf[256];
- snprintf_nol(buf, sizeof(buf) - 1, "%f", a);
- return buf;
+ char buf[256];
+ snprintf_nol(buf, sizeof(buf) - 1, "%f", a);
+ return buf;
}
std::string bool2str(bool a)
{
- return a?"true":"false";
+ return a?"true":"false";
}
float str2float(std::string a)
{
- if(a == "") return 0.0;
- return atof_nol(a.c_str());
+ if(a == "")
+ {
+ return 0.0;
+ }
+
+ return atof_nol(a.c_str());
}
std::string DrumGizmo::configString()
{
- std::string mmapfile;
- if(ie->isMidiEngine()) {
- AudioInputEngineMidi *aim = (AudioInputEngineMidi*)ie;
- mmapfile = aim->midimapFile();
- }
-
- return
- "<config>\n"
- " <value name=\"drumkitfile\">" + kit.file() + "</value>\n"
- " <value name=\"midimapfile\">" + mmapfile + "</value>\n"
- " <value name=\"enable_velocity_modifier\">" +
- bool2str(Conf::enable_velocity_modifier) + "</value>\n"
- " <value name=\"velocity_modifier_falloff\">" +
- float2str(Conf::velocity_modifier_falloff) + "</value>\n"
- " <value name=\"velocity_modifier_weight\">" +
- float2str(Conf::velocity_modifier_weight) + "</value>\n"
- " <value name=\"enable_velocity_randomiser\">" +
- bool2str(Conf::enable_velocity_randomiser) + "</value>\n"
- " <value name=\"velocity_randomiser_weight\">" +
- float2str(Conf::velocity_randomiser_weight) + "</value>\n"
- "</config>";
+ std::string mmapfile;
+ if(ie->isMidiEngine())
+ {
+ AudioInputEngineMidi *aim = (AudioInputEngineMidi*)ie;
+ mmapfile = aim->midimapFile();
+ }
+
+ return
+ "<config>\n"
+ " <value name=\"drumkitfile\">" + kit.file() + "</value>\n"
+ " <value name=\"midimapfile\">" + mmapfile + "</value>\n"
+ " <value name=\"enable_velocity_modifier\">" +
+ bool2str(Conf::enable_velocity_modifier) + "</value>\n"
+ " <value name=\"velocity_modifier_falloff\">" +
+ float2str(Conf::velocity_modifier_falloff) + "</value>\n"
+ " <value name=\"velocity_modifier_weight\">" +
+ float2str(Conf::velocity_modifier_weight) + "</value>\n"
+ " <value name=\"enable_velocity_randomiser\">" +
+ bool2str(Conf::enable_velocity_randomiser) + "</value>\n"
+ " <value name=\"velocity_randomiser_weight\">" +
+ float2str(Conf::velocity_randomiser_weight) + "</value>\n"
+ "</config>";
}
-
bool DrumGizmo::setConfigString(std::string cfg)
{
- DEBUG(config, "Load config: %s\n", cfg.c_str());
-
- std::string dkf;
- ConfigParser p;
- if(p.parse(cfg)) {
- ERR(drumgizmo, "Config parse error.\n");
- return false;
- }
-
- if(p.value("enable_velocity_modifier") != "") {
- Conf::enable_velocity_modifier =
- p.value("enable_velocity_modifier") == "true";
- }
-
- if(p.value("velocity_modifier_falloff") != "") {
- Conf::velocity_modifier_falloff =
- str2float(p.value("velocity_modifier_falloff"));
- }
-
- if(p.value("velocity_modifier_weight") != "") {
- Conf::velocity_modifier_weight =
- str2float(p.value("velocity_modifier_weight"));
- }
-
- if(p.value("enable_velocity_randomiser") != "") {
- Conf::enable_velocity_randomiser =
- p.value("enable_velocity_randomiser") == "true";
- }
-
- if(p.value("velocity_randomiser_weight") != "") {
- Conf::velocity_randomiser_weight =
- str2float(p.value("velocity_randomiser_weight"));
- }
-
- if(p.value("enable_resampling") != "") {
- Conf::enable_resampling =
- p.value("enable_resampling") == "true";
- }
-
- std::string newkit = p.value("drumkitfile");
- if(newkit != "" && kit.file() != newkit) {
- /*
- if(!loadkit(p.values["drumkitfile"])) return false;
- init(true);
- */
- LoadDrumKitMessage *msg = new LoadDrumKitMessage();
- msg->drumkitfile = newkit;
- msghandler.sendMessage(MSGRCV_ENGINE, msg);
- }
-
- std::string newmidimap = p.value("midimapfile");
- if(newmidimap != "") {
- //midimapfile = newmidimap;
- LoadMidimapMessage *msg = new LoadMidimapMessage();
- msg->midimapfile = newmidimap;
- msghandler.sendMessage(MSGRCV_ENGINE, msg);
- }
-
- return true;
-}
-
-#ifdef TEST_DRUMGIZMO
-//deps: instrument.cc sample.cc channel.cc audiofile.cc drumkit.cc drumkitparser.cc configuration.cc saxparser.cc instrumentparser.cc path.cc
-//cflags: $(SNDFILE_CFLAGS) $(EXPAT_CFLAGS) -I../include -DSSE -msse -msse2 -msse3
-//libs: $(SNDFILE_LIBS) $(EXPAT_LIBS)
-#include "test.h"
-
-static float f(size_t x)
-{
- return x + 1.0;
+ DEBUG(config, "Load config: %s\n", cfg.c_str());
+
+ std::string dkf;
+ ConfigParser p;
+ if(p.parse(cfg))
+ {
+ ERR(drumgizmo, "Config parse error.\n");
+ return false;
+ }
+
+ if(p.value("enable_velocity_modifier") != "")
+ {
+ Conf::enable_velocity_modifier =
+ p.value("enable_velocity_modifier") == "true";
+ }
+
+ if(p.value("velocity_modifier_falloff") != "")
+ {
+ Conf::velocity_modifier_falloff =
+ str2float(p.value("velocity_modifier_falloff"));
+ }
+
+ if(p.value("velocity_modifier_weight") != "")
+ {
+ Conf::velocity_modifier_weight =
+ str2float(p.value("velocity_modifier_weight"));
+ }
+
+ if(p.value("enable_velocity_randomiser") != "")
+ {
+ Conf::enable_velocity_randomiser =
+ p.value("enable_velocity_randomiser") == "true";
+ }
+
+ if(p.value("velocity_randomiser_weight") != "")
+ {
+ Conf::velocity_randomiser_weight =
+ str2float(p.value("velocity_randomiser_weight"));
+ }
+
+ if(p.value("enable_resampling") != "")
+ {
+ Conf::enable_resampling =
+ p.value("enable_resampling") == "true";
+ }
+
+ std::string newkit = p.value("drumkitfile");
+ if(newkit != "" && kit.file() != newkit)
+ {
+ /*
+ if(!loadkit(p.values["drumkitfile"]))
+ {
+ return false;
+ }
+ init(true);
+ */
+ LoadDrumKitMessage *msg = new LoadDrumKitMessage();
+ msg->drumkitfile = newkit;
+ msghandler.sendMessage(MSGRCV_ENGINE, msg);
+ }
+
+ std::string newmidimap = p.value("midimapfile");
+ if(newmidimap != "")
+ {
+ //midimapfile = newmidimap;
+ LoadMidimapMessage *msg = new LoadMidimapMessage();
+ msg->midimapfile = newmidimap;
+ msghandler.sendMessage(MSGRCV_ENGINE, msg);
+ }
+
+ return true;
}
-
-class AITest : public AudioInputEngine {
-public:
- bool init(Instruments &instruments) { return true; }
- void setParm(std::string parm, std::string value) {}
- bool start() { return true; }
- void stop() {}
- void pre() {}
- event_t *run(size_t pos, size_t len, size_t *nevents)
- {
- event_t *e = NULL;
- *nevents = 0;
-
- if(pos <= offset && offset < pos + len) {
- e = new event_t;
-
- e->type = TYPE_ONSET;
- e->instrument = 0;
- e->velocity = 1.0;
- e->offset = offset - pos;
-
- *nevents = 1;
- }
- return e;
- }
- void post() {}
- size_t offset;
-};
-
-class AOTest : public AudioOutputEngine {
-public:
- bool init(Channels channels) { return true; }
- void setParm(std::string parm, std::string value) {}
- bool start() { return true; }
- void stop() {}
- void pre(size_t nsamples) {}
- void run(int ch, sample_t *samples, size_t nsamples)
- {
- }
- void post(size_t nsamples) {}
-};
-
-const char xml_kit[] =
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<drumkit name=\"test\" description=\"\">\n"
- " <channels>\n"
- " <channel name=\"ch1\"/>\n"
- " </channels>\n"
- " <instruments>\n"
- " <instrument name=\"instr1\" file=\"instr1.xml\">\n"
- " <channelmap in=\"ch1\" out=\"ch1\"/>\n"
- " </instrument>\n"
- " </instruments>\n"
- "</drumkit>";
-
-const char xml_instr[] =
- "<?xml version='1.0' encoding='UTF-8'?>\n"
- "<instrument name=\"instr1\">\n"
- " <samples>\n"
- " <sample name=\"sample1\">\n"
- " <audiofile channel=\"ch1\" file=\"instr1.wav\"/>\n"
- " </sample>\n"
- " </samples>\n"
- " <velocities>\n"
- " <velocity lower=\"0\" upper=\"1.0\">\n"
- " <sampleref name=\"sample1\"/>\n"
- " </velocity>\n"
- " </velocities>\n"
- "</instrument>";
-
-#define PCM_SIZE 100
-
-void createTestKit()
-{
- FILE *fp;
- fp = fopen("/tmp/kit.xml", "w");
- fwrite(xml_kit, strlen(xml_kit), 1, fp);
- fclose(fp);
-
- fp = fopen("/tmp/instr1.xml", "w");
- fwrite(xml_instr, strlen(xml_instr), 1, fp);
- fclose(fp);
-
- SF_INFO sf_info;
- sf_info.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT;
- sf_info.samplerate = 44100;
- sf_info.channels = 1;
-
- SNDFILE *fh = sf_open("/tmp/instr1.wav", SFM_WRITE, &sf_info);
- if(!fh) {
- printf("Error: %s\n", sf_strerror(fh));
- }
-
- size_t size = PCM_SIZE;
- sample_t samples[size];
-
- for(size_t i = 0; i < size; i++) {
- samples[i] = f(i);//(float)i / (float)size;
- }
-
- sf_write_float(fh, samples, size);
- sf_close(fh);
-}
-
-void deleteTestKit()
-{
- unlink("/tmp/kit.xml");
- unlink("/tmp/instr1.xml");
- unlink("/tmp/instr1.wav");
-}
-
-TEST_BEGIN;
-
-createTestKit();
-
-size_t size = PCM_SIZE;
-//for(size_t chunksz = 1; chunksz < size + 1; chunksz++) {
-size_t chunksz = 16; {
- sample_t samples[chunksz];
-
- for(size_t offset = 0; offset < chunksz + size + 1; offset++) {
- //size_t offset = 5; {
- for(size_t padding = 0; padding < chunksz + size + offset + 1; padding++) {
- //size_t padding = 2; {
- TEST_MSG("Values (offset %d, padding %d, chunksz %d)",
- offset, padding, chunksz);
-
- AOTest ao;
- AITest ai; ai.offset = offset;
- DrumGizmo dg(&ao, &ai);
- dg.loadkit("/tmp/kit.xml");
-
- size_t pos = 0;
- // sample_t samples[chunksz];
- while(pos < offset + size + padding) {
- dg.run(pos, samples, chunksz);
-
- float err = 0;
- size_t errcnt = 0;
- for(size_t i = 0; i < chunksz && pos < offset + size + padding; i++) {
- float val = 0.0;
- if(pos >= offset && pos < (offset + size)) val = f(pos - offset);
- float diff = samples[i] - val;
- /*
- if(diff != 0.0) {
- TEST_EQUAL_FLOAT(samples[i], val,
- "samples[%d] ?= val, pos %d", i, pos);
- }
- */
- if(diff != 0.0) errcnt++;
-
- err += fabs(diff);
- pos++;
- }
-
- TEST_EQUAL_FLOAT(err, 0.0,
- "Compare error (offset %d, padding %d, chunksz %d)",
- offset, padding, chunksz);
- TEST_EQUAL_INT(errcnt, 0,
- "Compare count (offset %d, padding %d, chunksz %d)",
- offset, padding, chunksz);
- }
-
- }
- }
-}
-
-deleteTestKit();
-
-TEST_END;
-
-#endif/*TEST_DRUMGIZMO*/
diff --git a/src/drumgizmo.h b/src/drumgizmo.h
index 1e38e08..98cd287 100644
--- a/src/drumgizmo.h
+++ b/src/drumgizmo.h
@@ -53,52 +53,54 @@
#define REFSFILE "refs.conf"
#define RESAMPLER_INPUT_BUFFER 64
-class DrumGizmo : public MessageReceiver {
+class DrumGizmo
+ : public MessageReceiver
+{
public:
- DrumGizmo(AudioOutputEngine *outputengine, AudioInputEngine *inputengine);
- virtual ~DrumGizmo();
+ DrumGizmo(AudioOutputEngine *outputengine, AudioInputEngine *inputengine);
+ virtual ~DrumGizmo();
- bool loadkit(std::string kitfile);
+ bool loadkit(std::string kitfile);
- bool init();
+ bool init();
- bool run(size_t pos, sample_t *samples, size_t nsamples);
- void stop();
+ bool run(size_t pos, sample_t *samples, size_t nsamples);
+ void stop();
- void getSamples(int ch, int pos, sample_t *s, size_t sz);
+ void getSamples(int ch, int pos, sample_t *s, size_t sz);
- std::string configString();
- bool setConfigString(std::string cfg);
+ std::string configString();
+ bool setConfigString(std::string cfg);
- void handleMessage(Message *msg);
+ void handleMessage(Message *msg);
- int samplerate();
- void setSamplerate(int samplerate);
+ int samplerate();
+ void setSamplerate(int samplerate);
- void setFrameSize(size_t framesize);
+ void setFrameSize(size_t framesize);
- void setFreeWheel(bool freewheel);
+ void setFreeWheel(bool freewheel);
-private:
- DrumKitLoader loader;
+protected:
+ DrumKitLoader loader;
- Mutex mutex;
- bool is_stopping; ///< Is set to true when a TYPE_STOP event has been seen.
+ Mutex mutex;
+ bool is_stopping; ///< Is set to true when a TYPE_STOP event has been seen.
- AudioOutputEngine *oe;
- AudioInputEngine *ie;
+ AudioOutputEngine *oe;
+ AudioInputEngine *ie;
- std::list< Event* > activeevents[MAX_NUM_CHANNELS];
+ std::list< Event* > activeevents[MAX_NUM_CHANNELS];
- CHResampler resampler[MAX_NUM_CHANNELS];
- sample_t resampler_output_buffer[MAX_NUM_CHANNELS][4096];
- sample_t resampler_input_buffer[MAX_NUM_CHANNELS][RESAMPLER_INPUT_BUFFER];
+ CHResampler resampler[MAX_NUM_CHANNELS];
+ sample_t resampler_output_buffer[MAX_NUM_CHANNELS][4096];
+ sample_t resampler_input_buffer[MAX_NUM_CHANNELS][RESAMPLER_INPUT_BUFFER];
- std::map<std::string, AudioFile *> audiofiles;
+ std::map<std::string, AudioFile *> audiofiles;
- AudioCache audioCache;
- DrumKit kit;
+ AudioCache audioCache;
+ DrumKit kit;
- size_t framesize;
- bool freewheel;
+ size_t framesize;
+ bool freewheel;
};
diff --git a/src/drumkitloader.cc b/src/drumkitloader.cc
index 0a44db0..64d6710 100644
--- a/src/drumkitloader.cc
+++ b/src/drumkitloader.cc
@@ -32,146 +32,165 @@
#include "drumgizmo.h"
DrumKitLoader::DrumKitLoader()
- : semaphore("drumkitloader")
- , framesize(0)
+ : semaphore("drumkitloader")
+ , framesize(0)
{
- run();
- run_semaphore.wait(); // Wait for the thread to actually start.
+ run();
+ run_semaphore.wait(); // Wait for the thread to actually start.
}
DrumKitLoader::~DrumKitLoader()
{
DEBUG(loader, "~DrumKitLoader() pre\n");
- if(running) {
- framesize_semaphore.post();
- stop();
- }
+
+ if(running)
+ {
+ framesize_semaphore.post();
+ stop();
+ }
+
DEBUG(loader, "~DrumKitLoader() post\n");
}
void DrumKitLoader::stop()
{
- {
- MutexAutolock l(mutex);
- load_queue.clear();
- }
-
- running = false;
- semaphore.post();
- wait_stop();
+ {
+ MutexAutolock l(mutex);
+ load_queue.clear();
+ }
+
+ running = false;
+ semaphore.post();
+ wait_stop();
}
void DrumKitLoader::skip()
{
- MutexAutolock l(mutex);
- load_queue.clear();
+ MutexAutolock l(mutex);
+ load_queue.clear();
}
void DrumKitLoader::setFrameSize(size_t framesize)
{
DEBUG(loader, "%s pre\n", __PRETTY_FUNCTION__);
+
{
- MutexAutolock l(mutex);
- this->framesize = framesize;
- framesize_semaphore.post(); // Signal that the framesize has been set.
+ MutexAutolock l(mutex);
+ this->framesize = framesize;
+ framesize_semaphore.post(); // Signal that the framesize has been set.
}
+
DEBUG(loader, "%s post\n", __PRETTY_FUNCTION__);
}
bool DrumKitLoader::isDone()
{
- MutexAutolock l(mutex);
- return load_queue.size() == 0;
+ MutexAutolock l(mutex);
+ return load_queue.size() == 0;
}
void DrumKitLoader::loadKit(DrumKit *kit)
{
- MutexAutolock l(mutex);
-
- DEBUG(loader, "Create AudioFile queue from DrumKit\n");
-
- total_num_audiofiles = 0;// For UI Progress Messages
-
- { // 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++;
- }
- }
-
- fraction = total_num_audiofiles / 200;
- if(fraction == 0) fraction = 1;
-
- { // 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++;
- }
- }
-
- loaded = 0; // For UI Progress Messages
-
- DEBUG(loader, "Queued %d (size: %d) AudioFiles for loading.\n",
- (int)total_num_audiofiles, (int)load_queue.size());
-
- semaphore.post(); // Start loader loop.
+ MutexAutolock l(mutex);
+
+ DEBUG(loader, "Create AudioFile queue from DrumKit\n");
+
+ total_num_audiofiles = 0;// For UI Progress Messages
+
+ { // 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;
+ }
+ }
+
+ fraction = total_num_audiofiles / 200;
+ if(fraction == 0)
+ {
+ fraction = 1;
+ }
+
+ { // 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;
+ }
+ }
+
+ loaded = 0; // For UI Progress Messages
+
+ DEBUG(loader, "Queued %d (size: %d) AudioFiles for loading.\n",
+ (int)total_num_audiofiles, (int)load_queue.size());
+
+ semaphore.post(); // Start loader loop.
}
void DrumKitLoader::thread_main()
{
- running = true;
-
- run_semaphore.post(); // Signal that the thread has been started.
-
- framesize_semaphore.wait(); // Wait until the framesize has been set.
-
- while(running) {
- size_t size;
- {
- MutexAutolock l(mutex);
- size = load_queue.size();
- }
-
- // Only sleep if queue is empty.
- if(size == 0) semaphore.wait();
-
- std::string filename;
- {
- MutexAutolock l(mutex);
- if(load_queue.size() == 0) continue;
- AudioFile *audiofile = load_queue.front();
- load_queue.pop_front();
- filename = audiofile->filename;
- size_t preload_size = framesize * CHUNK_MULTIPLIER + framesize;
- if(preload_size < 1024)
- {
+ running = true;
+
+ run_semaphore.post(); // Signal that the thread has been started.
+
+ framesize_semaphore.wait(); // Wait until the framesize has been set.
+
+ while(running)
+ {
+ size_t size;
+ {
+ MutexAutolock l(mutex);
+ size = load_queue.size();
+ }
+
+ // Only sleep if queue is empty.
+ if(size == 0)
+ {
+ semaphore.wait();
+ }
+
+ std::string filename;
+ {
+ MutexAutolock l(mutex);
+ if(load_queue.size() == 0)
+ {
+ continue;
+ }
+ AudioFile *audiofile = load_queue.front();
+ load_queue.pop_front();
+ filename = audiofile->filename;
+ size_t preload_size = framesize * CHUNK_MULTIPLIER + framesize;
+ if(preload_size < 1024)
+ {
preload_size = 1024;
- }
- (void)preload_size;
- audiofile->load(ALL_SAMPLES); // Note: Change this to enable diskstreaming
- }
-
- loaded++;
-
- if(loaded % fraction == 0 || loaded == total_num_audiofiles) {
- LoadStatusMessage *ls = new LoadStatusMessage();
- ls->number_of_files = total_num_audiofiles;
- ls->numer_of_files_loaded = loaded;
- ls->current_file = filename;
- msghandler.sendMessage(MSGRCV_UI, ls);
- }
- }
-
- DEBUG(loader, "Loader thread finished.");
+ }
+ (void)preload_size;
+ audiofile->load(ALL_SAMPLES); // Note: Change this to enable diskstreaming
+ }
+
+ loaded++;
+
+ if(loaded % fraction == 0 || loaded == total_num_audiofiles)
+ {
+ LoadStatusMessage *ls = new LoadStatusMessage();
+ ls->number_of_files = total_num_audiofiles;
+ ls->numer_of_files_loaded = loaded;
+ ls->current_file = filename;
+ msghandler.sendMessage(MSGRCV_UI, ls);
+ }
+ }
+
+ DEBUG(loader, "Loader thread finished.");
}
diff --git a/src/drumkitloader.h b/src/drumkitloader.h
index 22859a0..0532691 100644
--- a/src/drumkitloader.h
+++ b/src/drumkitloader.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_DRUMKITLOADER_H__
-#define __DRUMGIZMO_DRUMKITLOADER_H__
+#pragma once
#include <string>
#include <list>
@@ -36,69 +35,51 @@
#include "drumkit.h"
-/**
- * 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 {
+//! 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:
- /**
- * The constrcutor starts the loader thread.
- */
- DrumKitLoader();
+ //! 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();
+ //! 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);
-
- // I have no idea what this does..
- //void reset(AudioFile* af);
+ //! 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 thread_main();
+ void thread_main();
- /**
- * Simply reports if the load queue is empty (i.e. all AudioFiles has been
- * loaded).
- */
- bool isDone();
+ //! 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();
+ //! Signal the loader to stop and wait until it has.
+ void stop();
- /**
- * Skip all queued AudioFiles.
- */
- void skip();
+ //! Skip all queued AudioFiles.
+ void skip();
- void setFrameSize(size_t framesize);
+ void setFrameSize(size_t framesize);
-private:
- Semaphore run_semaphore;
- Semaphore semaphore;
- Semaphore framesize_semaphore;
- Mutex mutex;
+protected:
+ Semaphore run_semaphore;
+ Semaphore semaphore;
+ Semaphore framesize_semaphore;
+ Mutex mutex;
volatile bool running{false};
- std::list<AudioFile*> load_queue;
+ std::list<AudioFile*> load_queue;
size_t total_num_audiofiles{0};
size_t fraction{1};
size_t loaded{0};
-
size_t framesize{0};
};
-
-#endif/*__DRUMGIZMO_DRUMKITLOADER_H__*/