On Wed, 2008-04-16 at 18:36 +0200, Pau Arumí Albó
wrote:
Luthman va escriure:
This is a development tool, but I'm sending
it to the LAU list as well
in case there are any not-yet-hackers who would like to start writing
effects or synths. It's easy, I promise. Here's the code you would need
to write for a simple gain effect:
#include <lv2plugin.hpp>
#include "gain.peg"
class Gain : public LV2::Plugin<Gain> {
public:
Gain(double rate) : LV2::Plugin<Gain>(p_n_ports) { }
void run(uint32_t nframes) {
for (uint32_t i = 0; i < nframes; ++i)
p(p_out)[i] = p(p_gain) * p(p_in);
}
};
static int _ = Gain::register_class("http://my.plugin/");
This is simple indeed.
However, this code brings me some questions. Are all variables (p,
p_out, p_in, p_gain) declared as Plugin base class members?
It does not make much sense to me that "p_gain" is a generic
control/member?
What about p_n_ports? Seems undefined to me.
( Also i assume that p(p_in) should be p(p_in)[i] )
Hmmm, i smell that gain.peg might be the answer to some of this
questions. Could you explain what goes in there?
float* p(uint32_t i) is a member function of LV2::Plugin that returns
the buffer for the port with index i. LV2::Plugin handles all port
connecting (unless you override connect_port()) so some way of accessing
the buffers is needed.
LV2 plugins have two parts, code (seen above) and data, which is stored
in RDF files. These data files contain, among other things, descriptions
of the plugin's ports. In this case the plugin has three ports, one
audio input, one audio output and one control input. Each port has an
index (starting from 0 and counting upwards) and a "symbol", in this
case "in", "out", and "gain".
The symbols are for the hosts to use as nice descriptive (and
programming language friendly) identifiers for ports in e.g. scripting.
In the code for the plugin code you need to reference the ports by
index. But lv2-c++-tools contains a program called lv2peg that generates
a C header file (gain.peg in this case) from an RDF data file, with an
enum that maps port symbols to indices, like this:
enum { p_in, p_out, p_gain, p_n_ports };
"p" is a prefix that was defined in the RDF file and is used in case
someone would have data for multiple plugins in the same RDF file.
So basically it's just a more descriptive way of referencing plugin
ports. You could just as well use the indices and the number of ports
directly and don't bother with lv2peg, but it's nice to have while
working on a plugin with lots of ports where you may remove and add
ports while hacking, or change ranges and default values (those things
are also included in the output of lv2peg). There is more info and some
examples at
http://lv2plug.in/lv2pftci/
Now it all makes sense. Thanks.
However I'd like to see the entire example (the link lv2pftci seems
dead). If available, could you point to the generated gain.peg and the
human written RDF? (Or an equivalent example)
Cheers,
Pau