Mercurial > hg > svcore
comparison data/model/WaveFileModel.cpp @ 377:166c22eff678
* Ensure waveforms are strictly correct even when using a non-power-of-two
non-power-of-sqrt-two block size with cacheing off and painting only small
areas at a time
author | Chris Cannam |
---|---|
date | Thu, 07 Feb 2008 15:25:05 +0000 |
parents | 0e30c8ec15a0 |
children | 183ee2a55fc7 |
comparison
equal
deleted
inserted
replaced
376:ab24af1271e9 | 377:166c22eff678 |
---|---|
377 } | 377 } |
378 | 378 |
379 return i; | 379 return i; |
380 } | 380 } |
381 | 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 | |
382 void | 398 void |
383 WaveFileModel::getSummaries(size_t channel, size_t start, size_t count, | 399 WaveFileModel::getSummaries(size_t channel, size_t start, size_t count, |
384 RangeBlock &ranges, size_t &blockSize) const | 400 RangeBlock &ranges, size_t &blockSize) const |
385 { | 401 { |
386 ranges.clear(); | 402 ranges.clear(); |
387 if (!isOK()) return; | 403 if (!isOK()) return; |
404 ranges.reserve((count / blockSize) + 1); | |
388 | 405 |
389 if (start > m_startFrame) start -= m_startFrame; | 406 if (start > m_startFrame) start -= m_startFrame; |
390 else if (count <= m_startFrame - start) return; | 407 else if (count <= m_startFrame - start) return; |
391 else { | 408 else { |
392 count -= (m_startFrame - start); | 409 count -= (m_startFrame - start); |
393 start = 0; | 410 start = 0; |
394 } | 411 } |
395 | 412 |
396 int cacheType = 0; | 413 int cacheType = 0; |
397 int power = m_zoomConstraint.getMinCachePower(); | 414 int power = m_zoomConstraint.getMinCachePower(); |
398 blockSize = m_zoomConstraint.getNearestBlockSize | 415 size_t roundedBlockSize = m_zoomConstraint.getNearestBlockSize |
399 (blockSize, cacheType, power, ZoomConstraint::RoundUp); | 416 (blockSize, cacheType, power, ZoomConstraint::RoundDown); |
400 | 417 |
401 size_t channels = getChannelCount(); | 418 size_t channels = getChannelCount(); |
402 | 419 |
403 if (cacheType != 0 && cacheType != 1) { | 420 if (cacheType != 0 && cacheType != 1) { |
404 | 421 |
408 // for stereo files, in two separate calls to this method. | 425 // for stereo files, in two separate calls to this method. |
409 // We could fairly trivially handle this for most cases that | 426 // We could fairly trivially handle this for most cases that |
410 // matter by putting a single cache in getInterleavedFrames | 427 // matter by putting a single cache in getInterleavedFrames |
411 // for short queries. | 428 // for short queries. |
412 | 429 |
413 SampleBlock frames; | 430 m_directReadMutex.lock(); |
414 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 | |
415 float max = 0.0, min = 0.0, total = 0.0; | 441 float max = 0.0, min = 0.0, total = 0.0; |
416 size_t i = 0, got = 0; | 442 size_t i = 0, got = 0; |
417 | 443 |
418 while (i < count) { | 444 while (i < count) { |
419 | 445 |
420 size_t index = i * channels + channel; | 446 size_t index = i * channels + channel; |
421 if (index >= frames.size()) break; | 447 if (index >= m_directRead.size()) break; |
422 | 448 |
423 float sample = frames[index]; | 449 float sample = m_directRead[index]; |
424 if (sample > max || got == 0) max = sample; | 450 if (sample > max || got == 0) max = sample; |
425 if (sample < min || got == 0) min = sample; | 451 if (sample < min || got == 0) min = sample; |
426 total += fabsf(sample); | 452 total += fabsf(sample); |
427 | 453 |
428 ++i; | 454 ++i; |
433 min = max = total = 0.0f; | 459 min = max = total = 0.0f; |
434 got = 0; | 460 got = 0; |
435 } | 461 } |
436 } | 462 } |
437 | 463 |
464 m_directReadMutex.unlock(); | |
465 | |
438 if (got > 0) { | 466 if (got > 0) { |
439 ranges.push_back(Range(min, max, total / got)); | 467 ranges.push_back(Range(min, max, total / got)); |
440 } | 468 } |
441 | 469 |
442 return; | 470 return; |
444 } else { | 472 } else { |
445 | 473 |
446 QMutexLocker locker(&m_mutex); | 474 QMutexLocker locker(&m_mutex); |
447 | 475 |
448 const RangeBlock &cache = m_cache[cacheType]; | 476 const RangeBlock &cache = m_cache[cacheType]; |
477 | |
478 blockSize = roundedBlockSize; | |
449 | 479 |
450 size_t cacheBlock, div; | 480 size_t cacheBlock, div; |
451 | 481 |
452 if (cacheType == 0) { | 482 if (cacheType == 0) { |
453 cacheBlock = (1 << m_zoomConstraint.getMinCachePower()); | 483 cacheBlock = (1 << m_zoomConstraint.getMinCachePower()); |