mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
AudioProcessorGraph: Remove unnecessary precision conversion buffer
The double-precision buffer is unnecessary because internal nodes should be prepared using the same precision as the graph itself, and all AudioProcessors *must* support single-precision processing. Therefore, if the graph is prepared to use single-precision, then all inner nodes *must* also use single-precision. This change also shares the remaining temporary buffer.
This commit is contained in:
parent
a31cadaa18
commit
5297df9995
1 changed files with 105 additions and 13 deletions
|
|
@ -788,7 +788,11 @@ struct GraphRenderSequence
|
|||
}
|
||||
}
|
||||
|
||||
return std::make_unique<ProcessOp> (node, audioChannelsUsed, totalNumChans, midiBuffer);
|
||||
return std::make_unique<ProcessOp> (node,
|
||||
audioChannelsUsed,
|
||||
totalNumChans,
|
||||
midiBuffer,
|
||||
*precisionConversionBuffer);
|
||||
}();
|
||||
|
||||
renderOps.push_back (std::move (op));
|
||||
|
|
@ -801,6 +805,8 @@ struct GraphRenderSequence
|
|||
currentAudioOutputBuffer.setSize (numBuffersNeeded + 1, blockSize);
|
||||
currentAudioOutputBuffer.clear();
|
||||
|
||||
precisionConversionBuffer->setSize (numBuffersNeeded, blockSize);
|
||||
|
||||
currentMidiOutputBuffer.clear();
|
||||
|
||||
midiBuffers.clearQuick();
|
||||
|
|
@ -898,7 +904,14 @@ private:
|
|||
|
||||
struct ProcessOp final : public NodeOp
|
||||
{
|
||||
using NodeOp::NodeOp;
|
||||
ProcessOp (const Node::Ptr& n,
|
||||
const Array<int>& audioChannelsUsed,
|
||||
int totalNumChans,
|
||||
int midiBufferIndex,
|
||||
AudioBuffer<float>& tempBuffer)
|
||||
: NodeOp (n, audioChannelsUsed, totalNumChans, midiBufferIndex),
|
||||
temporaryBuffer (tempBuffer)
|
||||
{}
|
||||
|
||||
void processWithBuffer (const GlobalIO&, bool bypass, AudioBuffer<FloatType>& audio, MidiBuffer& midi) final
|
||||
{
|
||||
|
|
@ -909,9 +922,14 @@ private:
|
|||
{
|
||||
if (this->processor.isUsingDoublePrecision())
|
||||
{
|
||||
tempBufferDouble.makeCopyOf (buffer, true);
|
||||
processImpl (bypass, this->processor, tempBufferDouble, midi);
|
||||
buffer.makeCopyOf (tempBufferDouble, true);
|
||||
// The graph is processing in single-precision, but this node is expecting a
|
||||
// double-precision buffer. If the graph is using single-precision, it
|
||||
// should also have set its internal nodes to use single-precision
|
||||
// during prepareToPlay(). You should avoid calling setProcessingPrecision()
|
||||
// directly on processors within an AudioProcessorGraph.
|
||||
jassertfalse;
|
||||
buffer.clear();
|
||||
midi.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -927,9 +945,11 @@ private:
|
|||
}
|
||||
else
|
||||
{
|
||||
tempBufferFloat.makeCopyOf (buffer, true);
|
||||
processImpl (bypass, this->processor, tempBufferFloat, midi);
|
||||
buffer.makeCopyOf (tempBufferFloat, true);
|
||||
// This branch will be taken if the graph is configured for double-precision but
|
||||
// this node only supports single-precision.
|
||||
temporaryBuffer.makeCopyOf (buffer, true);
|
||||
processImpl (bypass, this->processor, temporaryBuffer, midi);
|
||||
buffer.makeCopyOf (temporaryBuffer, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -942,7 +962,7 @@ private:
|
|||
p.processBlock (audio, midi);
|
||||
}
|
||||
|
||||
AudioBuffer<float> tempBufferFloat, tempBufferDouble;
|
||||
AudioBuffer<float>& temporaryBuffer;
|
||||
};
|
||||
|
||||
struct MidiInOp final : public NodeOp
|
||||
|
|
@ -996,6 +1016,8 @@ private:
|
|||
};
|
||||
|
||||
std::vector<std::unique_ptr<RenderOp>> renderOps;
|
||||
|
||||
std::unique_ptr<AudioBuffer<float>> precisionConversionBuffer = std::make_unique<AudioBuffer<float>>();
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -2246,6 +2268,63 @@ public:
|
|||
expect (graph.getLatencySamples() == nodeALatency + nodeBLatency + finalLatency);
|
||||
}
|
||||
|
||||
beginTest ("nodes use double precision if supported");
|
||||
{
|
||||
AudioProcessorGraph graph;
|
||||
constexpr auto blockSize = 512;
|
||||
AudioBuffer<float> bufferFloat (2, blockSize);
|
||||
AudioBuffer<double> bufferDouble (2, blockSize);
|
||||
MidiBuffer midi;
|
||||
|
||||
auto processorOwner = BasicProcessor::make (BasicProcessor::getStereoProperties(), MidiIn::no, MidiOut::no);
|
||||
auto* processor = processorOwner.get();
|
||||
graph.addNode (std::move (processorOwner));
|
||||
|
||||
// Process in single-precision
|
||||
{
|
||||
graph.setProcessingPrecision (AudioProcessor::singlePrecision);
|
||||
graph.prepareToPlay (44100.0, blockSize);
|
||||
|
||||
graph.processBlock (bufferFloat, midi);
|
||||
expect (processor->getProcessingPrecision() == AudioProcessor::singlePrecision);
|
||||
expect (processor->getLastBlockPrecision() == AudioProcessor::singlePrecision);
|
||||
|
||||
graph.releaseResources();
|
||||
}
|
||||
|
||||
// Process in double-precision
|
||||
{
|
||||
graph.setProcessingPrecision (AudioProcessor::doublePrecision);
|
||||
graph.prepareToPlay (44100.0, blockSize);
|
||||
|
||||
graph.processBlock (bufferDouble, midi);
|
||||
expect (processor->getProcessingPrecision() == AudioProcessor::doublePrecision);
|
||||
expect (processor->getLastBlockPrecision() == AudioProcessor::doublePrecision);
|
||||
|
||||
graph.releaseResources();
|
||||
}
|
||||
|
||||
// Process in double-precision when node only supports single-precision
|
||||
{
|
||||
processor->setSupportsDoublePrecisionProcessing (false);
|
||||
|
||||
graph.setProcessingPrecision (AudioProcessor::doublePrecision);
|
||||
graph.prepareToPlay (44100.0, blockSize);
|
||||
|
||||
graph.processBlock (bufferDouble, midi);
|
||||
expect (processor->getProcessingPrecision() == AudioProcessor::singlePrecision);
|
||||
expect (processor->getLastBlockPrecision() == AudioProcessor::singlePrecision);
|
||||
|
||||
graph.releaseResources();
|
||||
}
|
||||
|
||||
// It's not possible for the node to *only* support double-precision.
|
||||
// It's also not possible to prepare the graph in single-precision mode, and then
|
||||
// to set an individual node into double-precision mode. This would require calling
|
||||
// prepareToPlay() on an individual node after preparing the graph as a whole, which is
|
||||
// not a supported usage pattern.
|
||||
}
|
||||
|
||||
beginTest ("large render sequence can be built");
|
||||
{
|
||||
AudioProcessorGraph graph;
|
||||
|
|
@ -2302,15 +2381,22 @@ private:
|
|||
void setStateInformation (const void*, int) override {}
|
||||
void prepareToPlay (double, int) override {}
|
||||
void releaseResources() override {}
|
||||
void processBlock (AudioBuffer<float>&, MidiBuffer&) override {}
|
||||
bool supportsDoublePrecisionProcessing() const override { return true; }
|
||||
bool supportsDoublePrecisionProcessing() const override { return doublePrecisionSupported; }
|
||||
bool isMidiEffect() const override { return {}; }
|
||||
void reset() override {}
|
||||
void setNonRealtime (bool) noexcept override {}
|
||||
|
||||
using AudioProcessor::processBlock;
|
||||
void processBlock (AudioBuffer<float>&, MidiBuffer&) override
|
||||
{
|
||||
blockPrecision = singlePrecision;
|
||||
}
|
||||
|
||||
static std::unique_ptr<AudioProcessor> make (const BusesProperties& layout,
|
||||
void processBlock (AudioBuffer<double>&, MidiBuffer&) override
|
||||
{
|
||||
blockPrecision = doublePrecision;
|
||||
}
|
||||
|
||||
static std::unique_ptr<BasicProcessor> make (const BusesProperties& layout,
|
||||
MidiIn midiIn,
|
||||
MidiOut midiOut)
|
||||
{
|
||||
|
|
@ -2334,9 +2420,15 @@ private:
|
|||
.withOutput ("out", AudioChannelSet::discreteChannels (numChannels));
|
||||
}
|
||||
|
||||
void setSupportsDoublePrecisionProcessing (bool x) { doublePrecisionSupported = x; }
|
||||
|
||||
ProcessingPrecision getLastBlockPrecision() const { return blockPrecision; }
|
||||
|
||||
private:
|
||||
MidiIn midiIn;
|
||||
MidiOut midiOut;
|
||||
ProcessingPrecision blockPrecision = ProcessingPrecision (-1); // initially invalid
|
||||
bool doublePrecisionSupported = true;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue