From 60cd3f9dc45b194198198591a7bf48e2d8afb16c Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Fri, 22 May 2015 10:34:21 +0200 Subject: Added framesize control mechanism to the engine, and made us of it in the cachemanager and drumkitloader. --- drumgizmo/drumgizmoc.cc | 19 +++++++++++++- drumgizmo/output/alsa/alsa.cc | 12 +++++++++ lv2/lv2.cc | 34 ++++++++++++------------ src/audiooutputengine.h | 5 ---- src/cachemanager.cc | 51 +++++++++++++++++++++++------------- src/cachemanager.h | 9 ++++--- src/drumgizmo.cc | 60 ++++++++++++++++++++++--------------------- src/drumgizmo.h | 17 +++++------- src/drumkitloader.cc | 12 ++++++++- src/drumkitloader.h | 5 ++++ vst/drumgizmo_vst.cc | 1 + 11 files changed, 140 insertions(+), 85 deletions(-) diff --git a/drumgizmo/drumgizmoc.cc b/drumgizmo/drumgizmoc.cc index 1ccc151..ab91423 100644 --- a/drumgizmo/drumgizmoc.cc +++ b/drumgizmo/drumgizmoc.cc @@ -328,6 +328,8 @@ int CliMain::run(int argc, char *argv[]) DrumGizmo gizmo(oe, ie); + gizmo.setFrameSize(oe->getBufferSize()); + if(kitfile == "" || !gizmo.loadkit(kitfile)) { printf("Failed to load \"%s\".\n", kitfile.c_str()); return 1; @@ -357,7 +359,22 @@ int CliMain::run(int argc, char *argv[]) return 1; } - gizmo.run(endpos); + size_t pos = 0; + size_t nsamples = oe->getBufferSize(); + sample_t *samples = (sample_t *)malloc(nsamples * sizeof(sample_t)); + + ie->start(); + oe->start(); + + while(gizmo.run(pos, samples, nsamples) == true) { + pos += nsamples; + if(endpos != -1 && pos >= (size_t)endpos) break; + } + + ie->stop(); + oe->stop(); + + free(samples); printf("Quit.\n"); fflush(stdout); diff --git a/drumgizmo/output/alsa/alsa.cc b/drumgizmo/output/alsa/alsa.cc index 71e0c3d..f9a2068 100644 --- a/drumgizmo/output/alsa/alsa.cc +++ b/drumgizmo/output/alsa/alsa.cc @@ -49,6 +49,7 @@ public: void pre(size_t size); void run(int channel, sample_t* data, size_t size); void post(size_t size); + size_t bufsize(); size_t samplerate(); private: @@ -158,6 +159,11 @@ void Alsa::post(size_t size) snd_pcm_writei(handle, data, size); } +size_t Alsa::bufsize() +{ + return frames; +} + size_t Alsa::samplerate() { return srate; @@ -217,6 +223,12 @@ extern "C" { alsa->post(s); } + size_t bufsize(void *h) + { + Alsa *alsa = (Alsa*)h; + return alsa->bufsize(); + } + size_t samplerate(void *h) { Alsa *alsa = (Alsa*)h; diff --git a/lv2/lv2.cc b/lv2/lv2.cc index d87665d..687f989 100644 --- a/lv2/lv2.cc +++ b/lv2/lv2.cc @@ -47,12 +47,11 @@ static DrumGizmo *dg_get_pci(LV2_Handle instance) return dglv2->dg; } -LV2_State_Status -dg_save(LV2_Handle instance, - LV2_State_Store_Function store, - LV2_State_Handle handle, - uint32_t flags, - const LV2_Feature *const * features) +LV2_State_Status dg_save(LV2_Handle instance, + LV2_State_Store_Function store, + LV2_State_Handle handle, + uint32_t flags, + const LV2_Feature *const * features) { DGLV2 *dglv2 = (DGLV2 *)instance; @@ -77,12 +76,11 @@ dg_save(LV2_Handle instance, return LV2_STATE_SUCCESS; } -LV2_State_Status -dg_restore(LV2_Handle instance, - LV2_State_Retrieve_Function retrieve, - LV2_State_Handle handle, - uint32_t flags, - const LV2_Feature *const * features) +LV2_State_Status dg_restore(LV2_Handle instance, + LV2_State_Retrieve_Function retrieve, + LV2_State_Handle handle, + uint32_t flags, + const LV2_Feature *const * features) { DGLV2 *dglv2 = (DGLV2 *)instance; @@ -148,9 +146,7 @@ LV2_Handle instantiate(const struct _LV2_Descriptor *descriptor, return (LV2_Handle)dglv2; } -void connect_port(LV2_Handle instance, - uint32_t port, - void *data_location) +void connect_port(LV2_Handle instance, uint32_t port, void *data_location) { DGLV2 *dglv2 = (DGLV2 *)instance; @@ -171,12 +167,15 @@ void activate(LV2_Handle instance) (void)dglv2; } -void run(LV2_Handle instance, - uint32_t sample_count) +void run(LV2_Handle instance, uint32_t sample_count) { static size_t pos = 0; DGLV2 *dglv2 = (DGLV2 *)instance; + if(dglv2->buffer_size != sample_count) { + dglv2->buffer_size = sample_count; + dglv2->dg->setFrameSize(sample_count); + } dglv2->dg->run(pos, dglv2->buffer, sample_count); pos += sample_count; @@ -184,7 +183,6 @@ void run(LV2_Handle instance, void deactivate(LV2_Handle instance) { - // We don't really need to do anything here. DGLV2 *dglv2 = (DGLV2 *)instance; dglv2->dg->stop(); } diff --git a/src/audiooutputengine.h b/src/audiooutputengine.h index 7f15e49..8b2b768 100644 --- a/src/audiooutputengine.h +++ b/src/audiooutputengine.h @@ -50,11 +50,6 @@ public: // Reimplement this if you wish to use internal buffer directly. virtual sample_t *getBuffer(int ch) { return NULL; } - - /* - * Overload this method to force engine to use different buffer size. - */ - virtual size_t getBufferSize() { return 1024; } }; #endif/*__DRUMGIZMO_AUDIOOUTPUTENGINE_H__*/ diff --git a/src/cachemanager.cc b/src/cachemanager.cc index 61fdb3e..4053f05 100644 --- a/src/cachemanager.cc +++ b/src/cachemanager.cc @@ -28,15 +28,16 @@ #include #include +#include #include #include -static sample_t nodata[FRAMESIZE]; - #define BUFFER_SIZE 4092 +#define CHUNKSIZE(x) (x * CHUNK_MULTIPLIER) + static size_t readChunk(std::string filename, int filechannel, size_t pos, size_t num_samples, sample_t* buf) { @@ -84,21 +85,22 @@ static size_t readChunk(std::string filename, int filechannel, size_t pos, return size; } -CacheManager::CacheManager() {} +CacheManager::CacheManager() + : framesize(0) + , nodata(NULL) +{ +} CacheManager::~CacheManager() { deinit(); + delete[] nodata; } void CacheManager::init(size_t poolsize, bool threaded) { this->threaded = threaded; - for(size_t i = 0; i < FRAMESIZE; i++) { - nodata[i] = 0; - } - id2cache.resize(poolsize); for(size_t i = 0; i < poolsize; i++) { availableids.push_back(i); @@ -137,6 +139,7 @@ sample_t *CacheManager::open(AudioFile *file, size_t initial_samples_needed, } if(id == CACHE_DUMMYID) { + assert(nodata); return nodata; } @@ -145,10 +148,10 @@ sample_t *CacheManager::open(AudioFile *file, size_t initial_samples_needed, c.channel = channel; c.pos = initial_samples_needed; c.localpos = 0; - c.front = new sample_t[CHUNKSIZE]; - c.back = new sample_t[CHUNKSIZE]; + c.front = new sample_t[CHUNKSIZE(framesize)]; + c.back = new sample_t[CHUNKSIZE(framesize)]; - size_t size = CHUNKSIZE; + size_t size = CHUNKSIZE(framesize); if(size > (file->preloadedsize - c.pos)) size = (file->preloadedsize - c.pos); memcpy(c.front, c.file->data + c.pos, size * sizeof(sample_t)); c.ready = false; @@ -174,21 +177,22 @@ sample_t *CacheManager::open(AudioFile *file, size_t initial_samples_needed, sample_t *CacheManager::next(cacheid_t id, size_t &size) { - size = FRAMESIZE; + size = framesize; if(id == CACHE_DUMMYID) { + assert(nodata); return nodata; } cache_t& c = id2cache[id]; - if(c.localpos < CHUNKSIZE) { + if(c.localpos < CHUNKSIZE(framesize)) { sample_t *s = c.front + c.localpos; c.localpos += size; return s; } if(!c.ready) { - printf("#%d: NOT READY!\n", id); // TODO: Count and show in UI? + //printf("#%d: NOT READY!\n", id); // TODO: Count and show in UI? } // Swap buffers @@ -198,7 +202,7 @@ sample_t *CacheManager::next(cacheid_t id, size_t &size) c.localpos = size; // Next time we go here we have already read the first frame. - c.pos += CHUNKSIZE; + c.pos += CHUNKSIZE(framesize); if(c.pos < c.file->size) { cevent_t e = createLoadNextEvent(c.file, c.channel, c.pos, c.back); @@ -220,17 +224,28 @@ void CacheManager::close(cacheid_t id) pushEvent(e); } +void CacheManager::setFrameSize(size_t framesize) +{ + this->framesize = framesize; + delete[] nodata; + nodata = new sample_t[framesize]; + + for(size_t i = 0; i < framesize; i++) { + nodata[i] = 0; + } +} + void CacheManager::handleLoadNextEvent(cevent_t &e) { #if 0 // memcpy - size_t size = CHUNKSIZE; + size_t size = CHUNKSIZE(framesize); if(size > (e.file->size - e.pos)) { size = (e.file->size - e.pos); } memcpy(e.buffer, e.file->data + e.pos, size * sizeof(sample_t)); #elif 1 // diskread - //memset(e.buffer, 0, CHUNKSIZE * sizeof(sample_t)); - readChunk(e.file->filename, e.channel, e.pos, CHUNKSIZE, e.buffer); + //memset(e.buffer, 0, CHUNKSIZE(framesize) * sizeof(sample_t)); + readChunk(e.file->filename, e.channel, e.pos, CHUNKSIZE(framesize), e.buffer); #endif *e.ready = true; } @@ -246,7 +261,7 @@ void CacheManager::handleCloseEvent(cevent_t &e) availableids.push_back(e.id); } - // TODO: Count down ref coutner on c.file and close it if 0. + // TODO: Count down ref counter on c.file and close it if 0. } diff --git a/src/cachemanager.h b/src/cachemanager.h index f2c0122..d98d66c 100644 --- a/src/cachemanager.h +++ b/src/cachemanager.h @@ -41,9 +41,7 @@ #define CACHE_DUMMYID -2 #define CACHE_NOID -1 -#define FRAMESIZE 2048 -#define CHUNKSIZE (FRAMESIZE * 16) -#define PRELOADSIZE (FRAMESIZE + CHUNKSIZE) +#define CHUNK_MULTIPLIER 16 class AudioFile; typedef int cacheid_t; @@ -131,10 +129,15 @@ public: */ void close(cacheid_t id); + void setFrameSize(size_t framesize); + ///! Internal thread main method - needs to be public. void thread_main(); private: + size_t framesize; + sample_t *nodata; + typedef struct { AudioFile *file; size_t channel; diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index fb4f042..8661232 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -46,8 +46,11 @@ #include "nolocale.h" DrumGizmo::DrumGizmo(AudioOutputEngine *o, AudioInputEngine *i) - : MessageReceiver(MSGRCV_ENGINE), - loader(), oe(o), ie(i) + : MessageReceiver(MSGRCV_ENGINE) + , loader() + , oe(o) + , ie(i) + , framesize(0) { is_stopping = false; cacheManager.init(1000, true); // start thread @@ -166,8 +169,30 @@ void DrumGizmo::handleMessage(Message *msg) } } +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) { + printf("New framesize: %d\n", framesize); + + this->framesize = framesize; + + // Update framesize in drumkitloader and cachemanager: + loader.setFrameSize(framesize); + printf("loader.setFrameSize\n"); fflush(stdout); + cacheManager.setFrameSize(framesize); + printf("cacheManager.setFrameSize\n"); fflush(stdout); + } +} + 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); @@ -355,26 +380,6 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples) return true; } -void DrumGizmo::run(int endpos) -{ - size_t pos = 0; - size_t nsamples = oe->getBufferSize(); - sample_t *samples = (sample_t *)malloc(nsamples * sizeof(sample_t)); - - ie->start(); - oe->start(); - - while(run(pos, samples, nsamples) == true) { - pos += nsamples; - if(endpos != -1 && pos >= (size_t)endpos) break; - } - - ie->stop(); - oe->stop(); - - free(samples); -} - #ifdef SSE #define N 8 typedef float vNsf __attribute__ ((vector_size(sizeof(float)*N))); @@ -383,7 +388,7 @@ typedef float vNsf __attribute__ ((vector_size(sizeof(float)*N))); void DrumGizmo::getSamples(int ch, int pos, sample_t *s, size_t sz) { std::list< Event* >::iterator i = activeevents[ch].begin(); - while(i != activeevents[ch].end()) { + for(; i != activeevents[ch].end(); ++i) { bool removeevent = false; Event *event = *i; @@ -405,17 +410,12 @@ void DrumGizmo::getSamples(int ch, int pos, sample_t *s, size_t sz) continue; } - size_t buffer_offset = 0; - if(evt->cache_id == CACHE_NOID) { size_t initial_chunksize = (pos + sz) - evt->offset; evt->buffer = cacheManager.open(af, initial_chunksize, ch, evt->cache_id); evt->buffer_size = initial_chunksize; } - else { - buffer_offset = evt->offset; - } { MutexAutolock l(af->mutex); @@ -479,7 +479,6 @@ void DrumGizmo::getSamples(int ch, int pos, sample_t *s, size_t sz) i = activeevents[ch].erase(i); continue; } - i++; } } @@ -500,6 +499,9 @@ void DrumGizmo::setSamplerate(int samplerate) 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*/ } diff --git a/src/drumgizmo.h b/src/drumgizmo.h index f1ec546..807e1e0 100644 --- a/src/drumgizmo.h +++ b/src/drumgizmo.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_DRUMGIZMO_H__ -#define __DRUMGIZMO_DRUMGIZMO_H__ +#pragma once #include #include @@ -52,6 +51,7 @@ #define MAX_NUM_CHANNELS 64 #define REFSFILE "refs.conf" +#define RESAMPLER_INPUT_BUFFER 64 class DrumGizmo : public MessageReceiver { public: @@ -62,10 +62,6 @@ public: bool init(); - /** - * @param endpos number of samples to process, -1 := never stop. - */ - void run(int endpos); bool run(size_t pos, sample_t *samples, size_t nsamples); void stop(); @@ -79,6 +75,8 @@ public: int samplerate(); void setSamplerate(int samplerate); + void setFrameSize(size_t framesize); + private: DrumKitLoader loader; @@ -92,14 +90,13 @@ private: CHResampler resampler[MAX_NUM_CHANNELS]; sample_t resampler_output_buffer[MAX_NUM_CHANNELS][4096]; - sample_t resampler_input_buffer[MAX_NUM_CHANNELS][64]; + sample_t resampler_input_buffer[MAX_NUM_CHANNELS][RESAMPLER_INPUT_BUFFER]; std::map audiofiles; CacheManager cacheManager; DrumKit kit; -}; - -#endif/*__DRUMGIZMO_DRUMGIZMO_H__*/ + size_t framesize; +}; diff --git a/src/drumkitloader.cc b/src/drumkitloader.cc index 2b66ae0..413d3f4 100644 --- a/src/drumkitloader.cc +++ b/src/drumkitloader.cc @@ -34,6 +34,7 @@ DrumKitLoader::DrumKitLoader() : semaphore("drumkitloader") + , framesize(0) { run(); run_semaphore.wait(); // Wait for the thread to actually start. @@ -64,6 +65,13 @@ void DrumKitLoader::skip() load_queue.clear(); } +void DrumKitLoader::setFrameSize(size_t framesize) +{ + MutexAutolock l(mutex); + this->framesize = framesize; + framesize_semaphore.post(); // Signal that the framesize has been set. +} + bool DrumKitLoader::isDone() { MutexAutolock l(mutex); @@ -120,6 +128,8 @@ void DrumKitLoader::thread_main() 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; { @@ -137,7 +147,7 @@ void DrumKitLoader::thread_main() AudioFile *audiofile = load_queue.front(); load_queue.pop_front(); filename = audiofile->filename; - audiofile->load(PRELOADSIZE); + audiofile->load(framesize * CHUNK_MULTIPLIER + framesize); } loaded++; diff --git a/src/drumkitloader.h b/src/drumkitloader.h index b4a0a69..22859a0 100644 --- a/src/drumkitloader.h +++ b/src/drumkitloader.h @@ -85,15 +85,20 @@ public: */ void skip(); + void setFrameSize(size_t framesize); + private: Semaphore run_semaphore; Semaphore semaphore; + Semaphore framesize_semaphore; Mutex mutex; volatile bool running{false}; std::list load_queue; size_t total_num_audiofiles{0}; size_t fraction{1}; size_t loaded{0}; + + size_t framesize{0}; }; #endif/*__DRUMGIZMO_DRUMKITLOADER_H__*/ diff --git a/vst/drumgizmo_vst.cc b/vst/drumgizmo_vst.cc index d9cb975..6e26ea4 100644 --- a/vst/drumgizmo_vst.cc +++ b/vst/drumgizmo_vst.cc @@ -450,6 +450,7 @@ void DrumGizmoVst::processReplacing(float** inputs, float** outputs, if(buffer) free(buffer); buffer_size = sampleFrames; buffer = (sample_t*)malloc(sizeof(sample_t) * buffer_size); + drumgizmo->setFrameSize(buffer_size); } drumgizmo->run(pos, buffer, buffer_size); -- cgit v1.2.3