psyn/voice.c

134 lines
3.2 KiB
C
Raw Normal View History

2010-01-13 10:35:51 +00:00
#include <stdint.h>
#include <stdbool.h>
#include <math.h>
#include "osc.h"
#include "env.h"
#include "filter.h"
2010-01-20 07:49:38 +00:00
#include "control.h"
2010-01-21 08:36:18 +00:00
#include "voice.h"
2010-01-20 07:49:38 +00:00
#include "engine.h"
2010-01-13 10:35:51 +00:00
#include "psyn.h"
#include "rng.h"
2010-01-20 07:49:38 +00:00
static inline double max(double a, double b)
{
return a > b ? a : b;
}
void voice_init(struct voice_t *voice, double freq)
{
2010-01-20 07:49:38 +00:00
uint8_t i;
// filter_init_rc(&voice->fil[0], 1000.0, 0.000000047);
// filter_init_rc(&voice->fil[1], 47000.0, 0.000000047);
2010-01-20 07:49:38 +00:00
// 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++) {
2010-01-21 08:36:18 +00:00
voice->osc[i].shape = _engine.params[i].shape.value;
voice->osc[i].level = _engine.params[i].level.value;
2010-01-21 08:36:18 +00:00
osc_setfreq(&voice->osc[i], freq * _engine.params[i].freq_mult.value);
osc_setphase(&voice->osc[i], _engine.params[i].phase.value);
}
}
2010-01-13 10:35:51 +00:00
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;
2010-01-21 08:36:18 +00:00
int i;
double a[VOICE_OSCILLATORS];
double l = 0.0;
double r = 0.0;
2010-01-13 10:35:51 +00:00
//for (pos = 0; pos < samples; pos++) {
voice_tick(voice);
2010-01-21 08:36:18 +00:00
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;
}
2010-01-13 10:35:51 +00:00
if (amplitude <= 0.0001) {
voice->playing = false;
return;
}
2010-01-21 08:36:18 +00:00
for (i = 0; i < VOICE_OSCILLATORS; i++) {
2010-01-21 17:40:30 +00:00
float ss;
float pl = osc_getsample(&voice->osc[i]);
float pr = pl;
2010-01-21 08:36:18 +00:00
// Mix
2010-01-21 17:40:30 +00:00
switch (_engine.params[i].pan_type) {
case PAN_FIXED:
pl *= _engine.params[i].pan_level;
pr *= _engine.params[i].pan_level_r;
break;
case PAN_OSC:
ss = osc_getsample(&voice->osc[_engine.params[i].pan_source]) * _engine.params[i].pan_level * 0.5;
pl *= 0.5 + ss;
pr *= 0.5 - ss;
break;
case PAN_LFO:
ss = osc_getsample(&_engine.lfo[_engine.params[i].pan_source]) * _engine.params[i].pan_level * 0.5;
pl *= 0.5 + ss;
pr *= 0.5 - ss;
break;
}
l += a[i] * pl;
r += a[i] * pr;
2010-01-21 08:36:18 +00:00
}
2010-01-20 07:49:38 +00:00
// 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);
// }
2010-01-13 10:35:51 +00:00
2010-01-20 07:49:38 +00:00
// *left += l;
// *right += r;
2010-01-13 10:35:51 +00:00
2010-01-20 07:49:38 +00:00
double out_l, out_r;
2010-01-21 08:36:18 +00:00
double cutoff = max(env_getamplitude(&_engine.cutoff_env, voice->sample, 0), _engine.aftertouch.value) * 8000.0;
2010-01-20 07:49:38 +00:00
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);
2010-01-13 10:35:51 +00:00
2010-01-20 07:49:38 +00:00
*left += out_l;
*right += out_r;
// *left += voice->fil[0].last_out_l;
// *right += voice->fil[0].last_out_r;
2010-01-13 10:35:51 +00:00
// }
}