<html>
  <head>
    <meta content="text/html; charset=windows-1252"
      http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <br>
    <div class="moz-cite-prefix">On 08/10/14 13:36, Raine M. Ekman
      wrote:<br>
    </div>
    <blockquote
      cite="mid:20141008153614.uuizkn38g0s8oc48@webmail1.abo.fi"
      type="cite">
      <blockquote type="cite">Phil CM <a class="moz-txt-link-rfc2396E" href="mailto:philcm@gnu.org"><philcm@gnu.org></a> wrote:
        <br>
        <blockquote type="cite">Now the only think that is left is a
          portamento function, to go from
          <br>
          one note to another (/exactly/ like so-404
          <br>
          <a class="moz-txt-link-rfc2396E" href="http://d00m.org/%7Esomeone/so404/"><http://d00m.org/%7Esomeone/so404/></a> does).
          <br>
        </blockquote>
      </blockquote>
      <br>
      <blockquote type="cite">
        <blockquote type="cite">Does anyone know the algorithm to
          implement that? That would really
          <br>
          help me.
          <br>
        </blockquote>
      </blockquote>
      <br>
      Quoting Philipp Überbacher <a class="moz-txt-link-rfc2396E" href="mailto:murks@tuxfamily.org"><murks@tuxfamily.org></a>:
      <br>
      <blockquote type="cite">I have never done this but I suggest to
        look at the calf monosynth
        <br>
        code. AFAIR it has a couple of different ways to handle
        <br>
        successive/overlapping notes.
        <br>
        <br>
        Another synth that comes to mind and has portamento is phasex.
        <br>
      </blockquote>
      <br>
      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:
      <br>
      freq = ((portamento/127.0)*0.9)*freq +
      (1.0-((portamento/127.0)*0.9))*tfreq;
      <br>
      <br>
      I guess tfreq is the target frequency of the note being
      portamented towards.
      <br>
      <br>
    </blockquote>
    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. <br>
    <br>
    About this tfreq calculation, a few newbie questions. Here is my <b>entire</b>
    synth <a href="https://bitbucket.org/xaccrocheur/ksi">code</a> :<br>
    <br>
    <tt>#include <lv2synth.hpp></tt><tt><br>
    </tt><tt>#include "ksi.peg"</tt><tt><br>
    </tt><tt><br>
    </tt><tt>class BeepVoice : public LV2::Voice {</tt><tt><br>
    </tt><tt>public:</tt><tt><br>
    </tt><tt><br>
    </tt><tt>  BeepVoice(double rate)</tt><tt><br>
    </tt><tt>    : m_key(LV2::INVALID_KEY), m_rate(rate), m_period(10),
      m_counter(0) {</tt><tt><br>
    </tt><tt>  }</tt><tt><br>
    </tt><tt><br>
    </tt><tt>  void on(unsigned char key, unsigned char velocity) {</tt><tt><br>
    </tt><tt>    m_key = key;</tt><tt><br>
    </tt><tt>    m_period = m_rate * 4.0 / LV2::key2hz(m_key);</tt><tt><br>
    </tt><tt>    m_envelope = velocity / 128.0;</tt><tt><br>
    </tt><tt>  }</tt><tt><br>
    </tt><tt><br>
    </tt><tt>  void off(unsigned char velocity) {</tt><tt><br>
    </tt><tt>    m_key = LV2::INVALID_KEY;</tt><tt><br>
    </tt><tt>  }</tt><tt><br>
    </tt><tt><br>
    </tt><tt>  unsigned char get_key() const {</tt><tt><br>
    </tt><tt>    return m_key;</tt><tt><br>
    </tt><tt>  }</tt><tt><br>
    </tt><tt><br>
    </tt><tt>  void render(uint32_t from, uint32_t to) {</tt><tt><br>
    </tt><tt>    if (m_key == LV2::INVALID_KEY)</tt><tt><br>
    </tt><tt>      return;</tt><tt><br>
    </tt><tt>    for (uint32_t i = from; i < to; ++i) {</tt><tt><br>
    </tt><tt>      float pwm = *p(p_pwm) + (1 - *p(p_pwm)) * m_envelope;</tt><tt><br>
    </tt><tt>      float s = -0.25 + 0.5 * (m_counter > m_period * (1
      + pwm) / 2);</tt><tt><br>
    </tt><tt>      // float s = -0.25 + 0.5 * (m_counter > m_period /
      2);</tt><tt><br>
    </tt><tt>      m_counter = (m_counter + 1) % m_period;</tt><tt><br>
    </tt><tt>      p(p_left)[i] += s;</tt><tt><br>
    </tt><tt>      p(p_right)[i] += s;</tt><tt><br>
    </tt><tt>      if (m_envelope > 0)</tt><tt><br>
    </tt><tt>    m_envelope -= 0.5 / m_rate;</tt><tt><br>
    </tt><tt>    }</tt><tt><br>
    </tt><tt>  }</tt><tt><br>
    </tt><tt><br>
    </tt><tt>protected:</tt><tt><br>
    </tt><tt><br>
    </tt><tt>  unsigned char m_key;</tt><tt><br>
    </tt><tt>  double m_rate;</tt><tt><br>
    </tt><tt>  uint32_t m_period;</tt><tt><br>
    </tt><tt>  uint32_t m_counter;</tt><tt><br>
    </tt><tt>  float m_envelope;</tt><tt><br>
    </tt><tt>};</tt><tt><br>
    </tt><tt><br>
    </tt><tt><br>
    </tt><tt>class Beep : public LV2::Synth<BeepVoice, Beep> {</tt><tt><br>
    </tt><tt>public:</tt><tt><br>
    </tt><tt><br>
    </tt><tt>  Beep(double rate)</tt><tt><br>
    </tt><tt>    : LV2::Synth<BeepVoice, Beep>(p_n_ports, p_midi)
      {</tt><tt><br>
    </tt><tt>    add_voices(new BeepVoice(rate));</tt><tt><br>
    </tt><tt><br>
    </tt><tt>    add_audio_outputs(p_left, p_right);</tt><tt><br>
    </tt><tt>  }</tt><tt><br>
    </tt><tt><br>
    </tt><tt>  void post_process(uint32_t from, uint32_t to) {</tt><tt><br>
    </tt><tt>    for (uint32_t i = from; i < to; ++i) {</tt><tt><br>
    </tt><tt>      p(p_left)[i] *= *p(p_gain);</tt><tt><br>
    </tt><tt>      p(p_right)[i] *= *p(p_gain);</tt><tt><br>
    </tt><tt>    }</tt><tt><br>
    </tt><tt>  }</tt><tt><br>
    </tt><tt><br>
    </tt><tt>};</tt><tt><br>
    </tt><tt><br>
    </tt><tt>static int _ = Beep::register_class(p_uri);</tt><tt><br>
    </tt><br>
    Apart from that there is a ksi.ttl with a<br>
    <br>
    <tt>  lv2:port [</tt><tt><br>
    </tt><tt>    a ev:EventPort, lv2:InputPort;</tt><tt><br>
    </tt><tt>    lv2:index 0;</tt><tt><br>
    </tt><tt>    ev:supportsEvent
      <a class="moz-txt-link-rfc2396E" href="http://lv2plug.in/ns/ext/midi#MidiEvent"><http://lv2plug.in/ns/ext/midi#MidiEvent></a>;</tt><tt><br>
    </tt><tt>    lv2:symbol "midi";</tt><tt><br>
    </tt><tt>    lv2:name "MIDI";</tt><tt><br>
    </tt><tt>  ],</tt><tt><br>
    </tt>(...)<br>
    <br>
    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 <br>
    <tt><br>
    </tt><tt>  [</tt><tt><br>
    </tt><tt>    a lv2:AudioPort, lv2:OutputPort;</tt><tt><br>
    </tt><tt>    lv2:index 1;</tt><tt><br>
    </tt><tt>    lv2:symbol "left";</tt><tt><br>
    </tt><tt>    lv2:name "Left";</tt><tt><br>
    </tt><tt>    pg:membership [</tt><tt><br>
    </tt><tt>      pg:group
      <a class="moz-txt-link-rfc2396E" href="http://ll-plugins.nongnu.org/lv2/lv2pftci/ksi/out"><http://ll-plugins.nongnu.org/lv2/lv2pftci/ksi/out></a>;</tt><tt><br>
    </tt><tt>      pg:role pg:leftChannel;</tt><tt><br>
    </tt><tt>    ];</tt><tt><br>
    </tt><tt>  ],</tt><tt><br>
    </tt><tt><br>
    </tt><tt>  [</tt><tt><br>
    </tt><tt>    a lv2:AudioPort, lv2:OutputPort;</tt><tt><br>
    </tt><tt>    lv2:index 2;</tt><tt><br>
    </tt><tt>    lv2:symbol "right";</tt><tt><br>
    </tt><tt>    lv2:name "Right";</tt><tt><br>
    </tt><tt>    pg:membership [</tt><tt><br>
    </tt><tt>      pg:group
      <a class="moz-txt-link-rfc2396E" href="http://ll-plugins.nongnu.org/lv2/lv2pftci/ksi/out"><http://ll-plugins.nongnu.org/lv2/lv2pftci/ksi/out></a>;</tt><tt><br>
    </tt><tt>      pg:role pg:rightChannel;</tt><tt><br>
    </tt><tt>    ];</tt><tt><br>
    </tt><tt>  ],</tt><tt><br>
    </tt><br>
    To output sound (and it does, and it sounds good).<br>
    <br>
    In order to implement the frequency calculation, what would be the
    rough roadmap, the synthetic (so to speak) bullet points ?<br>
    <br>
    Thank you for your patience.<br>
    <br>
    --<br>
    Philippe<br>
  </body>
</html>