On Tue, 2009-07-28 at 14:12 -0500, Gabriel M. Beddingfield wrote:
> Hi Damon,
>
> On Tue, 28 Jul 2009, Damon Chaplin wrote:
> > A quick update - fixes have been found for blop, caps & cmt, and the
> > ladspa Sine plugin problem is fixed in the latest version.
>
> Great job! Did you update your test program? Could you please post it to
> the list?
I've only reordered it so it connects the ports before calling activate,
to avoid the crashes with the amb and swh plugins.
I've attached the new version.
Damon
/*
* Test app to load & run all LADSPA plugins for one cycle.
*
* Compile with:
* gcc `pkg-config --cflags --libs gmodule-2.0` -lm -o test-ladspa test-ladspa.c
*
* Simply run it with './test-ladspa' to test all plugins.
* Run it with './test-ladspa -p PACKAGE' to test a particular package.
* (Run ./test-ladspa --help to see the list of known packages.)
*
* Run it with 'valgrind --tool=memcheck ./test-ladspa' to spot memory errors.
*/
#include <stdlib.h>
#include <math.h>
#include <glib.h>
#include <gmodule.h>
#include <ladspa.h>
/* The default places to look for LADSPA plugins, if LADSPA_PATH isn't set. */
#define DEFAULT_LADSPA_PATH "/usr/lib/ladspa:/usr/local/lib/ladspa"
/* The sample rate to pass to the plugins. We don't output audio so it's not
too important. */
#define SAMPLE_RATE 48000
/* The number of samples to use for the run. Again, not too important. */
#define NUM_SAMPLES 256
static char *package = NULL;
static char **file_list = NULL;
/* These are the lists of files containing the plugins in the various
packages. I got most of these using 'rpm -ql <PACKAGE>'. There may be
more packages around that I haven't got installed at present. */
static char *amb_file_list[] = { "ambisonic1.so", "ambisonic2.so", NULL };
static char *blop_file_list[] = {
"adsr_1653.so", "adsr_1680.so", "amp_1654.so", "branch_1673.so",
"dahdsr_2021.so", "difference_2030.so", "fmod_1656.so",
"interpolator_1660.so", "lp4pole_1671.so", "parabola_1649_data.so",
"product_1668.so", "pulse_1645.so", "quantiser100_2029.so",
"quantiser20_2027.so", "quantiser50_2028.so", "random_1661.so",
"ratio_2034.so", "sawtooth_1641_data.so", "sawtooth_1641.so",
"sequencer16_1677.so", "sequencer32_1676.so", "sequencer64_1675.so",
"square_1643_data.so", "square_1643.so", "sum_1665.so",
"sync_pulse_2023.so", "sync_square_1678.so", "tracker_2025.so",
"triangle_1649.so",
NULL
};
static char *calf_file_list[] = { "calf.so", NULL };
static char *caps_file_list[] = { "caps.so", NULL };
static char *cmt_file_list[] = { "cmt.so", NULL };
static char *fil_file_list[] = { "filters.so", NULL };
static char *ladspa_file_list[] = { "amp.so", "delay.so", "filter.so",
"noise.so", "sine.so", NULL };
static char *mcp_file_list[] = { "cs_chorus.so", "cs_phaser.so",
"mvchpf24.so", "mvclpf24.so", NULL };
static char *rev_file_list[] = { "g2reverb.so", NULL };
static char *swh_file_list[] = {
"alias_1407.so", "allpass_1895.so", "am_pitchshift_1433.so", "amp_1181.so",
"analogue_osc_1416.so", "bandpass_a_iir_1893.so", "bandpass_iir_1892.so",
"bode_shifter_1431.so", "bode_shifter_cv_1432.so", "butterworth_1902.so",
"chebstortion_1430.so", "comb_1190.so", "comb_1887.so",
"comb_splitter_1411.so", "const_1909.so", "crossover_dist_1404.so",
"dc_remove_1207.so", "decay_1886.so", "decimator_1202.so", "declip_1195.so",
"delay_1898.so", "delayorama_1402.so", "diode_1185.so", "divider_1186.so",
"dj_eq_1901.so", "dj_flanger_1438.so", "dyson_compress_1403.so",
"fad_delay_1192.so", "fast_lookahead_limiter_1913.so", "flanger_1191.so",
"fm_osc_1415.so", "foldover_1213.so", "foverdrive_1196.so",
"freq_tracker_1418.so", "gate_1410.so", "giant_flange_1437.so",
"gong_1424.so", "gong_beater_1439.so", "gsm_1215.so", "gverb_1216.so",
"hard_limiter_1413.so", "harmonic_gen_1220.so", "hermes_filter_1200.so",
"highpass_iir_1890.so", "hilbert_1440.so", "imp_1199.so", "impulse_1885.so",
"inv_1429.so", "karaoke_1409.so", "latency_1914.so", "lcr_delay_1436.so",
"lowpass_iir_1891.so", "ls_filter_1908.so", "matrix_ms_st_1421.so",
"matrix_spatialiser_1422.so", "matrix_st_ms_1420.so", "mbeq_1197.so",
"mod_delay_1419.so", "multivoice_chorus_1201.so", "notch_iir_1894.so",
"phasers_1217.so", "pitch_scale_1193.so", "pitch_scale_1194.so",
"plate_1423.so", "pointer_cast_1910.so", "rate_shifter_1417.so",
"retro_flange_1208.so", "revdelay_1605.so", "ringmod_1188.so",
"satan_maximiser_1408.so", "sc1_1425.so", "sc2_1426.so", "sc3_1427.so",
"sc4_1882.so", "sc4m_1916.so", "se4_1883.so", "shaper_1187.so",
"sifter_1210.so", "sin_cos_1881.so", "single_para_1203.so",
"sinus_wavewrapper_1198.so", "smooth_decimate_1414.so", "split_1406.so",
"step_muxer_1212.so", "surround_encoder_1401.so", "svf_1214.so",
"tape_delay_1211.so", "transient_1206.so", "triple_para_1204.so",
"valve_1209.so", "valve_rect_1405.so", "vynil_1905.so",
"wave_terrain_1412.so", "xfade_1915.so", "zm1_1428.so",
NULL
};
static char *tap_file_list[] = {
"tap_autopan.so", "tap_chorusflanger.so", "tap_deesser.so", "tap_doubler.so",
"tap_dynamics_m.so", "tap_dynamics_st.so", "tap_echo.so", "tap_eq.so",
"tap_eqbw.so", "tap_limiter.so", "tap_pinknoise.so", "tap_pitch.so",
"tap_reflector.so", "tap_reverb.so", "tap_rotspeak.so", "tap_sigmoid.so",
"tap_tremolo.so", "tap_tubewarmth.so", "tap_vibrato.so",
NULL
};
static char *vco_file_list[] = { "blvco.so", "vco_sawpulse.so", NULL };
static gpointer
create_buffer_for_port (LADSPA_Descriptor *descriptor,
gint port_num)
{
LADSPA_PortDescriptor port_descriptor;
const LADSPA_PortRangeHint *port_range_hint;
LADSPA_PortRangeHintDescriptor hint_descriptor;
gfloat *buffer, minimum, maximum, value = 0.0F;
gint i;
port_descriptor = descriptor->PortDescriptors[port_num];
port_range_hint = &descriptor->PortRangeHints[port_num];
hint_descriptor = port_range_hint->HintDescriptor;
if (port_descriptor & LADSPA_PORT_AUDIO)
{
buffer = g_new (float, NUM_SAMPLES);
for (i = 0; i < NUM_SAMPLES; i++)
buffer[i] = 0.0F;
}
else
{
buffer = g_new (float, 1);
minimum = port_range_hint->LowerBound;
if (LADSPA_IS_HINT_SAMPLE_RATE (hint_descriptor))
minimum *= SAMPLE_RATE;
maximum = port_range_hint->UpperBound;
if (LADSPA_IS_HINT_SAMPLE_RATE (hint_descriptor))
maximum *= SAMPLE_RATE;
/* Calculate the default value. See ladspa.h for the formulas.
We could try testing plugins with all kinds of input data later. */
if (LADSPA_IS_HINT_HAS_DEFAULT (hint_descriptor))
{
if (LADSPA_IS_HINT_DEFAULT_MINIMUM (hint_descriptor))
value = minimum;
else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM (hint_descriptor))
value = maximum;
else if (LADSPA_IS_HINT_DEFAULT_0 (hint_descriptor))
value = 0;
else if (LADSPA_IS_HINT_DEFAULT_1 (hint_descriptor))
value = 1;
else if (LADSPA_IS_HINT_DEFAULT_100 (hint_descriptor))
value = 100;
else if (LADSPA_IS_HINT_DEFAULT_440 (hint_descriptor))
value = 440;
else if (LADSPA_IS_HINT_DEFAULT_LOW (hint_descriptor))
{
if (LADSPA_IS_HINT_LOGARITHMIC (hint_descriptor))
value = exp (log (minimum) * 0.75 + log (maximum) * 0.25);
else
value = (minimum * 0.75 + maximum * 0.25);
}
else if (LADSPA_IS_HINT_DEFAULT_MIDDLE (hint_descriptor))
{
if (LADSPA_IS_HINT_LOGARITHMIC (hint_descriptor))
value = exp (log (minimum) * 0.5 + log (maximum) * 0.5);
else
value = (minimum * 0.5 + maximum * 0.5);
}
else if (LADSPA_IS_HINT_DEFAULT_HIGH (hint_descriptor))
{
if (LADSPA_IS_HINT_LOGARITHMIC (hint_descriptor))
value = exp (log (minimum) * 0.25 + log (maximum) * 0.75);
else
value = (minimum * 0.25 + maximum * 0.75);
}
}
*buffer = value;
}
return buffer;
}
/* Returns TRUE if a plugin should be skipped. */
static gboolean
skip_file (const gchar *filename)
{
gint i;
if (file_list)
{
for (i = 0; file_list[i]; i++)
{
if (!strcmp (file_list[i], filename))
return FALSE;
}
return TRUE;
}
return FALSE;
}
static void
test_ladspa_plugin (const gchar *filename,
LADSPA_Descriptor *descriptor)
{
LADSPA_Handle ladspa_instance;
gint num_ports, port_num;
GList *buffers = NULL, *elem;
gpointer buffer;
#if 1
g_print ("###############################################################################\n");
#endif
#if 1
g_print ("Testing %i: %s (%s)\n", descriptor->UniqueID,
descriptor->Name ? descriptor->Name : "Unnamed", filename);
#endif
/* Instantiate the plugin. */
ladspa_instance = descriptor->instantiate (descriptor, SAMPLE_RATE);
/* Connect up the ports. */
num_ports = descriptor->PortCount;
for (port_num = 0; port_num < num_ports; port_num++)
{
buffer = create_buffer_for_port (descriptor, port_num);
#if 0
g_print ("Connecting port: %i to: %p\n", port_num, buffer);
#endif
descriptor->connect_port (ladspa_instance, port_num, buffer);
buffers = g_list_prepend (buffers, buffer);
}
/* Activate it, if necessary. */
if (descriptor->activate)
descriptor->activate (ladspa_instance);
/* Do one run of the plugin. */
descriptor->run (ladspa_instance, NUM_SAMPLES);
/* Free the buffers. */
for (elem = buffers; elem; elem = elem->next)
g_free (elem->data);
g_list_free (buffers);
/* Deactivate it, if necessary. */
if (descriptor->deactivate)
descriptor->deactivate (ladspa_instance);
/* Free any resources. */
descriptor->cleanup (ladspa_instance);
}
static void
scan_ladspa_plugin (gchar *pathname,
const gchar *filename)
{
GModule *module;
LADSPA_Descriptor_Function ladspa_func;
LADSPA_Descriptor *descriptor;
gpointer symbol;
gint i;
module = g_module_open (pathname, G_MODULE_BIND_LAZY);
if (!module)
return;
/* Lookup the special "ladspa_descriptor" symbol. */
if (g_module_symbol (module, "ladspa_descriptor", &symbol))
{
ladspa_func = (LADSPA_Descriptor_Function) symbol;
/* Get the LADSPA descriptor for each module in the library. */
for (i = 0; ; i++)
{
descriptor = (LADSPA_Descriptor*) ladspa_func (i);
if (!descriptor)
break;
test_ladspa_plugin (filename, descriptor);
}
}
g_module_close (module);
}
static void
scan_ladspa_directory (gchar *directory)
{
GDir *dir;
const char *filename;
char *pathname;
dir = g_dir_open (directory, 0, NULL);
if (!dir)
return;
/* Step through the files in the LADSPA plugin directory. */
while ((filename = g_dir_read_name (dir)))
{
if (skip_file (filename))
{
#if 0
g_print ("Skipping file: %s\n", filename);
#endif
continue;
}
pathname = g_strdup_printf ("%s%c%s", directory, G_DIR_SEPARATOR,
filename);
scan_ladspa_plugin (pathname, filename);
g_free (pathname);
}
g_dir_close (dir);
}
static void
test_ladspa_plugins ()
{
const gchar *path;
gchar **directories;
gint directory_num;
/* Use the $LADSPA_PATH environment variable, or the default path if that
hasn't been set. */
path = g_getenv ("LADSPA_PATH");
if (!path)
path = DEFAULT_LADSPA_PATH;
/* Split the path into an array of directories. */
directories = g_strsplit (path, ":", -1);
/* Scan each directory in turn. */
for (directory_num = 0; directories[directory_num]; directory_num++)
scan_ladspa_directory (directories[directory_num]);
/* Free the array. */
g_strfreev (directories);
}
/* Command-line options. */
static GOptionEntry entries[] =
{
{ "package", 'p', 0, G_OPTION_ARG_STRING, &package, "Package to test (amb, blop, calf, caps, cmt, fil, ladspa, mcp, rev, swh, tap or vco)", "PACKAGE" },
{ NULL }
};
int
main (int argc, char *argv[])
{
GOptionContext *context;
GError *error = NULL;
context = g_option_context_new ("- test LADSPA plugins");
g_option_context_add_main_entries (context, entries, NULL);
if (!g_option_context_parse (context, &argc, &argv, &error))
{
g_print ("option parsing failed: %s\n", error->message);
exit (1);
}
/* If a package is specified, set the appropriate file list to scan. */
if (package)
{
if (!strcmp (package, "amb"))
file_list = amb_file_list;
else if (!strcmp (package, "blop"))
file_list = blop_file_list;
else if (!strcmp (package, "calf"))
file_list = calf_file_list;
else if (!strcmp (package, "caps"))
file_list = caps_file_list;
else if (!strcmp (package, "cmt"))
file_list = cmt_file_list;
else if (!strcmp (package, "fil"))
file_list = fil_file_list;
else if (!strcmp (package, "ladspa"))
file_list = ladspa_file_list;
else if (!strcmp (package, "mcp"))
file_list = mcp_file_list;
else if (!strcmp (package, "rev"))
file_list = rev_file_list;
else if (!strcmp (package, "swh"))
file_list = swh_file_list;
else if (!strcmp (package, "tap"))
file_list = tap_file_list;
else if (!strcmp (package, "vco"))
file_list = vco_file_list;
}
test_ladspa_plugins ();
return 0;
}
_______________________________________________
Linux-audio-dev mailing list
[email protected]
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev