diff --git a/lv2-examples/beep2/Makefile b/lv2-examples/beep2/Makefile new file mode 100644 index 0000000..49351e4 --- /dev/null +++ b/lv2-examples/beep2/Makefile @@ -0,0 +1,23 @@ +BUNDLE = lv2pftci-beep2.lv2 +INSTALL_DIR = /home/pi/zynthian/zynthian-plugins/mod-lv2 + + +$(BUNDLE): manifest.ttl beep2.ttl beep2.so + rm -rf $(BUNDLE) + mkdir $(BUNDLE) + cp $^ $(BUNDLE) + +beep2.so: beep.cpp beep.peg + g++ -shared -fPIC -DPIC beep.cpp -I. -I/usr/local/include/lvtk-2 -L/usr/local/lib -llvtk_plugin2 -o beep2.so + +beep.peg: beep2.ttl + lv2peg beep2.ttl beep.peg + +install: $(BUNDLE) + mkdir -p $(INSTALL_DIR) + rm -rf $(INSTALL_DIR)/$(BUNDLE) + cp -R $(BUNDLE) $(INSTALL_DIR) + +clean: + rm -rf $(BUNDLE) beep2.so beep.peg + diff --git a/lv2-examples/beep2/beep.cpp b/lv2-examples/beep2/beep.cpp new file mode 100644 index 0000000..3d873b9 --- /dev/null +++ b/lv2-examples/beep2/beep.cpp @@ -0,0 +1,94 @@ +// from: http://ll-plugins.nongnu.org/lv2pftci/#A_synth + +#include +#include "beep.peg" + +class BeepVoice : public lvtk::Voice { +public: + + BeepVoice(double rate) + : m_key(lvtk::INVALID_KEY), m_rate(rate), m_period(10), m_counter(0) { + + } + + void on(unsigned char key, unsigned char velocity) { + m_key = key; + m_period = m_rate * 4.0 / lvtk::key2hz(m_key); + m_pos = std::rand() / float(RAND_MAX); + m_envelope = velocity / 128.0; + } + + void off(unsigned char velocity) { + m_key = lvtk::INVALID_KEY; + } + + unsigned char get_key() const { + return m_key; + } + + void render(uint32_t from, uint32_t to) { + if (m_key == lvtk::INVALID_KEY) + return; + for (uint32_t i = from; i < to; ++i) { + float pwm = *p(p_pwm) + (1 - *p(p_pwm)) * m_envelope; + float s = -0.25 + 0.5 * (m_counter > m_period * (1 + pwm) / 2); + m_counter = (m_counter + 1) % m_period; + p(p_left)[i] += (1 - m_pos) * s; + p(p_right)[i] += m_pos * s; + if (m_envelope > 0) + m_envelope -= 0.5 / m_rate; + } + } + +protected: + + unsigned char m_key; + double m_rate; + uint32_t m_period; + uint32_t m_counter; + float m_pos; + float m_envelope; + +}; + + +class Beep : public lvtk::Synth { +public: + + Beep(double rate) + : lvtk::Synth(p_n_ports, p_midi), + m_buf_pos(0), m_delay(rate / 3), + m_l_buffer(new float[m_delay]), m_r_buffer(new float[m_delay]) { + add_voices(new BeepVoice(rate), new BeepVoice(rate), new BeepVoice(rate)); + add_audio_outputs(p_left, p_right); + for (unsigned i = 0; i < m_delay; ++i) { + m_l_buffer[i] = 0; + m_r_buffer[i] = 0; + } + } + + void post_process(uint32_t from, uint32_t to) { + for (uint32_t i = from; i < to; ++i) { + float mono = (p(p_left)[i] + p(p_right)[i]) / 2; + p(p_left)[i] += m_l_buffer[m_buf_pos]; + p(p_right)[i] += m_r_buffer[m_buf_pos]; + float tmp = m_l_buffer[m_buf_pos]; + m_l_buffer[m_buf_pos] = 0.6 * (mono + m_r_buffer[m_buf_pos]); + m_r_buffer[m_buf_pos] = 0.6 * tmp; + m_buf_pos = (m_buf_pos + 1) % m_delay; + p(p_left)[i] *= *p(p_gain); + p(p_right)[i] *= *p(p_gain); + } + } + +protected: + + unsigned m_buf_pos; + unsigned m_delay; + float* m_l_buffer; + float* m_r_buffer; + +}; + + +static int _ = Beep::register_class(p_uri); diff --git a/lv2-examples/beep2/beep.peg b/lv2-examples/beep2/beep.peg new file mode 100644 index 0000000..4f6689f --- /dev/null +++ b/lv2-examples/beep2/beep.peg @@ -0,0 +1,39 @@ +#ifndef beep_peg +#define beep_peg + + +#ifndef PEG_STRUCT +#define PEG_STRUCT +typedef struct { + float min; + float max; + float default_value; + char toggled; + char integer; + char logarithmic; +} peg_data_t; +#endif + +/* */ + +static const char p_uri[] = "http://ll-plugins.nongnu.org/lv2/lv2pftci/beep2"; + +enum p_port_enum { + p_midi, + p_left, + p_right, + p_pwm, + p_gain, + p_n_ports +}; + +static const peg_data_t p_ports[] = { + { -3.40282e+38, 3.40282e+38, -3.40282e+38, 0, 0, 0 }, + { -3.40282e+38, 3.40282e+38, -3.40282e+38, 0, 0, 0 }, + { -3.40282e+38, 3.40282e+38, -3.40282e+38, 0, 0, 0 }, + { 0, 1, 0.5, 0, 0, 0 }, + { 0, 2, 1, 0, 0, 0 }, +}; + + +#endif /* beep_peg */ diff --git a/lv2-examples/beep2/beep2.ttl b/lv2-examples/beep2/beep2.ttl new file mode 100644 index 0000000..c9d3d90 --- /dev/null +++ b/lv2-examples/beep2/beep2.ttl @@ -0,0 +1,69 @@ +@prefix lv2: . +@prefix doap: . +@prefix rdf: . +@prefix rdfs: . +@prefix ll: . +@prefix pg: . +@prefix ev: . +@prefix atom: . + + a pg:StereoGroup. + + + a lv2:Plugin, lv2:InstrumentPlugin; + lv2:binary ; + doap:name "Beep2"; + doap:license ; + ll:pegName "p"; + + lv2:port [ + a lv2:InputPort, atom:AtomPort ; + atom:bufferType atom:Sequence ; + atom:supports ; + lv2:index 0; + ev:supportsEvent ; + lv2:symbol "midi"; + lv2:name "MIDI"; + ], + + [ + a lv2:AudioPort, lv2:OutputPort; + lv2:index 1; + lv2:symbol "left"; + lv2:name "Left"; + pg:membership [ + pg:group ; + pg:role pg:leftChannel; + ]; + ], + + [ + a lv2:AudioPort, lv2:OutputPort; + lv2:index 2; + lv2:symbol "right"; + lv2:name "Right"; + pg:membership [ + pg:group ; + pg:role pg:rightChannel; + ]; + ], + + [ + a lv2:ControlPort, lv2:InputPort; + lv2:index 3; + lv2:symbol "pwm"; + lv2:name "PWM"; + lv2:minimum 0; + lv2:maximum 1; + lv2:default 0.5; + ], + + [ + a lv2:ControlPort, lv2:InputPort; + lv2:index 4; + lv2:symbol "gain"; + lv2:name "Gain"; + lv2:minimum 0; + lv2:maximum 2; + lv2:default 1; + ]. diff --git a/lv2-examples/beep2/lv2pftci-beep2.lv2/beep2.ttl b/lv2-examples/beep2/lv2pftci-beep2.lv2/beep2.ttl new file mode 100644 index 0000000..c9d3d90 --- /dev/null +++ b/lv2-examples/beep2/lv2pftci-beep2.lv2/beep2.ttl @@ -0,0 +1,69 @@ +@prefix lv2: . +@prefix doap: . +@prefix rdf: . +@prefix rdfs: . +@prefix ll: . +@prefix pg: . +@prefix ev: . +@prefix atom: . + + a pg:StereoGroup. + + + a lv2:Plugin, lv2:InstrumentPlugin; + lv2:binary ; + doap:name "Beep2"; + doap:license ; + ll:pegName "p"; + + lv2:port [ + a lv2:InputPort, atom:AtomPort ; + atom:bufferType atom:Sequence ; + atom:supports ; + lv2:index 0; + ev:supportsEvent ; + lv2:symbol "midi"; + lv2:name "MIDI"; + ], + + [ + a lv2:AudioPort, lv2:OutputPort; + lv2:index 1; + lv2:symbol "left"; + lv2:name "Left"; + pg:membership [ + pg:group ; + pg:role pg:leftChannel; + ]; + ], + + [ + a lv2:AudioPort, lv2:OutputPort; + lv2:index 2; + lv2:symbol "right"; + lv2:name "Right"; + pg:membership [ + pg:group ; + pg:role pg:rightChannel; + ]; + ], + + [ + a lv2:ControlPort, lv2:InputPort; + lv2:index 3; + lv2:symbol "pwm"; + lv2:name "PWM"; + lv2:minimum 0; + lv2:maximum 1; + lv2:default 0.5; + ], + + [ + a lv2:ControlPort, lv2:InputPort; + lv2:index 4; + lv2:symbol "gain"; + lv2:name "Gain"; + lv2:minimum 0; + lv2:maximum 2; + lv2:default 1; + ]. diff --git a/lv2-examples/beep2/lv2pftci-beep2.lv2/manifest.ttl b/lv2-examples/beep2/lv2pftci-beep2.lv2/manifest.ttl new file mode 100644 index 0000000..1516813 --- /dev/null +++ b/lv2-examples/beep2/lv2pftci-beep2.lv2/manifest.ttl @@ -0,0 +1,5 @@ +@prefix lv2: . +@prefix rdfs: . + + a lv2:Plugin; + rdfs:seeAlso . diff --git a/lv2-examples/beep2/manifest.ttl b/lv2-examples/beep2/manifest.ttl new file mode 100644 index 0000000..1516813 --- /dev/null +++ b/lv2-examples/beep2/manifest.ttl @@ -0,0 +1,5 @@ +@prefix lv2: . +@prefix rdfs: . + + a lv2:Plugin; + rdfs:seeAlso .