Oops, lots of changes
parent
a2f4261b7a
commit
2d4ffb346b
53
engine.c
53
engine.c
|
@ -6,11 +6,14 @@
|
|||
#include "osc.h"
|
||||
#include "filter.h"
|
||||
#include "voice.h"
|
||||
#include "control.h"
|
||||
#include "engine.h"
|
||||
#include "psyn.h"
|
||||
|
||||
static double _freqs[128];
|
||||
|
||||
struct engine_t _engine;
|
||||
|
||||
void engine_init()
|
||||
{
|
||||
uint32_t i;
|
||||
|
@ -21,7 +24,14 @@ void engine_init()
|
|||
|
||||
osc_init();
|
||||
env_init(&_env, 0.0125, 0.025, 5.0, 0.0, 0.25);
|
||||
env_init(&_env2, 0.0125, 0.025, 0.5, 0.0, 0.25);
|
||||
env_init(&_env2, 0.0, 0.0, 0.5, 0.0, 0.25);
|
||||
|
||||
osc_setfreq(&_engine.osc[0], 10.0);
|
||||
osc_setfreq(&_engine.osc[1], 2.0);
|
||||
osc_setfreq(&_engine.osc[2], 1.0);
|
||||
_engine.osc[0].level = 1.0;
|
||||
_engine.osc[1].level = 1.0;
|
||||
_engine.osc[2].level = 1.0;
|
||||
}
|
||||
|
||||
void engine_run(struct engine_t *engine, uint32_t samples, float *left, float *right)
|
||||
|
@ -31,14 +41,16 @@ void engine_run(struct engine_t *engine, uint32_t samples, float *left, float *r
|
|||
uint32_t i;
|
||||
|
||||
for (pos = 0; pos < samples; pos++) {
|
||||
control_tick(&_engine.lowpass);
|
||||
|
||||
left[pos] = 0.0;
|
||||
right[pos] = 0.0;
|
||||
|
||||
for (i = 0; i < NUM_LFO; i++) {
|
||||
osc_tick(&engine->osc[i]);
|
||||
osc_tick(&_engine.osc[i]);
|
||||
}
|
||||
|
||||
v = engine->voice;
|
||||
v = _engine.voice;
|
||||
for (i = 0; i < NUM_POLYPHONY; i++, v++) {
|
||||
if (!v->playing) continue;
|
||||
|
||||
|
@ -52,6 +64,19 @@ void engine_startvoice(struct engine_t *engine, uint8_t note, uint8_t velocity)
|
|||
struct voice_t *v = engine->voice;
|
||||
uint32_t i;
|
||||
|
||||
if (engine->monosynth > 0) {
|
||||
/* Constant voice parameters */
|
||||
v->playing = true;
|
||||
if (v->released || engine->monosynth == 1) v->sample = 0;
|
||||
v->released = 0;
|
||||
v->note = note;
|
||||
v->velocity = velocity / 127.0;
|
||||
|
||||
/* Voice parameters which determine sound */
|
||||
voice_init(v, _freqs[note]);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_POLYPHONY; i++, v++) {
|
||||
if (v->playing) continue;
|
||||
|
||||
|
@ -80,3 +105,25 @@ void engine_endvoice(struct engine_t *engine, uint8_t note, uint8_t velocity)
|
|||
v->released = v->sample;
|
||||
}
|
||||
}
|
||||
|
||||
void engine_controlchange(struct engine_t *engine, uint8_t controller, uint8_t value)
|
||||
{
|
||||
printf("Control change %u -> %u\n", controller, value);
|
||||
}
|
||||
|
||||
void engine_programchange(struct engine_t *engine, uint8_t value)
|
||||
{
|
||||
printf("Program change %u\n", value);
|
||||
}
|
||||
|
||||
void engine_aftertouch(struct engine_t *engine, uint8_t value)
|
||||
{
|
||||
// printf("Aftertouch %u\n", value);
|
||||
engine->aftertouch.value = value / 127.0;
|
||||
}
|
||||
|
||||
void engine_pitchchange(struct engine_t *engine, int16_t value)
|
||||
{
|
||||
printf("Pitch %d\n", value);
|
||||
engine->pitchbend.value = value;
|
||||
}
|
||||
|
|
17
engine.h
17
engine.h
|
@ -4,11 +4,28 @@
|
|||
|
||||
struct engine_t
|
||||
{
|
||||
struct control_t lowpass;
|
||||
|
||||
struct control_t modwheel;
|
||||
struct control_t pitchbend;
|
||||
struct control_t aftertouch;
|
||||
|
||||
struct control_t osc_shape[4];
|
||||
struct control_t osc_level[4];
|
||||
|
||||
int monosynth;
|
||||
|
||||
struct osc_t osc[NUM_LFO];
|
||||
struct voice_t voice[NUM_POLYPHONY];
|
||||
};
|
||||
|
||||
extern struct engine_t _engine;
|
||||
|
||||
void engine_init();
|
||||
void engine_run(struct engine_t *engine, uint32_t samples, float *left, float *right);
|
||||
void engine_startvoice(struct engine_t *engine, uint8_t note, uint8_t velocity);
|
||||
void engine_endvoice(struct engine_t *engine, uint8_t note, uint8_t velocity);
|
||||
void engine_controlchange(struct engine_t *engine, uint8_t controller, uint8_t value);
|
||||
void engine_programchange(struct engine_t *engine, uint8_t value);
|
||||
void engine_aftertouch(struct engine_t *engine, uint8_t value);
|
||||
void engine_pitchchange(struct engine_t *engine, int16_t value);
|
||||
|
|
52
filter.c
52
filter.c
|
@ -1,15 +1,18 @@
|
|||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "filter.h"
|
||||
#include "psyn.h"
|
||||
|
||||
void filter_init_rc(struct filter_t *filter, double R, double C)
|
||||
{
|
||||
memset(filter, 0, sizeof *filter);
|
||||
filter->k = 1.0 / (R * C) / _sample_rate;
|
||||
filter->r = 1.0;
|
||||
}
|
||||
|
||||
void filter_init_freq(struct filter_t *filter, double freq)
|
||||
{
|
||||
memset(filter, 0, sizeof *filter);
|
||||
filter->k = (2.0 * M_PI * freq) / _sample_rate;
|
||||
filter->r = 1.0;
|
||||
}
|
||||
|
@ -31,3 +34,52 @@ void filter_run_hp(struct filter_t *filter, double left, double right)
|
|||
filter->last_in_l = left;
|
||||
filter->last_in_r = right;
|
||||
}
|
||||
|
||||
void bw_filter_init_lp(struct bw_filter_t *f, double freq, double resonance)
|
||||
{
|
||||
double c = 1.0 / tan(M_PI * freq / _sample_rate);
|
||||
f->a1 = 1.0 / (1.0 + resonance * c + c * c);
|
||||
f->a2 = 2 * f->a1;
|
||||
f->a3 = f->a1;
|
||||
f->b1 = 2.0 * (1.0 - c * c) * f->a1;
|
||||
f->b2 = (1.0 - resonance * c + c * c) * f->a1;
|
||||
}
|
||||
|
||||
void bw_filter_run(struct bw_filter_t *f, double in_l, double in_r, double *out_l, double *out_r)
|
||||
{
|
||||
*out_l = f->a1 * in_l + f->a2 * f->in1_l + f->a3 * f->in2_l - f->b1 * f->out1_l - f->b2 * f->out2_l;
|
||||
*out_r = f->a1 * in_r + f->a2 * f->in1_r + f->a3 * f->in2_r - f->b1 * f->out1_r - f->b2 * f->out2_r;
|
||||
|
||||
f->in2_l = f->in1_l;
|
||||
f->in1_l = in_l;
|
||||
f->out2_l = f->out1_l;
|
||||
f->out1_l = *out_l;
|
||||
|
||||
f->in2_r = f->in1_r;
|
||||
f->in1_r = in_r;
|
||||
f->out2_r = f->out1_r;
|
||||
f->out1_r = *out_r;
|
||||
}
|
||||
|
||||
/*
|
||||
The filter algo:
|
||||
out(n) = a1 * in + a2 * in(n-1) + a3 * in(n-2) - b1*out(n-1) - b2*out(n-2)
|
||||
|
||||
Lowpass:
|
||||
c = 1.0 / tan(pi * f / sample_rate);
|
||||
|
||||
a1 = 1.0 / ( 1.0 + r * c + c * c);
|
||||
a2 = 2* a1;
|
||||
a3 = a1;
|
||||
b1 = 2.0 * ( 1.0 - c*c) * a1;
|
||||
b2 = ( 1.0 - r * c + c * c) * a1;
|
||||
|
||||
Hipass:
|
||||
c = tan(pi * f / sample_rate);
|
||||
|
||||
a1 = 1.0 / ( 1.0 + r * c + c * c);
|
||||
a2 = -2*a1;
|
||||
a3 = a1;
|
||||
b1 = 2.0 * ( c*c - 1.0) * a1;
|
||||
b2 = ( 1.0 - r * c + c * c) * a1;
|
||||
*/
|
||||
|
|
18
filter.h
18
filter.h
|
@ -1,5 +1,6 @@
|
|||
|
||||
struct filter_t {
|
||||
struct filter_t
|
||||
{
|
||||
double k;
|
||||
double r;
|
||||
double v_l;
|
||||
|
@ -10,7 +11,22 @@ struct filter_t {
|
|||
double last_out_r;
|
||||
};
|
||||
|
||||
struct bw_filter_t
|
||||
{
|
||||
double a1;
|
||||
double a2;
|
||||
double a3;
|
||||
double b1;
|
||||
double b2;
|
||||
|
||||
double in1_l, in2_l, out1_l, out2_l;
|
||||
double in1_r, in2_r, out1_r, out2_r;
|
||||
};
|
||||
|
||||
void filter_init_rc(struct filter_t *filter, double R, double C);
|
||||
void filter_init_freq(struct filter_t *filter, double freq);
|
||||
void filter_run_lp(struct filter_t *filter, double left, double right);
|
||||
void filter_run_hp(struct filter_t *filter, double left, double right);
|
||||
|
||||
void bw_filter_init_lp(struct bw_filter_t *f, double freq, double resonance);
|
||||
void bw_filter_run(struct bw_filter_t *f, double in_l, double in_r, double *out_l, double *out_r);
|
||||
|
|
33
osc.c
33
osc.c
|
@ -3,24 +3,33 @@
|
|||
#include "psyn.h"
|
||||
#include "osc.h"
|
||||
|
||||
double _sin_table[LOOKUP_SAMPLES + 1];
|
||||
double _saw_table[LOOKUP_SAMPLES + 1];
|
||||
double _tri_table[LOOKUP_SAMPLES + 1];
|
||||
double _lookup_table[6][LOOKUP_SAMPLES + 1];
|
||||
|
||||
void osc_init()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= LOOKUP_SAMPLES; i++) {
|
||||
_sin_table[i] = sin(2 * M_PI * (double)i / LOOKUP_SAMPLES);
|
||||
}
|
||||
for (i = 0; i <= LOOKUP_SAMPLES; i++) {
|
||||
_saw_table[i] = 1.0 - ((double)i / (LOOKUP_SAMPLES / 2));
|
||||
}
|
||||
for (i = 0; i <= LOOKUP_SAMPLES; i++) {
|
||||
_tri_table[i] = (double)i / (LOOKUP_SAMPLES / 4);
|
||||
if (_tri_table[i] > 1.0) _tri_table[i] = 2.0 - _tri_table[i];
|
||||
if (_tri_table[i] < -1.0) _tri_table[i] = -2.0 - _tri_table[i];
|
||||
double ph = (double)i / LOOKUP_SAMPLES;
|
||||
|
||||
_lookup_table[0][i] = sin(2.0 * M_PI * ph);
|
||||
|
||||
_lookup_table[1][i] = -1.0 + ph * 2.0;
|
||||
|
||||
if (ph <= 0.25) _lookup_table[2][i] = ph * 4.0;
|
||||
else if (ph <= 0.75) _lookup_table[2][i] = 2.0 - ph * 4.0;
|
||||
else _lookup_table[2][i] = ph * 4.0 - 4.0;
|
||||
|
||||
//if (_tri_table[i] > 1.0) _tri_table[i] = 2.0 - _tri_table[i];
|
||||
//if (_tri_table[i] < -1.0) _tri_table[i] = -2.0 - _tri_table[i];
|
||||
|
||||
_lookup_table[3][i] = (ph >= 0.5) ? -1.0 : 1.0;
|
||||
|
||||
if (ph < 0.5) _lookup_table[4][i] = -1.0 + ph * 4.0;
|
||||
else _lookup_table[4][i] = 1.0 - 2.0 * ph;
|
||||
|
||||
if (ph > 0.5) _lookup_table[5][i] = 1.0 - ph;
|
||||
else _lookup_table[5][i] = -1.0 + 8.0 * ph * ph;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
40
osc.h
40
osc.h
|
@ -1,32 +1,50 @@
|
|||
|
||||
#define LOOKUP_SAMPLES 360
|
||||
#define LOOKUP_SAMPLES 3600
|
||||
|
||||
extern double _sin_table[LOOKUP_SAMPLES + 1];
|
||||
extern double _saw_table[LOOKUP_SAMPLES + 1];
|
||||
extern double _tri_table[LOOKUP_SAMPLES + 1];
|
||||
extern double _lookup_table[6][LOOKUP_SAMPLES + 1];
|
||||
|
||||
struct osc_t
|
||||
{
|
||||
double freq;
|
||||
double step;
|
||||
double ramp;
|
||||
double level;
|
||||
|
||||
double sin;
|
||||
double saw;
|
||||
double tri;
|
||||
uint8_t shape;
|
||||
};
|
||||
|
||||
void osc_init();
|
||||
void osc_setfreq(struct osc_t *osc, double freq);
|
||||
|
||||
static inline void osc_setphase(struct osc_t *osc, double phase)
|
||||
{
|
||||
osc->ramp = LOOKUP_SAMPLES * phase;
|
||||
}
|
||||
|
||||
static inline void osc_tick(struct osc_t *osc)
|
||||
{
|
||||
osc->ramp += osc->step;
|
||||
if (osc->ramp > LOOKUP_SAMPLES) osc->ramp -= LOOKUP_SAMPLES;
|
||||
|
||||
uint32_t pos = floor(osc->ramp);
|
||||
//uint32_t pos = floor(osc->ramp);
|
||||
|
||||
osc->sin = _sin_table[pos];
|
||||
osc->saw = _saw_table[pos];
|
||||
osc->tri = _tri_table[pos];
|
||||
//osc->sin = _sin_table[pos];
|
||||
//osc->saw = _saw_table[pos];
|
||||
//osc->tri = _tri_table[pos];
|
||||
}
|
||||
|
||||
static inline double osc_getsample(struct osc_t *osc)
|
||||
{
|
||||
uint32_t pos = osc->ramp;
|
||||
return _lookup_table[osc->shape][pos] * osc->level;
|
||||
}
|
||||
|
||||
static inline double osc_getsamplewithphase(struct osc_t *osc, float phase)
|
||||
{
|
||||
double sample = osc->ramp + phase * LOOKUP_SAMPLES;
|
||||
if (sample < 0.0) sample += LOOKUP_SAMPLES;
|
||||
else if (sample > LOOKUP_SAMPLES) sample -= LOOKUP_SAMPLES;
|
||||
|
||||
uint32_t pos = sample;
|
||||
return _lookup_table[osc->shape][pos] * osc->level;
|
||||
}
|
||||
|
|
55
psyn.c
55
psyn.c
|
@ -8,6 +8,7 @@
|
|||
#include "osc.h"
|
||||
#include "filter.h"
|
||||
#include "voice.h"
|
||||
#include "control.h"
|
||||
#include "engine.h"
|
||||
#include "psyn.h"
|
||||
|
||||
|
@ -20,8 +21,10 @@ struct psyn_t
|
|||
int midi_event_id;
|
||||
float *out_l;
|
||||
float *out_r;
|
||||
|
||||
struct engine_t eng;
|
||||
float *ctrlMono;
|
||||
float *ctrlLP;
|
||||
float *ctrlOscShape[4];
|
||||
float *ctrlOscLevel[4];
|
||||
};
|
||||
|
||||
static void psyn_init(struct psyn_t *psyn, uint32_t sample_rate)
|
||||
|
@ -78,6 +81,18 @@ static void connect_port(LV2_Handle lv2instance, uint32_t port, void *data)
|
|||
case 2:
|
||||
psyn->out_r = data;
|
||||
break;
|
||||
case 3:
|
||||
psyn->ctrlMono = data;
|
||||
break;
|
||||
case 4:
|
||||
psyn->ctrlLP = data;
|
||||
break;
|
||||
case 5: case 6: case 7: case 8:
|
||||
psyn->ctrlOscShape[port - 5] = data;
|
||||
break;
|
||||
case 9: case 10: case 11: case 12:
|
||||
psyn->ctrlOscLevel[port - 9] = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,6 +104,7 @@ static void cleanup(LV2_Handle lv2instance)
|
|||
|
||||
static void run(LV2_Handle lv2instance, uint32_t sample_count)
|
||||
{
|
||||
uint8_t i;
|
||||
struct psyn_t *psyn = (struct psyn_t *)lv2instance;
|
||||
uint32_t frame = 0;
|
||||
LV2_Event *ev = NULL;
|
||||
|
@ -98,6 +114,13 @@ static void run(LV2_Handle lv2instance, uint32_t sample_count)
|
|||
|
||||
if (lv2_event_is_valid(&iterator)) ev = lv2_event_get(&iterator, NULL);
|
||||
|
||||
control_setstep(&_engine.lowpass, *psyn->ctrlLP, sample_count);
|
||||
_engine.monosynth = (int)*psyn->ctrlMono;
|
||||
for (i = 0; i < 4; i++) {
|
||||
_engine.osc_shape[i].value = *psyn->ctrlOscShape[i];
|
||||
_engine.osc_level[i].value = *psyn->ctrlOscLevel[i];
|
||||
}
|
||||
|
||||
while (frame < sample_count) {
|
||||
uint32_t to;
|
||||
|
||||
|
@ -107,22 +130,42 @@ static void run(LV2_Handle lv2instance, uint32_t sample_count)
|
|||
to = sample_count;
|
||||
}
|
||||
|
||||
engine_run(&psyn->eng, to - frame, psyn->out_l + frame, psyn->out_r + frame);
|
||||
engine_run(&_engine, to - frame, psyn->out_l + frame, psyn->out_r + frame);
|
||||
frame = to;
|
||||
|
||||
if (ev != NULL) {
|
||||
if (ev->type == 0) {
|
||||
psyn->event_ref->lv2_event_unref(psyn->event_ref->callback_data, ev);
|
||||
} else if (ev->type == psyn->midi_event_id && ev->size == 3) {
|
||||
} else if (ev->type == psyn->midi_event_id) {
|
||||
uint8_t *data = (uint8_t *)(ev + 1);
|
||||
|
||||
switch (data[0] & 0xF0) {
|
||||
case 0x80:
|
||||
engine_endvoice(&psyn->eng, data[1], data[2]);
|
||||
engine_endvoice(&_engine, data[1], data[2]);
|
||||
break;
|
||||
|
||||
case 0x90:
|
||||
engine_startvoice(&psyn->eng, data[1], data[2]);
|
||||
engine_startvoice(&_engine, data[1], data[2]);
|
||||
break;
|
||||
|
||||
case 0xA0:
|
||||
engine_aftertouch(&_engine, data[2]);
|
||||
break;
|
||||
|
||||
case 0xC0:
|
||||
engine_programchange(&_engine, data[1]);
|
||||
break;
|
||||
|
||||
case 0xB0:
|
||||
engine_controlchange(&_engine, data[1], data[2]);
|
||||
break;
|
||||
|
||||
case 0xD0:
|
||||
engine_aftertouch(&_engine, data[1]);
|
||||
break;
|
||||
|
||||
case 0xE0:
|
||||
engine_pitchchange(&_engine, (data[1] | data[2] << 7) - 0x2000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
90
psyn.ttl
90
psyn.ttl
|
@ -34,4 +34,94 @@
|
|||
lv2:index 2;
|
||||
lv2:symbol "out R";
|
||||
lv2:name "Audio Output R";
|
||||
],
|
||||
[
|
||||
a lv2:InputPort, lv2:ControlPort;
|
||||
lv2:index 3;
|
||||
lv2:symbol "mono";
|
||||
lv2:name "Mono mode";
|
||||
lv2:minimum 0;
|
||||
lv2:default 0;
|
||||
lv2:maximum 2;
|
||||
],
|
||||
[
|
||||
a lv2:InputPort, lv2:ControlPort;
|
||||
lv2:index 4;
|
||||
lv2:symbol "lp_freq";
|
||||
lv2:name "Low Pass Filter Frequency";
|
||||
lv2:minimum 1.0;
|
||||
lv2:default 2000.0;
|
||||
lv2:maximum 16000.0;
|
||||
],
|
||||
[
|
||||
a lv2:InputPort, lv2:ControlPort;
|
||||
lv2:index 5;
|
||||
lv2:symbol "oscshape0";
|
||||
lv2:name "Oscillator 0 shape";
|
||||
lv2:minimum 0;
|
||||
lv2:default 0;
|
||||
lv2:maximum 5;
|
||||
],
|
||||
[
|
||||
a lv2:InputPort, lv2:ControlPort;
|
||||
lv2:index 6;
|
||||
lv2:symbol "oscshape1";
|
||||
lv2:name "Oscillator 1 shape";
|
||||
lv2:minimum 0;
|
||||
lv2:default 0;
|
||||
lv2:maximum 5;
|
||||
],
|
||||
[
|
||||
a lv2:InputPort, lv2:ControlPort;
|
||||
lv2:index 7;
|
||||
lv2:symbol "oscshape2";
|
||||
lv2:name "Oscillator 2 shape";
|
||||
lv2:minimum 0;
|
||||
lv2:default 0;
|
||||
lv2:maximum 5;
|
||||
],
|
||||
[
|
||||
a lv2:InputPort, lv2:ControlPort;
|
||||
lv2:index 8;
|
||||
lv2:symbol "oscshape3";
|
||||
lv2:name "Oscillator 3 shape";
|
||||
lv2:minimum 0;
|
||||
lv2:default 0;
|
||||
lv2:maximum 5;
|
||||
],
|
||||
[
|
||||
a lv2:InputPort, lv2:ControlPort;
|
||||
lv2:index 9;
|
||||
lv2:symbol "osclevel0";
|
||||
lv2:name "Oscillator 0 level";
|
||||
lv2:minimum 0;
|
||||
lv2:default 1;
|
||||
lv2:maximum 1;
|
||||
],
|
||||
[
|
||||
a lv2:InputPort, lv2:ControlPort;
|
||||
lv2:index 10;
|
||||
lv2:symbol "osclevel1";
|
||||
lv2:name "Oscillator 1 level";
|
||||
lv2:minimum 0;
|
||||
lv2:default 0;
|
||||
lv2:maximum 1;
|
||||
],
|
||||
[
|
||||
a lv2:InputPort, lv2:ControlPort;
|
||||
lv2:index 11;
|
||||
lv2:symbol "osclevel2";
|
||||
lv2:name "Oscillator 2 level";
|
||||
lv2:minimum 0;
|
||||
lv2:default 0;
|
||||
lv2:maximum 1;
|
||||
],
|
||||
[
|
||||
a lv2:InputPort, lv2:ControlPort;
|
||||
lv2:index 12;
|
||||
lv2:symbol "osclevel3";
|
||||
lv2:name "Oscillator 3 level";
|
||||
lv2:minimum 0;
|
||||
lv2:default 0;
|
||||
lv2:maximum 1;
|
||||
].
|
||||
|
|
77
voice.c
77
voice.c
|
@ -6,19 +6,39 @@
|
|||
#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], 2000.0);
|
||||
filter_init_freq(&voice->fil[1], 150.0);
|
||||
// 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_setfreq(&voice->osc[1], freq * 1.2);
|
||||
osc_setfreq(&voice->osc[2], freq * 5);
|
||||
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)
|
||||
|
@ -50,22 +70,53 @@ void voice_run(struct voice_t *voice, uint32_t samples, float *left, float *righ
|
|||
|
||||
amplitude *= voice->velocity;
|
||||
|
||||
l = amplitude * voice->osc[0].sin * (1.0 + rng() * 0.25);
|
||||
r = amplitude * voice->osc[0].sin * (1.0 + rng() * 0.25);
|
||||
float s;
|
||||
|
||||
amplitude = env_getamplitude(&_env2, voice->sample, voice->released) * voice->velocity * voice->velocity * 1.5;
|
||||
s = osc_getsample(&voice->osc[0]);
|
||||
l = amplitude * s;// * (1.0 + rng() * 0.25);
|
||||
r = amplitude * s;// * (1.0 + rng() * 0.25);
|
||||
|
||||
if (amplitude > 0.0) {
|
||||
l += amplitude * voice->osc[1].tri * (1.0 + voice->osc[2].sin * 0.25);
|
||||
r += amplitude * voice->osc[1].tri * (1.0 + voice->osc[2].sin * 0.25);
|
||||
}
|
||||
s = osc_getsample(&voice->osc[1]);
|
||||
l += amplitude * s;
|
||||
r += amplitude * s;
|
||||
|
||||
*left += l;
|
||||
*right += r;
|
||||
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;
|
||||
// }
|
||||
|
|
Loading…
Reference in New Issue