wip: phase accumulated osc
This commit is contained in:
2
main.c
2
main.c
@@ -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);
|
||||||
|
|||||||
84
oscillator.c
84
oscillator.c
@@ -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 = ¶m.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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user