Vst 2 mono input -> true stereo output


#1

I’m moved here from another post because I need to understand very well the channel setup of a VST 2 plugin.
My intention is to develop VSTs for guitar/bass, instruments that have a mono output.
So in my plugins I need to have a mono input and a TRUE stereo output.
I mean that even I have only one getReadPointer(0) (left channel or mono), i must have two separate writePointers (0 = Left and 1 = right).

Please can some of you make a step by step process to get this setup?


#2

Ok, I’ve found a very good start point in the plugin example…
Now i would like to add another effect, a reverb:

I’ve settled up all but the algorithm.

This is the code for ::applyDelay()

const int numSamples = buffer.getNumSamples();
const float delayLevel = *delayParam;

int delayPos = 0;

for (int channel = 0; channel < getTotalNumInputChannels(); ++channel)
{
    FloatType* const channelData = buffer.getWritePointer (channel);
    FloatType* const delayData = delayBuffer.getWritePointer (jmin (channel, delayBuffer.getNumChannels() - 1));
    delayPos = delayPosition;
    
    for (int i = 0; i < numSamples; ++i)
    {
        const FloatType in = channelData[i];
        channelData[i] += delayData[delayPos];
        delayData[delayPos] = (delayData[delayPos] + in) * delayLevel;
        
        if (++delayPos >= delayBuffer.getNumSamples())
            delayPos = 0;
    }
}

delayPosition = delayPos;

But now i have a new template function named ::applyReverb()

I have this code for reverberation:

int numlines = 8;
float t1 = 50.0; // d0 time
float g1 = 0.75; // d0 gain
float rev = -3*t1 / log10 (g1);

for (int n = 0; n < numlines; ++n)
{
float dt = t1 / pow (2, (float (n) / numlines));
float g = pow (10, -((3*dt) / rev));
printf (“d%d t=%.3f g=%.3f\n”, n, dt, g);
}

The above with t1=50.0 and g1=0.75 yields:

d0 t=50.000 g=0.750
d1 t=45.850 g=0.768
d2 t=42.045 g=0.785
d3 t=38.555 g=0.801
d4 t=35.355 g=0.816
d5 t=32.421 g=0.830
d6 t=29.730 g=0.843
d7 t=27.263 g=0.855

How I can implement it in the ::applyReverb() template?


#3

You haven’t provided enough information about the algorithm you want to implement. What do d, t and g represent?


#4

Don’t mind… I’ve found the STK modules and now I use them…
No more need to implement external algorithms.

Thanks anyway!


#5

Excuse me, I realized that the configuration I have is mono->mono or stereo->stereo again.
How do have I set the buffers and the various configurations to obtain a mono input and a stereo output?


#6

In the constructor of your AudioProcessor do:

YourAudioProcessor::YourAudioProcessor()
    : AudioProcessor (BusesProperties().withInput  ("Input",  AudioChannelSet::mono(), true)
                                       .withOutput ("Output", AudioChannelSet::stereo(), true))

Also have your isBusesLayoutSupported method look like this:

bool YourAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const
{
    const AudioChannelSet& mainInput  = layouts.getMainInputChannelSet();
    const AudioChannelSet& mainOutput = layouts.getMainOutputChannelSet();

    return mainInput.size() == 1 && mainOutput.size() == 2;
}

#7

Thanks very much!!!
I’m becoming mad to understand a way to do that!

And now, how i can use buffers?

If I use:

if (int channel = 0; channel < getNumTotalOutputChannels(); ++channel)
{
float* channelData = buffer.getWritePointer(channel);

for (int i = 0; i < buffer.getNumSamples(); ++i)
{
    channelData[i] = ....
}

}

should work?


#8

No, it doesn’t work…
Ho can i route from mono input buffer and stereo output buffer?


#9

Your technique is wrong: I receive this from Xcode:

// if some output channels are disabled, some hosts supply the same buffer
// for multiple channels - this buggers up our method of copying the
// inputs over the outputs, so we need to create unique temp buffers in this case…

on the line:

if (chan != input[i]) …

of the juceVstWrapper class, input = NULL


#10

This was a bug in JUCE - I’ve just pushed a fix to the develop branch.

The changes I suggested work as expected with VST3 and AU, and with the latest fix they should now work with VST2 too.

Thank you for your patience!


#11

So now I can use your code?


#12

If you get the latest version of JUCE from GitHub, yes.


#13

Ok thanks…
But now how can I setup the read/write pointers of buffer?
Said:

const float readBuf = buffer.getReadPointer(0);
float lBuf = buffer.getWritePointer(0);
float rBuf = buffer.getWritePointer(1);

something like this?


#14

Yes, but remember that these return pointers: float*


#15

Ok, thanks again…
Oh, how can I download the latest version from GitHub?
I have OS X and JUCE installed… I have only to copy the new JUCE folder?


#16

Click on the green download button and download the zip file, then replace your JUCE folder.

If you do this you will need to either move the Projucer application somewhere else first, or recompile the Projucer in the new directory afterwards.


#17

At the end I got it work!
Thanks for your JUCE update!


#18

How can I set an audio plugin to have always mono input and stereo output?
The above code doesn’t work…it doesn’t split channels in getWritePointer(0) and getWritePointer(1).
I don’t ear left and right diversity…


#19

How are you testing it? The above code works correctly for me.

Add the code to the JUCE demo plug-in, change a few calls from getTotalNumInputChannels() to getTotalNumOutputChannels(), do

const int numSamples = buffer.getNumSamples();
buffer.copyFrom (1, 0, buffer, 0, 0, numSamples);

as the first thing in JuceDemoPluginAudioProcessor::process, and that’s all you need. From here you can process the left and right sides of the audio differently.


#20

Ok now It works… but only in certain effects (I use the STK modules by @danlin) like pit shift chorus and reverb… but not in the delay. Please watch this post:

(My last post)