AtlatestRepositorysigil-dsp
1
/*2
* fm4.h - Four-operator phase-modulation FM voice3
*4
* DX/OPL-style: four sine operators, an algorithm table that says which5
* operator modulates which and which operators are carriers, a per-6
* operator frequency ratio, level and linear ADSR, feedback on operator 4,7
* and a global modulation index that scales every modulator's depth.8
*9
* Everything here is deterministic given the parameters and the sample10
* rate: the sine comes from a 4096-entry table with linear interpolation11
* (no libm at run time), so the same inputs produce the same samples on12
* every target that runs the same float arithmetic.13
*14
* Signal-rate inputs (set every sample by the host, motif's render loop):15
* freq base frequency (Hz)16
* gate > 0.5 is on; a rising edge resets phases and retriggers17
* every operator envelope18
* index global modulation index (0 = every carrier is a pure sine)19
* velocity 0..1, scales the index through the velocity curve20
*21
* Per-operator parameters (set at init or with sp_fm4_set_op):22
* ratio frequency multiple of `freq` (coarse + fine folded in)23
* level 0..1 output level (carriers: amplitude; modulators: depth)24
* a d s r attack / decay / release in seconds, sustain 0..125
*/27
#ifndef SIGIL_DSP_FM4_H28
#define SIGIL_DSP_FM4_H30
#include "soundpipe.h"32
#define SP_FM4_OPS 433
#define SP_FM4_ALGORITHMS 835
typedef struct {36
SPFLOAT ratio;37
SPFLOAT level;38
SPFLOAT attack, decay, sustain, release;39
/* state */40
SPFLOAT phase; /* 0..1 */41
SPFLOAT env; /* current envelope value */42
int stage; /* 0 idle, 1 attack, 2 decay, 3 sustain, 4 release */43
SPFLOAT out; /* this sample's output */44
SPFLOAT out_prev; /* previous sample's output (feedback) */45
SPFLOAT out_prev2; /* two samples back (feedback averaging) */46
SPFLOAT rel_rate; /* envelope decrement per sample during release */47
} sp_fm4_op;49
typedef struct sp_fm4 {50
int algorithm; /* 0..SP_FM4_ALGORITHMS-1 */51
SPFLOAT feedback; /* 0..1; 1 = pi radians of self-modulation on op 4 */52
SPFLOAT vel_depth; /* 0..1: how much velocity scales the index */53
SPFLOAT vel_curve; /* exponent applied to velocity (1 = linear) */54
sp_fm4_op op[SP_FM4_OPS];55
int gate_prev;56
SPFLOAT sr;57
} sp_fm4;59
int sp_fm4_create(sp_fm4 **p);60
int sp_fm4_destroy(sp_fm4 **p);61
/* Defaults: algorithm 0, feedback 0, vel_depth 0, vel_curve 1, every62
* operator ratio 1 level 1 ADSR 0.005/0.1/1.0/0.1. */63
int sp_fm4_init(sp_data *sp, sp_fm4 *p);64
int sp_fm4_set_algorithm(sp_fm4 *p, int algorithm);65
int sp_fm4_set_op(sp_fm4 *p, int op, SPFLOAT ratio, SPFLOAT level,66
SPFLOAT attack, SPFLOAT decay, SPFLOAT sustain,67
SPFLOAT release);68
/* One sample. */69
int sp_fm4_compute(sp_data *sp, sp_fm4 *p, SPFLOAT freq, SPFLOAT gate,70
SPFLOAT index, SPFLOAT velocity, SPFLOAT *out);72
/* Algorithm table entries: mod_mask[i] is the bitmask of operators that73
* modulate operator i; carrier_mask is the bitmask of operators summed74
* into the output. Exposed so hosts can print or validate a table. */75
typedef struct {76
const char *name;77
unsigned char mod_mask[SP_FM4_OPS];78
unsigned char carrier_mask;79
} sp_fm4_algorithm;81
const sp_fm4_algorithm *sp_fm4_algorithm_table(void);83
#endif