24 #ifndef LVTK_LV2_SYNTH_HPP
25 #define LVTK_LV2_SYNTH_HPP
31 #include <lvtk/plugin.hpp>
38 static const unsigned char INVALID_KEY = 255;
43 static inline float key2hz(
unsigned char key) {
44 return 8.1758 * std::pow(1.0594, key);
64 void on(
unsigned char key,
unsigned char velocity) { }
70 void off(
unsigned char velocity) { }
76 unsigned char get_key()
const {
return lvtk::INVALID_KEY; }
83 void render(uint32_t from, uint32_t to) { }
89 void set_port_buffers(vector<void*>& ports) { m_ports = &ports; }
94 template <
typename T>
inline T*&
p(uint32_t port) {
95 return reinterpret_cast<T*&
>((*m_ports)[port]);
99 float*&
p(uint32_t port) {
100 return reinterpret_cast<float*&
>((*m_ports)[port]);
104 vector<void*>* m_ports;
181 template <
class V,
class D,
182 class Ext1 = end,
class Ext2 = end,
class Ext3 = end,
183 class Ext4 = end,
class Ext5 = end,
class Ext6 = end,
185 class Synth :
public Plugin<D, URID<true>, Ext1, Ext2, Ext3, Ext4, Ext5, Ext6, Ext7>
199 Synth(uint32_t ports, uint32_t midi_input)
201 m_midi_input (midi_input)
203 m_midi_type = Parent::map (LV2_MIDI__MidiEvent);
210 for (
unsigned i = 0; i < m_voices.size(); ++i)
227 for (
unsigned i = 0; i < m_voices.size(); ++i)
229 if (m_voices[i]->get_key() == lvtk::INVALID_KEY)
251 if (size != 3)
return;
252 LV2_Midi_Message_Type type (lv2_midi_message_type (data));
258 if (voice < m_voices.size())
259 m_voices[voice]->on(data[1], data[2]);
261 else if (data[0] == 0x80)
263 for (
unsigned i = 0; i < m_voices.size(); ++i)
265 if (m_voices[i]->get_key() == data[1])
267 m_voices[i]->off(data[2]);
275 handle_atom_event (LV2_Atom_Event* ev) { }
313 run(uint32_t sample_count)
315 D* synth =
static_cast<D*
>(
this);
318 for (
unsigned i = 0; i < m_audio_ports.size(); ++i)
319 std::memset(
p(m_audio_ports[i]), 0,
sizeof(float) * sample_count);
322 for (
unsigned i = 0; i < m_voices.size(); ++i)
323 m_voices[i]->set_port_buffers(Parent::m_ports);
325 const LV2_Atom_Sequence* seq = p<LV2_Atom_Sequence> (m_midi_input);
326 uint32_t last_frame = 0;
328 for (LV2_Atom_Event* ev = lv2_atom_sequence_begin (&seq->body);
329 !lv2_atom_sequence_is_end(&seq->body, seq->atom.size, ev);
330 ev = lv2_atom_sequence_next (ev))
332 synth->pre_process (last_frame, ev->time.frames);
333 for (uint32_t i = 0; i < m_voices.size(); ++i)
334 m_voices[i]->render (last_frame, ev->time.frames);
335 synth->post_process (last_frame, ev->time.frames);
337 if (ev->body.type == m_midi_type)
338 synth->handle_midi (ev->body.size, (uint8_t*) LV2_ATOM_BODY (&ev->body));
340 synth->handle_atom_event (ev);
342 last_frame = ev->time.frames;
345 if (last_frame < sample_count)
347 synth->pre_process (last_frame, sample_count);
348 for (uint32_t i = 0; i < m_voices.size(); ++i)
349 m_voices[i]->render (last_frame, sample_count);
350 synth->post_process (last_frame, sample_count);
368 uint32_t p3 = -1, uint32_t p4 = -1,
369 uint32_t p5 = -1, uint32_t p6 = -1)
371 if (p1 == uint32_t(-1))
373 m_audio_ports.push_back(p1);
374 if (p2 == uint32_t(-1))
376 m_audio_ports.push_back(p2);
377 if (p3 == uint32_t(-1))
379 m_audio_ports.push_back(p3);
380 if (p4 == uint32_t(-1))
382 m_audio_ports.push_back(p4);
383 if (p5 == uint32_t(-1))
385 m_audio_ports.push_back(p5);
386 if (p6 == uint32_t(-1))
388 m_audio_ports.push_back(p6);
402 void add_voices(V* v01 = 0, V* v02 = 0, V* v03 = 0, V* v04 = 0, V* v05 = 0,
403 V* v06 = 0, V* v07 = 0, V* v08 = 0, V* v09 = 0, V* v10 = 0,
404 V* v11 = 0, V* v12 = 0, V* v13 = 0, V* v14 = 0, V* v15 = 0,
405 V* v16 = 0, V* v17 = 0, V* v18 = 0, V* v19 = 0, V* v20 = 0)
409 m_voices.push_back(v01);
412 m_voices.push_back(v02);
415 m_voices.push_back(v03);
418 m_voices.push_back(v04);
421 m_voices.push_back(v05);
424 m_voices.push_back(v06);
427 m_voices.push_back(v07);
430 m_voices.push_back(v08);
433 m_voices.push_back(v09);
436 m_voices.push_back(v10);
439 m_voices.push_back(v11);
442 m_voices.push_back(v12);
445 m_voices.push_back(v13);
448 m_voices.push_back(v14);
451 m_voices.push_back(v15);
454 m_voices.push_back(v16);
457 m_voices.push_back(v17);
460 m_voices.push_back(v18);
463 m_voices.push_back(v19);
466 m_voices.push_back(v20);
473 template <
typename T> T*&
475 return reinterpret_cast<T*&
>(Parent::m_ports[port]);
481 return reinterpret_cast<float*&
>(Parent::m_ports[port]);
488 vector<uint32_t> m_audio_ports;
491 uint32_t m_midi_input;
494 LV2_URID m_midi_type;