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

Constructor & Destructor Documentation

◆ WaveTrackCache() [1/2]

WaveTrackCache::WaveTrackCache ( )
inline

Definition at line 643 of file WaveTrack.h.

644  : mBufferSize(0)
645  , mOverlapBuffer()
646  , mNValidBuffers(0)
647  {
648  }

◆ WaveTrackCache() [2/2]

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

Definition at line 650 of file WaveTrack.h.

651  : mBufferSize(0)
652  , mOverlapBuffer()
653  , mNValidBuffers(0)
654  {
655  SetTrack(pTrack);
656  }

◆ ~WaveTrackCache()

WaveTrackCache::~WaveTrackCache ( )

Definition at line 2738 of file WaveTrack.cpp.

2739 {
2740 }

Member Function Documentation

◆ Free()

void WaveTrackCache::Free ( )
private

Definition at line 2941 of file WaveTrack.cpp.

2942 {
2943  mBuffers[0].Free();
2944  mBuffers[1].Free();
2945  mOverlapBuffer.Free();
2946  mNValidBuffers = 0;
2947 }

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

2763 {
2764  constexpr auto format = floatSample;
2765  if (format == floatSample && len > 0) {
2766  const auto end = start + len;
2767 
2768  bool fillFirst = (mNValidBuffers < 1);
2769  bool fillSecond = (mNValidBuffers < 2);
2770 
2771  // Discard cached results that we no longer need
2772  if (mNValidBuffers > 0 &&
2773  (end <= mBuffers[0].start ||
2774  start >= mBuffers[mNValidBuffers - 1].end())) {
2775  // Complete miss
2776  fillFirst = true;
2777  fillSecond = true;
2778  }
2779  else if (mNValidBuffers == 2 &&
2780  start >= mBuffers[1].start &&
2781  end > mBuffers[1].end()) {
2782  // Request starts in the second buffer and extends past it.
2783  // Discard the first buffer.
2784  // (But don't deallocate the buffer space.)
2785  mBuffers[0] .swap ( mBuffers[1] );
2786  fillSecond = true;
2787  mNValidBuffers = 1;
2788  }
2789  else if (mNValidBuffers > 0 &&
2790  start < mBuffers[0].start &&
2791  0 <= mPTrack->GetBlockStart(start)) {
2792  // Request is not a total miss but starts before the cache,
2793  // and there is a clip to fetch from.
2794  // Not the access pattern for drawing spectrogram or playback,
2795  // but maybe scrubbing causes this.
2796  // Move the first buffer into second place, and later
2797  // refill the first.
2798  // (This case might be useful when marching backwards through
2799  // the track, as with scrubbing.)
2800  mBuffers[0] .swap ( mBuffers[1] );
2801  fillFirst = true;
2802  fillSecond = false;
2803  // Cache is not in a consistent state yet
2804  mNValidBuffers = 0;
2805  }
2806 
2807  // Refill buffers as needed
2808  if (fillFirst) {
2809  const auto start0 = mPTrack->GetBlockStart(start);
2810  if (start0 >= 0) {
2811  const auto len0 = mPTrack->GetBestBlockSize(start0);
2812  wxASSERT(len0 <= mBufferSize);
2813  if (!mPTrack->GetFloats(
2814  mBuffers[0].data.get(), start0, len0,
2815  fillZero, mayThrow))
2816  return nullptr;
2817  mBuffers[0].start = start0;
2818  mBuffers[0].len = len0;
2819  if (!fillSecond &&
2820  mBuffers[0].end() != mBuffers[1].start)
2821  fillSecond = true;
2822  // Keep the partially updated state consistent:
2823  mNValidBuffers = fillSecond ? 1 : 2;
2824  }
2825  else {
2826  // Request may fall between the clips of a track.
2827  // Invalidate all. WaveTrack::Get() will return zeroes.
2828  mNValidBuffers = 0;
2829  fillSecond = false;
2830  }
2831  }
2832  wxASSERT(!fillSecond || mNValidBuffers > 0);
2833  if (fillSecond) {
2834  mNValidBuffers = 1;
2835  const auto end0 = mBuffers[0].end();
2836  if (end > end0) {
2837  const auto start1 = mPTrack->GetBlockStart(end0);
2838  if (start1 == end0) {
2839  const auto len1 = mPTrack->GetBestBlockSize(start1);
2840  wxASSERT(len1 <= mBufferSize);
2841  if (!mPTrack->GetFloats(mBuffers[1].data.get(), start1, len1, fillZero, mayThrow))
2842  return nullptr;
2843  mBuffers[1].start = start1;
2844  mBuffers[1].len = len1;
2845  mNValidBuffers = 2;
2846  }
2847  }
2848  }
2849  wxASSERT(mNValidBuffers < 2 || mBuffers[0].end() == mBuffers[1].start);
2850 
2851  samplePtr buffer = nullptr; // will point into mOverlapBuffer
2852  auto remaining = len;
2853 
2854  // Possibly get an initial portion that is uncached
2855 
2856  // This may be negative
2857  const auto initLen =
2858  mNValidBuffers < 1 ? sampleCount( len )
2859  : std::min(sampleCount( len ), mBuffers[0].start - start);
2860 
2861  if (initLen > 0) {
2862  // This might be fetching zeroes between clips
2864  // initLen is not more than len:
2865  auto sinitLen = initLen.as_size_t();
2866  if (!mPTrack->GetFloats(
2867  // See comment below about casting
2868  reinterpret_cast<float *>(mOverlapBuffer.ptr()),
2869  start, sinitLen, fillZero, mayThrow))
2870  return nullptr;
2871  wxASSERT( sinitLen <= remaining );
2872  remaining -= sinitLen;
2873  start += initLen;
2874  buffer = mOverlapBuffer.ptr() + sinitLen * SAMPLE_SIZE(format);
2875  }
2876 
2877  // Now satisfy the request from the buffers
2878  for (int ii = 0; ii < mNValidBuffers && remaining > 0; ++ii) {
2879  const auto starti = start - mBuffers[ii].start;
2880  // Treatment of initLen above establishes this loop invariant,
2881  // and statements below preserve it:
2882  wxASSERT(starti >= 0);
2883 
2884  // This may be negative
2885  const auto leni =
2886  std::min( sampleCount( remaining ), mBuffers[ii].len - starti );
2887  if (initLen <= 0 && leni == len) {
2888  // All is contiguous already. We can completely avoid copying
2889  // leni is nonnegative, therefore start falls within mBuffers[ii],
2890  // so starti is bounded between 0 and buffer length
2891  return mBuffers[ii].data.get() + starti.as_size_t() ;
2892  }
2893  else if (leni > 0) {
2894  // leni is nonnegative, therefore start falls within mBuffers[ii]
2895  // But we can't satisfy all from one buffer, so copy
2896  if (!buffer) {
2898  buffer = mOverlapBuffer.ptr();
2899  }
2900  // leni is positive and not more than remaining
2901  const size_t size = sizeof(float) * leni.as_size_t();
2902  // starti is less than mBuffers[ii].len and nonnegative
2903  memcpy(buffer, mBuffers[ii].data.get() + starti.as_size_t(), size);
2904  wxASSERT( leni <= remaining );
2905  remaining -= leni.as_size_t();
2906  start += leni;
2907  buffer += size;
2908  }
2909  }
2910 
2911  if (remaining > 0) {
2912  // Very big request!
2913  // Fall back to direct fetch
2914  if (!buffer) {
2916  buffer = mOverlapBuffer.ptr();
2917  }
2918  // See comment below about casting
2919  if (!mPTrack->GetFloats( reinterpret_cast<float*>(buffer),
2920  start, remaining, fillZero, mayThrow))
2921  return 0;
2922  }
2923 
2924  // Overlap buffer was meant for the more general support of sample formats
2925  // besides float, which explains the cast
2926  return reinterpret_cast<const float*>(mOverlapBuffer.ptr());
2927  }
2928  else {
2929 #if 0
2930  // Cache works only for float format.
2932  if (mPTrack->Get(mOverlapBuffer.ptr(), format, start, len, fillZero, mayThrow))
2933  return mOverlapBuffer.ptr();
2934 #else
2935  // No longer handling other than float format. Therefore len is 0.
2936 #endif
2937  return nullptr;
2938  }
2939 }

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

