You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
3.2 KiB
135 lines
3.2 KiB
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <math.h>
|
|
#include "osc.h"
|
|
#include "env.h"
|
|
#include "filter.h"
|
|
#include "control.h"
|
|
#include "voice.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, const struct engine_t *engine, 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->params[i].shape.value;
|
|
voice->osc[i].level = engine->params[i].level.value;
|
|
|
|
osc_setfreq(&voice->osc[i], freq * engine->params[i].freq_mult.value);
|
|
osc_setphase(&voice->osc[i], engine->params[i].phase.value);
|
|
}
|
|
}
|
|
|
|
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, const struct engine_t *engine, uint32_t samples, float *left, float *right)
|
|
{
|
|
// uint32_t pos;
|
|
int i;
|
|
double a[VOICE_OSCILLATORS];
|
|
double l = 0.0;
|
|
double r = 0.0;
|
|
|
|
//for (pos = 0; pos < samples; pos++) {
|
|
voice_tick(voice);
|
|
|
|
double amplitude = 0.0;
|
|
for (i = 0; i < VOICE_OSCILLATORS; i++) {
|
|
a[i] = env_getamplitude(&engine->params[i].env, voice->sample, voice->released);
|
|
amplitude += a[i];
|
|
a[i] *= voice->velocity;
|
|
}
|
|
|
|
if (amplitude <= 0.0001) {
|
|
voice->playing = false;
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < VOICE_OSCILLATORS; i++) {
|
|
const struct voice_param_t *params = &engine->params[i];
|
|
float ss;
|
|
float pl = osc_getsample(&voice->osc[i]);
|
|
float pr = pl;
|
|
// Mix
|
|
|
|
switch (params->pan_type) {
|
|
case PAN_FIXED:
|
|
pl *= params->pan_level;
|
|
pr *= params->pan_level_r;
|
|
break;
|
|
case PAN_OSC:
|
|
ss = osc_getsample(&voice->osc[params->pan_source]) * params->pan_level * 0.5;
|
|
pl *= 0.5 + ss;
|
|
pr *= 0.5 - ss;
|
|
break;
|
|
case PAN_LFO:
|
|
ss = osc_getsample(&engine->lfo[params->pan_source]) * params->pan_level * 0.5;
|
|
pl *= 0.5 + ss;
|
|
pr *= 0.5 - ss;
|
|
break;
|
|
}
|
|
|
|
l += a[i] * pl;
|
|
r += a[i] * pr;
|
|
}
|
|
|
|
// 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(&engine->cutoff_env, 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;
|
|
// }
|
|
}
|