annotate data/model/WritableWaveFileModel.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 QMUL.
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 "WritableWaveFileModel.h"
lbajardsilogic@0 17
lbajardsilogic@0 18 #include "base/TempDirectory.h"
lbajardsilogic@0 19 #include "base/Exceptions.h"
lbajardsilogic@0 20
lbajardsilogic@0 21 #include "fileio/WavFileWriter.h"
lbajardsilogic@0 22 #include "fileio/WavFileReader.h"
lbajardsilogic@0 23
lbajardsilogic@0 24 #include <QDir>
lbajardsilogic@0 25
lbajardsilogic@0 26 #include <cassert>
lbajardsilogic@0 27 #include <iostream>
lbajardsilogic@0 28
lbajardsilogic@0 29 //#define DEBUG_WRITABLE_WAVE_FILE_MODEL 1
lbajardsilogic@0 30
lbajardsilogic@0 31 WritableWaveFileModel::WritableWaveFileModel(size_t sampleRate,
lbajardsilogic@0 32 size_t channels,
lbajardsilogic@0 33 QString path) :
lbajardsilogic@0 34 m_model(0),
lbajardsilogic@0 35 m_writer(0),
lbajardsilogic@0 36 m_reader(0),
lbajardsilogic@0 37 m_sampleRate(sampleRate),
lbajardsilogic@0 38 m_channels(channels),
lbajardsilogic@0 39 m_frameCount(0),
lbajardsilogic@0 40 m_completion(0)
lbajardsilogic@0 41 {
lbajardsilogic@0 42 if (path.isEmpty()) {
lbajardsilogic@0 43 try {
lbajardsilogic@0 44 QDir dir(TempDirectory::getInstance()->getPath());
lbajardsilogic@0 45 path = dir.filePath(QString("written_%1.wav")
lbajardsilogic@0 46 .arg((intptr_t)this));
lbajardsilogic@0 47 } catch (DirectoryCreationFailed f) {
lbajardsilogic@0 48 std::cerr << "WritableWaveFileModel: Failed to create temporary directory" << std::endl;
lbajardsilogic@0 49 return;
lbajardsilogic@0 50 }
lbajardsilogic@0 51 }
lbajardsilogic@0 52
lbajardsilogic@0 53 m_writer = new WavFileWriter(path, sampleRate, channels);
lbajardsilogic@0 54 if (!m_writer->isOK()) {
lbajardsilogic@0 55 std::cerr << "WritableWaveFileModel: Error in creating WAV file writer: " << m_writer->getError().toStdString() << std::endl;
lbajardsilogic@0 56 delete m_writer;
lbajardsilogic@0 57 m_writer = 0;
lbajardsilogic@0 58 return;
lbajardsilogic@0 59 }
lbajardsilogic@0 60
lbajardsilogic@0 61 m_reader = new WavFileReader(m_writer->getPath(), true);
lbajardsilogic@0 62 if (!m_reader->getError().isEmpty()) {
lbajardsilogic@0 63 std::cerr << "WritableWaveFileModel: Error in creating wave file reader" << std::endl;
lbajardsilogic@0 64 delete m_reader;
lbajardsilogic@0 65 m_reader = 0;
lbajardsilogic@0 66 return;
lbajardsilogic@0 67 }
lbajardsilogic@0 68
lbajardsilogic@0 69 m_model = new WaveFileModel(m_writer->getPath(), m_reader);
lbajardsilogic@0 70 if (!m_model->isOK()) {
lbajardsilogic@0 71 std::cerr << "WritableWaveFileModel: Error in creating wave file model" << std::endl;
lbajardsilogic@0 72 delete m_model;
lbajardsilogic@0 73 m_model = 0;
lbajardsilogic@0 74 delete m_reader;
lbajardsilogic@0 75 m_reader = 0;
lbajardsilogic@0 76 return;
lbajardsilogic@0 77 }
lbajardsilogic@0 78
lbajardsilogic@0 79 connect(m_model, SIGNAL(modelChanged()), this, SIGNAL(modelChanged()));
lbajardsilogic@0 80 connect(m_model, SIGNAL(modelChanged(size_t, size_t)),
lbajardsilogic@0 81 this, SIGNAL(modelChanged(size_t, size_t)));
lbajardsilogic@0 82 }
lbajardsilogic@0 83
lbajardsilogic@0 84 WritableWaveFileModel::~WritableWaveFileModel()
lbajardsilogic@0 85 {
lbajardsilogic@0 86 delete m_model;
lbajardsilogic@0 87 delete m_writer;
lbajardsilogic@0 88 delete m_reader;
lbajardsilogic@0 89 }
lbajardsilogic@0 90
lbajardsilogic@0 91 bool
lbajardsilogic@0 92 WritableWaveFileModel::addSamples(float **samples, size_t count)
lbajardsilogic@0 93 {
lbajardsilogic@0 94 if (!m_writer) return false;
lbajardsilogic@0 95
lbajardsilogic@0 96 #ifdef DEBUG_WRITABLE_WAVE_FILE_MODEL
lbajardsilogic@0 97 // std::cerr << "WritableWaveFileModel::addSamples(" << count << ")" << std::endl;
lbajardsilogic@0 98 #endif
lbajardsilogic@0 99
lbajardsilogic@0 100 if (!m_writer->writeSamples(samples, count)) {
lbajardsilogic@0 101 std::cerr << "ERROR: WritableWaveFileModel::addSamples: writer failed: " << m_writer->getError().toStdString() << std::endl;
lbajardsilogic@0 102 return false;
lbajardsilogic@0 103 }
lbajardsilogic@0 104
lbajardsilogic@0 105 m_frameCount += count;
lbajardsilogic@0 106
lbajardsilogic@0 107 static int updateCounter = 0;
lbajardsilogic@0 108
lbajardsilogic@0 109 if (m_reader && m_reader->getChannelCount() == 0) {
lbajardsilogic@0 110 #ifdef DEBUG_WRITABLE_WAVE_FILE_MODEL
lbajardsilogic@0 111 std::cerr << "WritableWaveFileModel::addSamples(" << count << "): calling updateFrameCount (initial)" << std::endl;
lbajardsilogic@0 112 #endif
lbajardsilogic@0 113 m_reader->updateFrameCount();
lbajardsilogic@0 114 } else if (++updateCounter == 100) {
lbajardsilogic@0 115 #ifdef DEBUG_WRITABLE_WAVE_FILE_MODEL
lbajardsilogic@0 116 std::cerr << "WritableWaveFileModel::addSamples(" << count << "): calling updateFrameCount (periodic)" << std::endl;
lbajardsilogic@0 117 #endif
lbajardsilogic@0 118 if (m_reader) m_reader->updateFrameCount();
lbajardsilogic@0 119 updateCounter = 0;
lbajardsilogic@0 120 }
lbajardsilogic@0 121
lbajardsilogic@0 122 return true;
lbajardsilogic@0 123 }
lbajardsilogic@0 124
lbajardsilogic@0 125 bool
lbajardsilogic@0 126 WritableWaveFileModel::isOK() const
lbajardsilogic@0 127 {
lbajardsilogic@0 128 bool ok = (m_writer && m_writer->isOK());
lbajardsilogic@0 129 // std::cerr << "WritableWaveFileModel::isOK(): ok = " << ok << std::endl;
lbajardsilogic@0 130 return ok;
lbajardsilogic@0 131 }
lbajardsilogic@0 132
lbajardsilogic@0 133 bool
lbajardsilogic@0 134 WritableWaveFileModel::isReady(int *completion) const
lbajardsilogic@0 135 {
lbajardsilogic@0 136 if (completion) *completion = m_completion;
lbajardsilogic@0 137 return (m_completion == 100);
lbajardsilogic@0 138 }
lbajardsilogic@0 139
lbajardsilogic@0 140 void
lbajardsilogic@0 141 WritableWaveFileModel::setCompletion(int completion)
lbajardsilogic@0 142 {
lbajardsilogic@0 143 m_completion = completion;
lbajardsilogic@0 144 if (completion == 100) {
lbajardsilogic@0 145 if (m_reader) m_reader->updateDone();
lbajardsilogic@0 146 }
lbajardsilogic@0 147 }
lbajardsilogic@0 148
lbajardsilogic@0 149 size_t
lbajardsilogic@0 150 WritableWaveFileModel::getFrameCount() const
lbajardsilogic@0 151 {
lbajardsilogic@0 152 // std::cerr << "WritableWaveFileModel::getFrameCount: count = " << m_frameCount << std::endl;
lbajardsilogic@0 153 return m_frameCount;
lbajardsilogic@0 154 }
lbajardsilogic@0 155
lbajardsilogic@0 156 Model *
lbajardsilogic@0 157 WritableWaveFileModel::clone() const
lbajardsilogic@0 158 {
lbajardsilogic@0 159 assert(0); //!!!
lbajardsilogic@0 160 return 0;
lbajardsilogic@0 161 }
lbajardsilogic@0 162
lbajardsilogic@0 163 size_t
lbajardsilogic@0 164 WritableWaveFileModel::getValues(int channel, size_t start, size_t end,
lbajardsilogic@0 165 float *buffer) const
lbajardsilogic@0 166 {
lbajardsilogic@0 167 if (!m_model || m_model->getChannelCount() == 0) return 0;
lbajardsilogic@0 168 return m_model->getValues(channel, start, end, buffer);
lbajardsilogic@0 169 }
lbajardsilogic@0 170
lbajardsilogic@0 171 size_t
lbajardsilogic@0 172 WritableWaveFileModel::getValues(int channel, size_t start, size_t end,
lbajardsilogic@0 173 double *buffer) const
lbajardsilogic@0 174 {
lbajardsilogic@0 175 if (!m_model || m_model->getChannelCount() == 0) return 0;
lbajardsilogic@0 176 // std::cerr << "WritableWaveFileModel::getValues(" << channel << ", "
lbajardsilogic@0 177 // << start << ", " << end << "): calling model" << std::endl;
lbajardsilogic@0 178 return m_model->getValues(channel, start, end, buffer);
lbajardsilogic@0 179 }
lbajardsilogic@0 180
lbajardsilogic@0 181 void
lbajardsilogic@0 182 WritableWaveFileModel::getRanges(size_t channel, size_t start, size_t end,
lbajardsilogic@0 183 RangeBlock &ranges,
lbajardsilogic@0 184 size_t &blockSize) const
lbajardsilogic@0 185 {
lbajardsilogic@0 186 ranges.clear();
lbajardsilogic@0 187 if (!m_model || m_model->getChannelCount() == 0) return;
lbajardsilogic@0 188 m_model->getRanges(channel, start, end, ranges, blockSize);
lbajardsilogic@0 189 }
lbajardsilogic@0 190
lbajardsilogic@0 191 WritableWaveFileModel::Range
lbajardsilogic@0 192 WritableWaveFileModel::getRange(size_t channel, size_t start, size_t end) const
lbajardsilogic@0 193 {
lbajardsilogic@0 194 if (!m_model || m_model->getChannelCount() == 0) return Range();
lbajardsilogic@0 195 return m_model->getRange(channel, start, end);
lbajardsilogic@0 196 }
lbajardsilogic@0 197
lbajardsilogic@0 198 void
lbajardsilogic@0 199 WritableWaveFileModel::toXml(QTextStream &out,
lbajardsilogic@0 200 QString indent,
lbajardsilogic@0 201 QString extraAttributes) const
lbajardsilogic@0 202 {
lbajardsilogic@0 203 // We don't actually write the data to XML. We just write a brief
lbajardsilogic@0 204 // description of the model. Any code that uses this class is
lbajardsilogic@0 205 // going to need to be aware that it will have to make separate
lbajardsilogic@0 206 // arrangements for the audio file itself.
lbajardsilogic@0 207
lbajardsilogic@0 208 Model::toXml
lbajardsilogic@0 209 (out, indent,
lbajardsilogic@0 210 QString("type=\"writablewavefile\" file=\"%1\" channels=\"%2\" %3")
lbajardsilogic@0 211 .arg(m_writer->getPath()).arg(m_model->getChannelCount()).arg(extraAttributes));
lbajardsilogic@0 212 }
lbajardsilogic@0 213
lbajardsilogic@0 214 QString
lbajardsilogic@0 215 WritableWaveFileModel::toXmlString(QString indent,
lbajardsilogic@0 216 QString extraAttributes) const
lbajardsilogic@0 217 {
lbajardsilogic@0 218 // As above.
lbajardsilogic@0 219
lbajardsilogic@0 220 return Model::toXmlString
lbajardsilogic@0 221 (indent,
lbajardsilogic@0 222 QString("type=\"writablewavefile\" file=\"%1\" channels=\"%2\" %3")
lbajardsilogic@0 223 .arg(m_writer->getPath()).arg(m_model->getChannelCount()).arg(extraAttributes));
lbajardsilogic@0 224 }
lbajardsilogic@0 225