Skip to content
Closed
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
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@ LDLIBS = -lm
PYTHON = python3
PLAY = ffplay -v fatal -nodisp -autoexit -f s32le -ar 48000 -ch_layout mono -i pipe:0

effects = flanger echo fm phaser discont am distortion
effects = flanger echo fm phaser discont am distortion chorus
flanger_defaults = 0.6 0.6 0.6 0.6
echo_defaults = 0.3 0.3 0.3 0.3
fm_defaults = 0.25 0.25 0.5 0.5
am_defaults = 0.5 0.5 0.5 0.5
phaser_defaults = 0.3 0.3 0.5 0.5
discont_defaults = 0.8 0.1 0.2 0.2
distortion_defaults = 0.5 0.6 0.8 0.0
chorus_defaults = 0.3 0.4 0.5 0.7

HEADERS = biquad.h discont.h distortion.h echo.h effect.h flanger.h fm.h gensin.h lfo.h phaser.h util.h process.h
HEADERS = biquad.h chorus.h discont.h distortion.h echo.h effect.h flanger.h fm.h gensin.h lfo.h phaser.h process.h util.h

default:
@echo "Pick one of" $(effects)
Expand Down
67 changes: 67 additions & 0 deletions chorus.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//
// Chorus effect - multiple voices with modulated delays
//
// Creates a thicker sound by mixing the original signal with
// multiple slightly detuned copies using LFO-modulated delays.
//
static struct {
struct lfo_state lfo1, lfo2, lfo3;
float delay_ms;
float depth;
float mix;
} chorus;

static inline void chorus_init(float pot1, float pot2, float pot3, float pot4)
{
// pot1: LFO rate (0.1 - 5 Hz)
float rate = 0.1 + pot1 * 4.9;

// Slightly offset rates for each voice to avoid phase lock
set_lfo_freq(&chorus.lfo1, rate);
set_lfo_freq(&chorus.lfo2, rate * 1.1);
set_lfo_freq(&chorus.lfo3, rate * 0.9);

// pot2: base delay (5 - 30 ms)
chorus.delay_ms = 5 + pot2 * 25;

// pot3: depth/modulation amount (0 - 100%)
chorus.depth = pot3;

// pot4: wet/dry mix (0 = dry, 1 = full wet)
chorus.mix = pot4;

fprintf(stderr, "chorus:");
fprintf(stderr, " rate=%g Hz", rate);
fprintf(stderr, " delay=%g ms", chorus.delay_ms);
fprintf(stderr, " depth=%g", pot3);
fprintf(stderr, " mix=%g\n", pot4);
}

static inline float chorus_step(float in)
{
// Store input in delay buffer
sample_array_write(in);

// Get three modulated delay values
float lfo1 = lfo_step(&chorus.lfo1, lfo_sinewave);
float lfo2 = lfo_step(&chorus.lfo2, lfo_sinewave);
float lfo3 = lfo_step(&chorus.lfo3, lfo_sinewave);

float base_samples = chorus.delay_ms * SAMPLES_PER_MSEC;
float mod_range = base_samples * chorus.depth * 0.5;

float d1 = base_samples + lfo1 * mod_range;
float d2 = base_samples + lfo2 * mod_range;
float d3 = base_samples + lfo3 * mod_range;

// Read delayed samples
float v1 = sample_array_read(d1);
float v2 = sample_array_read(d2);
float v3 = sample_array_read(d3);

// Mix voices (average of three delayed signals)
float wet = (v1 + v2 + v3) / 3.0f;

// Blend dry and wet
return in * (1.0f - chorus.mix) + wet * chorus.mix;
}
2 changes: 2 additions & 0 deletions convert.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "phaser.h"
#include "discont.h"
#include "distortion.h"
#include "chorus.h"

static void magnitude_init(float pot1, float pot2, float pot3, float pot4) {}
static float magnitude_step(float in) { return u32_to_fraction(magnitude); }
Expand All @@ -36,6 +37,7 @@ struct effect {
EFF(echo),
EFF(flanger),
EFF(phaser),
EFF(chorus),

/* "Helper" effects */
EFF(am),
Expand Down