Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ TODO

### use the Bela API instead of recreating in memory redundant functions and variables:

- pi -> M_PI
- twopi
- clamp -> constrain

### separate headers and libraries so that each composition only compiles the necessary code
Expand Down
23 changes: 10 additions & 13 deletions libraries/REBUS/dsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// by Claude Heiland-Allen 2023-06-19
// added float-specialisations 2023-06-27
// added more documentation 2025-12-10
// removed pi/twopi 2026-03-07 (use M_PI instead)

//---------------------------------------------------------------------
// common definitions
Expand All @@ -21,10 +22,6 @@ typedef float sample;
#define SR 44100
#endif

// Mathematical constants.
#define pi 3.141592653589793
#define twopi 6.283185307179586

//---------------------------------------------------------------------
// functions
//---------------------------------------------------------------------
Expand Down Expand Up @@ -192,7 +189,7 @@ static inline sample biquad(BIQUAD *bq, sample x0) {
// Calculate the coefficients for a lowpass biquad filter
// with cutoff frequency 'hz' (in Hz), and q-factor 'q'.
static inline BIQUAD *lowpass(BIQUAD *bq, sample hz, sample q) {
double w0 = hz * twopi / SR;
double w0 = hz * 2*M_PI / SR;
double a = fabs(sin(w0) / (2 * q));
double c = cos(w0);
double b0 = (1 - c) / 2, b1 = 1 - c, b2 = (1 - c) / 2;
Expand All @@ -208,7 +205,7 @@ static inline BIQUAD *lowpass(BIQUAD *bq, sample hz, sample q) {
// Calculate the coefficients for a highpass biquad filter
// with cutoff frequency 'hz' (in Hz), and q-factor 'q'.
static inline BIQUAD *highpass(BIQUAD *bq, sample hz, sample q) {
double w0 = hz * twopi / SR;
double w0 = hz * 2*M_PI / SR;
double a = fabs(sin(w0) / (2 * q));
double c = cos(w0);
double b0 = (1 + c) / 2, b1 = -(1 + c), b2 = (1 + c) / 2;
Expand All @@ -224,7 +221,7 @@ static inline BIQUAD *highpass(BIQUAD *bq, sample hz, sample q) {
// Calculate the coefficients for a bandpass biquad filter
// with center frequency 'hz' (in Hz), and q-factor 'q'.
static inline BIQUAD *bandpass(BIQUAD *bq, sample hz, sample q) {
double w0 = hz * twopi / SR;
double w0 = hz * 2*M_PI / SR;
double a = fabs(sin(w0) / (2 * q));
double c = cos(w0);
double b0 = a, b1 = 0, b2 = -a;
Expand All @@ -240,7 +237,7 @@ static inline BIQUAD *bandpass(BIQUAD *bq, sample hz, sample q) {
// Calculate the coefficients for a notch biquad filter
// with center frequency 'hz' (in Hz), and q-factor 'q'.
static inline BIQUAD *notch(BIQUAD *bq, sample hz, sample q) {
double w0 = hz * twopi / SR;
double w0 = hz * 2*M_PI / SR;
double a = fabs(sin(w0) / (2 * q));
double c = cos(w0);
double b0 = 1, b1 = -2 * c, b2 = 1;
Expand Down Expand Up @@ -270,7 +267,7 @@ typedef struct { double re, im; } VCF;
static inline sample vcf(VCF *s, sample x, sample hz, sample q) {
double qinv = q > 0 ? 1 / q : 0;
double ampcorrect = 2 - 2 / (q + 2);
double cf = hz * twopi / SR;
double cf = hz * 2*M_PI / SR;
if (cf < 0) { cf = 0; }
double r = qinv > 0 ? 1 - cf * qinv : 0;
if (r < 0) { r = 0; }
Expand All @@ -292,7 +289,7 @@ typedef struct { float re, im; } VCFF;
static inline sample vcff(VCFF *s, sample x, sample hz, sample q) {
float qinv = q > 0 ? 1 / q : 0;
float ampcorrect = 2 - 2 / (q + 2);
float cf = hz * twopi / SR;
float cf = hz * 2*M_PI / SR;
if (cf < 0) { cf = 0; }
float r = qinv > 0 ? 1 - cf * qinv : 0;
if (r < 0) { r = 0; }
Expand All @@ -314,7 +311,7 @@ typedef struct { double y; } LOP;
// low pass filter function
// (double precision version for more accuracy, less speed)
static inline sample lop(LOP *s, sample x, sample hz) {
double c = clamp(twopi * hz / SR, 0, 1);
double c = clamp(2*M_PI * hz / SR, 0, 1);
return s->y = mix(x, s->y, 1 - c);
}

Expand All @@ -325,7 +322,7 @@ typedef struct { float y; } LOPF;
// low pass filter function
// (single precision version for more speed, less accuracy)
static inline sample lopf(LOPF *s, sample x, sample hz) {
float c = clamp((float(twopi) / SR) * hz, 0, 1);
float c = clamp((float(2*M_PI) / SR) * hz, 0, 1);
return s->y = mix(s->y, x, c);
}

Expand All @@ -336,7 +333,7 @@ typedef struct { double y; } HIP;
// high pass filter state
// (double precision version for more accuracy, less speed)
static inline sample hip(HIP *s, sample x, sample hz) {
double c = clamp(1 - twopi * hz / SR, 0, 1);
double c = clamp(1 - 2*M_PI * hz / SR, 0, 1);
double n = (1 + c) / 2;
double y = x + c * s->y;
double o = n * (y - s->y);
Expand Down
2 changes: 1 addition & 1 deletion libraries/REBUS/dsp_neon.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ sample4 vcf4(VCF4 *s, const sample4 &x, const sample4 &hz, const sample &q)
// q is scalar, have not yet needed vector version
sample qinv = 1 / q;
sample ampcorrect = 2 - 2 / (q + 2);
sample4 cf = vmulq_n_f32(hz, float(twopi) / SR); // cf = hz * 2 pi / SR
sample4 cf = vmulq_n_f32(hz, float(2*M_PI) / SR); // cf = hz * 2 pi / SR
sample4 one = vmovq_n_f32(1.0f); // one = 1
sample4 r = vsubq_f32(one, vmulq_n_f32(cf, qinv)); // r = 1 - cf * qinv
r = vmaxq_f32(r, vmovq_n_f32(0.0f)); // r = max(r, 0)
Expand Down
6 changes: 3 additions & 3 deletions projects/dub-terrain/dub-terrain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ void COMPOSITION_render(BelaContext *context, struct COMPOSITION *C, int n,
float out[2], const float in[2], const float magnitude, const float phase)
{
static const sample4 prime2pi =
{ 2 * float(twopi), 3 * float(twopi), 5 * float(twopi), 7 * float(twopi) };
{ 2 * float(2*M_PI), 3 * float(2*M_PI), 5 * float(2*M_PI), 7 * float(2*M_PI) };
const sample4 one = vmovq_n_f32(1.0f);

// dry drum sounds
Expand All @@ -109,7 +109,7 @@ void COMPOSITION_render(BelaContext *context, struct COMPOSITION *C, int n,
clock *= clock;
clock *= clock;
// the kick is a sine wave with decaying frequency (chirp)
sample kick = sinf(32 * float(pi) * clock);
sample kick = sinf(32 * float(M_PI) * clock);
// the bass is resonant high pass filtered
sample bass = kick - biquad(&C->bass, kick);
// the sub is resonant low pass filtered
Expand Down Expand Up @@ -157,7 +157,7 @@ void COMPOSITION_render(BelaContext *context, struct COMPOSITION *C, int n,

// waveshaping / mixing
// overall non-feedback gain is based on the REBUS antenna magnitude control
sample gain = 0.5 * sinf(float(pi) * magnitude);
sample gain = 0.5 * sinf(float(M_PI) * magnitude);
sample common = (3 * kick + 2 * bass + 4 * sub) * gain;
// add the four filtered feedbacks to the dry sounds and waveshape
out[0] = sinf(common
Expand Down
34 changes: 17 additions & 17 deletions projects/uneven-terrain/uneven-terrain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ void COMPOSITION_render(BelaContext *context, struct COMPOSITION *C, int n,
hat *= hat;
hat *= hat;
// modulate hi-hat amplitude by magnitude
hat *= clamp(sinf(7 * float(twopi) * m), 0, 1);
hat *= clamp(sinf(7 * float(2*M_PI) * m), 0, 1);
// make hi-hats as high-pass filtered noise in stereo
float hats[2] =
{ hip(&C->hat[0], noise() * hat, 4000)
Expand All @@ -145,10 +145,10 @@ void COMPOSITION_render(BelaContext *context, struct COMPOSITION *C, int n,
// increase gain of attack
snare *= snare + 1;
// modulate snare amplitude by magnitude
snare *= clamp(sinf(6 * float(twopi) * m), 0, 1);
snare *= clamp(sinf(6 * float(2*M_PI) * m), 0, 1);
// make snares as sample-and-hold filtered noise in stereo
// modulate sample-and-hold frequency by magnitude
float snarePitch = mix(1000, 2000, 0.5 * (1.0 - cosf(6 * float(twopi) * m)));
float snarePitch = mix(1000, 2000, 0.5 * (1.0 - cosf(6 * float(2*M_PI) * m)));
float snares[2] =
{ samphold(&C->snare[0], noise(), wrap(snarePitch * clock - 0.25)) * snare
, samphold(&C->snare[1], noise(), wrap(snarePitch * clock + 0.25)) * snare
Expand All @@ -163,7 +163,7 @@ void COMPOSITION_render(BelaContext *context, struct COMPOSITION *C, int n,
kick *= kick;
kick *= kick;
// turn into a sine wave with decaying frequency (chirp)
kick = sinf(16 * float(pi) * kick);
kick = sinf(16 * float(M_PI) * kick);

// bass is kick minus a resonant high pass filter of kick
float bass = kick - biquad(&C->bq[0], kick);
Expand All @@ -173,7 +173,7 @@ void COMPOSITION_render(BelaContext *context, struct COMPOSITION *C, int n,

// comb filter
// frequency of filter is modulated by both magnitude and phase
float fbhz = mix(64, 512, 0.5f * (1 - cosf(5 * float(twopi) * (m + p))));
float fbhz = mix(64, 512, 0.5f * (1 - cosf(5 * float(2*M_PI) * (m + p))));
// read from delay lines
float fb0[2] =
{ delread1(&C->del0, 1000 / fbhz)
Expand All @@ -184,8 +184,8 @@ void COMPOSITION_render(BelaContext *context, struct COMPOSITION *C, int n,
fb0[1] = hip(&C->fb[1], fb0[1], 100);
// rotate in the stereo field modulated by phase
// this is like a matrix-vector multiplication
float co = cosf(float(twopi) * p);
float si = sinf(float(twopi) * p);
float co = cosf(float(2*M_PI) * p);
float si = sinf(float(2*M_PI) * p);
float fb[2] =
{ co * fb0[0] - si * fb0[1]
, si * fb0[0] + co * fb0[1]
Expand All @@ -196,20 +196,20 @@ void COMPOSITION_render(BelaContext *context, struct COMPOSITION *C, int n,
// the inside numbers (modulation coefficients) are different
// this gives stereo effects
out[0] = hip(&C->dc[0], 0.5f * sinf
( ( 3 * sinf(7 * float(twopi) * p) * kick
+ 2 * sinf( 5 * sinf(3 * float(twopi) * p) * bass
+ float(pi) * sinf(3 * float(twopi) * m))
+ 4 * sinf(5 * float(twopi) * m) * sub
+ 6 * sinf(6 * float(twopi) * m) * fb[0]
( ( 3 * sinf(7 * float(2*M_PI) * p) * kick
+ 2 * sinf( 5 * sinf(3 * float(2*M_PI) * p) * bass
+ float(M_PI) * sinf(3 * float(2*M_PI) * m))
+ 4 * sinf(5 * float(2*M_PI) * m) * sub
+ 6 * sinf(6 * float(2*M_PI) * m) * fb[0]
+ snares[0] + hats[0]
) * 0.5f
), 1);
out[1] = hip(&C->dc[1], 0.5f * sinf
( ( 3 * sinf(5 * float(twopi) * p) * kick
+ 2 * sinf( 5 * sinf(4 * float(twopi) * p) * bass
+ float(pi) * sinf(4 * float(twopi) * m))
+ 4 * sinf(7 * float(twopi) * m) * sub
+ 6 * sinf(8 * float(twopi) * m) * fb[1]
( ( 3 * sinf(5 * float(2*M_PI) * p) * kick
+ 2 * sinf( 5 * sinf(4 * float(2*M_PI) * p) * bass
+ float(M_PI) * sinf(4 * float(2*M_PI) * m))
+ 4 * sinf(7 * float(2*M_PI) * m) * sub
+ 6 * sinf(8 * float(2*M_PI) * m) * fb[1]
+ snares[1] + hats[1]
) * 0.5f
), 1);
Expand Down