AtlatestRepositorysigil-dsp

sigil-dsp / tree / src / cfx4.h

1/*
2 * fx4.h - The tracker fatteners: chorus, crush, compressor
3 *
4 * Three small mono effects written for motif's DSP graph. All parameters
5 * that a tracker effects column would want to move are signal-rate
6 * 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 dry
9 * signal. compute(in, rate_hz, depth_ms, mix)
10 * sp_crush tanh drive, then bit-depth quantise, then sample-and-hold
11 * rate reduction. compute(in, drive, bits, rate_div)
12 * sp_comp feed-forward peak compressor with a one-pole attack/release
13 * envelope. compute(in, threshold_db, ratio); attack, release
14 * and makeup gain are init-time; makeup is applied even at
15 * ratio 1, and a ratio below 1 is a bypass, not expansion.
16 *
17 * Deterministic: no randomness, no libm on the per-sample path except
18 * tanhf in the crush drive stage and the dB conversions in the compressor
19 * (both computed from float inputs the same way on every target).
20 */
22#ifndef SIGIL_DSP_FX4_H
23#define SIGIL_DSP_FX4_H
25#include "soundpipe.h"
27/* ---- chorus ---- */
29#define SP_CHORUS_MAX_MS 40.0f
31typedef struct sp_chorus {
32 SPFLOAT *buf;
33 int bufsize;
34 int pos;
35 SPFLOAT lfo_phase; /* 0..1 */
36 SPFLOAT sr;
37} sp_chorus;
39int sp_chorus_create(sp_chorus **p);
40int sp_chorus_destroy(sp_chorus **p);
41int 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 */
43int sp_chorus_compute(sp_data *sp, sp_chorus *p, SPFLOAT in, SPFLOAT rate,
44 SPFLOAT depth, SPFLOAT mix, SPFLOAT *out);
46/* ---- crush ---- */
48typedef struct sp_crush {
49 SPFLOAT held; /* last sampled value for rate reduction */
50 SPFLOAT counter; /* samples since last hold */
51} sp_crush;
53int sp_crush_create(sp_crush **p);
54int sp_crush_destroy(sp_crush **p);
55int sp_crush_init(sp_data *sp, sp_crush *p);
56/* drive >= 0 (0 = clean), bits 1..16 (16 = no quantisation), rate_div >= 1
57 * (1 = no rate reduction; N = hold every value for N samples) */
58int sp_crush_compute(sp_data *sp, sp_crush *p, SPFLOAT in, SPFLOAT drive,
59 SPFLOAT bits, SPFLOAT rate_div, SPFLOAT *out);
61/* ---- compressor ---- */
63typedef 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;
74int sp_comp_create(sp_comp **p);
75int sp_comp_destroy(sp_comp **p);
76int 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) */
79int sp_comp_compute(sp_data *sp, sp_comp *p, SPFLOAT in, SPFLOAT threshold_db,
80 SPFLOAT ratio, SPFLOAT *out);
82#endif