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