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

(none)
author benoitrigolleau
date Fri, 31 Oct 2008 11:00:24 +0000
parents be6d31baecb9
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 and 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 "WavFileWriter.h"
lbajardsilogic@0 17
lbajardsilogic@0 18 #include "model/DenseTimeValueModel.h"
lbajardsilogic@0 19 #include "base/Selection.h"
lbajardsilogic@0 20 #include "system/System.h"
lbajardsilogic@0 21
lbajardsilogic@0 22 #include <QFileInfo>
lbajardsilogic@0 23
lbajardsilogic@0 24 #include <iostream>
lbajardsilogic@0 25
lbajardsilogic@0 26 WavFileWriter::WavFileWriter(QString path,
lbajardsilogic@0 27 size_t sampleRate,
lbajardsilogic@0 28 size_t channels) :
lbajardsilogic@0 29 m_path(path),
lbajardsilogic@0 30 m_sampleRate(sampleRate),
lbajardsilogic@0 31 m_channels(channels),
lbajardsilogic@0 32 m_file(0)
lbajardsilogic@0 33 {
lbajardsilogic@0 34 SF_INFO fileInfo;
lbajardsilogic@0 35 fileInfo.samplerate = m_sampleRate;
lbajardsilogic@0 36 fileInfo.channels = m_channels;
lbajardsilogic@0 37 fileInfo.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT;
lbajardsilogic@0 38
lbajardsilogic@0 39 m_file = sf_open(m_path.toLocal8Bit(), SFM_WRITE, &fileInfo);
lbajardsilogic@0 40 if (!m_file) {
lbajardsilogic@0 41 std::cerr << "WavFileWriter: Failed to open file ("
lbajardsilogic@0 42 << sf_strerror(m_file) << ")" << std::endl;
lbajardsilogic@0 43 m_error = QString("Failed to open audio file '%1' for writing")
lbajardsilogic@0 44 .arg(m_path);
lbajardsilogic@0 45 }
lbajardsilogic@0 46 }
lbajardsilogic@0 47
lbajardsilogic@0 48 WavFileWriter::~WavFileWriter()
lbajardsilogic@0 49 {
lbajardsilogic@0 50 if (m_file) close();
lbajardsilogic@0 51 }
lbajardsilogic@0 52
lbajardsilogic@0 53 bool
lbajardsilogic@0 54 WavFileWriter::isOK() const
lbajardsilogic@0 55 {
lbajardsilogic@0 56 return (m_error.isEmpty());
lbajardsilogic@0 57 }
lbajardsilogic@0 58
lbajardsilogic@0 59 QString
lbajardsilogic@0 60 WavFileWriter::getError() const
lbajardsilogic@0 61 {
lbajardsilogic@0 62 return m_error;
lbajardsilogic@0 63 }
lbajardsilogic@0 64
lbajardsilogic@0 65 bool
lbajardsilogic@0 66 WavFileWriter::writeModel(DenseTimeValueModel *source,
lbajardsilogic@0 67 MultiSelection *selection)
lbajardsilogic@0 68 {
lbajardsilogic@0 69 if (source->getChannelCount() != m_channels) {
lbajardsilogic@0 70 std::cerr << "WavFileWriter::writeModel: Wrong number of channels ("
lbajardsilogic@0 71 << source->getChannelCount() << " != " << m_channels << ")"
lbajardsilogic@0 72 << std::endl;
lbajardsilogic@0 73 m_error = QString("Failed to write model to audio file '%1'")
lbajardsilogic@0 74 .arg(m_path);
lbajardsilogic@0 75 return false;
lbajardsilogic@0 76 }
lbajardsilogic@0 77
lbajardsilogic@0 78 if (!m_file) {
lbajardsilogic@0 79 m_error = QString("Failed to write model to audio file '%1': File not open")
lbajardsilogic@0 80 .arg(m_path);
lbajardsilogic@0 81 return false;
lbajardsilogic@0 82 }
lbajardsilogic@0 83
lbajardsilogic@0 84 bool ownSelection = false;
lbajardsilogic@0 85 if (!selection) {
lbajardsilogic@0 86 selection = new MultiSelection;
lbajardsilogic@0 87 selection->setSelection(Selection(source->getStartFrame(),
lbajardsilogic@0 88 source->getEndFrame()));
lbajardsilogic@0 89 ownSelection = true;
lbajardsilogic@0 90 }
lbajardsilogic@0 91
lbajardsilogic@0 92 size_t bs = 2048;
lbajardsilogic@0 93 float *ub = new float[bs]; // uninterleaved buffer (one channel)
lbajardsilogic@0 94 float *ib = new float[bs * m_channels]; // interleaved buffer
lbajardsilogic@0 95
lbajardsilogic@0 96 for (MultiSelection::SelectionList::const_iterator i =
lbajardsilogic@0 97 selection->getSelections().begin();
lbajardsilogic@0 98 i != selection->getSelections().end(); ++i) {
lbajardsilogic@0 99
lbajardsilogic@0 100 size_t f0(i->getStartFrame()), f1(i->getEndFrame());
lbajardsilogic@0 101
lbajardsilogic@0 102 for (size_t f = f0; f < f1; f += bs) {
lbajardsilogic@0 103
lbajardsilogic@191 104 size_t n = MIN(bs, f1 - f);
lbajardsilogic@0 105
lbajardsilogic@0 106 for (int c = 0; c < int(m_channels); ++c) {
lbajardsilogic@0 107 source->getValues(c, f, f + n, ub);
lbajardsilogic@0 108 for (size_t i = 0; i < n; ++i) {
lbajardsilogic@0 109 ib[i * m_channels + c] = ub[i];
lbajardsilogic@0 110 }
lbajardsilogic@0 111 }
lbajardsilogic@0 112
lbajardsilogic@0 113 sf_count_t written = sf_writef_float(m_file, ib, n);
lbajardsilogic@0 114
lbajardsilogic@0 115 if (written < n) {
lbajardsilogic@0 116 m_error = QString("Only wrote %1 of %2 frames at file frame %3")
lbajardsilogic@0 117 .arg(written).arg(n).arg(f);
lbajardsilogic@0 118 break;
lbajardsilogic@0 119 }
lbajardsilogic@0 120 }
lbajardsilogic@0 121 }
lbajardsilogic@0 122
lbajardsilogic@0 123 delete[] ub;
lbajardsilogic@0 124 delete[] ib;
lbajardsilogic@0 125 if (ownSelection) delete selection;
lbajardsilogic@0 126
lbajardsilogic@0 127 return isOK();
lbajardsilogic@0 128 }
lbajardsilogic@0 129
lbajardsilogic@0 130 bool
lbajardsilogic@0 131 WavFileWriter::writeSamples(float **samples, size_t count)
lbajardsilogic@0 132 {
lbajardsilogic@0 133 if (!m_file) {
lbajardsilogic@0 134 m_error = QString("Failed to write model to audio file '%1': File not open")
lbajardsilogic@0 135 .arg(m_path);
lbajardsilogic@0 136 return false;
lbajardsilogic@0 137 }
lbajardsilogic@0 138
lbajardsilogic@0 139 float *b = new float[count * m_channels];
lbajardsilogic@0 140 for (size_t i = 0; i < count; ++i) {
lbajardsilogic@0 141 for (size_t c = 0; c < m_channels; ++c) {
lbajardsilogic@0 142 b[i * m_channels + c] = samples[c][i];
lbajardsilogic@0 143 }
lbajardsilogic@0 144 }
lbajardsilogic@0 145
lbajardsilogic@0 146 sf_count_t written = sf_writef_float(m_file, b, count);
lbajardsilogic@0 147
lbajardsilogic@0 148 delete[] b;
lbajardsilogic@0 149
lbajardsilogic@0 150 if (written < count) {
lbajardsilogic@0 151 m_error = QString("Only wrote %1 of %2 frames")
lbajardsilogic@0 152 .arg(written).arg(count);
lbajardsilogic@0 153 }
lbajardsilogic@0 154
lbajardsilogic@0 155 return isOK();
lbajardsilogic@0 156 }
lbajardsilogic@0 157
lbajardsilogic@0 158 bool
lbajardsilogic@0 159 WavFileWriter::close()
lbajardsilogic@0 160 {
lbajardsilogic@0 161 if (m_file) {
lbajardsilogic@0 162 sf_close(m_file);
lbajardsilogic@0 163 m_file = 0;
lbajardsilogic@0 164 }
lbajardsilogic@0 165 return true;
lbajardsilogic@0 166 }
lbajardsilogic@0 167