forked from klang-modular/synthapp
parent
9e07cb5103
commit
2ca29337c3
24 changed files with 531 additions and 135 deletions
@ -0,0 +1,36 @@ |
||||
#ifndef __DELAYLINE_H__ |
||||
#define __DELAYLINE_H__ |
||||
|
||||
#include <cstddef> |
||||
|
||||
#include "frame.h" |
||||
|
||||
template <size_t CAPACITY> |
||||
class DelayLine { |
||||
private: |
||||
const size_t size; |
||||
frame samples[CAPACITY] = {{0, 0}}; |
||||
size_t cursor; |
||||
|
||||
public: |
||||
DelayLine(size_t size = CAPACITY) : size(size) {} |
||||
|
||||
inline frame tick(frame in) { |
||||
samples[cursor++] = in; |
||||
if(cursor == size) { |
||||
cursor = 0; |
||||
} |
||||
return samples[cursor]; |
||||
} |
||||
|
||||
inline frame tap(size_t n) { |
||||
size_t index = cursor + n; |
||||
if(index < size) { |
||||
return samples[index]; |
||||
} else { |
||||
return samples[index - size]; |
||||
} |
||||
} |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,141 @@ |
||||
#ifndef __FRAME_H__ |
||||
#define __FRAME_H__ |
||||
|
||||
struct frame { |
||||
float l; |
||||
float r; |
||||
|
||||
inline frame operator+(const frame& rhs) { |
||||
return { |
||||
.l = l + rhs.l, |
||||
.r = r + rhs.r |
||||
}; |
||||
} |
||||
|
||||
inline frame operator+(float rhs) { |
||||
return { |
||||
.l = l + rhs, |
||||
.r = r + rhs |
||||
}; |
||||
} |
||||
|
||||
inline frame operator-(const frame& rhs) { |
||||
return { |
||||
.l = l - rhs.l, |
||||
.r = r - rhs.r |
||||
}; |
||||
} |
||||
|
||||
inline frame operator-(float rhs) { |
||||
return { |
||||
.l = l - rhs, |
||||
.r = r - rhs |
||||
}; |
||||
} |
||||
|
||||
inline frame operator*(const frame& rhs) { |
||||
return { |
||||
.l = l * rhs.l, |
||||
.r = r * rhs.r |
||||
}; |
||||
} |
||||
|
||||
inline frame operator*(float rhs) { |
||||
return { |
||||
.l = l * rhs, |
||||
.r = r * rhs |
||||
}; |
||||
} |
||||
|
||||
inline frame operator/(const frame& rhs) { |
||||
return { |
||||
.l = l / rhs.l, |
||||
.r = r / rhs.r |
||||
}; |
||||
} |
||||
|
||||
inline frame operator/(float rhs) { |
||||
return { |
||||
.l = l / rhs, |
||||
.r = r / rhs |
||||
}; |
||||
} |
||||
|
||||
inline frame operator+=(const frame& rhs) { |
||||
this->l += rhs.l; |
||||
this->r += rhs.r; |
||||
return *this; |
||||
} |
||||
|
||||
inline frame operator+=(float rhs) { |
||||
this->l += rhs; |
||||
this->r += rhs; |
||||
return *this; |
||||
} |
||||
|
||||
inline frame operator-=(const frame& rhs) { |
||||
this->l -= rhs.l; |
||||
this->r -= rhs.r; |
||||
return *this; |
||||
} |
||||
|
||||
inline frame operator-=(float rhs) { |
||||
this->l -= rhs; |
||||
this->r -= rhs; |
||||
return *this; |
||||
} |
||||
|
||||
inline frame operator*=(const frame& rhs) { |
||||
this->l *= rhs.l; |
||||
this->r *= rhs.r; |
||||
return *this; |
||||
} |
||||
|
||||
inline frame operator*=(float rhs) { |
||||
this->l *= rhs; |
||||
this->r *= rhs; |
||||
return *this; |
||||
} |
||||
|
||||
inline frame operator/=(const frame& rhs) { |
||||
this->l /= rhs.l; |
||||
this->r /= rhs.r; |
||||
return *this; |
||||
} |
||||
|
||||
inline frame operator/=(float rhs) { |
||||
this->l /= rhs; |
||||
this->r /= rhs; |
||||
return *this; |
||||
} |
||||
}; |
||||
|
||||
inline frame operator+(float lhs, const frame& rhs) { |
||||
return { |
||||
lhs + rhs.l, |
||||
lhs + rhs.r |
||||
}; |
||||
} |
||||
|
||||
inline frame operator-(float lhs, const frame& rhs) { |
||||
return { |
||||
lhs + rhs.l, |
||||
lhs + rhs.r |
||||
}; |
||||
} |
||||
|
||||
inline frame operator*(float lhs, const frame& rhs) { |
||||
return { |
||||
lhs * rhs.l, |
||||
lhs * rhs.r |
||||
}; |
||||
} |
||||
|
||||
inline frame operator/(float lhs, const frame& rhs) { |
||||
return { |
||||
lhs / rhs.l, |
||||
lhs / rhs.r |
||||
}; |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,55 @@ |
||||
#ifndef __REVERB_H__ |
||||
#define __REVERB_H__ |
||||
|
||||
// Velvet noise reverb ("Late Reverberation Synthesis Using Filtered Velvet Noise")
|
||||
|
||||
#include <algorithm> |
||||
|
||||
#include "frame.h" |
||||
#include "delayline.h" |
||||
#include "sap.h" |
||||
|
||||
#define REVERB_FRAMES 131072 |
||||
#define REVERB_TAPS 256 |
||||
|
||||
class Reverb { |
||||
private: |
||||
struct Tap { |
||||
size_t lp, rp; |
||||
float lg, rg; |
||||
}; |
||||
|
||||
DelayLine<REVERB_FRAMES> dl; |
||||
Tap taps[REVERB_TAPS]; |
||||
float lpfL = 0.f, lpfR = 0.f; |
||||
float hpfL = 0.f, hpfR = 0.f; |
||||
|
||||
public: |
||||
float mix = 0.25f; |
||||
|
||||
Reverb(); |
||||
|
||||
frame tick(frame in) { |
||||
dl.tick(in); |
||||
|
||||
frame out{0, 0}; |
||||
|
||||
for(Tap& tap : taps) { |
||||
out.l += tap.lg * dl.tap(tap.lp).l; |
||||
out.r += tap.rg * dl.tap(tap.rp).r; |
||||
} |
||||
|
||||
lpfL += 0.1f * (out.l - lpfL); |
||||
lpfR += 0.1f * (out.r - lpfR); |
||||
|
||||
hpfL += 0.05f * (lpfL - hpfL); |
||||
hpfR += 0.05f * (lpfR - hpfR); |
||||
|
||||
out.l = lpfL - hpfL; |
||||
out.r = lpfR - hpfR; |
||||
|
||||
return mix * out + (1 - mix) * in; |
||||
} |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,28 @@ |
||||
#ifndef __SAP_H__ |
||||
#define __SAP_H__ |
||||
|
||||
// Schroeder All-Pass (delay w/feedback)
|
||||
|
||||
#include <cstddef> |
||||
|
||||
#include "delayline.h" |
||||
|
||||
template <size_t CAPACITY> |
||||
class SAP { |
||||
private: |
||||
const size_t size; |
||||
DelayLine<CAPACITY> dl; |
||||
|
||||
public: |
||||
float gain = 0.7; |
||||
|
||||
SAP(size_t size = CAPACITY) : size(size) {} |
||||
|
||||
inline frame tick(frame in) { |
||||
frame fb = in + dl.tap(0) * gain; |
||||
frame out = dl.tick(fb) + fb * -gain; |
||||
return out; |
||||
} |
||||
}; |
||||
|
||||
#endif |
@ -1,41 +0,0 @@ |
||||
#ifndef __FRAME_H__ |
||||
#define __FRAME_H__ |
||||
|
||||
struct frame { |
||||
float left; |
||||
float right; |
||||
|
||||
inline frame operator+(const frame& rhs) { |
||||
return { |
||||
.left = left + rhs.left, |
||||
.right = right + rhs.right |
||||
}; |
||||
} |
||||
|
||||
inline frame operator+=(const frame& rhs) { |
||||
this->left += rhs.left; |
||||
this->right += rhs.right; |
||||
return *this; |
||||
} |
||||
|
||||
inline frame operator*(float rhs) { |
||||
return { |
||||
.left = left * rhs, |
||||
.right = right * rhs |
||||
}; |
||||
} |
||||
|
||||
inline frame operator+=(float rhs) { |
||||
this->left += rhs; |
||||
this->right += rhs; |
||||
return *this; |
||||
} |
||||
|
||||
inline frame operator*=(float rhs) { |
||||
this->left *= rhs; |
||||
this->right *= rhs; |
||||
return *this; |
||||
} |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,16 @@ |
||||
#include <cmath> |
||||
|
||||
#include "synth/dsp/reverb.h" |
||||
|
||||
Reverb::Reverb() { |
||||
size_t interval = REVERB_FRAMES / REVERB_TAPS - 4096 / REVERB_TAPS; |
||||
for(size_t tap = 0; tap < REVERB_TAPS; ++tap) { |
||||
float gain = exp2f(-8.f + 8.f * tap / (REVERB_TAPS - 1)); |
||||
taps[tap] = { |
||||
.lp = tap * interval + (rand() % interval), |
||||
.rp = tap * interval + (rand() % interval), |
||||
.lg = (rand() > RAND_MAX / 2 ? 1 : -1) * gain, |
||||
.rg = (rand() > RAND_MAX / 2 ? 1 : -1) * gain |
||||
}; |
||||
} |
||||
} |
Loading…
Reference in new issue