static gboolean gst_lv2_filter_stop (GstBaseTransform * transform) { GstLV2Filter *lv2 = (GstLV2Filter *) transform; if (lv2->activated == FALSE) { GST_ERROR_OBJECT (transform, "Deactivating but LV2 plugin not activated"); return TRUE; } if (lv2->instance == NULL) { GST_ERROR_OBJECT (transform, "Deactivating but no LV2 plugin set"); return TRUE; } GST_DEBUG_OBJECT (lv2, "deactivating"); lilv_instance_deactivate (lv2->instance); lv2->activated = FALSE; lilv_instance_free (lv2->instance); lv2->instance = NULL; return TRUE; }
void LV2Module::deactivate() { if (instance != nullptr && active) { lilv_instance_deactivate (instance); active = false; } }
EFFECT_LV2::~EFFECT_LV2 (void) { release(); if (plugin_desc != 0) { for(unsigned int n = 0; n < plugins_rep.size(); n++) { lilv_instance_deactivate(plugins_rep[n]->me); lilv_instance_free(plugins_rep[n]->me); delete plugins_rep[n]; } } }
void EFFECT_LV2::init(SAMPLE_BUFFER *insample) { EFFECT_BASE::init(insample); DBC_CHECK(samples_per_second() > 0); if (buffer_repp != insample) { release(); buffer_repp = insample; buffer_repp->get_pointer_reflock(); } if (plugin_desc != 0) { for(unsigned int n = 0; n < plugins_rep.size(); n++) { lilv_instance_deactivate(plugins_rep[n]->me); lilv_instance_free(plugins_rep[n]->me); delete plugins_rep[n]; } plugins_rep.clear(); } DBC_CHECK(plugins_rep.size() == 0); if (in_audio_ports > 1 || out_audio_ports > 1) { //Just insert into the first location plugins_rep.push_back(Lilv::Instance::create(plugin_desc,samples_per_second(),NULL)); int inport = 0; int outport = 0; for(unsigned long m = 0; m < port_count_rep; m++) { Lilv::Port p= plugin_desc.get_port_by_index(m); if (p.is_a(ECA_LV2_WORLD::AudioClassNode())) { if (p.is_a(ECA_LV2_WORLD::InputClassNode())) { if (inport < channels()) { plugins_rep[0]->connect_port(m, buffer_repp->buffer[inport]); } ++inport; } else if(p.is_a(ECA_LV2_WORLD::OutputClassNode())) { if (outport < channels()) { plugins_rep[0]->connect_port(m, buffer_repp->buffer[outport]); } ++outport; } } } if (inport > channels()) ECA_LOG_MSG(ECA_LOGGER::info, "WARNING: chain has less channels than plugin has input ports (" + name() + ")."); if (outport > channels()) ECA_LOG_MSG(ECA_LOGGER::info, "WARNING: chain has less channels than plugin has output ports (" + name() + ")."); } else { for(int n = 0; n < channels(); n++) { plugins_rep.push_back(Lilv::Instance::create(plugin_desc,samples_per_second(),NULL)); for(unsigned long m = 0; m < port_count_rep; m++) { Lilv::Port p= plugin_desc.get_port_by_index(m); if (p.is_a(ECA_LV2_WORLD::AudioClassNode())) { plugins_rep[n]->connect_port(m,buffer_repp->buffer[n]); } } } } ECA_LOG_MSG(ECA_LOGGER::system_objects, "Instantiated " + kvu_numtostr(plugins_rep.size()) + " LV2 plugin(s), each with " + kvu_numtostr(in_audio_ports) + " audio input port(s) and " + kvu_numtostr(out_audio_ports) + " output port(s), to chain with " + kvu_numtostr(channels()) + " channel(s) and srate of " + kvu_numtostr(samples_per_second()) + "."); int data_index = 0; for(unsigned long m = 0; m < port_count_rep; m++) { Lilv::Port p=plugin_desc.get_port_by_index(m); if (p.is_a(ECA_LV2_WORLD::ControlClassNode())) { for(unsigned int n = 0; n < plugins_rep.size(); n++) { plugins_rep[n]->connect_port(m,&(params[data_index])); } ++data_index; } } for(unsigned long m = 0; m < plugins_rep.size(); m++) plugins_rep[m]->activate(); }
bool LV2Effect::ProcessStereo(int count, WaveTrack *left, WaveTrack *right, sampleCount lstart, sampleCount rstart, sampleCount len) { /* Allocate buffers */ if (mBlockSize == 0) { mBlockSize = left->GetMaxBlockSize() * 2; fInBuffer = new float *[mAudioInputs.GetCount()]; for (size_t i = 0; i < mAudioInputs.GetCount(); i++) { fInBuffer[i] = new float[mBlockSize]; } fOutBuffer = new float *[mAudioOutputs.GetCount()]; for (size_t i = 0; i < mAudioOutputs.GetCount(); i++) { fOutBuffer[i] = new float[mBlockSize]; } } /* Instantiate the plugin */ LilvInstance *handle = lilv_plugin_instantiate(mData, left->GetRate(), gLV2Features); if (!handle) { wxMessageBox(wxString::Format(_("Unable to load plug-in %s"), pluginName.c_str())); return false; } /* Write the Note On to the MIDI event buffer and connect it */ LV2_Event_Buffer *midiBuffer = NULL; int noteOffTime; if (mMidiInput) { midiBuffer = lv2_event_buffer_new(40, 2); LV2_Event_Iterator iter; lv2_event_begin(&iter, midiBuffer); uint8_t noteOn[] = { 0x90, mNoteKey, mNoteVelocity }; lv2_event_write(&iter, 0, 0, 1, 3, noteOn); noteOffTime = mNoteLength * left->GetRate(); if (noteOffTime < len && noteOffTime < mBlockSize) { uint8_t noteOff[] = { 0x80, mNoteKey, 64 }; lv2_event_write(&iter, noteOffTime, 0, 1, 3, noteOff); } lilv_instance_connect_port(handle, mMidiInput->mIndex, midiBuffer); } for (size_t p = 0; p < mAudioInputs.GetCount(); p++) { lilv_instance_connect_port(handle, mAudioInputs[p].mIndex, fInBuffer[p]); } for (size_t p = 0; p < mAudioOutputs.GetCount(); p++) { lilv_instance_connect_port(handle, mAudioOutputs[p].mIndex, fOutBuffer[p]); } for (size_t p = 0; p < mControlInputs.GetCount(); p++) { lilv_instance_connect_port(handle, mControlInputs[p].mIndex, &mControlInputs[p].mControlBuffer); } for (size_t p = 0; p < mControlOutputs.GetCount(); p++) { lilv_instance_connect_port(handle, mControlOutputs[p].mIndex, &mControlOutputs[p].mControlBuffer); } float latency = 0.0; if (mLatencyPortIndex >= 0) { lilv_instance_connect_port(handle, mLatencyPortIndex, &latency); } lilv_instance_activate(handle); // Actually perform the effect here sampleCount originalLen = len; sampleCount ls = lstart; sampleCount rs = rstart; sampleCount ols = ls; sampleCount ors = rs; bool noteOver = false; sampleCount delayed = 0; sampleCount delay = 0; bool cleared = false; while (len || delayed) { int block = mBlockSize; if (len) { if (block > len) { block = len; } if (left && mAudioInputs.GetCount() > 0) { left->Get((samplePtr)fInBuffer[0], floatSample, ls, block); } if (right && mAudioInputs.GetCount() > 1) { right->Get((samplePtr)fInBuffer[1], floatSample, rs, block); } } else if (delayed) { // At the end if we don't have enough left for a whole block if (block > delayed) { block = delayed; } // Clear the input buffer so that we only pass zeros to the effect. if (!cleared) { for (int i = 0; i < mBlockSize; i++) { fInBuffer[0][i] = 0.0; } if (right) { memcpy(fInBuffer[1], fOutBuffer[0], mBlockSize); } cleared = true; } } lilv_instance_run(handle, block); if (delayed == 0 && latency != 0) { delayed = delay = latency; } if (delay >= block) { delay -= block; } else if (delay > 0) { sampleCount oblock = block - delay; if (left && mAudioOutputs.GetCount() > 0) { left->Set((samplePtr)(fOutBuffer[0] + delay), floatSample, ols, oblock); } if (right && mAudioOutputs.GetCount() > 1) { right->Set((samplePtr)(fOutBuffer[1] + delay), floatSample, ors, oblock); } ols += oblock; ors += oblock; delay = 0; } else { if (left && mAudioOutputs.GetCount() > 0) { left->Set((samplePtr)fOutBuffer[0], floatSample, ols, block); } if (right && mAudioOutputs.GetCount() > 1) { right->Set((samplePtr)fOutBuffer[1], floatSample, ors, block); } ols += block; ors += block; } if (len) { len -= block; noteOffTime -= block; // Clear the event buffer and add the note off event if needed if (mMidiInput) { lv2_event_buffer_reset(midiBuffer, 1, (uint8_t *)midiBuffer + sizeof(LV2_Event_Buffer)); if (!noteOver && noteOffTime < len && noteOffTime < block) { LV2_Event_Iterator iter; lv2_event_begin(&iter, midiBuffer); uint8_t noteOff[] = { 0x80, mNoteKey, 64 }; lv2_event_write(&iter, noteOffTime, 0, 1, 3, noteOff); noteOver = true; } } } else if (delayed) { delayed -= block; } ls += block; rs += block; if (mAudioInputs.GetCount() > 1) { if (TrackGroupProgress(count, (ls-lstart)/(double)originalLen)) { return false; } } else { if (TrackProgress(count, (ls-lstart)/(double)originalLen)) { return false; } } } lilv_instance_deactivate(handle); lilv_instance_free(handle); return true; }
static double bench(const LilvPlugin* p, uint32_t sample_count, uint32_t block_size) { URITable uri_table; uri_table_init(&uri_table); LV2_URID_Map map = { &uri_table, uri_table_map }; LV2_Feature map_feature = { LV2_URID_MAP_URI, &map }; LV2_URID_Unmap unmap = { &uri_table, uri_table_unmap }; LV2_Feature unmap_feature = { LV2_URID_UNMAP_URI, &unmap }; const LV2_Feature* features[] = { &map_feature, &unmap_feature, NULL }; float* const buf = (float*)calloc(block_size * 2, sizeof(float)); float* const in = buf; float* const out = buf + block_size; if (!buf) { fprintf(stderr, "Out of memory\n"); return 0.0; } LV2_Atom_Sequence seq = { { sizeof(LV2_Atom_Sequence_Body), uri_table_map(&uri_table, LV2_ATOM__Sequence) }, { 0, 0 } }; const char* uri = lilv_node_as_string(lilv_plugin_get_uri(p)); LilvNodes* required = lilv_plugin_get_required_features(p); LILV_FOREACH(nodes, i, required) { const LilvNode* feature = lilv_nodes_get(required, i); if (!lilv_node_equals(feature, urid_map)) { fprintf(stderr, "<%s> requires feature <%s>, skipping\n", uri, lilv_node_as_uri(feature)); free(buf); uri_table_destroy(&uri_table); return 0.0; } } LilvInstance* instance = lilv_plugin_instantiate(p, 48000.0, features); if (!instance) { fprintf(stderr, "Failed to instantiate <%s>\n", lilv_node_as_uri(lilv_plugin_get_uri(p))); free(buf); uri_table_destroy(&uri_table); return 0.0; } float* controls = (float*)calloc( lilv_plugin_get_num_ports(p), sizeof(float)); lilv_plugin_get_port_ranges_float(p, NULL, NULL, controls); const uint32_t n_ports = lilv_plugin_get_num_ports(p); for (uint32_t index = 0; index < n_ports; ++index) { const LilvPort* port = lilv_plugin_get_port_by_index(p, index); if (lilv_port_is_a(p, port, lv2_ControlPort)) { lilv_instance_connect_port(instance, index, &controls[index]); } else if (lilv_port_is_a(p, port, lv2_AudioPort) || lilv_port_is_a(p, port, lv2_CVPort)) { if (lilv_port_is_a(p, port, lv2_InputPort)) { lilv_instance_connect_port(instance, index, in); } else if (lilv_port_is_a(p, port, lv2_OutputPort)) { lilv_instance_connect_port(instance, index, out); } else { fprintf(stderr, "<%s> port %d neither input nor output, skipping\n", uri, index); lilv_instance_free(instance); free(buf); free(controls); uri_table_destroy(&uri_table); return 0.0; } } else if (lilv_port_is_a(p, port, atom_AtomPort)) { lilv_instance_connect_port(instance, index, &seq); } else { fprintf(stderr, "<%s> port %d has unknown type, skipping\n", uri, index); lilv_instance_free(instance); free(buf); free(controls); uri_table_destroy(&uri_table); return 0.0; } } lilv_instance_activate(instance); struct timespec ts = bench_start(); for (uint32_t i = 0; i < (sample_count / block_size); ++i) { lilv_instance_run(instance, block_size); } const double elapsed = bench_end(&ts); lilv_instance_deactivate(instance); lilv_instance_free(instance); uri_table_destroy(&uri_table); if (full_output) { printf("%d %d ", block_size, sample_count); } printf("%lf %s\n", elapsed, uri); free(buf); free(controls); return elapsed; }