From 84e2cacec69c73712100de31585da3fe96c94704 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Thu, 24 Dec 2015 17:49:09 +0100 Subject: Split internal CacheManager AFile class out into it's own file/class CacheAudioFile and improve interface. --- src/cacheaudiofile.cc | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 src/cacheaudiofile.cc (limited to 'src/cacheaudiofile.cc') diff --git a/src/cacheaudiofile.cc b/src/cacheaudiofile.cc new file mode 100644 index 0000000..0d4aec9 --- /dev/null +++ b/src/cacheaudiofile.cc @@ -0,0 +1,156 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * cacheaudiofile.cc + * + * Thu Dec 24 12:17:58 CET 2015 + * Copyright 2015 Bent Bisballe Nyeng + * deva@aasimon.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. + */ +#include "cacheaudiofile.h" + +#include + +#include + +#include + +#include "cachemanager.h" + +CacheAudioFile::CacheAudioFile(const std::string& filename) + : filename(filename) +{ + fh = sf_open(filename.c_str(), SFM_READ, &sf_info); + if(!fh) + { + ERR(audiofile,"SNDFILE Error (%s): %s\n", + filename.c_str(), sf_strerror(fh)); + } +} + +CacheAudioFile::~CacheAudioFile() +{ + if(fh) + { + sf_close(fh); + fh = nullptr; + } +} + +size_t CacheAudioFile::getSize() const +{ + return sf_info.frames; +} + +const std::string& CacheAudioFile::getFilename() const +{ + return filename; +} + +void CacheAudioFile::readChunk(const CacheChannels& channels, + size_t pos, size_t num_samples) +{ + if(fh == nullptr) + { + printf("File handle is null.\n"); + return; + } + + if(pos > sf_info.frames) + { + printf("pos > sf_info.frames\n"); + return; + } + + sf_seek(fh, pos, + SEEK_SET); + + size_t size = sf_info.frames - pos; + if(size > num_samples) + { + size = num_samples; + } + + static sample_t *read_buffer = nullptr; + static size_t read_buffer_size = 0; + + 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. + } + + size_t read_size = sf_readf_float(fh, read_buffer, size); + (void)read_size; + + for(auto it = channels.begin(); it != channels.end(); ++it) + { + size_t channel = it->channel; + sample_t *data = it->samples; + for (size_t i = 0; i < size; ++i) + { + data[i] = read_buffer[(i * sf_info.channels) + channel]; + } + } + + for(auto it = channels.begin(); it != channels.end(); ++it) + { + *(it->ready) = true; + } +} + +CacheAudioFile& CacheAudioFiles::getAudioFile(const std::string filename) +{ + auto it = audiofiles.find(filename); + if(it == audiofiles.end()) + { + it = audiofiles.insert(audiofiles.begin(), std::make_pair(filename, new CacheAudioFile(filename))); + //it = audiofiles.find(filename); + } + + auto afile = it->second; + + // Increase ref count. + ++afile->ref; + + return *afile; +} + +void CacheAudioFiles::release(const std::string filename) +{ + auto it = audiofiles.find(filename); + if(it == audiofiles.end()) + { + return; // not open + } + + auto audiofile = it->second; + + assert(audiofile->ref); // If ref is not > 0 it shouldn't be in the map. + + --audiofile->ref; + if(audiofile->ref == 0) + { + delete audiofile; + audiofiles.erase(it); + } +} -- cgit v1.2.3