Browse Source

Convolution: Added a flag to disable normalisation of loaded impulse responses and fixed a potential crash

tags/2021-05-28
hogliux 7 years ago
parent
commit
7c6d25681e
2 changed files with 64 additions and 27 deletions
  1. +55
    -24
      modules/juce_dsp/frequency/juce_Convolution.cpp
  2. +9
    -3
      modules/juce_dsp/frequency/juce_Convolution.h

+ 55
- 24
modules/juce_dsp/frequency/juce_Convolution.cpp View File

@@ -57,9 +57,10 @@ struct ConvolutionEngine
AudioBuffer<float>* buffer; AudioBuffer<float>* buffer;
double sampleRate = 0; double sampleRate = 0;
bool wantsStereo;
bool wantsTrimming;
size_t impulseResponseSize;
bool wantsStereo = true;
bool wantsTrimming = true;
bool wantsNormalization = true;
size_t impulseResponseSize = 0;
size_t maximumBufferSize = 0; size_t maximumBufferSize = 0;
}; };
@@ -85,7 +86,7 @@ struct ConvolutionEngine
FFTSize = blockSize > 128 ? 2 * blockSize FFTSize = blockSize > 128 ? 2 * blockSize
: 4 * blockSize; : 4 * blockSize;
numSegments = ((size_t) info.buffer->getNumSamples()) / (FFTSize - blockSize) + 1;
numSegments = ((size_t) info.buffer->getNumSamples()) / (FFTSize - blockSize) + 1u;
numInputSegments = (blockSize > 128 ? numSegments : 3 * numSegments); numInputSegments = (blockSize > 128 ? numSegments : 3 * numSegments);
@@ -341,6 +342,7 @@ public:
changeImpulseResponseSize, changeImpulseResponseSize,
changeStereo, changeStereo,
changeTrimming, changeTrimming,
changeNormalization,
numChangeRequestTypes numChangeRequestTypes
}; };
@@ -599,12 +601,23 @@ public:
bool newWantsTrimming = requestParameters[n]; bool newWantsTrimming = requestParameters[n];
if (currentInfo.wantsTrimming != newWantsTrimming) if (currentInfo.wantsTrimming != newWantsTrimming)
changeLevel = jmax(1, changeLevel);
changeLevel = jmax (1, changeLevel);
currentInfo.wantsTrimming = newWantsTrimming; currentInfo.wantsTrimming = newWantsTrimming;
} }
break; break;
case ChangeRequest::changeNormalization:
{
bool newWantsNormalization = requestParameters[n];
if (currentInfo.wantsNormalization != newWantsNormalization)
changeLevel = jmax (1, changeLevel);
currentInfo.wantsNormalization = newWantsNormalization;
}
break;
default: default:
jassertfalse; jassertfalse;
break; break;
@@ -767,15 +780,19 @@ private:
if (isThreadRunning() && threadShouldExit()) if (isThreadRunning() && threadShouldExit())
return; return;
if (currentInfo.wantsStereo)
if (currentInfo.wantsNormalization)
{ {
normalizeImpulseResponse (currentInfo.buffer->getWritePointer(0), currentInfo.buffer->getNumSamples(), 1.0);
normalizeImpulseResponse (currentInfo.buffer->getWritePointer(1), currentInfo.buffer->getNumSamples(), 1.0);
}
else
{
normalizeImpulseResponse (currentInfo.buffer->getWritePointer (0), currentInfo.buffer->getNumSamples(), 1.0);
if (currentInfo.wantsStereo)
{
normalizeImpulseResponse (currentInfo.buffer->getWritePointer(0), currentInfo.buffer->getNumSamples(), 1.0);
normalizeImpulseResponse (currentInfo.buffer->getWritePointer(1), currentInfo.buffer->getNumSamples(), 1.0);
}
else
{
normalizeImpulseResponse (currentInfo.buffer->getWritePointer (0), currentInfo.buffer->getNumSamples(), 1.0);
}
} }
} }
/** Converts the data from an audio file into a stereo audio buffer of floats, and /** Converts the data from an audio file into a stereo audio buffer of floats, and
@@ -996,7 +1013,9 @@ Convolution::~Convolution()
{ {
} }
void Convolution::loadImpulseResponse (const void* sourceData, size_t sourceDataSize, bool wantsStereo, bool wantsTrimming, size_t size)
void Convolution::loadImpulseResponse (const void* sourceData, size_t sourceDataSize,
bool wantsStereo, bool wantsTrimming, size_t size,
bool wantsNormalization)
{ {
if (sourceData == nullptr) if (sourceData == nullptr)
return; return;
@@ -1004,7 +1023,8 @@ void Convolution::loadImpulseResponse (const void* sourceData, size_t sourceData
Pimpl::ChangeRequest types[] = { Pimpl::ChangeRequest::changeSource, Pimpl::ChangeRequest types[] = { Pimpl::ChangeRequest::changeSource,
Pimpl::ChangeRequest::changeImpulseResponseSize, Pimpl::ChangeRequest::changeImpulseResponseSize,
Pimpl::ChangeRequest::changeStereo, Pimpl::ChangeRequest::changeStereo,
Pimpl::ChangeRequest::changeTrimming };
Pimpl::ChangeRequest::changeTrimming,
Pimpl::ChangeRequest::changeNormalization };
Array<juce::var> sourceParameter; Array<juce::var> sourceParameter;
@@ -1014,12 +1034,14 @@ void Convolution::loadImpulseResponse (const void* sourceData, size_t sourceData
juce::var parameters[] = { juce::var (sourceParameter), juce::var parameters[] = { juce::var (sourceParameter),
juce::var (static_cast<int64> (size)), juce::var (static_cast<int64> (size)),
juce::var (wantsStereo), juce::var (wantsStereo),
juce::var (wantsTrimming) };
juce::var (wantsTrimming),
juce::var (wantsNormalization) };
pimpl->addToFifo (types, parameters, 3);
pimpl->addToFifo (types, parameters, 5);
} }
void Convolution::loadImpulseResponse (const File& fileImpulseResponse, bool wantsStereo, bool wantsTrimming, size_t size)
void Convolution::loadImpulseResponse (const File& fileImpulseResponse, bool wantsStereo,
bool wantsTrimming, size_t size, bool wantsNormalization)
{ {
if (! fileImpulseResponse.existsAsFile()) if (! fileImpulseResponse.existsAsFile())
return; return;
@@ -1027,7 +1049,8 @@ void Convolution::loadImpulseResponse (const File& fileImpulseResponse, bool wan
Pimpl::ChangeRequest types[] = { Pimpl::ChangeRequest::changeSource, Pimpl::ChangeRequest types[] = { Pimpl::ChangeRequest::changeSource,
Pimpl::ChangeRequest::changeImpulseResponseSize, Pimpl::ChangeRequest::changeImpulseResponseSize,
Pimpl::ChangeRequest::changeStereo, Pimpl::ChangeRequest::changeStereo,
Pimpl::ChangeRequest::changeTrimming };
Pimpl::ChangeRequest::changeTrimming,
Pimpl::ChangeRequest::changeNormalization };
Array<juce::var> sourceParameter; Array<juce::var> sourceParameter;
@@ -1037,13 +1060,14 @@ void Convolution::loadImpulseResponse (const File& fileImpulseResponse, bool wan
juce::var parameters[] = { juce::var (sourceParameter), juce::var parameters[] = { juce::var (sourceParameter),
juce::var (static_cast<int64> (size)), juce::var (static_cast<int64> (size)),
juce::var (wantsStereo), juce::var (wantsStereo),
juce::var (wantsTrimming) };
juce::var (wantsTrimming),
juce::var (wantsNormalization) };
pimpl->addToFifo (types, parameters, 3);
pimpl->addToFifo (types, parameters, 5);
} }
void Convolution::copyAndLoadImpulseResponseFromBuffer (const AudioBuffer<float>& buffer, void Convolution::copyAndLoadImpulseResponseFromBuffer (const AudioBuffer<float>& buffer,
double bufferSampleRate, bool wantsStereo, bool wantsTrimming, size_t size)
double bufferSampleRate, bool wantsStereo, bool wantsTrimming, bool wantsNormalization, size_t size)
{ {
jassert (bufferSampleRate > 0); jassert (bufferSampleRate > 0);
@@ -1055,7 +1079,8 @@ void Convolution::copyAndLoadImpulseResponseFromBuffer (const AudioBuffer<float>
Pimpl::ChangeRequest types[] = { Pimpl::ChangeRequest::changeSource, Pimpl::ChangeRequest types[] = { Pimpl::ChangeRequest::changeSource,
Pimpl::ChangeRequest::changeImpulseResponseSize, Pimpl::ChangeRequest::changeImpulseResponseSize,
Pimpl::ChangeRequest::changeStereo, Pimpl::ChangeRequest::changeStereo,
Pimpl::ChangeRequest::changeTrimming };
Pimpl::ChangeRequest::changeTrimming,
Pimpl::ChangeRequest::changeNormalization };
Array<juce::var> sourceParameter; Array<juce::var> sourceParameter;
sourceParameter.add (juce::var ((int) ConvolutionEngine::ProcessingInformation::SourceType::sourceAudioBuffer)); sourceParameter.add (juce::var ((int) ConvolutionEngine::ProcessingInformation::SourceType::sourceAudioBuffer));
@@ -1064,9 +1089,10 @@ void Convolution::copyAndLoadImpulseResponseFromBuffer (const AudioBuffer<float>
juce::var parameters[] = { juce::var (sourceParameter), juce::var parameters[] = { juce::var (sourceParameter),
juce::var (static_cast<int64> (size)), juce::var (static_cast<int64> (size)),
juce::var (wantsStereo), juce::var (wantsStereo),
juce::var (wantsTrimming) };
juce::var (wantsTrimming),
juce::var (wantsNormalization) };
pimpl->addToFifo (types, parameters, 3);
pimpl->addToFifo (types, parameters, 5);
} }
void Convolution::prepare (const ProcessSpec& spec) void Convolution::prepare (const ProcessSpec& spec)
@@ -1091,6 +1117,8 @@ void Convolution::prepare (const ProcessSpec& spec)
dryBuffer = AudioBlock<float> (dryBufferStorage, dryBuffer = AudioBlock<float> (dryBufferStorage,
jmin (spec.numChannels, 2u), jmin (spec.numChannels, 2u),
spec.maximumBlockSize); spec.maximumBlockSize);
isActive = true;
} }
void Convolution::reset() noexcept void Convolution::reset() noexcept
@@ -1101,6 +1129,9 @@ void Convolution::reset() noexcept
void Convolution::processSamples (const AudioBlock<float>& input, AudioBlock<float>& output, bool isBypassed) noexcept void Convolution::processSamples (const AudioBlock<float>& input, AudioBlock<float>& output, bool isBypassed) noexcept
{ {
if (! isActive)
return;
jassert (input.getNumChannels() == output.getNumChannels()); jassert (input.getNumChannels() == output.getNumChannels());
jassert (isPositiveAndBelow (input.getNumChannels(), static_cast<size_t> (3))); // only mono and stereo is supported jassert (isPositiveAndBelow (input.getNumChannels(), static_cast<size_t> (3))); // only mono and stereo is supported


+ 9
- 3
modules/juce_dsp/frequency/juce_Convolution.h View File

@@ -93,9 +93,11 @@ public:
@param wantsStereo requests to load both stereo channels or only one mono channel @param wantsStereo requests to load both stereo channels or only one mono channel
@param wantsTrimming requests to trim the start and the end of the impulse response @param wantsTrimming requests to trim the start and the end of the impulse response
@param size the expected size for the impulse response after loading @param size the expected size for the impulse response after loading
@param wantsNormalization requests to normalize the impulse response amplitude
*/ */
void loadImpulseResponse (const void* sourceData, size_t sourceDataSize, void loadImpulseResponse (const void* sourceData, size_t sourceDataSize,
bool wantsStereo, bool wantsTrimming, size_t size);
bool wantsStereo, bool wantsTrimming, size_t size,
bool wantsNormalization = true);
/** This function loads an impulse response from an audio file on any drive. It /** This function loads an impulse response from an audio file on any drive. It
can load any of the audio formats registered in JUCE, and performs some can load any of the audio formats registered in JUCE, and performs some
@@ -105,9 +107,11 @@ public:
@param wantsStereo requests to load both stereo channels or only one mono channel @param wantsStereo requests to load both stereo channels or only one mono channel
@param wantsTrimming requests to trim the start and the end of the impulse response @param wantsTrimming requests to trim the start and the end of the impulse response
@param size the expected size for the impulse response after loading @param size the expected size for the impulse response after loading
@param wantsNormalization requests to normalize the impulse response amplitude
*/ */
void loadImpulseResponse (const File& fileImpulseResponse, void loadImpulseResponse (const File& fileImpulseResponse,
bool wantsStereo, bool wantsTrimming, size_t size);
bool wantsStereo, bool wantsTrimming, size_t size,
bool wantsNormalization = true);
/** This function loads an impulse response from an audio buffer, which is /** This function loads an impulse response from an audio buffer, which is
copied before doing anything else. Performs some resampling and copied before doing anything else. Performs some resampling and
@@ -117,10 +121,11 @@ public:
@param bufferSampleRate the sampleRate of the data in the AudioBuffer @param bufferSampleRate the sampleRate of the data in the AudioBuffer
@param wantsStereo requests to load both stereo channels or only one mono channel @param wantsStereo requests to load both stereo channels or only one mono channel
@param wantsTrimming requests to trim the start and the end of the impulse response @param wantsTrimming requests to trim the start and the end of the impulse response
@param wantsNormalization requests to normalize the impulse response amplitude
@param size the expected size for the impulse response after loading @param size the expected size for the impulse response after loading
*/ */
void copyAndLoadImpulseResponseFromBuffer (const AudioBuffer<float>& buffer, double bufferSampleRate, void copyAndLoadImpulseResponseFromBuffer (const AudioBuffer<float>& buffer, double bufferSampleRate,
bool wantsStereo, bool wantsTrimming, size_t size);
bool wantsStereo, bool wantsTrimming, bool wantsNormalization, size_t size);
private: private:
//============================================================================== //==============================================================================
@@ -133,6 +138,7 @@ private:
//============================================================================== //==============================================================================
double sampleRate; double sampleRate;
bool currentIsBypassed = false; bool currentIsBypassed = false;
bool isActive = false;
LinearSmoothedValue<float> volumeDry[2], volumeWet[2]; LinearSmoothedValue<float> volumeDry[2], volumeWet[2];
AudioBlock<float> dryBuffer; AudioBlock<float> dryBuffer;
HeapBlock<char> dryBufferStorage; HeapBlock<char> dryBufferStorage;


Loading…
Cancel
Save