Mercurial > hg > svcore
comparison data/model/WaveFileModel.cpp @ 363:0e30c8ec15a0
* Add wave file model method for reading more than one channel at once,
avoiding ludicrously expensive backward seeks and double-reads when
playing multi-channel files or using them as inputs to feature extraction
plugins
author | Chris Cannam |
---|---|
date | Thu, 24 Jan 2008 14:35:43 +0000 |
parents | 700cd3350391 |
children | 166c22eff678 |
comparison
equal
deleted
inserted
replaced
362:cc4eb32efc6c | 363:0e30c8ec15a0 |
---|---|
187 { | 187 { |
188 // Always read these directly from the file. | 188 // Always read these directly from the file. |
189 // This is used for e.g. audio playback. | 189 // This is used for e.g. audio playback. |
190 // Could be much more efficient (although compiler optimisation will help) | 190 // Could be much more efficient (although compiler optimisation will help) |
191 | 191 |
192 if (start > m_startFrame) { | 192 if (start >= m_startFrame) { |
193 start -= m_startFrame; | 193 start -= m_startFrame; |
194 } else { | 194 } else { |
195 for (size_t i = 0; i < count; ++i) buffer[i] = 0.f; | 195 for (size_t i = 0; i < count; ++i) buffer[i] = 0.f; |
196 if (count <= m_startFrame - start) { | 196 if (count <= m_startFrame - start) { |
197 return 0; | 197 return 0; |
209 #ifdef DEBUG_WAVE_FILE_MODEL | 209 #ifdef DEBUG_WAVE_FILE_MODEL |
210 // std::cerr << "WaveFileModel::getValues(" << channel << ", " | 210 // std::cerr << "WaveFileModel::getValues(" << channel << ", " |
211 // << start << ", " << end << "): calling reader" << std::endl; | 211 // << start << ", " << end << "): calling reader" << std::endl; |
212 #endif | 212 #endif |
213 | 213 |
214 SampleBlock frames; | 214 int channels = getChannelCount(); |
215 | |
216 SampleBlock frames(count * channels); | |
215 m_reader->getInterleavedFrames(start, count, frames); | 217 m_reader->getInterleavedFrames(start, count, frames); |
216 | 218 |
217 size_t i = 0; | 219 size_t i = 0; |
218 | 220 |
219 int ch0 = channel, ch1 = channel, channels = getChannelCount(); | 221 int ch0 = channel, ch1 = channel; |
220 if (channel == -1) { | 222 if (channel == -1) { |
221 ch0 = 0; | 223 ch0 = 0; |
222 ch1 = channels - 1; | 224 ch1 = channels - 1; |
223 } | 225 } |
224 | 226 |
260 if (!m_reader || !m_reader->isOK() || count == 0) { | 262 if (!m_reader || !m_reader->isOK() || count == 0) { |
261 for (size_t i = 0; i < count; ++i) buffer[i] = 0.0; | 263 for (size_t i = 0; i < count; ++i) buffer[i] = 0.0; |
262 return 0; | 264 return 0; |
263 } | 265 } |
264 | 266 |
265 SampleBlock frames; | 267 int channels = getChannelCount(); |
268 | |
269 SampleBlock frames(count * channels); | |
266 m_reader->getInterleavedFrames(start, count, frames); | 270 m_reader->getInterleavedFrames(start, count, frames); |
267 | 271 |
268 size_t i = 0; | 272 size_t i = 0; |
269 | 273 |
270 int ch0 = channel, ch1 = channel, channels = getChannelCount(); | 274 int ch0 = channel, ch1 = channel; |
271 if (channel == -1) { | 275 if (channel == -1) { |
272 ch0 = 0; | 276 ch0 = 0; |
273 ch1 = channels - 1; | 277 ch1 = channels - 1; |
274 } | 278 } |
275 | 279 |
285 float sample = frames[index]; | 289 float sample = frames[index]; |
286 buffer[i] += sample; | 290 buffer[i] += sample; |
287 } | 291 } |
288 | 292 |
289 ++i; | 293 ++i; |
294 } | |
295 | |
296 return i; | |
297 } | |
298 | |
299 size_t | |
300 WaveFileModel::getData(size_t fromchannel, size_t tochannel, | |
301 size_t start, size_t count, | |
302 float **buffer) const | |
303 { | |
304 size_t channels = getChannelCount(); | |
305 | |
306 if (fromchannel > tochannel) { | |
307 std::cerr << "ERROR: WaveFileModel::getData: fromchannel (" | |
308 << fromchannel << ") > tochannel (" << tochannel << ")" | |
309 << std::endl; | |
310 return 0; | |
311 } | |
312 | |
313 if (tochannel >= channels) { | |
314 std::cerr << "ERROR: WaveFileModel::getData: tochannel (" | |
315 << tochannel << ") >= channel count (" << channels << ")" | |
316 << std::endl; | |
317 return 0; | |
318 } | |
319 | |
320 if (fromchannel == tochannel) { | |
321 return getData(fromchannel, start, count, buffer[0]); | |
322 } | |
323 | |
324 size_t reqchannels = (tochannel - fromchannel) + 1; | |
325 | |
326 // Always read these directly from the file. | |
327 // This is used for e.g. audio playback. | |
328 // Could be much more efficient (although compiler optimisation will help) | |
329 | |
330 if (start >= m_startFrame) { | |
331 start -= m_startFrame; | |
332 } else { | |
333 for (size_t c = 0; c < reqchannels; ++c) { | |
334 for (size_t i = 0; i < count; ++i) buffer[c][i] = 0.f; | |
335 } | |
336 if (count <= m_startFrame - start) { | |
337 return 0; | |
338 } else { | |
339 count -= (m_startFrame - start); | |
340 start = 0; | |
341 } | |
342 } | |
343 | |
344 if (!m_reader || !m_reader->isOK() || count == 0) { | |
345 for (size_t c = 0; c < reqchannels; ++c) { | |
346 for (size_t i = 0; i < count; ++i) buffer[c][i] = 0.f; | |
347 } | |
348 return 0; | |
349 } | |
350 | |
351 SampleBlock frames(count * channels); | |
352 m_reader->getInterleavedFrames(start, count, frames); | |
353 | |
354 size_t i = 0; | |
355 | |
356 int ch0 = fromchannel, ch1 = tochannel; | |
357 | |
358 size_t index = 0, available = frames.size(); | |
359 | |
360 while (i < count) { | |
361 | |
362 if (index >= available) break; | |
363 | |
364 size_t destc = 0; | |
365 | |
366 for (size_t c = 0; c < channels; ++c) { | |
367 | |
368 if (c >= fromchannel && c <= tochannel) { | |
369 buffer[destc][i] = frames[index]; | |
370 ++destc; | |
371 } | |
372 | |
373 ++index; | |
374 } | |
375 | |
376 ++i; | |
290 } | 377 } |
291 | 378 |
292 return i; | 379 return i; |
293 } | 380 } |
294 | 381 |