#include "processors.h" #include #include #include typedef struct { double rate, phase, frequency; float gain, velocity; unsigned pitch; } voice; static xtc_result prepare(double rate, size_t frames, const float *values, size_t count, void **out) { voice *v = calloc(1, sizeof(*v)); (void)frames; (void)count; *out = v; if (!v) return XTC_ERR_OUT_OF_MEMORY; v->rate = rate; v->gain = values[0]; return XTC_OK; } static void reset(void *state) { voice *v = state; v->phase = 0; v->velocity = 0; } static void parameter(void *state, unsigned id, float value) { (void)id; ((voice *)state)->gain = value; } static void destroy(void *state) { free(state); } static xtc_result effect(void *state, const xtc_native_block *b) { voice *v = state; size_t i; for (i = 0; i < b->frames; ++i) b->output[i] = b->input ? b->input[i] * v->gain : 0; return XTC_OK; } static xtc_result instrument(void *state, const xtc_native_block *b) { voice *v = state; size_t i, e = 0; for (i = 0; i < b->frames; ++i) { while (e < b->event_count && b->events[e].offset == i) { const xtc_midi_event *m = b->events + e++; if (m->type == XTC_MIDI_NOTE_ON) { v->pitch = m->pitch; v->velocity = (float)m->velocity / 127.0f; v->frequency = 440.0 * pow(2.0, ((double)m->pitch - 69.0) / 12.0); } else if (m->type == XTC_MIDI_ALL_OFF || m->pitch == v->pitch) v->velocity = 0; } b->output[i] = (float)sin(v->phase) * v->velocity * v->gain; v->phase = fmod(v->phase + 6.283185307179586 * v->frequency / v->rate, 6.283185307179586); } return XTC_OK; } xtc_processor_descriptor example_effect(void) { xtc_processor_descriptor d; memset(&d, 0, sizeof(d)); d.abi_version = XTC_PROCESSOR_ABI; d.struct_size = sizeof(d); strcpy(d.identifier, "xtc.example.gain.v1"); d.kind = XTC_NATIVE_EFFECT; d.parameter_count = 1; d.parameters[0].id = 1; strcpy(d.parameters[0].name, "Gain"); strcpy(d.parameters[0].unit, "linear"); d.parameters[0].minimum = 0; d.parameters[0].maximum = 2; d.parameters[0].default_value = 1; d.prepare = prepare; d.reset = reset; d.process = effect; d.parameter = parameter; d.destroy = destroy; return d; } xtc_processor_descriptor example_instrument(void) { xtc_processor_descriptor d = example_effect(); strcpy(d.identifier, "xtc.example.sine.v1"); d.kind = XTC_NATIVE_INSTRUMENT; d.process = instrument; return d; }