659 { 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 2742 of file WaveTrack.cpp.

2743 {
2744  if (mPTrack != pTrack) {
2745  if (pTrack) {
2746  mBufferSize = pTrack->GetMaxBlockSize();
2747  if (!mPTrack ||
2748  mPTrack->GetMaxBlockSize() != mBufferSize) {
2749  Free();
2750  mBuffers[0].data = Floats{ mBufferSize };
2751  mBuffers[1].data = Floats{ mBufferSize };
2752  }
2753  }
2754  else
2755  Free();
2756  mPTrack = pTrack;
2757  mNValidBuffers = 0;
2758  }
2759 }

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

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

◆ mBufferSize

size_t WaveTrackCache::mBufferSize
private

Definition at line 689 of file WaveTrack.h.

Referenced by GetFloats(), and SetTrack().

◆ mNValidBuffers

int WaveTrackCache::mNValidBuffers
private

Definition at line 692 of file WaveTrack.h.

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

◆ mOverlapBuffer

GrowableSampleBuffer WaveTrackCache::mOverlapBuffer
private

Definition at line 691 of file WaveTrack.h.

Referenced by Free(), and GetFloats().

◆ mPTrack

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

Definition at line 688 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:680
GrowableSampleBuffer::Free
void Free()
Definition: SampleFormat.h:127
WaveTrackCache::mNValidBuffers
int mNValidBuffers
Definition: WaveTrack.h:692
WaveTrackCache::mBuffers
Buffer mBuffers[2]
Definition: WaveTrack.h:690
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:678
fillZero
@ fillZero
Definition: SampleFormat.h:54
floatSample
@ floatSample
Definition: SampleFormat.h:34
WaveTrackCache::Buffer::len
sampleCount len
Definition: WaveTrack.h:674
WaveTrackCache::Buffer::Free
void Free()
Definition: WaveTrack.h:677
WaveTrackCache::mPTrack
std::shared_ptr< const WaveTrack > mPTrack
Definition: WaveTrack.h:688
WaveTrackCache::mOverlapBuffer
GrowableSampleBuffer mOverlapBuffer
Definition: WaveTrack.h:691
WaveTrackCache::mBufferSize
size_t mBufferSize
Definition: WaveTrack.h:689
format
int format
Definition: ExportPCM.cpp:56
WaveTrackCache::SetTrack
void SetTrack(const std::shared_ptr< const WaveTrack > &pTrack)
Definition: WaveTrack.cpp:2742
samplePtr
char * samplePtr
Definition: SampleFormat.h:49
WaveTrack::GetMaxBlockSize
size_t GetMaxBlockSize() const
Definition: WaveTrack.cpp:1800
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:2941
WaveTrackCache::Buffer::data
Floats data
Definition: WaveTrack.h:672
ArrayOf< float >
WaveTrackCache::Buffer::start
sampleCount start
Definition: WaveTrack.h:673