[{"data":1,"prerenderedAt":462},["ShallowReactive",2],{"content-query-YstfKz3lpk":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"created":10,"body":11,"_type":456,"_id":457,"_source":458,"_file":459,"_stem":460,"_extension":461},"/blog/tidal-custom-osc","blog",false,"","sending custom OSC messages with Tidal (or rather, hosc)","TidalCycles communicates with its audio engine (normally SuperDirt) via OSC. message construction and socket I/O is handled behind the scenes, freeing the musician from having to think about it. but sometimes you may want to send custom, one-shot OSC messages from the Tidal environment. maybe you want to activate a complex effects chain in SuperCollider, or tell a visualizer to change scenes, or something, without leaving the Tidal code window.","2026-06-25",{"type":12,"children":13,"toc":454},"root",[14,40,54,59,175,196,209,304,309,435,440,448],{"type":15,"tag":16,"props":17,"children":18},"element","p",{},[19,29,31,38],{"type":15,"tag":20,"props":21,"children":25},"a",{"href":22,"rel":23},"https://tidalcycles.org",[24],"nofollow",[26],{"type":27,"value":28},"text","TidalCycles",{"type":27,"value":30}," communicates with its audio engine (normally ",{"type":15,"tag":20,"props":32,"children":35},{"href":33,"rel":34},"https://codeberg.org/musikinformatik/SuperDirt",[24],[36],{"type":27,"value":37},"SuperDirt",{"type":27,"value":39},") via OSC. message construction and socket I/O is handled behind the scenes, freeing the musician from having to think about it. but sometimes you may want to send custom, one-shot OSC messages from the Tidal environment. maybe you want to activate a complex effects chain in SuperCollider, or tell a visualizer to change scenes, or something, without leaving the Tidal code window.",{"type":15,"tag":16,"props":41,"children":42},{},[43,45,52],{"type":27,"value":44},"the way to do this actually doesn't really involve Tidal at all. but Tidal runs in a regular Haskell interpreter, so we can invoke other Haskell libraries, in particular ",{"type":15,"tag":20,"props":46,"children":49},{"href":47,"rel":48},"https://hackage.haskell.org/package/hosc",[24],[50],{"type":27,"value":51},"hosc",{"type":27,"value":53},". Tidal itself uses hosc, so it doesn't need to be installed separately.",{"type":15,"tag":16,"props":55,"children":56},{},[57],{"type":27,"value":58},"let's say we want to send messages to the localhost IPv4 address on port 12345. the following code opens a UDP socket for this:",{"type":15,"tag":60,"props":61,"children":65},"pre",{"code":62,"language":63,"meta":7,"className":64,"style":7},"import qualified Sound.Osc.Fd as O\nimport qualified Sound.Osc.Transport.Fd.Udp as O\n\nsock \u003C- O.openUdp \"127.0.0.1\" 12345\n","haskell","language-haskell shiki shiki-themes github-dark",[66],{"type":15,"tag":67,"props":68,"children":69},"code",{"__ignoreMap":7},[70,103,128,138],{"type":15,"tag":71,"props":72,"children":75},"span",{"class":73,"line":74},"line",1,[76,82,87,93,98],{"type":15,"tag":71,"props":77,"children":79},{"style":78},"--shiki-default:#F97583",[80],{"type":27,"value":81},"import",{"type":15,"tag":71,"props":83,"children":84},{"style":78},[85],{"type":27,"value":86}," qualified",{"type":15,"tag":71,"props":88,"children":90},{"style":89},"--shiki-default:#B392F0",[91],{"type":27,"value":92}," Sound.Osc.Fd",{"type":15,"tag":71,"props":94,"children":95},{"style":78},[96],{"type":27,"value":97}," as",{"type":15,"tag":71,"props":99,"children":100},{"style":89},[101],{"type":27,"value":102}," O\n",{"type":15,"tag":71,"props":104,"children":106},{"class":73,"line":105},2,[107,111,115,120,124],{"type":15,"tag":71,"props":108,"children":109},{"style":78},[110],{"type":27,"value":81},{"type":15,"tag":71,"props":112,"children":113},{"style":78},[114],{"type":27,"value":86},{"type":15,"tag":71,"props":116,"children":117},{"style":89},[118],{"type":27,"value":119}," Sound.Osc.Transport.Fd.Udp",{"type":15,"tag":71,"props":121,"children":122},{"style":78},[123],{"type":27,"value":97},{"type":15,"tag":71,"props":125,"children":126},{"style":89},[127],{"type":27,"value":102},{"type":15,"tag":71,"props":129,"children":131},{"class":73,"line":130},3,[132],{"type":15,"tag":71,"props":133,"children":135},{"emptyLinePlaceholder":134},true,[136],{"type":27,"value":137},"\n",{"type":15,"tag":71,"props":139,"children":141},{"class":73,"line":140},4,[142,148,153,158,163,169],{"type":15,"tag":71,"props":143,"children":145},{"style":144},"--shiki-default:#E1E4E8",[146],{"type":27,"value":147},"sock ",{"type":15,"tag":71,"props":149,"children":150},{"style":78},[151],{"type":27,"value":152},"\u003C-",{"type":15,"tag":71,"props":154,"children":155},{"style":89},[156],{"type":27,"value":157}," O.",{"type":15,"tag":71,"props":159,"children":160},{"style":144},[161],{"type":27,"value":162},"openUdp ",{"type":15,"tag":71,"props":164,"children":166},{"style":165},"--shiki-default:#9ECBFF",[167],{"type":27,"value":168},"\"127.0.0.1\"",{"type":15,"tag":71,"props":170,"children":172},{"style":171},"--shiki-default:#79B8FF",[173],{"type":27,"value":174}," 12345\n",{"type":15,"tag":16,"props":176,"children":177},{},[178,180,186,188,194],{"type":27,"value":179},"this could be added to ",{"type":15,"tag":67,"props":181,"children":183},{"className":182},[],[184],{"type":27,"value":185},"BootTidal.hs",{"type":27,"value":187}," to make it happen automatically on Tidal startup. note that ",{"type":15,"tag":67,"props":189,"children":191},{"className":190},[],[192],{"type":27,"value":193},"sock",{"type":27,"value":195}," is an arbitrary variable name, you are free to call it whatever.",{"type":15,"tag":16,"props":197,"children":198},{},[199,201,207],{"type":27,"value":200},"with the socket open, we are ready to send messages. the following code sends a message to the OSC address ",{"type":15,"tag":67,"props":202,"children":204},{"className":203},[],[205],{"type":27,"value":206},"/hello",{"type":27,"value":208},", with integer, float and string arguments:",{"type":15,"tag":60,"props":210,"children":212},{"code":211,"language":63,"meta":7,"className":64,"style":7},"O.sendMessage sock (O.message \"/hello\" [O.int32 1, O.float 2.5, O.string \"beep\"])\n",[213],{"type":15,"tag":67,"props":214,"children":215},{"__ignoreMap":7},[216],{"type":15,"tag":71,"props":217,"children":218},{"class":73,"line":74},[219,224,229,233,238,243,248,252,257,262,267,271,276,281,285,289,294,299],{"type":15,"tag":71,"props":220,"children":221},{"style":89},[222],{"type":27,"value":223},"O.",{"type":15,"tag":71,"props":225,"children":226},{"style":144},[227],{"type":27,"value":228},"sendMessage sock (",{"type":15,"tag":71,"props":230,"children":231},{"style":89},[232],{"type":27,"value":223},{"type":15,"tag":71,"props":234,"children":235},{"style":144},[236],{"type":27,"value":237},"message ",{"type":15,"tag":71,"props":239,"children":240},{"style":165},[241],{"type":27,"value":242},"\"/hello\"",{"type":15,"tag":71,"props":244,"children":245},{"style":144},[246],{"type":27,"value":247}," [",{"type":15,"tag":71,"props":249,"children":250},{"style":89},[251],{"type":27,"value":223},{"type":15,"tag":71,"props":253,"children":254},{"style":144},[255],{"type":27,"value":256},"int32 ",{"type":15,"tag":71,"props":258,"children":259},{"style":171},[260],{"type":27,"value":261},"1",{"type":15,"tag":71,"props":263,"children":264},{"style":144},[265],{"type":27,"value":266},", ",{"type":15,"tag":71,"props":268,"children":269},{"style":89},[270],{"type":27,"value":223},{"type":15,"tag":71,"props":272,"children":273},{"style":144},[274],{"type":27,"value":275},"float ",{"type":15,"tag":71,"props":277,"children":278},{"style":171},[279],{"type":27,"value":280},"2.5",{"type":15,"tag":71,"props":282,"children":283},{"style":144},[284],{"type":27,"value":266},{"type":15,"tag":71,"props":286,"children":287},{"style":89},[288],{"type":27,"value":223},{"type":15,"tag":71,"props":290,"children":291},{"style":144},[292],{"type":27,"value":293},"string ",{"type":15,"tag":71,"props":295,"children":296},{"style":165},[297],{"type":27,"value":298},"\"beep\"",{"type":15,"tag":71,"props":300,"children":301},{"style":144},[302],{"type":27,"value":303},"])\n",{"type":15,"tag":16,"props":305,"children":306},{},[307],{"type":27,"value":308},"a receiver for such messages in SuperCollider might look something like this:",{"type":15,"tag":60,"props":310,"children":314},{"code":311,"language":312,"meta":7,"className":313,"style":7},"(\nOSCdef(\\myReceiver, { |msg|\n    var addr, args;\n    #addr ... args = msg;\n    \"addr=%, args=%\\n\".postf(addr, args);\n}, \"/hello\", recvPort: 12345);\n)\n","supercollider","language-supercollider shiki shiki-themes github-dark",[315],{"type":15,"tag":67,"props":316,"children":317},{"__ignoreMap":7},[318,326,349,362,370,394,426],{"type":15,"tag":71,"props":319,"children":320},{"class":73,"line":74},[321],{"type":15,"tag":71,"props":322,"children":323},{"style":144},[324],{"type":27,"value":325},"(\n",{"type":15,"tag":71,"props":327,"children":328},{"class":73,"line":105},[329,334,339,344],{"type":15,"tag":71,"props":330,"children":331},{"style":89},[332],{"type":27,"value":333},"OSCdef",{"type":15,"tag":71,"props":335,"children":336},{"style":144},[337],{"type":27,"value":338},"(",{"type":15,"tag":71,"props":340,"children":341},{"style":89},[342],{"type":27,"value":343},"\\myReceiver",{"type":15,"tag":71,"props":345,"children":346},{"style":144},[347],{"type":27,"value":348},", { |msg|\n",{"type":15,"tag":71,"props":350,"children":351},{"class":73,"line":130},[352,357],{"type":15,"tag":71,"props":353,"children":354},{"style":78},[355],{"type":27,"value":356},"    var",{"type":15,"tag":71,"props":358,"children":359},{"style":144},[360],{"type":27,"value":361}," addr, args;\n",{"type":15,"tag":71,"props":363,"children":364},{"class":73,"line":140},[365],{"type":15,"tag":71,"props":366,"children":367},{"style":144},[368],{"type":27,"value":369},"    #addr ... args = msg;\n",{"type":15,"tag":71,"props":371,"children":373},{"class":73,"line":372},5,[374,379,384,389],{"type":15,"tag":71,"props":375,"children":376},{"style":165},[377],{"type":27,"value":378},"    \"addr=%, args=%",{"type":15,"tag":71,"props":380,"children":381},{"style":171},[382],{"type":27,"value":383},"\\n",{"type":15,"tag":71,"props":385,"children":386},{"style":165},[387],{"type":27,"value":388},"\"",{"type":15,"tag":71,"props":390,"children":391},{"style":144},[392],{"type":27,"value":393},".postf(addr, args);\n",{"type":15,"tag":71,"props":395,"children":397},{"class":73,"line":396},6,[398,403,407,411,416,421],{"type":15,"tag":71,"props":399,"children":400},{"style":144},[401],{"type":27,"value":402},"}, ",{"type":15,"tag":71,"props":404,"children":405},{"style":165},[406],{"type":27,"value":242},{"type":15,"tag":71,"props":408,"children":409},{"style":144},[410],{"type":27,"value":266},{"type":15,"tag":71,"props":412,"children":413},{"style":171},[414],{"type":27,"value":415},"recvPort:",{"type":15,"tag":71,"props":417,"children":418},{"style":171},[419],{"type":27,"value":420}," 12345",{"type":15,"tag":71,"props":422,"children":423},{"style":144},[424],{"type":27,"value":425},");\n",{"type":15,"tag":71,"props":427,"children":429},{"class":73,"line":428},7,[430],{"type":15,"tag":71,"props":431,"children":432},{"style":144},[433],{"type":27,"value":434},")\n",{"type":15,"tag":16,"props":436,"children":437},{},[438],{"type":27,"value":439},"this splits incoming messages into separate variables for address and arguments, then prints them, producing output like:",{"type":15,"tag":60,"props":441,"children":443},{"code":442},"addr=/hello, args=[1, 2.5, beep]\n",[444],{"type":15,"tag":67,"props":445,"children":446},{"__ignoreMap":7},[447],{"type":27,"value":442},{"type":15,"tag":449,"props":450,"children":451},"style",{},[452],{"type":27,"value":453},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":105,"depth":105,"links":455},[],"markdown","content:blog:tidal-custom-osc.md","content","blog/tidal-custom-osc.md","blog/tidal-custom-osc","md",1782387211347]