<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>