From 7788892bfb8aaceaa67fccad1ea4aff325a5ac32 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Tue, 19 Jan 2016 08:32:44 +0100 Subject: Split CacheManager into several AudioCache classes and refactored the lot of them. Unit tests added. --- src/audiocache.h | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 src/audiocache.h (limited to 'src/audiocache.h') diff --git a/src/audiocache.h b/src/audiocache.h new file mode 100644 index 0000000..824db3a --- /dev/null +++ b/src/audiocache.h @@ -0,0 +1,136 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * cachemanager.h + * + * Fri Apr 10 10:39:24 CEST 2015 + * Copyright 2015 Jonas Suhr Christensen + * jsc@umbraculum.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include +#include +#include + +#include "audiotypes.h" +#include "audiofile.h" + +#include "audiocachefile.h" +#include "audiocacheidmanager.h" +#include "audiocacheeventhandler.h" + +#define CHUNK_MULTIPLIER 16 + + +//TODO: +// 1: Move nodata initialisation to init method. +// 2: Make semaphore in thread to block init call until thread has been started. + +//// next +// Pre: preloaded contains 2 x framesize. chunk size is framesize. +// allocate 2 chunks and copy initial_samples_needed to first buffer from +// preloaded data and enough to fill up the second buffer from preloaded +// 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 + +//// next +// Return which ever buffer is the front, swap them and add event to load the +// next chunk. + +//// close +// 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. + +class AudioCache { +public: + AudioCache() = default; + + //! Destroy object and stop thread if needed. + ~AudioCache(); + + //! Initialise cache manager and allocate needed resources + //! This method starts the cache manager thread. + //! This method blocks until the thread has been started. + //! \param poolsize The maximum number of parellel events supported. + void init(size_t poolsize); + + //! Stop thread and clean up resources. + //! This method blocks until the thread has stopped. + void deinit(); + + //! Register new cache entry. + //! Prepares an entry in the cache manager for future disk streaming. + //! \param file A pointer to the file which is to be streamed from. + //! \param initial_samples_needed The number of samples needed in the first + //! read that is not nessecarily of framesize. This is the number of samples + //! from the input event offset to the end of the frame in which it resides. + //! initial_samples_needed <= framesize. + //! \param channel The channel to which the cache id will be bound. + //! \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, + cacheid_t& new_id); + + //! Get next buffer. + //! Returns the next buffer for reading based on cache id. + //! This function will (if needed) schedule a new disk read to make sure that + //! data is available in the next call to this method. + //! \param id The cache id to read from. + //! \param [out] size The size of the returned buffer. + //! \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 form disk. + bool isReady(cacheid_t id); + + //! Unregister cache entry. + //! Close associated file handles and free associated buffers. + //! \param id The cache id to close. + void close(cacheid_t id); + + //! Set/get internal framesize used when iterating through cache buffers. + void setFrameSize(size_t framesize); + size_t frameSize() const; + + //! Control/get reader threaded mode. + //! True means reading happening threaded, false means all reading done + //! synchronious. + void setAsyncMode(bool async); + bool asyncMode() const; + + //! Return the number of chunks that were read too late. + size_t getNumberOfUnderruns() const; + + //! Set underrun counter to 0. + void resetNumberOfUnderruns(); + +private: + size_t framesize{0}; + sample_t *nodata{nullptr}; + size_t numberOfUnderruns{0}; + + AudioCacheIDManager idManager; + AudioCacheEventHandler eventHandler{idManager}; +}; -- cgit v1.2.3