mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-21 01:24:21 +00:00
DSP: Ensure that IRs are loaded immediately when Convolution is prepared
Previously, if `loadImpulseResponse` was called before `prepareToPlay`, the IR wasn't guaranteed to have loaded before the first call to `processSamples`. Now, we flush the queue of pending IR-load commands during `prepareToPlay`, which should ensure that the most recently-loaded IR is ready to use immediately.
This commit is contained in:
parent
c213796951
commit
cd41e31cb5
2 changed files with 88 additions and 12 deletions
|
|
@ -89,6 +89,19 @@ class ConvolutionTest : public UnitTest
|
|||
expect (! std::isnan (block.getSample ((int) channel, (int) sample)));
|
||||
}
|
||||
|
||||
void checkAllChannelsNonZero (const AudioBlock<float>& block)
|
||||
{
|
||||
for (size_t i = 0; i != block.getNumChannels(); ++i)
|
||||
{
|
||||
const auto* channel = block.getChannelPointer (i);
|
||||
|
||||
expect (std::any_of (channel, channel + block.getNumSamples(), [] (float sample)
|
||||
{
|
||||
return sample != 0.0f;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void nonAllocatingExpectWithinAbsoluteError (const T& a, const T& b, const T& error)
|
||||
{
|
||||
|
|
@ -168,16 +181,21 @@ class ConvolutionTest : public UnitTest
|
|||
}
|
||||
};
|
||||
|
||||
const auto time = Time::getMillisecondCounter();
|
||||
|
||||
// Wait 10 seconds to load the impulse response
|
||||
while (Time::getMillisecondCounter() - time < 10'000)
|
||||
// If we load an IR while the convolution is already running, we'll need to wait
|
||||
// for it to be loaded on a background thread
|
||||
if (initSequence == InitSequence::prepareThenLoad)
|
||||
{
|
||||
processBlocksWithDiracImpulse();
|
||||
const auto time = Time::getMillisecondCounter();
|
||||
|
||||
// Check if the impulse response was loaded
|
||||
if (block.getSample (0, 1) != 0.0f)
|
||||
break;
|
||||
// Wait 10 seconds to load the impulse response
|
||||
while (Time::getMillisecondCounter() - time < 10'000)
|
||||
{
|
||||
processBlocksWithDiracImpulse();
|
||||
|
||||
// Check if the impulse response was loaded
|
||||
if (block.getSample (0, 1) != 0.0f)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, our convolution should be loaded and the current IR size should
|
||||
|
|
@ -326,6 +344,45 @@ public:
|
|||
checkForNans (block);
|
||||
}
|
||||
|
||||
beginTest ("Convolutions can cope with a change in samplerate and blocksize");
|
||||
{
|
||||
Convolution convolution;
|
||||
|
||||
auto copy = impulseData;
|
||||
convolution.loadImpulseResponse (std::move (copy),
|
||||
2000,
|
||||
Convolution::Stereo::yes,
|
||||
Convolution::Trim::no,
|
||||
Convolution::Normalise::yes);
|
||||
|
||||
const dsp::ProcessSpec specs[] = { { 96'000.0, 1024, 2 },
|
||||
{ 48'000.0, 512, 2 },
|
||||
{ 44'100.0, 256, 2 } };
|
||||
|
||||
for (const auto& thisSpec : specs)
|
||||
{
|
||||
convolution.prepare (thisSpec);
|
||||
|
||||
expectWithinAbsoluteError ((double) convolution.getCurrentIRSize(),
|
||||
thisSpec.sampleRate * 0.5,
|
||||
1.0);
|
||||
|
||||
juce::AudioBuffer<float> thisBuffer ((int) thisSpec.numChannels,
|
||||
(int) thisSpec.maximumBlockSize);
|
||||
AudioBlock<float> thisBlock { thisBuffer };
|
||||
ProcessContextReplacing<float> thisContext { thisBlock };
|
||||
|
||||
nTimes (100, [&]
|
||||
{
|
||||
addDiracImpulse (thisBlock);
|
||||
convolution.process (thisContext);
|
||||
|
||||
checkForNans (thisBlock);
|
||||
checkAllChannelsNonZero (thisBlock);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
beginTest ("Short uniform convolutions work");
|
||||
{
|
||||
const auto ramp = makeRamp (static_cast<int> (spec.maximumBlockSize) / 2);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue