59 lines
2.5 KiB
C
59 lines
2.5 KiB
C
#include "processors.h"
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
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;
|
|
}
|