Mercurial > hg > easaier-soundaccess
diff data/fileio/WavFileWriter.cpp @ 0:fc9323a41f5a
start base : Sonic Visualiser sv1-1.0rc1
author | lbajardsilogic |
---|---|
date | Fri, 11 May 2007 09:08:14 +0000 |
parents | |
children | be6d31baecb9 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/fileio/WavFileWriter.cpp Fri May 11 09:08:14 2007 +0000 @@ -0,0 +1,167 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006 Chris Cannam and QMUL. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#include "WavFileWriter.h" + +#include "model/DenseTimeValueModel.h" +#include "base/Selection.h" +#include "system/System.h" + +#include <QFileInfo> + +#include <iostream> + +WavFileWriter::WavFileWriter(QString path, + size_t sampleRate, + size_t channels) : + m_path(path), + m_sampleRate(sampleRate), + m_channels(channels), + m_file(0) +{ + SF_INFO fileInfo; + fileInfo.samplerate = m_sampleRate; + fileInfo.channels = m_channels; + fileInfo.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT; + + m_file = sf_open(m_path.toLocal8Bit(), SFM_WRITE, &fileInfo); + if (!m_file) { + std::cerr << "WavFileWriter: Failed to open file (" + << sf_strerror(m_file) << ")" << std::endl; + m_error = QString("Failed to open audio file '%1' for writing") + .arg(m_path); + } +} + +WavFileWriter::~WavFileWriter() +{ + if (m_file) close(); +} + +bool +WavFileWriter::isOK() const +{ + return (m_error.isEmpty()); +} + +QString +WavFileWriter::getError() const +{ + return m_error; +} + +bool +WavFileWriter::writeModel(DenseTimeValueModel *source, + MultiSelection *selection) +{ + if (source->getChannelCount() != m_channels) { + std::cerr << "WavFileWriter::writeModel: Wrong number of channels (" + << source->getChannelCount() << " != " << m_channels << ")" + << std::endl; + m_error = QString("Failed to write model to audio file '%1'") + .arg(m_path); + return false; + } + + if (!m_file) { + m_error = QString("Failed to write model to audio file '%1': File not open") + .arg(m_path); + return false; + } + + bool ownSelection = false; + if (!selection) { + selection = new MultiSelection; + selection->setSelection(Selection(source->getStartFrame(), + source->getEndFrame())); + ownSelection = true; + } + + size_t bs = 2048; + float *ub = new float[bs]; // uninterleaved buffer (one channel) + float *ib = new float[bs * m_channels]; // interleaved buffer + + for (MultiSelection::SelectionList::const_iterator i = + selection->getSelections().begin(); + i != selection->getSelections().end(); ++i) { + + size_t f0(i->getStartFrame()), f1(i->getEndFrame()); + + for (size_t f = f0; f < f1; f += bs) { + + size_t n = min(bs, f1 - f); + + for (int c = 0; c < int(m_channels); ++c) { + source->getValues(c, f, f + n, ub); + for (size_t i = 0; i < n; ++i) { + ib[i * m_channels + c] = ub[i]; + } + } + + sf_count_t written = sf_writef_float(m_file, ib, n); + + if (written < n) { + m_error = QString("Only wrote %1 of %2 frames at file frame %3") + .arg(written).arg(n).arg(f); + break; + } + } + } + + delete[] ub; + delete[] ib; + if (ownSelection) delete selection; + + return isOK(); +} + +bool +WavFileWriter::writeSamples(float **samples, size_t count) +{ + if (!m_file) { + m_error = QString("Failed to write model to audio file '%1': File not open") + .arg(m_path); + return false; + } + + float *b = new float[count * m_channels]; + for (size_t i = 0; i < count; ++i) { + for (size_t c = 0; c < m_channels; ++c) { + b[i * m_channels + c] = samples[c][i]; + } + } + + sf_count_t written = sf_writef_float(m_file, b, count); + + delete[] b; + + if (written < count) { + m_error = QString("Only wrote %1 of %2 frames") + .arg(written).arg(count); + } + + return isOK(); +} + +bool +WavFileWriter::close() +{ + if (m_file) { + sf_close(m_file); + m_file = 0; + } + return true; +} +