2010-01-13 10:35:51 +00:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include "env.h"
|
|
|
|
#include "osc.h"
|
2010-01-13 17:05:00 +00:00
|
|
|
#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-13 10:35:51 +00:00
|
|
|
#include "engine.h"
|
|
|
|
#include "psyn.h"
|
|
|
|
|
|
|
|
static double _freqs[128];
|
|
|
|
|
2010-01-20 07:49:38 +00:00
|
|
|
struct engine_t _engine;
|
|
|
|
|
2010-01-13 10:35:51 +00:00
|
|
|
void engine_init()
|
|
|
|
{
|
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < 128; i++) {
|
|
|
|
_freqs[i] = 440.0 * pow(2.0, (i - 69.0) / 12.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
osc_init();
|
2010-01-21 08:36:18 +00:00
|
|
|
env_init(&_engine.params[0].env, 0.0125, 0.025, 5.0, 0.0, 0.25);
|
|
|
|
env_init(&_engine.params[1].env, 0.0, 0.0, 0.5, 0.0, 0.25);
|
|
|
|
|
|
|
|
osc_setfreq(&_engine.lfo[0], 10.0);
|
|
|
|
osc_setfreq(&_engine.lfo[1], 2.0);
|
|
|
|
osc_setfreq(&_engine.lfo[2], 1.0);
|
|
|
|
_engine.lfo[0].level = 1.0;
|
|
|
|
_engine.lfo[1].level = 1.0;
|
|
|
|
_engine.lfo[2].level = 1.0;
|
2010-01-13 10:35:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void engine_run(struct engine_t *engine, uint32_t samples, float *left, float *right)
|
|
|
|
{
|
|
|
|
struct voice_t *v;
|
|
|
|
uint32_t pos;
|
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
for (pos = 0; pos < samples; pos++) {
|
2010-01-20 07:49:38 +00:00
|
|
|
control_tick(&_engine.lowpass);
|
|
|
|
|
2010-01-13 10:35:51 +00:00
|
|
|
left[pos] = 0.0;
|
|
|
|
right[pos] = 0.0;
|
|
|
|
|
|
|
|
for (i = 0; i < NUM_LFO; i++) {
|
2010-01-21 08:36:18 +00:00
|
|
|
osc_tick(&_engine.lfo[i]);
|
2010-01-13 10:35:51 +00:00
|
|
|
}
|
|
|
|
|
2010-01-20 07:49:38 +00:00
|
|
|
v = _engine.voice;
|
2010-01-13 10:35:51 +00:00
|
|
|
for (i = 0; i < NUM_POLYPHONY; i++, v++) {
|
|
|
|
if (!v->playing) continue;
|
|
|
|
|
|
|
|
voice_run(v, 1, left + pos, right + pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void engine_startvoice(struct engine_t *engine, uint8_t note, uint8_t velocity)
|
|
|
|
{
|
|
|
|
struct voice_t *v = engine->voice;
|
|
|
|
uint32_t i;
|
|
|
|
|
2010-01-20 07:49:38 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-01-13 10:35:51 +00:00
|
|
|
for (i = 0; i < NUM_POLYPHONY; i++, v++) {
|
|
|
|
if (v->playing) continue;
|
|
|
|
|
2010-01-13 17:05:00 +00:00
|
|
|
/* Constant voice parameters */
|
2010-01-13 10:35:51 +00:00
|
|
|
v->playing = true;
|
|
|
|
v->sample = 0;
|
|
|
|
v->released = 0;
|
|
|
|
v->note = note;
|
|
|
|
v->velocity = velocity / 127.0;
|
|
|
|
|
2010-01-13 17:05:00 +00:00
|
|
|
/* Voice parameters which determine sound */
|
|
|
|
voice_init(v, _freqs[note]);
|
2010-01-13 10:35:51 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void engine_endvoice(struct engine_t *engine, uint8_t note, uint8_t velocity)
|
|
|
|
{
|
|
|
|
struct voice_t *v = engine->voice;
|
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < NUM_POLYPHONY; i++, v++) {
|
|
|
|
if (v->released > 0 || v->note != note) continue;
|
|
|
|
|
|
|
|
v->released = v->sample;
|
|
|
|
}
|
|
|
|
}
|
2010-01-20 07:49:38 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|