Hi all,

I’m trying to sync my Norns and modular via an FH-1. I don’t really care which one is the master and which is the slave. As far as I understand I can send clock input to the X channel of the FH-1 but I’m not sure how to receive it in Norns. On the other hand I should somehow create a tempo synced square LFO and output it on the FH-1 which also breaks my head every time I look at any Expert Sleepers config tools.

Any advice?

Got back to this today…

Made the change to clock.c and re-running my blinker script (with print(util.round (presync, 0.0001)) to make it a little more readable) …

Here’s get_beats() pre-sync

Summary

1013.0005
1013.5006
1014.0004
1014.5004
1015.0004
1015.5003
1016.0004
1016.5004
1017.0022
1017.4995
1017.9996
1018.5004
1019.0005
1019.5006
1020.0006
1020.5004
1021.0003
1021.5004
1022.0006
1022.5005
1023.0005
1023.5004
1024.0004
1024.5004
1025.0006
1025.5004
1026.0005
1026.5005
1027.0006
1027.5018
1028.0021
1028.4994
1028.5008
1028.9994
1029.0006
1029.5005
1030.0003
1030.5005
1031.0006
1031.5004
1032.0005
1032.5006
1033.0004
1033.5007
1034.0003
1034.5006
1035.0005
1035.5006
1036.0006
1036.5005
1037.0006
1037.5019
1037.9994
1038.0004
1038.5001
1039.0003
1039.4996
1040.0007
1040.5005
1041.0009
1041.5036
1042.0004
1042.499
1042.5007
1043.0004
1043.5004
1044.0004
1044.5003
1045.0004
1045.5003
1046.0004
1046.5005
1047.0004
1047.5017
1047.9995
1048.4997
1048.9998
1049.5007
1050.0004
1050.5003
1051.0004
1051.5004
1052.0008
1052.5003
1053.0006
1053.5006
1054.0004
1054.5005
1055.0004
1055.5004
1056.0006
1056.5003
1057.0004
1057.5005
1058.0005
1058.5017
1058.9981
1059.002
1059.4994
1059.5009

here's another pass with unrounded values

125.00038107682
125.50051083379
126.0006772059
126.50048854331
127.00046182727
127.5003872255
128.00036202053
128.50055553832
129.00039845784
129.50036315788
130.0004037633
130.50042025742
131.00037066048
131.5018334103
131.99940912318
132.00065144651
132.49942393294
132.50068592023
133.00042569444
133.50036928672
134.00047920936
134.50038863495
135.00038423826
135.50040105045
136.00042457235
136.50052962025
137.00039330264
137.5004948146
138.00037107944
138.50051952601
139.00046953304
139.50056114657
140.00047175493
140.50037697773
141.00039435476
141.50171125342
141.99950295867
142.49973044423
143.00076928949
143.50053120383
144.00034713106
144.50058369549
145.00050170111
145.50037353263
146.00035846436
146.50038465707
147.00036897752
147.5005716319
148.00051806648
148.50039545151
149.00054137477
149.50039621066
150.0005700381
150.50047684109
151.00037075658
151.50178860482
151.99946190958
152.50011827762
153.00047088708
153.50002479182
153.99359897408
154.00102142561
154.46442043267
154.50043530788
154.94900238529
154.99865255172
155.00028226384
155.47582096828
155.50038580754
155.93293440423
155.99707620146
156.0002154332
156.4517201026
156.49921000974
156.50027240581
156.99200703129
157.00035776119
157.50331719612
158.01458973774
158.50779636333
159.00077533409
159.50044622877
160.00139051495
160.49926992424
160.50083222291
160.9991375898
161.00086525841
161.50045162687
162.00041570265
162.5002868069
163.00036696101
163.50033879987
164.00036985046
164.5003339111
165.00029104769
165.50036662874
166.00029886455
166.5003348234
167.00031314826
167.50059483486

At 80bpm it seems a little bit better than before, but I think I’m seeing some (minimal) slight stutters or missed beats on the screen blink.

here's some values when that happened

1463.0001
1463.5
1464.0006
1464.5001
1464.9999
1465.5018
1465.9996
1466.4992
1466.5003
1467.0006
1467.5002
1467.9999
1468.5007
1469.0001
1469.4998
1470.0006
1470.5002

1 Like

Questions:

Should these be consistent?
clock.set_source(1) - value is zero based?
params:set("clock_source", 2) - value is 1 based


The following gives me inconsistent results for tempo1 and tempo2 if I change default_bpm and reload the script
Do I need to save/write params for this to “stick”?

