Skip to content

Unstable device 2.3.0 update #66

Open

Description

@vanzuiden

Hi all,

I have a sync device that was very tight on version 2.1.0. I'm playing around with the new 2.3.0 update and noticed that my device is off quite a bit. I downgraded to 2.2.1 and found the same issue.

UPDATE: Sorry, i accidentally loaded 2.3.0 instead of 2.2.1 in the test below. 2.2.1 shows the same results as with 2.1.0. The issue is introduced with 2.3.0. I will investigate further.

Here's a screenshot from Ableton. The first track contains my device running v2.1.0 firing 16th triggers to an external synth. The second track is v2.2.1 (see UPDATE above) and the other tracks are all v2.3.0 with different setPhaseLockQuartersCount and setExtIntervalBuffer settings. All these test are done with the same clock and hardware. I'm syncing to an external clock running at 24PPQN via hardware interrupt.

Image

Here's my setup() with 2.1.0

uClock.init();
uClock.setMode(uClock.EXTERNAL_CLOCK);
uClock.setOnPPQN(ClockOut);
uClock.setOnStep(ShuffleOut);
uClock.setShuffle(false);
uClock.start();

With 2.2.1 and later:

uClock.init();
uClock.setClockMode(uClock.EXTERNAL_CLOCK);
uClock.setOutputPPQN(uClock.PPQN_96);
uClock.setInputPPQN(uClock.PPQN_24);
uClock.setOnOutputPPQN(ClockOut);
uClock.setOnStep(ShuffleOut);
uClock.setShuffle(false);
uClock.start();

These test were done with the straight clock output, e.g. SetOnPPQN and setOnOutputPPQN.

Coming from 2.1.0, I'm currently not using ATOMIC. I expect that to impact performance, but my issue seems to be a consistent offset with version 2.2.1 and 2.3.0. I expect any performance issues regarding not using ATOMIC will be random jitter and performance issues?

Any input on how to solve this?

Thank you!

