Mercurial > hg > svcore
diff data/fileio/CodedAudioFileReader.cpp @ 148:1a42221a1522
* Reorganising code base. This revision will not compile.
author | Chris Cannam |
---|---|
date | Mon, 31 Jul 2006 11:49:58 +0000 |
parents | |
children | 900ac6667eab |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/fileio/CodedAudioFileReader.cpp Mon Jul 31 11:49:58 2006 +0000 @@ -0,0 +1,192 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006 Chris Cannam. + + This program 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. See the file + COPYING included with this distribution for more information. +*/ + +#include "CodedAudioFileReader.h" + +#include "WavFileReader.h" +#include "base/TempDirectory.h" +#include "base/Exceptions.h" + +#include <iostream> +#include <QDir> + +CodedAudioFileReader::CodedAudioFileReader(CacheMode cacheMode) : + m_cacheMode(cacheMode), + m_initialised(false), + m_cacheFileWritePtr(0), + m_cacheFileReader(0), + m_cacheWriteBuffer(0), + m_cacheWriteBufferIndex(0), + m_cacheWriteBufferSize(16384) +{ +} + +CodedAudioFileReader::~CodedAudioFileReader() +{ + if (m_cacheFileWritePtr) sf_close(m_cacheFileWritePtr); + if (m_cacheFileReader) delete m_cacheFileReader; + if (m_cacheWriteBuffer) delete[] m_cacheWriteBuffer; + + if (m_cacheFileName != "") { + if (!QFile(m_cacheFileName).remove()) { + std::cerr << "WARNING: CodedAudioFileReader::~CodedAudioFileReader: Failed to delete cache file \"" << m_cacheFileName.toStdString() << "\"" << std::endl; + } + } +} + +void +CodedAudioFileReader::initialiseDecodeCache() +{ + if (m_cacheMode == CacheInTemporaryFile) { + + m_cacheWriteBuffer = new float[m_cacheWriteBufferSize * m_channelCount]; + m_cacheWriteBufferIndex = 0; + + try { + QDir dir(TempDirectory::getInstance()->getPath()); + m_cacheFileName = dir.filePath(QString("decoded_%1.wav") + .arg((intptr_t)this)); + + SF_INFO fileInfo; + fileInfo.samplerate = m_sampleRate; + fileInfo.channels = m_channelCount; + fileInfo.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT; + + m_cacheFileWritePtr = sf_open(m_cacheFileName.toLocal8Bit(), + SFM_WRITE, &fileInfo); + + if (!m_cacheFileWritePtr) { + std::cerr << "CodedAudioFileReader::initialiseDecodeCache: failed to open cache file \"" << m_cacheFileName.toStdString() << "\" (" << m_channelCount << " channels, sample rate " << m_sampleRate << " for writing, falling back to in-memory cache" << std::endl; + m_cacheMode = CacheInMemory; + } + } catch (DirectoryCreationFailed f) { + std::cerr << "CodedAudioFileReader::initialiseDecodeCache: failed to create temporary directory! Falling back to in-memory cache" << std::endl; + m_cacheMode = CacheInMemory; + } + } + + if (m_cacheMode == CacheInMemory) { + m_data.clear(); + } + + m_initialised = true; +} + +void +CodedAudioFileReader::addSampleToDecodeCache(float sample) +{ + if (!m_initialised) return; + + switch (m_cacheMode) { + + case CacheInTemporaryFile: + + m_cacheWriteBuffer[m_cacheWriteBufferIndex++] = sample; + + if (m_cacheWriteBufferIndex == + m_cacheWriteBufferSize * m_channelCount) { + + //!!! check for return value! out of disk space, etc! + sf_writef_float(m_cacheFileWritePtr, + m_cacheWriteBuffer, + m_cacheWriteBufferSize); + + m_cacheWriteBufferIndex = 0; + } + break; + + case CacheInMemory: + m_data.push_back(sample); + break; + } +} + +void +CodedAudioFileReader::finishDecodeCache() +{ + if (!m_initialised) { + std::cerr << "WARNING: CodedAudioFileReader::finishDecodeCache: Cache was never initialised!" << std::endl; + return; + } + + switch (m_cacheMode) { + + case CacheInTemporaryFile: + + if (m_cacheWriteBufferIndex > 0) { + //!!! check for return value! out of disk space, etc! + sf_writef_float(m_cacheFileWritePtr, + m_cacheWriteBuffer, + m_cacheWriteBufferIndex / m_channelCount); + } + + if (m_cacheWriteBuffer) { + delete[] m_cacheWriteBuffer; + m_cacheWriteBuffer = 0; + } + + m_cacheWriteBufferIndex = 0; + + sf_close(m_cacheFileWritePtr); + m_cacheFileWritePtr = 0; + + m_cacheFileReader = new WavFileReader(m_cacheFileName); + + if (!m_cacheFileReader->isOK()) { + std::cerr << "ERROR: CodedAudioFileReader::finishDecodeCache: Failed to construct WAV file reader for temporary file: " << m_cacheFileReader->getError().toStdString() << std::endl; + delete m_cacheFileReader; + m_cacheFileReader = 0; + } + break; + + case CacheInMemory: + // nothing to do + break; + } +} + +void +CodedAudioFileReader::getInterleavedFrames(size_t start, size_t count, + SampleBlock &frames) const +{ + if (!m_initialised) return; + + switch (m_cacheMode) { + + case CacheInTemporaryFile: + if (m_cacheFileReader) { + m_cacheFileReader->getInterleavedFrames(start, count, frames); + } + break; + + case CacheInMemory: + { + frames.clear(); + if (!isOK()) return; + if (count == 0) return; + + // slownessabounds + + for (size_t i = start; i < start + count; ++i) { + for (size_t ch = 0; ch < m_channelCount; ++ch) { + size_t index = i * m_channelCount + ch; + if (index >= m_data.size()) return; + frames.push_back(m_data[index]); + } + } + } + } +} +