Hi,
i’ve implemented oversampling in my plugin.
it work in normal daws,
but it crash with plugindoctor and blue cat patchwork.
can you help me ?
// PluginProcessor.h oversampling declarations
obtenirParametres(juce::AudioProcessorValueTreeState& apvts);
static juce::AudioProcessorValueTreeState::ParameterLayout creationParametres();
juce::AudioProcessorValueTreeState apvts {*this, nullptr, "Parametres", creationParametres()};
int parametre_oversampling = 0;
int etat_parametre_oversampling = 0;
std::array<juce::dsp::Oversampling<float>, 18> etat_oversamplers
{ {
{ 2, 1, juce::dsp::Oversampling<float>::filterHalfBandPolyphaseIIR, true, true }, // 0 not use
// normal oversampling
{ 2, 1, juce::dsp::Oversampling<float>::filterHalfBandPolyphaseIIR, true, true },
{ 2, 2, juce::dsp::Oversampling<float>::filterHalfBandPolyphaseIIR, true, true },
{ 2, 3, juce::dsp::Oversampling<float>::filterHalfBandPolyphaseIIR, true, true },
{ 2, 4, juce::dsp::Oversampling<float>::filterHalfBandPolyphaseIIR, true, true },
{ 2, 1, juce::dsp::Oversampling<float>::filterHalfBandFIREquiripple, true, true },
{ 2, 2, juce::dsp::Oversampling<float>::filterHalfBandFIREquiripple, true, true },
{ 2, 3, juce::dsp::Oversampling<float>::filterHalfBandFIREquiripple, true, true },
{ 2, 4, juce::dsp::Oversampling<float>::filterHalfBandFIREquiripple, true, true },
{ 4, 1, juce::dsp::Oversampling<float>::filterHalfBandPolyphaseIIR, true, true }, // 9 no use
// sidechains oversampling
{ 4, 1, juce::dsp::Oversampling<float>::filterHalfBandPolyphaseIIR, true, true },
{ 4, 2, juce::dsp::Oversampling<float>::filterHalfBandPolyphaseIIR, true, true },
{ 4, 3, juce::dsp::Oversampling<float>::filterHalfBandPolyphaseIIR, true, true },
{ 4, 4, juce::dsp::Oversampling<float>::filterHalfBandPolyphaseIIR, true, true },
{ 4, 1, juce::dsp::Oversampling<float>::filterHalfBandFIREquiripple, true, true },
{ 4, 2, juce::dsp::Oversampling<float>::filterHalfBandFIREquiripple, true, true },
{ 4, 3, juce::dsp::Oversampling<float>::filterHalfBandFIREquiripple, true, true },
{ 4, 4, juce::dsp::Oversampling<float>::filterHalfBandFIREquiripple, true, true }
} };
----
// PluginProcessor.cpp oversampling parts
// initialisation of the audioprocessor class
AudioProcessor()
{
…
ecoutes();
}
void prepareToPlay (double sampleRate, int samplesPerBlock)
{
for (auto& etat_oversampler : etat_oversamplers)
etat_oversampler.initProcessing(samplesPerBlock);
sr = (float)sampleRate;
sr_double = sampleRate;
if (sr < 44100.0f)
{
sr = 44100.0f;
}
if (sr_double < 44100.0)
{
sr_double = 44100.0;
}
…
rafraichit(true);
...
}
void processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
…
// "ticket" so oversampling done stays the same Inside processBlock
int parametre_oversampling_ticket = parametre_oversampling;
// read only pointers class on buffer
juce::dsp::AudioBlock<float> block(buffer);
// read only pointers class on oversampling buffer (why using buffer ?)
juce::dsp::AudioBlock<float> reblock(buffer);
// the input sample buffer used
juce::AudioBuffer<float> interne;
// the sidechain sample buffer used
juce::AudioBuffer<float> externe;
// the oversampled buffer
juce::AudioBuffer<float> buffero;
if (parametre_oversampling != 0 && parametre_oversampling != 9)
{
// the reblock is a block pointing to oversampled audiobuffer that is not directly provided
reblock = etat_oversamplers[size_t(parametre_oversampling)].processSamplesUp(block);
// we set the futur oversampled audiobuffer to the good size
buffero = juce::AudioBuffer<float>(buffer.getNumChannels(), buffer.getNumSamples() * etat_oversamplers[size_t (parametre_oversampling_ticket)].getOversamplingFactor());
// we copy the oversampled buffer (that is read only if we use the block) to our oversampled buffer
reblock.copyTo(buffero);
// now we can handle the oversampled buffer
interne = getBusBuffer(buffero, true, 0);
if (sc == true)
{
externe = getBusBuffer(buffero, true, 1);
}
}
// no oversampling
else
{
// classic buffer handling
interne = getBusBuffer(buffer, true, 0);
if (sc == true)
{
externe = getBusBuffer(buffer, true, 1);
}
}
…
if (parametre_oversampling_ticket != 0 && parametre_oversampling_ticket != 9)
{
// the block pointing to oversampled audiobuffer need to have the handled sample
reblock.copyFrom(buffero);
// block given to the downsampler but it manage to write on the audiobuffer pointed by the block ...
etat_oversamplers[size_t(parametre_oversampling_ticket)].processSamplesDown(block);
}
…
}
void ecoutes()
{
...
apvts.addParameterListener("oversampling", this);
...
}
juce::AudioProcessorValueTreeState::ParameterLayout creationParametres()
{
juce::AudioProcessorValueTreeState::ParameterLayout layout;
...
layout.add(std::make_unique<juce::AudioParameterChoice>("oversampling", "Oversampling", juce::StringArray{ "1X", "2X IIR", "4X IIR", "8X IIR", "16X IIR", "2X FIR", "4X FIR", "8X FIR", "16X FIR" }, 0));
...
return layout;
}
obtenirParametres(juce::AudioProcessorValueTreeState& apvts)
{
Parametres parametres;
...
parametres.oversampling = static_cast<int>(apvts.getRawParameterValue("oversampling")->load());
...
return parametres;
}
void parameterChanged(const juce::String& idIn, float valueIn)
{
// detecter si monitoring
if (!etat_rafraichit)
{
// etat_rafraichit is for "meta" parameters to avoid rafraichit on the target parameters (true in begin of "manipultion" false in the end)
rafraichit(false);
}
}
void rafraichit(bool premier)
{
Parametres parametres = obtenirParametres(apvts);
parametre_oversampling = parametres.oversampling;
if (sc == true && (parametre_externe > 0 || parametre_analyse > 0))
{
parametre_oversampling += 9;
}
if (premier == true || etat_parametre_oversampling != parametre_oversampling)
{
if (premier)
{
for (auto& etat_oversampler : etat_oversamplers)
etat_oversampler.initProcessing(spb);
}
if (parametre_oversampling == 0 || parametre_oversampling == 9)
{
etat_sro = sr;
if (getLatencySamples() != 0)
{
setLatencySamples(0);
}
sl = true;
}
else
{
etat_sro = etat_oversamplers[size_t(parametre_oversampling)].getOversamplingFactor() * sr;
if (getLatencySamples() != (static_cast<int>(etat_oversamplers[size_t(parametre_oversampling)].getLatencyInSamples()) ))
{
setLatencySamples(static_cast<int>(etat_oversamplers[size_t(parametre_oversampling)].getLatencyInSamples()) );
}
sl = true;
}
…
}
sr_double = static_cast<double>(etat_sro);
// si la latence n'a pas été setté dans premier, alors on utilise l'objet oversamplers uniquement pour un setting de latence
if (sl == false)
{
if (parametre_oversampling == 0 || parametre_oversampling == 9)
{
if (getLatencySamples() != 0)
{
setLatencySamples(0);
}
}
else
{
if (getLatencySamples() != (static_cast<int>(etat_oversamplers[size_t(parametre_oversampling)].getLatencyInSamples()) ))
{
setLatencySamples(static_cast<int>(etat_oversamplers[size_t(parametre_oversampling)].getLatencyInSamples()) );
}
}
}
etat_parametre_oversampling = parametre_oversampling;
…
}
