Chris@148: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@148: Chris@148: /* Chris@148: Sonic Visualiser Chris@148: An audio file viewer and annotation editor. Chris@148: Centre for Digital Music, Queen Mary, University of London. Chris@148: This file copyright 2006 Chris Cannam. Chris@148: Chris@148: This program is free software; you can redistribute it and/or Chris@148: modify it under the terms of the GNU General Public License as Chris@148: published by the Free Software Foundation; either version 2 of the Chris@148: License, or (at your option) any later version. See the file Chris@148: COPYING included with this distribution for more information. Chris@148: */ Chris@148: Chris@148: #include "WavFileWriter.h" Chris@148: Chris@148: #include "model/DenseTimeValueModel.h" Chris@148: #include "base/Selection.h" Chris@148: Chris@148: #include Chris@148: #include Chris@148: Chris@148: #include Chris@148: Chris@148: WavFileWriter::WavFileWriter(QString path, Chris@148: size_t sampleRate, Chris@148: DenseTimeValueModel *source, Chris@148: MultiSelection *selection) : Chris@148: m_path(path), Chris@148: m_sampleRate(sampleRate), Chris@148: m_model(source), Chris@148: m_selection(selection) Chris@148: { Chris@148: } Chris@148: Chris@148: WavFileWriter::~WavFileWriter() Chris@148: { Chris@148: } Chris@148: Chris@148: bool Chris@148: WavFileWriter::isOK() const Chris@148: { Chris@148: return (m_error.isEmpty()); Chris@148: } Chris@148: Chris@148: QString Chris@148: WavFileWriter::getError() const Chris@148: { Chris@148: return m_error; Chris@148: } Chris@148: Chris@148: void Chris@148: WavFileWriter::write() Chris@148: { Chris@148: int channels = m_model->getChannelCount(); Chris@148: Chris@148: SF_INFO fileInfo; Chris@148: fileInfo.samplerate = m_sampleRate; Chris@148: fileInfo.channels = channels; Chris@148: fileInfo.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT; Chris@148: Chris@148: SNDFILE *file = sf_open(m_path.toLocal8Bit(), SFM_WRITE, &fileInfo); Chris@148: if (!file) { Chris@148: std::cerr << "WavFileWriter::write: Failed to open file (" Chris@148: << sf_strerror(file) << ")" << std::endl; Chris@148: m_error = QString("Failed to open audio file '%1' for writing") Chris@148: .arg(m_path); Chris@148: return; Chris@148: } Chris@148: Chris@148: MultiSelection *selection = m_selection; Chris@148: Chris@148: if (!m_selection) { Chris@148: selection = new MultiSelection; Chris@148: selection->setSelection(Selection(m_model->getStartFrame(), Chris@148: m_model->getEndFrame())); Chris@148: } Chris@148: Chris@148: size_t bs = 2048; Chris@148: float *ub = new float[bs]; // uninterleaved buffer (one channel) Chris@148: float *ib = new float[bs * channels]; // interleaved buffer Chris@148: Chris@148: for (MultiSelection::SelectionList::iterator i = Chris@148: selection->getSelections().begin(); Chris@148: i != selection->getSelections().end(); ++i) { Chris@148: Chris@148: size_t f0(i->getStartFrame()), f1(i->getEndFrame()); Chris@148: Chris@148: for (size_t f = f0; f < f1; f += bs) { Chris@148: Chris@148: size_t n = std::min(bs, f1 - f); Chris@148: Chris@148: for (int c = 0; c < channels; ++c) { Chris@148: m_model->getValues(c, f, f + n, ub); Chris@148: for (size_t i = 0; i < n; ++i) { Chris@148: ib[i * channels + c] = ub[i]; Chris@148: } Chris@148: } Chris@148: Chris@148: sf_count_t written = sf_writef_float(file, ib, n); Chris@148: Chris@148: if (written < n) { Chris@148: m_error = QString("Only wrote %1 of %2 frames at file frame %3") Chris@148: .arg(written).arg(n).arg(f); Chris@148: break; Chris@148: } Chris@148: } Chris@148: } Chris@148: Chris@148: sf_close(file); Chris@148: Chris@148: delete[] ub; Chris@148: delete[] ib; Chris@148: if (!m_selection) delete selection; Chris@148: } Chris@148: Chris@148: Chris@148: Chris@148: