Mercurial > hg > svcore
comparison data/fileio/WavFileWriter.cpp @ 1350:1bc6f70cb4c7 3.0-integration
And similar approach for the writer
author | Chris Cannam |
---|---|
date | Fri, 06 Jan 2017 21:04:52 +0000 |
parents | b3cb0edc25cd |
children | 87ae75da6527 |
comparison
equal
deleted
inserted
replaced
1349:330bcc92507d | 1350:1bc6f70cb4c7 |
---|---|
26 #include <cmath> | 26 #include <cmath> |
27 | 27 |
28 using namespace std; | 28 using namespace std; |
29 | 29 |
30 WavFileWriter::WavFileWriter(QString path, | 30 WavFileWriter::WavFileWriter(QString path, |
31 sv_samplerate_t sampleRate, | 31 sv_samplerate_t sampleRate, |
32 int channels, | 32 int channels, |
33 FileWriteMode mode) : | 33 FileWriteMode mode) : |
34 m_path(path), | 34 m_path(path), |
35 m_sampleRate(sampleRate), | 35 m_sampleRate(sampleRate), |
36 m_channels(channels), | 36 m_channels(channels), |
37 m_temp(0), | 37 m_temp(0), |
38 m_sndfile(0), | 38 m_file(0) |
39 m_qfile(0) | |
40 { | 39 { |
41 SF_INFO fileInfo; | 40 SF_INFO fileInfo; |
42 | 41 |
43 int fileRate = int(round(m_sampleRate)); | 42 int fileRate = int(round(m_sampleRate)); |
44 if (m_sampleRate != sv_samplerate_t(fileRate)) { | 43 if (m_sampleRate != sv_samplerate_t(fileRate)) { |
45 SVCERR << "WavFileWriter: WARNING: Non-integer sample rate " | 44 cerr << "WavFileWriter: WARNING: Non-integer sample rate " |
46 << m_sampleRate << " presented, rounding to " << fileRate | 45 << m_sampleRate << " presented, rounding to " << fileRate |
47 << endl; | 46 << endl; |
48 } | 47 } |
49 fileInfo.samplerate = fileRate; | 48 fileInfo.samplerate = fileRate; |
50 fileInfo.channels = m_channels; | 49 fileInfo.channels = m_channels; |
51 fileInfo.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT; | 50 fileInfo.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT; |
52 | 51 |
53 try { | 52 try { |
53 QString writePath = m_path; | |
54 if (mode == WriteToTemporary) { | 54 if (mode == WriteToTemporary) { |
55 m_temp = new TempWriteFile(m_path); | 55 m_temp = new TempWriteFile(m_path); |
56 m_qfile = new QFile(m_temp->getTemporaryFilename()); | 56 writePath = m_temp->getTemporaryFilename(); |
57 } else { | 57 } |
58 m_qfile = new QFile(m_path); | 58 #ifdef Q_OS_WIN |
59 } | 59 m_file = sf_wchar_open((LPCWSTR)writePath.utf16(), SFM_WRITE, &fileInfo); |
60 if (!m_qfile->open(QIODevice::WriteOnly)) { | 60 #else |
61 SVCERR << "WavFileWriter: Failed to open file for writing" << endl; | 61 m_file = sf_open(writePath.toLocal8Bit(), SFM_WRITE, &fileInfo); |
62 #endif | |
63 if (!m_file) { | |
64 cerr << "WavFileWriter: Failed to open file (" | |
65 << sf_strerror(m_file) << ")" << endl; | |
62 m_error = QString("Failed to open audio file '%1' for writing") | 66 m_error = QString("Failed to open audio file '%1' for writing") |
63 .arg(m_qfile->fileName()); | 67 .arg(writePath); |
64 } else { | |
65 m_sndfile = sf_open_fd(m_qfile->handle(), | |
66 SFM_WRITE, &fileInfo, false); | |
67 if (!m_sndfile) { | |
68 SVCERR << "WavFileWriter: Failed to open file (" | |
69 << sf_strerror(m_sndfile) << ")" << endl; | |
70 m_error = QString("Failed to open audio file '%1' for writing") | |
71 .arg(m_qfile->fileName()); | |
72 } | |
73 } | 68 } |
74 } catch (FileOperationFailed &f) { | 69 } catch (FileOperationFailed &f) { |
75 m_error = f.what(); | 70 m_error = f.what(); |
76 m_temp = 0; | 71 m_temp = 0; |
77 m_qfile = 0; | 72 m_file = 0; |
78 m_sndfile = 0; | |
79 } | 73 } |
80 } | 74 } |
81 | 75 |
82 WavFileWriter::~WavFileWriter() | 76 WavFileWriter::~WavFileWriter() |
83 { | 77 { |
84 if (m_sndfile) close(); | 78 if (m_file) close(); |
85 } | 79 } |
86 | 80 |
87 bool | 81 bool |
88 WavFileWriter::isOK() const | 82 WavFileWriter::isOK() const |
89 { | 83 { |
117 m_error = QString("Failed to write model to audio file '%1'") | 111 m_error = QString("Failed to write model to audio file '%1'") |
118 .arg(getWriteFilename()); | 112 .arg(getWriteFilename()); |
119 return false; | 113 return false; |
120 } | 114 } |
121 | 115 |
122 if (!m_sndfile) { | 116 if (!m_file) { |
123 m_error = QString("Failed to write model to audio file '%1': File not open") | 117 m_error = QString("Failed to write model to audio file '%1': File not open") |
124 .arg(getWriteFilename()); | 118 .arg(getWriteFilename()); |
125 return false; | 119 return false; |
126 } | 120 } |
127 | 121 |
128 bool ownSelection = false; | 122 bool ownSelection = false; |
129 if (!selection) { | 123 if (!selection) { |
130 selection = new MultiSelection; | 124 selection = new MultiSelection; |
131 selection->setSelection(Selection(source->getStartFrame(), | 125 selection->setSelection(Selection(source->getStartFrame(), |
132 source->getEndFrame())); | 126 source->getEndFrame())); |
133 ownSelection = true; | 127 ownSelection = true; |
134 } | 128 } |
135 | 129 |
136 sv_frame_t bs = 2048; | 130 sv_frame_t bs = 2048; |
137 | 131 |
138 for (MultiSelection::SelectionList::iterator i = | 132 for (MultiSelection::SelectionList::iterator i = |
139 selection->getSelections().begin(); | 133 selection->getSelections().begin(); |
140 i != selection->getSelections().end(); ++i) { | 134 i != selection->getSelections().end(); ++i) { |
141 | 135 |
142 sv_frame_t f0(i->getStartFrame()), f1(i->getEndFrame()); | 136 sv_frame_t f0(i->getStartFrame()), f1(i->getEndFrame()); |
143 | 137 |
144 for (sv_frame_t f = f0; f < f1; f += bs) { | 138 for (sv_frame_t f = f0; f < f1; f += bs) { |
145 | 139 |
146 sv_frame_t n = min(bs, f1 - f); | 140 sv_frame_t n = min(bs, f1 - f); |
147 floatvec_t interleaved(n * m_channels, 0.f); | 141 floatvec_t interleaved(n * m_channels, 0.f); |
148 | 142 |
149 for (int c = 0; c < int(m_channels); ++c) { | 143 for (int c = 0; c < int(m_channels); ++c) { |
150 auto chanbuf = source->getData(c, f, n); | 144 auto chanbuf = source->getData(c, f, n); |
151 for (int i = 0; in_range_for(chanbuf, i); ++i) { | 145 for (int i = 0; in_range_for(chanbuf, i); ++i) { |
152 interleaved[i * m_channels + c] = chanbuf[i]; | 146 interleaved[i * m_channels + c] = chanbuf[i]; |
153 } | 147 } |
154 } | 148 } |
155 | 149 |
156 sf_count_t written = sf_writef_float(m_sndfile, interleaved.data(), n); | 150 sf_count_t written = sf_writef_float(m_file, interleaved.data(), n); |
157 | 151 |
158 if (written < n) { | 152 if (written < n) { |
159 m_error = QString("Only wrote %1 of %2 frames at file frame %3") | 153 m_error = QString("Only wrote %1 of %2 frames at file frame %3") |
160 .arg(written).arg(n).arg(f); | 154 .arg(written).arg(n).arg(f); |
161 break; | 155 break; |
162 } | 156 } |
163 } | 157 } |
164 } | 158 } |
165 | 159 |
166 if (ownSelection) delete selection; | 160 if (ownSelection) delete selection; |
167 | 161 |
168 return isOK(); | 162 return isOK(); |
169 } | 163 } |
170 | 164 |
171 bool | 165 bool |
172 WavFileWriter::writeSamples(const float *const *samples, sv_frame_t count) | 166 WavFileWriter::writeSamples(const float *const *samples, sv_frame_t count) |
173 { | 167 { |
174 if (!m_sndfile) { | 168 if (!m_file) { |
175 m_error = QString("Failed to write model to audio file '%1': File not open") | 169 m_error = QString("Failed to write model to audio file '%1': File not open") |
176 .arg(getWriteFilename()); | 170 .arg(getWriteFilename()); |
177 return false; | 171 return false; |
178 } | 172 } |
179 | 173 |
180 float *b = new float[count * m_channels]; | 174 float *b = new float[count * m_channels]; |
181 for (sv_frame_t i = 0; i < count; ++i) { | 175 for (sv_frame_t i = 0; i < count; ++i) { |
182 for (int c = 0; c < int(m_channels); ++c) { | 176 for (int c = 0; c < int(m_channels); ++c) { |
183 b[i * m_channels + c] = samples[c][i]; | 177 b[i * m_channels + c] = samples[c][i]; |
184 } | 178 } |
185 } | 179 } |
186 | 180 |
187 sv_frame_t written = sf_writef_float(m_sndfile, b, count); | 181 sv_frame_t written = sf_writef_float(m_file, b, count); |
188 | 182 |
189 delete[] b; | 183 delete[] b; |
190 | 184 |
191 if (written < count) { | 185 if (written < count) { |
192 m_error = QString("Only wrote %1 of %2 frames") | 186 m_error = QString("Only wrote %1 of %2 frames") |
197 } | 191 } |
198 | 192 |
199 bool | 193 bool |
200 WavFileWriter::close() | 194 WavFileWriter::close() |
201 { | 195 { |
202 if (m_sndfile) { | 196 if (m_file) { |
203 sf_close(m_sndfile); | 197 sf_close(m_file); |
204 m_sndfile = 0; | 198 m_file = 0; |
205 } | 199 } |
206 | |
207 delete m_qfile; | |
208 m_qfile = 0; | |
209 | |
210 if (m_temp) { | 200 if (m_temp) { |
211 m_temp->moveToTarget(); | 201 m_temp->moveToTarget(); |
212 delete m_temp; | 202 delete m_temp; |
213 m_temp = 0; | 203 m_temp = 0; |
214 } | 204 } |
215 | |
216 return true; | 205 return true; |
217 } | 206 } |
218 | 207 |