35 lines
1.4 KiB
C
35 lines
1.4 KiB
C
#include "synth.h"
|
|
#include <math.h>
|
|
#define SAMPLE_RATE 44100.0f
|
|
|
|
void play_note(Note *note, int16_t *buffer, int buffer_size) {
|
|
for (int i = 0; i < buffer_size; i++) {
|
|
// update phase counter
|
|
note->phase = fmodf(note->phase + note->freq / SAMPLE_RATE, 1.0f);
|
|
|
|
// oscillator
|
|
float sample = 0.0f;
|
|
switch (note->form) {
|
|
case WAVE_SINE: sample = sinf(2.0f * (float) M_PI * note->phase); break;
|
|
case WAVE_SAW: sample = 2.0f * note->phase - 1.0f; break;
|
|
case WAVE_SQUARE: sample = note->phase < 0.5f ? 1.0f : -1.0f; break;
|
|
case WAVE_TRIANGLE: sample = 4.0f * fabsf(note->phase - 0.5f) - 1.0f; break;
|
|
default: break;
|
|
}
|
|
|
|
//note->lp += note->filter_cutoff * (sample - note->lp);
|
|
//sample = note->lp;
|
|
|
|
// basic attack / release
|
|
// convert attack / release time to a number of steps to reach target gain
|
|
float attack_step = 0.2f / ((note->attack_ms / 1000.0f) * SAMPLE_RATE);
|
|
float release_step = 0.2f / ((note->release_ms / 1000.0f) * SAMPLE_RATE);
|
|
note->gain = note->is_playing
|
|
? fminf(note->gain + attack_step, 0.2f) // attack
|
|
: fmaxf(note->gain - release_step, 0); // release
|
|
|
|
// convert sample to 16-bit signed integer and apply gain
|
|
buffer[i] = (int16_t) (note->gain * sample * (float) INT16_MAX);
|
|
}
|
|
}
|