comparison data/model/WaveFileModel.cpp @ 383:94fc0591ea43 1.2-stable

* merge from trunk (1.2 ended up being tracked from trunk, but we may want this branch for fixes later)
author Chris Cannam
date Wed, 27 Feb 2008 10:32:45 +0000
parents 700cd3350391
children
comparison
equal deleted inserted replaced
349:f39d33b0b265 383:94fc0591ea43
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
290 } 294 }
291 295
292 return i; 296 return i;
293 } 297 }
294 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;
377 }
378
379 return i;
380 }
381
382 size_t
383 WaveFileModel::getSummaryBlockSize(size_t desired) const
384 {
385 int cacheType = 0;
386 int power = m_zoomConstraint.getMinCachePower();
387 size_t roundedBlockSize = m_zoomConstraint.getNearestBlockSize
388 (desired, cacheType, power, ZoomConstraint::RoundDown);
389 if (cacheType != 0 && cacheType != 1) {
390 // We will be reading directly from file, so can satisfy any
391 // blocksize requirement
392 return desired;
393 } else {
394 return roundedBlockSize;
395 }
396 }
397
295 void 398 void
296 WaveFileModel::getSummaries(size_t channel, size_t start, size_t count, 399 WaveFileModel::getSummaries(size_t channel, size_t start, size_t count,
297 RangeBlock &ranges, size_t &blockSize) const 400 RangeBlock &ranges, size_t &blockSize) const
298 { 401 {
299 ranges.clear(); 402 ranges.clear();
300 if (!isOK()) return; 403 if (!isOK()) return;
404 ranges.reserve((count / blockSize) + 1);
301 405
302 if (start > m_startFrame) start -= m_startFrame; 406 if (start > m_startFrame) start -= m_startFrame;
303 else if (count <= m_startFrame - start) return; 407 else if (count <= m_startFrame - start) return;
304 else { 408 else {
305 count -= (m_startFrame - start); 409 count -= (m_startFrame - start);
306 start = 0; 410 start = 0;
307 } 411 }
308 412
309 int cacheType = 0; 413 int cacheType = 0;
310 int power = m_zoomConstraint.getMinCachePower(); 414 int power = m_zoomConstraint.getMinCachePower();
311 blockSize = m_zoomConstraint.getNearestBlockSize 415 size_t roundedBlockSize = m_zoomConstraint.getNearestBlockSize
312 (blockSize, cacheType, power, ZoomConstraint::RoundUp); 416 (blockSize, cacheType, power, ZoomConstraint::RoundDown);
313 417
314 size_t channels = getChannelCount(); 418 size_t channels = getChannelCount();
315 419
316 if (cacheType != 0 && cacheType != 1) { 420 if (cacheType != 0 && cacheType != 1) {
317 421
321 // for stereo files, in two separate calls to this method. 425 // for stereo files, in two separate calls to this method.
322 // We could fairly trivially handle this for most cases that 426 // We could fairly trivially handle this for most cases that
323 // matter by putting a single cache in getInterleavedFrames 427 // matter by putting a single cache in getInterleavedFrames
324 // for short queries. 428 // for short queries.
325 429
326 SampleBlock frames; 430 m_directReadMutex.lock();
327 m_reader->getInterleavedFrames(start, count, frames); 431
432 if (m_lastDirectReadStart != start ||
433 m_lastDirectReadCount != count ||
434 m_directRead.empty()) {
435
436 m_reader->getInterleavedFrames(start, count, m_directRead);
437 m_lastDirectReadStart = start;
438 m_lastDirectReadCount = count;
439 }
440
328 float max = 0.0, min = 0.0, total = 0.0; 441 float max = 0.0, min = 0.0, total = 0.0;
329 size_t i = 0, got = 0; 442 size_t i = 0, got = 0;
330 443
331 while (i < count) { 444 while (i < count) {
332 445
333 size_t index = i * channels + channel; 446 size_t index = i * channels + channel;
334 if (index >= frames.size()) break; 447 if (index >= m_directRead.size()) break;
335 448
336 float sample = frames[index]; 449 float sample = m_directRead[index];
337 if (sample > max || got == 0) max = sample; 450 if (sample > max || got == 0) max = sample;
338 if (sample < min || got == 0) min = sample; 451 if (sample < min || got == 0) min = sample;
339 total += fabsf(sample); 452 total += fabsf(sample);
340 453
341 ++i; 454 ++i;
346 min = max = total = 0.0f; 459 min = max = total = 0.0f;
347 got = 0; 460 got = 0;
348 } 461 }
349 } 462 }
350 463
464 m_directReadMutex.unlock();
465
351 if (got > 0) { 466 if (got > 0) {
352 ranges.push_back(Range(min, max, total / got)); 467 ranges.push_back(Range(min, max, total / got));
353 } 468 }
354 469
355 return; 470 return;
357 } else { 472 } else {
358 473
359 QMutexLocker locker(&m_mutex); 474 QMutexLocker locker(&m_mutex);
360 475
361 const RangeBlock &cache = m_cache[cacheType]; 476 const RangeBlock &cache = m_cache[cacheType];
477
478 blockSize = roundedBlockSize;
362 479
363 size_t cacheBlock, div; 480 size_t cacheBlock, div;
364 481
365 if (cacheType == 0) { 482 if (cacheType == 0) {
366 cacheBlock = (1 << m_zoomConstraint.getMinCachePower()); 483 cacheBlock = (1 << m_zoomConstraint.getMinCachePower());