1
0
Fork 0
forked from hanez/xtc
xtc/examples/processors.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;
}