static GstFlowReturn
gst_lv2_filter_transform_data (GstLV2Filter * self,
                               GstMapInfo * in_map, GstMapInfo * out_map)
{
    GstAudioFilterClass *audiofilter_class;
    GstLV2FilterClass *lv2_class;
    GstLV2FilterGroup *lv2_group;
    GstLV2FilterPort *lv2_port;
    guint j, nframes, samples, out_samples;

    gfloat *in = NULL, *out = NULL;

    nframes = in_map->size / sizeof (float);

    audiofilter_class = GST_AUDIO_FILTER_GET_CLASS (self);
    lv2_class = (GstLV2FilterClass *) audiofilter_class;

    samples = nframes / lv2_class->in_group.ports->len;

    /* multi channel inputs */
    lv2_group = &lv2_class->in_group;

    in = g_new0 (gfloat, nframes);

    if (lv2_group->ports->len > 1)
        gst_lv2_filter_deinterleave_data (lv2_group->ports->len, in,
                                          samples, (gfloat *) in_map->data);

    for (j = 0; j < lv2_group->ports->len; ++j) {
        lv2_port = &g_array_index (lv2_group->ports, GstLV2FilterPort, j);

        lilv_instance_connect_port (self->instance, lv2_port->index,
                                    in + (j * samples));
    }

    lv2_group = &lv2_class->out_group;
    out_samples = nframes / lv2_group->ports->len;
    out = g_new0 (gfloat, samples * lv2_group->ports->len);
    for (j = 0; j < lv2_group->ports->len; ++j) {
        lv2_port = &g_array_index (lv2_group->ports, GstLV2FilterPort, j);
        lilv_instance_connect_port (self->instance, lv2_port->index,
                                    out + (j * out_samples));
    }

    lilv_instance_run (self->instance, samples);

    if (lv2_group->ports->len > 1)
        gst_lv2_filter_interleave_data (lv2_group->ports->len,
                                        (gfloat *) out_map->data, out_samples, out);
    g_free (out);
    g_free (in);

    return GST_FLOW_OK;
}
Example #2
0
void
LV2Module::run (uint32 nframes)
{
    if (worker)
        worker->processWorkResponses();
    
    lilv_instance_run (instance, nframes);
    
    if (worker)
        worker->endRun();
}
Example #3
0
void EFFECT_LV2::process(void)
{
  for(unsigned long m = 0; m < plugins_rep.size(); m++)
    lilv_instance_run(plugins_rep[m]->me, buffer_repp->length_in_samples());
}
Example #4
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;
}
Example #5
0
static GstFlowReturn
gst_lv2_source_fill (GstBaseSrc * base, guint64 offset,
    guint length, GstBuffer * buffer)
{
  GstLV2Source *lv2 = (GstLV2Source *) base;
  GstLV2SourceClass *klass = (GstLV2SourceClass *) GST_BASE_SRC_GET_CLASS (lv2);
  GstLV2Class *lv2_class = &klass->lv2;
  GstLV2Group *lv2_group;
  GstLV2Port *lv2_port;
  GstClockTime next_time;
  gint64 next_sample, next_byte;
  guint bytes, samples;
  GstElementClass *eclass;
  GstMapInfo map;
  gint samplerate, bpf;
  guint j, k, l;
  gfloat *out = NULL, *cv = NULL, *mem;
  gfloat val;

  /* example for tagging generated data */
  if (!lv2->tags_pushed) {
    GstTagList *taglist;

    taglist = gst_tag_list_new (GST_TAG_DESCRIPTION, "lv2 wave", NULL);

    eclass = GST_ELEMENT_CLASS (parent_class);
    if (eclass->send_event)
      eclass->send_event (GST_ELEMENT (base), gst_event_new_tag (taglist));
    else
      gst_tag_list_unref (taglist);
    lv2->tags_pushed = TRUE;
  }

  if (lv2->eos_reached) {
    GST_INFO_OBJECT (lv2, "eos");
    return GST_FLOW_EOS;
  }

  samplerate = GST_AUDIO_INFO_RATE (&lv2->info);
  bpf = GST_AUDIO_INFO_BPF (&lv2->info);

  /* if no length was given, use our default length in samples otherwise convert
   * the length in bytes to samples. */
  if (length == -1)
    samples = lv2->samples_per_buffer;
  else
    samples = length / bpf;

  /* if no offset was given, use our next logical byte */
  if (offset == -1)
    offset = lv2->next_byte;

  /* now see if we are at the byteoffset we think we are */
  if (offset != lv2->next_byte) {
    GST_DEBUG_OBJECT (lv2, "seek to new offset %" G_GUINT64_FORMAT, offset);
    /* we have a discont in the expected sample offset, do a 'seek' */
    lv2->next_sample = offset / bpf;
    lv2->next_time =
        gst_util_uint64_scale_int (lv2->next_sample, GST_SECOND, samplerate);
    lv2->next_byte = offset;
  }

  /* check for eos */
  if (lv2->check_seek_stop &&
      (lv2->sample_stop > lv2->next_sample) &&
      (lv2->sample_stop < lv2->next_sample + samples)
      ) {
    /* calculate only partial buffer */
    lv2->generate_samples_per_buffer = lv2->sample_stop - lv2->next_sample;
    next_sample = lv2->sample_stop;
    lv2->eos_reached = TRUE;

    GST_INFO_OBJECT (lv2, "eos reached");
  } else {
    /* calculate full buffer */
    lv2->generate_samples_per_buffer = samples;
    next_sample = lv2->next_sample + (lv2->reverse ? (-samples) : samples);
  }

  bytes = lv2->generate_samples_per_buffer * bpf;

  next_byte = lv2->next_byte + (lv2->reverse ? (-bytes) : bytes);
  next_time = gst_util_uint64_scale_int (next_sample, GST_SECOND, samplerate);

  GST_LOG_OBJECT (lv2, "samplerate %d", samplerate);
  GST_LOG_OBJECT (lv2,
      "next_sample %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT, next_sample,
      GST_TIME_ARGS (next_time));

  gst_buffer_set_size (buffer, bytes);

  GST_BUFFER_OFFSET (buffer) = lv2->next_sample;
  GST_BUFFER_OFFSET_END (buffer) = next_sample;
  if (!lv2->reverse) {
    GST_BUFFER_TIMESTAMP (buffer) = lv2->timestamp_offset + lv2->next_time;
    GST_BUFFER_DURATION (buffer) = next_time - lv2->next_time;
  } else {
    GST_BUFFER_TIMESTAMP (buffer) = lv2->timestamp_offset + next_time;
    GST_BUFFER_DURATION (buffer) = lv2->next_time - next_time;
  }

  gst_object_sync_values (GST_OBJECT (lv2), GST_BUFFER_TIMESTAMP (buffer));

  lv2->next_time = next_time;
  lv2->next_sample = next_sample;
  lv2->next_byte = next_byte;

  GST_LOG_OBJECT (lv2, "generating %u samples at ts %" GST_TIME_FORMAT,
      samples, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));

  gst_buffer_map (buffer, &map, GST_MAP_WRITE);

  /* multi channel outputs */
  lv2_group = &lv2_class->out_group;
  if (lv2_group->ports->len > 1) {
    out = g_new0 (gfloat, samples * lv2_group->ports->len);
    for (j = 0; j < lv2_group->ports->len; ++j) {
      lv2_port = &g_array_index (lv2_group->ports, GstLV2Port, j);
      lilv_instance_connect_port (lv2->lv2.instance, lv2_port->index,
          out + (j * samples));
      GST_LOG_OBJECT (lv2, "connected port %d/%d", j, lv2_group->ports->len);
    }
  } else {
    lv2_port = &g_array_index (lv2_group->ports, GstLV2Port, 0);
    lilv_instance_connect_port (lv2->lv2.instance, lv2_port->index,
        (gfloat *) map.data);
    GST_LOG_OBJECT (lv2, "connected port 0");
  }

  /* cv ports */
  cv = g_new (gfloat, samples * lv2_class->num_cv_in);
  for (j = k = 0; j < lv2_class->control_in_ports->len; j++) {
    lv2_port = &g_array_index (lv2_class->control_in_ports, GstLV2Port, j);
    if (lv2_port->type != GST_LV2_PORT_CV)
      continue;

    mem = cv + (k * samples);
    val = lv2->lv2.ports.control.in[j];
    /* FIXME: use gst_control_binding_get_value_array */
    for (l = 0; l < samples; l++)
      mem[l] = val;
    lilv_instance_connect_port (lv2->lv2.instance, lv2_port->index, mem);
    k++;
  }

  lilv_instance_run (lv2->lv2.instance, samples);

  if (lv2_group->ports->len > 1) {
    gst_lv2_source_interleave_data (lv2_group->ports->len,
        (gfloat *) map.data, samples, out);
    g_free (out);
  }

  g_free (cv);

  gst_buffer_unmap (buffer, &map);

  return GST_FLOW_OK;
}
Example #6
0
void Lv2Plugin::doProcess(bool rolling, jack_position_t &pos, jack_nframes_t nframes, jack_nframes_t time) {

    // pull in new control mappings
    Lv2ControlMapping *freshMapping;
    while(newControlMappingsQueue.pop(freshMapping)) {
        freshMapping->getConnection()->addMapping(freshMapping);
    }

    // process MIDI inputs
    Lv2MidiInput *midiInput = midiInputList.getFirst();
    while(midiInput) {
        midiInput->process(rolling, pos, nframes, time);
        midiInput = midiInputList.getNext(midiInput);
    }

    // process and connect audio inputs
    for(uint32_t i = 0; i < audioInputCount; i++) {
        AudioConnection *connection = audioInput[i].getConnection();
        if(connection) {
            connection->getSource()->process(rolling, pos, nframes, time);
            lilv_instance_connect_port(instance, audioInputIndex[i], connection->getAudio());
        } else {
            lilv_instance_connect_port(instance, audioInputIndex[i], AudioConnection::getDummyBuffer());
        }
    }

    // update control port values from scheduled control events
    Lv2ControlEvent* evt = controlBuffer.getNextEvent(rolling, pos, nframes);
    while(evt) {
        evt->getPort()->value = evt->getValue();
        ObjectCollector::scriptCollector().recycle(evt);
        evt = controlBuffer.getNextEvent(rolling, pos, nframes);
    }

    // process control connections
    Lv2ControlConnection *connection = this->controlConnections.getFirst();
    while(connection) {
        connection->process(rolling, pos, nframes, time);
        connection = controlConnections.getNext(connection);
    }

    // clear event output buffers
    Lv2MidiOutput *midiOutput = midiOutputList.getFirst();
    while(midiOutput) {
        midiOutput->clear();
        midiOutput = midiOutputList.getNext(midiOutput);
    }

    // set up audio output buffers
    for(uint32_t i = 0; i < audioOutputCount; i++) {
        lilv_instance_connect_port(instance, audioOutputIndex[i], audioOutput[i]->getAudio());
    }

    // run the plugin
    lilv_instance_run(instance, nframes);

    // fire MIDI events
    fireMidiEvents(pos);

    // emit worker responses
    if(worker) {
        worker->respond();
    }
}
Example #7
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;
}