annotate data/fileio/CodedAudioFileReader.cpp @ 205:05154c7bb90b

* Basics of an approximate way of managing memory that we've committed to using but haven't allocated yet
author Chris Cannam
date Fri, 15 Dec 2006 18:05:31 +0000
parents 900ac6667eab
children 71dfc6ab3b54
rev   line source
Chris@148 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@148 2
Chris@148 3 /*
Chris@148 4 Sonic Visualiser
Chris@148 5 An audio file viewer and annotation editor.
Chris@148 6 Centre for Digital Music, Queen Mary, University of London.
Chris@148 7 This file copyright 2006 Chris Cannam.
Chris@148 8
Chris@148 9 This program is free software; you can redistribute it and/or
Chris@148 10 modify it under the terms of the GNU General Public License as
Chris@148 11 published by the Free Software Foundation; either version 2 of the
Chris@148 12 License, or (at your option) any later version. See the file
Chris@148 13 COPYING included with this distribution for more information.
Chris@148 14 */
Chris@148 15
Chris@148 16 #include "CodedAudioFileReader.h"
Chris@148 17
Chris@148 18 #include "WavFileReader.h"
Chris@148 19 #include "base/TempDirectory.h"
Chris@148 20 #include "base/Exceptions.h"
Chris@192 21 #include "base/Profiler.h"
Chris@148 22
Chris@148 23 #include <iostream>
Chris@148 24 #include <QDir>
Chris@148 25
Chris@148 26 CodedAudioFileReader::CodedAudioFileReader(CacheMode cacheMode) :
Chris@148 27 m_cacheMode(cacheMode),
Chris@148 28 m_initialised(false),
Chris@148 29 m_cacheFileWritePtr(0),
Chris@148 30 m_cacheFileReader(0),
Chris@148 31 m_cacheWriteBuffer(0),
Chris@148 32 m_cacheWriteBufferIndex(0),
Chris@148 33 m_cacheWriteBufferSize(16384)
Chris@148 34 {
Chris@148 35 }
Chris@148 36
Chris@148 37 CodedAudioFileReader::~CodedAudioFileReader()
Chris@148 38 {
Chris@148 39 if (m_cacheFileWritePtr) sf_close(m_cacheFileWritePtr);
Chris@148 40 if (m_cacheFileReader) delete m_cacheFileReader;
Chris@148 41 if (m_cacheWriteBuffer) delete[] m_cacheWriteBuffer;
Chris@148 42
Chris@148 43 if (m_cacheFileName != "") {
Chris@148 44 if (!QFile(m_cacheFileName).remove()) {
Chris@148 45 std::cerr << "WARNING: CodedAudioFileReader::~CodedAudioFileReader: Failed to delete cache file \"" << m_cacheFileName.toStdString() << "\"" << std::endl;
Chris@148 46 }
Chris@148 47 }
Chris@148 48 }
Chris@148 49
Chris@148 50 void
Chris@148 51 CodedAudioFileReader::initialiseDecodeCache()
Chris@148 52 {
Chris@148 53 if (m_cacheMode == CacheInTemporaryFile) {
Chris@148 54
Chris@148 55 m_cacheWriteBuffer = new float[m_cacheWriteBufferSize * m_channelCount];
Chris@148 56 m_cacheWriteBufferIndex = 0;
Chris@148 57
Chris@148 58 try {
Chris@148 59 QDir dir(TempDirectory::getInstance()->getPath());
Chris@148 60 m_cacheFileName = dir.filePath(QString("decoded_%1.wav")
Chris@148 61 .arg((intptr_t)this));
Chris@148 62
Chris@148 63 SF_INFO fileInfo;
Chris@148 64 fileInfo.samplerate = m_sampleRate;
Chris@148 65 fileInfo.channels = m_channelCount;
Chris@148 66 fileInfo.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT;
Chris@148 67
Chris@148 68 m_cacheFileWritePtr = sf_open(m_cacheFileName.toLocal8Bit(),
Chris@148 69 SFM_WRITE, &fileInfo);
Chris@148 70
Chris@148 71 if (!m_cacheFileWritePtr) {
Chris@148 72 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;
Chris@148 73 m_cacheMode = CacheInMemory;
Chris@148 74 }
Chris@148 75 } catch (DirectoryCreationFailed f) {
Chris@148 76 std::cerr << "CodedAudioFileReader::initialiseDecodeCache: failed to create temporary directory! Falling back to in-memory cache" << std::endl;
Chris@148 77 m_cacheMode = CacheInMemory;
Chris@148 78 }
Chris@148 79 }
Chris@148 80
Chris@148 81 if (m_cacheMode == CacheInMemory) {
Chris@148 82 m_data.clear();
Chris@148 83 }
Chris@148 84
Chris@148 85 m_initialised = true;
Chris@148 86 }
Chris@148 87
Chris@148 88 void
Chris@148 89 CodedAudioFileReader::addSampleToDecodeCache(float sample)
Chris@148 90 {
Chris@148 91 if (!m_initialised) return;
Chris@148 92
Chris@148 93 switch (m_cacheMode) {
Chris@148 94
Chris@148 95 case CacheInTemporaryFile:
Chris@148 96
Chris@148 97 m_cacheWriteBuffer[m_cacheWriteBufferIndex++] = sample;
Chris@148 98
Chris@148 99 if (m_cacheWriteBufferIndex ==
Chris@148 100 m_cacheWriteBufferSize * m_channelCount) {
Chris@148 101
Chris@148 102 //!!! check for return value! out of disk space, etc!
Chris@148 103 sf_writef_float(m_cacheFileWritePtr,
Chris@148 104 m_cacheWriteBuffer,
Chris@148 105 m_cacheWriteBufferSize);
Chris@148 106
Chris@148 107 m_cacheWriteBufferIndex = 0;
Chris@148 108 }
Chris@148 109 break;
Chris@148 110
Chris@148 111 case CacheInMemory:
Chris@148 112 m_data.push_back(sample);
Chris@148 113 break;
Chris@148 114 }
Chris@148 115 }
Chris@148 116
Chris@148 117 void
Chris@148 118 CodedAudioFileReader::finishDecodeCache()
Chris@148 119 {
Chris@192 120 Profiler profiler("CodedAudioFileReader::finishDecodeCache", true);
Chris@192 121
Chris@148 122 if (!m_initialised) {
Chris@148 123 std::cerr << "WARNING: CodedAudioFileReader::finishDecodeCache: Cache was never initialised!" << std::endl;
Chris@148 124 return;
Chris@148 125 }
Chris@148 126
Chris@148 127 switch (m_cacheMode) {
Chris@148 128
Chris@148 129 case CacheInTemporaryFile:
Chris@148 130
Chris@148 131 if (m_cacheWriteBufferIndex > 0) {
Chris@148 132 //!!! check for return value! out of disk space, etc!
Chris@148 133 sf_writef_float(m_cacheFileWritePtr,
Chris@148 134 m_cacheWriteBuffer,
Chris@148 135 m_cacheWriteBufferIndex / m_channelCount);
Chris@148 136 }
Chris@148 137
Chris@148 138 if (m_cacheWriteBuffer) {
Chris@148 139 delete[] m_cacheWriteBuffer;
Chris@148 140 m_cacheWriteBuffer = 0;
Chris@148 141 }
Chris@148 142
Chris@148 143 m_cacheWriteBufferIndex = 0;
Chris@148 144
Chris@148 145 sf_close(m_cacheFileWritePtr);
Chris@148 146 m_cacheFileWritePtr = 0;
Chris@148 147
Chris@148 148 m_cacheFileReader = new WavFileReader(m_cacheFileName);
Chris@148 149
Chris@148 150 if (!m_cacheFileReader->isOK()) {
Chris@148 151 std::cerr << "ERROR: CodedAudioFileReader::finishDecodeCache: Failed to construct WAV file reader for temporary file: " << m_cacheFileReader->getError().toStdString() << std::endl;
Chris@148 152 delete m_cacheFileReader;
Chris@148 153 m_cacheFileReader = 0;
Chris@148 154 }
Chris@148 155 break;
Chris@148 156
Chris@148 157 case CacheInMemory:
Chris@148 158 // nothing to do
Chris@148 159 break;
Chris@148 160 }
Chris@148 161 }
Chris@148 162
Chris@148 163 void
Chris@148 164 CodedAudioFileReader::getInterleavedFrames(size_t start, size_t count,
Chris@148 165 SampleBlock &frames) const
Chris@148 166 {
Chris@148 167 if (!m_initialised) return;
Chris@148 168
Chris@148 169 switch (m_cacheMode) {
Chris@148 170
Chris@148 171 case CacheInTemporaryFile:
Chris@148 172 if (m_cacheFileReader) {
Chris@148 173 m_cacheFileReader->getInterleavedFrames(start, count, frames);
Chris@148 174 }
Chris@148 175 break;
Chris@148 176
Chris@148 177 case CacheInMemory:
Chris@148 178 {
Chris@148 179 frames.clear();
Chris@148 180 if (!isOK()) return;
Chris@148 181 if (count == 0) return;
Chris@148 182
Chris@148 183 // slownessabounds
Chris@148 184
Chris@148 185 for (size_t i = start; i < start + count; ++i) {
Chris@148 186 for (size_t ch = 0; ch < m_channelCount; ++ch) {
Chris@148 187 size_t index = i * m_channelCount + ch;
Chris@148 188 if (index >= m_data.size()) return;
Chris@148 189 frames.push_back(m_data[index]);
Chris@148 190 }
Chris@148 191 }
Chris@148 192 }
Chris@148 193 }
Chris@148 194 }
Chris@148 195