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

replace Tempo module by an ableton-link synched clock that comes with tidal-link #1059

Merged
merged 15 commits into from
Apr 9, 2024

Conversation

polymorphicengine
Copy link
Collaborator

@polymorphicengine polymorphicengine commented Dec 29, 2023

to make tidal-link and tidals clock functionality more widely useable (i.e. not dependend on types from tidal) i decided to reimplement the Tempo.hs module in a new module Sound.Tidal.Clock, that is part of tidal-link. The functionality is still the same, but i rewrote the code to make the clock independed of tidal and added an API so it can be used more easily.

i also restructured the code into a Clock monad, which is essentialy just the IO monad with some read-only memory for the configuration and mutable state, imo this makes the code much easier to comprehend and maintain.

i also rewrote some of the Stream and Transition modules to use the Clock instead of Tempo.hs, here i tried to make as little changes as possible, most of the code is exactly the same. the most notable changes are

  • streamReplace : updatePattern is no longer handled by the clock, it was only that way to tag the patterns with the time of evaluation, this time can be gotten from the clock through the API
  • streamFirst : onSingleTick is also no longer handled by the clock, the zeroedLinkOperations needed for the action can also be gotten through the clock API
  • transiton : also this function is no longer handled directly by the clock

the next step would be to restructure the Stream module, possibly splitting it into a couple of modules, maybe also rewriting Stream as an IO based monad.

what do you think @yaxu @Zalastax @mindofmatthew ?

Copy link
Contributor

@matthewkaney matthewkaney left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! This makes sense to me. I've added some comments and questions I had, but overall I think this is a good direction to move in.

Comment on lines +91 to +92
,cQuantum = 4
,cBeatsPerCycle = 4
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably a @Zalastax questions, but what's the difference between cQuantum and cBeatsPerCycle? To me they seem redundant: if someone wants to define Tidal "bpm" in terms of a 4-beat cycle, is there a case where they wouldn't also want cycles phase-aligned with other 4-beat measures (loops, etc) on the network (which is what quantum is for)?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's mostly redundant. I thought it could possibly be useful for some people but wasn't sure if it would be used. I was thinking people think of cycles in interesting and different ways and that I don't want to impose my way. It could also act as a workaround for the limits of Link BPM.

tidal-link/src/hs/Sound/Tidal/Clock.hs Outdated Show resolved Hide resolved
src/Sound/Tidal/Stream.hs Outdated Show resolved Hide resolved
tidal-link/src/hs/Sound/Tidal/Clock.hs Outdated Show resolved Hide resolved
tidal-link/src/hs/Sound/Tidal/Clock.hs Outdated Show resolved Hide resolved
@matthewkaney
Copy link
Contributor

Btw, can you update the BootTidal.hs file so that it's easier to test this branch?

Copy link
Collaborator

@Zalastax Zalastax left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of my goals when I introduced Link was to sequentialize everything that can affect time. I did so by moving the handling of Transition and once into Tempo and putting everything in a queue which is processed between the processing of the normal clock. This is inspired by my experience with Erlang actors and I believe it often reduces bugs. We are here moving away from that pattern. I do see benefits with this new approach, like once happening more immediately and ClockActions being a cleaner interface. I also don't think the drawbacks are very significant and I notice I didn't even fully complete that vision because pmap is modified from multiple threads. So I quite like this change but wanted to provide some context. Might be room for some future tidying up, but not sure much benefits can be gained.

}

-- | possible actions for interacting with the clock
data ClockAction
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that this focuses the actions to be time related instead of the mix that TempoAction had.

@@ -37,11 +39,30 @@ import Sound.Tidal.Utils (enumerate)
along with this library. If not, see <http://www.gnu.org/licenses/>.
-}

type TransitionMapper = Time -> [ControlPattern] -> ControlPattern
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

@@ -25,31 +24,21 @@ data Config = Config {cCtrlListen :: Bool,
cCtrlAddr :: String,
cCtrlPort :: Int,
cCtrlBroadcast :: Bool,
cFrameTimespan :: Double,
cEnableLink :: Bool,
cProcessAhead :: Double,
cTempoAddr :: String,
cTempoPort :: Int,
cTempoClientPort :: Int,
Copy link
Contributor

@matthewkaney matthewkaney Jan 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this PR would be a good place to get rid of cTempoAddr, cTempoPort and cTempoClientPort, since it's already changing the Config type? They're for a tempo-sharing mechanism that was replaced with Link, and are unused everywhere else.

@polymorphicengine
Copy link
Collaborator Author

i got around to the restructuring of the stream module now. it is seperated into 7 sub-modules now all of which are re-exported by the old Sound.Tidal.Stream module. They are:

  • Config, basically as before containing the config of the clock and the control listener
  • Types, basically the module StreamTypes, but including the Stream and Target definitions
  • Target, contains logic for creating targets, and sending messages to targets, aswell as the default dirt/superdirt targets
  • Process, defines doTick, which is the core logic of querying patterns at an arc and processing it's events into OSC messages which are then sent out to the tragets
  • UI, the exposed user interface into the stream logic, contains all functions for interacting with a given stream
  • Listen, function for interacting with the stream from outside via OSC
  • Main, brings the Process and Listen modules together to define startStream, aswell as startTidal

i didn't make any changes to the code yet, it was just a matter of copy and pasting things into the right places. hope this makes sense to you, let me know what you think! @mindofmatthew @yaxu @Zalastax

@matthewkaney
Copy link
Contributor

This reorganization makes sense to me!

I was curious: are you thinking of doing a major restructuring of the Stream code in this PR? I could see it getting unwieldy, but since there are only a couple of us who will likely comment, I think it's manageable. If that's the case, would you mind if I submitted pull requests against your branch? I have some ideas of my own (eg #1051), and would generally be interested in helping out with the effort!

@polymorphicengine
Copy link
Collaborator Author

are you thinking of doing a major restructuring of the Stream code in this PR?

i thought about it, but i think we could actually close this PR if everyone is happy with it and then work on a new, seperate PR to actually make some changes to the code, aswell as add some things etc. maybe that would make it a bit cleaner. what do you think?

@matthewkaney
Copy link
Contributor

That sounds good with me, although I'd wait to merge it in until we can get a 1.9.5 release out.

Unless @yaxu objects, then I'm going to look into merging the build fixes (#1062) and then releasing 1.9.5 later this week! In the meantime, I think you're safe to treat this PR as approved and start a new branch off of this one for a future Stream PR

@yaxu
Copy link
Member

yaxu commented Feb 26, 2024

Hi sorry I'm still away from things until next week, but had a quick look and can't see anything controversial so please go ahead @mindofmatthew !

@yaxu
Copy link
Member

yaxu commented Apr 9, 2024

Shall we merge this now?

@matthewkaney
Copy link
Contributor

@yaxu Sounds great! Go ahead and do this before you do your branch tidying

@yaxu yaxu merged commit 997e3f7 into tidalcycles:1.10-dev Apr 9, 2024
22 checks passed
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

Successfully merging this pull request may close these issues.

4 participants