WritableWaveFileModel.cpp

Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006 QMUL.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #include "WritableWaveFileModel.h"
00017 
00018 #include "base/TempDirectory.h"
00019 #include "base/Exceptions.h"
00020 
00021 #include "fileio/WavFileWriter.h"
00022 #include "fileio/WavFileReader.h"
00023 
00024 #include <QDir>
00025 #include <QTextStream>
00026 
00027 #include <cassert>
00028 #include <iostream>
00029 
00030 //#define DEBUG_WRITABLE_WAVE_FILE_MODEL 1
00031 
00032 WritableWaveFileModel::WritableWaveFileModel(size_t sampleRate,
00033                                              size_t channels,
00034                                              QString path) :
00035     m_model(0),
00036     m_writer(0),
00037     m_reader(0),
00038     m_sampleRate(sampleRate),
00039     m_channels(channels),
00040     m_frameCount(0),
00041     m_startFrame(0),
00042     m_completion(0)
00043 {
00044     if (path.isEmpty()) {
00045         try {
00046             QDir dir(TempDirectory::getInstance()->getPath());
00047             path = dir.filePath(QString("written_%1.wav")
00048                                 .arg((intptr_t)this));
00049         } catch (DirectoryCreationFailed f) {
00050             std::cerr << "WritableWaveFileModel: Failed to create temporary directory" << std::endl;
00051             return;
00052         }
00053     }
00054 
00055     m_writer = new WavFileWriter(path, sampleRate, channels);
00056     if (!m_writer->isOK()) {
00057         std::cerr << "WritableWaveFileModel: Error in creating WAV file writer: " << m_writer->getError().toStdString() << std::endl;
00058         delete m_writer; 
00059         m_writer = 0;
00060         return;
00061     }
00062 
00063     FileSource source(m_writer->getPath());
00064 
00065     m_reader = new WavFileReader(source, true);
00066     if (!m_reader->getError().isEmpty()) {
00067         std::cerr << "WritableWaveFileModel: Error in creating wave file reader" << std::endl;
00068         delete m_reader;
00069         m_reader = 0;
00070         return;
00071     }
00072     
00073     m_model = new WaveFileModel(source, m_reader);
00074     if (!m_model->isOK()) {
00075         std::cerr << "WritableWaveFileModel: Error in creating wave file model" << std::endl;
00076         delete m_model;
00077         m_model = 0;
00078         delete m_reader;
00079         m_reader = 0;
00080         return;
00081     }
00082     m_model->setStartFrame(m_startFrame);
00083 
00084     connect(m_model, SIGNAL(modelChanged()), this, SIGNAL(modelChanged()));
00085     connect(m_model, SIGNAL(modelChanged(size_t, size_t)),
00086             this, SIGNAL(modelChanged(size_t, size_t)));
00087 }
00088 
00089 WritableWaveFileModel::~WritableWaveFileModel()
00090 {
00091     delete m_model;
00092     delete m_writer;
00093     delete m_reader;
00094 }
00095 
00096 void
00097 WritableWaveFileModel::setStartFrame(size_t startFrame)
00098 {
00099     m_startFrame = startFrame;
00100     if (m_model) m_model->setStartFrame(startFrame);
00101 }
00102 
00103 bool
00104 WritableWaveFileModel::addSamples(float **samples, size_t count)
00105 {
00106     if (!m_writer) return false;
00107 
00108 #ifdef DEBUG_WRITABLE_WAVE_FILE_MODEL
00109 //    std::cerr << "WritableWaveFileModel::addSamples(" << count << ")" << std::endl;
00110 #endif
00111 
00112     if (!m_writer->writeSamples(samples, count)) {
00113         std::cerr << "ERROR: WritableWaveFileModel::addSamples: writer failed: " << m_writer->getError().toStdString() << std::endl;
00114         return false;
00115     }
00116 
00117     m_frameCount += count;
00118 
00119     static int updateCounter = 0;
00120 
00121     if (m_reader && m_reader->getChannelCount() == 0) {
00122 #ifdef DEBUG_WRITABLE_WAVE_FILE_MODEL
00123         std::cerr << "WritableWaveFileModel::addSamples(" << count << "): calling updateFrameCount (initial)" << std::endl;
00124 #endif
00125         m_reader->updateFrameCount();
00126     } else if (++updateCounter == 100) {
00127 #ifdef DEBUG_WRITABLE_WAVE_FILE_MODEL
00128         std::cerr << "WritableWaveFileModel::addSamples(" << count << "): calling updateFrameCount (periodic)" << std::endl;
00129 #endif
00130         if (m_reader) m_reader->updateFrameCount();
00131         updateCounter = 0;
00132     }
00133 
00134     return true;
00135 }
00136 
00137 bool
00138 WritableWaveFileModel::isOK() const
00139 {
00140     bool ok = (m_writer && m_writer->isOK());
00141 //    std::cerr << "WritableWaveFileModel::isOK(): ok = " << ok << std::endl;
00142     return ok;
00143 }
00144 
00145 bool
00146 WritableWaveFileModel::isReady(int *completion) const
00147 {
00148     if (completion) *completion = m_completion;
00149     return (m_completion == 100);
00150 }
00151 
00152 void
00153 WritableWaveFileModel::setCompletion(int completion)
00154 {
00155     m_completion = completion;
00156     if (completion == 100) {
00157         if (m_reader) m_reader->updateDone();
00158     }
00159 }
00160 
00161 size_t
00162 WritableWaveFileModel::getFrameCount() const
00163 {
00164 //    std::cerr << "WritableWaveFileModel::getFrameCount: count = " << m_frameCount << std::endl;
00165     return m_frameCount;
00166 }
00167 
00168 Model *
00169 WritableWaveFileModel::clone() const
00170 {
00171     assert(0); 
00172     return 0;
00173 }
00174 
00175 size_t
00176 WritableWaveFileModel::getData(int channel, size_t start, size_t count,
00177                                float *buffer) const
00178 {
00179     if (!m_model || m_model->getChannelCount() == 0) return 0;
00180     return m_model->getData(channel, start, count, buffer);
00181 }
00182 
00183 size_t
00184 WritableWaveFileModel::getData(int channel, size_t start, size_t count,
00185                                double *buffer) const
00186 {
00187     if (!m_model || m_model->getChannelCount() == 0) return 0;
00188     return m_model->getData(channel, start, count, buffer);
00189 }
00190 
00191 size_t
00192 WritableWaveFileModel::getData(size_t fromchannel, size_t tochannel,
00193                                size_t start, size_t count,
00194                                float **buffers) const
00195 {
00196     if (!m_model || m_model->getChannelCount() == 0) return 0;
00197     return m_model->getData(fromchannel, tochannel, start, count, buffers);
00198 }    
00199 
00200 size_t
00201 WritableWaveFileModel::getSummaryBlockSize(size_t desired) const
00202 {
00203     if (!m_model) return desired;
00204     return m_model->getSummaryBlockSize(desired);
00205 }
00206 
00207 void
00208 WritableWaveFileModel::getSummaries(size_t channel, size_t start, size_t count,
00209                                     RangeBlock &ranges,
00210                                     size_t &blockSize) const
00211 {
00212     ranges.clear();
00213     if (!m_model || m_model->getChannelCount() == 0) return;
00214     m_model->getSummaries(channel, start, count, ranges, blockSize);
00215 }
00216 
00217 WritableWaveFileModel::Range
00218 WritableWaveFileModel::getSummary(size_t channel, size_t start, size_t count) const
00219 {
00220     if (!m_model || m_model->getChannelCount() == 0) return Range();
00221     return m_model->getSummary(channel, start, count);
00222 }
00223 
00224 void
00225 WritableWaveFileModel::toXml(QTextStream &out,
00226                              QString indent,
00227                              QString extraAttributes) const
00228 {
00229     // We don't actually write the data to XML.  We just write a brief
00230     // description of the model.  Any code that uses this class is
00231     // going to need to be aware that it will have to make separate
00232     // arrangements for the audio file itself.
00233 
00234     Model::toXml
00235         (out, indent,
00236          QString("type=\"writablewavefile\" file=\"%1\" channels=\"%2\" %3")
00237          .arg(m_writer->getPath()).arg(m_model->getChannelCount()).arg(extraAttributes));
00238 }
00239 

Generated on Wed Feb 20 15:45:30 2008 for SonicVisualiser by  doxygen 1.5.1