Hi friends,
I’ve figured out how to guard against hosts sending too big of blocksizes – just break the I/O buffer up into smaller chunks & call your wrapped processing function for each chunk in sequence.
But the next thing I want to learn to program defensively against is hosts sending blocksizes that are too small…
Here’s what I’ve got so far. This function is nested inside an outer one that checks for buffers too big, so I know that buffers fed into this function will never exceed my declared internalBlocksize
. My goal with this function is to ensure that my renderBlock()
method is only ever called with block sizes exactly equal to my internalBlocksize
.
Does this seem like a good approach? Or am I doing something wrong here?
Where numStoredInputSamples & numStoredOutputSamples are integer members initialized to zero; inputCollectionBuffer, outputCollectionBuffer, inputTransferBuffer & outputInterimBuffer are AudioBuffer members with a size of internalBlocksize * 2
samples:
template<typename SampleType>
void ImogenEngine<SampleType>::processWrapped (AudioBuffer<SampleType>& input, AudioBuffer<SampleType>& output)
{
const int numNewSamples = input.getNumSamples();
jassert (numNewSamples <= internalBlocksize);
const int totalNumInputSamplesAvailable = numStoredInputSamples + numNewSamples;
if (totalNumInputSamplesAvailable < internalBlocksize)
{
inputCollectionBuffer.copyFrom (0, numStoredInputSamples, input, 0, 0, numNewSamples);
numStoredInputSamples = totalNumInputSamplesAvailable;
if (numStoredOutputSamples < numNewSamples)
{
output.clear();
return;
}
for (int chan = 0; chan < 2; ++chan)
output.copyFrom (chan, 0, outputCollectionBuffer, chan, 0, numNewSamples);
usedOutputSamples (numNewSamples);
return;
}
AudioBuffer<SampleType> thisChunksOutput (outputCollectionBuffer.getArrayOfWritePointers(), 2, numStoredOutputSamples, internalBlocksize);
if (numStoredInputSamples == 0)
{
renderBlock (input, thisChunksOutput);
for (int chan = 0; chan < 2; ++chan)
output.copyFrom (chan, 0, outputCollectionBuffer, chan, 0, numNewSamples);
usedOutputSamples (numNewSamples);
return;
}
inputCollectionBuffer.copyFrom (0, numStoredInputSamples, input, 0, 0, numNewSamples);
AudioBuffer<SampleType> inputCollectionBufferProxy (inputCollectionBuffer.getArrayOfWritePointers(), 1, 0, internalBlocksize);
renderBlock (inputCollectionBufferProxy, thisChunksOutput);
for (int chan = 0; chan < 2; ++chan)
output.copyFrom (chan, 0, outputCollectionBuffer, chan, 0, numNewSamples);
usedOutputSamples (numNewSamples);
numStoredInputSamples = totalNumInputSamplesAvailable - internalBlocksize;
if (numStoredInputSamples == 0)
return;
inputTransferBuffer .copyFrom (0, 0, inputCollectionBuffer, 0, internalBlocksize, numStoredInputSamples);
inputCollectionBuffer.copyFrom (0, 0, inputTransferBuffer, 0, 0, numStoredInputSamples);
};
and here is the usedOutputSamples() function:
template<typename SampleType>
void ImogenEngine<SampleType>::usedOutputSamples (const int numSamples)
{
numStoredOutputSamples -= numSamples;
if (numStoredOutputSamples > 0)
{
for (int chan = 0; chan < 2; ++chan)
{
outputInterimBuffer .copyFrom (chan, 0, outputCollectionBuffer, chan, numSamples, numStoredOutputSamples);
outputCollectionBuffer.copyFrom (chan, 0, outputInterimBuffer, chan, 0, numStoredOutputSamples);
}
}
else
numStoredOutputSamples = 0;
};
and I should mention that the last line of my renderBlock() function is this:
numStoredOutputSamples += internalBlocksize;
There’s probably a more elegant way to do this that hasn’t occurred to me yet… ¯_(ツ)_/¯