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
 
std::unique_ptr< WaveClipListenerClone () const override
 
void MarkChanged () noexcept 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)
 
void MakeStereo (WaveClipListener &&other, bool aligned) override
 
void SwapChannels () override
 Default implementation does nothing. More...
 
void Erase (size_t index) override
 
- Public Member Functions inherited from WaveClipListener
virtual ~WaveClipListener ()=0
 
virtual void MarkChanged () noexcept=0
 
virtual void Invalidate ()=0
 
virtual void WriteXMLAttributes (XMLWriter &writer) const
 
virtual bool HandleXMLAttribute (const std::string_view &attr, const XMLAttributeValueView &valueView)
 
virtual void MakeStereo (WaveClipListener &&other, bool aligned)
 
virtual void SwapChannels ()
 Default implementation does nothing. More...
 
virtual void Erase (size_t index)
 

Static Public Member Functions

static WaveClipWaveformCacheGet (const WaveChannelInterval &clip)
 

Public Attributes

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

Detailed Description

Definition at line 61 of file WaveformCache.h.

Constructor & Destructor Documentation

◆ WaveClipWaveformCache()

WaveClipWaveformCache::WaveClipWaveformCache ( size_t  nChannels)
explicit

Definition at line 271 of file WaveformCache.cpp.

272 : mWaveCaches(nChannels)
273{
274 for (auto &pCache : mWaveCaches)
275 pCache = std::make_unique<WaveCache>();
276}
std::vector< std::unique_ptr< WaveCache > > mWaveCaches
Definition: WaveformCache.h:69

References mWaveCaches.

◆ ~WaveClipWaveformCache()

WaveClipWaveformCache::~WaveClipWaveformCache ( )
override

Definition at line 278 of file WaveformCache.cpp.

279{
280}

Member Function Documentation

◆ Clear()

void WaveClipWaveformCache::Clear ( )

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

◆ Clone()

std::unique_ptr< WaveClipListener > WaveClipWaveformCache::Clone ( ) const
override

Definition at line 282 of file WaveformCache.cpp.

283{
284 // Don't need to copy contents
285 return std::make_unique<WaveClipWaveformCache>(mWaveCaches.size());
286}

References mWaveCaches.

◆ Erase()

void WaveClipWaveformCache::Erase ( size_t  index)
overridevirtual

Erase attachment at a given index, if it existed, moving later-indexed attachments to earlier indices

Default implementation does nothing

Reimplemented from WaveClipListener.

Definition at line 324 of file WaveformCache.cpp.

325{
326 if (index < mWaveCaches.size())
327 mWaveCaches.erase(mWaveCaches.begin() + index);
328}

References mWaveCaches.

◆ Get()

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

Definition at line 293 of file WaveformCache.cpp.

294{
295 return const_cast<WaveClip&>(clip.GetClip()) // Consider it mutable data
296 .Attachments::Get< WaveClipWaveformCache >( sKeyW );
297}
static WaveClip::Attachments::RegisteredFactory sKeyW
WaveClip & GetClip()
Definition: WaveClip.h:96
This allows multiple clips to be a part of one WaveTrack.
Definition: WaveClip.h:238

References WaveClipChannel::GetClip(), and sKeyW.

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

Here is the call graph for this function:
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;
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 reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:58
sampleCount GetNumSamples() const
Definition: Sequence.h:87
size_t GetChannelIndex() const
Definition: WaveClip.h:99
constSamplePtr GetAppendBuffer() const
Definition: WaveClip.cpp:135
int GetRate() const override
Definition: WaveClip.cpp:193
double GetTrimLeft() const
Definition: WaveClip.cpp:110
const Sequence & GetSequence() const
Definition: WaveClip.cpp:127
double GetStretchRatio() const override
Definition: WaveClip.cpp:218
size_t GetAppendBufferLen() const
Definition: WaveClip.cpp:140
float * rms
Definition: WaveformCache.h:26
sampleCount * where
Definition: WaveformCache.h:25
std::vector< sampleCount > ownWhere
Definition: WaveformCache.h:28
float * min
Definition: WaveformCache.h:26
float * max
Definition: WaveformCache.h:26
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:19
AUDACITY_DLL_API void fillWhere(std::vector< sampleCount > &where, size_t len, bool addBias, double correction, double t0, double sampleRate, double stretchRatio, double samplesPerPixel)
AUDACITY_DLL_API 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)
__finl float_x4 __vecc sqrt(const float_x4 &a)
bool GetWaveDisplay(const WaveChannelInterval &clip, WaveDisplay &display, double t0, double pixelsPerSecond)

References WaveClipUIUtilities::fillWhere(), WaveClipUIUtilities::findCorrection(), floatSample, WaveClipChannel::GetAppendBuffer(), WaveClipChannel::GetAppendBufferLen(), WaveClipChannel::GetChannelIndex(), Sequence::GetNumSamples(), WaveClipChannel::GetRate(), WaveClipChannel::GetSequence(), WaveClipChannel::GetStretchRatio(), WaveClipChannel::GetTrimLeft(), GetWaveDisplay(), WaveDisplay::max, mDirty, min(), WaveDisplay::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 304 of file WaveformCache.cpp.

305{
306 // Invalidate wave display caches
307 for (auto &pCache : mWaveCaches)
308 pCache = std::make_unique<WaveCache>();
309}

References mWaveCaches.

◆ MakeStereo()

void WaveClipWaveformCache::MakeStereo ( WaveClipListener &&  other,
bool  aligned 
)
overridevirtual

Append the other's attachments to this, assuming concrete subclasses are the same

Default implementation does nothing

Parameters
alignedwhether the strong invariant condition on the clip may be assumed
Precondition
typeid(*this) == typeid(other)

Reimplemented from WaveClipListener.

Definition at line 311 of file WaveformCache.cpp.

312{
313 auto pOther = dynamic_cast<WaveClipWaveformCache *>(&other);
314 assert(pOther); // precondition
315 mWaveCaches.push_back(move(pOther->mWaveCaches[0]));
316}

References mWaveCaches.

◆ MarkChanged()

void WaveClipWaveformCache::MarkChanged ( )
overridevirtualnoexcept

Implements WaveClipListener.

Definition at line 299 of file WaveformCache.cpp.

300{
301 ++mDirty;
302}

References mDirty.

◆ SwapChannels()

void WaveClipWaveformCache::SwapChannels ( )
overridevirtual

Default implementation does nothing.

Reimplemented from WaveClipListener.

Definition at line 318 of file WaveformCache.cpp.

319{
320 mWaveCaches.resize(2);
322}
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
Definition: NoteTrack.cpp:628

References mWaveCaches, and anonymous_namespace{NoteTrack.cpp}::swap().

Here is the call graph for this function:

Member Data Documentation

◆ mDirty

int WaveClipWaveformCache::mDirty { 0 }

Definition at line 70 of file WaveformCache.h.

Referenced by GetWaveDisplay(), and MarkChanged().

◆ mWaveCaches

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

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