From ce6a4d9ae541ec0422fd1af28422722f3f09e359 Mon Sep 17 00:00:00 2001 From: HiveBeats Date: Tue, 27 Jun 2023 02:23:57 +0400 Subject: [PATCH] wip: phase accumulated osc --- main.c | 2 +- oscillator.c | 86 +++++++++++++++++++++++++++++++++++++++++++--------- oscillator.h | 4 +++ 3 files changed, 76 insertions(+), 16 deletions(-) diff --git a/main.c b/main.c index 0f81f21..8eb1e74 100644 --- a/main.c +++ b/main.c @@ -109,7 +109,7 @@ SynthSound note(Synth* synth, int semitone, float beats) { // will change after oscillator starts to be more autonomous for (size_t i = 0; i < synth->oscillators.count; i++) { - synth->oscillators.array[i].freq = hz; + osc_set_freq(&synth->oscillators.array[i], hz); } return freq(duration, synth->oscillators); diff --git a/oscillator.c b/oscillator.c index 62d995b..9e6bd42 100644 --- a/oscillator.c +++ b/oscillator.c @@ -3,6 +3,8 @@ #include "math.h" #include "stdlib.h" +#define TWO_PI 2*SYNTH_PI + static SynthSound get_init_samples(float duration) { size_t sample_count = (size_t)(duration * SAMPLE_RATE); float* samples = malloc(sizeof(float) * sample_count); @@ -23,42 +25,96 @@ static float pos(float hz, float x) { return fmodf(hz * x / SAMPLE_RATE, 1); } -static float sineosc(float hz, float x) { - return sinf(x * (2.f * SYNTH_PI * hz / SAMPLE_RATE)); +static void sine_osc_phase_incr(Oscillator* osc) { + osc->phase += osc->phase_dt; + if (osc->phase >= TWO_PI) + osc->phase -= TWO_PI; +} + +static void saw_osc_phase_incr(Oscillator* osc) { + osc->phase += osc->phase_dt; + if (osc->phase >= 1.0f) + osc->phase -= 1.0f; +} + +static float calc_saw_phase_delta(float freq) { + return freq / SAMPLE_RATE; +} + +static float calc_sine_phase_delta(float freq) { + return (TWO_PI * freq) / SAMPLE_RATE; +} + +static float sineosc(Oscillator* osc) { + float result = sinf(osc->phase); + sine_osc_phase_incr(osc); + return result; } static float sign(float v) { return (v > 0.0) ? 1.f : -1.f; } -static float squareosc(float hz, float x) { - return sign(sineosc(hz, x)); +static float squareosc(Oscillator* osc) { + return sign(sineosc(osc)); } -static float triangleosc(float hz, float x) { - return 1.f - fabsf(pos(hz, x) - 0.5f) * 4.f; +static float triangleosc(Oscillator* osc) { + float result = 1.f - fabsf(osc->phase - 0.5f) * 4.f; + saw_osc_phase_incr(osc); + return result; } -static float sawosc(float hz, float x) { - return pos(hz, x) * 2.f - 1.f; +static float sawosc(Oscillator* osc) { + float result = osc->phase * 2.f - 1.f; + saw_osc_phase_incr(osc); + return result; +} + +void osc_set_freq(Oscillator* osc, float freq) { + osc->freq = freq; + osc->phase = 0; + switch (osc->osc) + { + case Sine: + osc->phase_dt = calc_sine_phase_delta(freq); + break; + case Square: + osc->phase_dt = calc_sine_phase_delta(freq); + break; + case Triangle: + osc->phase_dt = calc_saw_phase_delta(freq); + break; + case Saw: + osc->phase_dt = calc_saw_phase_delta(freq); + break; + default: + break; + } +} + +void osc_reset(Oscillator* osc) { + osc->volume = 0; + osc->phase = 0; + osc->phase_dt = 0; } float multiosc(OscillatorGenerationParameter param) { float osc_sample = 0.f; for (size_t i = 0; i < param.oscillators.count; i++) { - Oscillator osc = param.oscillators.array[i]; - switch (osc.osc) { + Oscillator* osc = ¶m.oscillators.array[i]; + switch (osc->osc) { case Sine: - osc_sample += sineosc(osc.freq, param.sample) * osc.volume; + osc_sample += sineosc(osc) * osc->volume; break; case Triangle: - osc_sample += triangleosc(osc.freq, param.sample) * osc.volume; + osc_sample += triangleosc(osc) * osc->volume; break; case Square: - osc_sample += squareosc(osc.freq, param.sample) * osc.volume; + osc_sample += squareosc(osc) * osc->volume; break; case Saw: - osc_sample += sawosc(osc.freq, param.sample) * osc.volume; + osc_sample += sawosc(osc) * osc->volume; break; } } @@ -68,7 +124,7 @@ float multiosc(OscillatorGenerationParameter param) { SynthSound freq(float duration, OscillatorArray osc) { SynthSound samples = get_init_samples(duration); - + float* output = malloc(sizeof(float) * samples.sample_count); for (int i = 0; i < samples.sample_count; i++) { float sample = samples.samples[i]; diff --git a/oscillator.h b/oscillator.h index 3a886ad..410994b 100644 --- a/oscillator.h +++ b/oscillator.h @@ -14,6 +14,8 @@ typedef struct Oscillator { OscillatorType osc; float freq; float volume; + float phase; + float phase_dt; } Oscillator; typedef struct OscillatorArray { @@ -26,6 +28,8 @@ typedef struct OscillatorGenerationParameter { float sample; } OscillatorGenerationParameter; +void osc_set_freq(Oscillator* osc, float freq); +void osc_reset(Oscillator* osc); float multiosc(OscillatorGenerationParameter param); SynthSound freq(float duration, OscillatorArray osc);