comparison data/fileio/WavFileWriter.cpp @ 174:f8cf055dbf34

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