#include #include #include #include #include #include "env.h" #include "osc.h" #include "filter.h" #include "control.h" #include "voice.h" #include "engine.h" #include "psyn.h" void engine_init(struct engine_t *engine) { uint32_t i; for (i = 0; i < 128; i++) { engine->freqs[i] = 440.0 * pow(2.0, (i - 69.0) / 12.0); } osc_init(); engine_load_program(engine); } void engine_load_program(struct engine_t *engine) { FILE *f = fopen("program.txt", "r"); while (!feof(f)) { char buf[1024]; fgets(buf, sizeof buf, f); if (!strncmp(buf, "voice", 5)) { // Ignore voice } else if (!strncmp(buf, "lfo", 3)) { int lfo; float freq; int r = sscanf(buf, "lfo %d %f", &lfo, &freq); if (r >= 2 && lfo >= 0 && lfo < NUM_LFO) { osc_setfreq(&engine->lfo[lfo], freq); engine->lfo[lfo].level = 1.0; } } else if (!strncmp(buf, "osc", 3)) { int osc; char sshape[1024]; float level; float freq; float phase; int r = sscanf(buf, "osc %d %s %f %f %f", &osc, sshape, &level, &freq, &phase); if (r >= 5 && osc >= 0 && osc < VOICE_OSCILLATORS) { int shape = 0; if (!strcmp(sshape, "SINE")) shape = OSC_SINE; else if (!strcmp(sshape, "SAW")) shape = OSC_SAW; else if (!strcmp(sshape, "TRIANGLE")) shape = OSC_TRIANGLE; else if (!strcmp(sshape, "SQUARE")) shape = OSC_SQUARE; else if (!strcmp(sshape, "MOOGSAW")) shape = OSC_MOOGSAW; else if (!strcmp(sshape, "EXP")) shape = OSC_EXP; engine->params[osc].shape.value = shape; engine->params[osc].level.value = level; engine->params[osc].freq_mult.value = freq; engine->params[osc].phase.value = phase; } } else if (!strncmp(buf, "pan", 3)) { int pan; char ssource[1024]; float parm1; float parm2; int r = sscanf(buf, "pan %d %s %f %f", &pan, ssource, &parm1, &parm2); if (r >= 4 && pan >= 0 && pan <= VOICE_OSCILLATORS) { int source = 0; if (!strcmp(ssource, "FIXED")) { engine->params[pan].pan_type = PAN_FIXED; engine->params[pan].pan_level = parm1; engine->params[pan].pan_level_r = parm2; } else if (!strcmp(ssource, "OSC")) { engine->params[pan].pan_type = PAN_OSC; engine->params[pan].pan_source = parm1; engine->params[pan].pan_level = parm2; } else if (!strcmp(ssource, "LFO")) { engine->params[pan].pan_type = PAN_LFO; engine->params[pan].pan_source = parm1; engine->params[pan].pan_level = parm2; } } } else if (!strncmp(buf, "env", 3)) { int env; float attack; float hold; float decay; float sustain; float release; int r = sscanf(buf, "env %d %f %f %f %f %f", &env, &attack, &hold, &decay, &sustain, &release); if (r >= 6 && env >= 0 && env < VOICE_OSCILLATORS) { env_init(&engine->params[env].env, attack, hold, decay, sustain, release); } } else if (!strncmp(buf, "cutoff_env", 10)) { int env; float attack; float hold; float decay; float sustain; float release; int r = sscanf(buf, "cutoff_env %d %f %f %f %f %f", &env, &attack, &hold, &decay, &sustain, &release); if (r >= 6 && env >= 0 && env < 1) { env_init(&engine->cutoff_env, attack, hold, decay, sustain, release); } } } fclose(f); } 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++) { control_tick(&engine->lowpass); left[pos] = 0.0; right[pos] = 0.0; for (i = 0; i < NUM_LFO; i++) { osc_tick(&engine->lfo[i]); } v = engine->voice; for (i = 0; i < NUM_POLYPHONY; i++, v++) { if (!v->playing) continue; voice_run(v, engine, 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; 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, engine, engine->freqs[note]); return; } for (i = 0; i < NUM_POLYPHONY; i++, v++) { if (v->playing) continue; /* Constant voice parameters */ v->playing = true; v->sample = 0; v->released = 0; v->note = note; v->velocity = velocity / 127.0; /* Voice parameters which determine sound */ voice_init(v, engine, engine->freqs[note]); 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; } } 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; }