Deep-Symmetry / carabiner

A loose connector for interacting with Ableton Link
GNU General Public License v2.0
157 stars 14 forks source link

Meaning of 'start' #11

Closed yaxu closed 5 years ago

yaxu commented 5 years ago

Thanks for carabiner! I'm trying to get it working with https://github.com/tidalcycles/tidal, a haskell-based thing. I get the bpm fine but I'm struggling to work out the meaning of the 'start' parameter so that I can get the phase right. If I telnet into carabiner, I see that if I change the bpm, then the value in the start parameter also changes:

bpm 120
status { :peers 1 :bpm 120.000000 :start 15578165470 :beat 43.826974 }
bpm 130
status { :peers 1 :bpm 130.000000 :start 15580539346 :beat 61.756445 }
bpm 110
status { :peers 1 :bpm 110.000000 :start 15574531192 :beat 71.633537 }

If I decrease the bpm, then the start point goes back in time. Is that because it's telling me the time that it would have been after the current number of beats if the bpm had been the new value all along?

I'm guessing so, but as I'm getting funny behaviour out of my calculations, I thought I'd check that my (linux mint) system isn't behaving strangely..

brunchboy commented 5 years ago

Hi, Alex! It’s lovely to hear from you in this context, and cool to learn that Tidal is looking at Carabiner as a bridge to Link. It sounds like you have arrived at the correct understanding: In Link, when you change the tempo, you do not want that to mess up the phase, so Link re-evaluates the entire timeline to pretend that it has always been at the new tempo. If you slow down the tempo, beats get spread further apart, so the previous ones get expanded backwards in time, while upcoming beats get expanded further into the future. The start marker tells you when, according to the system monotonic nanosecond clock, the timeline began, so that shifts back (or forward) as needed to keep your beat number and phase unchanged before and after the tempo change.

I kind of wish I was fluent in some sort of animation tool so I could create a visualization of this! ^_^

brunchboy commented 5 years ago

As a side thought, since Tidal seems to already be under GPL, it looks like you do have the option of using Haskell’s Cxx foreign function interface to call the Link C++ library directly, rather than mucking with talking to Carabiner in a separate process.

yaxu commented 5 years ago

Hi James! Thanks for the quick response.

Thanks for confirming that, I'll keep hacking at it until it works, then. I'm using OSC, which uses NTP clock with a different epoch, so there is some messing about to convert between them..

Before spotting carabiner, we actually made something very similar - https://github.com/tidalcycles/TidaLink Carabiner looks much more complete/a lot less hacky, though!

From what I can tell, linking Haskell with C++ is unfortunately not at all easy.

brunchboy commented 5 years ago

Unfortunately I think you are going to find it a nightmare to try to reconcile those clocks, because the NTP clock not only uses a different epoch, but it is not monotonic. It can go backwards as well as forwards. I guess you can probe the current difference between the monotonic and wall clocks each time you need to translate between them or something? In my case, I ended up rewriting my own libraries to exclusively use to the monotonic clock when I started integrating with Link. But that sounds impossible (or at least impractical) in your case.

Thanks for the kind words about Carabiner! I really don’t know what I am doing in C++, so I tried to keep it as simple as I possibly could.

And I can imagine that the FFI is tough, the runtime models of the two languages are so different. I hope that Carabiner turns out to be helpful then.

yaxu commented 5 years ago

Yes that's what I'm doing at the moment - getting the delta between the two clocks every time I receive a status message from carabiner. I did start converting tidal to monotonic clock too, but realised that was pointless because I currently send messages to supercollider over OSC, which uses the NTP epoch for timestamps.

(To clarify, I'm not actually using ntpd, just the NTP epoch.)

That said, the supercollider language is getting Link support, so hopefully all this will be straightened out at some point..

yaxu commented 5 years ago

Anyway, will close this issue for now, thanks!

yaxu commented 5 years ago

I got it working pretty well, thanks again

brunchboy commented 5 years ago

Sweet, thanks for the update! And I was thinking about the fact that Supercollider is probably trying to share a full time base over OSC, which means that there is no better epoch than NTP’s, because multiple different hosts need to agree on it. Link doesn’t try to do that, it only synchronizes tempo and beat/bar phase between hosts, letting them each have a separate notion about what the local beat number is, so it can use the monotonic clock which is better for such things on a single host, but cannot be meaningfully communicated between hosts.