const osc = require('osc') const midi = require('midi') const Quat = require('quaternion'); // Stevilke senzorjev const INDEX_GLAVA = 1 const INDEX_ROKA = 2 const INDEX_BEKAP = 3 // CC kanali za midi mapping (kanal, CC kanal) const midiKanal = 176; // CC kanali senzorjev const midiKanalSenzor = { 1: 20, 2: 21, 3: 22 } const senzorCCKanal = { 1: 75, 2: 76, 3: 77 } const senzorCCMute = { 1: 78, 2: 79, 3: 80 } const senzorCCkalibracija = { 1: 81, 2: 82, 3: 83 } const DEBUG = { midi: true, osc: false } // Kalibracijsko izhodisce const izhodisceQ = { 1: new Quat(), 2: new Quat(), 3: new Quat() } const prejsnjiQ = { 1: new Quat(), 2: new Quat(), 3: new Quat() } const eulerRotacija = { 1: [0, 0, 0], 2: [0, 0, 0], 3: [0, 0, 0] } const senzorCC = { 1: 64, 2: 64, 3: 64 } let staroVrtenjeZMidi = { 1: 0, 2: 0, 3: 0 }; const muteMidi = { 1: 0, 2: 0, 3: 0 } // Midi controller input const mi = new midi.Input() mi.openVirtualPort("danijela-midi") mi.on('message', (deltaTime, msg) => { if (msg[0] === midiKanal) { if (Object.values(senzorCCKanal).includes(msg[1])) { const s = Object.values(senzorCCKanal).indexOf(msg[1]) + 1 if (!muteMidi[s]) { senzorCC[s] = msg[2] console.log(`senzor ${s}: ${msg[2]}`) } } else if (Object.values(senzorCCMute).includes(msg[1])) { const s = Object.values(senzorCCMute).indexOf(msg[1]) + 1 if (msg[2]) { console.log(`senzor UNMUTE ${s}`) muteMidi[s] = false; } else { muteMidi[s] = true; console.log(`senzor MUTE ${s}`) } } else if (Object.values(senzorCCkalibracija).includes(msg[1])) { const s = Object.values(senzorCCkalibracija).indexOf(msg[1]) + 1 izhodisceQ[s] = prejsnjiQ[s].conjugate() console.log(`senzor KALIBRACIJA ${s}`) } } //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(midiKanal, 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) 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 novQ = new Quat({w: args[0], x: args[1], y: args[2], z: args[3]}) const novQC = novQ.mul(izhodisceQ[index]) const qWd = novQC.div(prejsnjiQ[index]) prejsnjiQ[index] = novQC; const eulerD = qWd.toEuler() //console.log(index, eulerD) eulerRotacija[index][0] += eulerD.roll * (senzorCC[index] / 64); eulerRotacija[index][1] += eulerD.pitch * (senzorCC[index] / 64); eulerRotacija[index][2] += eulerD.yaw * (senzorCC[index] / 64); const vrtenjeX = Math.abs(Math.sin(eulerRotacija[index][0])); /* posljiMidi(180, 20, Math.round(vrtenjeX * 127)); */ // Roka dol/gor const vrtenjeY = Math.abs(Math.sin(eulerRotacija[index][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(eulerRotacija[index][2]) //console.log(vrtenjeZ) const vrtenjeZmidi = Math.round(vrtenjeZ * 127) //console.log('vrtenjeZ', vrtenjeZmidi) //console.log('cmp', vrtenjeZmidi, staroVrtenjeZmidi); //console.log(vrtenjeZmidi); if (vrtenjeZmidi !== staroVrtenjeZMidi[index] && !muteMidi[index]) { posljiMidi(182, midiKanalSenzor[index], vrtenjeZmidi) staroVrtenjeZMidi[index] = vrtenjeZmidi } } } }) oscWS.open()