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