Skip to content

Lesson 1: Patching

npisanti edited this page Feb 14, 2016 · 32 revisions

For this tutorial we need the basic setup object and also:

    pdsp::VAOscillator osc;
    pdsp::LFO lfo;
    pdsp::Amp amp;
    pdsp::Processor engine; // the name is the same and it is called in audioOut as seen in the setup wiki

We will do our patching in the of setup() method, before calling ofxPDSPSetup().

You can use the patch operator >> to connect pdsp objects (that we will call "modules"). All the modules have some input and outputs, when you use the >> operator you are connecting one of those outputs to one of those inputs. For example in the setup method, before ofxPDSPSetup() we could write.

    osc >> engine.channels[0];

we have just patched the oscillator output to our system left channel. Lower your system volume out, compile and run. You should hear a buzzing pitched sound from your left speaker / headphone.

When you are patching something you could use the * operator to scale the signal, for example:

    osc * 0.25f >> engine.channels[0];
    osc * 0.50f >> engine.channels[1];

Compile and run. Now you should ear the same sound but lower in volume and slightly panned to the right.

When you are using the patch operator on the modules you are patching the default outputs / inputs. You could access other inputs and outputs with some in____() and out____() methods. What ins/outs are available and what are the default is described in the documentation. For example we could take a look at the VAOscillator page for knowing what outputs we have. We have outputs for all the four basic waveform, so we could try:

    osc.out_sine() * 0.25f >> engine.channels[0];
    osc.out_sine() * 0.25f >> engine.channels[1];

Compile and run. You should hear a sine wave with no panning. Now our code is really the same of example-hello_world.

Looking at the VAOscillator documentation you should have seen that there were many inputs, but we haven't patched anything to them. When an input is not patched it usually takes a default value, for example in our case in_pitch() will have the default value of 69, that is A4 = 440hz (so you could use it to tune your instruments).

We can patch a float number right into osc.in_pitch(). When something is connected to an input the default value will be ignored.

    osc.out_sine() * 0.25f >> engine.channels[0];
    osc.out_sine() * 0.25f >> engine.channels[1];
    81.0f >> osc.in_pitch();

Compile and run. Now the sine frequency should be an octave higher.
REMEMBER: when you are patching a float to an input you are not setting the default value, you are connecting a "number" to the input. You can have only one float number connected to each input so you could think it is the same, but the difference is that when you are patching another module to the input the module signal will override the default input, but it will be summed to connected floats.

    osc.out_sine() * 0.25f >> engine.channels[0];
    osc.out_sine() * 0.25f >> engine.channels[1];
    43.0f >> osc.in_pitch(); // now the pitch is 43
    60.0f >> osc.in_pitch(); // now the pitch is 60 (C4), the floats are not summed!

You could patch multiple signal to an input, and they will be summed. It's time to patch the LFO:

    osc.out_sine() * 0.25f >> engine.channels[0];
    osc.out_sine() * 0.25f >> engine.channels[1];
                         60.0f >> osc.in_pitch(); 
    lfo.out_triangle() * 24.0f >> osc.in_pitch(); 

Compile and run, you should hear the sine wave modulated by the LFO.

You could use also the + operator to patch multiple modules with one >> operation, so the following code will produce the same result (remember only that the float has to be the first argument of the sum, because: c++ reasons):

    osc.out_sine() * 0.25f >> engine.channels[0];
    osc.out_sine() * 0.25f >> engine.channels[1];
    60.0f + lfo.out_triangle() * 24.0f >> osc.in_pitch(); 

Compile and run, the result will be the same.

It isn't thread-safe to patch something when the audio callback is running, but it is thread safe to patch floats, so we can add a bit of interaction:

void ofApp::mouseMoved(int x, int y ){
    float pitch = ofMap(x, 0, ofGetWidth(), 48.0f, 72.0f);
    float lfoFreq = ofMap(y, 0, ofGetHeight(), 1.5f, 0.25f);
    pitch >> osc.in_pitch();
    lfoFreq >> lfo.in_freq();
}

Compile and run. Now you can control the pitch and the lfo speed by hovering the mouse in the app window. The change of those patched values is not smoothed out so if you move the mouse fast in the x axis you should ear some "grainy" noise. For a smoother value change you could patch floats to a pdsp::CRSlew and then patch this pdsp::CRSlew to the desired input (more on this later).