From 329642ab558251418085fd076b0c685d30714b41 Mon Sep 17 00:00:00 2001 From: Connor Olding Date: Wed, 29 Jan 2014 19:36:08 -0800 Subject: [PATCH] basic parameter support (LADSPA) --- Makefile | 6 +- README.md | 6 +- crap_eq-ladspa.c | 218 ---------------------------------------------- crap_eq.h | 6 +- template-ladspa.c | 114 +++++++++++++++++------- template-vst.cpp | 5 +- 6 files changed, 95 insertions(+), 260 deletions(-) delete mode 100644 crap_eq-ladspa.c diff --git a/Makefile b/Makefile index 1b8ef2c..cb94fc9 100755 --- a/Makefile +++ b/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} diff --git a/README.md b/README.md index 6a7e154..4169b5d 100644 --- a/README.md +++ b/README.md @@ -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 + diff --git a/crap_eq-ladspa.c b/crap_eq-ladspa.c deleted file mode 100644 index f8eb9d7..0000000 --- a/crap_eq-ladspa.c +++ /dev/null @@ -1,218 +0,0 @@ -#include -#include -#include -#include -#include - -#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; -} diff --git a/crap_eq.h b/crap_eq.h index b5b91b2..6a916bc 100644 --- a/crap_eq.h +++ b/crap_eq.h @@ -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) { } diff --git a/template-ladspa.c b/template-ladspa.c index 45179e9..e5c0830 100644 --- a/template-ladspa.c +++ b/template-ladspa.c @@ -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 +} diff --git a/template-vst.cpp b/template-vst.cpp index 9c10f37..f4494f6 100644 --- a/template-vst.cpp +++ b/template-vst.cpp @@ -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()