Klang C++
Language Reference (draft)
Loading...
Searching...
No Matches
Examples

Examples

These code examples demonstrate a range of common audio DSP processes. To use them, either replace the MyEffect or MySynth struct definitions in MyEffect.k or MySynth.k, or rename the struct and constructor used in the code to that of your .k file.

The following lines should also be present before the example code:

#include <klang.h>
using namespace klang::optimised;

Effects Processes

Amplitude

Level / Gain
struct MyEffect : Effect {
MyEffect() {
controls = {
Dial("Gain", 0.0, 1.0, 0.5),
};
}
void process() {
param gain = controls[0];
in * gain >> out;
}
};
Stereo Pan
struct MyEffect : Stereo::Effect {
MyEffect() {
controls = {
Dial("Pan", 0.0, 1.0, 0.5),
};
}
void process() {
param x = controls[0];
in.l * (1 - x) >> out.l;
in.r * (x) >> out.r;
}
};
Tremolo
struct MyEffect : Effect {
Sine lfo;
MyEffect() {
controls = {
Dial("Mod Rate", 1.0, 10.0, 6.0),
Dial("Mod Depth", 0.0, 0.5, 0.5),
};
}
void process() {
param rate = controls[0];
param depth = controls[1];
signal mod = lfo(rate) * depth + (1 - depth);
in * mod >> out;
}
};
Ring Modulation
struct MyEffect : Effect {
Sine lfo;
MyEffect() {
controls = {
Dial("Mod Rate", 1.0, 1000.0, 100.0),
};
}
void process() {
param rate = controls[0];
in * lfo(rate) >> out;
}
};

Distortion

Hard Clipping
struct MyEffect : Effect {
MyEffect() {
controls = {
Dial("Overdrive", 1.0, 25.0, 1.0),
};
}
void process() {
param gain = controls[0];
in *= gain; // overdrive
if(in > 1) // clamp to [-1 .. 1]
in = 1;
else if(in < -1)
in = -1;
in >> out;
}
};
Transfer Functions (C-style)

NB: Hide help to view graph plot.

float hardclip(float x){
if(x > 1)
return 1;
else if(x < -1)
return -1;
else
return x;
}
struct MyEffect : Effect {
MyEffect() {
controls = {
Dial("Overdrive", 1.0, 25.0, 1.0),
};
hardclip >> graph(-2,2,-2,2); // plot transfer function
}
void process() {
param gain = controls[0];
hardclip(in * gain) >> out;
}
};
Transfer Functions (object-based)

NB: Hide help to view graph plot.

struct HardClip : Function<float> {
void process() {
if(in > 1)
out = 1;
else if(in < -1)
out = -1;
else
out = in;
}
};
struct MyEffect : Effect {
HardClip function;
MyEffect() {
controls = {
Dial("Overdrive", 1.0, 25.0, 1.0),
};
function >> graph(-2,2,-2,2);
}
void process() {
param gain = controls[0];
in * gain >> function >> out;
}
};
Soft Clipping / Shaping

NB: Hide help to view graph plot.

float hardclip(float x){
if(x > 1)
return 1;
else if(x < -1)
return -1;
else
return x;
}
float softclip(float x, float c){
return tanh(c * x) / tanh(c);
}
struct MyEffect : Effect {
MyEffect() {
controls = {
Dial("Distort", 0.001, 5.6, 0.001),
};
}
void prepare() {
param distort = controls[0];
Function f(softclip);
f.with(distort) >> graph;
}
void process() {
param distort = controls[0];
Function f(softclip);
in >> f(distort) >> out;
}
};

Filtering

Low/High/Band Pass Filter
struct MyEffect : Effect {
LPF lpf;
HPF hpf;
BPF bpf;
MyEffect() {
controls = {
Menu("Type", "LPF", "HPF", "BPF"),
Dial("Cutoff", 10, 10000, 1000),
Dial("Resonance", 0.1, 10, root2),
};
}
void process() {
int type = controls[0];
param f = controls[1];
param Q = controls[2];
switch(type){
case 0: in >> lpf(f,Q) >> out; break
case 1: in >> hpf(f,Q) >> out; break
case 2: in >> bpf(f,Q) >> out; break
}
}
};
Custom Filter (basic IIR)
struct LPF : Modifier {
param a, b;
void set(param coeff) {
a = coeff;
b = 1 - a;
}
void process() {
(a * in) + (b * out) >> out;
}
};
struct MyEffect : Effect {
LPF lpf;
MyEffect() {
controls = {
Dial("Cutoff", 0.0, 1.0, 0.5),
};
}
void process() {
param c = controls[0];
in >> lpf(c) >> out;
}
};
Wah-wah Effect
struct MyEffect : Effect {
LPF lpf;
Sine lfo;
WahWah() {
controls = {
Dial("f", 10, 10000, 1000),
Dial("Q", 0.1, 10, 1),
Dial("Rate", 4, 10, 6),
};
}
void process() {
param f = controls[0];
param Q = controls[1];
param rate = controls[2];
signal mod = lfo(rate) * 0.5 + 0.5f;
in >> lpf(mod * f, Q) >> out;
}
};
Filter Bands
struct Bands : Effect {
BPF filter1;
BPF filter2;
Bands() {
controls = {
Dial("Band1 - f", 10, 1000, 100),
Dial("Band1 - Q", 0.1, 10, root2),
Dial("Band2 - f", 10, 1000, 500),
Dial("Band2 - Q", 0.1, 10, root2),
};
}
void process() {
param gain = controls[0];
signal band1 = in >> filter1(controls[0], controls[1]);
signal band2 = in >> filter2(controls[2], controls[3]);
band1 + band2 >> out;
}
};
3-Band Equaliser (EQ)
struct MyEffect : Effect {
LPF lpf;
HPF hpf;
EQ() {
controls = {
Dial("Low", 0.0, 1.0, 0.5),
Dial("Mid", 0.0, 1.0, 0.5),
Dial("High", 0.0, 1.0, 0.5),
};
}
void prepare() {
lpf.set(200);
hpf.set(4000);
}
void process() {
signal lows = in >> lpf;
signal highs = in >> hpf;
signal mids = in - (lows + highs);
lows * sqr(controls[0]) + mids * sqr(controls[1]) + highs * sqr(controls[2]) >> out;
}
};

Delay

Basic Echo
struct MyEffect : Effect {
Delay<192000> delay; // max. 1s @ 192kHz
MyEffect() {
controls = {
Dial("Delay", 0.0, 1.0, 0.5),
Dial("Gain", 0.0, 1.0, 0.5),
};
}
void process() {
param time = controls[0] * fs;
param gain = controls[1];
in >> delay;
in + delay(time) * gain >> out;
}
};
Echo with Feedback
struct MyEffect : Effect {
Delay<192000> delay; // max. 1s @ 192kHz
MyEffect() {
controls = {
Dial("Delay", 0.0, 1.0, 0.5),
Dial("Gain", 0.0, 1.0, 0.5),
};
}
void process() {
param time = controls[0] * fs;
param gain = controls[1];
in + delay(time) * gain >> out;
delay << out; // feedback delay
}
};
Stereo Delay (ping-pong)
struct MyEffect : Stereo::Effect {
Stereo::Delay<192000> delay;
MyEffect() {
controls = {
Dial("Delay L", 0.0, 1.0, 0.25),
Dial("Feedback L", 0.0, 1.0, 0.5),
Dial("Delay R", 0.0, 1.0, 0.5),
Dial("Feedback R", 0.0, 1.0, 0.5),
};
}
void process() {
stereo::signal time = { controls[0], controls[1] };
stereo::signal gain = { controls[1], controls[3] };
stereo::signal feedback = delay(time * fs) * gain;
in.l + feedback.r >> out.l;
in.r + feedback.l >> out.r;
delay << out;
}
};
Patterned Delay
struct MyEffect : Effect {
Delay<192000> delay;
MyEffect() {
controls = {
Menu("Pattern", "1", "2", "3"),
};
}
void process() {
param times[3][3] = {
{ 0.5f, 1.0f, 1.5f }, // Pattern 1
{ 0.25f,0.5f, 1.0f }, // Pattern 2
{ 0.5f, .75f, 1.0f }, // Pattern 3
};
param gains[3][3] = {
{ .75f, 0.5f, .25f },
{ .25f, 0.5f, .75f },
{ .25f, 0.5f, .25f },
};
const int p = controls[0]; // selected pattern
signal mix = in;
for(int d=0; d<3; d++)
mix += delay(times[p][d] * fs) * gains[p][d];
mix >> out;
}
};
Basic Reverb
struct MyEffect : Effect {
Delay<192000> feedforward, feedback;
LPF filter;
const param times[8] =
{ 2.078, 5.154, 5.947, 7.544, 8.878, 10.422, 13.938, 17.140 };
const param gains[8] =
{ .609, .262, -.360, -.470, .290, -.423, .100, .200 };
Reverb() {
controls = {
Dial("Resonance", 0, 0.5, 0.4),
Dial("Room Size", 0, 0.4, 0.1),
Dial("Brightness", 500, 5000, 1500),
};
}
void prepare() {
filter.set(controls[2]);
}
// early reflections
signal early() {
in >> feedforward;
signal mix = in;
for(int d=0; d<8; d++)
mix += feedforward(times[d] * fs/1000) * gains[d];
return mix;
}
// late reflections
signal late() {
return controls[0] * feedback((controls[1]) * fs) >> filter;
}
void process() {
early() + late() >> out >> feedback;
}
};
Stereo Reverb
struct MyEffect : Stereo::Effect {
Delay<192000> feedforward[2];
Delay<192000> feedback[2];
LPF filter[2];
param times[2][8] =
{ 2.078, 5.154, 5.947, 7.544, 8.878, 10.422, 13.938, 17.140 };
param gains[8] =
{ .609, .262, -.360, -.470, .290, -.423, .100, .200 };
MyEffect() {
controls = {
Dial("Resonance", 0, 0.5, 0.4),
Dial("Room Size", 0, 0.4, 0.2),
Dial("Brightness", 500, 5000, 2250),
};
for(int t=0; t<8; t++)
times[1][t] = times[0][t] * (1.f - 0.2f * gains[t]);
}
void prepare() {
filter[0].set(controls[2]);
filter[1].set(controls[2]);
}
// early reflections
signal early(int chn) {
in[chn] >> feedforward[chn];
signal mix = in[chn];
for(int t=0; t<8; t++)
mix += feedforward[chn](times[chn][t] * fs/1000) * gains[t];
return mix;
}
// early reflections
signal late(int chn) {
return controls[0] * feedback[chn]((controls[1] + 0.01232 * chn) * fs) >> filter[chn];
}
void process() {
early(0) + late(0) >> out.l >> feedback[0];
early(1) + late(1) >> out.r >> feedback[1];
}
};

Modulation

Mod Delay / Vibrato
struct MyEffect : Effect {
Delay<192000> delay;
Sine lfo;
MyEffect() {
controls = {
Dial("Mod Rate", 1, 10, 6),
Dial("Mod Depth", 0.0, 1.0, 0.2),
};
}
void process() {
param rate = controls[0];
param depth = cube(controls[1].smooth()) / 10.f;
signal mod = lfo(rate) * depth + depth;
(in >> delay)(mod * fs) >> out;
}
};
Flanger
struct MyEffect : Effect {
Delay<192000> delay;
Triangle lfo;
Flanger() {
controls = {
Dial("Mod Rate", 0.1, 1.0, 0.75),
Dial("Mod Depth", 0.1, 5.0, 1.5),
};
}
void process() {
param rate = controls[0];
param depth = controls[1] / 1000.f;
signal mod = lfo(rate) * depth + depth;
in + (in >> delay)(mod * fs) >> out;
}
};
Chorus
struct MyEffect : Effect {
Delay<192000> delay;
Sine lfo[3];
MyEffect() {
controls = {
Dial("Mod Rate", 1, 10, 6),
Dial("Mod Depth", 0.0, 1.0, 0.1),
};
}
signal mod(int m){
const param rates[3] = { 2.5,3,3.5 };
const param depths[3] = { 0.45, 0.5, 0.55 };
return (lfo[m](rates[m]) * depths[m] + depths[m]) * fs / 1000.f;
}
void process() {
in >> delay;
0.5f * (in + delay(mod(0)) + delay(mod(1)) + delay(mod(2))) >> out;
}
};

Synthesis Techniques

(coming soon)