Mercurial > hg > svcore
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 |