22 double sampleRate, std::optional<sampleCount> genLength,
int channel,
25 std::vector<std::shared_ptr<EffectInstance>> instances;
28 const auto nChannels = (channel < 0) ? nInputChannels : 1;
29 for (
size_t ii = 0; ii < nChannels;)
34 throw std::exception{};
35 auto count = pInstance->GetAudioInCount();
40 throw std::exception{};
47 instances.push_back(move(pInstance));
52 throw std::exception();
60 CreateToken,
int channel,
int nInputChannels, Source& upstream,
62 double sampleRate, std::optional<sampleCount> genLength)
63 : mUpstream { upstream }
64 , mInBuffers { inBuffers }
69 , mIsProcessor { !genLength.has_value() }
70 , mDelayRemaining { genLength ? *genLength :
sampleCount::max() }
72 assert(upstream.AcceptsBlockSize(inBuffers.
BlockSize()));
80 int channel,
int nInputChannels, Source& upstream,
Buffers& inBuffers,
82 std::optional<sampleCount> genLength) -> std::unique_ptr<EffectStage>
85 return std::make_unique<EffectStage>(
89 catch (
const std::exception &) {
99 pInstance->ProcessFinalize();
137 size_t curBlockSize = 0;
144 curBlockSize = *oCurBlockSize;
152 for (
size_t ii = 1, nn =
mInstances.size(); ii < nn; ++ii)
158 while (delay > 0 && curBlockSize > 0) {
160 data.
Discard(discard, curBlockSize - discard);
162 curBlockSize -= discard;
163 if (curBlockSize == 0) {
168 curBlockSize = *oCurBlockSize;
172 if (curBlockSize > 0) {
174 if (curBlockSize < bound) {
178 data, bound - curBlockSize,
false, curBlockSize)
182 curBlockSize += *oCurBlockSize;
185 else while (delay > 0) {
186 assert(curBlockSize == 0);
218 assert(result <= bound);
221 assert(bound == 0 ||
Remaining() == 0 || result > 0);
226 Buffers &data,
size_t bound,
bool doZeroes,
size_t outBufferOffset)
228 std::optional<size_t> oCurBlockSize;
241 std::fill(p, p + blockSize, 0);
254 const auto curBlockSize = *oCurBlockSize;
255 if (curBlockSize == 0)
256 assert(doZeroes ||
mUpstream.Remaining() == 0);
264 for (
size_t ii = 0, nn =
mInstances.size(); ii < nn; ++ii) {
268 if (!
Process(*pInstance, ii, data, curBlockSize, outBufferOffset))
292 return oCurBlockSize;
296 size_t channel,
const Buffers &data,
size_t curBlockSize,
297 size_t outBufferOffset)
const
305 assert(channel <= nPositions);
306 std::vector<float *> inPositions(
307 positions + channel, positions + nPositions - channel);
313 std::vector<float *> advancedOutPositions;
315 advancedOutPositions.reserve(
size);
322 for (
size_t ii = channel; ii < channels; ++ii)
323 advancedOutPositions.push_back(outPositions[ii] + outBufferOffset);
326 advancedOutPositions.resize(
size, advancedOutPositions.back());
329 inPositions.data(), advancedOutPositions.data(), curBlockSize);
344 return (processed == curBlockSize);
372 assert(channel <
static_cast<int>(nChannels));
Declare abstract class AudacityException, some often-used subclasses, and GuardedCall.
unsigned MakeChannelMap(int nChannels, int channel, ChannelName map[3])
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
static Settings & settings()
Base class for exceptions specially processed by the application.
Accumulates (non-interleaved) data during effect processing.
float & GetWritePosition(unsigned iChannel)
Get writable position for one channel.
void Advance(size_t count)
Move the positions.
void Rewind()
Reset positions to starts of buffers.
size_t Rotate()
Shift all data at and after the old position to position 0.
unsigned Channels() const
void Discard(size_t drop, size_t keep)
Discard some data at the (unchanging) positions.
float *const * Positions() const
Get array of positions in the buffers.
Performs effect computation.
virtual unsigned GetAudioInCount() const =0
How many input buffers to allocate at once.
virtual size_t ProcessBlock(EffectSettings &settings, const float *const *inBlock, float *const *outBlock, size_t blockLen)=0
Called for destructive effect computation.
virtual unsigned GetAudioOutCount() const =0
How many output buffers to allocate at once.
bool AcceptsBlockSize(size_t size) const override
See postcondition of constructor.
const std::vector< std::shared_ptr< EffectInstance > > mInstances
bool Release() override
Caller is done examining last Acquire()d positions.
std::optional< size_t > Acquire(Buffers &data, size_t bound) override
Occupy vacant space in Buffers with some data.
static std::unique_ptr< EffectStage > Create(int channel, int nInputChannels, Source &upstream, Buffers &inBuffers, const Factory &factory, EffectSettings &settings, double sampleRate, std::optional< sampleCount > genLength)
Satisfies postcondition of constructor or returns null.
sampleCount mDelayRemaining
std::optional< size_t > FetchProcessAndAdvance(Buffers &data, size_t bound, bool doZeros, size_t outBufferOffset=0)
~EffectStage() override
Finalizes the instance.
sampleCount Remaining() const override
Result includes any amount Acquired and not yet Released.
EffectStage(CreateToken, int channel, int nInputChannels, Source &upstream, Buffers &inBuffers, const Factory &factory, EffectSettings &settings, double sampleRate, std::optional< sampleCount > genLength)
Don't call directly but use Create()
bool AcceptsBuffers(const Buffers &buffers) const override
bool Process(EffectInstance &instance, size_t channel, const Buffers &data, size_t curBlockSize, size_t outBufferOffset) const
Produce exactly curBlockSize samples in data
std::function< std::shared_ptr< EffectInstance >()> Factory
sampleCount DelayRemaining() const
EffectSettings & mSettings
Positions or offsets within audio files need a wide type.
constexpr auto sampleRate
std::vector< std::shared_ptr< EffectInstance > > MakeInstances(const EffectStage::Factory &factory, EffectSettings &settings, double sampleRate, std::optional< sampleCount > genLength, int channel, int nInputChannels)
Externalized state of a plug-in.