Esempio n. 1
0
int
main(int argc, char** argv)
{
	if (argc != 2) {
		fprintf(stderr, "USAGE: %s BUNDLE\n", argv[0]);
		return 1;
	}

	const char* bundle_path = argv[1];
	LilvWorld*  world       = lilv_world_new();

	// Load test plugin bundle
	uint8_t*  abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path);
	SerdNode  bundle     = serd_node_new_file_uri(abs_bundle, 0, 0, true);
	LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf);
	lilv_world_load_bundle(world, bundle_uri);
	free(abs_bundle);
	serd_node_free(&bundle);

	LilvNode*          plugin_uri = lilv_new_uri(world, PLUGIN_URI);
	const LilvPlugins* plugins    = lilv_world_get_all_plugins(world);
	const LilvPlugin*  plugin     = lilv_plugins_get_by_uri(plugins, plugin_uri);
	TEST_ASSERT(plugin);

	LilvInstance* instance = lilv_plugin_instantiate(plugin, 48000.0, NULL);
	TEST_ASSERT(instance);

	lilv_world_free(world);

	return 0;
}
Esempio n. 2
0
Result
LV2Module::instantiate (double samplerate)
{
    freeInstance();
    currentSampleRate = samplerate;
    
    features.clearQuick();
    world.getFeatures (features);
    
    // check for a worker interface
    LilvNodes* nodes = lilv_plugin_get_extension_data (plugin);
    LILV_FOREACH (nodes, iter, nodes)
    {
        const LilvNode* node = lilv_nodes_get (nodes, iter);
        if (lilv_node_equals (node, world.work_interface))
        {
            worker = new LV2Worker (world.getWorkThread(), 1);
            features.add (worker->getFeature());
        }
    }
    lilv_nodes_free (nodes); nodes = nullptr;        
    
    features.add (nullptr);
    instance = lilv_plugin_instantiate (plugin, samplerate,
                                        features.getRawDataPointer());
    if (instance == nullptr) {
        features.clearQuick();
        worker = nullptr;
        return Result::fail ("Could not instantiate plugin.");
    }
    
    if (const void* data = getExtensionData (LV2_WORKER__interface))
    {
        assert (worker != nullptr);
        worker->setSize (2048);
        worker->setInterface (lilv_instance_get_handle (instance),
                              (LV2_Worker_Interface*) data);
    }
    else if (worker)
    {
        features.removeFirstMatchingValue (worker->getFeature());
        worker = nullptr;
    }
    
    return Result::ok();
}
Esempio n. 3
0
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 gboolean
gst_lv2_filter_setup (GstAudioFilter * gsp, const GstAudioInfo * info)
{
    GstLV2Filter *self;
    GstLV2FilterClass *oclass;
    GstAudioFilterClass *audiofilter_class;
    gint i;

    audiofilter_class = GST_AUDIO_FILTER_GET_CLASS (gsp);
    self = (GstLV2Filter *) gsp;
    oclass = (GstLV2FilterClass *) audiofilter_class;

    g_return_val_if_fail (self->activated == FALSE, FALSE);

    GST_DEBUG_OBJECT (self, "instantiating the plugin at %d Hz",
                      GST_AUDIO_INFO_RATE (info));

    if (self->instance)
        lilv_instance_free (self->instance);

    if (!(self->instance =
                lilv_plugin_instantiate (oclass->plugin, GST_AUDIO_INFO_RATE (info),
                                         NULL)))
        goto no_instance;

    /* connect the control ports */
    for (i = 0; i < oclass->control_in_ports->len; i++)
        lilv_instance_connect_port (self->instance,
                                    g_array_index (oclass->control_in_ports, GstLV2FilterPort, i).index,
                                    &(self->ports.control.in[i]));

    for (i = 0; i < oclass->control_out_ports->len; i++)
        lilv_instance_connect_port (self->instance,
                                    g_array_index (oclass->control_out_ports, GstLV2FilterPort, i).index,
                                    &(self->ports.control.out[i]));

    /* FIXME Handle audio channel positionning while negotiating CAPS */
#if 0
    /* set input group pad audio channel position */
    for (i = 0; i < oclass->in_groups->len; ++i) {
        group = &g_array_index (oclass->in_groups, GstLV2FilterGroup, i);
        if (group->has_roles) {
            if ((positions = gst_lv2_filter_build_positions (group))) {
                if ((pad = gst_element_get_static_pad (GST_ELEMENT (gsp),
                                                       lilv_node_as_string (group->symbol)))) {
                    GST_INFO_OBJECT (self, "set audio channel positions on sink pad %s",
                                     lilv_node_as_string (group->symbol));
                    s = gst_caps_get_structure (caps, 0);
                    gst_audio_set_channel_positions (s, positions);
                    gst_object_unref (pad);
                }
                g_free (positions);
                positions = NULL;
            }
        }
    }
    /* set output group pad audio channel position */
    for (i = 0; i < oclass->out_groups->len; ++i) {
        group = &g_array_index (oclass->out_groups, GstLV2FilterGroup, i);
        if (group->has_roles) {
            if ((positions = gst_lv2_filter_build_positions (group))) {
                if ((pad = gst_element_get_static_pad (GST_ELEMENT (gsp),
                                                       lilv_node_as_string (group->symbol)))) {
                    GST_INFO_OBJECT (self, "set audio channel positions on src pad %s",
                                     lilv_node_as_string (group->symbol));
                    s = gst_caps_get_structure (caps, 0);
                    gst_audio_set_channel_positions (s, positions);
                    gst_object_unref (pad);
                }
                g_free (positions);
                positions = NULL;
            }
        }
    }
#endif

    lilv_instance_activate (self->instance);
    self->activated = TRUE;

    return TRUE;

no_instance:
    {
        GST_ERROR_OBJECT (gsp, "could not create instance");
        return FALSE;
    }
}
Esempio n. 5
0
Lv2Plugin *Lv2PluginCache::getPlugin(const char *uri, const char *preset, Lv2State *state) {
    // create a unique key for uri/preset/state
    std::string keyString(uri);
    if(preset) {
        keyString.append(":");
        keyString.append(preset);
    }
    std::size_t hash = std::hash<std::string>()(keyString);
    if(state) {
        hash = hash ^ (state->getHash() << 1);
    }

    // count tells how many instances of this type of plugin
    int count = ++instanceCount[hash];

    // return cached plugin instance if available
    int key = hash + count;
    Lv2Plugin *cachedPlugin = findObject(key);
    if(cachedPlugin) {
        cachedPlugin->restore();
        return cachedPlugin;
    }

    // look in cache for plugin type by uri
    std::string uriString(uri);
    const LilvPlugin *lilvPlugin = pluginMap[uriString];
    if(!lilvPlugin) {
        // find lv2 plugin in lilv
        LilvNode *lilvUri = lilv_new_uri(world, uri);
        lilvPlugin = lilv_plugins_get_by_uri(plugins, lilvUri);
        lilv_node_free(lilvUri);

        if(!lilvPlugin) {
            throw std::logic_error(std::string("Plugin is not installed on this system: ") + uriString);
        }

        // check that required features are supported
        LilvNodes* features = lilv_plugin_get_required_features(lilvPlugin);
        for (LilvIter* f = lilv_nodes_begin(features); !lilv_nodes_is_end(features, f); f = lilv_nodes_next(features, f)) {
            const char* featureUri = lilv_node_as_uri(lilv_nodes_get(features, f));
            if(!supported[featureUri]) {
                throw std::logic_error(std::string("Plugin ") + uriString + " requires unsupported feature: " + featureUri);
            }
        }
        lilv_nodes_free(features);
        pluginMap[uriString] = lilvPlugin;
    }

    // create worker if required
    Lv2Worker *worker = 0;
    if (lilv_plugin_has_feature(lilvPlugin, lv2Constants.lv2WorkerSchedule)
        && lilv_plugin_has_extension_data(lilvPlugin, lv2Constants.lv2WorkerInterface)) {
        worker = new Lv2Worker();
        ((LV2_Worker_Schedule*)lv2Features[5]->data)->handle = worker;
    }

    // instantiate
    LilvInstance *instance = lilv_plugin_instantiate(lilvPlugin, sampleRate, lv2Features);

    // connect worker with plugin instance
    if(worker) {
        worker->setInstance(instance);
    }

    // create plugin object
    Lv2Plugin *plugin = new Lv2Plugin(lilvPlugin, instance, lv2Constants, worker);

    // restore baseline default state
    LilvState *defaultState =  lilv_state_new_from_world(world, &map, lilv_plugin_get_uri(lilvPlugin));
    lilv_state_restore(defaultState, instance, setPortValue, plugin, 0, lv2Features);

    // find and restore preset
    if(preset) {
        LilvNodes* presets = lilv_plugin_get_related(lilvPlugin, lv2Constants.lv2Presets);
        LilvNode *myPreset = 0;
        LILV_FOREACH(nodes, i, presets) {
            const LilvNode* presetNode = lilv_nodes_get(presets, i);
            lilv_world_load_resource(world, presetNode);
            LilvNodes* labels = lilv_world_find_nodes(world, presetNode, lv2Constants.lv2RdfsLabel, NULL);
            if (labels) {
                const LilvNode* label = lilv_nodes_get_first(labels);
                const char *labelString = lilv_node_as_string(label); // TODO: free?
                if(!strcmp(labelString, preset)) {
                    myPreset = lilv_node_duplicate(presetNode);
                }
                lilv_nodes_free(labels);
            }
        }
        lilv_nodes_free(presets);
        if(myPreset) {
            LilvState* presetState = lilv_state_new_from_world(world, &map, myPreset);
            lilv_state_restore(presetState, instance, setPortValue, plugin, 0, NULL);
            // lilv_state_free(state); // TODO
        }
        else {
            throw std::logic_error(std::string("Plugin ") + uriString + " has no such preset: " + preset);
        }
    }
    // restore state
    else if(state) {    // TODO: what if state is requested on a plugin that doesn't support?
Esempio n. 6
0
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;
}