Audacity 3.2.0
Public Member Functions | Static Public Member Functions | Public Attributes | List of all members
WaveClipWaveformCache Struct Referencefinal

#include <WaveformCache.h>

Inheritance diagram for WaveClipWaveformCache:
[legend]
Collaboration diagram for WaveClipWaveformCache:
[legend]

Public Member Functions

 WaveClipWaveformCache (size_t nChannels)
 
 ~WaveClipWaveformCache () override
 
void MarkChanged () override
 
void Invalidate () override
 
void Clear ()
 Delete the wave cache - force redraw. Thread-safe. More...
 
bool GetWaveDisplay (const WaveChannelInterval &clip, WaveDisplay &display, double t0, double pixelsPerSecond)
 
- Public Member Functions inherited from WaveClipListener
virtual ~WaveClipListener ()=0
 
virtual void MarkChanged ()=0
 
virtual void Invalidate ()=0
 

Static Public Member Functions

static WaveClipWaveformCacheGet (const WaveClip &clip)
 

Public Attributes

std::vector< std::unique_ptr< WaveCache > > mWaveCaches
 
int mDirty { 0 }
 

Detailed Description

Definition at line 19 of file WaveformCache.h.

Constructor & Destructor Documentation

◆ WaveClipWaveformCache()

WaveClipWaveformCache::WaveClipWaveformCache ( size_t  nChannels)
explicit

Definition at line 271 of file WaveformCache.cpp.

273 : mWaveCaches(std::max<size_t>(2, nChannels))
274{
275 for (auto &pCache : mWaveCaches)
276 pCache = std::make_unique<WaveCache>();
277}
std::vector< std::unique_ptr< WaveCache > > mWaveCaches
Definition: WaveformCache.h:25

References mWaveCaches.

◆ ~WaveClipWaveformCache()

WaveClipWaveformCache::~WaveClipWaveformCache ( )
override

Definition at line 279 of file WaveformCache.cpp.

280{
281}

Member Function Documentation

◆ Clear()

void WaveClipWaveformCache::Clear ( )

Delete the wave cache - force redraw. Thread-safe.

◆ Get()

WaveClipWaveformCache & WaveClipWaveformCache::Get ( const WaveClip clip)
static

Definition at line 287 of file WaveformCache.cpp.

288{
289 return const_cast< WaveClip& >( clip ) // Consider it mutable data
290 .Caches::Get< WaveClipWaveformCache >( sKeyW );
291}
static WaveClip::Caches::RegisteredFactory sKeyW
This allows multiple clips to be a part of one WaveTrack.
Definition: WaveClip.h:113

References sKeyW.

Referenced by anonymous_namespace{WaveformView.cpp}::DrawClipWaveform().

Here is the caller graph for this function:

◆ GetWaveDisplay()

bool WaveClipWaveformCache::GetWaveDisplay ( const WaveChannelInterval clip,
WaveDisplay display,
double  t0,
double  pixelsPerSecond 
)

Getting high-level data for screen display

Definition at line 66 of file WaveformCache.cpp.

