annotate data/fileio/CodedAudioFileReader.cpp @ 282:d9319859a4cf tip

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