basic parameter support (LADSPA)
This commit is contained in:
parent
1006245886
commit
329642ab55
6 changed files with 95 additions and 260 deletions
6
Makefile
6
Makefile
|
@ -5,9 +5,9 @@ DISTNAME = crap
|
|||
VERSION = git
|
||||
FULLNAME = ${DISTNAME}-${VERSION}
|
||||
|
||||
BOTH = crap_eq_const
|
||||
LADSPA_ONLY = crap_eq crap_noise
|
||||
VST_ONLY = crap_eq crap_delay_test
|
||||
BOTH = crap_eq crap_eq_const
|
||||
LADSPA_ONLY = crap_noise
|
||||
VST_ONLY = crap_delay_test
|
||||
LADSPA = ${BOTH:=-ladspa} ${LADSPA_ONLY:=-ladspa}
|
||||
VST = ${BOTH:=-vst} ${VST_ONLY:=-vst}
|
||||
PLUGINS = ${LADSPA} ${VST}
|
||||
|
|
|
@ -45,10 +45,12 @@ remember to export `VST\_SDK\_DIR` to the path of your `vstsdk2.4/`
|
|||
|
||||
## TODO
|
||||
|
||||
* finish VST/LADSPA parameter/port support in templates
|
||||
* convert crap\_eq and crap\_noise to the template format
|
||||
* convert crap\_noise to the template format
|
||||
* rename plugins (fix capitalization consistency and such)
|
||||
* remove crap\_ prefixes?
|
||||
* move to subdirs?
|
||||
* make crap faster (hand-written SSE2? compiler directives?)
|
||||
* reduce input/output buffers on biquads (shared)
|
||||
* ease up on the preprocessor ifs
|
||||
* polish parameter support
|
||||
|
||||
|
|
218
crap_eq-ladspa.c
218
crap_eq-ladspa.c
|
@ -1,218 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ladspa.h"
|
||||
#include "crap_util.h"
|
||||
|
||||
typedef unsigned long ulong;
|
||||
|
||||
/* Ports:
|
||||
* BANDS*0 to BANDS*1-1: gain
|
||||
* BANDS*1 to BANDS*2-1: frequency
|
||||
* BANDS*2 to BANDS*3-1: bandwidth
|
||||
*/
|
||||
#ifndef BANDS
|
||||
#define BANDS 4
|
||||
#endif
|
||||
#define EQ_INPUT (BANDS*3+0)
|
||||
#define EQ_OUTPUT (BANDS*3+1)
|
||||
#define PCOUNT (BANDS*3+2)
|
||||
|
||||
#define GAIN_MIN -60
|
||||
#define GAIN_MAX 18
|
||||
#define FREQ_MIN 1
|
||||
#define FREQ_MAX 20000
|
||||
#define BW_MIN 0.02
|
||||
#define BW_MAX 8
|
||||
|
||||
void __attribute__ ((constructor)) eq_init();
|
||||
|
||||
static const char *gain_desc = "Band %i Gain [dB]";
|
||||
static const char *freq_desc = "Band %i Freq [Hz]";
|
||||
static const char *band_desc = "Band %i Bandwidth [octaves]";
|
||||
|
||||
#define NAME_SIZE 32
|
||||
LADSPA_PortDescriptor p_discs[PCOUNT];
|
||||
LADSPA_PortRangeHint p_hints[PCOUNT];
|
||||
char name_buffer[PCOUNT*NAME_SIZE];
|
||||
char *p_names[PCOUNT];
|
||||
|
||||
typedef struct {
|
||||
LADSPA_Data *chg[BANDS];
|
||||
LADSPA_Data *chf[BANDS];
|
||||
LADSPA_Data *chb[BANDS];
|
||||
LADSPA_Data old_chg[BANDS];
|
||||
LADSPA_Data old_chf[BANDS];
|
||||
LADSPA_Data old_chb[BANDS];
|
||||
LADSPA_Data *input;
|
||||
LADSPA_Data *output;
|
||||
|
||||
biquad filters[BANDS];
|
||||
LADSPA_Data fs;
|
||||
} eq_t;
|
||||
|
||||
static void
|
||||
activate_eq(LADSPA_Handle instance) {
|
||||
eq_t *eq = (eq_t *)instance;
|
||||
biquad *filters = eq->filters;
|
||||
|
||||
for (int i = 0; i < BANDS; i++)
|
||||
biquad_init(&filters[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup_eq(LADSPA_Handle instance) {
|
||||
free(instance);
|
||||
}
|
||||
|
||||
static void
|
||||
connect_port_eq(LADSPA_Handle instance, ulong port, LADSPA_Data *data) {
|
||||
eq_t *eq = (eq_t *)instance;
|
||||
if (port < BANDS)
|
||||
eq->chg[port - BANDS*0] = data;
|
||||
else if (port < BANDS*2)
|
||||
eq->chf[port - BANDS*1] = data;
|
||||
else if (port < BANDS*3)
|
||||
eq->chb[port - BANDS*2] = data;
|
||||
else if (port == EQ_INPUT)
|
||||
eq->input = data;
|
||||
else if (port == EQ_OUTPUT)
|
||||
eq->output = data;
|
||||
}
|
||||
|
||||
static LADSPA_Handle
|
||||
instantiate_eq(const LADSPA_Descriptor *descriptor, ulong s_rate) {
|
||||
eq_t *eq = (eq_t *) calloc(1, sizeof(eq_t));
|
||||
biquad *filters = eq->filters;
|
||||
LADSPA_Data fs = s_rate;
|
||||
|
||||
eq->fs = fs;
|
||||
|
||||
const LADSPA_Data g = 0;
|
||||
const LADSPA_Data f = 440;
|
||||
const LADSPA_Data b = 1;
|
||||
for (int i = 0; i < BANDS; i++) {
|
||||
eq->old_chg[i] = g;
|
||||
eq->old_chf[i] = f;
|
||||
eq->old_chb[i] = b;
|
||||
filters[i] = biquad_gen(1, f, g, b, fs);
|
||||
}
|
||||
|
||||
return (LADSPA_Handle) eq;
|
||||
}
|
||||
|
||||
static void
|
||||
watch_parameters(eq_t *eq) {
|
||||
biquad *filters = eq->filters;
|
||||
const LADSPA_Data fs = eq->fs;
|
||||
for (int i = 0; i < BANDS; i++) {
|
||||
const LADSPA_Data rg = *(eq->chg[i]);
|
||||
const LADSPA_Data rf = *(eq->chf[i]);
|
||||
const LADSPA_Data rb = *(eq->chb[i]);
|
||||
if ((rg != eq->old_chg[i])
|
||||
|| (rf != eq->old_chf[i])
|
||||
|| (rb != eq->old_chb[i])) {
|
||||
const LADSPA_Data g = LIMIT(rg, GAIN_MIN, GAIN_MAX);
|
||||
const LADSPA_Data f = LIMIT(rf, FREQ_MIN, FREQ_MAX);
|
||||
const LADSPA_Data b = LIMIT(rb, BW_MIN, BW_MAX);
|
||||
eq->old_chg[i] = g;
|
||||
eq->old_chf[i] = f;
|
||||
eq->old_chb[i] = b;
|
||||
filters[i] = biquad_gen(1, f, g, b, fs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
run_eq(LADSPA_Handle instance, ulong sample_count) {
|
||||
eq_t *eq = (eq_t *) instance;
|
||||
biquad *filters = eq->filters;
|
||||
|
||||
watch_parameters(eq);
|
||||
|
||||
const LADSPA_Data *input = eq->input;
|
||||
LADSPA_Data *output = eq->output;
|
||||
|
||||
for (ulong pos = 0; pos < sample_count; pos++) {
|
||||
LADSPA_Data samp = input[pos];
|
||||
for (int i = 0; i < BANDS; i++)
|
||||
samp = biquad_run(&filters[i], samp);
|
||||
output[pos] = samp;
|
||||
}
|
||||
}
|
||||
|
||||
static LADSPA_Descriptor eqDescriptor = {
|
||||
.UniqueID = 0xCAFED,
|
||||
.Label = "crap_eq",
|
||||
.Properties = 0,
|
||||
.Name = "crap Parametric Equalizer",
|
||||
.Maker = "Connor Olding",
|
||||
.Copyright = "MIT",
|
||||
.PortCount = PCOUNT,
|
||||
.PortDescriptors = p_discs,
|
||||
.PortRangeHints = p_hints,
|
||||
.PortNames = p_names,
|
||||
|
||||
.activate = activate_eq,
|
||||
.cleanup = cleanup_eq,
|
||||
.connect_port = connect_port_eq,
|
||||
.deactivate = NULL,
|
||||
.instantiate = instantiate_eq,
|
||||
.run = run_eq,
|
||||
.run_adding = NULL,
|
||||
.set_run_adding_gain = NULL
|
||||
};
|
||||
|
||||
const LADSPA_Descriptor *
|
||||
ladspa_descriptor(ulong index) {
|
||||
if (index != 0)
|
||||
return NULL;
|
||||
return &eqDescriptor;
|
||||
}
|
||||
|
||||
void
|
||||
eq_init() {
|
||||
#define INCTRL (LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL)
|
||||
#define BOUNDED (LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE)
|
||||
for (int i = 0; i < PCOUNT; i++)
|
||||
p_names[i] = &name_buffer[i*NAME_SIZE];
|
||||
for (int i = 0; i < BANDS; i++) {
|
||||
const int gi = i;
|
||||
const int fi = i + BANDS;
|
||||
const int bi = i + BANDS*2;
|
||||
|
||||
p_discs[gi] = INCTRL;
|
||||
p_discs[fi] = INCTRL;
|
||||
p_discs[bi] = INCTRL;
|
||||
|
||||
sprintf(p_names[gi], gain_desc, i);
|
||||
sprintf(p_names[fi], freq_desc, i);
|
||||
sprintf(p_names[bi], band_desc, i);
|
||||
|
||||
p_hints[gi].HintDescriptor = BOUNDED
|
||||
| LADSPA_HINT_DEFAULT_0;
|
||||
p_hints[fi].HintDescriptor = BOUNDED
|
||||
| LADSPA_HINT_LOGARITHMIC
|
||||
| LADSPA_HINT_DEFAULT_440;
|
||||
p_hints[bi].HintDescriptor = BOUNDED
|
||||
| LADSPA_HINT_DEFAULT_1;
|
||||
|
||||
p_hints[gi].LowerBound = GAIN_MIN;
|
||||
p_hints[gi].UpperBound = GAIN_MAX;
|
||||
p_hints[fi].LowerBound = FREQ_MIN;
|
||||
p_hints[fi].UpperBound = FREQ_MAX;
|
||||
p_hints[bi].LowerBound = BW_MIN;
|
||||
p_hints[bi].UpperBound = BW_MAX;
|
||||
}
|
||||
|
||||
p_discs[EQ_INPUT] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
|
||||
strcpy(p_names[EQ_INPUT], "Input");
|
||||
p_hints[EQ_INPUT].HintDescriptor = 0;
|
||||
|
||||
p_discs[EQ_OUTPUT] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
|
||||
strcpy(p_names[EQ_OUTPUT], "Output");
|
||||
p_hints[EQ_OUTPUT].HintDescriptor = 0;
|
||||
}
|
|
@ -67,7 +67,7 @@ pause(personal *data) {
|
|||
}
|
||||
|
||||
static void
|
||||
construct(personal *data, param *params) {
|
||||
construct_params(param *params) {
|
||||
for (int i = 0; i < BANDS; i++) {
|
||||
sprintf(params[0].name, "Band %i Frequency", i + 1);
|
||||
params[0].min = 20;
|
||||
|
@ -94,6 +94,10 @@ construct(personal *data, param *params) {
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
construct(personal *data) {
|
||||
}
|
||||
|
||||
static void
|
||||
destruct(personal *data) {
|
||||
}
|
||||
|
|
|
@ -3,44 +3,29 @@
|
|||
|
||||
//#INCLUDE
|
||||
|
||||
#ifndef PARAM_NAME_LEN
|
||||
#define PARAM_NAME_LEN 24
|
||||
#endif
|
||||
|
||||
#define PLUG_INPUT_L 0
|
||||
#define PLUG_INPUT_R 1
|
||||
#define PLUG_OUTPUT_L 2
|
||||
#define PLUG_OUTPUT_R 3
|
||||
#define PCOUNT (PARAMETERS + 4)
|
||||
|
||||
const LADSPA_PortDescriptor p_discs[PCOUNT] = {
|
||||
LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO
|
||||
,
|
||||
LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO
|
||||
,
|
||||
LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO
|
||||
,
|
||||
LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO
|
||||
//#PORT_DESCRIPTIONS
|
||||
};
|
||||
static void __attribute__ ((constructor)) plug_init();
|
||||
|
||||
const LADSPA_PortRangeHint p_hints[PCOUNT] = {
|
||||
{.HintDescriptor = 0}
|
||||
,
|
||||
{.HintDescriptor = 0}
|
||||
,
|
||||
{.HintDescriptor = 0}
|
||||
,
|
||||
{.HintDescriptor = 0}
|
||||
//#PORT_HINTS
|
||||
};
|
||||
|
||||
const char *p_names[PCOUNT] = {
|
||||
"L input"
|
||||
,
|
||||
"R input"
|
||||
,
|
||||
"L output"
|
||||
,
|
||||
"R output"
|
||||
//#PORT_NAMES
|
||||
LADSPA_PortDescriptor p_descs[PCOUNT];
|
||||
LADSPA_PortRangeHint p_hints[PCOUNT];
|
||||
char p_default_strings[4][PARAM_NAME_LEN + 1] = {
|
||||
"Input L", "Input R",
|
||||
"Output L", "Output R"
|
||||
};
|
||||
#if (PARAMETERS > 0)
|
||||
static param global_params[PARAMETERS];
|
||||
char p_name_strings[PARAMETERS][PARAM_NAME_LEN + 1];
|
||||
#endif
|
||||
char *p_names[PCOUNT];
|
||||
|
||||
typedef struct {
|
||||
LADSPA_Data *input_L;
|
||||
|
@ -48,8 +33,11 @@ typedef struct {
|
|||
LADSPA_Data *output_L;
|
||||
LADSPA_Data *output_R;
|
||||
|
||||
//#PORT_DATA
|
||||
personal data;
|
||||
#if (PARAMETERS > 0)
|
||||
float *values[PARAMETERS];
|
||||
param params[PARAMETERS];
|
||||
#endif
|
||||
} plug_t;
|
||||
|
||||
static void
|
||||
|
@ -63,7 +51,10 @@ plug_connect(LADSPA_Handle instance, unsigned long port, LADSPA_Data *data) {
|
|||
plug->output_L = data;
|
||||
else if (port == PLUG_OUTPUT_R)
|
||||
plug->output_R = data;
|
||||
//#PORT_CONNECT
|
||||
#if (PARAMETERS > 0)
|
||||
else if (port < PARAMETERS + 4)
|
||||
plug->values[port - 4] = data;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -82,7 +73,12 @@ static LADSPA_Handle
|
|||
plug_construct(const LADSPA_Descriptor *descriptor, unsigned long fs) {
|
||||
plug_t *plug = (plug_t *) calloc(1, sizeof(plug_t));
|
||||
construct(&plug->data);
|
||||
#if (PARAMETERS > 0)
|
||||
memcpy(plug->params, global_params, sizeof(param)*PARAMETERS);
|
||||
adjust(&plug->data, plug->params, fs);
|
||||
#else
|
||||
adjust(&plug->data, fs);
|
||||
#endif
|
||||
return (LADSPA_Handle) plug;
|
||||
}
|
||||
|
||||
|
@ -96,6 +92,14 @@ plug_destruct(LADSPA_Handle instance) {
|
|||
static void
|
||||
plug_process(LADSPA_Handle instance, unsigned long count) {
|
||||
plug_t *plug = (plug_t *)instance;
|
||||
#if (PARAMETERS > 0)
|
||||
for (int i = 0; i < PARAMETERS; i++) {
|
||||
if (*plug->values[i] != plug->params[i].value) {
|
||||
plug->params[i].value = *plug->values[i];
|
||||
adjust_one(&plug->data, plug->params, i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
process(&plug->data,
|
||||
plug->input_L, plug->input_R,
|
||||
plug->output_L, plug->output_R,
|
||||
|
@ -110,7 +114,7 @@ static const LADSPA_Descriptor plug_desc = {
|
|||
.Maker = AUTHOR,
|
||||
.Copyright = COPYRIGHT,
|
||||
.PortCount = PCOUNT,
|
||||
.PortDescriptors = p_discs,
|
||||
.PortDescriptors = p_descs,
|
||||
.PortRangeHints = p_hints,
|
||||
.PortNames = p_names,
|
||||
|
||||
|
@ -130,3 +134,47 @@ ladspa_descriptor(unsigned long index) {
|
|||
return NULL;
|
||||
return &plug_desc;
|
||||
}
|
||||
|
||||
static void
|
||||
plug_init() {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
p_names[i] = p_default_strings[i];
|
||||
p_descs[i] = LADSPA_PORT_AUDIO;
|
||||
p_descs[i] |= (i < 2) ? LADSPA_PORT_INPUT : LADSPA_PORT_OUTPUT;
|
||||
p_hints[i] = (LADSPA_PortRangeHint){.HintDescriptor = 0};
|
||||
}
|
||||
|
||||
#if (PARAMETERS > 0)
|
||||
construct_params(global_params);
|
||||
for (int i = 0; i < PARAMETERS; i++) {
|
||||
int j = i + 4;
|
||||
param *p = &global_params[i];
|
||||
|
||||
memcpy(p_name_strings[i], p->name, PARAM_NAME_LEN + 1);
|
||||
p_names[j] = p_name_strings[i];
|
||||
p_descs[j] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
|
||||
int hint = LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE;
|
||||
|
||||
p_hints[j].LowerBound = p->min;
|
||||
p_hints[j].UpperBound = p->max;
|
||||
|
||||
if (p->scale == SCALE_INT) hint |= LADSPA_HINT_INTEGER;
|
||||
if (p->scale == SCALE_TOGGLE) hint |= LADSPA_HINT_TOGGLED;
|
||||
if (p->scale >= SCALE_LOG) hint |= LADSPA_HINT_LOGARITHMIC;
|
||||
|
||||
switch (p->def) {
|
||||
case DEFAULT_0: hint |= LADSPA_HINT_DEFAULT_0; break;
|
||||
case DEFAULT_1: hint |= LADSPA_HINT_DEFAULT_1; break;
|
||||
case DEFAULT_100: hint |= LADSPA_HINT_DEFAULT_100; break;
|
||||
case DEFAULT_440: hint |= LADSPA_HINT_DEFAULT_440; break;
|
||||
case DEFAULT_MIN: hint |= LADSPA_HINT_DEFAULT_MINIMUM; break;
|
||||
case DEFAULT_LOW: hint |= LADSPA_HINT_DEFAULT_LOW; break;
|
||||
case DEFAULT_HIGH: hint |= LADSPA_HINT_DEFAULT_HIGH; break;
|
||||
case DEFAULT_MAX: hint |= LADSPA_HINT_DEFAULT_MAXIMUM; break;
|
||||
case DEFAULT_HALF: hint |= LADSPA_HINT_DEFAULT_MIDDLE; break;
|
||||
}
|
||||
|
||||
p_hints[j].HintDescriptor = hint;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -55,10 +55,9 @@ plugin::plugin(audioMasterCallback audioMaster)
|
|||
setUniqueID(ID);
|
||||
canProcessReplacing();
|
||||
#if (PARAMETERS > 0)
|
||||
::construct(&data, params);
|
||||
#else
|
||||
::construct(&data);
|
||||
::construct_params(params);
|
||||
#endif
|
||||
::construct(&data);
|
||||
}
|
||||
|
||||
plugin::~plugin()
|
||||
|
|
Loading…
Reference in a new issue