forked from Sneeds-Feed-and-Seed/sneedacity
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSequence.h
285 lines (210 loc) · 8.33 KB
/
Sequence.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
/**********************************************************************
Sneedacity: A Digital Audio Editor
Sequence.h
Dominic Mazzoni
**********************************************************************/
#ifndef __SNEEDACITY_SEQUENCE__
#define __SNEEDACITY_SEQUENCE__
#include <vector>
#include <functional>
#include "SampleFormat.h"
#include "xml/XMLTagHandler.h"
#include "Identifier.h"
class SampleBlock;
class SampleBlockFactory;
using SampleBlockFactoryPtr = std::shared_ptr<SampleBlockFactory>;
// This is an internal data structure! For advanced use only.
class SeqBlock {
public:
using SampleBlockPtr = std::shared_ptr<SampleBlock>;
SampleBlockPtr sb;
///the sample in the global wavetrack that this block starts at.
sampleCount start;
SeqBlock()
: sb{}, start(0)
{}
SeqBlock(const SampleBlockPtr &sb_, sampleCount start_)
: sb(sb_), start(start_)
{}
// Construct a SeqBlock with changed start, same file
SeqBlock Plus(sampleCount delta) const
{
return SeqBlock(sb, start + delta);
}
};
class BlockArray : public std::vector<SeqBlock> {};
using BlockPtrArray = std::vector<SeqBlock*>; // non-owning pointers
// Put extra symbol information in the release build, for the purpose of gathering
// profiling information (as from Windows Process Monitor), when there otherwise
// isn't a need for SNEEDACITY_DLL_API.
#ifdef IS_ALPHA
#define PROFILE_DLL_API SNEEDACITY_DLL_API
#else
#define PROFILE_DLL_API
#endif
class PROFILE_DLL_API Sequence final : public XMLTagHandler{
public:
//
// Static methods
//
static void SetMaxDiskBlockSize(size_t bytes);
static size_t GetMaxDiskBlockSize();
//
// Constructor / Destructor / Duplicator
//
Sequence(const SampleBlockFactoryPtr &pFactory, sampleFormat format);
Sequence(const Sequence &orig, const SampleBlockFactoryPtr &pFactory);
Sequence( const Sequence& ) = delete;
Sequence& operator= (const Sequence&) PROHIBITED;
~Sequence();
//
// Editing
//
sampleCount GetNumSamples() const { return mNumSamples; }
bool Get(samplePtr buffer, sampleFormat format,
sampleCount start, size_t len, bool mayThrow) const;
// Note that len is not size_t, because nullptr may be passed for buffer, in
// which case, silence is inserted, possibly a large amount.
void SetSamples(constSamplePtr buffer, sampleFormat format,
sampleCount start, sampleCount len);
// where is input, assumed to be nondecreasing, and its size is len + 1.
// min, max, rms, bl are outputs, and their lengths are len.
// Each position in the output arrays corresponds to one column of pixels.
// The column for pixel p covers samples from
// where[p] up to (but excluding) where[p + 1].
// bl is negative wherever data are not yet available.
// Return true if successful.
bool GetWaveDisplay(float *min, float *max, float *rms, int* bl,
size_t len, const sampleCount *where) const;
// Return non-null, or else throw!
// Must pass in the correct factory for the result. If it's not the same
// as in this, then block contents must be copied.
std::unique_ptr<Sequence> Copy( const SampleBlockFactoryPtr &pFactory,
sampleCount s0, sampleCount s1) const;
void Paste(sampleCount s0, const Sequence *src);
size_t GetIdealAppendLen() const;
void Append(constSamplePtr buffer, sampleFormat format, size_t len);
//! Append data, not coalescing blocks, returning a pointer to the new block.
SeqBlock::SampleBlockPtr AppendNewBlock(
constSamplePtr buffer, sampleFormat format, size_t len);
//! Append a complete block, not coalescing
void AppendSharedBlock(const SeqBlock::SampleBlockPtr &pBlock);
void Delete(sampleCount start, sampleCount len);
void SetSilence(sampleCount s0, sampleCount len);
void InsertSilence(sampleCount s0, sampleCount len);
const SampleBlockFactoryPtr &GetFactory() { return mpFactory; }
//
// 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 */;
bool GetErrorOpening() { return mErrorOpening; }
//
// Lock all of this sequence's sample blocks, keeping them
// from being destroyed when closing.
bool CloseLock();//should be called upon project close.
// not balanced by unlocking calls.
//
// Manipulating Sample Format
//
sampleFormat GetSampleFormat() const;
// Return true iff there is a change
bool ConvertToSampleFormat(sampleFormat format,
const std::function<void(size_t)> & progressReport = {});
//
// Retrieving summary info
//
std::pair<float, float> GetMinMax(
sampleCount start, sampleCount len, bool mayThrow) const;
float GetRMS(sampleCount start, sampleCount len, bool mayThrow) const;
//
// Getting block size and alignment information
//
// This returns a possibly large or negative value
sampleCount GetBlockStart(sampleCount position) const;
// These return a nonnegative number of samples meant to size a memory buffer
size_t GetBestBlockSize(sampleCount start) const;
size_t GetMaxBlockSize() const;
size_t GetIdealBlockSize() const;
//
// This should only be used if you really, really know what
// you're doing!
//
BlockArray &GetBlockArray() { return mBlock; }
const BlockArray &GetBlockArray() const { return mBlock; }
private:
//
// Private static variables
//
static size_t sMaxDiskBlockSize;
//
// Private variables
//
SampleBlockFactoryPtr mpFactory;
BlockArray mBlock;
sampleFormat mSampleFormat;
// Not size_t! May need to be large:
sampleCount mNumSamples{ 0 };
size_t mMinSamples; // min samples per block
size_t mMaxSamples; // max samples per block
bool mErrorOpening{ false };
//
// Private methods
//
int FindBlock(sampleCount pos) const;
SeqBlock::SampleBlockPtr DoAppend(
constSamplePtr buffer, sampleFormat format, size_t len, bool coalesce);
static void AppendBlock(SampleBlockFactory *pFactory, sampleFormat format,
BlockArray &blocks,
sampleCount &numSamples,
const SeqBlock &b);
static bool Read(samplePtr buffer,
sampleFormat format,
const SeqBlock &b,
size_t blockRelativeStart,
size_t len,
bool mayThrow);
// Accumulate NEW block files onto the end of a block array.
// Does not change this sequence. The intent is to use
// CommitChangesIfConsistent later.
static void Blockify(SampleBlockFactory &factory,
size_t maxSamples,
sampleFormat format,
BlockArray &list,
sampleCount start,
constSamplePtr buffer,
size_t len);
bool Get(int b,
samplePtr buffer,
sampleFormat format,
sampleCount start,
size_t len,
bool mayThrow) const;
public:
//
// Public methods
//
// This function throws if the track is messed up
// because of inconsistent block starts & lengths
void ConsistencyCheck (const wxChar *whereStr, bool mayThrow = true) const;
// This function prints information to stdout about the blocks in the
// tracks and indicates if there are inconsistencies.
static void DebugPrintf
(const BlockArray &block, sampleCount numSamples, wxString *dest);
private:
static void ConsistencyCheck
(const BlockArray &block, size_t maxSamples, size_t from,
sampleCount numSamples, const wxChar *whereStr,
bool mayThrow = true);
// The next two are used in methods that give a strong guarantee.
// They either throw because final consistency check fails, or swap the
// changed contents into place.
void CommitChangesIfConsistent
(BlockArray &newBlock, sampleCount numSamples, const wxChar *whereStr);
void AppendBlocksIfConsistent
(BlockArray &additionalBlocks, bool replaceLast,
sampleCount numSamples, const wxChar *whereStr);
};
#endif // __SNEEDACITY_SEQUENCE__