69{
70 auto &waveCache = mWaveCaches[clip.GetChannelIndex()];
71
72 t0 += clip.GetTrimLeft();
73
74 const bool allocated = (display.where != 0);
75
76 const size_t numPixels = (int)display.width;
77
78 size_t p0 = 0; // least column requiring computation
79 size_t p1 = numPixels; // greatest column requiring computation, plus one
80
81 float *min;
82 float *max;
83 float *rms;
84 std::vector<sampleCount> *pWhere;
85
86 if (allocated) {
87 // assume ownWhere is filled.
88 min = &display.min[0];
89 max = &display.max[0];
90 rms = &display.rms[0];
91 pWhere = &display.ownWhere;
92 }
93 else {
94 const auto sampleRate = clip.GetRate();
95 const auto stretchRatio = clip.GetStretchRatio();
96 const double samplesPerPixel =
97 sampleRate / pixelsPerSecond / stretchRatio;
98
99 // Make a tolerant comparison of the samples-per-pixel values in this wise:
100 // accumulated difference of times over the number of pixels is less than
101 // a sample period.
102 const bool samplesPerPixelMatch =
103 waveCache &&
104 (fabs(samplesPerPixel - waveCache->samplesPerPixel) * numPixels < 1.0);
105
106 const bool match = waveCache && samplesPerPixelMatch &&
107 waveCache->len > 0 && waveCache->dirty == mDirty;
108
109 if (match &&
110 waveCache->start == t0 &&
111 waveCache->len >= numPixels) {
112
113 // Satisfy the request completely from the cache
114 display.min = &waveCache->min[0];
115 display.max = &waveCache->max[0];
116 display.rms = &waveCache->rms[0];
117 display.where = &waveCache->where[0];
118 return true;
119 }
120
121 std::unique_ptr<WaveCache> oldCache(std::move(waveCache));
122
123 int oldX0 = 0;
124 double correction = 0.0;
125 size_t copyBegin = 0, copyEnd = 0;
126 if (match) {
128 oldCache->where, oldCache->len, numPixels, t0, sampleRate,
129 stretchRatio, samplesPerPixel, oldX0, correction);
130 // Remember our first pixel maps to oldX0 in the old cache,
131 // possibly out of bounds.
132 // For what range of pixels can data be copied?
133 copyBegin = std::min<size_t>(numPixels, std::max(0, -oldX0));
134 copyEnd = std::min<size_t>(numPixels, std::max(0,
135 (int)oldCache->len - oldX0
136 ));
137 }
138 if (!(copyEnd > copyBegin))
139 oldCache.reset(0);
140
141 waveCache = std::make_unique<WaveCache>(
142 numPixels, samplesPerPixel, sampleRate, t0, mDirty);
143 min = &waveCache->min[0];
144 max = &waveCache->max[0];
145 rms = &waveCache->rms[0];
146 pWhere = &waveCache->where;
147
148 constexpr auto addBias = false;
149 fillWhere(
150 *pWhere, numPixels, addBias, correction, t0, sampleRate, stretchRatio,
151 samplesPerPixel);
152
153 // The range of pixels we must fetch from the Sequence:
154 p0 = (copyBegin > 0) ? 0 : copyEnd;
155 p1 = (copyEnd >= numPixels) ? copyBegin : numPixels;
156
157 // Optimization: if the old cache is good and overlaps
158 // with the current one, re-use as much of the cache as
159 // possible
160
161 if (oldCache) {
162
163 // Copy what we can from the old cache.
164 const int length = copyEnd - copyBegin;
165 const size_t sizeFloats = length * sizeof(float);
166 const int srcIdx = (int)copyBegin + oldX0;
167 memcpy(&min[copyBegin], &oldCache->min[srcIdx], sizeFloats);
168 memcpy(&max[copyBegin], &oldCache->max[srcIdx], sizeFloats);
169 memcpy(&rms[copyBegin], &oldCache->rms[srcIdx], sizeFloats);
170 }
171 }
172
173 if (p1 > p0) {
174 // Cache was not used or did not satisfy the whole request
175 std::vector<sampleCount> &where = *pWhere;
176
177 /* handle values in the append buffer */
178
179 const auto &sequence = clip.GetSequence();
180 auto numSamples = sequence.GetNumSamples();
181 auto a = p0;
182
183 // Not all of the required columns might be in the sequence.
184 // Some might be in the append buffer.
185 for (; a < p1; ++a) {
186 if (where[a + 1] > numSamples)
187 break;
188 }
189
190 // Handle the columns that land in the append buffer.
191 //compute the values that are outside the overlap from scratch.
192 if (a < p1) {
193 const auto appendBufferLen = clip.GetAppendBufferLen();
194 const auto &appendBuffer = clip.GetAppendBuffer();
195 sampleFormat seqFormat = sequence.GetSampleFormats().Stored();
196 bool didUpdate = false;
197 for(auto i = a; i < p1; i++) {
198 auto left = std::max(sampleCount{ 0 },
199 where[i] - numSamples);
200 auto right = std::min(sampleCount{ appendBufferLen },
201 where[i + 1] - numSamples);
202
203 //wxCriticalSectionLocker locker(mAppendCriticalSection);
204
205 if (right > left) {
206 Floats b;
207 const float *pb{};
208 // left is nonnegative and at most mAppendBufferLen:
209 auto sLeft = left.as_size_t();
210 // The difference is at most mAppendBufferLen:
211 size_t len = ( right - left ).as_size_t();
212
213 if (seqFormat == floatSample)
214 pb = &((const float *)appendBuffer)[sLeft];
215 else {
216 b.reinit(len);
217 pb = b.get();
219 appendBuffer + sLeft * SAMPLE_SIZE(seqFormat),
220 seqFormat, b.get(), len);
221 }
222
223 float theMax, theMin, sumsq;
224 {
225 const float val = pb[0];
226 theMax = theMin = val;
227 sumsq = val * val;
228 }
229 for(decltype(len) j = 1; j < len; j++) {
230 const float val = pb[j];
231 theMax = std::max(theMax, val);
232 theMin = std::min(theMin, val);
233 sumsq += val * val;
234 }
235
236 min[i] = theMin;
237 max[i] = theMax;
238 rms[i] = (float)sqrt(sumsq / len);
239
240 didUpdate=true;
241 }
242 }
243
244 // Shrink the right end of the range to fetch from Sequence
245 if(didUpdate)
246 p1 = a;
247 }
248
249 // Done with append buffer, now fetch the rest of the cache miss
250 // from the sequence
251 if (p1 > p0) {
252 if (!::GetWaveDisplay(sequence, &min[p0], &max[p0], &rms[p0], p1 - p0,
253 &where[p0]))
254 {
255 return false;
256 }
257 }
258 }
259
260 if (!allocated) {
261 // Now report the results
262 display.min = min;
263 display.max = max;
264 display.rms = rms;
265 display.where = &(*pWhere)[0];
266 }
267
268 return true;
269}
int min(int a, int b)
void SamplesToFloats(constSamplePtr src, sampleFormat srcFormat, float *dst, size_t len, size_t srcStride, size_t dstStride)
Copy samples from any format into the widest format, which is 32 bit float, with no dithering.
sampleFormat
The ordering of these values with operator < agrees with the order of increasing bit width.
Definition: SampleFormat.h:30
#define SAMPLE_SIZE(SampleFormat)
Definition: SampleFormat.h:52
void findCorrection(const std::vector< sampleCount > &oldWhere, size_t oldLen, size_t newLen, double t0, double sampleRate, double stretchRatio, double samplesPerPixel, int &oldX0, double &correction)
void fillWhere(std::vector< sampleCount > &where, size_t len, bool addBias, double correction, double t0, double sampleRate, double stretchRatio, double samplesPerPixel)
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:56
sampleCount GetNumSamples() const
Definition: Sequence.h:84
double GetStretchRatio() const override
Definition: WaveTrack.cpp:128
constSamplePtr GetAppendBuffer() const
Definition: WaveTrack.cpp:168
size_t GetAppendBufferLen() const
Definition: WaveTrack.cpp:174
double GetTrimLeft() const
Definition: WaveTrack.cpp:133
const Sequence & GetSequence() const
Definition: WaveTrack.cpp:159
int GetRate() const override
Definition: WaveTrack.cpp:108
size_t GetChannelIndex() const
Definition: WaveTrack.h:81
float * rms
Definition: WaveClip.h:57
sampleCount * where
Definition: WaveClip.h:56
std::vector< sampleCount > ownWhere
Definition: WaveClip.h:59
float * min
Definition: WaveClip.h:57
int width
Definition: WaveClip.h:55
float * max
Definition: WaveClip.h:57
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:19
__finl float_x4 __vecc sqrt(const float_x4 &a)
bool GetWaveDisplay(const WaveChannelInterval &clip, WaveDisplay &display, double t0, double pixelsPerSecond)

