Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync to external Eurorack trigger #40

Open
carlosedp opened this issue Jul 22, 2024 · 10 comments
Open

Sync to external Eurorack trigger #40

carlosedp opened this issue Jul 22, 2024 · 10 comments

Comments

@carlosedp
Copy link

Hi, I'm writing an Eurorack module for clock generation and division and wonder if I can sync my module that uses uClock to an external trigger coming from another Eurorack module.

The input trigger is usually a square wave from another oscillator or LFO (not MIDI).

Can I use the uClock.clockMe() for this? Any tips?

Thanks!

@midilab
Copy link
Owner

midilab commented Jul 23, 2024

Hi @carlosedp,

Yes it is possible to sync to external clock. one of the uclock main features is the phase lock mechanism to keep a good and solid internal clock based on external one.

uClock.clockMe() should be called at each low or high state of you square wave depending of the rise/fall style of your clock signal.

Rigth now the expected clock is 24PPQN, we have a TODO list to include the option to change expected external clock too.

But for now if you have any external clock different from 24PPQN you need to handle it on your code. For example: if you have a 48PPQN input clock, you should trigger uclock.clockMe() each second tick.

A code example

uint8_t clockDiv48Trig = 0;
void ppqInterrupt() {
  if (clockDiv48Trig == 0 || clockDiv48Trig % 2 == 0) {
    uClock.clockMe();
  }
  ++clockDiv48Trig;
}         

and a thread about the subject:
#37

If you external clock is 24PPQN than you only need to call uClock.clockMe() each external signal rise or fall.

@carlosedp
Copy link
Author

Got it but I think in my case it's kinda the opposite... I need to generate a 24PPQN from a single pulse (can I call it 1 PPQN?)... right?
Is this viable or precise?

@midilab
Copy link
Owner

midilab commented Jul 23, 2024

i dont think it exist such of 1PPQN resolution. Most eurorack modules are based on 48PPQN or 24PPQN, if it is a simple LFO that you have, there is no resolution at all, it is only a signal that you will try to sync to.

My suggestion is that you try it first uClock.clockMe() at each signal input LOW or HIGH(choose one of those only), and check it how it behaves, for clock generation. After that, just adjust the clock output to sane levels based on your LFO input(example: maybe the middle of your LFO time knob should be something like 140BPM output? then try to find how many signals to count before trigger uclock.clockMe())

Since a LFO is not PPQN sync based, you will need to find the ideal sync count that fits you purpose. To find the ideal clock count, try different values of CLOCK_COUNTER incrementing from 2 to 20 or more.... until you find the ideal value.

#define CLOCK_COUNTER 2
uint8_t clockDiv48Trig = 0;
void ppqInterrupt() {
  if (clockDiv48Trig == 0 || clockDiv48Trig % CLOCK_COUNTER == 0) {
    uClock.clockMe();
  }
  ++clockDiv48Trig;
}         

Mabe you can start with the example:
https://github.com/midilab/uClock/blob/main/examples/GenericMasterOrExternalSync/GenericMasterOrExternalSync.ino

your clock output will be done inside onSync24Callback function based on bellow example(wich outputs at 24PPQN resolution)

The example is doing clockMe() inside loop() function, but ideally you should use interruption linked to your clock input PIN instead of doing inside loop().

@houtson
Copy link

houtson commented Sep 22, 2024

I think the OP is looking for a 'tap tempo' style of input, with a trigger per step/quarter note.

@houtson
Copy link

houtson commented Sep 22, 2024

But for now if you have any external clock different from 24PPQN you need to handle it on your code. For example: if you have a 48PPQN input clock, you should trigger uclock.clockMe() each second tick.

Thanks for the 48PPQN example, I'll use that for syncing with old Korg DINSYNC synths.

Cheers Paul

@carlosedp
Copy link
Author

That's exactly what @houtson mentioned... suppose I want to sync my module that uses uClock with MI Marbles T2 output for example... it would output 120BPM in the middle position... if I connect it to my module's INPUT that triggers the clockMe function, it wouldn't work since it expects 24PPQN which would be 24x Marbles output.

Is there any way to make the clockMe set the input PPQN for the sync signal?

@midilab
Copy link
Owner

midilab commented Nov 17, 2024

The library needs a new feature to set the resolution of clock sync input signal other than 24ppqn, its on the TODO list.

If the resolution is higher you can div your clock like 48ppqn with div = 2. but in your case where the resolution is lowerw than the uClock base resolution nothing can be done with uClock.clockMe() to solve it on current version.

@doctea starts some code on tap tempo feature wich can leads to another way of doing what you need.

But the ideal feature would be to set PPQN input resolution, just as we have on current version of uClock a set PPQN for output. Also some setMultiplier and setDivider functions would be nice to add on input and output of uClock signal.

@IC-Alchemy
Copy link

IC-Alchemy commented Dec 10, 2024

@carlosedp

Marbles is a confusing example so my answer below assumes you are asking about generating a MIDI clock from a typical eurorack module.
image

I need to generate a 24PPQN from a single pulse (can I call it 1 PPQN?)... right?

24 PPQN describes timing resolution used for MIDI clock.

I think of PPQN like Frames Per Second (FPS)

FPS is the number of individual images (frames) displayed each second.
PPQN is the number of pulses used to represent one beat (specifically, a quarter note) in music

Higher PPQN means the musical timing is divided into more parts, allowing for finer placement of notes and rhythms.

For example Ableton uses 960PPQN which is a high enough resolution where you can come close to any swing imaginable.

@carlosedp
Copy link
Author

Yea, I know... :) When I mean 1PPQN I mean imagine syncing the library to an LFO with a square wave outputting pulses every second (60BPM) ... the idea is that while pretty unstable, this pulse train would drive the clock at 60BPM too.

I think Pamela's workout has a setting where you can set the input PPQN for the output clock where the default is 24PPQN but it can go as low as 1PPQN.

Check this part of the video: https://youtu.be/mkoVfQq7m8Y?t=285

@IC-Alchemy
Copy link

IC-Alchemy commented Dec 14, 2024

I've made tons of devices that move forward one step on each rising edge trigger.
This can be done with out any clock at all, and without keeping track of time.

if (risingEdge)
    step++; 

For this to be synced with uClock,
so that you could output a midi clock that is synced with your LFO for example,
you'd have to decide what note value you want to assign to each step.

This won't work if you think of an LFO as being 1PPQN

The standard sequencer defaults to 16th notes, like on a TB303.

Each 16th note consists of 6PPQN, assuming your clock is MIDI at 24PPQN

If you don't plan on outputting multiple synd'd signals there are a ton of advantages of not using any clock at all and just moving forward one step like you mention.

I call this "time agnostic" but I think I just made that up.

A time agnostic sequencer automatically locks perfectly to what ever you send it, including swing, tempo changes, randomness etc...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants