NodeVCOWavetable
[ NODE_VCO_WAVETABLE ]
+-------------------------+
| |
IN00--| FREQ SIGNAL |--OUT00
IN01--| AMP |
| |
+-------------------------+
the wavetable node produces a periodic signal from a chunk of memory ( wavetable ). the speed at which the signal is produced from the wavetable can be adjusted by the changing its frequency FREQ
and the amplitude by changing AMP
. the node is often used as an oscillator to produce a sinewave, triangle, square or sawtooth shaped signal at an audible frequency ( (V)oltage-(C)ontrolled (O)scillator (VCO
) ). however, this node can also be used to manipulate other parameters ( e.g the frequency of another node ) at a lower frequency ( (L)ow (F)requency (O)scillator (LFO
) ).
SET_VALUE
- FREQUENCY_F32
- AMPLITUDE_F32
- OFFSET_F32
- WAVEFORM_I8
/*
* this example demonstrates how to generate signals from oscillators. note that there are two different types of
* oscillators:
*
* - `NodeVCOFunction` :: computes a signal from a function on the fly. it is more precise especially at very low
* frequencies, and uses less memory but requires more compuational resources.
* - `NodeVCOWavetable` :: computes a signal from a wavetable. it requires more memory and might create artifacts
* especially at low frequencies. it however is much faster. note that the wavetable is not generated at
* instantiation time, and must always be popluated before use. the wavetable can also be populated with custom
* waveforms.
*
* press keys 1–4 to switch the waveform of the function oscillators. press keys 5–8 to switch the waveform of the
* wavetable oscillators. use mouse to change the frequency and the amplitude of the osciallators.
*/
#include "Klangstrom.h"
#include "KlangNodes.hpp"
using namespace klang;
using namespace klangstrom;
NodeVCOFunction mVCOFunction;
NodeVCOWavetable mVCOWavetable;
NodeDAC mDAC;
void setup() {
Klang::connect(mVCOFunction, Node::CH_OUT_SIGNAL, mDAC, NodeDAC::CH_IN_SIGNAL_LEFT);
Klang::connect(mVCOWavetable, Node::CH_OUT_SIGNAL, mDAC, NodeDAC::CH_IN_SIGNAL_RIGHT);
mVCOFunction.set_frequency(DEFAULT_FREQUENCY * 2);
mVCOFunction.set_amplitude(0.5);
mVCOWavetable.set_frequency(mVCOFunction.get_frequency());
mVCOWavetable.set_amplitude(mVCOFunction.get_amplitude());
mVCOWavetable.set_waveform(NodeVCOWavetable::WAVEFORM::SINE);
mDAC.set_stereo(true);
}
void loop() {}
void audioblock(float** input_signal, float** output_signal) {
mDAC.process_frame(output_signal[LEFT], output_signal[RIGHT]);
}
void handle_key_pressed(char key) {
switch (key) {
case '1':
mVCOFunction.set_waveform(NodeVCOFunction::WAVEFORM::SINE);
break;
case '2':
mVCOFunction.set_waveform(NodeVCOFunction::WAVEFORM::TRIANGLE);
break;
case '3':
mVCOFunction.set_waveform(NodeVCOFunction::WAVEFORM::SAWTOOTH);
break;
case '4':
mVCOFunction.set_waveform(NodeVCOFunction::WAVEFORM::SQUARE);
break;
case '5':
mVCOWavetable.set_waveform(NodeVCOWavetable::WAVEFORM::SINE);
break;
case '6':
mVCOWavetable.set_waveform(NodeVCOWavetable::WAVEFORM::TRIANGLE);
break;
case '7':
mVCOWavetable.set_waveform(NodeVCOWavetable::WAVEFORM::SAWTOOTH);
break;
case '8':
mVCOWavetable.set_waveform(NodeVCOWavetable::WAVEFORM::SQUARE);
break;
case '9':
mVCOWavetable.set_waveform(NodeVCOWavetable::WAVEFORM::EXPONENT);
break;
}
}
void event_receive(const EVENT_TYPE event, const void* data) {
switch (event) {
case EVENT_KEY_PRESSED:
handle_key_pressed(keyboard_event(data).keys[0]);
break;
case EVENT_MOUSE_MOVED:
mVCOFunction.set_frequency(DEFAULT_FREQUENCY / 2 * floor(32 * mouse_event(data).x));
mVCOFunction.set_amplitude(0.5 * mouse_event(data).y);
mVCOWavetable.set_frequency(mVCOFunction.get_frequency());
mVCOWavetable.set_amplitude(mVCOFunction.get_amplitude());
break;
}
}