2015-04-04 02:06:13 -07:00
|
|
|
#include <alloca.h>
|
2013-11-11 08:26:22 -08:00
|
|
|
#include <stdlib.h>
|
2013-11-16 11:51:01 -08:00
|
|
|
#include <stdio.h>
|
2013-11-11 08:26:22 -08:00
|
|
|
#include <assert.h>
|
|
|
|
#include <time.h>
|
2015-04-04 02:44:33 -07:00
|
|
|
#include <math.h>
|
2013-11-11 08:26:22 -08:00
|
|
|
|
|
|
|
#include "dlfcn.h"
|
2015-06-06 10:42:14 -07:00
|
|
|
#include "ladspa.hpp"
|
|
|
|
#include "util.hpp"
|
2013-11-11 08:26:22 -08:00
|
|
|
|
2015-04-04 06:48:27 -07:00
|
|
|
#define BLOCK_SIZE 2048
|
2013-11-11 08:26:22 -08:00
|
|
|
|
|
|
|
void *plug = NULL;
|
2013-11-16 11:51:01 -08:00
|
|
|
static float *audio_buffer;
|
|
|
|
static int audio_count = 0;
|
2013-11-11 08:26:22 -08:00
|
|
|
|
2015-04-04 06:48:27 -07:00
|
|
|
INNER void
|
2014-02-05 23:47:16 -08:00
|
|
|
cleanup()
|
|
|
|
{
|
2013-11-11 08:26:22 -08:00
|
|
|
dlclose(plug);
|
2013-11-16 11:51:01 -08:00
|
|
|
if (audio_count) free(audio_buffer);
|
2013-11-11 08:26:22 -08:00
|
|
|
}
|
|
|
|
|
2015-04-04 06:48:27 -07:00
|
|
|
INNER const LADSPA_Descriptor*
|
2014-02-05 23:47:16 -08:00
|
|
|
load_ladspa(char *path)
|
|
|
|
{
|
2013-11-11 08:26:22 -08:00
|
|
|
plug = dlopen(path, RTLD_NOW);
|
|
|
|
assert(plug);
|
|
|
|
atexit(cleanup);
|
|
|
|
|
2015-06-06 10:42:14 -07:00
|
|
|
LADSPA_Descriptor_Function df;
|
|
|
|
df = (typeof(df)) dlsym(plug, "ladspa_descriptor");
|
2013-11-11 08:26:22 -08:00
|
|
|
assert(df);
|
|
|
|
|
|
|
|
const LADSPA_Descriptor *d = df(0);
|
|
|
|
assert(d);
|
|
|
|
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
2015-04-04 06:48:27 -07:00
|
|
|
INNER float
|
2015-04-04 02:44:33 -07:00
|
|
|
between(float percent, float min, float max, int logscale)
|
|
|
|
{
|
|
|
|
if (logscale)
|
|
|
|
return log(min/percent)/log(min/max);
|
|
|
|
else
|
|
|
|
return (min - percent)/(min - max);
|
|
|
|
}
|
|
|
|
|
2015-04-04 06:48:27 -07:00
|
|
|
INNER float
|
2015-04-04 02:44:33 -07:00
|
|
|
get_default(LADSPA_PortRangeHint hint)
|
|
|
|
{
|
|
|
|
float x = 0;
|
|
|
|
int hd = hint.HintDescriptor;
|
|
|
|
float min = hint.LowerBound;
|
|
|
|
float max = hint.UpperBound;
|
|
|
|
float logscale = LADSPA_IS_HINT_LOGARITHMIC(hd);
|
|
|
|
if (LADSPA_IS_HINT_DEFAULT_0(hd))
|
|
|
|
x = 0;
|
|
|
|
if (LADSPA_IS_HINT_DEFAULT_1(hd))
|
|
|
|
x = 1;
|
|
|
|
if (LADSPA_IS_HINT_DEFAULT_100(hd))
|
|
|
|
x = 100;
|
|
|
|
if (LADSPA_IS_HINT_DEFAULT_440(hd))
|
|
|
|
x = 440;
|
|
|
|
if (LADSPA_IS_HINT_DEFAULT_MINIMUM(hd))
|
|
|
|
x = min;
|
|
|
|
if (LADSPA_IS_HINT_DEFAULT_LOW(hd))
|
|
|
|
x = between(0.25, min, max, logscale);
|
|
|
|
if (LADSPA_IS_HINT_DEFAULT_MIDDLE(hd))
|
|
|
|
x = between(0.50, min, max, logscale);
|
|
|
|
if (LADSPA_IS_HINT_DEFAULT_HIGH(hd))
|
|
|
|
x = between(0.75, min, max, logscale);
|
|
|
|
if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(hd))
|
|
|
|
x = max;
|
|
|
|
if (LADSPA_IS_HINT_INTEGER(hd))
|
|
|
|
x = round(x);
|
|
|
|
if (LADSPA_IS_HINT_TOGGLED(hd)) {
|
|
|
|
float mid = between(0.50, min, max, logscale);
|
|
|
|
x = x >= mid ? max : min;
|
|
|
|
}
|
|
|
|
if (x < min) x = min;
|
|
|
|
if (x > max) x = max;
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
2013-11-11 08:26:22 -08:00
|
|
|
int
|
2014-02-05 23:47:16 -08:00
|
|
|
main(int argc, char **argv)
|
|
|
|
{
|
2013-11-11 08:26:22 -08:00
|
|
|
assert(argc > 1);
|
|
|
|
|
|
|
|
const LADSPA_Descriptor *d = load_ladspa(argv[1]);
|
|
|
|
|
|
|
|
LADSPA_Handle h = d->instantiate(d, 44100);
|
|
|
|
assert(h);
|
|
|
|
|
2013-11-16 11:51:01 -08:00
|
|
|
// we're lazy so we don't distinguish inputs and outputs
|
|
|
|
for (int i = 0; i < d->PortCount; i++)
|
|
|
|
if (LADSPA_IS_PORT_AUDIO(d->PortDescriptors[i]))
|
|
|
|
audio_count++;
|
|
|
|
|
2015-06-06 10:42:14 -07:00
|
|
|
audio_buffer = (typeof(audio_buffer)) calloc(audio_count*BLOCK_SIZE, sizeof(float));
|
2013-11-16 11:51:01 -08:00
|
|
|
|
|
|
|
int a = 0;
|
2015-04-04 02:06:13 -07:00
|
|
|
for (int i = 0; i < d->PortCount; i++) {
|
|
|
|
if (LADSPA_IS_PORT_AUDIO(d->PortDescriptors[i])) {
|
2013-11-16 11:51:01 -08:00
|
|
|
d->connect_port(h, i, audio_buffer + a++*BLOCK_SIZE);
|
2015-04-04 02:06:13 -07:00
|
|
|
} else {
|
2015-06-06 10:42:14 -07:00
|
|
|
float *x;
|
|
|
|
x = (typeof(x)) alloca(sizeof(float));
|
2015-04-04 02:44:33 -07:00
|
|
|
*x = get_default(d->PortRangeHints[i]);
|
2015-04-04 02:06:13 -07:00
|
|
|
d->connect_port(h, i, x);
|
|
|
|
}
|
|
|
|
}
|
2013-11-11 08:26:22 -08:00
|
|
|
|
|
|
|
mirand = time(NULL);
|
2013-11-16 11:51:01 -08:00
|
|
|
for (int i = 0; i < audio_count*BLOCK_SIZE; i++)
|
|
|
|
audio_buffer[i] = whitenoise();
|
2013-11-11 08:26:22 -08:00
|
|
|
|
|
|
|
if (d->activate) d->activate(h);
|
|
|
|
for (int i = 0; i < 64*64*8; i++)
|
|
|
|
d->run(h, BLOCK_SIZE);
|
|
|
|
if (d->deactivate) d->deactivate(h);
|
|
|
|
|
|
|
|
d->cleanup(h);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|