-
Notifications
You must be signed in to change notification settings - Fork 37
Lesson 4: sequencing 101
In this lesson we will learn about more sequencing with ofxPDSP. Copy again the init app code again. in 'ofApp.h' we need:
// pdsp modules
ofxPDSPEngine engine;
pdsp::Sequence sequence;
pdsp::ADSR adsr;
pdsp::Amp amp;
pdsp::FMOperator sine;
now in the ofApp.cpp
code:
void ofApp::patch(){
engine.score.setTempo(108.0);
engine.score.sections.resize(1); // by default we have 0 sections, we need 1
engine.score.sections[0].setCell(0, &sequence, pdsp::Behavior::Loop);
// arguments are: index, pointer to pdsp::ScoreCell or pdsp::Sequence, pointer to pdsp::CellChange
engine.score.sections[0].launchCell(0); // cells are stopped by default, start the first cell of sections[0]
// we patch our section to our synth
engine.score.sections[0].out_trig(0) >> adsr; // first output is patched to envelope
// our synth is a simple sine wave
adsr.set(0.0f, 50.0f, 1.0f, 50.0f) >> amp.in_mod();
sine >> amp * 0.5f >> engine.audio_out(0);
amp * 0.5f >> engine.audio_out(1);
// SEQUENCE CODING
sequence.set( { 1.0f, 0.0f, 0.5f, 0.0f, 0.3f, 0.0f, 0.2f, 0.0f }, 16.0, 1.0);
// arguments are: an inline array of values, the time division (16.0 = 1/16t), the sequence length
}
Now i will explain what it's happening here. Inside our engine
we have a score
member. score
is the object we use for updating the global playhead and for sequencing. Inside score there is a vector member called sections
. Think of those sections as tracks of your arrangment, or different sections of an orchestral score. Each section has one ore more outputs you can patch to your modules.
Also each sections has a table with pointers to our pdsp::ScoreCell
object with each index.
pdsp::ScoreCell
is a class that rapresent the message we are scoring. We will use pdsp::Sequence
, that is a subclass of pdsp::CellChange
easier to work with. We are setting sequence
giving it a list of values that will be sent to the connected envelope sequentially at the given clock division (in our case 8.0 = 1/16th). After the sequence length is expired another ScoreCell/Sequence is triggered (in our case the sequence retrigger itself as we have set pdsp::Behavior::Loop for that section index). The positive values are opening the envelope gate, the 0.0f value are closing it, so even if we have set our time to 16.0 we will hear an 8th division.
Compile and run, you should hear our sequentially triggered beeps.
void ofApp::patch(){
engine.score.setTempo(108.0);
engine.score.sections.resize(1); // by default we have 0 sections, we need 1
engine.score.sections[0].setCell(0, &sequence, pdsp::Behavior::Self);
engine.score.sections[0].launchCell(0);
// we patch our section to our synth
// in out_trig() or out_value() you pass the output number (or 0 if you don't give an argument)
// you can't use both out_trig() and out_value() for the same output number
engine.score.sections[0].out_trig(0) >> ahr; // first output is patched to envelope
engine.score.sections[0].out_value(1) >> sine.in_pitch(); // second is patched to pitch
ahr.set(0.0f, 50.0f, 50.0f) >> amp.in_mod();
sine >> amp * 0.5f >> engine.audio_out(0);
amp * 0.5f >> engine.audio_out(1);
}
Home
Lesson 1: Patching
Lesson 2: More Basics
Lesson 3: making Modules
[Lesson 4: Sequencing 101] (https://github.com/npisanti/ofxPDSP/wiki/Lesson-4:-sequencing-101)