Audacity  3.0.3
Classes | Public Member Functions | Private Member Functions | Private Attributes | List of all members
WaveTrackCache Class Reference

A short-lived object, during whose lifetime, the contents of the WaveTrack are assumed not to change. More...

#include <WaveTrack.h>

Collaboration diagram for WaveTrackCache:
[legend]

Classes

struct  Buffer
 

Public Member Functions

 WaveTrackCache ()
 
 WaveTrackCache (const std::shared_ptr< const WaveTrack > &pTrack)
 
 ~WaveTrackCache ()
 
const std::shared_ptr< const WaveTrack > & GetTrack () const
 
void SetTrack (const std::shared_ptr< const WaveTrack > &pTrack)
 
const float * GetFloats (sampleCount start, size_t len, bool mayThrow)
 Retrieve samples as floats from the track or from the memory cache. More...
 

Private Member Functions

void Free ()
 

Private Attributes

std::shared_ptr< const WaveTrackmPTrack
 
size_t mBufferSize
 
Buffer mBuffers [2]
 
GrowableSampleBuffer mOverlapBuffer
 
int mNValidBuffers
 

Detailed Description

A short-lived object, during whose lifetime, the contents of the WaveTrack are assumed not to change.

It can replace repeated calls to WaveTrack::Get() (each of which opens and closes at least one block).

Definition at line 626 of file WaveTrack.h.

Constructor & Destructor Documentation

◆ WaveTrackCache() [1/2]

WaveTrackCache::WaveTrackCache ( )
inline

Definition at line 628 of file WaveTrack.h.

629  : mBufferSize(0)
630  , mOverlapBuffer()
631  , mNValidBuffers(0)
632  {
633  }

◆ WaveTrackCache() [2/2]

WaveTrackCache::WaveTrackCache ( const std::shared_ptr< const WaveTrack > &  pTrack)
inlineexplicit

Definition at line 635 of file WaveTrack.h.

636  : mBufferSize(0)
637  , mOverlapBuffer()
638  , mNValidBuffers(0)
639  {
640  SetTrack(pTrack);
641  }

◆ ~WaveTrackCache()

WaveTrackCache::~WaveTrackCache ( )

Definition at line 2521 of file WaveTrack.cpp.

2522 {
2523 }

Member Function Documentation

◆ Free()

void WaveTrackCache::Free ( )
private

Definition at line 2724 of file WaveTrack.cpp.

2725 {
2726  mBuffers[0].Free();
2727  mBuffers[1].Free();
2728  mOverlapBuffer.Free();
2729  mNValidBuffers = 0;
2730 }

References GrowableSampleBuffer::Free(), WaveTrackCache::Buffer::Free(), mBuffers, mNValidBuffers, and mOverlapBuffer.

Referenced by SetTrack().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetFloats()

const float * WaveTrackCache::GetFloats ( sampleCount  start,
size_t  len,
bool  mayThrow 
)

Retrieve samples as floats from the track or from the memory cache.

Uses fillZero always

Returns
null on failure; this object owns the memory; may be invalidated if GetFloats() is called again

Definition at line 2544 of file WaveTrack.cpp.

