diff options
-rw-r--r-- | src/audiocache.cc | 40 | ||||
-rw-r--r-- | src/audiocache.h | 6 | ||||
-rw-r--r-- | src/audiocacheeventhandler.cc | 23 | ||||
-rw-r--r-- | src/audiocacheeventhandler.h | 4 | ||||
-rw-r--r-- | src/audiocachefile.cc | 35 | ||||
-rw-r--r-- | src/audiocachefile.h | 7 | ||||
-rw-r--r-- | src/audiocacheidmanager.cc | 14 | ||||
-rw-r--r-- | src/audiocacheidmanager.h | 2 | ||||
-rw-r--r-- | src/audiofile.cc | 4 | ||||
-rw-r--r-- | src/audiofile.h | 4 | ||||
-rw-r--r-- | src/drumgizmo.cc | 60 | ||||
-rw-r--r-- | test/audiocachefiletest.cc | 8 | ||||
-rw-r--r-- | test/audiocacheidmanagertest.cc | 2 | ||||
-rw-r--r-- | test/audiocachetest.cc | 2 |
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; |