Compare commits

..

3 Commits

Author SHA1 Message Date
rc 579506e4c5 Fix port 2022-03-05 15:31:22 +01:00
rc f0d95ecb9d disable console log of osc messages and debug set to false 2022-03-05 13:32:05 +01:00
rc 198bbf69cc Calibrate global reference with btn1 2022-03-05 13:23:30 +01:00
12 changed files with 90 additions and 4698 deletions

4
.gitignore vendored
View File

@ -1,5 +1 @@
node_modules node_modules
.~*~
.*~undo-tree~
.~lock*#
.*.swp

View File

@ -4,22 +4,6 @@ OSC controlled visual (used with motion controller)
Also see https://git.kompot.si/g1smo/pifcamp-2021 Also see https://git.kompot.si/g1smo/pifcamp-2021
* Running
0. Install dependencies
`npm i`
1. Serial port
`node server.js /dev/ttyUSB0 115200`
2. Bluetooth
`node server.js /dev/rfcomm0 115200`
3. WiFi
`node server.js`
(wait for it)
* older prototypes * older prototypes
- https://kreten.si/spin/ - https://kreten.si/spin/
- https://kreten.si/spin-color/ - https://kreten.si/spin-color/

90
anim.js
View File

@ -38,13 +38,8 @@ var rotacijaX = 0;
var rotacijaY = 0; var rotacijaY = 0;
var rotacijaZ = 0; var rotacijaZ = 0;
var crotacijaX = 0.000;
var crotacijaY = 0.000;
var crotacijaZ = 0.000;
// Premik obstojecih barv // Premik obstojecih barv
var zamikBarve = 0.01; var zamikBarve = 0.01;
var barvapuls = 10;
// Zamik pri novem objektu // Zamik pri novem objektu
var barva_mod = 0.003; var barva_mod = 0.003;
@ -52,14 +47,16 @@ var saturacija = 1;
var svetlost = 0.4; var svetlost = 0.4;
// Rotiranje kamere // Rotiranje kamere
var qKamera = new THREE.Quaternion(); var kameraX = 0;
var kameraY = 0;
var kameraZ = 0;
// Quaternioni za rotacijo in kalibracijo // Quaternioni za rotacijo in kalibracijo
var qWW = new THREE.Quaternion(); var qWW = new THREE.Quaternion(-1, 0, 0, 0);
var qWWo = new THREE.Quaternion(); var qWWo = new THREE.Quaternion(-1, 0, 0, 0);
var qWWd = new THREE.Quaternion(); var qWWd = new THREE.Quaternion(-1, 0, 0, 0);
var qObj = new THREE.Quaternion(); var qObj = new THREE.Quaternion(-1, 0, 0, 0);
var qStart = new THREE.Quaternion(); var qStart = new THREE.Quaternion(-1, 0, 0, 0);
var calibrate = true; var calibrate = true;
var reset = false; var reset = false;
@ -88,8 +85,6 @@ renderer.setSize(window.innerWidth, window.innerHeight);
// Črno ozadje // Črno ozadje
renderer.setClearColor(0x000000, 1); renderer.setClearColor(0x000000, 1);
//var pivot = new THREE.Group();
//scene.add( pivot );
@ -112,13 +107,8 @@ function render () {
function modulirajParametre() { function modulirajParametre() {
// Vsi gumbi? => RESET // Vsi gumbi? => RESET
if ((keysPressed[0] + keysPressed[1] + keysPressed[2] + keysPressed[3]) === 4 && !reset) { if ((keysPressed[0] + keysPressed[1] + keysPressed[2] + keysPressed[3]) === 4 && !reset) {
setTimeout(() => { reset = true;
if ((keysPressed[0] + keysPressed[1] + keysPressed[2] + keysPressed[3]) === 4) { window.location.reload()
setTimeout(() => {
window.location.reload()
}, 1000);
}
}, 1000)
} }
// Posodobi kvaternion polozaja kontrolerja // Posodobi kvaternion polozaja kontrolerja
@ -131,32 +121,20 @@ function modulirajParametre() {
} }
// Rotiranje manualno (z rocnimi gibi "iz sredine") // Rotiranje manualno (z rocnimi gibi "iz sredine")
if (keysPressed[0]) { if (keysPressed[3]) {
var k = objekti.slice(-1)[0]; var k = objekti.slice(-1)[0];
qObj.multiply(qWWd); qObj.multiply(qWWd);
k.quaternion.multiply(qWWd); k.quaternion.multiply(qWWd);
} }
if (keysPressed[1]) { if (keysPressed[2]) {
drotacijaX += qWWd.x / 10; drotacijaX += qWWd.x / 10;
drotacijaY += qWWd.y / 10; drotacijaY += qWWd.y / 10;
drotacijaZ += qWWd.z / 10; drotacijaZ += qWWd.z / 10;
} }
if (keysPressed[2]) { if (keysPressed[0]) {
crotacijaX += qWWd.x / 30; width *= 1 + dqX;
//crotacijaY += qWWd.y / 30; barva_mod += (dqZ / 100);
crotacijaZ += qWWd.z / 30; obj_limit *= 1 + (dqY);
barvapuls += qWWd.y;
}
if (keysPressed[3]) {
width *= 1 + (dqX / 3);
barva_mod += (dqZ / 1000);
obj_limit *= 1 - dqY;
}
if (kbdPressed['c']) {
crotacijaX *= 0.9;
crotacijaY *= 0.9;
crotacijaZ *= 0.9;
} }
} }
@ -178,8 +156,7 @@ function objAnim() {
// Funkcija za dodajanje novih objektov // Funkcija za dodajanje novih objektov
function addObj(w, h) { function addObj(w, h) {
var col = new THREE.Color(); var col = new THREE.Color();
//col.setHSL(stevec * barva_mod, saturacija, svetlost); col.setHSL(stevec * barva_mod, saturacija, svetlost);
col.setHSL(stevec * barva_mod, saturacija, (Math.sin(stevec/barvapuls) / 6) + 0.3);
var mat = new THREE.LineBasicMaterial({ var mat = new THREE.LineBasicMaterial({
color: col color: col
@ -203,7 +180,6 @@ function addObj(w, h) {
var obj = new THREE.Line(geo, mat, THREE.LineSegments); var obj = new THREE.Line(geo, mat, THREE.LineSegments);
scene.add(obj); scene.add(obj);
//pivot.add(obj);
obj.setRotationFromQuaternion(qObj); obj.setRotationFromQuaternion(qObj);
// Pocisti za seboj // Pocisti za seboj
@ -215,14 +191,27 @@ function addObj(w, h) {
} }
}; };
qK = new THREE.Quaternion() var xAksa = new THREE.Vector3(0, 1, 0);
function camRotate () { function camRotate () {
//scene.setRotationFromQuaternion(qKamera) // rotiraj po z osi
scene.rotation.x += crotacijaX camera.translateX(kameraX);
scene.rotation.y += crotacijaY camera.translateZ(odmik_kamere - Math.sqrt(Math.pow(odmik_kamere, 2) + Math.pow(kameraX, 2)));
scene.rotation.z += crotacijaZ
} /*
camera.translateY(kameraY);
camera.translateX(odmik_kamere - Math.sqrt(Math.pow(odmik_kamere, 2) + Math.pow(kameraY, 2)));
camera.translateZ(kameraZ);
camera.translateX(odmik_kamere - Math.sqrt(Math.pow(odmik_kamere, 2) + Math.pow(kameraZ, 2)));
*/
/*
camera.position.x = Math.sin((stevec % 10) / 10) * cam_rot_offset;
camera.position.y = Math.cos((stevec % 10) / 10) * cam_rot_offset;
*/
camera.lookAt(scene.position);
};
// Inicializiraj // Inicializiraj
document.onreadystatechange = function () { document.onreadystatechange = function () {
@ -246,12 +235,11 @@ function getVal(msg) {
return msg.value; return msg.value;
} }
const kbdPressed = { kbdPressed = {
a: false, a: false,
s: false, s: false,
d: false, d: false,
f: false, f: false
c: false
}; };
window.addEventListener('keydown', (e) => { window.addEventListener('keydown', (e) => {

4282
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,6 @@
"description": "epilepsija", "description": "epilepsija",
"dependencies": { "dependencies": {
"express": "^4.17.1", "express": "^4.17.1",
"midi": "^2.0.0",
"nodemon": "^2.0.12", "nodemon": "^2.0.12",
"nouislider": "14.6.2", "nouislider": "14.6.2",
"osc": "^2.4.2", "osc": "^2.4.2",

View File

@ -1,134 +0,0 @@
// Zacetek / konec
Server.local.boot;
Server.local.quit;
s.boot;
s.stop;
// Server -> Boot /// Ctrl+B
{SinOsc.ar}.play; // Shift+Enter evalvira
// Ctrl + . ustavi zvok!
// Start/stop prek spremenljivke
x = {SinOsc.ar}.play;
x.free;
// HELP: shift+ctrl+D
// recimo ugen
{SinOsc.ar(SinOsc.kr(1, 0, 1, 1), 0, 1, 0)}.play
{SinOsc.ar(520, 0, SinOsc.ar(3, 0.75, add: 1, phase: 0))}.play;
{VarSaw.ar(42, 0, SinOsc.ar(2, 0.75, add: 1, phase: 0))}.play;
{SinOsc.ar(32, 0, VarSaw.kr(3, 0.75, add: 1, phase: 0))}.play;
{SinOsc.ar(100, )}.play
// Kurzor na keyword in Ctrl+d odpre help zanj
(
{SinOsc.ar(100,)}.play;
{SinOsc.ar(100, 3.14)}.play;
)
()
(
SynthDef.new(\kFaza, {
var a = SinOsc.ar(100);
var b = SinOsc.ar(100, 3.14);
Out.ar(0, a);
Out.ar(1, b);
}).add;
)
(
SynthDef.new(\faza, {
var a = SinOsc.ar(100);
var b = SinOsc.ar(100);
Out.ar(0, a);
Out.ar(1, b);
}).add;
)
s = Synth.new(\kFaza);
v = Synth.new(\faza);
z.set(\f, 80);
z.set(\f, 200, \amp, 0.5);
NetAddr.langPort;
a= 0;
b= 0;
c= 0;
d= 0;
// WW
// Receiver function
(
SynthDef.new(\slOSC, {
// Najprej argumenti, potem variable
arg f=0, ampOsc=0, ch=0, off=0;
var so;
so = SinOsc.ar(f, off, SinOsc.kr(ampOsc));
Out.ar(ch, so);
}).add;
a = Synth.new(\slOSC);
b = Synth.new(\slOSC);
c = Synth.new(\slOSC);
d = Synth.new(\slOSC);
s = [a, b, c, d];
OSCFunc({
arg msg, time, addr, recvPort;
//[msg, time, addr, recvPort].postln;
~gX = msg[1] * 100;
~gY = msg[2] / 3;
}, '/euler', n);
OSCFunc({
arg msg, time, addr, recvPort;
//[msg, time, addr, recvPort].postln;
4.do({
arg i;
if (msg[i + 1] == 1.0) {
s[i].set(\f, ~gX);
s[i].set(\ampOsc, ~gY);
s[i].set(\off, ~gZ);
}
});
}, '/keys', n);
)
// ENDWW
(
w = {
arg noiseHz = 2.5;
var f, sig, amp;
// Med 200 in 1000 Hz
//f = LFNoise0.kr(8, 400, 600);
// f = LFNoise0.kr(8).range(200, 1000)
f = LFNoise0.kr(noiseHz).exprange(300, 600);
amp = LFNoise1.kr(9).exprange(0.2, 1);
sig = SinOsc.ar(f) * amp;
}.play;
)
w.set(\noiseHz, 48);
w.set(\noiseHz, exprand(260, 400));
w.free;

View File

@ -1,57 +0,0 @@
// Zacetek / konec
s.boot;
s.stop;
// Server -> Boot /// Ctrl+B
// HELP: shift+ctrl+D
// recimo ugen
NetAddr.langPort;
(
SynthDef.new(\slOSC, {
// Najprej argumenti, potem variable
arg f=440, ampOsc=0, ch=0, off=0;
var so;
so = SinOsc.ar(f, off, SinOsc.kr(ampOsc));
Out.ar(ch, so);
}).add;
s = [
Synth.new(\slOSC),
Synth.new(\slOSC),
Synth.new(\slOSC),
Synth.new(\slOSC)
];
OSCFunc({
arg msg, time, addr, recvPort;
//[msg, time, addr, recvPort].postln;
~gX = msg[1] * 100;
~gY = msg[2] / 3;
~gZ = msg[3] / 5;
}, '/eulerDiff', n);
OSCFunc({
arg msg, time, addr, recvPort;
msg.postln;
}, '/euler', n);
OSCFunc({
arg msg, time, addr, recvPort;
//[msg, time, addr, recvPort].postln;
4.do({
arg i;
if (msg[i + 1] == 1.0) {
s[i].get(\f, {arg f; s[i].set(\f, f + ~gX)});
s[i].get(\ampOsc, {arg ao; s[i].set(\ampOsc, ao + ~gY)});
s[i].get(\off, {arg o; s[i].set(\off, o + ~gZ)});
}
});
}, '/keys', n);
)

View File

@ -1,70 +0,0 @@
// Zacetek / konec
s.boot;
s.stop;
// Server -> Boot /// Ctrl+B
// HELP: shift+ctrl+D
// recimo ugen
NetAddr.langPort;
(
(
SynthDef.new(\slOSC, {
// Najprej argumenti, potem variable
arg f=120, ampOsc=1, ch=0, off=1;
var so;
so = SinOsc.ar(f, off, SinOsc.kr(ampOsc));
Out.ar(ch, so);
}).add);
s = [
Synth.new(\slOSC),
Synth.new(\slOSC, [\ampOsc, 1.5]),
Synth.new(\slOSC, [\ampOsc, 3]),
Synth.new(\slOSC, [\ampOsc, 4])
];
OSCFunc({
arg msg, time, addr, recvPort;
//[msg, time, addr, recvPort].postln;
~gX = msg[1];
~gY = msg[2];
~gZ = msg[3];
}, '/eulerDiff', n);
OSCFunc({
arg msg, time, addr, recvPort;
msg.postln;
}, '/euler', n);
OSCFunc({
arg msg, time, addr, recvPort;
//[msg, time, addr, recvPort].postln;
/*
if (msg[0]+msg[1]+msg[2]+msg[3] == 4.0) {
4.do({
arg i;
if (msg[i + 1] == 1.0) {
s[i].set(\f, 100);
s[i].set(\ampOsc, 1);
s[i].set(\off, 1);
}
});
} else {*/
4.do({
arg i;
if (msg[i + 1] == 1.0) {
s[i].get(\f, {arg f; s[i].set(\f, f * (1 + ~gX))});
s[i].get(\ampOsc, {arg ao; s[i].set(\ampOsc, ao * (1 + ~gY))});
s[i].get(\off, {arg o; s[i].set(\off, o * (1 + ~gZ))});
}
});
//}
}, '/keys', n);
)

View File

@ -64,7 +64,7 @@ o = OSCFunc({
~oX = ~gX; ~oX = ~gX;
~oY = ~gY; ~oY = ~gY;
~oZ = ~gZ; ~oZ = ~gZ;
msg.postln;
//[msg, time, addr, recvPort].postln; //[msg, time, addr, recvPort].postln;
~gW = msg[1]; ~gW = msg[1];
~gZ = msg[2]; ~gZ = msg[2];
@ -92,11 +92,11 @@ o = OSCFunc({
~euler = ~quaternionToEuler.([~dgW, ~dgX, ~dgY, ~dgZ]); ~euler = ~quaternionToEuler.([~dgW, ~dgX, ~dgY, ~dgZ]);
~euler.postln; ~euler.postln;
}, '/quaternion', n); }, '/quaternion/', n);
) )
// ENDWW // ENDWW
OSCFunc.trace(false); OSCFunc.trace(true);

123
server.js
View File

@ -1,36 +1,11 @@
// Which port do I send OSC messages to? (SupperCollider, ...)
const OSCPORT = 57120;
// Which port do I listen to (for visuals, calibration)
const PORT = 6676
// Do we have a problem, shall we debug?
const DEBUG = {
osc: true,
udp: false,
midi: true
}
// MIDI out
const MIDI = true
const express = require('express') const express = require('express')
const http = require('http') const http = require('http')
const WebSocket = require('ws') const WebSocket = require('ws')
const osc = require('osc') const osc = require('osc')
const readline = require('readline') const readline = require('readline')
const fs = require('fs') const fs = require('fs')
const midi = require('midi')
const port = 6676
// Vzemi iz argumenta // Vzemi iz argumenta
const tty = process.argv[2] const tty = process.argv[2]
@ -55,19 +30,11 @@ const include_files = [
const app = express(); const app = express();
const server = http.Server(app); const server = http.Server(app);
const DEBUG = true
// Odprti serijski OSC link // Odprti serijski OSC link
let scon = null let scon = null
let mo = null
if (MIDI) {
// Midi port
mo = new midi.Output()
//mo.getPortCount()
//mo.getPortName(0)
//mo.openPort(0)
mo.openVirtualPort("kegel")
}
function openSerial() { function openSerial() {
console.log('opening ', tty, baudrate) console.log('opening ', tty, baudrate)
@ -77,6 +44,7 @@ function openSerial() {
autoOpen: true, autoOpen: true,
useSLIP: true useSLIP: true
}) })
scon.open()
scon.on('open', e => { scon.on('open', e => {
console.log('serial connection opened') console.log('serial connection opened')
@ -88,21 +56,18 @@ function openSerial() {
}) })
scon.on('close', e => { scon.on('close', e => {
console.warn('serial connection closed, restarting in 1 second') console.warn('serial connection closed, restarting in 1 second')
setTimeout(openSerial, 1000)
}) })
// Arduino OSC gre v web // Arduino OSC gre v web
scon.on('message', msg => { scon.on('message', msg => {
// Debug incoming osc // Debug incoming osc
if (DEBUG.osc) { if (DEBUG) {
console.log('osc msg', msg) console.log('osc msg', msg)
} }
sendAll(msg, null, null, osclients) sendAll(msg, null, null, osclients)
}) })
scon.open()
if (scon._closeCode) { if (scon._closeCode) {
scon = null scon = null
console.log('restarting serial connection') console.log('restarting serial connection')
@ -126,14 +91,6 @@ app.get('/test', (req, res) => {
res.sendFile(__dirname + '/test.html'); res.sendFile(__dirname + '/test.html');
}); });
// Hydra inclusion
app.get('/hydra', function(req, res) {
res.sendFile(__dirname + '/hydra-osc-main/index.html');
});
app.get('/lib/osc.min.js', function(req, res) {
res.sendFile(__dirname + '/hydra-osc-main/lib/osc.min.js');
});
let settings = {}; let settings = {};
app.get('/settings', function(req, res) { app.get('/settings', function(req, res) {
res.send(settings); res.send(settings);
@ -145,7 +102,7 @@ include_files.map(function(file) {
}); });
}); });
server.listen(PORT, () => console.log('listening on *:' + PORT)) server.listen(port, () => console.log('listening on *:' + port))
// Websocket init // Websocket init
const wss = new WebSocket.Server({ server }) const wss = new WebSocket.Server({ server })
@ -153,18 +110,17 @@ const wss = new WebSocket.Server({ server })
// Relay multicast to websockets // Relay multicast to websockets
// @TODO still sends to supercollider? Do we need two sockets? // @TODO still sends to supercollider? Do we need two sockets?
/* //var dgram = require('dgram');
var dgram = require('dgram'); //var sss = dgram.createSocket('udp4');
var sss = dgram.createSocket('udp4'); //sss.on('listening', () => {
sss.on('listening', () => { // sss.addMembership('224.0.1.9');
sss.addMembership('224.0.1.9'); //})
}) //sss.bind(57120);
sss.bind(6696, '224.0.1.9');
*/
const scudp = new osc.UDPPort({ const scudp = new osc.UDPPort({
remotePort: OSCPORT
//socket: sss //socket: sss
remotePort: 57121,
localPort: 57100
}) })
scudp.on('open', () => { scudp.on('open', () => {
@ -172,10 +128,7 @@ scudp.on('open', () => {
}) })
scudp.on('message', (msg) => { scudp.on('message', (msg) => {
if (DEBUG.udp) { console.log('got UDP msg', msg);
console.log('got UDP msg', msg);
}
osclients.forEach( client => { osclients.forEach( client => {
if (client) { if (client) {
//console.log("sending", msg, info) //console.log("sending", msg, info)
@ -222,10 +175,10 @@ function eulerFromQuaternion(quaternion) {
} }
const sendAll = (msg, info, oscWS, osclients) => { const sendAll = (msg, info, oscWS, osclients) => {
// Reset euler rotation to 0
if (msg.address == '/keys') { if (msg.address == '/keys') {
if (msg.args[0] && msg.args[1] && msg.args[2] && msg.args[3]) { if (msg.args[0] == 1) {
eulerRotation = [0, 0, 0] eulerRotation = [0, 0, 0];
console.log("EULER ROTATION RESET");
} }
} }
@ -255,53 +208,31 @@ const sendAll = (msg, info, oscWS, osclients) => {
}) })
if (scudp) { if (scudp) {
if (DEBUG.udp) { console.log("SENDING UDP", msg)
console.log("UDP SEND", msg)
}
scudp.send(msg) scudp.send(msg)
} }
} }
let osclients = [] const osclients = []
wss.on('connection', function (ws) { wss.on('connection', function (ws) {
console.log('new client connection', ws._socket.remoteAddress) console.log('new client connection')
let oscWS = new osc.WebSocketPort({ const oscWS = new osc.WebSocketPort({
socket: ws socket: ws,
metadata: false
}); });
// Vsi OSC sem grejo naprej na kliente OSC // Vsi OSC sem grejo naprej na kliente OSC
oscWS.on('message', ({ address, args}, info) => { oscWS.on('packet', (packet, info) => {
console.log('fasal sem', address, args) // Broadcast adjust msg
if (MIDI) { const [address, args] = packet
if (address == '/midi') {
if (DEBUG.midi) {
console.log('midi SEND', args)
}
mo.send(args)
}
}
sendAll({ address, args}, info, oscWS, osclients) sendAll({ address, args}, info, oscWS, osclients)
}) })
oscWS.on('error', error => { oscWS.on('error', error => {
console.warn('Ignoring invalid OSC') console.warn('Ignoring invalid OSC')
console.warn(error) console.warn(error)
oscWS.close()
osclients = osclients.filter(ws => ws !== oscWS)
}) })
osclients.push(oscWS) osclients.push(oscWS)
oscWS.on('close', () => {
console.log('closing socket', oscWS.socket.remoteAddress)
osclients = osclients.filter(ws => ws !== oscWS)
})
}) })
// Zapri midi
/*
if (MIDI && mo) {
mo.closePort()
}
*/

View File

@ -65,8 +65,9 @@ scene.add(skupina);
// Quaternioni za rotacijo in kalibracijo // Quaternioni za rotacijo in kalibracijo
var qWW = new THREE.Quaternion(); var qWW = new THREE.Quaternion();
var qObj = new THREE.Quaternion(); var qObj = new THREE.Quaternion(-1, 0, 0, 0);
var qStart = new THREE.Quaternion(); var qStart = new THREE.Quaternion(-1, 0, 0, 0);
var qCalibrate = new THREE.Quaternion();
var reset = false; var reset = false;