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
|
/**********************************************************************
Audacity: A Digital Audio Editor
@file AudioGraphBuffers.h
@brief Buffers that mediate data transfer between a Source and a Sink
Paul Licameli split from PerTrackEffect.h
**********************************************************************/
#ifndef __AUDACITY_AUDIO_GRAPH_BUFFERS__
#define __AUDACITY_AUDIO_GRAPH_BUFFERS__
#include "SampleFormat.h"
#include <vector>
namespace AudioGraph {
//! Accumulates (non-interleaved) data during effect processing
/*!
@invariant `BlockSize() > 0`
@invariant `BufferSize() > 0`
@invariant `BufferSize() % BlockSize() == 0`
@invariant `mBuffers.size() == mPositions.size()`
@invariant all `mBuffers[i].size()` are equal to `BufferSize()`
@invariant all `(mPositions[i] - mBuffers[i].data())` are equal and in
range [`0`, `BufferSize()`]
*/
class AUDIO_GRAPH_API Buffers {
public:
/*!
@pre `blockSize > 0`
@post `BlockSize() == blockSize`
@post `BufferSize() == blockSize`
@post `IsRewound()`
*/
explicit Buffers(size_t blockSize = 512);
/*!
@param padding extra allocation can work around a soxr library bug
@pre `blockSize > 0`
@pre `nBlocks > 0`
@post `Channels() == nChannels`
@post `BlockSize() == blockSize`
@post `BufferSize() == blockSize * nBlocks`
*/
Buffers(unsigned nChannels, size_t blockSize, size_t nBlocks,
size_t padding = 0);
unsigned Channels() const { return mBuffers.size(); }
size_t BufferSize() const { return mBufferSize; }
size_t BlockSize() const { return mBlockSize; }
size_t Position() const {
return mBuffers.empty() ? 0
: Positions()[0]
- reinterpret_cast<const float*>(GetReadPosition(0));
}
size_t Remaining() const { return BufferSize() - Position(); }
bool IsRewound() const { return BufferSize() == Remaining(); }
/*!
@param padding extra allocation can work around a soxr library bug
@pre `blockSize > 0`
@pre `nBlocks > 0`
@post `Channels() == nChannels`
@post `BlockSize() == blockSize`
@post `BufferSize() == blockSize * nBlocks`
*/
void Reinit(unsigned nChannels, size_t blockSize, size_t nBlocks,
size_t padding = 0);
//! Get array of positions in the buffers
float *const *Positions() const { return mPositions.data(); }
//! Discard some data at the (unchanging) positions
/*!
@param drop how many values to discard
@param keep how many following values are defined
@pre drop + keep <= Remaining()
@post `Remaining()` is unchanged
*/
void Discard(size_t drop, size_t keep);
//! Move the positions
/*!
@pre count <= Remaining()
@post `Remaining()` reduced by `count`
*/
void Advance(size_t count);
//! Reset positions to starts of buffers
/*!
@post `IsRewound()`
*/
void Rewind();
//! Shift all data at and after the old position to position 0
/*!
@return how many positions were shifted; other contents are unspecified
@post `IsRewound()`
*/
size_t Rotate();
//! Get accumulated data for one channel
/*!
Last channel is replicated for all greater indices
@pre `Channels() > 0`
@pre `BufferSize() > 0`
@post result: `result != nullptr`
*/
constSamplePtr GetReadPosition(unsigned iChannel) const;
//! Get writable position for one channel
/*!
@pre `iChannel < Channels()`
@pre `BufferSize() > 0`
*/
float &GetWritePosition(unsigned iChannel);
//! Zero-fill n places in one of the buffers,
//! starting from its position
void ClearBuffer(unsigned iChannel, size_t n);
private:
std::vector<std::vector<float>> mBuffers;
std::vector<float *> mPositions;
size_t mBufferSize{ 0 };
size_t mBlockSize{ 0 };
};
}
#endif
|