| 604 | } |
| 605 | |
| 606 | bool WaveClipSpectrumCache::GetSpectrogram( |
| 607 | const WaveChannelInterval &clip, |
| 608 | const float*& spectrogram, SpectrogramSettings& settings, |
| 609 | const sampleCount*& where, size_t numPixels, double t0, |
| 610 | double pixelsPerSecond) |
| 611 | |
| 612 | { |
| 613 | auto &mSpecCache = mSpecCaches[clip.GetChannelIndex()]; |
| 614 | |
| 615 | const auto sampleRate = clip.GetRate(); |
| 616 | const auto stretchRatio = clip.GetStretchRatio(); |
| 617 | const auto samplesPerPixel = sampleRate / pixelsPerSecond / stretchRatio; |
| 618 | |
| 619 | //Trim offset comparison failure forces spectrogram cache rebuild |
| 620 | //and skip copying "unchanged" data after clip border was trimmed. |
| 621 | bool match = mSpecCache && mSpecCache->leftTrim == clip.GetTrimLeft() && |
| 622 | mSpecCache->rightTrim == clip.GetTrimRight() && |
| 623 | mSpecCache->len > 0 && |
| 624 | mSpecCache->Matches(mDirty, samplesPerPixel, settings); |
| 625 | |
| 626 | if (match && mSpecCache->start == t0 && mSpecCache->len >= numPixels) |
| 627 | { |
| 628 | spectrogram = &mSpecCache->freq[0]; |
| 629 | where = &mSpecCache->where[0]; |
| 630 | |
| 631 | return false; //hit cache completely |
| 632 | } |
| 633 | |
| 634 | // Caching is not implemented for reassignment, unless for |
| 635 | // a complete hit, because of the complications of time reassignment |
| 636 | if (settings.algorithm == SpectrogramSettings::algReassignment) |
| 637 | match = false; |
| 638 | |
| 639 | // Free the cache when it won't cause a major stutter. |
| 640 | // If the window size changed, we know there is nothing to be copied |
| 641 | // If we zoomed out, or resized, we can give up memory. But not too much - |
| 642 | // up to 2x extra is needed at the end of the clip to prevent stutter. |
| 643 | if (mSpecCache->freq.capacity() > 2.1 * mSpecCache->freq.size() || |
| 644 | mSpecCache->windowSize*mSpecCache->zeroPaddingFactor < |
| 645 | settings.WindowSize()*settings.ZeroPaddingFactor()) |
| 646 | { |
| 647 | match = false; |
| 648 | mSpecCache = std::make_unique<SpecCache>(); |
| 649 | } |
| 650 | |
| 651 | int oldX0 = 0; |
| 652 | double correction = 0.0; |
| 653 | |
| 654 | int copyBegin = 0, copyEnd = 0; |
| 655 | if (match) { |
| 656 | WaveClipUIUtilities::findCorrection( |
| 657 | mSpecCache->where, mSpecCache->len, numPixels, t0, sampleRate, |
| 658 | stretchRatio, samplesPerPixel, oldX0, correction); |
| 659 | // Remember our first pixel maps to oldX0 in the old cache, |
| 660 | // possibly out of bounds. |
| 661 | // For what range of pixels can data be copied? |
| 662 | int oldLen = mSpecCache->len; |
| 663 | copyBegin = std::min(oldLen, std::max(0, -oldX0)); |
no test coverage detected