annotate data/fileio/CodedAudioFileReader.cpp @ 294:2c1e57ad86e7

* Show colour swatch next to layer name in pane (if available) * Fix for incorrect layer name prefix handling (was making some layers appear to have the same model name in cases where the model names differed by the final character only)
author Chris Cannam
date Wed, 05 Sep 2007 15:17:15 +0000
parents 92e8dbde73cd
children c022976d18e8
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@263 25 #include <QMutexLocker>
Chris@148 26
Chris@148 27 CodedAudioFileReader::CodedAudioFileReader(CacheMode cacheMode) :
Chris@148 28 m_cacheMode(cacheMode),
Chris@148 29 m_initialised(false),
Chris@148 30 m_cacheFileWritePtr(0),
Chris@148 31 m_cacheFileReader(0),
Chris@148 32 m_cacheWriteBuffer(0),
Chris@148 33 m_cacheWriteBufferIndex(0),
Chris@148 34 m_cacheWriteBufferSize(16384)
Chris@148 35 {
Chris@148 36 }
Chris@148 37
Chris@148 38 CodedAudioFileReader::~CodedAudioFileReader()
Chris@148 39 {
Chris@263 40 QMutexLocker locker(&m_cacheMutex);
Chris@263 41
Chris@148 42 if (m_cacheFileWritePtr) sf_close(m_cacheFileWritePtr);
Chris@148 43 if (m_cacheFileReader) delete m_cacheFileReader;
Chris@148 44 if (m_cacheWriteBuffer) delete[] m_cacheWriteBuffer;
Chris@148 45
Chris@148 46 if (m_cacheFileName != "") {
Chris@290 47 if (!QFile(m_cacheFileName).remove()) {
Chris@290 48 std::cerr << "WARNING: CodedAudioFileReader::~CodedAudioFileReader: Failed to delete cache file \"" << m_cacheFileName.toStdString() << "\"" << std::endl;
Chris@148 49 }
Chris@148 50 }
Chris@148 51 }
Chris@148 52
Chris@148 53 void
Chris@148 54 CodedAudioFileReader::initialiseDecodeCache()
Chris@148 55 {
Chris@263 56 QMutexLocker locker(&m_cacheMutex);
Chris@263 57
Chris@148 58 if (m_cacheMode == CacheInTemporaryFile) {
Chris@148 59
Chris@148 60 m_cacheWriteBuffer = new float[m_cacheWriteBufferSize * m_channelCount];
Chris@148 61 m_cacheWriteBufferIndex = 0;
Chris@148 62
Chris@148 63 try {
Chris@148 64 QDir dir(TempDirectory::getInstance()->getPath());
Chris@148 65 m_cacheFileName = dir.filePath(QString("decoded_%1.wav")
Chris@290 66 .arg((intptr_t)this));
Chris@148 67
Chris@148 68 SF_INFO fileInfo;
Chris@148 69 fileInfo.samplerate = m_sampleRate;
Chris@148 70 fileInfo.channels = m_channelCount;
Chris@148 71 fileInfo.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT;
Chris@148 72
Chris@290 73 m_cacheFileWritePtr = sf_open(m_cacheFileName.toLocal8Bit(),
Chris@148 74 SFM_WRITE, &fileInfo);
Chris@148 75
Chris@265 76 if (m_cacheFileWritePtr) {
Chris@265 77
Chris@265 78 //!!! really want to do this now only if we're in a
Chris@265 79 //threaded mode -- creating the reader later if we're
Chris@265 80 //not threaded -- but we don't have access to that
Chris@265 81 //information here
Chris@265 82
Chris@265 83 m_cacheFileReader = new WavFileReader(m_cacheFileName);
Chris@265 84
Chris@265 85 if (!m_cacheFileReader->isOK()) {
Chris@290 86 std::cerr << "ERROR: CodedAudioFileReader::initialiseDecodeCache: Failed to construct WAV file reader for temporary file: " << m_cacheFileReader->getError().toStdString() << std::endl;
Chris@265 87 delete m_cacheFileReader;
Chris@265 88 m_cacheFileReader = 0;
Chris@265 89 m_cacheMode = CacheInMemory;
Chris@265 90 sf_close(m_cacheFileWritePtr);
Chris@265 91 }
Chris@265 92 } else {
Chris@290 93 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 94 m_cacheMode = CacheInMemory;
Chris@148 95 }
Chris@265 96
Chris@148 97 } catch (DirectoryCreationFailed f) {
Chris@148 98 std::cerr << "CodedAudioFileReader::initialiseDecodeCache: failed to create temporary directory! Falling back to in-memory cache" << std::endl;
Chris@148 99 m_cacheMode = CacheInMemory;
Chris@148 100 }
Chris@148 101 }
Chris@148 102
Chris@148 103 if (m_cacheMode == CacheInMemory) {
Chris@148 104 m_data.clear();
Chris@148 105 }
Chris@148 106
Chris@148 107 m_initialised = true;
Chris@148 108 }
Chris@148 109
Chris@148 110 void
Chris@148 111 CodedAudioFileReader::addSampleToDecodeCache(float sample)
Chris@148 112 {
Chris@263 113 QMutexLocker locker(&m_cacheMutex);
Chris@263 114
Chris@148 115 if (!m_initialised) return;
Chris@148 116
Chris@148 117 switch (m_cacheMode) {
Chris@148 118
Chris@148 119 case CacheInTemporaryFile:
Chris@148 120
Chris@148 121 m_cacheWriteBuffer[m_cacheWriteBufferIndex++] = sample;
Chris@148 122
Chris@148 123 if (m_cacheWriteBufferIndex ==
Chris@148 124 m_cacheWriteBufferSize * m_channelCount) {
Chris@148 125
Chris@148 126 //!!! check for return value! out of disk space, etc!
Chris@148 127 sf_writef_float(m_cacheFileWritePtr,
Chris@148 128 m_cacheWriteBuffer,
Chris@148 129 m_cacheWriteBufferSize);
Chris@148 130
Chris@148 131 m_cacheWriteBufferIndex = 0;
Chris@266 132 }
Chris@265 133
Chris@266 134 if (m_cacheWriteBufferIndex % 10240 == 0 &&
Chris@266 135 m_cacheFileReader) {
Chris@266 136 m_cacheFileReader->updateFrameCount();
Chris@148 137 }
Chris@148 138 break;
Chris@148 139
Chris@148 140 case CacheInMemory:
Chris@148 141 m_data.push_back(sample);
Chris@148 142 break;
Chris@148 143 }
Chris@148 144 }
Chris@148 145
Chris@148 146 void
Chris@148 147 CodedAudioFileReader::finishDecodeCache()
Chris@148 148 {
Chris@263 149 QMutexLocker locker(&m_cacheMutex);
Chris@263 150
Chris@192 151 Profiler profiler("CodedAudioFileReader::finishDecodeCache", true);
Chris@192 152
Chris@148 153 if (!m_initialised) {
Chris@148 154 std::cerr << "WARNING: CodedAudioFileReader::finishDecodeCache: Cache was never initialised!" << std::endl;
Chris@148 155 return;
Chris@148 156 }
Chris@148 157
Chris@148 158 switch (m_cacheMode) {
Chris@148 159
Chris@148 160 case CacheInTemporaryFile:
Chris@148 161
Chris@148 162 if (m_cacheWriteBufferIndex > 0) {
Chris@148 163 //!!! check for return value! out of disk space, etc!
Chris@148 164 sf_writef_float(m_cacheFileWritePtr,
Chris@148 165 m_cacheWriteBuffer,
Chris@148 166 m_cacheWriteBufferIndex / m_channelCount);
Chris@148 167 }
Chris@148 168
Chris@148 169 if (m_cacheWriteBuffer) {
Chris@148 170 delete[] m_cacheWriteBuffer;
Chris@148 171 m_cacheWriteBuffer = 0;
Chris@148 172 }
Chris@148 173
Chris@148 174 m_cacheWriteBufferIndex = 0;
Chris@148 175
Chris@148 176 sf_close(m_cacheFileWritePtr);
Chris@148 177 m_cacheFileWritePtr = 0;
Chris@148 178
Chris@265 179 m_cacheFileReader->updateFrameCount();
Chris@265 180 /*
Chris@148 181 m_cacheFileReader = new WavFileReader(m_cacheFileName);
Chris@148 182
Chris@148 183 if (!m_cacheFileReader->isOK()) {
Chris@290 184 std::cerr << "ERROR: CodedAudioFileReader::finishDecodeCache: Failed to construct WAV file reader for temporary file: " << m_cacheFileReader->getError().toStdString() << std::endl;
Chris@148 185 delete m_cacheFileReader;
Chris@148 186 m_cacheFileReader = 0;
Chris@265 187 }*/
Chris@265 188
Chris@148 189 break;
Chris@148 190
Chris@148 191 case CacheInMemory:
Chris@148 192 // nothing to do
Chris@148 193 break;
Chris@148 194 }
Chris@148 195 }
Chris@148 196
Chris@148 197 void
Chris@148 198 CodedAudioFileReader::getInterleavedFrames(size_t start, size_t count,
Chris@148 199 SampleBlock &frames) const
Chris@148 200 {
Chris@263 201 //!!! we want to ensure this doesn't require a lock -- at the
Chris@263 202 // moment it does need one, but it doesn't have one...
Chris@263 203
Chris@265 204 if (!m_initialised) {
Chris@265 205 std::cerr << "CodedAudioFileReader::getInterleavedFrames: not initialised" << std::endl;
Chris@265 206 return;
Chris@265 207 }
Chris@148 208
Chris@148 209 switch (m_cacheMode) {
Chris@148 210
Chris@148 211 case CacheInTemporaryFile:
Chris@148 212 if (m_cacheFileReader) {
Chris@148 213 m_cacheFileReader->getInterleavedFrames(start, count, frames);
Chris@148 214 }
Chris@148 215 break;
Chris@148 216
Chris@148 217 case CacheInMemory:
Chris@148 218 {
Chris@148 219 frames.clear();
Chris@148 220 if (!isOK()) return;
Chris@148 221 if (count == 0) return;
Chris@148 222
Chris@148 223 // slownessabounds
Chris@148 224
Chris@148 225 for (size_t i = start; i < start + count; ++i) {
Chris@148 226 for (size_t ch = 0; ch < m_channelCount; ++ch) {
Chris@148 227 size_t index = i * m_channelCount + ch;
Chris@148 228 if (index >= m_data.size()) return;
Chris@148 229 frames.push_back(m_data[index]);
Chris@148 230 }
Chris@148 231 }
Chris@148 232 }
Chris@148 233 }
Chris@148 234 }
Chris@148 235