forked from Sneeds-Feed-and-Seed/sneedacity
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathWaveClip.h
382 lines (306 loc) · 12 KB
/
WaveClip.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
/**********************************************************************
Sneedacity: A Digital Audio Editor
WaveClip.h
?? Dominic Mazzoni
?? Markus Meyer
*******************************************************************/
#ifndef __SNEEDACITY_WAVECLIP__
#define __SNEEDACITY_WAVECLIP__
#include "SampleFormat.h"
#include "xml/XMLTagHandler.h"
#include <wx/longlong.h>
#include <vector>
#include <functional>
class BlockArray;
class Envelope;
class ProgressDialog;
class SampleBlock;
class SampleBlockFactory;
using SampleBlockFactoryPtr = std::shared_ptr<SampleBlockFactory>;
class Sequence;
class SpectrogramSettings;
class WaveCache;
class WaveTrackCache;
class wxFileNameWrapper;
class SNEEDACITY_DLL_API SpecCache {
public:
// Make invalid cache
SpecCache()
: algorithm(-1)
, pps(-1.0)
, start(-1.0)
, windowType(-1)
, frequencyGain(-1)
, dirty(-1)
{
}
~SpecCache()
{
}
bool Matches(int dirty_, double pixelsPerSecond,
const SpectrogramSettings &settings, double rate) const;
// Calculate one column of the spectrum
bool CalculateOneSpectrum
(const SpectrogramSettings &settings,
WaveTrackCache &waveTrackCache,
const int xx, sampleCount numSamples,
double offset, double rate, double pixelsPerSecond,
int lowerBoundX, int upperBoundX,
const std::vector<float> &gainFactors,
float* __restrict scratch,
float* __restrict out) const;
// Grow the cache while preserving the (possibly now invalid!) contents
void Grow(size_t len_, const SpectrogramSettings& settings,
double pixelsPerSecond, double start_);
// Calculate the dirty columns at the begin and end of the cache
void Populate
(const SpectrogramSettings &settings, WaveTrackCache &waveTrackCache,
int copyBegin, int copyEnd, size_t numPixels,
sampleCount numSamples,
double offset, double rate, double pixelsPerSecond);
size_t len { 0 }; // counts pixels, not samples
int algorithm;
double pps;
double start;
int windowType;
size_t windowSize { 0 };
unsigned zeroPaddingFactor { 0 };
int frequencyGain;
std::vector<float> freq;
std::vector<sampleCount> where;
int dirty;
};
class SpecPxCache {
public:
SpecPxCache(size_t cacheLen)
: len{ cacheLen }
, values{ len }
{
valid = false;
scaleType = 0;
range = gain = -1;
minFreq = maxFreq = -1;
}
size_t len;
Floats values;
bool valid;
int scaleType;
int range;
int gain;
int minFreq;
int maxFreq;
};
class WaveClip;
// Array of pointers that assume ownership
using WaveClipHolder = std::shared_ptr< WaveClip >;
using WaveClipHolders = std::vector < WaveClipHolder >;
using WaveClipConstHolders = std::vector < std::shared_ptr< const WaveClip > >;
// A bundle of arrays needed for drawing waveforms. The object may or may not
// own the storage for those arrays. If it does, it destroys them.
class WaveDisplay
{
public:
int width;
sampleCount *where;
float *min, *max, *rms;
int* bl;
std::vector<sampleCount> ownWhere;
std::vector<float> ownMin, ownMax, ownRms;
std::vector<int> ownBl;
public:
WaveDisplay(int w)
: width(w), where(0), min(0), max(0), rms(0), bl(0)
{
}
// Create "own" arrays.
void Allocate()
{
ownWhere.resize(width + 1);
ownMin.resize(width);
ownMax.resize(width);
ownRms.resize(width);
ownBl.resize(width);
where = &ownWhere[0];
if (width > 0) {
min = &ownMin[0];
max = &ownMax[0];
rms = &ownRms[0];
bl = &ownBl[0];
}
else {
min = max = rms = 0;
bl = 0;
}
}
~WaveDisplay()
{
}
};
class SNEEDACITY_DLL_API WaveClip final : public XMLTagHandler
{
private:
// It is an error to copy a WaveClip without specifying the
// sample block factory.
WaveClip(const WaveClip&) PROHIBITED;
WaveClip& operator= (const WaveClip&) PROHIBITED;
public:
// typical constructor
WaveClip(const SampleBlockFactoryPtr &factory, sampleFormat format,
int rate, int colourIndex);
// essentially a copy constructor - but you must pass in the
// current sample block factory, because we might be copying
// from one project to another
WaveClip(const WaveClip& orig,
const SampleBlockFactoryPtr &factory,
bool copyCutlines);
// Copy only a range from the given WaveClip
WaveClip(const WaveClip& orig,
const SampleBlockFactoryPtr &factory,
bool copyCutlines,
double t0, double t1);
virtual ~WaveClip();
void ConvertToSampleFormat(sampleFormat format,
const std::function<void(size_t)> & progressReport = {});
// Always gives non-negative answer, not more than sample sequence length
// even if t0 really falls outside that range
void TimeToSamplesClip(double t0, sampleCount *s0) const;
int GetRate() const { return mRate; }
// Set rate without resampling. This will change the length of the clip
void SetRate(int rate);
// Resample clip. This also will set the rate, but without changing
// the length of the clip
void Resample(int rate, ProgressDialog *progress = NULL);
void SetColourIndex( int index ){ mColourIndex = index;};
int GetColourIndex( ) const { return mColourIndex;};
void SetOffset(double offset);
double GetOffset() const { return mOffset; }
/*! @excsafety{No-fail} */
void Offset(double delta)
{ SetOffset(GetOffset() + delta); }
double GetStartTime() const;
double GetEndTime() const;
sampleCount GetStartSample() const;
sampleCount GetEndSample() const;
sampleCount GetNumSamples() const;
// One and only one of the following is true for a given t (unless the clip
// has zero length -- then BeforeClip() and AfterClip() can both be true).
// Within() is true if the time is substantially within the clip
bool WithinClip(double t) const;
bool BeforeClip(double t) const;
bool AfterClip(double t) const;
bool IsClipStartAfterClip(double t) const;
bool GetSamples(samplePtr buffer, sampleFormat format,
sampleCount start, size_t len, bool mayThrow = true) const;
void SetSamples(constSamplePtr buffer, sampleFormat format,
sampleCount start, size_t len);
Envelope* GetEnvelope() { return mEnvelope.get(); }
const Envelope* GetEnvelope() const { return mEnvelope.get(); }
BlockArray* GetSequenceBlockArray();
const BlockArray* GetSequenceBlockArray() const;
// Get low-level access to the sequence. Whenever possible, don't use this,
// but use more high-level functions inside WaveClip (or add them if you
// think they are useful for general use)
Sequence* GetSequence() { return mSequence.get(); }
const Sequence* GetSequence() const { return mSequence.get(); }
/** WaveTrack calls this whenever data in the wave clip changes. It is
* called automatically when WaveClip has a chance to know that something
* has changed, like when member functions SetSamples() etc. are called. */
/*! @excsafety{No-fail} */
void MarkChanged()
{ mDirty++; }
/** Getting high-level data for screen display and clipping
* calculations and Contrast */
bool GetWaveDisplay(WaveDisplay &display,
double t0, double pixelsPerSecond) const;
bool GetSpectrogram(WaveTrackCache &cache,
const float *& spectrogram,
const sampleCount *& where,
size_t numPixels,
double t0, double pixelsPerSecond) const;
std::pair<float, float> GetMinMax(
double t0, double t1, bool mayThrow = true) const;
float GetRMS(double t0, double t1, bool mayThrow = true) const;
/** Whenever you do an operation to the sequence that will change the number
* of samples (that is, the length of the clip), you will want to call this
* function to tell the envelope about it. */
void UpdateEnvelopeTrackLen();
//! For use in importing pre-version-3 projects to preserve sharing of blocks
std::shared_ptr<SampleBlock> AppendNewBlock(
samplePtr buffer, sampleFormat format, size_t len);
//! For use in importing pre-version-3 projects to preserve sharing of blocks
void AppendSharedBlock(const std::shared_ptr<SampleBlock> &pBlock);
/// You must call Flush after the last Append
/// @return true if at least one complete block was created
bool Append(constSamplePtr buffer, sampleFormat format,
size_t len, unsigned int stride);
/// Flush must be called after last Append
void Flush();
/// This name is consistent with WaveTrack::Clear. It performs a "Cut"
/// operation (but without putting the cut audio to the clipboard)
void Clear(double t0, double t1);
/// Clear, and add cut line that starts at t0 and contains everything until t1.
void ClearAndAddCutLine(double t0, double t1);
/// Paste data from other clip, resampling it if not equal rate
void Paste(double t0, const WaveClip* other);
/** Insert silence - note that this is an efficient operation for large
* amounts of silence */
void InsertSilence( double t, double len, double *pEnvelopeValue = nullptr );
/** Insert silence at the end, and causes the envelope to ramp
linearly to the given value */
void AppendSilence( double len, double envelopeValue );
/// Get access to cut lines list
WaveClipHolders &GetCutLines() { return mCutLines; }
const WaveClipConstHolders &GetCutLines() const
{ return reinterpret_cast< const WaveClipConstHolders& >( mCutLines ); }
size_t NumCutLines() const { return mCutLines.size(); }
/** Find cut line at (approximately) this position. Returns true and fills
* in cutLineStart and cutLineEnd (if specified) if a cut line at this
* position could be found. Return false otherwise. */
bool FindCutLine(double cutLinePosition,
double* cutLineStart = NULL,
double *cutLineEnd = NULL) const;
/** Expand cut line (that is, re-insert audio, then DELETE audio saved in
* cut line). Returns true if a cut line could be found and successfully
* expanded, false otherwise */
void ExpandCutLine(double cutLinePosition);
/// Remove cut line, without expanding the audio in it
bool RemoveCutLine(double cutLinePosition);
/// Offset cutlines right to time 't0' by time amount 'len'
void OffsetCutLines(double t0, double len);
void CloseLock(); //should be called when the project closes.
// not balanced by unlocking calls.
///Delete the wave cache - force redraw. Thread-safe
void ClearWaveCache();
//
// XMLTagHandler callback methods for loading and saving
//
bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) override;
void HandleXMLEndTag(const wxChar *tag) override;
XMLTagHandler *HandleXMLChild(const wxChar *tag) override;
void WriteXML(XMLWriter &xmlFile) const /* not override */;
// AWD, Oct 2009: for pasting whitespace at the end of selection
bool GetIsPlaceholder() const { return mIsPlaceholder; }
void SetIsPlaceholder(bool val) { mIsPlaceholder = val; }
// used by commands which interact with clips using the keyboard
bool SharesBoundaryWithNextClip(const WaveClip* next) const;
public:
// Cache of values to colour pixels of Spectrogram - used by TrackArtist
mutable std::unique_ptr<SpecPxCache> mSpecPxCache;
protected:
double mOffset { 0 };
int mRate;
int mDirty { 0 };
int mColourIndex;
std::unique_ptr<Sequence> mSequence;
std::unique_ptr<Envelope> mEnvelope;
mutable std::unique_ptr<WaveCache> mWaveCache;
mutable std::unique_ptr<SpecCache> mSpecCache;
SampleBuffer mAppendBuffer {};
size_t mAppendBufferLen { 0 };
// Cut Lines are nothing more than ordinary wave clips, with the
// offset relative to the start of the clip.
WaveClipHolders mCutLines {};
// AWD, Oct. 2009: for whitespace-at-end-of-selection pasting
bool mIsPlaceholder { false };
};
#endif