[LAD] LV2::Synth from one note to another

Phil CM philcm at gnu.org
Wed Oct 8 14:00:21 UTC 2014


On 08/10/14 13:36, Raine M. Ekman wrote:
>> Phil CM <philcm at gnu.org> wrote:
>>> Now the only think that is left is a portamento function, to go from
>>> one note to another (/exactly/ like so-404
>>> <http://d00m.org/%7Esomeone/so404/> does).
>
>>> Does anyone know the algorithm to implement that? That would really
>>> help me.
>
> Quoting Philipp Überbacher <murks at tuxfamily.org>:
>> I have never done this but I suggest to look at the calf monosynth
>> code. AFAIR it has a couple of different ways to handle
>> successive/overlapping notes.
>>
>> Another synth that comes to mind and has portamento is phasex.
>
> Well, if it has to be exactly the same, I'd suggest digging in the 
> so-404 code and not in those other synths. Looks like it adjusts 
> frequency at samplerate/100, calculating:
> freq = ((portamento/127.0)*0.9)*freq + 
> (1.0-((portamento/127.0)*0.9))*tfreq;
>
> I guess tfreq is the target frequency of the note being portamented 
> towards.
>
You are probably right ; Philip's advice was good too, as the calf code 
is somehow simpler. Comparatively, the so-404 is very monolithic / 
mathematical and hard to decipher.

About this tfreq calculation, a few newbie questions. Here is my 
*entire* synth code <https://bitbucket.org/xaccrocheur/ksi> :

#include <lv2synth.hpp>
#include "ksi.peg"

class BeepVoice : public LV2::Voice {
public:

   BeepVoice(double rate)
     : m_key(LV2::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 / LV2::key2hz(m_key);
     m_envelope = velocity / 128.0;
   }

   void off(unsigned char velocity) {
     m_key = LV2::INVALID_KEY;
   }

   unsigned char get_key() const {
     return m_key;
   }

   void render(uint32_t from, uint32_t to) {
     if (m_key == LV2::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);
       // float s = -0.25 + 0.5 * (m_counter > m_period / 2);
       m_counter = (m_counter + 1) % m_period;
       p(p_left)[i] += s;
       p(p_right)[i] += 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_envelope;
};


class Beep : public LV2::Synth<BeepVoice, Beep> {
public:

   Beep(double rate)
     : LV2::Synth<BeepVoice, Beep>(p_n_ports, p_midi) {
     add_voices(new BeepVoice(rate));

     add_audio_outputs(p_left, p_right);
   }

   void post_process(uint32_t from, uint32_t to) {
     for (uint32_t i = from; i < to; ++i) {
       p(p_left)[i] *= *p(p_gain);
       p(p_right)[i] *= *p(p_gain);
     }
   }

};

static int _ = Beep::register_class(p_uri);

Apart from that there is a ksi.ttl with a

   lv2:port [
     a ev:EventPort, lv2:InputPort;
     lv2:index 0;
     ev:supportsEvent <http://lv2plug.in/ns/ext/midi#MidiEvent>;
     lv2:symbol "midi";
     lv2:name "MIDI";
   ],
(...)

Witch I understand is what somehow calls a public method in the Beep 
class, that in turns uses public methods in the BeepVoice class, who 
does the final rendering, magically connecting to

   [
     a lv2:AudioPort, lv2:OutputPort;
     lv2:index 1;
     lv2:symbol "left";
     lv2:name "Left";
     pg:membership [
       pg:group <http://ll-plugins.nongnu.org/lv2/lv2pftci/ksi/out>;
       pg:role pg:leftChannel;
     ];
   ],

   [
     a lv2:AudioPort, lv2:OutputPort;
     lv2:index 2;
     lv2:symbol "right";
     lv2:name "Right";
     pg:membership [
       pg:group <http://ll-plugins.nongnu.org/lv2/lv2pftci/ksi/out>;
       pg:role pg:rightChannel;
     ];
   ],

To output sound (and it does, and it sounds good).

In order to implement the frequency calculation, what would be the rough 
roadmap, the synthetic (so to speak) bullet points ?

Thank you for your patience.

--
Philippe
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.linuxaudio.org/pipermail/linux-audio-dev/attachments/20141008/f4d4e6bc/attachment.html>


More information about the Linux-audio-dev mailing list