diff --git a/packages/osc/README.md b/packages/osc/README.md new file mode 100644 index 00000000..e8f5069b --- /dev/null +++ b/packages/osc/README.md @@ -0,0 +1,33 @@ +# @strudel.cycles/osc + +OSC messaging between strudel and super collider? + +## Sniffing Tidal Messages + +```sh +npm run tidal-sniffer +``` + +Now open a .tidal file and play something. There should be logs like: + +```log +received: /dirt/play [ + '_id_', '1', + 'cps', 0.5625, + 'cutoff', 100, + 'cycle', 724.1875, + 'delta', 0.11111068725585938, + 'orbit', 0, + 's', 'arpy' +] +``` + +## Web Client + Server (WIP) + +```sh +npm run client +npm run server # another terminal +``` + +Then go to [http://localhost:4321](localhost:4321) and push the button. +In your server terminal, there should be a log. diff --git a/packages/osc/index.html b/packages/osc/index.html new file mode 100644 index 00000000..0890caa1 --- /dev/null +++ b/packages/osc/index.html @@ -0,0 +1,22 @@ + + + diff --git a/packages/osc/package-lock.json b/packages/osc/package-lock.json new file mode 100644 index 00000000..33516920 --- /dev/null +++ b/packages/osc/package-lock.json @@ -0,0 +1,76 @@ +{ + "name": "@strudel.cycles/osc", + "version": "0.0.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@strudel.cycles/osc", + "version": "0.0.1", + "license": "GPL-3.0-or-later", + "dependencies": { + "osc-js": "^2.3.0" + } + }, + "node_modules/isomorphic-ws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/osc-js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/osc-js/-/osc-js-2.3.0.tgz", + "integrity": "sha512-P2Oy9tf8Z9lQw8JZeR62HNqbKdxj7Kqbsag+ImiJvyxPDReGMVt5LtZbMh/7Ve/wbYEGODkQdFAaLHFVkIlHPw==", + "dependencies": { + "isomorphic-ws": "4.0.1", + "ws": "8.5.0" + } + }, + "node_modules/ws": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + }, + "dependencies": { + "isomorphic-ws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "requires": {} + }, + "osc-js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/osc-js/-/osc-js-2.3.0.tgz", + "integrity": "sha512-P2Oy9tf8Z9lQw8JZeR62HNqbKdxj7Kqbsag+ImiJvyxPDReGMVt5LtZbMh/7Ve/wbYEGODkQdFAaLHFVkIlHPw==", + "requires": { + "isomorphic-ws": "4.0.1", + "ws": "8.5.0" + } + }, + "ws": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "requires": {} + } + } +} diff --git a/packages/osc/package.json b/packages/osc/package.json new file mode 100644 index 00000000..67a0cc76 --- /dev/null +++ b/packages/osc/package.json @@ -0,0 +1,32 @@ +{ + "name": "@strudel.cycles/osc", + "version": "0.0.1", + "description": "OSC messaging for strudel", + "main": "osc.mjs", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "server": "node server.js", + "tidal-sniffer": "node tidal-sniffer.js", + "client": "npx serve -p 4321" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/tidalcycles/strudel.git" + }, + "keywords": [ + "tidalcycles", + "strudel", + "pattern", + "livecoding", + "algorave" + ], + "author": "Felix Roos ", + "license": "GPL-3.0-or-later", + "bugs": { + "url": "https://github.com/tidalcycles/strudel/issues" + }, + "homepage": "https://github.com/tidalcycles/strudel#readme", + "dependencies": { + "osc-js": "^2.3.0" + } +} diff --git a/packages/osc/server.js b/packages/osc/server.js new file mode 100644 index 00000000..0d5c6986 --- /dev/null +++ b/packages/osc/server.js @@ -0,0 +1,129 @@ +const OSC = require('osc-js'); + +const config = { + receiver: 'ws', // @param {string} Where messages sent via 'send' method will be delivered to, 'ws' for Websocket clients, 'udp' for udp client + udpServer: { + host: 'localhost', // @param {string} Hostname of udp server to bind to + port: 57121, // @param {number} Port of udp client for messaging + // enabling the following line will receive tidal messages: + // port: 57120, // @param {number} Port of udp client for messaging + exclusive: false, // @param {boolean} Exclusive flag + }, + udpClient: { + host: 'localhost', // @param {string} Hostname of udp client for messaging + port: 57120, // @param {number} Port of udp client for messaging + }, + wsServer: { + host: 'localhost', // @param {string} Hostname of WebSocket server + port: 8080, // @param {number} Port of WebSocket server + }, +}; +const osc = new OSC({ plugin: new OSC.BridgePlugin(config) }); + +osc.open(); // start a WebSocket server on port 8080 + +console.log('osc client running on port', config.udpClient.port); +console.log('osc server running on port', config.udpServer.port); +console.log('websocket server running on port', config.wsServer.port); + +// listen for messages from the client +osc.on('*', (m) => { + // forward message to supercollider?? + const message = new OSC.Message(m.address, ...m.args); + osc.send(message); // will it even be received?? + console.log('forward:', m.address, m.args); +}); + +/* +example tidal messages: + +/* + +received: /dirt/play [ + '_id_', + '1', + 'cps', + 0.5625, + 'cycle', + 503.5, + 'delta', + 0.8888888359069824, + 'orbit', + 0, + 's', + 'bd' +] +received: /dirt/play [ + '_id_', '1', + 'cps', 0.5625, + 'cycle', 503.6666564941406, + 'delta', 0.592592716217041, + 'orbit', 0, + 's', 'hh' +] +received: /dirt/play [ + '_id_', + '1', + 'cps', + 0.5625, + 'cycle', + 504, + 'delta', + 0.8888888359069824, + 'orbit', + 0, + 's', + 'bd' +] +received: /dirt/play [ + '_id_', + '1', + 'cps', + 0.5625, + 'cycle', + 504, + 'delta', + 0.592592716217041, + 'orbit', + 0, + 's', + 'hh' +] +received: /dirt/play [ + '_id_', + '1', + 'cps', + 0.5625, + 'cycle', + 504.3333435058594, + 'delta', + 0.5925922393798828, + 'orbit', + 0, + 's', + 'hh' +] +received: /dirt/play [ + '_id_', + '1', + 'cps', + 0.5625, + 'cycle', + 504.5, + 'delta', + 0.8888888359069824, + 'orbit', + 0, + 's', + 'bd' +] +received: /dirt/play [ + '_id_', '1', + 'cps', 0.5625, + 'cycle', 504.6666564941406, + 'delta', 0.592592716217041, + 'orbit', 0, + 's', 'hh' +] + +*/ diff --git a/packages/osc/tidal-sniffer.js b/packages/osc/tidal-sniffer.js new file mode 100644 index 00000000..a1bdd659 --- /dev/null +++ b/packages/osc/tidal-sniffer.js @@ -0,0 +1,125 @@ +const OSC = require('osc-js'); + +const config = { + receiver: 'ws', // @param {string} Where messages sent via 'send' method will be delivered to, 'ws' for Websocket clients, 'udp' for udp client + udpServer: { + host: 'localhost', // @param {string} Hostname of udp server to bind to + port: 57120, // @param {number} Port of udp client for messaging + exclusive: false, // @param {boolean} Exclusive flag + }, + udpClient: { + host: 'localhost', // @param {string} Hostname of udp client for messaging + // port: 57120, // @param {number} Port of udp client for messaging + port: 41235, // @param {number} Port of udp client for messaging + }, + wsServer: { + host: 'localhost', // @param {string} Hostname of WebSocket server + port: 8080, // @param {number} Port of WebSocket server + }, +}; +const osc = new OSC({ plugin: new OSC.BridgePlugin(config) }); + +osc.open(); // start a WebSocket server on port 8080 + +console.log('osc client running on port', config.udpClient.port); +console.log('osc server running on port', config.udpServer.port); +console.log('websocket server running on port', config.wsServer.port); + +// listen for messages from the client +osc.on('*', (m) => { + console.log('received:', m.address, m.args); +}); + +/* +example tidal messages: + +/* + +received: /dirt/play [ + '_id_', + '1', + 'cps', + 0.5625, + 'cycle', + 503.5, + 'delta', + 0.8888888359069824, + 'orbit', + 0, + 's', + 'bd' +] +received: /dirt/play [ + '_id_', '1', + 'cps', 0.5625, + 'cycle', 503.6666564941406, + 'delta', 0.592592716217041, + 'orbit', 0, + 's', 'hh' +] +received: /dirt/play [ + '_id_', + '1', + 'cps', + 0.5625, + 'cycle', + 504, + 'delta', + 0.8888888359069824, + 'orbit', + 0, + 's', + 'bd' +] +received: /dirt/play [ + '_id_', + '1', + 'cps', + 0.5625, + 'cycle', + 504, + 'delta', + 0.592592716217041, + 'orbit', + 0, + 's', + 'hh' +] +received: /dirt/play [ + '_id_', + '1', + 'cps', + 0.5625, + 'cycle', + 504.3333435058594, + 'delta', + 0.5925922393798828, + 'orbit', + 0, + 's', + 'hh' +] +received: /dirt/play [ + '_id_', + '1', + 'cps', + 0.5625, + 'cycle', + 504.5, + 'delta', + 0.8888888359069824, + 'orbit', + 0, + 's', + 'bd' +] +received: /dirt/play [ + '_id_', '1', + 'cps', 0.5625, + 'cycle', 504.6666564941406, + 'delta', 0.592592716217041, + 'orbit', 0, + 's', 'hh' +] + +*/