# HG changeset patch -- Bitbucket.org # Project Armstrong # URL http://bitbucket.org/paniq/armstrong/overview/ # User mental@rydia.net # Date 1240039816 14400 # Node ID bcb8dd70b78f42d968c0d7ca4259f9bb37b8e89c # Parent 22d3f5482d250064f44790af032e9314386c1a31 Support multiple instances of DSSI plugins that require run_multiple_synths() --- a/src/plugins/dssidapter/dssidapter.cpp +++ b/src/plugins/dssidapter/dssidapter.cpp @@ -26,6 +27,7 @@ #include "zzub/plugin.h" #include <vector> +#include <algorithm> #include <string> #include <assert.h> #include <alsa/asoundlib.h> @@ -49,7 +51,7 @@ extern "C" } #include "../ladspadapter/paramtools.h" -const char *myName = "zzub DSSI adaptor"; +const char *myName = "zzub DSSI adapter"; typedef ladspa_param dssi_param; @@ -75,6 +77,7 @@ struct dssi_info : zzub::info }; +static std::vector<dssidapter *> active_instances; std::vector<dssi_info *> infos; #include "osc_functions.h" @@ -182,6 +185,11 @@ dssidapter::~dssidapter() if (uiTarget && ui_osc_quit_path) { lo_send(uiTarget, ui_osc_quit_path, ""); } + std::vector<dssidapter *>::iterator found; + found = std::find(active_instances.begin(), active_instances.end(), this); + if (found != active_instances.end()) { + active_instances.erase(found); + } if (handle) { if (desc->LADSPA_Plugin->deactivate) @@ -219,6 +227,7 @@ dssidapter::dssidapter(const dssi_info * data_values = 0; myinfo = _dssi_info; track_count = 1; + output_backlog = 0; if (myinfo->global_parameters.size()) { @@ -371,11 +380,14 @@ void dssidapter::init(archive *arc) _host->set_event_handler(_metaplugin, this); handle = desc->LADSPA_Plugin->instantiate(desc->LADSPA_Plugin, _master_info->samples_per_second); if (!desc->run_synth && !desc->run_multiple_synths) { - printf("%s: Warning: no run_synth() method and no run_multiple_synth() method\n", myName); + printf("%s: Warning: no run_synth() method and no run_multiple_synths() method\n", myName); } if (myinfo->m_audioouts.size() < 1) { printf("%s: Warning: no audio outputs\n", myName); } + if (myinfo->m_audioins.size() > 0 && !desc->run_synth && desc->run_multiple_synths) { + printf("%s: Warning: audio input not supported with run_multiple_synths()\n", myName); + } std::vector<dssi_param>::const_iterator i; int index = 0; for (i = myinfo->m_metaparams.begin(); i != myinfo->m_metaparams.end(); ++i) @@ -449,6 +461,8 @@ void dssidapter::init(archive *arc) if (desc->LADSPA_Plugin->activate) desc->LADSPA_Plugin->activate(handle); + active_instances.push_back(this); + eventcount = 0; } @@ -631,7 +645,9 @@ bool dssidapter::process_stereo(float ** if (verbose) printf("dssidapter: process_stereo() returning false\n"); return false; } - if (myinfo->m_audioins.size() == 1) { + if (!desc->run_synth && desc->run_multiple_synths) { + // skip inputs since we can't readily support inputs and run_multiple_synths() + } else if (myinfo->m_audioins.size() == 1) { for (int i = 0; i < numsamples; i++) { inputs[0][i] = (pin[0][i] + pin[1][i]) * 0.5f; } @@ -646,12 +662,42 @@ bool dssidapter::process_stereo(float ** if (desc->run_synth) { desc->run_synth(handle, numsamples, events, eventcount); } else if (desc->run_multiple_synths) { - desc->run_multiple_synths(1, &handle, numsamples, &events, &eventcount); + if (output_backlog == 0) { + // no additional allocations necessary for <= 16 active instances + static std::vector<LADSPA_Handle> handles(16); + static std::vector<snd_seq_event_t *> event_vectors(16); + static std::vector<unsigned long> event_counts(16); + + // n.b. clear does not deallocate memory + handles.clear(); + event_vectors.clear(); + event_counts.clear(); + + // ensure minimal allocation if allocation is required + handles.reserve(active_instances.size()); + event_vectors.reserve(active_instances.size()); + event_counts.reserve(active_instances.size()); + + std::vector<dssidapter *>::iterator iter; + for (iter = active_instances.begin(); iter != active_instances.end(); ++iter) { + dssidapter *instance = *iter; + handles.push_back(instance->handle); + event_vectors.push_back(instance->events); + event_counts.push_back(instance->eventcount); + instance->eventcount = 0; + instance->output_backlog = numsamples; + } + + desc->run_multiple_synths(active_instances.size(), &handles[0], numsamples, &event_vectors[0], &event_counts[0]); + } else { + // what if output_backlog < numsamples ? + } } else { // No synth method -- what should we return? } + eventcount = 0; + output_backlog = 0; - eventcount = 0; if (myinfo->m_audioouts.size() == 1) { memcpy(pout[0], outputs[0], sizeof(float) * numsamples); memcpy(pout[1], outputs[0], sizeof(float) * numsamples); --- a/src/plugins/dssidapter/dssidapter.h +++ b/src/plugins/dssidapter/dssidapter.h @@ -100,6 +100,7 @@ struct dssidapter : plugin, event_handle LADSPA_Data *data_values; float inputs[16][256]; float outputs[16][256]; + int output_backlog; snd_seq_event_t *events; long unsigned int eventcount; zzub_plugin_t* _metaplugin;