2546 {
2547  constexpr auto format = floatSample;
2548  if (format == floatSample && len > 0) {
2549  const auto end = start + len;
2550 
2551  bool fillFirst = (mNValidBuffers < 1);
2552  bool fillSecond = (mNValidBuffers < 2);
2553 
2554  // Discard cached results that we no longer need
2555  if (mNValidBuffers > 0 &&
2556  (end <= mBuffers[0].start ||
2557  start >= mBuffers[mNValidBuffers - 1].end())) {
2558  // Complete miss
2559  fillFirst = true;
2560  fillSecond = true;
2561  }
2562  else if (mNValidBuffers == 2 &&
2563  start >= mBuffers[1].start &&
2564  end > mBuffers[1].end()) {
2565  // Request starts in the second buffer and extends past it.
2566  // Discard the first buffer.
2567  // (But don't deallocate the buffer space.)
2568  mBuffers[0] .swap ( mBuffers[1] );
2569  fillSecond = true;
2570  mNValidBuffers = 1;
2571  }
2572  else if (mNValidBuffers > 0 &&
2573  start < mBuffers[0].start &&
2574  0 <= mPTrack->GetBlockStart(start)) {
2575  // Request is not a total miss but starts before the cache,
2576  // and there is a clip to fetch from.
2577  // Not the access pattern for drawing spectrogram or playback,
2578  // but maybe scrubbing causes this.
2579  // Move the first buffer into second place, and later
2580  // refill the first.
2581  // (This case might be useful when marching backwards through
2582  // the track, as with scrubbing.)
2583  mBuffers[0] .swap ( mBuffers[1] );
2584  fillFirst = true;
2585  fillSecond = false;
2586  // Cache is not in a consistent state yet
2587  mNValidBuffers = 0;
2588  }
2589 
2590  // Refill buffers as needed
2591  if (fillFirst) {
2592  const auto start0 = mPTrack->GetBlockStart(start);
2593  if (start0 >= 0) {
2594  const auto len0 = mPTrack->GetBestBlockSize(start0);
2595  wxASSERT(len0 <= mBufferSize);
2596  if (!mPTrack->GetFloats(
2597  mBuffers[0].data.get(), start0, len0,
2598  fillZero, mayThrow))
2599  return nullptr;
2600  mBuffers[0].start = start0;
2601  mBuffers[0].len = len0;
2602  if (!fillSecond &&
2603  mBuffers[0].end() != mBuffers[1].start)
2604  fillSecond = true;
2605  // Keep the partially updated state consistent:
2606  mNValidBuffers = fillSecond ? 1 : 2;
2607  }
2608  else {
2609  // Request may fall between the clips of a track.
2610  // Invalidate all. WaveTrack::Get() will return zeroes.
2611  mNValidBuffers = 0;
2612  fillSecond = false;
2613  }
2614  }
2615  wxASSERT(!fillSecond || mNValidBuffers > 0);
2616  if (fillSecond) {
2617  mNValidBuffers = 1;
2618  const auto end0 = mBuffers[0].end();
2619  if (end > end0) {
2620  const auto start1 = mPTrack->GetBlockStart(end0);
2621  if (start1 == end0) {
2622  const auto len1 = mPTrack->GetBestBlockSize(start1);
2623  wxASSERT(len1 <= mBufferSize);
2624  if (!mPTrack->GetFloats(mBuffers[1].data.get(), start1, len1, fillZero, mayThrow))
2625  return nullptr;
2626  mBuffers[1].start = start1;
2627  mBuffers[1].len = len1;
2628  mNValidBuffers = 2;
2629  }
2630  }
2631  }
2632  wxASSERT(mNValidBuffers < 2 || mBuffers[0].end() == mBuffers[1].start);
2633 
2634  samplePtr buffer = nullptr; // will point into mOverlapBuffer
2635  auto remaining = len;
2636 
2637  // Possibly get an initial portion that is uncached
2638 
2639  // This may be negative
2640  const auto initLen =
2641  mNValidBuffers < 1 ? sampleCount( len )
2642  : std::min(sampleCount( len ), mBuffers[0].start - start);
2643 
2644  if (initLen > 0) {
2645  // This might be fetching zeroes between clips
2647  // initLen is not more than len:
2648  auto sinitLen = initLen.as_size_t();
2649  if (!mPTrack->GetFloats(
2650  // See comment below about casting
2651  reinterpret_cast<float *>(mOverlapBuffer.ptr()),
2652  start, sinitLen, fillZero, mayThrow))
2653  return nullptr;
2654  wxASSERT( sinitLen <= remaining );
2655  remaining -= sinitLen;
2656  start += initLen;
2657  buffer = mOverlapBuffer.ptr() + sinitLen * SAMPLE_SIZE(format);
2658  }
2659 
2660  // Now satisfy the request from the buffers
2661  for (int ii = 0; ii < mNValidBuffers && remaining > 0; ++ii) {
2662  const auto starti = start - mBuffers[ii].start;
2663  // Treatment of initLen above establishes this loop invariant,
2664  // and statements below preserve it:
2665  wxASSERT(starti >= 0);
2666 
2667  // This may be negative
2668  const auto leni =
2669  std::min( sampleCount( remaining ), mBuffers[ii].len - starti );
2670  if (initLen <= 0 && leni == len) {
2671  // All is contiguous already. We can completely avoid copying
2672  // leni is nonnegative, therefore start falls within mBuffers[ii],
2673  // so starti is bounded between 0 and buffer length
2674  return mBuffers[ii].data.get() + starti.as_size_t() ;
2675  }
2676  else if (leni > 0) {
2677  // leni is nonnegative, therefore start falls within mBuffers[ii]
2678  // But we can't satisfy all from one buffer, so copy
2679  if (!buffer) {
2681  buffer = mOverlapBuffer.ptr();
2682  }
2683  // leni is positive and not more than remaining
2684  const size_t size = sizeof(float) * leni.as_size_t();
2685  // starti is less than mBuffers[ii].len and nonnegative
2686  memcpy(buffer, mBuffers[ii].data.get() + starti.as_size_t(), size);
2687  wxASSERT( leni <= remaining );
2688  remaining -= leni.as_size_t();
2689  start += leni;
2690  buffer += size;
2691  }
2692  }
2693 
2694  if (remaining > 0) {
2695  // Very big request!
2696  // Fall back to direct fetch
2697  if (!buffer) {
2699  buffer = mOverlapBuffer.ptr();
2700  }
2701  // See comment below about casting
2702  if (!mPTrack->GetFloats( reinterpret_cast<float*>(buffer),
2703  start, remaining, fillZero, mayThrow))
2704  return 0;
2705  }
2706 
2707  // Overlap buffer was meant for the more general support of sample formats
2708  // besides float, which explains the cast
2709  return reinterpret_cast<const float*>(mOverlapBuffer.ptr());
2710  }
2711  else {
2712 #if 0
2713  // Cache works only for float format.
2715  if (mPTrack->Get(mOverlapBuffer.ptr(), format, start, len, fillZero, mayThrow))
2716  return mOverlapBuffer.ptr();
2717 #else
2718  // No longer handling other than float format. Therefore len is 0.
2719 #endif
2720  return nullptr;
2721  }
2722 }