Activity

  1. changed the title [-]Unstable device with 2.2.1 and 2.3.0 update[/-] [+]Unstable device 2.3.0 update[/+] on Apr 19, 2026
  2. midilab commented on Apr 23, 2026

    @midilab
    Owner

    Hi @vanzuiden ,

    Thanks for reporting back.

    This is certain related to this PR:
    Code review, shuffle multitrack support and refactor on external sync schema by @midilab in #60

    The off phase could be triger by the phase counting variable maybe, wich is used to a better lock phase on modular lower pulse sync like 2ppqn or 4ppqn, the setPhaseLockQuartersCount is used to adjust this behaviour depeding on the resolution of external clock (lower or higher)

    At main clock function:

    ...
        if (clock_mode == EXTERNAL_CLOCK) {
            // Tick Phase-lock
            if (labs(int_clock_tick - ext_clock_tick) > 1) {
                // only update tick at a full quarter or phase_lock_quarters * a quarter
                // how many quarters to count until we phase-lock?
                if ((ext_clock_tick * mod_clock_ref) % (output_ppqn*phase_lock_quarters) == 0) {
    ...

    or/and at external sync call function:

    ...
            case STARTING:
                clock_state = SYNCING;
                start_sync_counter = 4;
                break;
            case SYNCING:
                if (--start_sync_counter == 0)
                    clock_state = STARTED;
    ...

    looks like there are two 2.3.0 that syncs correctly on your screenshot? what values did you use on each test?

  3. vanzuiden commented on Apr 23, 2026

    @vanzuiden
    ContributorAuthor

    Hi @midilab, thank you for the reply. None of the 2.3.0 tests line up, you can compare all the hits to the first track in the screenshot.

    Unfortunately, I didn't write down the values. I can retest this for you with the values mentioned.

  4. midilab commented on Apr 23, 2026

    @midilab
    Owner

    Since none of those tests works, no need to re-test.

    I will try to make some changes that could possible solve and sent back to you via the develop branch if thats ok for you to test it.

    I ping you here when changes take place.

  5. midilab commented on Apr 23, 2026

    @midilab
    Owner

    @doctea can you tell me anything related on v2.3.0 vs olders based on the tests you have been running?

  6. vanzuiden commented on Apr 23, 2026

    @vanzuiden
    ContributorAuthor

    @midilab Sure thing, i'll keep my out on this thread!

  7. vanzuiden commented on Apr 23, 2026

    @vanzuiden
    ContributorAuthor

    This also now solves long-standing problem with BPM being a little too slow. Should now be perfectly accurate!

    Problem was needing to cast interval from uint32_t to int32_t so that the correct negative interval is passed to add_repeating_timer_us (because "the repeat delay in microseconds; if >0 then this is the delay between one callback ending and the next starting; if <0 then this is the negative of the time between the starts of the callbacks.")

    Originally posted by @doctea in #64 (comment)

    This might be related as i'm running a RP2040

  8. doctea commented on Apr 23, 2026

    @doctea
    Contributor

    @doctea can you tell me anything related on v2.3.0 vs olders based on the tests you have been running?

    I will try to do some test to try and understand it :). If I remember correctly then my own experience with moving to 2.3 was that it made external clock less reliable - I think the big change was the introduction of the PLL, whereas previously it was more directly synced to the external clock messages? But I'll have to check.

    I think there were API changes too which makes it not so simple to do direct A/B comparison with the same test sketch code. So perhaps it would be useful to be able to try different sync approaches while using the same test sketches.

    I wonder too if we need a testing harness so that we can run repeatable tests with different kinds of simulated clock and jitter, so that we can prove improvements and regressions..

  9. midilab commented on Apr 23, 2026

    @midilab
    Owner

    @doctea

    Im beting that the sync phase counter is the issue, but i will have to investigate it, probrably releasing on some branch a version without to test.

  10. midilab commented on May 10, 2026

    @midilab
    Owner

    hi @vanzuiden

    I've create a new branch and revert to the old external sync algorithm so we can test to see if the unstability is gone.

    https://github.com/midilab/uClock/tree/test/revert-ext-clock-alg

    Please let me know!

    @doctea
    Can you test it too? The setPhaseLockQuartersCount() does nothing in this branch, im almost sure that this new "feature" was the one in charge for the unstability.

  11. vanzuiden commented on May 10, 2026

    @vanzuiden
    ContributorAuthor

    @midilab Great, I will give it a go when i'm home next week. I'll report back, thank you!

  12. doctea commented on May 14, 2026

    @doctea
    Contributor

    @midilab I just did some quick testing with your test/revert-ext-clock-alg branch, the current main branch, and my feature-strict-external-develop.

    I used MIDI-OX as the clock source on my PC. (I have previously discovered that my FLStudio would not give me anything like sensible and sane clock output, giving a mad flurry of clock messages and maybe even missing some or sending extra entirely, which caused me much consternation, so I am eschewing that when testing now!).

    Using my Compulidian project (RP2040-based, USB MIDI connection, midihelpers as my uClock 'wrapper').

    I found that:-

    • The revert-ext-clock-alg branch did not work properly for me -- pressing play gives a brief initial burst and then nothing (silence/no clock) until a second or two later when clock seems to continue.
    • The main branch did not have this problem -- seemed to work correctly for me!
    • The feature-strict-external-develop branch (using setStrictExternalMode(true)) -- also seemed to work correctly. I also found this was better at tracking tempo changes (e.g., starting at 120bpm and then changing to 60bpm or 90bpm, or going from 90bpm to 120bpm) -- the clock synced with the beat at the new speed very quickly, whereas with the main version it took a couple of seconds to audibly slow down before syncing to the new beat.

    (The only thing I'm not quite sure about is whether my feature-strict-external-develop version always started on the downbeat correctly after a stop->reset->start -- it felt like perhaps the first step did not fire or had a little stutter, but without more testing I can't be sure exactly, and I think its more likely to be a bug I introduced in my project code a couple of weeks ago).

    Hope this helps!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions