psyn/voice.c

124 lines
2.9 KiB
C

#include <stdint.h>
#include <stdbool.h>
#include <math.h>
#include "osc.h"
#include "env.h"
#include "filter.h"
#include "voice.h"
#include "control.h"
#include "engine.h"
#include "psyn.h"
#include "rng.h"
static inline double max(double a, double b)
{
return a > b ? a : b;
}
void voice_init(struct voice_t *voice, double freq)
{
uint8_t i;
// filter_init_rc(&voice->fil[0], 1000.0, 0.000000047);
// filter_init_rc(&voice->fil[1], 47000.0, 0.000000047);
// filter_init_freq(&voice->fil[0], freq);
// filter_init_freq(&voice->fil[1], 150.0);
// bw_filter_init_lp(&voice->bw[0], _engine.lowpass.value, 1.0);
for (i = 0; i < VOICE_OSCILLATORS; i++) {
voice->osc[i].shape = _engine.osc_shape[i].value;
voice->osc[i].level = _engine.osc_level[i].value;
}
osc_setfreq(&voice->osc[0], freq);
osc_setphase(&voice->osc[0], 0.0);
osc_setfreq(&voice->osc[1], freq);// * 1.4983);
osc_setphase(&voice->osc[1], 0.25);
osc_setfreq(&voice->osc[2], freq * 2);
osc_setphase(&voice->osc[2], 0.0);
osc_setfreq(&voice->osc[3], 2500.0);
osc_setphase(&voice->osc[3], 0.0);
}
static inline void voice_tick(struct voice_t *voice)
{
unsigned i;
for (i = 0; i < VOICE_OSCILLATORS; i++) {
osc_tick(voice->osc + i);
}
voice->sample++;
}
void voice_run(struct voice_t *voice, uint32_t samples, float *left, float *right)
{
// uint32_t pos;
double amplitude;
double l;
double r;
//for (pos = 0; pos < samples; pos++) {
voice_tick(voice);
amplitude = env_getamplitude(&_env, voice->sample, voice->released);
if (amplitude <= 0.0001) {
voice->playing = false;
return;
}
amplitude *= voice->velocity;
float s;
s = osc_getsample(&voice->osc[0]);
l = amplitude * s;// * (1.0 + rng() * 0.25);
r = amplitude * s;// * (1.0 + rng() * 0.25);
s = osc_getsample(&voice->osc[1]);
l += amplitude * s;
r += amplitude * s;
s = osc_getsample(&voice->osc[2]);
l += amplitude * s;
r += amplitude * s;
s = osc_getsample(&_engine.osc[0]);
// Amplitude mod
// l *= 1.0 + s;
// r *= 1.0 + s;
// l = s * (1.0 + l);
// r = s * (1.0 + r);
// Ring mod
// l *= s;
// r *= s;
// amplitude = env_getamplitude(&_env2, voice->sample, voice->released) * voice->velocity * voice->velocity * 1.5;
// if (amplitude > 0.0) {
// float s1 = osc_getsample(&voice->osc[1]);
// float s2 = osc_getsample(&voice->osc[2]);
// l += amplitude * s1 * (1.0 + s2 * 0.25);
// r += amplitude * s1 * (1.0 + s2 * 0.25);
// }
// *left += l;
// *right += r;
double out_l, out_r;
double cutoff = max(env_getamplitude(&_env2, voice->sample, 0), _engine.aftertouch.value) * 8000.0;
bw_filter_init_lp(&voice->bw[0], _engine.lowpass.value + cutoff, 1.0);
bw_filter_run(&voice->bw[0], l, r, &out_l, &out_r);
// filter_run_lp(&voice->fil[0], l, r);
// filter_run_hp(&voice->fil[1], voice->fil[0].last_out_l, voice->fil[0].last_out_r);
*left += out_l;
*right += out_r;
// *left += voice->fil[0].last_out_l;
// *right += voice->fil[0].last_out_r;
// }
}