References WaveTrackCache::Buffer::data, WaveTrackCache::Buffer::end(), fillZero, floatSample, format, WaveTrackCache::Buffer::len, mBuffers, mBufferSize, min(), mNValidBuffers, mOverlapBuffer, mPTrack, GrowableSampleBuffer::ptr(), GrowableSampleBuffer::Resize(), SAMPLE_SIZE, WaveTrackCache::Buffer::start, and WaveTrackCache::Buffer::swap().

Referenced by SpecCache::CalculateOneSpectrum(), Mixer::MixSameRate(), and Mixer::MixVariableRates().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetTrack()

const std::shared_ptr<const WaveTrack>& WaveTrackCache::GetTrack ( ) const
inline

Definition at line 644 of file WaveTrack.h.

644 { return mPTrack; }

Referenced by anonymous_namespace{SpectrumView.cpp}::DrawClipSpectrum(), WaveClip::GetSpectrogram(), Mixer::MixSameRate(), Mixer::MixVariableRates(), and SpecCache::Populate().

Here is the caller graph for this function:

◆ SetTrack()

void WaveTrackCache::SetTrack ( const std::shared_ptr< const WaveTrack > &  pTrack)

Definition at line 2525 of file WaveTrack.cpp.

2526 {
2527  if (mPTrack != pTrack) {
2528  if (pTrack) {
2529  mBufferSize = pTrack->GetMaxBlockSize();
2530  if (!mPTrack ||
2531  mPTrack->GetMaxBlockSize() != mBufferSize) {
2532  Free();
2533  mBuffers[0].data = Floats{ mBufferSize };
2534  mBuffers[1].data = Floats{ mBufferSize };
2535  }
2536  }
2537  else
2538  Free();
2539  mPTrack = pTrack;
2540  mNValidBuffers = 0;
2541  }
2542 }

