Oops, lots of changes

master
Peter Nelson 13 years ago
parent a2f4261b7a
commit 2d4ffb346b
  1. 53
      engine.c
  2. 17
      engine.h
  3. 52
      filter.c
  4. 18
      filter.h
  5. 33
      osc.c
  6. 40
      osc.h
  7. 55
      psyn.c
  8. 90
      psyn.ttl
  9. 79
      voice.c
  10. 3
      voice.h

@ -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;
}

@ -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);

@ -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;
*/

@ -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

@ -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

@ -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];
}
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;
osc->sin = _sin_table[pos];
osc->saw = _saw_table[pos];
osc->tri = _tri_table[pos];
uint32_t pos = sample;
return _lookup_table[osc->shape][pos] * osc->level;
}

@ -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;
}
}

@ -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;
].

@ -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);
amplitude = env_getamplitude(&_env2, voice->sample, voice->released) * voice->velocity * voice->velocity * 1.5;
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);
// }
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);
}
// *left += l;
// *right += r;
*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;
// }

@ -11,7 +11,8 @@ struct voice_t
double velocity;
struct osc_t osc[VOICE_OSCILLATORS];
struct filter_t fil[VOICE_FILTERS];
//struct filter_t fil[VOICE_FILTERS];
struct bw_filter_t bw[VOICE_FILTERS];
};
void voice_init(struct voice_t *voice, double freq);

Loading…
Cancel
Save