From 99db25aae3c8f06b9bb1a17865e344cfe559b47e Mon Sep 17 00:00:00 2001 From: Jonas Suhr Christensen Date: Fri, 10 Apr 2015 16:28:03 +0200 Subject: Added unit test shell for cachemanager. Added cache manager logic - still needing audio related code. --- src/Makefile.am | 4 +- src/Makefile.am.drumgizmo | 3 +- src/audiofile.h | 2 +- src/cachemanager.cc | 107 +++++++++++++++++++++++++++++++++++++++++++++- src/cachemanager.h | 71 ++++++++++++++++++++++-------- test/Makefile.am | 13 +++++- 6 files changed, 175 insertions(+), 25 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index df9f4ca..cb44909 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,6 +9,7 @@ EXTRA_DIST = \ channelmixer.h \ chresampler.h \ configuration.h \ + cachemanager.h \ configparser.h \ drumgizmo.h \ drumkit.h \ @@ -39,6 +40,7 @@ EXTRA_DIST = \ audioinputenginemidi.cc \ audiooutputengine.cc \ beatmapper.cc \ + cachemanager.cc \ channel.cc \ channelmixer.cc \ chresampler.cc \ @@ -63,4 +65,4 @@ EXTRA_DIST = \ semaphore.cc \ thread.cc \ velocity.cc \ - versionstr.cc \ No newline at end of file + versionstr.cc diff --git a/src/Makefile.am.drumgizmo b/src/Makefile.am.drumgizmo index 1a3c857..ee09445 100644 --- a/src/Makefile.am.drumgizmo +++ b/src/Makefile.am.drumgizmo @@ -5,6 +5,7 @@ DRUMGIZMO_SOURCES = \ $(top_srcdir)/src/channelmixer.cc \ $(top_srcdir)/src/chresampler.cc \ $(top_srcdir)/src/configfile.cc \ + $(top_srcdir)/src/cachemanager.cc \ $(top_srcdir)/src/configuration.cc \ $(top_srcdir)/src/configparser.cc \ $(top_srcdir)/src/drumgizmo.cc \ @@ -28,4 +29,4 @@ DRUMGIZMO_SOURCES = \ $(top_srcdir)/src/velocity.cc \ $(top_srcdir)/src/versionstr.cc -DRUMGIZMO_LIBS = $(ZITA_LIBS) $(SNDFILE_LIBS) $(EXPAT_LIBS) $(SAMPLERATE_LIBS) \ No newline at end of file +DRUMGIZMO_LIBS = $(ZITA_LIBS) $(SNDFILE_LIBS) $(EXPAT_LIBS) $(SAMPLERATE_LIBS) diff --git a/src/audiofile.h b/src/audiofile.h index 98bf101..5b57db8 100644 --- a/src/audiofile.h +++ b/src/audiofile.h @@ -80,7 +80,7 @@ public: bool isLoaded(); volatile size_t size; - volatile sample_t *data; + sample_t *data; std::string filename; diff --git a/src/cachemanager.cc b/src/cachemanager.cc index 2e9eab9..5e2adf0 100644 --- a/src/cachemanager.cc +++ b/src/cachemanager.cc @@ -3,8 +3,8 @@ * cachemanager.cc * * Fri Apr 10 10:39:24 CEST 2015 - * Copyright 2015 Bent Bisballe Nyeng - * deva@aasimon.org + * Copyright 2015 Jonas Suhr Christensen + * jsc@umbraculum.org ****************************************************************************/ /* @@ -26,3 +26,106 @@ */ #include "cachemanager.h" +#include + +CacheManager::CacheManager() +{ +} + +CacheManager::~CacheManager() +{ + wait_stop(); +} + +void CacheManager::init(int poolsize) +{ + id2cache.resize(poolsize); + for(int i = 0; i < poolsize; i++) { + availableids.push_back(i); + } + + running = true; + run(); +} + +// Invariant: initial_samples_needed < preloaded audio data +sample_t *CacheManager::open(AudioFile *file, int initial_samples_needed, int channel, cacheid_t &id) +{ + // What if no free ids is available? + m_ids.lock(); + id = availableids.front(); + availableids.pop_front(); + m_ids.unlock(); + + cache_t c; + c.file = file; + c.channel = channel; + c.pos = initial_samples_needed; + // Allocate buffers + // Increase audio ref count + + id2cache[id] = c; + + event_t e; + e.id = id; + pushEvent(e); + + return file->data; +} + +void CacheManager::close(cacheid_t id) +{ + m_ids.lock(); + availableids.push_back(id); + m_ids.unlock(); + + // Clean cache_t mapped to event + // Clean event list for other events mapped to this id? + // Maybe we need an event for this, that we can push in front of eventqueue (con: we dont read from disk when doing this stuff). + // Decrement audiofile ref count +} + +sample_t *CacheManager::next(cacheid_t id, size_t &size) +{ + sample_t *s = NULL; + return s; +} + +void CacheManager::loadNext(cacheid_t id) +{ + printf("Loading next...\n"); + + // If more is left of file + if(false) { + event_t e; + e.id = id; + pushEvent(e); + } +} + +void CacheManager::thread_main() +{ + while(running) { + sem.wait(); + + m_events.lock(); + if(eventqueue.empty()) { + event_t e = eventqueue.front(); + eventqueue.pop_front(); + m_events.unlock(); + + loadNext(e.id); + } + else { + m_events.unlock(); + } + } +} + +void CacheManager::pushEvent(event_t e) +{ + // Check that if event should be merged (Maybe by event queue (ie. push in front). + m_events.lock(); + eventqueue.push_back(e); + m_events.unlock(); +} diff --git a/src/cachemanager.h b/src/cachemanager.h index ed89d12..e170bf4 100644 --- a/src/cachemanager.h +++ b/src/cachemanager.h @@ -3,8 +3,8 @@ * cachemanager.h * * Fri Apr 10 10:39:24 CEST 2015 - * Copyright 2015 Bent Bisballe Nyeng - * deva@aasimon.org + * Copyright 2015 Jonas Suhr Christensen + * jsc@umbraculum.org ****************************************************************************/ /* @@ -29,18 +29,28 @@ #include #include +#include +#include "thread.h" +#include "semaphore.h" +#include "mutex.h" + +#include "audiotypes.h" +#include "audiofile.h" + +#define CACHEMANAGER_NOID -1; class AudioFile; +typedef int cacheid_t; -class CacheManager { +class CacheManager : public Thread { public: + CacheManager(); + ~CacheManager(); - class Request { - public: - std::string filename; - std::map targets; - size_t pos; - }; + void init(int poolsize); + void deinit(); + + void thread_main(); // Pre: preloaded contains 2 x framesize. chunk size is framesize. // allocate 2 chunks and copy initial_samples_needed to first buffer from @@ -48,17 +58,17 @@ public: // returns the first buffer and its size in &size. // get id from "free stack" and store pointers to buffers in id vector. // event: open sndfile handle (if not already open) and increase refcount - sample_t *hello(AudioFile *file, int initial_samples_needed, int channel, id_t &new_id); + sample_t *open(AudioFile *file, int initial_samples_needed, int channel, cacheid_t &new_id); // Return which ever buffer is the front, swap them and add event to load the // next chunk. - sample_t *getNextBuffer(id_t id, size_t &size); + sample_t *next(cacheid_t id, size_t &size); // decrement file handle refcounter and close file if it is 0. // free the 2 buffers // (do not erase from the id vector), push index to // "free stack" for reuse. - void goodbye(id_t id); + void close(cacheid_t id); // id vector: // { @@ -70,15 +80,38 @@ public: // } private: - class File { - public: - sndfile_t *handle; - int refcounter; - }; - std::list requests; - std::map + void pushEvent(); + + typedef struct { + AudioFile *file; + int channel; + size_t pos; + void *a; + void *b; + } cache_t; + + typedef struct { + cacheid_t id; + } event_t; + + void loadNext(cacheid_t id); + void pushEvent(event_t e); + cacheid_t leaseId(); + cacheid_t releaseId(); + + // Protected by mutex + std::list eventqueue; + std::list availableids; + std::vector id2cache; + + Mutex m_events; + Mutex m_ids; + Mutex m_caches; + + Semaphore sem; + int running; }; #endif/*__DRUMGIZMO_CACHEMANAGER_H__*/ diff --git a/test/Makefile.am b/test/Makefile.am index 29ab4b1..2c2ab8d 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,7 +1,7 @@ # Rules for the test code (use `make check` to execute) include $(top_srcdir)/src/Makefile.am.drumgizmo -TESTS = resource engine gui resampler lv2 configfile +TESTS = resource engine cache gui resampler lv2 configfile check_PROGRAMS = $(TESTS) @@ -26,6 +26,17 @@ engine_SOURCES = \ test.cc \ engine.cc +cache_CXXFLAGS = -DOUTPUT=\"cache\" $(CPPUNIT_CFLAGS) \ + -I$(top_srcdir)/src -I$(top_srcdir)/include \ + -I$(top_srcdir)/hugin -DDISABLE_HUGIN +cache_CFLAGS = -DDISABLE_HUGIN +cache_LDFLAGS = $(CPPUNIT_LIBS) $(DRUMGIZMO_LIBS) $(PTHREAD_LIBS) +cache_SOURCES = \ + $(DRUMGIZMO_SOURCES) \ + $(top_srcdir)/hugin/hugin.c \ + test.cc \ + cache.cc + gui_CXXFLAGS = -DOUTPUT=\"gui\" $(CPPUNIT_CFLAGS) gui_LDFLAGS = $(CPPUNIT_LIBS) gui_SOURCES = \ -- cgit v1.2.3