References WaveTrackCache::Buffer::data, Free(), WaveTrack::GetMaxBlockSize(), mBuffers, mBufferSize, mNValidBuffers, and mPTrack.

Here is the call graph for this function:

Member Data Documentation

◆ mBuffers

Buffer WaveTrackCache::mBuffers[2]
private

Definition at line 675 of file WaveTrack.h.

Referenced by Free(), GetFloats(), and SetTrack().

◆ mBufferSize

size_t WaveTrackCache::mBufferSize
private

Definition at line 674 of file WaveTrack.h.

Referenced by GetFloats(), and SetTrack().

◆ mNValidBuffers

int WaveTrackCache::mNValidBuffers
private

Definition at line 677 of file WaveTrack.h.

Referenced by Free(), GetFloats(), and SetTrack().

◆ mOverlapBuffer

GrowableSampleBuffer WaveTrackCache::mOverlapBuffer
private

Definition at line 676 of file WaveTrack.h.

Referenced by Free(), and GetFloats().

◆ mPTrack

std::shared_ptr<const WaveTrack> WaveTrackCache::mPTrack
private

Definition at line 673 of file WaveTrack.h.

Referenced by GetFloats(), and SetTrack().


The documentation for this class was generated from the following files:
GrowableSampleBuffer::Resize
GrowableSampleBuffer & Resize(size_t count, sampleFormat format)
Definition: SampleFormat.h:118
WaveTrackCache::Buffer::swap
void swap(Buffer &other)
Definition: WaveTrack.h:665
GrowableSampleBuffer::Free
void Free()
Definition: SampleFormat.h:127
WaveTrackCache::mNValidBuffers
int mNValidBuffers
Definition: WaveTrack.h:677
WaveTrackCache::mBuffers
Buffer mBuffers[2]
Definition: WaveTrack.h:675
GrowableSampleBuffer::ptr
samplePtr ptr() const
Definition: SampleFormat.h:98
SAMPLE_SIZE
#define SAMPLE_SIZE(SampleFormat)
Definition: SampleFormat.h:44
WaveTrackCache::Buffer::end
sampleCount end() const
Definition: WaveTrack.h:663
fillZero
@ fillZero
Definition: SampleFormat.h:54
floatSample
@ floatSample
Definition: SampleFormat.h:34
WaveTrackCache::Buffer::len
sampleCount len
Definition: WaveTrack.h:659
WaveTrackCache::Buffer::Free
void Free()
Definition: WaveTrack.h:662
WaveTrackCache::mPTrack
std::shared_ptr< const WaveTrack > mPTrack
Definition: WaveTrack.h:673
WaveTrackCache::mOverlapBuffer
GrowableSampleBuffer mOverlapBuffer
Definition: WaveTrack.h:676
WaveTrackCache::mBufferSize
size_t mBufferSize
Definition: WaveTrack.h:674
format
int format
Definition: ExportPCM.cpp:56
WaveTrackCache::SetTrack
void SetTrack(const std::shared_ptr< const WaveTrack > &pTrack)
Definition: WaveTrack.cpp:2525
samplePtr
char * samplePtr
Definition: SampleFormat.h:49
WaveTrack::GetMaxBlockSize
size_t GetMaxBlockSize() const
Definition: WaveTrack.cpp:1581
min
int min(int a, int b)
Definition: CompareAudioCommand.cpp:106
sampleCount
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:18
WaveTrackCache::Free
void Free()
Definition: WaveTrack.cpp:2724
WaveTrackCache::Buffer::data
Floats data
Definition: WaveTrack.h:657
ArrayOf< float >
WaveTrackCache::Buffer::start
sampleCount start
Definition: WaveTrack.h:658