Audacity 3.2.0
Classes | Public Member Functions | Private Member Functions | Private Attributes | List of all members
SampleTrackCache Class Reference

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

#include <SampleTrackCache.h>

Collaboration diagram for SampleTrackCache:
[legend]

Classes

struct  Buffer
 

Public Member Functions

 SampleTrackCache ()
 
 SampleTrackCache (const std::shared_ptr< const SampleTrack > &pTrack)
 
 ~SampleTrackCache ()
 
const std::shared_ptr< const SampleTrack > & GetTrack () const
 
void SetTrack (const std::shared_ptr< const SampleTrack > &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 SampleTrackmPTrack
 
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 24 of file SampleTrackCache.h.

Constructor & Destructor Documentation

◆ SampleTrackCache() [1/2]

SampleTrackCache::SampleTrackCache ( )
inline

Definition at line 26 of file SampleTrackCache.h.

27 : mBufferSize(0)
30 {
31 }
GrowableSampleBuffer mOverlapBuffer

◆ SampleTrackCache() [2/2]

SampleTrackCache::SampleTrackCache ( const std::shared_ptr< const SampleTrack > &  pTrack)
inlineexplicit

Definition at line 33 of file SampleTrackCache.h.

34 : mBufferSize(0)
37 {
38 SetTrack(pTrack);
39 }
void SetTrack(const std::shared_ptr< const SampleTrack > &pTrack)

◆ ~SampleTrackCache()

SampleTrackCache::~SampleTrackCache ( )

Definition at line 14 of file SampleTrackCache.cpp.

15{
16}

Member Function Documentation

◆ Free()

void SampleTrackCache::Free ( )
private

Definition at line 217 of file SampleTrackCache.cpp.

218{
219 mBuffers[0].Free();
220 mBuffers[1].Free();
222 mNValidBuffers = 0;
223}

References GrowableSampleBuffer::Free(), SampleTrackCache::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 * SampleTrackCache::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 37 of file SampleTrackCache.cpp.

39{
40 constexpr auto format = floatSample;
41 if (format == floatSample && len > 0) {
42 const auto end = start + len;
43
44 bool fillFirst = (mNValidBuffers < 1);
45 bool fillSecond = (mNValidBuffers < 2);
46
47 // Discard cached results that we no longer need
48 if (mNValidBuffers > 0 &&
49 (end <= mBuffers[0].start ||
50 start >= mBuffers[mNValidBuffers - 1].end())) {
51 // Complete miss
52 fillFirst = true;
53 fillSecond = true;
54 }
55 else if (mNValidBuffers == 2 &&
56 start >= mBuffers[1].start &&
57 end > mBuffers[1].end()) {
58 // Request starts in the second buffer and extends past it.
59 // Discard the first buffer.
60 // (But don't deallocate the buffer space.)
61 mBuffers[0] .swap ( mBuffers[1] );
62 fillSecond = true;
64 }
65 else if (mNValidBuffers > 0 &&
66 start < mBuffers[0].start &&
67 0 <= mPTrack->GetBlockStart(start)) {
68 // Request is not a total miss but starts before the cache,
69 // and there is a clip to fetch from.
70 // Not the access pattern for drawing spectrogram or playback,
71 // but maybe scrubbing causes this.
72 // Move the first buffer into second place, and later
73 // refill the first.
74 // (This case might be useful when marching backwards through
75 // the track, as with scrubbing.)
76 mBuffers[0] .swap ( mBuffers[1] );
77 fillFirst = true;
78 fillSecond = false;
79 // Cache is not in a consistent state yet
81 }
82
83 // Refill buffers as needed
84 if (fillFirst) {
85 const auto start0 = mPTrack->GetBlockStart(start);
86 if (start0 >= 0) {
87 const auto len0 = mPTrack->GetBestBlockSize(start0);
88 wxASSERT(len0 <= mBufferSize);
89 if (!mPTrack->GetFloats(
90 mBuffers[0].data.get(), start0, len0,
91 fillZero, mayThrow))
92 return nullptr;
93 mBuffers[0].start = start0;
94 mBuffers[0].len = len0;
95 if (!fillSecond &&
96 mBuffers[0].end() != mBuffers[1].start)
97 fillSecond = true;
98 // Keep the partially updated state consistent:
99 mNValidBuffers = fillSecond ? 1 : 2;
100 }
101 else {
102 // Request may fall between the clips of a track.
103 // Invalidate all. WaveTrack::Get() will return zeroes.
104 mNValidBuffers = 0;
105 fillSecond = false;
106 }
107 }
108 wxASSERT(!fillSecond || mNValidBuffers > 0);
109 if (fillSecond) {
110 mNValidBuffers = 1;
111 const auto end0 = mBuffers[0].end();
112 if (end > end0) {
113 const auto start1 = mPTrack->GetBlockStart(end0);
114 if (start1 == end0) {
115 const auto len1 = mPTrack->GetBestBlockSize(start1);
116 wxASSERT(len1 <= mBufferSize);
117 if (!mPTrack->GetFloats(mBuffers[1].data.get(), start1, len1, fillZero, mayThrow))
118 return nullptr;
119 mBuffers[1].start = start1;
120 mBuffers[1].len = len1;
121 mNValidBuffers = 2;
122 }
123 }
124 }
125 wxASSERT(mNValidBuffers < 2 || mBuffers[0].end() == mBuffers[1].start);
126
127 samplePtr buffer = nullptr; // will point into mOverlapBuffer
128 auto remaining = len;
129
130 // Possibly get an initial portion that is uncached
131
132 // This may be negative
133 const auto initLen =
134 mNValidBuffers < 1 ? sampleCount( len )
135 : std::min(sampleCount( len ), mBuffers[0].start - start);
136
137 if (initLen > 0) {
138 // This might be fetching zeroes between clips
140 // initLen is not more than len:
141 auto sinitLen = initLen.as_size_t();
142 if (!mPTrack->GetFloats(
143 // See comment below about casting
144 reinterpret_cast<float *>(mOverlapBuffer.ptr()),
145 start, sinitLen, fillZero, mayThrow))
146 return nullptr;
147 wxASSERT( sinitLen <= remaining );
148 remaining -= sinitLen;
149 start += initLen;
150 buffer = mOverlapBuffer.ptr() + sinitLen * SAMPLE_SIZE(format);
151 }
152
153 // Now satisfy the request from the buffers
154 for (int ii = 0; ii < mNValidBuffers && remaining > 0; ++ii) {
155 const auto starti = start - mBuffers[ii].start;
156 // Treatment of initLen above establishes this loop invariant,
157 // and statements below preserve it:
158 wxASSERT(starti >= 0);
159
160 // This may be negative
161 const auto leni =
162 std::min( sampleCount( remaining ), mBuffers[ii].len - starti );
163 if (initLen <= 0 && leni == len) {
164 // All is contiguous already. We can completely avoid copying
165 // leni is nonnegative, therefore start falls within mBuffers[ii],
166 // so starti is bounded between 0 and buffer length
167 return mBuffers[ii].data.get() + starti.as_size_t() ;
168 }
169 else if (leni > 0) {
170 // leni is nonnegative, therefore start falls within mBuffers[ii]
171 // But we can't satisfy all from one buffer, so copy
172 if (!buffer) {
174 buffer = mOverlapBuffer.ptr();
175 }
176 // leni is positive and not more than remaining
177 const size_t size = sizeof(float) * leni.as_size_t();
178 // starti is less than mBuffers[ii].len and nonnegative
179 memcpy(buffer, mBuffers[ii].data.get() + starti.as_size_t(), size);
180 wxASSERT( leni <= remaining );
181 remaining -= leni.as_size_t();
182 start += leni;
183 buffer += size;
184 }
185 }
186
187 if (remaining > 0) {
188 // Very big request!
189 // Fall back to direct fetch
190 if (!buffer) {
192 buffer = mOverlapBuffer.ptr();
193 }
194 // See comment below about casting
195 if (!mPTrack->GetFloats( reinterpret_cast<float*>(buffer),
196 start, remaining, fillZero, mayThrow))
197 return 0;
198 }
199
200 // Overlap buffer was meant for the more general support of sample formats
201 // besides float, which explains the cast
202 return reinterpret_cast<const float*>(mOverlapBuffer.ptr());
203 }
204 else {
205#if 0
206 // Cache works only for float format.
208 if (mPTrack->Get(mOverlapBuffer.ptr(), format, start, len, fillZero, mayThrow))
209 return mOverlapBuffer.ptr();
210#else
211 // No longer handling other than float format. Therefore len is 0.
212#endif
213 return nullptr;
214 }
215}
int min(int a, int b)
int format
Definition: ExportPCM.cpp:53
char * samplePtr
Definition: SampleFormat.h:55
#define SAMPLE_SIZE(SampleFormat)
Definition: SampleFormat.h:50
@ fillZero
Definition: SampleFormat.h:60
GrowableSampleBuffer & Resize(size_t count, sampleFormat format)
Definition: SampleFormat.h:172
samplePtr ptr() const
Definition: SampleFormat.h:152
std::shared_ptr< const SampleTrack > mPTrack
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:19
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159
STL namespace.
void swap(Buffer &other)
sampleCount end() const

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

Referenced by SpecCache::CalculateOneSpectrum().

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

◆ GetTrack()

const std::shared_ptr< const SampleTrack > & SampleTrackCache::GetTrack ( ) const
inline

Definition at line 42 of file SampleTrackCache.h.

42{ return mPTrack; }

Referenced by anonymous_namespace{SpectrumView.cpp}::DrawClipSpectrum(), WaveClipSpectrumCache::GetSpectrogram(), and SpecCache::Populate().

Here is the caller graph for this function:

◆ SetTrack()

void SampleTrackCache::SetTrack ( const std::shared_ptr< const SampleTrack > &  pTrack)

Definition at line 18 of file SampleTrackCache.cpp.

19{
20 if (mPTrack != pTrack) {
21 if (pTrack) {
22 mBufferSize = pTrack->GetMaxBlockSize();
23 if (!mPTrack ||
24 mPTrack->GetMaxBlockSize() != mBufferSize) {
25 Free();
28 }
29 }
30 else
31 Free();
32 mPTrack = pTrack;
34 }
35}

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

Here is the call graph for this function:

Member Data Documentation

◆ mBuffers

Buffer SampleTrackCache::mBuffers[2]
private

Definition at line 73 of file SampleTrackCache.h.

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

◆ mBufferSize

size_t SampleTrackCache::mBufferSize
private

Definition at line 72 of file SampleTrackCache.h.

Referenced by GetFloats(), and SetTrack().

◆ mNValidBuffers

int SampleTrackCache::mNValidBuffers
private

Definition at line 75 of file SampleTrackCache.h.

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

◆ mOverlapBuffer

GrowableSampleBuffer SampleTrackCache::mOverlapBuffer
private

Definition at line 74 of file SampleTrackCache.h.

Referenced by Free(), and GetFloats().

◆ mPTrack

std::shared_ptr<const SampleTrack> SampleTrackCache::mPTrack
private

Definition at line 71 of file SampleTrackCache.h.

Referenced by GetFloats(), and SetTrack().


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