AtlatestRepositorysigil-dsp
1
/*2
* fx4.h - The tracker fatteners: chorus, crush, compressor3
*4
* Three small mono effects written for motif's DSP graph. All parameters5
* that a tracker effects column would want to move are signal-rate6
* arguments to the compute call; the rest are set at init.7
*8
* sp_chorus two LFO-modulated taps on one delay line, mixed with the dry9
* signal. compute(in, rate_hz, depth_ms, mix)10
* sp_crush tanh drive, then bit-depth quantise, then sample-and-hold11
* rate reduction. compute(in, drive, bits, rate_div)12
* sp_comp feed-forward peak compressor with a one-pole attack/release13
* envelope. compute(in, threshold_db, ratio); attack, release14
* and makeup gain are init-time; makeup is applied even at15
* ratio 1, and a ratio below 1 is a bypass, not expansion.16
*17
* Deterministic: no randomness, no libm on the per-sample path except18
* tanhf in the crush drive stage and the dB conversions in the compressor19
* (both computed from float inputs the same way on every target).20
*/22
#ifndef SIGIL_DSP_FX4_H23
#define SIGIL_DSP_FX4_H25
#include "soundpipe.h"27
/* ---- chorus ---- */29
#define SP_CHORUS_MAX_MS 40.0f31
typedef struct sp_chorus {32
SPFLOAT *buf;33
int bufsize;34
int pos;35
SPFLOAT lfo_phase; /* 0..1 */36
SPFLOAT sr;37
} sp_chorus;39
int sp_chorus_create(sp_chorus **p);40
int sp_chorus_destroy(sp_chorus **p);41
int sp_chorus_init(sp_data *sp, sp_chorus *p);42
/* rate in Hz, depth in ms (peak deviation around a 15 ms centre), mix 0..1 */43
int sp_chorus_compute(sp_data *sp, sp_chorus *p, SPFLOAT in, SPFLOAT rate,44
SPFLOAT depth, SPFLOAT mix, SPFLOAT *out);46
/* ---- crush ---- */48
typedef struct sp_crush {49
SPFLOAT held; /* last sampled value for rate reduction */50
SPFLOAT counter; /* samples since last hold */51
} sp_crush;53
int sp_crush_create(sp_crush **p);54
int sp_crush_destroy(sp_crush **p);55
int sp_crush_init(sp_data *sp, sp_crush *p);56
/* drive >= 0 (0 = clean), bits 1..16 (16 = no quantisation), rate_div >= 157
* (1 = no rate reduction; N = hold every value for N samples) */58
int sp_crush_compute(sp_data *sp, sp_crush *p, SPFLOAT in, SPFLOAT drive,59
SPFLOAT bits, SPFLOAT rate_div, SPFLOAT *out);61
/* ---- compressor ---- */63
typedef struct sp_comp {64
SPFLOAT attack; /* seconds */65
SPFLOAT release; /* seconds */66
SPFLOAT makeup; /* dB */67
SPFLOAT env; /* envelope follower state (linear) */68
SPFLOAT attack_coef;69
SPFLOAT release_coef;70
SPFLOAT makeup_lin;71
SPFLOAT sr;72
} sp_comp;74
int sp_comp_create(sp_comp **p);75
int sp_comp_destroy(sp_comp **p);76
int sp_comp_init(sp_data *sp, sp_comp *p, SPFLOAT attack, SPFLOAT release,77
SPFLOAT makeup_db);78
/* threshold in dBFS (<= 0), ratio >= 1 (1 = no compression) */79
int sp_comp_compute(sp_data *sp, sp_comp *p, SPFLOAT in, SPFLOAT threshold_db,80
SPFLOAT ratio, SPFLOAT *out);82
#endif