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

#include <WaveTrack.h>

Classes

struct  Buffer
 

Public Member Functions

 WaveTrackCache ()
 
 WaveTrackCache (const std::shared_ptr< const WaveTrack > &pTrack)
 
 ~WaveTrackCache ()
 
const WaveTrackGetTrack () const
 
void SetTrack (const std::shared_ptr< const WaveTrack > &pTrack)
 
constSamplePtr Get (sampleFormat format, sampleCount start, size_t len, bool mayThrow)
 

Private Member Functions

void Free ()
 

Private Attributes

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

Detailed Description

Definition at line 665 of file WaveTrack.h.

Constructor & Destructor Documentation

WaveTrackCache::WaveTrackCache ( )
inline

Definition at line 667 of file WaveTrack.h.

668  : mBufferSize(0)
669  , mOverlapBuffer()
670  , mNValidBuffers(0)
671  {
672  }
int mNValidBuffers
Definition: WaveTrack.h:717
GrowableSampleBuffer mOverlapBuffer
Definition: WaveTrack.h:716
size_t mBufferSize
Definition: WaveTrack.h:714
WaveTrackCache::WaveTrackCache ( const std::shared_ptr< const WaveTrack > &  pTrack)
inlineexplicit

Definition at line 674 of file WaveTrack.h.

References SetTrack().

675  : mBufferSize(0)
676  , mOverlapBuffer()
677  , mNValidBuffers(0)
678  {
679  SetTrack(pTrack);
680  }
int mNValidBuffers
Definition: WaveTrack.h:717
GrowableSampleBuffer mOverlapBuffer
Definition: WaveTrack.h:716
void SetTrack(const std::shared_ptr< const WaveTrack > &pTrack)
Definition: WaveTrack.cpp:2614
size_t mBufferSize
Definition: WaveTrack.h:714
WaveTrackCache::~WaveTrackCache ( )

Definition at line 2610 of file WaveTrack.cpp.

2611 {
2612 }

Member Function Documentation

void WaveTrackCache::Free ( )
private

Definition at line 2802 of file WaveTrack.cpp.

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

Referenced by SetTrack().

2803 {
2804  mBuffers[0].Free();
2805  mBuffers[1].Free();
2806  mOverlapBuffer.Free();
2807  mNValidBuffers = 0;
2808 }
Buffer mBuffers[2]
Definition: WaveTrack.h:715
int mNValidBuffers
Definition: WaveTrack.h:717
GrowableSampleBuffer mOverlapBuffer
Definition: WaveTrack.h:716
constSamplePtr WaveTrackCache::Get ( sampleFormat  format,
sampleCount  start,
size_t  len,
bool  mayThrow 
)

Definition at line 2633 of file WaveTrack.cpp.

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

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

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

Definition at line 683 of file WaveTrack.h.

References mPTrack.

Referenced by TrackArtist::DrawClipSpectrum(), WaveClip::GetSpectrogram(), Mixer::MixSameRate(), Mixer::MixVariableRates(), and SpecCache::Populate().

683 { return mPTrack.get(); }
std::shared_ptr< const WaveTrack > mPTrack
Definition: WaveTrack.h:713
void WaveTrackCache::SetTrack ( const std::shared_ptr< const WaveTrack > &  pTrack)

Definition at line 2614 of file WaveTrack.cpp.

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

Referenced by WaveTrackCache().

2615 {
2616  if (mPTrack != pTrack) {
2617  if (pTrack) {
2618  mBufferSize = pTrack->GetMaxBlockSize();
2619  if (!mPTrack ||
2620  mPTrack->GetMaxBlockSize() != mBufferSize) {
2621  Free();
2622  mBuffers[0].data = Floats{ mBufferSize };
2623  mBuffers[1].data = Floats{ mBufferSize };
2624  }
2625  }
2626  else
2627  Free();
2628  mPTrack = pTrack;
2629  mNValidBuffers = 0;
2630  }
2631 }
Buffer mBuffers[2]
Definition: WaveTrack.h:715
int mNValidBuffers
Definition: WaveTrack.h:717
size_t mBufferSize
Definition: WaveTrack.h:714
std::shared_ptr< const WaveTrack > mPTrack
Definition: WaveTrack.h:713

Member Data Documentation

Buffer WaveTrackCache::mBuffers[2]
private

Definition at line 715 of file WaveTrack.h.

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

size_t WaveTrackCache::mBufferSize
private

Definition at line 714 of file WaveTrack.h.

Referenced by Get(), and SetTrack().

int WaveTrackCache::mNValidBuffers
private

Definition at line 717 of file WaveTrack.h.

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

GrowableSampleBuffer WaveTrackCache::mOverlapBuffer
private

Definition at line 716 of file WaveTrack.h.

Referenced by Free(), and Get().

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

Definition at line 713 of file WaveTrack.h.

Referenced by Get(), GetTrack(), and SetTrack().


The documentation for this class was generated from the following files: