LV2 Toolkit  1.2.0
Public Types | Public Member Functions | Static Public Member Functions | Protected Member Functions | Protected Attributes | List of all members
Synth< V, D, Ext1, Ext2, Ext3, Ext4, Ext5, Ext6, Ext7 > Class Template Reference

#include <synth.hpp>

Collaboration diagram for Synth< V, D, Ext1, Ext2, Ext3, Ext4, Ext5, Ext6, Ext7 >:
Collaboration graph
[legend]

Public Types

typedef Plugin< D, URID< true >, Ext1, Ext2, Ext3, Ext4, Ext5, Ext6, Ext7 > Parent
 

Public Member Functions

 Synth (uint32_t ports, uint32_t midi_input)
 
 ~Synth ()
 
unsigned find_free_voice (unsigned char key, unsigned char velocity)
 
void handle_midi (uint32_t size, unsigned char *data)
 
void handle_atom_event (LV2_Atom_Event *ev)
 
void pre_process (uint32_t from, uint32_t to)
 
void post_process (uint32_t from, uint32_t to)
 
void run (uint32_t sample_count)
 
void add_audio_outputs (uint32_t p1=-1, uint32_t p2=-1, uint32_t p3=-1, uint32_t p4=-1, uint32_t p5=-1, uint32_t p6=-1)
 
void add_voices (V *v01=0, V *v02=0, V *v03=0, V *v04=0, V *v05=0, V *v06=0, V *v07=0, V *v08=0, V *v09=0, V *v10=0, V *v11=0, V *v12=0, V *v13=0, V *v14=0, V *v15=0, V *v16=0, V *v17=0, V *v18=0, V *v19=0, V *v20=0)
 
void connect_port (uint32_t port, void *data_location)
 
void activate ()
 
void deactivate ()
 
bool check_ok ()
 

Static Public Member Functions

static unsigned register_class (const char *uri)
 

Protected Member Functions

template<typename T >
T *& p (uint32_t port)
 
float *& p (uint32_t port)
 
const char * bundle_path () const
 
void set_ok (bool ok)
 

Protected Attributes

vector< V * > m_voices
 
vector< uint32_t > m_audio_ports
 
uint32_t m_midi_input
 
LV2_URID m_midi_type
 
std::vector< void * > m_ports
 

Detailed Description

template<class V, class D, class Ext1 = end, class Ext2 = end, class Ext3 = end, class Ext4 = end, class Ext5 = end, class Ext6 = end, class Ext7 = end>
class lvtk::Synth< V, D, Ext1, Ext2, Ext3, Ext4, Ext5, Ext6, Ext7 >

This is a base class template for LV2 synth plugins. Its parameters are a voice class, either a subclass of Voice or something written from scratch, and the derived class itself. By using the derived class as a template parameter the base class can call member functions in the derived class without resorting to virtual function calls, which are hard to optimise.

You can use mixins with this class just like with the Plugin class, but don't use URID - they are already added automatically.

Here is an example of a complete synth plugin. Granted, not a very exciting one, but it should be enough to explain how to do it:

#include <cstdlib>
#include <lvtk/synth.hpp>
enum {
MIDI_PORT,
AUDIO_PORT,
NUM_PORTS
};
struct NoiseVoice : public lvtk::Voice {
NoiseVoice() : m_gain(0), m_key(INVALID_KEY) { }
void on(unsigned char k, unsigned char velocity) {
m_gain = 1.0;
m_key = k;
}
void off(unsigned char velocity) {
m_gain = 0.0;
m_key = lvtk::INVALID_KEY;
}
unsigned char get_key() const {
return m_key;
}
void render(uint32_t from, uint32_t to) {
for (uint32_t i = from; i < to; ++i) {
p(AUDIO_PORT)[i] += m_gain * 2 * (rand() / float(RAND_MAX) - 0.5);
m_gain *= 0.9999;
}
}
float m_gain;
unsigned char m_key;
};
struct NoiseSynth : public lvtk::Synth<NoiseVoice, NoiseSynth> {
NoiseSynth(double)
: lvtk::Synth<NoiseVoice, NoiseSynth>(NUM_PORTS, MIDI_PORT), m_filterstate(0) {
add_voices(new NoiseVoice, new NoiseVoice, new NoiseVoice);
add_audio_outputs(AUDIO_PORT);
}
void post_process(uint32_t from, uint32_t to) {
for (uint32_t i = from; i < to; ++i) {
p(AUDIO_PORT)[i] = m_filterstate * 0.9 + p(AUDIO_PORT)[i] * 0.1;
m_filterstate = p(AUDIO_PORT)[i];
}
}
float m_filterstate;
};
Examples:
beep.cpp.

Constructor & Destructor Documentation

Synth ( uint32_t  ports,
uint32_t  midi_input 
)
inline

This constructor must be called in the initialiser list for your synth class.

Parameters
portsThe total number of ports in your plugin.
midi_inputThe index of the main MIDI input port (the one that the synth should use for note input).
~Synth ( )
inline

This is needed to delete the voices.

Member Function Documentation

void activate ( )
inlineinherited

Override this function if you need to do anything on activation. This is always called before the host starts using the run() function. You should reset your plugin to it's initial state here.

void add_audio_outputs ( uint32_t  p1 = -1,
uint32_t  p2 = -1,
uint32_t  p3 = -1,
uint32_t  p4 = -1,
uint32_t  p5 = -1,
uint32_t  p6 = -1 
)
inline

This should be called in the constructor of your derived class to tell the synth which ports the voices are using as audio output buffers, so the synth engine can fill them with zeros before rendering the voice audio.

If you for some reason don't want to zero your audio output buffers before the voices get mixed (you may for example want to fill them with something else in pre_process()) you should not call this function - but then you MUST take care of initialising the buffers yourself in every cycle.

void add_voices ( V *  v01 = 0,
V *  v02 = 0,
V *  v03 = 0,
V *  v04 = 0,
V *  v05 = 0,
V *  v06 = 0,
V *  v07 = 0,
V *  v08 = 0,
V *  v09 = 0,
V *  v10 = 0,
V *  v11 = 0,
V *  v12 = 0,
V *  v13 = 0,
V *  v14 = 0,
V *  v15 = 0,
V *  v16 = 0,
V *  v17 = 0,
V *  v18 = 0,
V *  v19 = 0,
V *  v20 = 0 
)
inline

This is typically called in the constructor of your derived class to add voices to the synth. The number of voices you add determine the polyphony. It can also be called while the plugin is running to change the polyphony on the fly, but it is NOT realtime safe and NOT threadsafe - you have to make sure that the run() callback isn't executing simultaneously with this function.

lvtk::Synth will assume ownership of the voices and delete them in its destructor.

const char* bundle_path ( ) const
inlineprotectedinherited

Returns the filesystem path to the bundle that contains this plugin. This may only be called after the plugin constructor is done executing.

void connect_port ( uint32_t  port,
void *  data_location 
)
inlineinherited

Connects the ports. You shouldn't have to override this, just use p() to access the port buffers.

If you do override this function, remember that if you want your plugin to be realtime safe this function may not block, allocate memory or otherwise take a long time to return.

Parameters
portThe index of the port to connect.
data_locationThe buffer to connect it to.
void deactivate ( )
inlineinherited

Override this function if you need to do anything on deactivation. The host calls this when it does not plan to make any more calls to run() (unless it calls activate() again).

unsigned find_free_voice ( unsigned char  key,
unsigned char  velocity 
)
inline

This function implements the voice stealing algorithm. The key and velocity arguments are the parameters for the MIDI Note On event that needs a voice. This default implementation just returns the first free voice, and if there is none it steals voice 0.

This is not a virtual function, but if you override it in a subclass this class will still use that implementation thanks to the second template class parameter. This means that you can override this function if you want to implement your own voice stealing algorithm.

void handle_midi ( uint32_t  size,
unsigned char *  data 
)
inline

This function is called for every MIDI event in the input. It will respond to note on and note off events by calling on() and off() in the voices.

This is not a virtual function, but if you override it in a subclass this class will still use that implementation thanks to the second template class parameter. This means that you can override this function if you want to respond to other MIDI events - just be sure to either call this function for note on and note off events or turn on and off the voices yourself.

T*& p ( uint32_t  port)
inlineprotected

Use this function to access data buffers for ports. They will be casted to pointers to the template parameter T.

float*& p ( uint32_t  port)
inlineprotected

Use this function to access data buffers for control or audio ports.

void post_process ( uint32_t  from,
uint32_t  to 
)
inline

This function is called after the synth renders a chunk of audio from the voices, from sample from to sample to in the output buffers. It can be used to apply global effects to the mixed audio. This default implementation does nothing.

This is not a virtual function, but if you override it in a subclass this class will still use that implementation thanks to the second template class parameter. This means that you can override this function if you want to implement your own post-processing.

void pre_process ( uint32_t  from,
uint32_t  to 
)
inline

This function is called before the synth renders a chunk of audio from the voices, from sample from to sample to in the output buffers. It can be used to compute parameters for the voices or adding initial ambient noise to the output buffers or something else. This default implementation does nothing.

This is not a virtual function, but if you override it in a subclass this class will still use that implementation thanks to the second template class parameter. This means that you can override this function if you want to implement your own pre-processing.

static unsigned register_class ( const char *  uri)
inlinestaticinherited

Use this function to register your plugin class so that the host can find it. You need to do this when the shared library is loaded by the host. One portable way of doing that is to put the function call in the initialiser for a global variable, like this:

unsigned _ = MypluginClass::register_class("http://my.plugin.class");
The return value is not important, it's just there so you can use that
trick.
void run ( uint32_t  sample_count)
inline

This is the main run function. It handles incoming MIDI events and mixes the voices to the output buffers with pre and post-processing applied. Don't override it unless you really know what you're doing.

void set_ok ( bool  ok)
inlineprotectedinherited

Sets the OK state of the plugin. If it's true (which is the default) the plugin has been instantiated OK, if false it has not and the host will discard it. You can call this in the constructor for your plugin class if you need to check some condition that isn't taken care of by a mixin.

Parameters
okTrue if the plugin instance is OK and can be used, false if it should be discarded.

The documentation for this class was generated from the following file: