diff options
author | Samuel Johnson <[email protected]> | 2025-03-18 12:30:57 -0400 |
---|---|---|
committer | Samuel Johnson <[email protected]> | 2025-03-18 12:30:57 -0400 |
commit | ca7ee50998d59951d46647f0d45258f1a4c21b06 (patch) | |
tree | be1c421b754df49dc756eb69ef70bbf468357067 | |
parent | a2f29c295d3ebbbe733b69de9f7e64a221d1ee25 (diff) |
Add FM synth
-rw-r--r-- | mmband/api/adsr.h | 24 | ||||
-rw-r--r-- | mmband/api/filter.h | 0 | ||||
-rw-r--r-- | mmband/api/instrument.h | 39 | ||||
-rw-r--r-- | mmband/api/lib.h | 14 | ||||
-rw-r--r-- | mmband/instrument.c | 108 | ||||
-rw-r--r-- | mmband/waves/none.c | 7 | ||||
-rw-r--r-- | mmband/waves/saw.c | 6 | ||||
-rw-r--r-- | mmband/waves/sine.c | 6 | ||||
-rw-r--r-- | mmband/waves/square.c | 6 | ||||
-rw-r--r-- | mmband/waves/triangle.c | 6 |
10 files changed, 189 insertions, 27 deletions
diff --git a/mmband/api/adsr.h b/mmband/api/adsr.h index d9a9e1b..62b58d2 100644 --- a/mmband/api/adsr.h +++ b/mmband/api/adsr.h @@ -1,21 +1,23 @@ #ifndef MMBAND_ADSR_H #define MMBAND_ADSR_H +#include <mmband/api/lib.h> + typedef struct adsr *adsr_ref; -adsr_ref adsr_new (); -void adsr_free (adsr_ref adsr); +MMAPI adsr_ref adsr_new (); +MMAPI void adsr_free (adsr_ref adsr); -void adsr_reset (adsr_ref adsr); -void adsr_gate (adsr_ref adsr); -float adsr_tick (adsr_ref adsr); +MMAPI void adsr_reset (adsr_ref adsr); +MMAPI void adsr_gate (adsr_ref adsr); +MMAPI float adsr_tick (adsr_ref adsr); -void adsr_set_attack (adsr_ref adsr, float attack_rate); -void adsr_set_decay (adsr_ref adsr, float decay_rate); -void adsr_set_sustain (adsr_ref adsr, float sustain_level); -void adsr_set_release (adsr_ref adsr, float release_rate); +MMAPI void adsr_set_attack (adsr_ref adsr, float attack_rate); +MMAPI void adsr_set_decay (adsr_ref adsr, float decay_rate); +MMAPI void adsr_set_sustain (adsr_ref adsr, float sustain_level); +MMAPI void adsr_set_release (adsr_ref adsr, float release_rate); -void adsr_set_asc_target (adsr_ref adsr, float target); -void adsr_set_desc_target (adsr_ref adsr, float target); +MMAPI void adsr_set_asc_target (adsr_ref adsr, float target); +MMAPI void adsr_set_desc_target (adsr_ref adsr, float target); #endif diff --git a/mmband/api/filter.h b/mmband/api/filter.h deleted file mode 100644 index e69de29..0000000 --- a/mmband/api/filter.h +++ /dev/null diff --git a/mmband/api/instrument.h b/mmband/api/instrument.h index 3fd07da..bad0d48 100644 --- a/mmband/api/instrument.h +++ b/mmband/api/instrument.h @@ -1,17 +1,25 @@ #ifndef MMBAND_INSTRUMENT_H #define MMBAND_INSTRUMENT_H +#include <mmband/api/lib.h> + enum filter_type { - FILTER_NONE = 0, + FILTER_NONE, FILTER_LOWPASS, FILTER_HIGHPASS, - FILTER_NOTCH, FILTER_LOWSHELF, - FILTER_HIGHSHELF + FILTER_HIGHSHELF, + FILTER_NOTCH +}; + +enum algorithm { + ALGORITHM_NONE, + ALGORITHM_RING, + ALGORITHM_FREQUENCY }; enum osc_type { - OSC_NONE = 0, + OSC_NONE, OSC_SINE, OSC_SQUARE, OSC_TRIANGLE, @@ -21,18 +29,19 @@ enum osc_type { // INSTRUMENT CREATION, TWEAKS typedef struct instrument *instrument_ref; -instrument_ref new_instrument (); -void free_instrument (instrument_ref instrument); -// int set_algorithm (instrument_ref instrument, enum algorithm alg); -int ins_set_osc (instrument_ref instrument, enum osc_type osc); -void ins_set_sample_rate (instrument_ref instrument, int sample_rate); +MMAPI instrument_ref ins_new (); +MMAPI void ins_free (instrument_ref instrument); +// int ins_set_algorithm (instrument_ref instrument, enum algorithm alg); +MMAPI void ins_set_carrier (instrument_ref instrument, enum osc_type osc); +MMAPI void ins_set_modulator (instrument_ref instrument, enum osc_type osc); +// void ins_set_filter (instrument_ref instrument, enum filter_type filter); -// OUTPUT CREATION, TWEAKS -struct audio_out { - float left_phase; - float right_phase; -}; +MMAPI void ins_set_carrier_amplitude (instrument_ref instrument, float amplitude); +MMAPI void ins_set_carrier_frequency (instrument_ref instrument, float amplitude); +MMAPI void ins_set_modulator_amplitude (instrument_ref instrument, float amplitude); +MMAPI void ins_set_frequency_ratio (instrument_ref instrument, float ratio); +MMAPI void ins_set_frequency (instrument_ref instrument, float frequency); -struct audio_out instrument_tick (instrument_ref instrument); +MMAPI float ins_tick (instrument_ref instrument, int sample_rate); #endif diff --git a/mmband/api/lib.h b/mmband/api/lib.h new file mode 100644 index 0000000..5c1f2f8 --- /dev/null +++ b/mmband/api/lib.h @@ -0,0 +1,14 @@ +#ifndef MMBAND_LIB_EXPORTS_H +#define MMBAND_LIB_EXPORTS_H + +#if defined _WIN32 +#if defined mmband_EXPORTS +#define MMAPI __declspec(dllexport) +#else +#define MMAPI __declspec(dllimport) +#endif +#else +#define MMAPI +#endif + +#endif diff --git a/mmband/instrument.c b/mmband/instrument.c index 96a8952..38c7d43 100644 --- a/mmband/instrument.c +++ b/mmband/instrument.c @@ -1,4 +1,110 @@ +#include <math.h> +#include <stdlib.h> + #include <mmband/api/instrument.h> #include <mmband/api/adsr.h> -struct instrument { }; +#include <mmband/waves/waveform.h> + +struct oscillation { + enum osc_type type; + + float frequency; + float phase; + float amplitude; +}; + +struct instrument { + struct oscillation carrier; + struct oscillation modulator; + + float frequency_ratio; +}; + +float osc_tick (struct oscillation *osc, int sample_rate) { + float sample = 0.0; + + switch (osc->type) { + case OSC_NONE: + sample = osc->amplitude * none(osc->phase); + break; + case OSC_SINE: + sample = osc->amplitude * sine(osc->phase); + break; + case OSC_SQUARE: + sample = osc->amplitude * square(osc->phase); + break; + case OSC_SAW: + sample = osc->amplitude * saw(osc->phase); + break; + case OSC_TRIANGLE: + sample = osc->amplitude * triangle(osc->phase); + break; + } + + osc->phase = fmod(osc->phase + osc->frequency * 2.0 * M_PI / sample_rate, 2.0 * M_PI); + return sample; +} + +// Currently default to ring modulation +// TODO: add others +float modulate (struct oscillation *carrier, struct oscillation *modulator, int sample_rate) { + return osc_tick(carrier, sample_rate) * osc_tick(modulator, sample_rate); +} + +instrument_ref ins_new () { + instrument_ref instrument = malloc(sizeof(struct instrument)); + + instrument->frequency_ratio = 1.0; + + instrument->carrier.type = OSC_SINE; + instrument->carrier.amplitude = 0.0; + instrument->carrier.frequency = 0.0; + instrument->carrier.phase = 0.0; + + instrument->modulator.type = OSC_SINE; + instrument->carrier.amplitude = 0.0; + instrument->carrier.frequency = 0.0; + instrument->carrier.phase = 0.0; + + return instrument; +} + +void ins_free (instrument_ref instrument) { + free(instrument); +} + +void ins_set_carrier (instrument_ref instrument, enum osc_type osc) { + instrument->carrier.type = osc; + instrument->carrier.amplitude = 0.0; + instrument->carrier.frequency = 0.0; + instrument->carrier.phase = 0.0; +} + +void ins_set_modulator (instrument_ref instrument, enum osc_type osc) { + instrument->modulator.type = osc; + instrument->modulator.amplitude = 0.0; + instrument->modulator.frequency = 0.0; + instrument->modulator.phase = 0.0; +} + +void ins_set_carrier_amplitude (instrument_ref instrument, float amplitude) { + instrument->carrier.amplitude = amplitude; +} + +void ins_set_modulator_aplitude (instrument_ref instrument, float amplitude) { + instrument->modulator.amplitude = amplitude; +} + +void ins_set_frequency_ratio (instrument_ref instrument, float frequency_ratio) { + instrument->frequency_ratio = frequency_ratio; +} + +void ins_set_frequency (instrument_ref instrument, float frequency) { + instrument->carrier.frequency = frequency; + instrument->modulator.frequency = frequency * instrument->frequency_ratio; +} + +float ins_tick (instrument_ref instrument, int sample_rate) { + return modulate(&instrument->carrier, &instrument->modulator, sample_rate); +} diff --git a/mmband/waves/none.c b/mmband/waves/none.c index e69de29..110dc1c 100644 --- a/mmband/waves/none.c +++ b/mmband/waves/none.c @@ -0,0 +1,7 @@ +#include <mmband/waves/waveform.h> + +float zero (float phase) { + (void) phase; + + return 0.0; +} diff --git a/mmband/waves/saw.c b/mmband/waves/saw.c index e69de29..4ce7663 100644 --- a/mmband/waves/saw.c +++ b/mmband/waves/saw.c @@ -0,0 +1,6 @@ +#include <math.h> +#include <mmband/waves/waveform.h> + +float saw (float phase) { + return -1.0 - (2.0 * fmod(phase / M_PI, 1.0)); +} diff --git a/mmband/waves/sine.c b/mmband/waves/sine.c index e69de29..52cf157 100644 --- a/mmband/waves/sine.c +++ b/mmband/waves/sine.c @@ -0,0 +1,6 @@ +#include <math.h> +#include <mmband/waves/waveform.h> + +float sine (float phase) { + return sinf(phase); +} diff --git a/mmband/waves/square.c b/mmband/waves/square.c index e69de29..97ad5e9 100644 --- a/mmband/waves/square.c +++ b/mmband/waves/square.c @@ -0,0 +1,6 @@ +#include <math.h> +#include <mmband/waves/waveform.h> + +float square (float phase) { + return (phase <= M_PI) ? 1.0 : -1.0; +} diff --git a/mmband/waves/triangle.c b/mmband/waves/triangle.c index e69de29..bf805ed 100644 --- a/mmband/waves/triangle.c +++ b/mmband/waves/triangle.c @@ -0,0 +1,6 @@ +#include <math.h> +#include <mmband/waves/waveform.h> + +float triangle (float phase) { + return (acosf(sinf(phase))) / M_PI; +} |