@jarm @yaxu Is the stream archived somewhere ??? I was about to watch it tonight but i can't find it on Twitch anymore
Erp I don't have a copy, but I think Jack intends to upload the archive soon
It's on YouTube: https://youtu.be/2njVkJ6Q6A4
Leaving it unlisted as I'm still undecided as to whether I'll make a better video
In case anyone is reading this. I updated my library so that it's much easier to install.
Just change line 6 of Boot.hs
Have you been going deeper with Tidal <> Bitwig over these last months?
It seemed like you were just beginning to explore it and that it was really powerful.
Unfortunately not, as I'm still in the final stages of PhD submission
I'd be happy to live vicariously off anyone else's progress in the meantime though
Hey All,
I've been trying to get the Bitwig OSC control up and running and I've been struggling getting it all setup.
I get errors whenever I add this to my BootTidal.hs (I'm using VSCode)
:script /Users/Rain/Dropbox/Software/Tidal_Dropbox/jarmlib/tidal/Boot.hs
I have updated the location in the Boot.hs file:
-- change to location of this dir:
:cd /Users/Rain/Dropbox/Software/Tidal_Dropbox/jarmlib/tidal
I've also gone through and commented out most of the libraries in the Lib.hs file.
One thing I'm wondering is, do I want to keep this in my main BootTidal file?
-- DEFAULT SUPERDIRT OSC SEND
tidal <- startTidal (superdirtTarget {oLatency = 0.1, oAddress = "127.0.0.1", oPort = 57120}) (defaultConfig {cFrameTimespan = 1/20})
Anyway, let me know if anyone can think of anything!
Cheers.
What errors are they?
cd means change directory. So your script paths become relative to whatever directory you changed to
If I keep the OSC send code to SuperDirt as it was before adding the :script
, so:
-- DEFAULT SUPERDIRT OSC SEND
tidal <- startTidal (superdirtTarget {oLatency = 0.1, oAddress = "127.0.0.1", oPort = 57120}) (defaultConfig {cFrameTimespan = 1/20})
-- jarmlib
:script /Users/Rain/Dropbox/Software/Tidal_Dropbox/jarmlib/tidal/Boot.hs
Then I get a whole heap of errors:
Summary
Installed in /Users/Rain/.cabal/share/x86_64-osx-ghc-8.8.3/tidal-1.7.8
Listening for external controls on 127.0.0.1:6010
Connected to SuperDirt.
Warning: GHCi |
Warning: GHCi | osc/targets/Bitwig/Bitwig.hs:12:12: warning: [-Wmissing-fields]
Warning: GHCi | ⢠Fields of âTargetâ not initialised: oBusPort, oHandshake
Warning: GHCi | ⢠In the expression:
Warning: GHCi | Target
Warning: GHCi | {oName = "bitwig", oAddress = "127.0.0.1", oPort = 8000,
Warning: GHCi | oLatency = 0.2, oWindow = Nothing, oSchedule = Live}
Warning: GHCi | In an equation for âbwTargetâ:
Warning: GHCi | bwTarget
Warning: GHCi | = Target
Warning: GHCi | {oName = "bitwig", oAddress = "127.0.0.1", oPort = 8000,
Warning: GHCi | oLatency = 0.2, oWindow = Nothing, oSchedule = Live}
Warning: GHCi | |
Warning: GHCi | 12 | bwTarget = Target {oName = "bitwig",
Warning: GHCi | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
[TidalCycles version 1.7.8]
Installed in /Users/Rain/.cabal/share/x86_64-osx-ghc-8.8.3/tidal-1.7.8
Listening for external controls on 127.0.0.1:6010
That port isn't available, perhaps another Tidal instance is already listening on that port?
Warning: GHCi | *** Exception: osc/targets/Bitwig/Bitwig.hs:(12,12)-(18,19): Missing field in record construction oBusPort
Warning: GHCi |
Warning: GHCi |
Warning: GHCi | lib/Signal.hs:19:20: error:
Warning: GHCi | ⢠Couldn't match expected type âPattern aâ
Warning: GHCi | with actual type âDouble -> Doubleâ
Warning: GHCi | ⢠Probable cause: âsinâ is applied to too few arguments
Warning: GHCi | In the second argument of â($)â, namely âsinâ
Warning: GHCi | In the expression: fast f $ sin
Warning: GHCi | In an equation for âsinfâ: sinf f = fast f $ sin
Warning: GHCi | ⢠Relevant bindings include
Warning: GHCi | sinf :: Pattern Time -> Pattern a (bound at lib/Signal.hs:19:1)
Warning: GHCi | |
Warning: GHCi | 19 | sinf f = fast f $ sin -- sine at freq
Warning: GHCi | | ^^^
Warning: GHCi |
Warning: GHCi | osc/targets/Bitwig/BitwigLib.hs:5:18: error:
Warning: GHCi | Variable not in scope: once :: ControlPattern -> t
Warning: GHCi | |
Warning: GHCi | 5 | let bwplay = once $ transport "play"
Warning: GHCi | | ^^^^
Warning: GHCi |
Warning: GHCi | osc/targets/Bitwig/BitwigLib.hs:6:18: error:
Warning: GHCi | Variable not in scope: once :: ControlPattern -> t
Warning: GHCi | |
Warning: GHCi | 6 | bwstop = once $ transport "stop"
Warning: GHCi | | ^^^^
Warning: GHCi |
Warning: GHCi | osc/targets/Bitwig/BitwigLib.hs:7:18: error:
Warning: GHCi | Variable not in scope: once :: ControlPattern -> t
Warning: GHCi | |
Warning: GHCi | 7 | bwrestart = once $ transport "restart"
Warning: GHCi | | ^^^^
Warning: GHCi |
Warning: GHCi | osc/targets/Bitwig/BitwigLib.hs:8:18: error:
Warning: GHCi | Variable not in scope: once :: ControlPattern -> t
Warning: GHCi | |
Warning: GHCi | 8 | bwloop = once $ transport "repeat"
Warning: GHCi | | ^^^^
Warning: GHCi |
Warning: GHCi | osc/targets/Bitwig/BitwigLib.hs:9:18: error:
Warning: GHCi | Variable not in scope: once :: ControlPattern -> t
Warning: GHCi | |
Warning: GHCi | 9 | bwclick = once $ transport "click"
Warning: GHCi | | ^^^^
Warning: GHCi |
Warning: GHCi | osc/targets/Bitwig/BitwigLib.hs:10:18: error:
Warning: GHCi | Variable not in scope: once :: ControlPattern -> t
Warning: GHCi | |
Warning: GHCi | 10 | bwpunchin = once $ transport "punchIn"
Warning: GHCi | | ^^^^
Warning: GHCi |
Warning: GHCi | osc/targets/Bitwig/BitwigLib.hs:11:18: error:
Warning: GHCi | Variable not in scope: once :: ControlPattern -> t
Warning: GHCi | |
Warning: GHCi | 11 | bwpunchout = once $ transport "punchOut"
Warning: GHCi | | ^^^^
Warning: GHCi |
Warning: GHCi | osc/targets/Bitwig/BitwigLib.hs:12:18: error:
Warning: GHCi | Variable not in scope: once :: ControlPattern -> t
Warning: GHCi | |
Warning: GHCi | 12 | bwrecord = once $ transport "record"
Warning: GHCi | | ^^^^
Warning: GHCi |
Warning: GHCi | osc/targets/Bitwig/BitwigLib.hs:13:18: error:
Warning: GHCi | Variable not in scope: once :: ControlPattern -> t
Warning: GHCi | |
Warning: GHCi | 13 | bwoverdub = once $ transport "overdub"
Warning: GHCi | | ^^^^
Warning: GHCi |
Warning: GHCi | osc/targets/Bitwig/BitwigLib.hs:14:18: error:
Warning: GHCi | Variable not in scope: once :: ControlPattern -> t
Warning: GHCi | |
Warning: GHCi | 14 | bwtempo t = once $ tempo t
Warning: GHCi | | ^^^^
Warning: GHCi |
Warning: GHCi | osc/targets/Bitwig/BitwigLib.hs:15:18: error:
Warning: GHCi | Variable not in scope: p :: [Char] -> ControlPattern -> t
Warning: GHCi | |
Warning: GHCi | 15 | bwtempo' t = p "tempo" $ tempo t -- patternable
Warning: GHCi | | ^
~ Warning: GHCi |
Warning: GHCi | <interactive>:19:23: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:20:23: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:23:23: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:24:23: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:25:27: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:26:33: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:27:23: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:28:27: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:29:23: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:30:25: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:32:31: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:33:21: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:34:37: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:36:49: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:38:49: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:41:26: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:42:30: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:43:30: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:44:27: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:45:30: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:46:25: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:47:29: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:48:30: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:49:30: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:50:44: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:51:32: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:52:36: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:53:27: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:54:31: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:55:31: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:56:35: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:57:28: error: Variable not in scope: tidal :: Stream
~ Warning: GHCi |
Warning: GHCi | <interactive>:76:23: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:77:23: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:78:23: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:79:23: error: Variable not in scope: tidal :: Stream
Warning: GHCi |
Warning: GHCi | <interactive>:80:23: error: Variable not in scope: tidal :: Stream
~ Warning: GHCi |
Warning: GHCi | <interactive>:157:13: error:
Warning: GHCi | ⢠Variable not in scope: setcps :: t -> t1
Warning: GHCi | ⢠Perhaps you meant one of these:
Warning: GHCi | âTempo.setCpsâ (imported from Sound.Tidal.Tempo),
Warning: GHCi | âstepsâ (imported from Sound.Tidal.Context)
Warning: GHCi |
Warning: GHCi | <interactive>:158:13: error:
Warning: GHCi | ⢠Variable not in scope: setcps :: t -> t1
Warning: GHCi | ⢠Perhaps you meant one of these:
Warning: GHCi | âTempo.setCpsâ (imported from Sound.Tidal.Tempo),
Warning: GHCi | âstepsâ (imported from Sound.Tidal.Context)
~ tidal> Warning: GHCi |
Warning: GHCi | <interactive>:178:1: error:
Warning: GHCi | Variable not in scope: asap :: Pattern ValueMap -> t
tidal>
I've commented out a lot of the things that I believe I don't need. That doesn't seem like the problem but wanted to mention.
I did change the path in the boot file as I mentioned in my previous post:
:cd /Users/Rain/Dropbox/Software/Tidal_Dropbox/jarmlib/tidal
Thank you!
Hey @jarm
I've spent some more time trying to get this setup to no avail. I think my main issue is not knowing what my BootTidal.hs file should look like. I believe your library modularizes much of the BootTidal file so I'm not sure what to comment out, etc. Is it possible to see what your BootTidal file looks like? Or maybe there's an easier way to know what mine should? Thanks!
I figured it out, if anyone is curious in the future.
The main thing that I had to do was replace the locations in all of the files with full strings. Replacing the main directory in Boot.hs
alone wasn't enough.
I also had to add two lines to the Target
block in Bitwig.hs
:
oHandshake = False, -- SuperDirt specific
oBusPort = Nothing -- Also SuperDirt specific
I also had to comment out some of the libraries in Lib.hs
.
But that did it for me!
Hi @ben, sorry for not replying, I had a show to play and a new job to start! Did you get everything working in the end?
And yes the code is now a little out of date re oHandshake
and oBusPort
.
I did, yes. I was able to give it a proper spin.
Super. Any learnings or feature requests?
My biggest issue was figuring out the latency of the OSC going to Bitwig in relation to the latencies caused by MIDI and SuperDirt. That aspect hurt my head.
I wanted to use a code based system for recording the MIDI sent by Tidal/SuperDirt, so that I'd end up with one MIDI clip for each block of code that I triggered. In my initial experiments the latency was hard to figure out and seemed to shift around. I ended up thinking that just sending a MIDI note or some CC from Tidal over IAC to Bitwig was easier and seemingly more reliable in terms of timing. Is it because the packet timing is different somehow?
So for my purposes it seemed like I was making the problem harder than it needed to be (a classic trait of mine lately). That's a bummer as this package is incredibly powerful. If I could figure out a way to get the messages to Bitwig aligned with the MIDI/Superdirt then I'd be excited.
And thanks!
Thanks for sharing.
In terms of latency/sync, I'd only got so far as using nudge
to do an initial alignment with Bitwig. I hadn't noticed any drift, but maybe I hadn't used it long enough for that to happen.
IIIRC, I had started to conclude that to really nail this, I would need to fork the Bitwig OSC extension and build a scheduler in it similar to how SuperDirt schedules Tidal events. But that extension (and all BW exts?) is written in Java which I don't have experience with.
It's so close, hard to tell how far it is from being super usable, versus stepping back and implementing another approach that is more fundamentally oriented towards the goal of DAW-code symmetry.
Yeah, I wondered if the lack of scheduler was the issue as well. It would explain why the timings differed in unexpected ways from SuperDirt. But again, I didn't do extensive testing. Only enough to raise red flags.
It's so close, hard to tell how far it is from being super usable, versus stepping back and implementing another approach that is more fundamentally oriented towards the goal of DAW-code symmetry.
I know! It's so powerful as-is but without the timing being accurate it restricts a lot of what it could be used for imho. I'd love to be incorrect though!