local default_bpm = 100
function init()
  params:set("clock_tempo", default_bpm)
  tempo1 = util.round (clock.get_tempo(), 1)
  tempo2 = util.round (params:get("clock_tempo"),1)
  print(tempo)
  print(tempo2)
end

clock docs for set_source (source) need to be expanded for link and crow

currently only shows
source integer : clock.INTERNAL (0) or clock.MIDI (1)

Also are clock.INTERNAL and clock.MIDI still valid globals? clock.MIDI returns nil

2 Likes

+1 on this. Happens with both crow and link syncing

1 Like

I’ve noticed the same thing in my script and any other that uses global clock, sync to ext is all over the place.

hey all, apologizes for the radio silence, as i’ve been working on something else. i think a few problems mentioned above might be fixed with the upcoming single-thread clock implementation, but no promises on when exactly.

the workaround (but also a good practice to follow in general), is to keep time-critical coroutines separated from the graphics and control i/o whenever possible.

2 Likes

Hi all,

As I understand clock can be only sent to one MIDI port (in system menu).
Is there a way to send clock to all midi port to synchronize more than one midi device?

Thanks!

1 Like

Yes, you can

a) send clock events (midi:clock) directly from the script to the ports you need.

b) every midi device has an IN port and an OUT port, so you can daisy-link them together to have the clock signal pass through them all.

Hope this helps!

Thanks a lot!

I try to sync a Digitakt and an O_c (captain midi).

I’ll try to use midi:clock for each port but I was more thinking about an option in clock parameters to avoid modifications in each script . Maybe in a future update.

thanks again.

Hi! I’m struggling with trying to send midi start/stop commands from the clock library. I managed to do it with BeatClock by following the studies, but not with the clock library. Is there a way to do so?

I have implemented clock.transport.start() and clock.transport.stop() functions in my script, but these only seem to work when other midi devices send the messages to norns, not when a clock gets started with clock.run(f) or stopped with clock.cancel(f).

Thanks in advance!

EDIT: found the answer, was using the wrong syntax :slight_smile:
If anybody else is wondering this will do it:

Summary

m = midi.connect()
m:start()
m:stop()

1 Like

I’ve recently picked up a second Norns and was wondering what’s the best way to sync them together when one is being clocked via crow. Is it possible to use ableton link while still being clocked via crow?

Also wondering if a clock reset has been added to the Norns clock system and if there are any scripts using it?
I’ve been wanting my sequences to reset once the clock has stopped. I find that I loose timing when I stop the clock to arm channels for recording.
I’ve thinking about using crow input 2 for a reset but it would be nice to have the Norns clock reset after not receiving a clock for a set amount of time.

Anyone else find them selves needing a reset input or option?

not possible with the current API. it should be possible to sync both norns via link and send out clock signal to crow, but not the other way.

2 Likes

Thanks for the reply. I have already tried out having Norns as the clock source and syncing the other Norns via link and clocking my pnw via crow but that still doesn’t address the reset issue.
Most scripts dont reset to the start once stopped so I still loose out on syncing lips and delays with my sequences.
Would it be difficult to implement a reset for Norns apps or within the Norns clock system?

not difficult for individual scripts — each could supply a PARAMS trigger that resets their respective step counters to the value they’re written to understand as the “1” and then another trigger to start counting again at the next clock pulse.

this isn’t a standard that can be generally enforced by the clock system, though, as a system-level reset wouldn’t be able to predict the myriad syntaxes each script uses to count steps or the many places where a reset might be handy (eg. boingg only has one track that’d need reset, but what would that mean for arcologies?).

as a proof of concept, i can spin up what this would look like for Awake tomorrow morning (see below) if that’d be helpful?


here’s a version of Awake with basic start + stop/reset functionality

  • i established a clock_active variable, which can either be true or false
  • i added this variable as a condition to the main step() function, which uses the clock to drive the script forward. if clock_active is true, the sequence can advance – if it’s false, the sequence won’t move forward.
  • i created a transport(state) function, which understands 0 as “stop” and any non-zero as “play”
    • when state == 0, clock_active is set to false and we clear any playing notes + reset the two sequence’s positions
    • otherwise, clock_active is set to true
  • i added a start/stop trigger to the PARAMS which executes that transport(state) function, passing 0 or 1 based on the current state of clock_active

all told, 22 lines of code gave us a straightforward manual start + stop/reset!

from here, you could add a few more lines to:

  • assign a crow input to do what the start/stop trigger does
  • direct MIDI start/stop messages to execute the transport function (passing 0 when MIDI stop is received, 1 for MIDI start)
  • get a little fancy and add a “reset every x bars” situation :slight_smile:

hope this helps!

3 Likes

