wip: phase accumulated osc

This commit is contained in:
2023-06-27 02:23:57 +04:00
parent 2918cac022
commit ce6a4d9ae5
3 changed files with 76 additions and 16 deletions

2
main.c
View File

@@ -109,7 +109,7 @@ SynthSound note(Synth* synth, int semitone, float beats) {
// will change after oscillator starts to be more autonomous // will change after oscillator starts to be more autonomous
for (size_t i = 0; i < synth->oscillators.count; i++) { 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); return freq(duration, synth->oscillators);

View File

@@ -3,6 +3,8 @@
#include "math.h" #include "math.h"
#include "stdlib.h" #include "stdlib.h"
#define TWO_PI 2*SYNTH_PI
static SynthSound get_init_samples(float duration) { static SynthSound get_init_samples(float duration) {
size_t sample_count = (size_t)(duration * SAMPLE_RATE); size_t sample_count = (size_t)(duration * SAMPLE_RATE);
float* samples = malloc(sizeof(float) * sample_count); 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); return fmodf(hz * x / SAMPLE_RATE, 1);
} }
static float sineosc(float hz, float x) { static void sine_osc_phase_incr(Oscillator* osc) {
return sinf(x * (2.f * SYNTH_PI * hz / SAMPLE_RATE)); 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) { static float sign(float v) {
return (v > 0.0) ? 1.f : -1.f; return (v > 0.0) ? 1.f : -1.f;
} }
static float squareosc(float hz, float x) { static float squareosc(Oscillator* osc) {
return sign(sineosc(hz, x)); return sign(sineosc(osc));
} }
static float triangleosc(float hz, float x) { static float triangleosc(Oscillator* osc) {
return 1.f - fabsf(pos(hz, x) - 0.5f) * 4.f; 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) { static float sawosc(Oscillator* osc) {
return pos(hz, x) * 2.f - 1.f; 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 multiosc(OscillatorGenerationParameter param) {
float osc_sample = 0.f; float osc_sample = 0.f;
for (size_t i = 0; i < param.oscillators.count; i++) { for (size_t i = 0; i < param.oscillators.count; i++) {
Oscillator osc = param.oscillators.array[i]; Oscillator* osc = &param.oscillators.array[i];
switch (osc.osc) { switch (osc->osc) {
case Sine: case Sine:
osc_sample += sineosc(osc.freq, param.sample) * osc.volume; osc_sample += sineosc(osc) * osc->volume;
break; break;
case Triangle: case Triangle:
osc_sample += triangleosc(osc.freq, param.sample) * osc.volume; osc_sample += triangleosc(osc) * osc->volume;
break; break;
case Square: case Square:
osc_sample += squareosc(osc.freq, param.sample) * osc.volume; osc_sample += squareosc(osc) * osc->volume;
break; break;
case Saw: case Saw:
osc_sample += sawosc(osc.freq, param.sample) * osc.volume; osc_sample += sawosc(osc) * osc->volume;
break; break;
} }
} }
@@ -68,7 +124,7 @@ float multiosc(OscillatorGenerationParameter param) {
SynthSound freq(float duration, OscillatorArray osc) { SynthSound freq(float duration, OscillatorArray osc) {
SynthSound samples = get_init_samples(duration); SynthSound samples = get_init_samples(duration);
float* output = malloc(sizeof(float) * samples.sample_count); float* output = malloc(sizeof(float) * samples.sample_count);
for (int i = 0; i < samples.sample_count; i++) { for (int i = 0; i < samples.sample_count; i++) {
float sample = samples.samples[i]; float sample = samples.samples[i];

View File

@@ -14,6 +14,8 @@ typedef struct Oscillator {
OscillatorType osc; OscillatorType osc;
float freq; float freq;
float volume; float volume;
float phase;
float phase_dt;
} Oscillator; } Oscillator;
typedef struct OscillatorArray { typedef struct OscillatorArray {
@@ -26,6 +28,8 @@ typedef struct OscillatorGenerationParameter {
float sample; float sample;
} OscillatorGenerationParameter; } OscillatorGenerationParameter;
void osc_set_freq(Oscillator* osc, float freq);
void osc_reset(Oscillator* osc);
float multiosc(OscillatorGenerationParameter param); float multiosc(OscillatorGenerationParameter param);
SynthSound freq(float duration, OscillatorArray osc); SynthSound freq(float duration, OscillatorArray osc);