195 lines
4.7 KiB
JavaScript
195 lines
4.7 KiB
JavaScript
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, 23]
|
|
const senzorRokeCCKanal = [176, 19]
|
|
|
|
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()
|