Noticed today that Clock system does not understand Swing, any swing amount is ignored. I was using crow to clock Norns so perhaps it has something to do with crow? Would be great if this could be implemented in the next update, will give the patterns more funk and life :slight_smile:
Thanks!

1 Like

since this came up in another thread, reitrating: this needs to be part of a script’s logic since there is no universal definition of what it “means” to reset the sequence/process whatever.

i wonder if there is utility (e.g., turn those 22 lines into 2 lines) for baking a “reset” handler into the clock API… somehow.

hmm… AFAIK we just respond to PPQ ticks. is there a standard for “swing” that tells us to post-process the PPQ stream in some way? who would be sending us this “swing” value and how? or are you proposing the addition of a swing parameter at the norns system level? (ed: sorry just re-read: you want the clock coming from crow to be “swung” or “shuffled” in some way, i think)

AFAIK, the concept of “swing” in DAWs and e.g. MPC sequences, means: process a sequence of notes such that some rhythmic unit is subdivided asymetrically - for example, eight-notes to dotted-sixteenths (or triplets or something in between.) in other words, it is a musical transformation defined by a sequencer. (not actually a property of a low-level clock.)

and given that assumption, it seems to me that sequencers can easily implement swing by calling e.g. clock.sync(0.75 /4)... clock.sync(0.25 /4)... instead of clock.sync(1/8)...
(or, more broadly, clock.sync((0.5 + swing) / 4)... clock.sync((0.5 - swing) / 4), with swing in [0, 0.5)).

(at least, that’s my understanding of what “swing/shuffle” usually means. could get a lot more granular / weird of course.)


maybe relevant too: at one point we considered adding the ability to metro to use a sequence of durations instead of a single duration. wasn’t convinced this was a sensible point of abstraction though.

if there is a general call for “clocks” to encapsulate more musical logic outside of what scripts do with them, then that could be sort of a bigger discussion; could do a lot more than swing/shuffle.

5 Likes

Thanks so much for adding this and writing out all the details to achieve it. I had a look at the updated Awake but couldn’t quite get it to work how I imagined. I also looked at trying to add a crow input to reset the sequence but I think it’s a just a little over my head at the moment.
I wish I had the knowledge because I know I could achieve many ideas if my coding was upto scratch. I might need to do some study.

1 Like

for sure!

gotcha, makes sense. can you spec out what exactly you want the script to do? i think that it’s important to not let the “it’s mostly there” stuff die out, you know? if we can land on a set of parameters that scripts should ideally incorporate through this process, it’d be time well spent :slight_smile:

so, what’s your ideal?

Definitely agree that we shouldn’t let “it’s mostly there” stuff die out.
Norns would really benefit from a solid clock system with start/stop and reset functions for the internal clock, link, midi and crow.
At the moment I think most things work well besides crow. I use crow 99% of the time when using Norns.
Not to digress too much but I still find syncing Norns with crow a little unstable with some apps.
Talking about the reset, what I’m ultimately wanting to achieve is that apps reset to step one of a sequence once a clock stops.
As input one on crow is used for clock, input two makes sense as a reset input just like on Ansible. But for me the issue with using input 2 for reset is some apps might use that input for other functions and I think it’s important to keep it free for that sole reason.
So I’m thinking there are a few things to achieve.

  1. Have the Norns clock detect if the clock (internal, link, midi or crow) has stopped and therefor reset to the start.
  2. An option to enable this reset function or not.
  3. Have Norns send Link info when internally or externally synced (this is a very specific use case as I recently got a second Norns and would like to sync one via crow and have it send Link sync to the second crow).

Hope that explains it a little better.

1 Like

cool, this is helpful to have laid out, thank you!

fwiw, stopping and resetting isn’t the duty of the norns clock, tho. the global clock should never stop — it is a fundamental timing heartbeat rather than a transport (side note: ohh, a global transport actually might be the right framing for the feature you’re requesting!). so, it’s up to each script to kinda create their own transports – to listen for external “stop” messages and to have a plan for what to do when it receives such a message. it’s also up to each script to define what it considers a “reset” and what it should do when it receives one. we can help standardize this with a clear example and more visibility of this standard in the documentation, so more folks can include these functions in their scripts.

re: crow syncing, i’ll follow back up on this thread tomorrow: Crow/norns/clock question

re: Link, that’s trickier — from what i understand, Link isn’t a “destination” or “source”, but more like a conversation between equals. i don’t think that you can send Link data without also listening to it, which becomes complicated in a system with only one clock. @artfwo will have much more concrete things to say about whether this is a norns-solvable issue or just the way the Link protocol works.

4 Likes