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 636 of file WaveTrack.h.

Constructor & Destructor Documentation

◆ WaveTrackCache() [1/2]

WaveTrackCache::WaveTrackCache ( )
inline

Definition at line 638 of file WaveTrack.h.

639  : mBufferSize(0)
640  , mOverlapBuffer()
641  , mNValidBuffers(0)
642  {
643  }

◆ WaveTrackCache() [2/2]

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

Definition at line 645 of file WaveTrack.h.

646  : mBufferSize(0)
647  , mOverlapBuffer()
648  , mNValidBuffers(0)
649  {
650  SetTrack(pTrack);
651  }

◆ ~WaveTrackCache()

WaveTrackCache::~WaveTrackCache ( )

Definition at line 2612 of file WaveTrack.cpp.

2613 {
2614 }

Member Function Documentation

◆ Free()

void WaveTrackCache::Free ( )
private

Definition at line 2815 of file WaveTrack.cpp.

2816 {
2817  mBuffers[0].Free();
2818  mBuffers[1].Free();
2819  mOverlapBuffer.Free();
2820  mNValidBuffers = 0;
2821 }

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 2635 of file WaveTrack.cpp.

2637 {
2638  constexpr auto format = floatSample;
2639  if (format == floatSample && len > 0) {
2640  const auto end = start + len;
2641 
2642  bool fillFirst = (mNValidBuffers < 1);
2643  bool fillSecond = (mNValidBuffers < 2);
2644 
2645  // Discard cached results that we no longer need
2646  if (mNValidBuffers > 0 &&
2647  (end <= mBuffers[0].start ||
2648  start >= mBuffers[mNValidBuffers - 1].end())) {
2649  // Complete miss
2650  fillFirst = true;
2651  fillSecond = true;
2652  }
2653  else if (mNValidBuffers == 2 &&
2654  start >= mBuffers[1].start &&
2655  end > mBuffers[1].end()) {
2656  // Request starts in the second buffer and extends past it.
2657  // Discard the first buffer.
2658  // (But don't deallocate the buffer space.)
2659  mBuffers[0] .swap ( mBuffers[1] );
2660  fillSecond = true;
2661  mNValidBuffers = 1;
2662  }
2663  else if (mNValidBuffers > 0 &&
2664  start < mBuffers[0].start &&
2665  0 <= mPTrack->GetBlockStart(start)) {
2666  // Request is not a total miss but starts before the cache,
2667  // and there is a clip to fetch from.
2668  // Not the access pattern for drawing spectrogram or playback,
2669  // but maybe scrubbing causes this.
2670  // Move the first buffer into second place, and later
2671  // refill the first.
2672  // (This case might be useful when marching backwards through
2673  // the track, as with scrubbing.)
2674  mBuffers[0] .swap ( mBuffers[1] );
2675  fillFirst = true;
2676  fillSecond = false;
2677  // Cache is not in a consistent state yet
2678  mNValidBuffers = 0;
2679  }
2680 
2681  // Refill buffers as needed
2682  if (fillFirst) {
2683  const auto start0 = mPTrack->GetBlockStart(start);
2684  if (start0 >= 0) {
2685  const auto len0 = mPTrack->GetBestBlockSize(start0);
2686  wxASSERT(len0 <= mBufferSize);
2687  if (!mPTrack->GetFloats(
2688  mBuffers[0].data.get(), start0, len0,
2689  fillZero, mayThrow))
2690  return nullptr;
2691  mBuffers[0].start = start0;
2692  mBuffers[0].len = len0;
2693  if (!fillSecond &&
2694  mBuffers[0].end() != mBuffers[1].start)
2695  fillSecond = true;
2696  // Keep the partially updated state consistent:
2697  mNValidBuffers = fillSecond ? 1 : 2;
2698  }
2699  else {
2700  // Request may fall between the clips of a track.
2701  // Invalidate all. WaveTrack::Get() will return zeroes.
2702  mNValidBuffers = 0;
2703  fillSecond = false;
2704  }
2705  }
2706  wxASSERT(!fillSecond || mNValidBuffers > 0);
2707  if (fillSecond) {
2708  mNValidBuffers = 1;
2709  const auto end0 = mBuffers[0].end();
2710  if (end > end0) {
2711  const auto start1 = mPTrack->GetBlockStart(end0);
2712  if (start1 == end0) {
2713  const auto len1 = mPTrack->GetBestBlockSize(start1);
2714  wxASSERT(len1 <= mBufferSize);
2715  if (!mPTrack->GetFloats(mBuffers[1].data.get(), start1, len1, fillZero, mayThrow))
2716  return nullptr;
2717  mBuffers[1].start = start1;
2718  mBuffers[1].len = len1;
2719  mNValidBuffers = 2;
2720  }
2721  }
2722  }
2723  wxASSERT(mNValidBuffers < 2 || mBuffers[0].end() == mBuffers[1].start);
2724 
2725  samplePtr buffer = nullptr; // will point into mOverlapBuffer
2726  auto remaining = len;
2727 
2728  // Possibly get an initial portion that is uncached
2729 
2730  // This may be negative
2731  const auto initLen =
2732  mNValidBuffers < 1 ? sampleCount( len )
2733  : std::min(sampleCount( len ), mBuffers[0].start - start);
2734 
2735  if (initLen > 0) {
2736  // This might be fetching zeroes between clips
2738  // initLen is not more than len:
2739  auto sinitLen = initLen.as_size_t();
2740  if (!mPTrack->GetFloats(
2741  // See comment below about casting
2742  reinterpret_cast<float *>(mOverlapBuffer.ptr()),
2743  start, sinitLen, fillZero, mayThrow))
2744  return nullptr;
2745  wxASSERT( sinitLen <= remaining );
2746  remaining -= sinitLen;
2747  start += initLen;
2748  buffer = mOverlapBuffer.ptr() + sinitLen * SAMPLE_SIZE(format);
2749  }
2750 
2751  // Now satisfy the request from the buffers
2752  for (int ii = 0; ii < mNValidBuffers && remaining > 0; ++ii) {
2753  const auto starti = start - mBuffers[ii].start;
2754  // Treatment of initLen above establishes this loop invariant,
2755  // and statements below preserve it:
2756  wxASSERT(starti >= 0);
2757 
2758  // This may be negative
2759  const auto leni =
2760  std::min( sampleCount( remaining ), mBuffers[ii].len - starti );
2761  if (initLen <= 0 && leni == len) {
2762  // All is contiguous already. We can completely avoid copying
2763  // leni is nonnegative, therefore start falls within mBuffers[ii],
2764  // so starti is bounded between 0 and buffer length
2765  return mBuffers[ii].data.get() + starti.as_size_t() ;
2766  }
2767  else if (leni > 0) {
2768  // leni is nonnegative, therefore start falls within mBuffers[ii]
2769  // But we can't satisfy all from one buffer, so copy
2770  if (!buffer) {
2772  buffer = mOverlapBuffer.ptr();
2773  }
2774  // leni is positive and not more than remaining
2775  const size_t size = sizeof(float) * leni.as_size_t();
2776  // starti is less than mBuffers[ii].len and nonnegative
2777  memcpy(buffer, mBuffers[ii].data.get() + starti.as_size_t(), size);
2778  wxASSERT( leni <= remaining );
2779  remaining -= leni.as_size_t();
2780  start += leni;
2781  buffer += size;
2782  }
2783  }
2784 
2785  if (remaining > 0) {
2786  // Very big request!
2787  // Fall back to direct fetch
2788  if (!buffer) {
2790  buffer = mOverlapBuffer.ptr();
2791  }
2792  // See comment below about casting
2793  if (!mPTrack->GetFloats( reinterpret_cast<float*>(buffer),
2794  start, remaining, fillZero, mayThrow))
2795  return 0;
2796  }
2797 
2798  // Overlap buffer was meant for the more general support of sample formats
2799  // besides float, which explains the cast
2800  return reinterpret_cast<const float*>(mOverlapBuffer.ptr());
2801  }
2802  else {
2803 #if 0
2804  // Cache works only for float format.
2806  if (mPTrack->Get(mOverlapBuffer.ptr(), format, start, len, fillZero, mayThrow))
2807  return mOverlapBuffer.ptr();
2808 #else
2809  // No longer handling other than float format. Therefore len is 0.
2810 #endif
2811  return nullptr;
2812  }
2813 }

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, 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 654 of file WaveTrack.h.

654 { 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 2616 of file WaveTrack.cpp.

2617 {
2618  if (mPTrack != pTrack) {
2619  if (pTrack) {
2620  mBufferSize = pTrack->GetMaxBlockSize();
2621  if (!mPTrack ||
2622  mPTrack->GetMaxBlockSize() != mBufferSize) {
2623  Free();
2624  mBuffers[0].data = Floats{ mBufferSize };
2625  mBuffers[1].data = Floats{ mBufferSize };
2626  }
2627  }
2628  else
2629  Free();
2630  mPTrack = pTrack;
2631  mNValidBuffers = 0;
2632  }
2633 }

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 685 of file WaveTrack.h.

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

◆ mBufferSize

size_t WaveTrackCache::mBufferSize
private

Definition at line 684 of file WaveTrack.h.

Referenced by GetFloats(), and SetTrack().

◆ mNValidBuffers

int WaveTrackCache::mNValidBuffers
private

Definition at line 687 of file WaveTrack.h.

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

◆ mOverlapBuffer

GrowableSampleBuffer WaveTrackCache::mOverlapBuffer
private

Definition at line 686 of file WaveTrack.h.

Referenced by Free(), and GetFloats().

◆ mPTrack

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

Definition at line 683 of file WaveTrack.h.

Referenced by GetFloats(), and SetTrack().


The documentation for this class was generated from the following files:
size
size_t size
Definition: ffmpeg-2.3.6-single-header.h:412
GrowableSampleBuffer::Resize
GrowableSampleBuffer & Resize(size_t count, sampleFormat format)
Definition: SampleFormat.h:118
WaveTrackCache::Buffer::swap
void swap(Buffer &other)
Definition: WaveTrack.h:675
GrowableSampleBuffer::Free
void Free()
Definition: SampleFormat.h:127
WaveTrackCache::mNValidBuffers
int mNValidBuffers
Definition: WaveTrack.h:687
WaveTrackCache::mBuffers
Buffer mBuffers[2]
Definition: WaveTrack.h:685
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:673
fillZero
@ fillZero
Definition: SampleFormat.h:54
floatSample
@ floatSample
Definition: SampleFormat.h:34
WaveTrackCache::Buffer::len
sampleCount len
Definition: WaveTrack.h:669
WaveTrackCache::Buffer::Free
void Free()
Definition: WaveTrack.h:672
WaveTrackCache::mPTrack
std::shared_ptr< const WaveTrack > mPTrack
Definition: WaveTrack.h:683
WaveTrackCache::mOverlapBuffer
GrowableSampleBuffer mOverlapBuffer
Definition: WaveTrack.h:686
WaveTrackCache::mBufferSize
size_t mBufferSize
Definition: WaveTrack.h:684
format
int format
Definition: ExportPCM.cpp:56
WaveTrackCache::SetTrack
void SetTrack(const std::shared_ptr< const WaveTrack > &pTrack)
Definition: WaveTrack.cpp:2616
samplePtr
char * samplePtr
Definition: SampleFormat.h:49
WaveTrack::GetMaxBlockSize
size_t GetMaxBlockSize() const
Definition: WaveTrack.cpp:1661
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:2815
WaveTrackCache::Buffer::data
Floats data
Definition: WaveTrack.h:667
ArrayOf< float >
WaveTrackCache::Buffer::start
sampleCount start
Definition: WaveTrack.h:668