const osc = require('osc') const midi = require('midi') const Quat = require('quaternion'); // Stevilke senzorjev const INDEX_GLAVA = 1 const INDEX_ROKA = 2 // CC kanali za midi mapping (kanal, CC kanal) const senzorGlaveCCKanal = [176, 75] const senzorRokeCCKanal = [176, 76] const DEBUG = { midi: true, osc: false } // Kalibracijsko izhodisce let izhodisceQGlave = new Quat() let izhodisceQRoke = new Quat() let prejsnjiQGlave = new Quat() let prejsnjiQRoke = new Quat() let eulerRotacijaRoke = [0, 0, 0] let eulerRotacijaGlave = [0, 0, 0] let senzorGlaveCC = 64 let senzorRokeCC = 64 let staroVrtenjeZmidi = 0; // Midi controller input const mi = new midi.Input() mi.openVirtualPort("danijela-midi") mi.on('message', (deltaTime, msg) => { if (msg[0] === senzorGlaveCCKanal[0] && msg[1] === senzorGlaveCCKanal[1]) { senzorGlaveCC = msg[2] console.log(`senzor glave CC ${senzorGlaveCC}`) } if (msg[0] === senzorRokeCCKanal[0] && msg[1] === senzorRokeCCKanal[1]) { senzorRokeCC = msg[2] console.log(`senzor roke CC ${senzorRokeCC}`) } // console.log(`midi in: ${msg} d: ${deltaTime}`); if (senzorGlaveCC === 0 && senzorRokeCC === 0) { console.log('===== KALIBRACIJA! =====') let izhodisceQGlave = prejsnjiQGlave.conjugate() let izhodisceQRoke = prejsnjiQRoke.conjugate() } }) // Razpon za pospeskomerje const accMin = -8000 const accMax = 8000 // Povezava na wavey wind const ip = process.argv[2] const oscWS = new osc.WebSocketPort({ url: `ws://${ip}:6676`, metadata: false }) oscWS.on('ready', () => { console.log(`Povezan sem na ${ip}`) /* PING test! setInterval(() => { console.log('ping') oscWS.send({ address: '/ping', args: [true]}) }, 500) */ }) function posljiMidi(kanal, vrednost, jakost) { if (DEBUG.midi) { console.log('MIDI', kanal, vrednost, jakost) } oscWS.send({ address: '/midi', args: [kanal, vrednost, jakost] }) } function posljiMidiCC(kanal, vrednost) { posljiMidi(176, kanal, vrednost); } //const norm = (val, min, max) => Math.min(1, (val - min) / (max - min)) const norm = (val, min, max) => { const d = 0 - min; const r = max - min return Math.min(1, (Math.max(min, val) + d) / r); } const normSin = val => { return norm(Math.sin(val), -1, 1); } const normMidi = (val, min, max) => Math.round(norm(val, min, max) * 127) const abs = Math.abs; let cakaj = false; oscWS.on('message', ({ address, args }) => { DEBUG.osc && console.log('MSG OSC', address, args.map(x => x.toFixed(4))) // Wavey Wind sporočila const re = /\/ww\/0\/ww\/(\d+)\/([a-zA-Z]+)/ const m = address.match(re) //console.log(m); if (m) { const index = parseInt(m[1]) const addr = m[2] if (addr == 'euler') { } if (addr == 'accel') { const acX = args[0] const acY = args[1] const acZ = args[2] //console.log(acX, acY, acZ); // CC sporocila! /* posljiMidiCC(20, normMidi(acX, accMin, accMax)); posljiMidiCC(21, normMidi(acY, accMin, accMax)); posljiMidiCC(22, normMidi(acZ, accMin, accMax)); */ } if (addr == 'quaternion') { //console.log('IDX', index) // Izracunaj spremembo rotacije const novQGlave = new Quat({w: args[0], x: args[1], y: args[2], z: args[3]}) const novQGlaveC = novQGlave.mul(izhodisceQGlave) const qWdGlave = novQGlaveC.div(prejsnjiQGlave) prejsnjiQGlave = novQGlaveC; const eulerD = qWdGlave.toEuler() eulerRotacijaGlave[0] += eulerD.roll * (senzorGlaveCC / 64); eulerRotacijaGlave[1] += eulerD.pitch * (senzorGlaveCC / 64); eulerRotacijaGlave[2] += eulerD.yaw * (senzorGlaveCC / 64); const vrtenjeX = Math.abs(Math.sin(eulerRotacijaGlave[0])); /* posljiMidi(180, 20, Math.round(vrtenjeX * 127)); */ // Roka dol/gor const vrtenjeY = Math.abs(Math.sin(eulerRotacijaGlave[1])); //posljiMidi(180, 20, Math.round(vrtenjeY * 127)); //posljiMidi(181, 20, Math.round(vrtenjeY * 127)); // Vrtenje levo/desno (stegnjena roka) //console.log(eulerRotacijaGlave) const vrtenjeZ = normSin(eulerRotacijaGlave[2]) const vrtenjeZmidi = Math.round(vrtenjeZ * 127); //console.log('vrtenjeZ', vrtenjeZmidi) //console.log('cmp', vrtenjeZmidi, staroVrtenjeZmidi); if ((vrtenjeZmidi !== staroVrtenjeZmidi) && (senzorRokeCC !== 0)) { posljiMidi(182, 20, vrtenjeZmidi); staroVrtenjeZmidi = vrtenjeZmidi; } //console.log('VRTENJE', euler.map(x => x.toFixed(3))); /* if (vrtenjeZ > 0.95 && !cakaj) { console.log('POSLJI TON!'); //posljiMidi(151, 60, 127); cakaj = true; setTimeout(function () { cakaj = false; }, 250); } */ } } }) oscWS.open()