summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/audiocache.cc40
-rw-r--r--src/audiocache.h6
-rw-r--r--src/audiocacheeventhandler.cc23
-rw-r--r--src/audiocacheeventhandler.h4
-rw-r--r--src/audiocachefile.cc35
-rw-r--r--src/audiocachefile.h7
-rw-r--r--src/audiocacheidmanager.cc14
-rw-r--r--src/audiocacheidmanager.h2
-rw-r--r--src/audiofile.cc4
-rw-r--r--src/audiofile.h4
-rw-r--r--src/drumgizmo.cc60
-rw-r--r--test/audiocachefiletest.cc8
-rw-r--r--test/audiocacheidmanagertest.cc2
-rw-r--r--test/audiocachetest.cc2
14 files changed, 109 insertions, 102 deletions
diff --git a/src/audiocache.cc b/src/audiocache.cc
index 237a3ff..86052c7 100644
--- a/src/audiocache.cc
+++ b/src/audiocache.cc
@@ -28,7 +28,6 @@
#include <mutex>
-#include <string.h>
#include <stdio.h>
#include <assert.h>
@@ -62,10 +61,10 @@ void AudioCache::deinit()
}
// Invariant: initial_samples_needed < preloaded audio data
-sample_t* AudioCache::open(AudioFile* file, size_t initial_samples_needed,
+sample_t* AudioCache::open(const AudioFile& file, size_t initial_samples_needed,
int channel, cacheid_t& id)
{
- if(!file->isValid())
+ if(!file.isValid())
{
// File preload not yet ready - skip this sample.
id = CACHE_DUMMYID;
@@ -87,7 +86,7 @@ sample_t* AudioCache::open(AudioFile* file, size_t initial_samples_needed,
// Get the cache_t connected with the registered id.
cache_t& c = id_manager.getCache(id);
- c.afile = &event_handler.openFile(file->filename);
+ c.afile = &event_handler.openFile(file.filename);
c.channel = channel;
// Next call to 'next()' will read from this point.
@@ -96,26 +95,37 @@ sample_t* AudioCache::open(AudioFile* file, size_t initial_samples_needed,
c.front = nullptr; // This is allocated when needed.
c.back = nullptr; // This is allocated when needed.
- // cropped_size is the preload chunk size cropped to sample length.
- size_t cropped_size = file->preloadedsize - c.localpos;
- cropped_size /= framesize;
- cropped_size *= framesize;
- cropped_size += initial_samples_needed;
+ size_t cropped_size;
- if(file->preloadedsize == file->size)
+ if(file.preloadedsize == file.size)
{
// We have preloaded the entire file, so use it.
- cropped_size = file->preloadedsize;
+ cropped_size = file.preloadedsize;
+ }
+ else
+ {
+ // Make sure that the preload-data made available to the next() calls
+ // fit on frame boundary:
+ //
+ // [ all preloaded data ]
+ // [ initial ][ biggest multiple of full frames ][ the rest ]
+ // \ /
+ // \----------------------v-------------------/
+ // cropped_size
+
+ cropped_size = file.preloadedsize - c.localpos;
+ cropped_size -= cropped_size % framesize;
+ cropped_size += initial_samples_needed;
}
- c.preloaded_samples = file->data;
+ c.preloaded_samples = file.data;
c.preloaded_samples_size = cropped_size;
// Next read from disk will read from this point.
c.pos = cropped_size;//c.preloaded_samples_size;
- // Only load next buffer if there are more data in the file to be loaded...
- if(c.pos < file->size)
+ // Only load next buffer if there is more data in the file to be loaded...
+ if(c.pos < file.size)
{
if(c.back == nullptr)
{
@@ -262,7 +272,7 @@ void AudioCache::setAsyncMode(bool async)
bool AudioCache::asyncMode() const
{
- return event_handler.getThreaded();
+ return event_handler.isThreaded();
}
size_t AudioCache::getNumberOfUnderruns() const
diff --git a/src/audiocache.h b/src/audiocache.h
index 004fcf8..059faa2 100644
--- a/src/audiocache.h
+++ b/src/audiocache.h
@@ -67,7 +67,7 @@ public:
//! \param [out] new_id The newly created cache id.
//! \return A pointer to the first buffer containing the
//! 'initial_samples_needed' number of samples.
- sample_t* open(AudioFile* file, size_t initial_samples_needed, int channel,
+ sample_t* open(const AudioFile& file, size_t initial_samples_needed, int channel,
cacheid_t& new_id);
//! Get next buffer.
@@ -79,7 +79,7 @@ public:
//! \return A pointer to the buffer.
sample_t* next(cacheid_t id, size_t &size);
- //! Returns if the next chunk of the supplied id has been read from disk.
+ //! Returns true iff the next chunk of the supplied id has been read from disk.
bool isReady(cacheid_t id);
//! Unregister cache entry.
@@ -105,7 +105,7 @@ public:
private:
size_t framesize{0};
- sample_t *nodata{nullptr};
+ sample_t* nodata{nullptr};
size_t number_of_underruns{0};
AudioCacheIDManager id_manager;
diff --git a/src/audiocacheeventhandler.cc b/src/audiocacheeventhandler.cc
index 7322785..6ec68b5 100644
--- a/src/audiocacheeventhandler.cc
+++ b/src/audiocacheeventhandler.cc
@@ -53,9 +53,7 @@ public:
};
AudioCacheEventHandler::AudioCacheEventHandler(AudioCacheIDManager& id_manager)
- // Hack to be able to forward declare CacheEvent:
- : eventqueue(new std::list<CacheEvent>())
- , id_manager(id_manager)
+ : id_manager(id_manager)
{
}
@@ -69,9 +67,6 @@ AudioCacheEventHandler::~AudioCacheEventHandler()
{
handleCloseCache(id);
}
-
- // Hack to be able to forward declare CacheEvent:
- delete eventqueue;
}
void AudioCacheEventHandler::start()
@@ -119,7 +114,7 @@ void AudioCacheEventHandler::setThreaded(bool threaded)
this->threaded = threaded;
}
-bool AudioCacheEventHandler::getThreaded() const
+bool AudioCacheEventHandler::isThreaded() const
{
return threaded;
}
@@ -206,7 +201,7 @@ AudioCacheFile& AudioCacheEventHandler::openFile(const std::string& filename)
void AudioCacheEventHandler::clearEvents()
{
// Iterate all events ignoring load events and handling close events.
- for(auto& event : *eventqueue)
+ for(auto& event : eventqueue)
{
if(event.eventType == EventType::Close)
{
@@ -214,7 +209,7 @@ void AudioCacheEventHandler::clearEvents()
}
}
- eventqueue->clear();
+ eventqueue.clear();
}
void AudioCacheEventHandler::handleLoadNextEvent(CacheEvent& cache_event)
@@ -263,14 +258,14 @@ void AudioCacheEventHandler::thread_main()
sem.wait();
mutex.lock();
- if(eventqueue->empty())
+ if(eventqueue.empty())
{
mutex.unlock();
continue;
}
- CacheEvent cache_event = eventqueue->front();
- eventqueue->pop_front();
+ CacheEvent cache_event = eventqueue.front();
+ eventqueue.pop_front();
mutex.unlock();
// TODO: Skip event if cache_event.pos < cache.pos
@@ -298,7 +293,7 @@ void AudioCacheEventHandler::pushEvent(CacheEvent& cache_event)
if(cache_event.eventType == EventType::LoadNext)
{
- for(auto& queued_event : *eventqueue)
+ for(auto& queued_event : eventqueue)
{
if((queued_event.eventType == EventType::LoadNext) &&
(cache_event.afile->getFilename() ==
@@ -318,7 +313,7 @@ void AudioCacheEventHandler::pushEvent(CacheEvent& cache_event)
if(!found)
{
// The event was not already on the list, create a new one.
- eventqueue->push_back(cache_event);
+ eventqueue.push_back(cache_event);
}
}
diff --git a/src/audiocacheeventhandler.h b/src/audiocacheeventhandler.h
index daf7bb9..473a010 100644
--- a/src/audiocacheeventhandler.h
+++ b/src/audiocacheeventhandler.h
@@ -59,7 +59,7 @@ public:
void setThreaded(bool threaded);
//! Get current threaded status.
- bool getThreaded() const;
+ bool isThreaded() const;
//! Lock thread mutex.
//! This methods are supplied to make this class lockable by std::lock_guard
@@ -101,7 +101,7 @@ protected:
std::mutex mutex;
- std::list<CacheEvent>* eventqueue;
+ std::list<CacheEvent> eventqueue;
bool threaded{false};
Semaphore sem;
diff --git a/src/audiocachefile.cc b/src/audiocachefile.cc
index 916ecb7..91fcecf 100644
--- a/src/audiocachefile.cc
+++ b/src/audiocachefile.cc
@@ -34,8 +34,9 @@
#include "audiocache.h"
-AudioCacheFile::AudioCacheFile(const std::string& filename)
- : filename(filename)
+AudioCacheFile::AudioCacheFile(const std::string& filename,
+ std::vector<sample_t>& read_buffer)
+ : filename(filename), read_buffer(read_buffer)
{
std::memset(&sf_info, 0, sizeof(SF_INFO));
@@ -49,7 +50,7 @@ AudioCacheFile::AudioCacheFile(const std::string& filename)
if(sf_info.frames == 0)
{
- printf("sf_info.frames == 0\n");
+ WARN(cache, "sf_info.frames == 0\n");
}
}
@@ -101,24 +102,18 @@ void AudioCacheFile::readChunk(const CacheChannels& channels,
size = num_samples;
}
- static sample_t *read_buffer = nullptr;
- static size_t read_buffer_size = 0;
-
- if((size * sf_info.channels) > read_buffer_size)
+ if((size * sf_info.channels) > read_buffer.size())
{
- delete[] read_buffer;
- read_buffer_size = size * sf_info.channels;
- read_buffer = new sample_t[read_buffer_size];
- // TODO: This buffer is never free'd on app shutdown.
+ read_buffer.resize(size * sf_info.channels);
}
- size_t read_size = sf_readf_float(fh, read_buffer, size);
+ size_t read_size = sf_readf_float(fh, read_buffer.data(), size);
(void)read_size;
for(auto it = channels.begin(); it != channels.end(); ++it)
{
size_t channel = it->channel;
- sample_t *data = it->samples;
+ sample_t* data = it->samples;
for (size_t i = 0; i < size; ++i)
{
data[i] = read_buffer[(i * sf_info.channels) + channel];
@@ -135,25 +130,25 @@ AudioCacheFile& AudioCacheFiles::getFile(const std::string& filename)
{
std::lock_guard<std::mutex> lock(mutex);
- AudioCacheFile* cacheAudioFile = nullptr;
+ AudioCacheFile* cache_audio_file = nullptr;
auto it = audiofiles.find(filename);
if(it == audiofiles.end())
{
- cacheAudioFile = new AudioCacheFile(filename);
- audiofiles.insert(std::make_pair(filename, cacheAudioFile));
+ cache_audio_file = new AudioCacheFile(filename, read_buffer);
+ audiofiles.insert(std::make_pair(filename, cache_audio_file));
}
else
{
- cacheAudioFile = it->second;
+ cache_audio_file = it->second;
}
- assert(cacheAudioFile);
+ assert(cache_audio_file);
// Increase ref count.
- ++cacheAudioFile->ref;
+ ++cache_audio_file->ref;
- return *cacheAudioFile;
+ return *cache_audio_file;
}
void AudioCacheFiles::releaseFile(const std::string& filename)
diff --git a/src/audiocachefile.h b/src/audiocachefile.h
index 9910563..8e40a2e 100644
--- a/src/audiocachefile.h
+++ b/src/audiocachefile.h
@@ -29,6 +29,7 @@
#include <string>
#include <list>
#include <map>
+#include <vector>
#include <mutex>
#include "mutex.h"
@@ -43,7 +44,7 @@ public:
size_t channel; //< Channel number
sample_t* samples; //< Sample buffer pointer.
size_t num_samples; //< Number of samples in the sample buffer
- volatile bool* ready; //< Is set to tru when the loading is done.
+ volatile bool* ready; //< Is set to true when the loading is done.
};
using CacheChannels = std::list<CacheChannel>;
@@ -56,7 +57,7 @@ class AudioCacheFile {
friend class TestableAudioCacheFiles;
public:
//! Create file handle for filename.
- AudioCacheFile(const std::string& filename);
+ AudioCacheFile(const std::string& filename, std::vector<sample_t>& read_buffer);
//! Closes file handle.
~AudioCacheFile();
@@ -78,6 +79,7 @@ private:
SNDFILE* fh{nullptr};
SF_INFO sf_info;
std::string filename;
+ std::vector<sample_t>& read_buffer;
};
class AudioCacheFiles {
@@ -95,4 +97,5 @@ public:
protected:
std::map<std::string, AudioCacheFile*> audiofiles;
std::mutex mutex;
+ std::vector<sample_t> read_buffer;
};
diff --git a/src/audiocacheidmanager.cc b/src/audiocacheidmanager.cc
index a3e16a0..444ac38 100644
--- a/src/audiocacheidmanager.cc
+++ b/src/audiocacheidmanager.cc
@@ -31,7 +31,7 @@
AudioCacheIDManager::~AudioCacheIDManager()
{
- assert(availableids.size() == id2cache.size()); // All ids should be released.
+ assert(available_ids.size() == id2cache.size()); // All ids should be released.
}
void AudioCacheIDManager::init(unsigned int capacity)
@@ -39,10 +39,10 @@ void AudioCacheIDManager::init(unsigned int capacity)
std::lock_guard<std::mutex> guard(mutex);
id2cache.resize(capacity);
- availableids.resize(capacity);
+ available_ids.resize(capacity);
for(size_t i = 0; i < capacity; ++i)
{
- availableids[i] = i;
+ available_ids[i] = i;
}
}
@@ -65,14 +65,14 @@ cacheid_t AudioCacheIDManager::registerID(const cache_t& cache)
cacheid_t id = CACHE_NOID;
- if(availableids.empty())
+ if(available_ids.empty())
{
return CACHE_DUMMYID;
}
else
{
- id = availableids.back();
- availableids.pop_back();
+ id = available_ids.back();
+ available_ids.pop_back();
}
assert(id2cache[id].id == CACHE_NOID); // Make sure it is not already in use
@@ -91,7 +91,7 @@ void AudioCacheIDManager::releaseID(cacheid_t id)
id2cache[id].id = CACHE_NOID;
- availableids.push_back(id);
+ available_ids.push_back(id);
}
void AudioCacheIDManager::disableActive()
diff --git a/src/audiocacheidmanager.h b/src/audiocacheidmanager.h
index 70f7ce1..7bf3169 100644
--- a/src/audiocacheidmanager.h
+++ b/src/audiocacheidmanager.h
@@ -89,5 +89,5 @@ protected:
std::mutex mutex;
std::vector<cache_t> id2cache;
- std::vector<cacheid_t> availableids;
+ std::vector<cacheid_t> available_ids;
};
diff --git a/src/audiofile.cc b/src/audiofile.cc
index e9b5976..b0ad4da 100644
--- a/src/audiofile.cc
+++ b/src/audiofile.cc
@@ -56,7 +56,7 @@ AudioFile::~AudioFile()
unload();
}
-bool AudioFile::isValid()
+bool AudioFile::isValid() const
{
return this == magic;
}
@@ -147,7 +147,7 @@ void AudioFile::load(int num_samples)
is_loaded = true;
}
-bool AudioFile::isLoaded()
+bool AudioFile::isLoaded() const
{
return is_loaded;
}
diff --git a/src/audiofile.h b/src/audiofile.h
index 3ca8b97..eb9440e 100644
--- a/src/audiofile.h
+++ b/src/audiofile.h
@@ -45,7 +45,7 @@ public:
void load(int num_samples = ALL_SAMPLES);
void unload();
- bool isLoaded();
+ bool isLoaded() const;
volatile size_t size{0}; // Full size of the file
volatile size_t preloadedsize{0}; // Number of samples preloaded (in data)
@@ -53,7 +53,7 @@ public:
std::string filename;
- bool isValid();
+ bool isValid() const;
Mutex mutex;
diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc
index a777125..f8f30b8 100644
--- a/src/drumgizmo.cc
+++ b/src/drumgizmo.cc
@@ -477,59 +477,59 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples)
typedef float vNsf __attribute__ ((vector_size(sizeof(sample_t)*N)));
#endif/*SSE*/
-void DrumGizmo::getSamples(int ch, int pos, sample_t *s, size_t sz)
+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* event = *i;
Event::type_t type = event->type();
switch(type) {
case Event::sample:
{
- EventSample *evt = (EventSample *)event;
- AudioFile *af = evt->file;
+ EventSample& evt = *static_cast<EventSample*>(event);
+ AudioFile& af = *evt.file;
- if(!af->isLoaded() || !af->isValid() || (s == nullptr))
+ 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))
+ if(evt.offset > (pos + sz))
{
continue;
}
- if(evt->cache_id == CACHE_NOID)
+ 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;
+ 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);
+ 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)
+ if(evt.offset > (size_t)pos)
{
- n = evt->offset - 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)
+ if((evt.t + end - n) > af.size)
{
- end = af->size - evt->t + n;
+ end = af.size - evt.t + n;
}
// This should not be necessary but make absolutely sure that we do
@@ -540,7 +540,7 @@ void DrumGizmo::getSamples(int ch, int pos, sample_t *s, size_t sz)
}
size_t t = 0; // Internal buffer counter
- if(evt->rampdown == NO_RAMPDOWN)
+ if(evt.rampdown == NO_RAMPDOWN)
{
#ifdef SSE
@@ -548,40 +548,40 @@ void DrumGizmo::getSamples(int ch, int pos, sample_t *s, size_t sz)
// Force source addr to be 16 byte aligned...
// (might skip 1 or 2 samples)
- while((size_t)&evt->buffer[t] % 16)
+ while((size_t)&evt.buffer[t] % 16)
{
++t;
}
- for(; (n < optend) && (t < evt->buffer_size); n += N)
+ for(; (n < optend) && (t < evt.buffer_size); n += N)
{
- *(vNsf*)&(s[n]) += *(vNsf*)&(evt->buffer[t]);
+ *(vNsf*)&(s[n]) += *(vNsf*)&(evt.buffer[t]);
t += N;
}
#endif
- for(; (n < end) && (t < evt->buffer_size); ++n)
+ for(; (n < end) && (t < evt.buffer_size); ++n)
{
- s[n] += evt->buffer[t];
+ s[n] += evt.buffer[t];
++t;
}
}
else
{ // Ramp down in progress.
- for(; (n < end) && (t < evt->buffer_size) && evt->rampdown; ++n)
+ 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;
+ float scale = (float)evt.rampdown/(float)evt.ramp_start;
+ s[n] += evt.buffer[t] * scale;
++t;
- evt->rampdown--;
+ evt.rampdown--;
}
}
// Add internal buffer counter to "global" event counter.
- evt->t += evt->buffer_size;
+ evt.t += evt.buffer_size;
- if((evt->t < af->size) && (evt->rampdown != 0))
+ if((evt.t < af.size) && (evt.rampdown != 0))
{
- evt->buffer = audioCache.next(evt->cache_id, evt->buffer_size);
+ evt.buffer = audioCache.next(evt.cache_id, evt.buffer_size);
}
else
{
@@ -590,7 +590,7 @@ void DrumGizmo::getSamples(int ch, int pos, sample_t *s, size_t sz)
if(removeevent)
{
- audioCache.close(evt->cache_id);
+ audioCache.close(evt.cache_id);
}
}
}
diff --git a/test/audiocachefiletest.cc b/test/audiocachefiletest.cc
index 98b7ab5..b7839b7 100644
--- a/test/audiocachefiletest.cc
+++ b/test/audiocachefiletest.cc
@@ -92,7 +92,9 @@ public:
ref_file[c]->load();
}
- AudioCacheFile file(filename);
+ std::vector<sample_t> read_buffer;
+
+ AudioCacheFile file(filename, read_buffer);
CPPUNIT_ASSERT_EQUAL(filename, file.getFilename());
CPPUNIT_ASSERT_EQUAL(13, (int)file.getChannelCount()); // Sanity check
@@ -188,7 +190,9 @@ public:
size_t buffer_size = 64;
std::string filename = "kits/no-such-file.wav";
- AudioCacheFile file(filename);
+ std::vector<sample_t> read_buffer;
+
+ AudioCacheFile file(filename, read_buffer);
CPPUNIT_ASSERT_EQUAL(filename, file.getFilename());
CPPUNIT_ASSERT_EQUAL(0u, (unsigned int)file.getSize());
CPPUNIT_ASSERT_EQUAL(0u, (unsigned int)file.getChannelCount());
diff --git a/test/audiocacheidmanagertest.cc b/test/audiocacheidmanagertest.cc
index a9cc878..eff7e78 100644
--- a/test/audiocacheidmanagertest.cc
+++ b/test/audiocacheidmanagertest.cc
@@ -34,7 +34,7 @@ class TestableAudioCacheIDManager
public:
int getAvailableIDs()
{
- return availableids.size();
+ return available_ids.size();
}
};
diff --git a/test/audiocachetest.cc b/test/audiocachetest.cc
index 5db5940..3ac63bf 100644
--- a/test/audiocachetest.cc
+++ b/test/audiocachetest.cc
@@ -81,7 +81,7 @@ public:
printf("open: initial_samples_needed: %d\n", (int)initial_samples_needed);
sample_t *samples =
- audio_cache.open(&audio_file, initial_samples_needed, channel, id);
+ audio_cache.open(audio_file, initial_samples_needed, channel, id);
size_t size = initial_samples_needed;
size_t offset = 0;