Closed Bubobubobubobubo closed 2 months ago
Hey @Bubobubobubobubo, looks like we both use the GPL 3 so thankfully talk about licenses can end there :) No objections here, only encouragement.
I am planning to focus work on haskell tidal towards version 2.0 for the next months so probably won't have much time to share on the python side, but feel free to ask questions
I did some work on it and it is now 'usable' with the following syntax:
tidal('pattern', s('kick snare'))
However, my initial conversion work got rid of some of the anti-drifting (or so I suppose) calculations that were installed by Vortex. The tempo is also incredibly fast (why?). A decent tempo for testing is clock.tempo = 10
. I'm really happy to see that it works though.
In tidal there are no beats, so tempo is in cycles (measures) per second not beats. Also there should be no drifting as time as rational.
In tidal there are no beats, so tempo is in cycles (measures) not beats. Also there should be no drifting as time as rational.
Yes, I think that I somehow messed up with the timestamp that comes with every SuperDirt message. It's really encouraging to see it working so fast though so it's just probably some fine tuning to do still :)
The tempo is now super stable. It's just... not the right tempo :) Still working on it. I should also look into freely nudging the tidal streams in time. This will open up the possibility of blending the different patterning flavours.
PS: I can actually still hear some micro fluctuations, very noticeable for high tempos.
Completely stuck with the notify_tick
function. It looks like I am not computing the diff
correctly with my port causing some noticeable delay with other types of patterns:
Solving this issue should resolve the timing issue that prevents it from being usable.
The original version was using liblo.time()
instead of that weird datetime thing.
Tried different corrections / tweaks / fixes / bleeps and bloops but I still can't manage to make them cooperate. The different flavors of patterns stay really close together, at the same tempo, but I can't manage to superpose them correctly. I've resorted to trimming the initial logic quite a lot in the vortex
branch to make it easy to understand in order to implement a working solution.
You can get them to superpose by playing with the .nudge
attribute attached to each Handler but this will only work for n
playbacks as the two pattern types will slowly drift in and out of phase again. Once locked, they now stay a little bit longer together before drifting which means that they will also take a lot more time to resync later in time again.
The tidal patterns are using an unconventional method to be scheduled compared to the base Sardine temporal model. I don't think that it should cause a problem though. The tidal patterns are really working great as is and are extremely stable.
Can you check the drift for both at 60bpm / 1cps against a 'known good' time source?
Not quite sure how to do that but I've noticed something interesting by looking at the OSC messages received by SuperCollider.
This is a message sent by Sardine-Vortex:
OSC Message Received:
time: -1682850773.2439
address: a NetAddr(127.0.0.1, 59285)
recvPort: 57120
msg: [ /dirt/play, s, bd, cps, 0.5, cycle, 2.75, delta, 0.5 ]
This is a message sent by Sardine:
OSC Message Received:
time: 3329.1294950701
address: a NetAddr(127.0.0.1, 58175)
recvPort: 57120
msg: [ /dirt/play, cps, 0.4995000064373, cycle, 26, orbit, 0, sound, hh ]
Very obviously, time
is negative for Vortex and the cps
isn't quite exactly equal to 0.5
for Sardine.
NOTE: testing can only be done using the link_clock
and not the internal_clock
(for the moment).
I converted the tidal_loop
from an async background loop to an AsyncRunner
following Sardine's main temporal logic. It is now working quite well but I need to rewrite some stuff and fully integrate Vortex before pushing to main. I also want to provide extensive documentation about it. It'll take some time but it will eventually be available as the third pattern language :)
EDIT: Trying to understand clock._ticks
. It looks like it's the key to getting it right.
Now in the main
branch but the algorithm for the query rate is still a bit wonky. The loop itself is in run.py
(init) and the other part in the clock itself link_clock.py
(for testing). The remaining issue is stability + precision for fast and intricate rhythms.
EDIT: after talking with Zalastax about the Tidal scheduler, it appears that the current implementation is quite naïve and misses a large part of the logic:
I have made some progress with the Vortex integration:
bd:2
still doesn't work. There is a weird bug in the mini-notation where tokens are parsed twice, the first version not returning the correct message: ~[((0, 1), (0, 1), {'s': {'n': 2, 's': 'bd'}})] ...~
. @munshkr, @TylerMclaughlin: any clue/advice?ply
, etc.).I am ready to backport some of the stuff I do to main Vortex if needed.
@Bubobubobubobubo Ah ply has a beautiful definition that is helpful in understanding the monadic stuff etc.
I think the priority should be modularising vortex into a form that sardine can use directly so we're not duplicating effort though. Otherwise if you want to keep it as a hard fork it would be best to rename it to avoid confusion, I think that would be a bit of a shame though.
I'm deep in Haskell land at the moment but want to do the same there, mirroring the structure of the strudel packages: https://github.com/tidalcycles/strudel/tree/main/packages
Solved most of the issues mentioned earlier:
bd:2
fix is on the Sardine side. The problem comes from the grammar/interpreter of the mini-notation. I manually transform a faulty message into a valid sample with index message.I think the priority should be modularising vortex into a form that sardine can use directly so we're not duplicating effort though. Otherwise if you want to keep it as a hard fork it would be best to rename it to avoid confusion, I think that would be a bit of a shame though.
@yaxu: I totally agree with you, Vortex should be modularized and I would be happy to help with the effort. I don't want to hard fork it, I just want to support it :) I didn't dwell on it too much for the moment because I'm trying to keep up with my doctoral research schedule: my funding is running out soon and I want to show some results. Naturally, I will then spend time consolidating this effort by contributing to more interoperability between languages/pattern systems, which is one of Sardine's goals. For a similar project, look at ziffers-python with Miika Alonen.
I don't want to rush this though, which would also be annoying to everyone involved. It is probably best to find a time when everyone will be available to speak about the refactoring as separate modules. There are many low hanging fruits on the Vortex side and it could be fun to add some varnish while splitting the project into multiple components.
@Bubobubobubobubo sounds like a good plan!
Closing because of a general lack of interest, will probably re-open in the future. The Vortex
integration will stay as is and will remain available. I have no plan to continue improving it before the next release but I don't want to remove it either.
It would be nice to support yet another flavor of patterning using Tidal's Vortex port made by @munshkr, @yaxu and others. It shouldn't be hard to get right as the two codebases have quite similar architectures. I have opened a
vortex
branch and started moving the pattern logic + the mini-notation in there. I have also added a few methods to my version of thelink-clock
inclock/
to support the pub/sub pattern Vortex uses.Hopefully, most of the work should be replacing
liblo
byosc4py3
+ making it talk with theFishBowl
. @munshkr, @yaxu, I would be happy to know what you think about the project and to work a bit on this new port with you if you have a bit of time to sink into it. More specifically, I want to be sure not to infringe any license or moral property of Vortex by porting it into Sardine.