annotate data/fileio/CodedAudioFileReader.cpp @ 168:04baa690f90d

* Start adding StorageAdviser class to determine whether caches should be on disc or in memory
author Chris Cannam
date Mon, 25 Sep 2006 13:44:05 +0000
parents 1a42221a1522
children 900ac6667eab
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@148 21
Chris@148 22 #include <iostream>
Chris@148 23 #include <QDir>
Chris@148 24
Chris@148 25 CodedAudioFileReader::CodedAudioFileReader(CacheMode cacheMode) :
Chris@148 26 m_cacheMode(cacheMode),
Chris@148 27 m_initialised(false),
Chris@148 28 m_cacheFileWritePtr(0),
Chris@148 29 m_cacheFileReader(0),
Chris@148 30 m_cacheWriteBuffer(0),
Chris@148 31 m_cacheWriteBufferIndex(0),
Chris@148 32 m_cacheWriteBufferSize(16384)
Chris@148 33 {
Chris@148 34 }
Chris@148 35
Chris@148 36 CodedAudioFileReader::~CodedAudioFileReader()
Chris@148 37 {
Chris@148 38 if (m_cacheFileWritePtr) sf_close(m_cacheFileWritePtr);
Chris@148 39 if (m_cacheFileReader) delete m_cacheFileReader;
Chris@148 40 if (m_cacheWriteBuffer) delete[] m_cacheWriteBuffer;
Chris@148 41
Chris@148 42 if (m_cacheFileName != "") {
Chris@148 43 if (!QFile(m_cacheFileName).remove()) {
Chris@148 44 std::cerr << "WARNING: CodedAudioFileReader::~CodedAudioFileReader: Failed to delete cache file \"" << m_cacheFileName.toStdString() << "\"" << std::endl;
Chris@148 45 }
Chris@148 46 }
Chris@148 47 }
Chris@148 48
Chris@148 49 void
Chris@148 50 CodedAudioFileReader::initialiseDecodeCache()
Chris@148 51 {
Chris@148 52 if (m_cacheMode == CacheInTemporaryFile) {
Chris@148 53
Chris@148 54 m_cacheWriteBuffer = new float[m_cacheWriteBufferSize * m_channelCount];
Chris@148 55 m_cacheWriteBufferIndex = 0;
Chris@148 56
Chris@148 57 try {
Chris@148 58 QDir dir(TempDirectory::getInstance()->getPath());
Chris@148 59 m_cacheFileName = dir.filePath(QString("decoded_%1.wav")
Chris@148 60 .arg((intptr_t)this));
Chris@148 61
Chris@148 62 SF_INFO fileInfo;
Chris@148 63 fileInfo.samplerate = m_sampleRate;
Chris@148 64 fileInfo.channels = m_channelCount;
Chris@148 65 fileInfo.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT;
Chris@148 66
Chris@148 67 m_cacheFileWritePtr = sf_open(m_cacheFileName.toLocal8Bit(),
Chris@148 68 SFM_WRITE, &fileInfo);
Chris@148 69
Chris@148 70 if (!m_cacheFileWritePtr) {
Chris@148 71 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 72 m_cacheMode = CacheInMemory;
Chris@148 73 }
Chris@148 74 } catch (DirectoryCreationFailed f) {
Chris@148 75 std::cerr << "CodedAudioFileReader::initialiseDecodeCache: failed to create temporary directory! Falling back to in-memory cache" << std::endl;
Chris@148 76 m_cacheMode = CacheInMemory;
Chris@148 77 }
Chris@148 78 }
Chris@148 79
Chris@148 80 if (m_cacheMode == CacheInMemory) {
Chris@148 81 m_data.clear();
Chris@148 82 }
Chris@148 83
Chris@148 84 m_initialised = true;
Chris@148 85 }
Chris@148 86
Chris@148 87 void
Chris@148 88 CodedAudioFileReader::addSampleToDecodeCache(float sample)
Chris@148 89 {
Chris@148 90 if (!m_initialised) return;
Chris@148 91
Chris@148 92 switch (m_cacheMode) {
Chris@148 93
Chris@148 94 case CacheInTemporaryFile:
Chris@148 95
Chris@148 96 m_cacheWriteBuffer[m_cacheWriteBufferIndex++] = sample;
Chris@148 97
Chris@148 98 if (m_cacheWriteBufferIndex ==
Chris@148 99 m_cacheWriteBufferSize * m_channelCount) {
Chris@148 100
Chris@148 101 //!!! check for return value! out of disk space, etc!
Chris@148 102 sf_writef_float(m_cacheFileWritePtr,
Chris@148 103 m_cacheWriteBuffer,
Chris@148 104 m_cacheWriteBufferSize);
Chris@148 105
Chris@148 106 m_cacheWriteBufferIndex = 0;
Chris@148 107 }
Chris@148 108 break;
Chris@148 109
Chris@148 110 case CacheInMemory:
Chris@148 111 m_data.push_back(sample);
Chris@148 112 break;
Chris@148 113 }
Chris@148 114 }
Chris@148 115
Chris@148 116 void
Chris@148 117 CodedAudioFileReader::finishDecodeCache()
Chris@148 118 {
Chris@148 119 if (!m_initialised) {
Chris@148 120 std::cerr << "WARNING: CodedAudioFileReader::finishDecodeCache: Cache was never initialised!" << std::endl;
Chris@148 121 return;
Chris@148 122 }
Chris@148 123
Chris@148 124 switch (m_cacheMode) {
Chris@148 125
Chris@148 126 case CacheInTemporaryFile:
Chris@148 127
Chris@148 128 if (m_cacheWriteBufferIndex > 0) {
Chris@148 129 //!!! check for return value! out of disk space, etc!
Chris@148 130 sf_writef_float(m_cacheFileWritePtr,
Chris@148 131 m_cacheWriteBuffer,
Chris@148 132 m_cacheWriteBufferIndex / m_channelCount);
Chris@148 133 }
Chris@148 134
Chris@148 135 if (m_cacheWriteBuffer) {
Chris@148 136 delete[] m_cacheWriteBuffer;
Chris@148 137 m_cacheWriteBuffer = 0;
Chris@148 138 }
Chris@148 139
Chris@148 140 m_cacheWriteBufferIndex = 0;
Chris@148 141
Chris@148 142 sf_close(m_cacheFileWritePtr);
Chris@148 143 m_cacheFileWritePtr = 0;
Chris@148 144
Chris@148 145 m_cacheFileReader = new WavFileReader(m_cacheFileName);
Chris@148 146
Chris@148 147 if (!m_cacheFileReader->isOK()) {
Chris@148 148 std::cerr << "ERROR: CodedAudioFileReader::finishDecodeCache: Failed to construct WAV file reader for temporary file: " << m_cacheFileReader->getError().toStdString() << std::endl;
Chris@148 149 delete m_cacheFileReader;
Chris@148 150 m_cacheFileReader = 0;
Chris@148 151 }
Chris@148 152 break;
Chris@148 153
Chris@148 154 case CacheInMemory:
Chris@148 155 // nothing to do
Chris@148 156 break;
Chris@148 157 }
Chris@148 158 }
Chris@148 159
Chris@148 160 void
Chris@148 161 CodedAudioFileReader::getInterleavedFrames(size_t start, size_t count,
Chris@148 162 SampleBlock &frames) const
Chris@148 163 {
Chris@148 164 if (!m_initialised) return;
Chris@148 165
Chris@148 166 switch (m_cacheMode) {
Chris@148 167
Chris@148 168 case CacheInTemporaryFile:
Chris@148 169 if (m_cacheFileReader) {
Chris@148 170 m_cacheFileReader->getInterleavedFrames(start, count, frames);
Chris@148 171 }
Chris@148 172 break;
Chris@148 173
Chris@148 174 case CacheInMemory:
Chris@148 175 {
Chris@148 176 frames.clear();
Chris@148 177 if (!isOK()) return;
Chris@148 178 if (count == 0) return;
Chris@148 179
Chris@148 180 // slownessabounds
Chris@148 181
Chris@148 182 for (size_t i = start; i < start + count; ++i) {
Chris@148 183 for (size_t ch = 0; ch < m_channelCount; ++ch) {
Chris@148 184 size_t index = i * m_channelCount + ch;
Chris@148 185 if (index >= m_data.size()) return;
Chris@148 186 frames.push_back(m_data[index]);
Chris@148 187 }
Chris@148 188 }
Chris@148 189 }
Chris@148 190 }
Chris@148 191 }
Chris@148 192