Manage channels processing

Hello everyone,

Noob alert here :sweat_smile: I’m trying to make a simple tremolo effect and I only got it to work correctly when pluging my guitar in the first channel of my audio interface. If I plug it in the second channel it either doesn’t process the signal or I get clicking in both channels.

I’ve been looking at the #1 most common programming mistake that we see on the forum post but I can’t understand how should I manage the different channels.

The code I have in the ProcessBlock (and that currently clicks on both channels) is this:

void AudioPluginAudioProcessor::processBlock (juce::AudioBuffer& buffer,
juce::MidiBuffer& midiMessages)
{
juce::ignoreUnused (midiMessages);
juce::ScopedNoDenormals noDenormals;
const int totalNumInputChannels = getTotalNumInputChannels();
const int totalNumOutputChannels = getTotalNumOutputChannels();
//
trem.SetFreq(freq); // changes frequency using a knob
trem.SetDepth(depth); // changes amplitude using another knob
//
for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
buffer.clear (i, 0, buffer.getNumSamples());
for (int channel = 0; channel < totalNumInputChannels; ++channel)
{
float* channelData = buffer.getWritePointer (channel);
for (size_t sample = 0; sample < buffer.getNumSamples(); ++sample)
{
float in = channelData[sample];
float out = trem.Process(in);
channelData[sample] = out;
}
}

And my trem.Process() looks like this:

float Tremolo::Process(float in)
modsig = dc_os_ + osc_.Process();
return in * modsig;

You can imagine what the osc_.Process() does.

I know it must be annoying to answer to the same problem so many times but I couldn’t put together how to solve this even with all the comments on the mentioned post and others I’m sorry :confounded: :confounded:

I hope someone can help me with this and thanks so much in advance to everyone!

Alex

You need to have a separate tremolo object for each channel you’re processing! That’s what the thread you linked to is talking about - it applies to more than just filters.

std::vector<Tremolo> trems;

void prepareToPlay()
{
    trems.resize(getNumChannels());
}

void processBlock()
{
    for (int channel = 0; channel < numChannels; channel++)
    {
        auto& trem = trems[channel];

        // ...
    }
}
1 Like

Ok, the idea makes complete sense but once I have as many instances of the tremolo object as channels can I stilll call my this object’s functions the same way? Just like trem.Process(in) works or how should I call my functions now?

Thanks a lot! Now at least I understand what the other post was talking about!

Solved it, just had to create an array for the Tremolo instances I want to create and use the methods from the Tremolo class as you would expect… it sometimes feels like the most obvious stuff slips from one’s mind :sweat_smile: