<html><head></head><body><div class="ydp1c3fc05byahoo-style-wrap" style="font-family:Helvetica Neue, Helvetica, Arial, sans-serif;font-size:16px;"><div><div dir="ltr" data-setdir="false">Unfortunately the code I wrote previously is for a company who would not be pleased if I shared it... but I took a minute to ask ChatGPT and it came with something halfway reasonable. I chatted with it a bit to refine. I'll paste it below. Note that it's working on sinusoids. You'll probably adapt it to work with timestamps/deltas instead. I tried to get chatgpt to do that, but it kept taking crazy shortcuts<br></div></div><div><br></div><div dir="ltr" data-setdir="false"><div>#include <stdio.h><br>#include <math.h><br><br>// Constants<br>#define PI 3.14159265<br><br>// PLL parameters<br>double phase = 0.0; // Current phase<br>double frequency = 4.0; // Output frequency (four times input)<br>double phaseError = 0.0; // Phase error<br>double phaseIncrement = 0.01; // Phase increment<br><br>// Reference signal<br>double referenceFrequency = 2.0; // Input frequency<br>double referencePhase = 0.0;<br><br>// Function to generate reference signal<br>double referenceSignal(double time) {<br> return sin(2 * PI * referenceFrequency * time + referencePhase);<br>}<br><br>// Function to update phase and frequency using PLL<br>void updatePLL(double time) {<br> double referenceValue = referenceSignal(time);<br> double inputSignal = sin(2 * PI * frequency * time + phase);<br> <br> // Compute phase error using difference of squares<br> phaseError = referenceValue * inputSignal;<br> <br> // Update phase using phase error<br> phase += phaseIncrement * phaseError;<br> <br> // Update output frequency to be four times the input frequency<br> frequency = 4 * referenceFrequency;<br>}<br><br>int main() {<br> double time = 0.0;<br> int i;<br> <br> // Simulate for 100 time steps<br> for (i = 0; i < 100; i++) {<br> // Update PLL<br> updatePLL(time);<br> <br> // Increment time<br> time += 0.1; // Time step<br> <br> // Print phase and frequency<br> printf("Time: %.2f, Phase: %.2f, Frequency: %.2f\n", time, phase, frequency);<br> }<br> <br> return 0;<br>}<br><br></div><br><div dir="ltr" data-setdir="false"><br></div><div><br></div><div class="ydp1c3fc05bsignature"><div dir="ltr" style="font-family:Helvetica, Arial, sans-serif;font-size:16px;">Noah Vawter's futuristic electronic music instrument lab: <a href="https://youtube.com/diydsp" rel="nofollow" target="_blank">youtube.com/diydsp</a></div></div></div>
<div><br></div><div><br></div>
</div><div id="yahoo_quoted_0404356404" class="yahoo_quoted">
<div style="font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;color:#26282a;">
<div>
On Friday, March 8, 2024 at 05:36:19 PM EST, Tom Wiltshire <tom@electricdruid.net> wrote:
</div>
<div><br></div>
<div><br></div>
<div><div id="yiv5425981031"><div>Thanks. Do you have any resources to point to that I could look up about software PLLs? All the stuff I've seen seems to assume it's a hardware solution. While some of that is clearly transferable, something that had software in mind would help a lot.<div class="yiv5425981031"><br clear="none" class="yiv5425981031"></div><div class="yiv5425981031">Tom</div><div class="yiv5425981031"><br clear="none" class="yiv5425981031"><div class="yiv5425981031">
<div>==================<br clear="none" class="yiv5425981031"> Electric Druid<br clear="none" class="yiv5425981031">Synth & Stompbox DIY<br clear="none" class="yiv5425981031">==================</div><div class="yiv5425981031"><br clear="none" class="yiv5425981031"></div><br clear="none" class="yiv5425981031Apple-interchange-newline">
</div>
<div id="yiv5425981031yqt97978" class="yiv5425981031yqt9723632354"><div><br clear="none" class="yiv5425981031"><blockquote type="cite" class="yiv5425981031"><div class="yiv5425981031">On 8 Mar 2024, at 16:52, DIY DSP <<a rel="nofollow noopener noreferrer" shape="rect" ymailto="mailto:diydsp@yahoo.com" target="_blank" href="mailto:diydsp@yahoo.com" class="yiv5425981031">diydsp@yahoo.com</a>> wrote:</div><br clear="none" class="yiv5425981031Apple-interchange-newline"><div class="yiv5425981031"><div class="yiv5425981031"><div style="font-family:Helvetica Neue, Helvetica, Arial, sans-serif;font-size:16px;" class="yiv5425981031ydpbad9314cyahoo-style-wrap"><div class="yiv5425981031"><div class="yiv5425981031"><br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031">I've done this the "easy" way with a software PLL, and the hard way with a Kalman filter. </div><div dir="ltr" class="yiv5425981031">Technically what you need depends on the noise/error profile of the source clock.</div><div dir="ltr" class="yiv5425981031">But start with the software PLL.. On every 4th input clock, use the error to update the phase and period of the output clock.</div><div dir="ltr" class="yiv5425981031">For this application, since the signals will converge very quickly relative to how often they chance, I recommend using only the P term from the PID to compute the error and reset the phase of the output clock on the spot to the input clock.<br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031"><br clear="none" class="yiv5425981031"></div><div class="yiv5425981031"><br clear="none" class="yiv5425981031"></div><div class="yiv5425981031"><br clear="none" class="yiv5425981031"></div><div class="yiv5425981031ydpbad9314csignature"><div dir="ltr" style="font-family:Helvetica, Arial, sans-serif;font-size:16px;" class="yiv5425981031">Noah Vawter's futuristic electronic music instrument lab: <a rel="nofollow noopener noreferrer" shape="rect" target="_blank" href="https://youtube.com/diydsp" class="yiv5425981031">youtube.com/diydsp</a></div></div></div>
<div class="yiv5425981031"><br clear="none" class="yiv5425981031"></div><div class="yiv5425981031"><br clear="none" class="yiv5425981031"></div>
</div><div id="yiv5425981031yahoo_quoted_0121750334" class="yiv5425981031yahoo_quoted">
<div style="font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;color:#26282a;" class="yiv5425981031">
<div class="yiv5425981031">
On Friday, March 8, 2024 at 10:20:30 AM EST, Tom Wiltshire <<a rel="nofollow noopener noreferrer" shape="rect" ymailto="mailto:tom@electricdruid.net" target="_blank" href="mailto:tom@electricdruid.net" class="yiv5425981031">tom@electricdruid.net</a>> wrote:
</div>
<div class="yiv5425981031"><br clear="none" class="yiv5425981031"></div>
<div class="yiv5425981031"><br clear="none" class="yiv5425981031"></div>
<div class="yiv5425981031"><div dir="ltr" class="yiv5425981031">Hi All,<br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031"><br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031">Has anyone got any experience dealing with writing software to sync to MIDI clock that they can share?<br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031"><br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031">I'm working on a drum sequencer which will run at 96PPQN, and it'd be nice if it could sync to incoming 24PPQN MIDI Clock messages.<br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031"><br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031">I can see a couple of ways to do this:<br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031"><br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031">1) Some sort of PID controller, where we compare the internal timing and the incoming clock timing and derive some error signals.<br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031">2) IIR filtering. We measure the time between incoming clocks and then use an IIR filter to provide some averaging and smoothing. We then set the internal clock based on the filter's output.<br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031"><br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031">(2) seems like the simpler approach. Clearly it will introduce some lag when changing tempo, but I'm not sure I see this as a fault - smooth tempo changes could be a feature. And depending on how much filtering is required, that lag might actually be quite short. What's a reasonable time constant for such a thing?<br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031"><br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031">How has this been approached in the past? I know that I'm not the first person to do this, so I'm just trying to avoid re-inventing the stone-age MIDI wheel!<br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031"><br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031">Many thanks for any ideas/pointers offered,<br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031">Tom<br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031"><br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031">==================<br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031"> Electric Druid<br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031">Synth & Stompbox DIY<br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031">==================<br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031"><br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031"><br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031"><br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031"><br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031">________________________________________________________<br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031">This is the Synth-diy mailing list<br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031">Submit email to: <a rel="nofollow noopener noreferrer" shape="rect" ymailto="mailto:Synth-diy@synth-diy.org" target="_blank" href="mailto:Synth-diy@synth-diy.org" class="yiv5425981031">Synth-diy@synth-diy.org</a><br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031">View archive at: <a rel="nofollow noopener noreferrer" shape="rect" target="_blank" href="https://synth-diy.org/pipermail/synth-diy/" class="yiv5425981031">https://synth-diy.org/pipermail/synth-diy/</a><br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031">Check your settings at: <a rel="nofollow noopener noreferrer" shape="rect" target="_blank" href="https://synth-diy.org/mailman/listinfo/synth-diy" class="yiv5425981031">https://synth-diy.org/mailman/listinfo/synth-diy</a><br clear="none" class="yiv5425981031"></div><div dir="ltr" class="yiv5425981031">Selling or trading? Use <a rel="nofollow noopener noreferrer" shape="rect" ymailto="mailto:marketplace@synth-diy.org" target="_blank" href="mailto:marketplace@synth-diy.org" class="yiv5425981031">marketplace@synth-diy.org</a><br clear="none" class="yiv5425981031"></div></div>
</div>
</div></div></div></blockquote></div></div><br clear="none" class="yiv5425981031"></div></div></div></div>
</div>
</div></body></html>