References fillWhere(), findCorrection(), floatSample, WaveChannelInterval::GetAppendBuffer(), WaveChannelInterval::GetAppendBufferLen(), WaveChannelInterval::GetChannelIndex(), Sequence::GetNumSamples(), WaveChannelInterval::GetRate(), WaveChannelInterval::GetSequence(), WaveChannelInterval::GetStretchRatio(), WaveChannelInterval::GetTrimLeft(), GetWaveDisplay(), WaveDisplay::max, mDirty, WaveDisplay::min, min(), mWaveCaches, WaveDisplay::ownWhere, ArrayOf< X >::reinit(), WaveDisplay::rms, SAMPLE_SIZE, anonymous_namespace{ClipSegmentTest.cpp}::sampleRate, SamplesToFloats(), staffpad::audio::simd::sqrt(), WaveDisplay::where, and WaveDisplay::width.

Referenced by GetWaveDisplay().

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

◆ Invalidate()

void WaveClipWaveformCache::Invalidate ( )
overridevirtual

Implements WaveClipListener.

Definition at line 298 of file WaveformCache.cpp.

299{
300 // Invalidate wave display caches
301 for (auto &pCache : mWaveCaches)
302 pCache = std::make_unique<WaveCache>();
303}

References mWaveCaches.

◆ MarkChanged()

void WaveClipWaveformCache::MarkChanged ( )
overridevirtual

Implements WaveClipListener.

Definition at line 293 of file WaveformCache.cpp.

294{
295 ++mDirty;
296}

References mDirty.

Member Data Documentation

◆ mDirty

int WaveClipWaveformCache::mDirty { 0 }

Definition at line 26 of file WaveformCache.h.

Referenced by GetWaveDisplay(), and MarkChanged().

◆ mWaveCaches

std::vector<std::unique_ptr<WaveCache> > WaveClipWaveformCache::mWaveCaches

Definition at line 25 of file WaveformCache.h.

Referenced by GetWaveDisplay(), Invalidate(), and WaveClipWaveformCache().


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