annotate data/fileio/CodedAudioFileReader.cpp @ 167:665342c6ec57

* Add a bit of resistance to pane dragging so as to make it harder to inadvertently drag in the other axis from the one you intended
author Chris Cannam
date Fri, 22 Sep 2006 16:46:10 +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