Thanks for your reply.
I do this in the prepare() function. I post it here below so you can see. It is my Chorus/flanger template class that I’m using within a processorChain juce::dsp::ProcessorChain<juce::dsp::LadderFilter, ChorusFlanger> processorChain; adding it to my feedbacked delayed signal. I think the problem might be in this class, because the problem only happens when the Chorus effect is not bypassed. The plugin can work perfectly fine using the chorus effect, but then suddenly plugin burst out audible overloaded audio on meter track(DAW).
#pragma once
#include "../JuceLibraryCode/JuceHeader.h"
#define MAX_DELAY_TIME 2
//=========================================================================================================
template <typename T>
class ChorusFlanger
{
public:
//=============================================================================
ChorusFlanger(){
mCurrentSampleRate = 0.0;
/* we set nullptr because we don't no the sample rate yet, and are not ready to instantiate audio data/ how big buffer is*/
mCircularBufferLeft = nullptr;
mCircularBufferRight = nullptr;
mCircularBufferWriteHead = 0;
mCircularBufferLength = 0;
mFeedBackLeft = 0;
mFeedBackRight = 0;
mLFOPhase = 0;
mDryWetSmoothing = 0;
mDepthSmoothing = 0;
mPhaseSmoothing = 0;
}
//==============================================================================
void prepare (const juce::dsp::ProcessSpec& spec)
{
mCurrentSampleRate = spec.sampleRate;
mLFOPhase = 0;
/* our bufferLength - time in samples we need to store - only (int) delay time allowed*/
mCircularBufferLength = spec.sampleRate * MAX_DELAY_TIME;
/* Here we check for nullptr, and create and set the size of our floating point array - the correct length of our buffers*/
if (mCircularBufferLeft == nullptr )
{
//mCircularBufferLeft.reset( new float[static_cast<int>(mCircularBufferLength)]);
mCircularBufferLeft = std::make_unique<float[]>(mCircularBufferLength);
}
//mCircularBufferLeft.reset();
zeromem(mCircularBufferLeft.get(), mCircularBufferLength * sizeof(float));
if (mCircularBufferRight == nullptr )
{
//mCircularBufferRight.reset(new float[static_cast<int>( mCircularBufferLength)]);
mCircularBufferRight = std::make_unique<float[]>(mCircularBufferLength);
}
//mCircularBufferRight.reset();
zeromem(mCircularBufferRight.get(), mCircularBufferLength * sizeof(float));
mCircularBufferWriteHead = 0;
}
template <typename ProcessContext>
void process (const ProcessContext& context) noexcept
{
const auto& inputBlock = context.getInputBlock();
auto& outputBlock = context.getOutputBlock();
const auto numInSamples = inputBlock.getNumSamples();
ScopedNoDenormals noDenormals;
const float* leftChannel = inputBlock.getChannelPointer(0); //context.getWritePointer(0);
const float* RightChannel = inputBlock.getChannelPointer(1); //context.getWritePointer(1);
/*Iterate through all samples in audio buffer, and proces buffer data in loop*/
for (int i = 0; i < numInSamples; i++)
{
/*we store data in circular buffer + adding the feedback data back, se below. Se diagram in notes */
mCircularBufferLeft.get()[mCircularBufferWriteHead] = leftChannel[i] + mFeedBackLeft;
mCircularBufferRight.get()[mCircularBufferWriteHead] = RightChannel[i] + mFeedBackRight;
/* Generating the left LFO output*/
float lfoOutLeft = sin(2*M_PI * mLFOPhase);
/* Moving our LFO phase forward*/
mLFOPhase += mRateParameter / mCurrentSampleRate;
/* to keep mLFOPhase between 0-1 (is exactly one cycle) */
if(mLFOPhase >= 1)
{
mLFOPhase -= 1;
}
mPhaseSmoothing = mPhaseSmoothing - 0.0001*(mPhaseSmoothing - mPhaseOffsetParameter);
/* calculate the right LFO phase*/
float lfoPhaseRight = mLFOPhase + mPhaseSmoothing; //*mPhaseOffsetParameter;
if(lfoPhaseRight > 1)
{
lfoPhaseRight -= 1;
}
/* Generating the right LFO output*/
float lfoOutRight = sin(2*M_PI * lfoPhaseRight);
/*We apply smooting, and add it to lfoOut*/
mDepthSmoothing = mDepthSmoothing - 0.0001*(mDepthSmoothing - mDepthParameter);
/* we set the range of the LFO, control the depth of lfo + apply smoothing*/
lfoOutLeft *= mDepthSmoothing;
lfoOutRight *= mDepthSmoothing;
/*we map lfo output to our desired delay times(chorus/flanger)*/
float lfoOutMappedLeft = 0;
float lfoOutMappedRight = 0;
/* Chorus */
if (mTypeParameter == 1)
{
lfoOutMappedLeft = jmap<float>(lfoOutLeft, -1.0f, 1.0f, 0.005f, 0.03f);
lfoOutMappedRight = jmap<float>(lfoOutRight, -1.0f, 1.0f, 0.005f, 0.03f);
}
if (mTypeParameter == 2)
{
/* Flanger */
lfoOutMappedLeft = jmap<float>(lfoOutLeft, -1.0f, 1.0f, 0.001f, 0.005f);
lfoOutMappedRight = jmap<float>( lfoOutRight, -1.0f, 1.0f, 0.001f, 0.005f);
}
/* Calculate delay lenght in samples. Equal to delaylength = samplerate * delayTimesInSeconds. */
float delayTimeSamplesLeft = mCurrentSampleRate * lfoOutMappedLeft;
float delayTimeSamplesRight = mCurrentSampleRate * lfoOutMappedRight;
/* calculate the left read head position, we want to read from */
float delayReadHeadLeft = mCircularBufferWriteHead - delayTimeSamplesLeft;
if (delayReadHeadLeft < 0)
{
delayReadHeadLeft += mCircularBufferLength;
}
/* calculate the right read head position, we want to read from */
float delayReadHeadRight = mCircularBufferWriteHead - delayTimeSamplesRight;
if (delayReadHeadRight < 0)
{
delayReadHeadRight += mCircularBufferLength;
}
/* here we calculate our linear interpolation values for left channel (to put in lin_interp() */
int readHeadLeft_x = static_cast<int>(delayReadHeadLeft); // Int is needed for mCircularBuffer array index access
int readHeadLeft_x1 = readHeadLeft_x + 1;
/* the float remainder value, used for interval between x and x1, where we want to compute a interpolated value */
float readHeadFloatLeft = delayReadHeadLeft - readHeadLeft_x;
/*If we exceed our buffer*/
if(readHeadLeft_x1 >= mCircularBufferLength)
{
readHeadLeft_x1 -= mCircularBufferLength;
}
/* here we calculate our linear interpolation values for right channel (to put in lin_interp() */
int readHeadRight_x = static_cast<int>(delayReadHeadRight); // Int is needed for mCircularBuffer array index access
int readHeadRight_x1 = readHeadRight_x + 1;
/* the float remainder value, used for interval between x and x1, where we want to compute a interpolated value */
float readHeadFloatRight = delayReadHeadRight - readHeadRight_x;
/*If we exceed our buffer*/
if(readHeadRight_x1 >= mCircularBufferLength)
{
readHeadRight_x1 -= mCircularBufferLength;
}
/* We generate our interpolated delayed output audio data we want to sum with original audio buffer. added to feedback(left/right), then into circularbuffer above, and summed below with original audio buffer buffer.addSample()*/
float delay_sample_left = lin_interp(mCircularBufferLeft.get()[readHeadLeft_x], mCircularBufferLeft.get()[readHeadLeft_x1], readHeadFloatLeft);
float delay_sample_right = lin_interp(mCircularBufferRight.get()[readHeadRight_x], mCircularBufferRight.get()[readHeadRight_x1], readHeadFloatRight);
/* here we scale our feedback audio data (* mFeedbackParameter) avoiding overloaded volume in DAW */
mFeedBackLeft = delay_sample_left * mFeedbackParameter;
mFeedBackRight = delay_sample_right * mFeedbackParameter;
/*we increment writeHead*/
mCircularBufferWriteHead++;
/* if end of array, we set writeHead to begining - circularbuffer concept */
if(mCircularBufferWriteHead >= mCircularBufferLength)
{
mCircularBufferWriteHead = 0;
}
/*We apply smoothing, and add it below (buffer.setSample) replacing *mDryWetParameter*/
mDryWetSmoothing = mDryWetSmoothing - 0.0001*(mDryWetSmoothing - mDryWetParameter);
/* here we add delayed signal/data to the original buffer data. */
outputBlock.setSample(0, i, inputBlock.getSample(0, i) * (1 - mDryWetSmoothing) +
delay_sample_left * mDryWetSmoothing );
outputBlock.setSample(1, i, inputBlock.getSample(1, i) * (1 - mDryWetSmoothing) +
delay_sample_right * mDryWetSmoothing );
}
}
void reset() noexcept
{
}
float lin_interp(float inSampleX, float inSampleY, float inFloatPhase)
{
return (1 - inFloatPhase) * inSampleX + inFloatPhase * inSampleY;
}
float getMDryWetParameter() const {
return mDryWetParameter;
}
void setMDryWetParameter(T mDryWet) {
mDryWetParameter = mDryWet;
}
float getMDepthParameter() const {
return mDepthParameter;
}
void setMDepthParameter(T mDepth) {
mDepthParameter = mDepth;
}
float getMRateParameter() const {
return mRateParameter;
}
void setMRateParameter(T mRate) {
mRateParameter = mRate;
}
float getMPhaseOffsetParameter() const {
return mPhaseOffsetParameter;
}
void setMPhaseOffsetParameter(T mPhaseOffset) {
mPhaseOffsetParameter = mPhaseOffset;
}
float getMFeedbackParameter() const {
return mFeedbackParameter;
}
void setMFeedbackParameter(T mFeedback) {
mFeedbackParameter = mFeedback;
}
float getMTypeParameter() const {
return mTypeParameter;
}
void setMTypeParameter(T mType) {
mTypeParameter = mType;
}
private:
//===============================================================================
double mCurrentSampleRate;
/*this is where we store our audio data from original audio buffer*/
std::unique_ptr<float[]> mCircularBufferLeft;
std::unique_ptr<float[]> mCircularBufferRight;
/*keep track of current postion in array/buffer we write to*/
int mCircularBufferWriteHead;
/*the size of our array/buffer*/
int mCircularBufferLength;
/* mFeedBack(L/R) Is the output of our delayed audio data, that we store/feed back in our circularBuffer + the original audio buffer data*/
float mFeedBackLeft;
float mFeedBackRight;
/* LFO data */
float mLFOPhase;
/* Parameter declaration: we are using the depth,rate, phase to modulate the delayReadHead, instead of manually in delay*/
float mDryWetParameter;
float mDepthParameter;
float mRateParameter;
float mPhaseOffsetParameter;
float mFeedbackParameter;
float mTypeParameter;
/*Smoothing variables*/
float mDryWetSmoothing;
float mDepthSmoothing;
float mPhaseSmoothing;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChorusFlanger)
};