diff --git a/app.js b/app.js index 33cf109..95f3e36 100755 --- a/app.js +++ b/app.js @@ -17,6 +17,8 @@ const exec = require('child_process').exec; const os = require('os'); const request = require('request'); +// vagrant でうまく動かないので、いったんコメントアウト +/* const five = require('johnny-five'); const board = new five.Board(); let boardSwitch = false; @@ -28,7 +30,7 @@ board.on('ready', () => { relay.off(); },500); }); - +*/ const exportComponent = require('./exportFunction.js'); const keycodeMap = require ('./lib/keyCode.json'); let statusList = require ('./lib/status.json'); @@ -40,10 +42,10 @@ const http = require('http'); //https鍵読み込み const options = { - key: fs.readFileSync(process.env.HTTPSKEY_PATH + 'privkey.pem'), - cert: fs.readFileSync(process.env.HTTPSKEY_PATH + 'cert.pem') -// key: fs.readFileSync('/home/knd/httpsKeys/' + 'key.pem'), -// cert: fs.readFileSync('/home/knd/httpsKeys/' + 'cert.pem') +// key: fs.readFileSync(process.env.HTTPSKEY_PATH + 'privkey.pem'), +// cert: fs.readFileSync(process.env.HTTPSKEY_PATH + 'cert.pem') + key: fs.readFileSync('./httpsKeys/' + 'privkey.pem'), + cert: fs.readFileSync('./httpsKeys/' + 'cert.pem') } @@ -111,8 +113,15 @@ let io = require('socket.io').listen(server); let httpPort = 8000; let httpServer = http.createServer(app).listen(httpPort); -console.log("server start in " + os.networkInterfaces().en0[0]["address"] + ":" + String(port)); -console.log("server start in " + os.networkInterfaces().en0[1]["address"] + ":" + String(port)); +if("en0" in os.networkInterfaces()){ + console.log("server start in " + os.networkInterfaces().en0[0]["address"] + ":" + String(port)); + console.log("server start in " + os.networkInterfaces().en0[1]["address"] + ":" + String(port)); +} else { + for(let key in os.networkInterfaces()){ + console.log("server start in " + os.networkInterfaces()[key][0]["address"] + ":" + String(port)) + console.log("server start in " + os.networkInterfaces()[key][1]["address"] + ":" + String(port)) + } +} const pcm2arr = (url) => { let tmpBuff = new Float32Array(8192); @@ -330,8 +339,38 @@ io.sockets.on('connection',(socket)=>{ "STREAMS": { "SECBEFORE": {"TO": true, "ACK": true, "arr": 0, "LATENCY": "0", "RATE":"44100"}, "RECORD": {"FROM": true, "arr": 0} - } + }, + "rhythm":{ + "bpm": 60 + } }; + switch(cliNo){ + case 0: + statusList.clients[sockId].rhythm["score"] = [1,1,1,1] + statusList.clients[sockId].rhythm["timbre"] = 440 + break; + case 1: + statusList.clients[sockId].rhythm["score"] = [0,1,0,1] + statusList.clients[sockId].rhythm["timbre"] = 880 + break; + case 2: + statusList.clients[sockId].rhythm["score"] = [1,0,0,0] + statusList.clients[sockId].rhythm["timbre"] = 110 + break; + case 3: + statusList.clients[sockId].rhythm["score"] = [1,0,0] + statusList.clients[sockId].rhythm["timbre"] = 220 + break; + case 4: + statusList.clients[sockId].rhythm["score"] = [1,0,0,1,0,0] + statusList.clients[sockId].rhythm["timbre"] = 660 + break; + default: + statusList.clients[sockId].rhythm["score"] = [1,1,1,1] + statusList.clients[sockId].rhythm["timbre"] = 440 + break; + } + statusList.clients[sockId].rhythm["interval"] = (60000 * 4)/(statusList.clients[sockId].rhythm.bpm * statusList.clients[sockId].rhythm.score.length) for(let key in statusList["cmd"]["streamFlag"]){ switch(key){ case "CHAT": @@ -349,6 +388,7 @@ io.sockets.on('connection',(socket)=>{ console.log(statusList["clients"]); io.to("ctrl").emit("statusFromServer", statusList); io.emit('streamListFromServer', statusList["streamStatus"]["streamCmd"]); + socket.emit('connectFromServer', statusList.clients[sockId]); /*debug io.emit("cmdFromServer", { "cmd": "INSTRUCTION", @@ -492,6 +532,27 @@ io.sockets.on('connection',(socket)=>{ }); +//let droneRoute = {}; +const droneRoute = () =>{ +//console.log("mode DRONE"); + let idArr = Object.keys(statusList.clients); + let rtnRoute = {}; + for(let i=0;i{ +// streamReq("droneChat"); +// },500); + return rtnRoute +} + const enterFromClient = (keyCode, socket) =>{ exportComponent.roomEmit(io,'textFromServer', strings, statusList["cmd"]["target"]); switch(strings){ @@ -603,6 +664,18 @@ const enterFromClient = (keyCode, socket) =>{ statusList["streamStatus"]["glitch"] = true; } break; + case "DRONE": + if(statusList["streamStatus"]["drone"]) { + statusList["streamStatus"]["drone"] = false; + } else { + statusList["streamStatus"]["drone"] = true; + statusList.streamStatus.droneRoute = droneRoute(); + } + io.emit('cmdFromServer',{ + "cmd": "DRONE", + "property": statusList.streamStatus.drone + }); + break; default: let cmd = cmdSelect(strings); if(cmd) { @@ -683,11 +756,52 @@ const charFromClient = (keyCode, socket) =>{ } else if(keyCode >= 48 && keyCode <= 90 || keyCode === 190 || keyCode === 32 || keyCode === 189 || keyCode === 226 || keyCode === 220){ //alphabet or number strings = strings + character; exportComponent.roomEmit(io, 'stringsFromServer', strings, statusList["cmd"]["target"]); + if(keyCode === 32) metronomeBPMCount(socket.id); } else if(character === "up_arrow"){ strings = statusList["cmd"]["prevCmd"]; exportComponent.roomEmit(io, 'stringsFromServer', strings, statusList["cmd"]["target"]); + //} else if(keyCode === 32){ + //console.log("debg"); + //spaceForMetronome(); } +} +let metronomeArr = []; +const metronomeBPMCount = (sourceId) =>{ + switch(metronomeArr.length){ + case 3: + let interval = (new Date().getTime() - metronomeArr[0])/3 + let bpm = 60000 / interval + statusList.clients[String(sourceId)].rhythm.bpm = bpm + statusList.clients[String(sourceId)].rhythm.interval = (60000 * 4) / (statusList.clients[String(sourceId)].rhythm.score.length * bpm) + //console.log(interval); + //console.log(bpm); + console.log(statusList.clients[String(sourceId)].rhythm); + io.to(sourceId).emit('cmdFromServer',{ + "cmd": "METRONOME", + "type": "param", + "trig": true, + "property": statusList.clients[String(sourceId)].rhythm + }); + /* + setTimeout(()=>{ + io.to(sourceId).emit('cmdFromServer',{ + "cmd": "METRONOME", + "type": "trig" + }); + }, statusList.clients[String(sourceId)].rhythm.interval) + */ + metronomeArr = []; + break; + default: + metronomeArr.push(new Date().getTime()); + let tapLength = Number(metronomeArr.length) + console.log(metronomeArr); + setTimeout(()=>{ + if(metronomeArr.length === tapLength) metronomeArr = []; + },10000); + break; + } } const joinUnderBar = (strings) => { @@ -790,6 +904,22 @@ const joinUnderBar = (strings) => { exportComponent.roomEmit(io, 'stringsFromServer', "sampling rate(" + strArr[0]+"):"+rtnRate + "Hz", statusList["cmd"]["target"]); } break; + case "STOP": + case "OFF": + for(let key in statusList["streamStatus"]["streamCmd"]){ + if(strArr[1] === key){ + console.log("stream stop"); + statusList.streamStatus.streamFlag[statusList.streamStatus.streamCmd[key]] = false + } + } + if(strArr[1] === "CLICK" || strArr[1] === "METRONOME") { + //console.log("stop"); + io.emit('cmdFromServer',{ + "cmd": "METRONOME", + "property": "STOP" + }); + } + break } Object.keys(io.sockets.adapter.rooms).forEach((value,index,arr)=>{ let targetRoom = strArr[0].toLowerCase(); @@ -846,77 +976,25 @@ const streamReq = (target, sockID) => { //console.log("Stream Request in " + target) if(statusList["streamStatus"]["streamFlag"][target]){ if(statusList["clients"][sockID] != undefined && statusList["clients"][sockID]["STREAMS"] != undefined && Number(statusList["clients"][sockID]["STREAMS"][target]["LATENCY"]) > 0) { - setTimeout(()=>{ - let idArr = []; - switch(target){ - case "CHAT": - idArr = exportComponent.pickupTarget(io.sockets.adapter.rooms, statusList["clients"], target, "FROM"); - if(idArr.length > 0){ - io.to(idArr[Math.floor(Math.random() * idArr.length)]).emit('streamReqFromServer', "CHAT"); - } - break; - case "TIMELAPSE": - idArr = exportComponent.pickupTarget(io.sockets.adapter.rooms, statusList["clients"], target, "TO"); - let json = { - "target": target, - "video": "", - "glitch": false - }; - if(idArr.length > 0 && timeLapseLength <= audioBuff[target].length){ - let targetID = idArr[Math.floor(Math.random() * idArr.length)]; - json["sampleRate"] = Number(statusList["clients"][String(targetID)]["STREAMS"][target]["RATE"]); - json["audio"] = audioBuff[target].shift(); - audioBuff[target].push(json["audio"]); - if(target in videoBuff && videoBuff[target].length > 0){ - json["video"] = videoBuff[target].shift(); - videoBuff[target].push(json["video"]); - if(statusList["streamStatus"]["glitch"]) json = exportComponent.glitchStream(json); + setTimeout(()=>{ + let idArr = []; + switch(target){ + case "CHAT": + idArr = exportComponent.pickupTarget(io.sockets.adapter.rooms, statusList["clients"], target, "FROM"); + if(idArr.length > 0){ + io.to(idArr[Math.floor(Math.random() * idArr.length)]).emit('streamReqFromServer', "CHAT"); } - io.to(targetID).emit('chunkFromServer', json); - timeLapseLength++; - } else if(timeLapseLength > audioBuff[target].length){ - timeLapseLength = 0; - io.emit('stringsFromServer', ""); - } else { - console.log("no timelapse target"); - } - break; - default: //PLAYBACK,TIMELAPSE,DRUM,SILENCEも含む //1008はTimelapseは含まず - idArr = exportComponent.pickupTarget(io.sockets.adapter.rooms, statusList["clients"], target, "TO"); - // console.log(idArr); - //console.log(idArr); - if(idArr.length > 0){ + break; + case "TIMELAPSE": + idArr = exportComponent.pickupTarget(io.sockets.adapter.rooms, statusList["clients"], target, "TO"); let json = { "target": target, "video": "", "glitch": false }; - let targetID = idArr[Math.floor(Math.random() * idArr.length)]; - json["sampleRate"] = Number(statusList["clients"][String(targetID)]["STREAMS"][target]["RATE"]); - if(statusList["streamStatus"]["emitMode"] === "RANDOM"){ - json["audio"] = audioBuff[target][Math.floor(Math.random() * audioBuff[target].length)]; - if(target in videoBuff && videoBuff[target].length > 0) { - json["video"] = videoBuff[target][Math.floor(Math.random() * videoBuff[target].length)]; - if(statusList["streamStatus"]["glitch"]) json = exportComponent.glitchStream(json); - } - //io.to(idArr[Math.floor(Math.random() * idArr.length)]).emit('chunkFromServer', json); - io.to(targetID).emit('chunkFromServer', json); - } else if(statusList["streamStatus"]["emitMode"] === "BROADCAST"){ - let idArr = exportComponent.pickupTarget(io.sockets.adapter.rooms, statusList["clients"], target, "TO") - for(let i=0;i 0) { - json["video"] = videoBuff[statusList["clients"][String(idArr[i])][target]["arr"]]; - if(statusList["streamStatus"]["glitch"]) json = exportComponent.glitchStream(json); - } - io.to(idArr[i]).emit('chunkFromServer',json); - if(statusList["clients"][String(idArr[i])][target]["arr"] < audioBuff[target].length){ - statusList["clients"][String(idArr[i])][target]["arr"]++; - } else { - statusList["clients"][String(idArr[i])][target]["arr"] = 0; - } - } - } else { + if(idArr.length > 0 && timeLapseLength <= audioBuff[target].length){ + let targetID = idArr[Math.floor(Math.random() * idArr.length)]; + json["sampleRate"] = Number(statusList["clients"][String(targetID)]["STREAMS"][target]["RATE"]); json["audio"] = audioBuff[target].shift(); audioBuff[target].push(json["audio"]); if(target in videoBuff && videoBuff[target].length > 0){ @@ -925,18 +1003,70 @@ const streamReq = (target, sockID) => { if(statusList["streamStatus"]["glitch"]) json = exportComponent.glitchStream(json); } io.to(targetID).emit('chunkFromServer', json); + timeLapseLength++; + } else if(timeLapseLength > audioBuff[target].length){ + timeLapseLength = 0; + io.emit('stringsFromServer', ""); + } else { + console.log("no timelapse target"); + } + break; + default: //PLAYBACK,TIMELAPSE,DRUM,SILENCEも含む //1008はTimelapseは含まず + idArr = exportComponent.pickupTarget(io.sockets.adapter.rooms, statusList["clients"], target, "TO"); + // console.log(idArr); + //console.log(idArr); + if(idArr.length > 0){ + let json = { + "target": target, + "video": "", + "glitch": false + }; + let targetID = idArr[Math.floor(Math.random() * idArr.length)]; + json["sampleRate"] = Number(statusList["clients"][String(targetID)]["STREAMS"][target]["RATE"]); + if(statusList["streamStatus"]["emitMode"] === "RANDOM"){ + json["audio"] = audioBuff[target][Math.floor(Math.random() * audioBuff[target].length)]; + if(target in videoBuff && videoBuff[target].length > 0) { + json["video"] = videoBuff[target][Math.floor(Math.random() * videoBuff[target].length)]; + if(statusList["streamStatus"]["glitch"] && target != "DRUM") json = exportComponent.glitchStream(json); + } + //io.to(idArr[Math.floor(Math.random() * idArr.length)]).emit('chunkFromServer', json); + io.to(targetID).emit('chunkFromServer', json); + } else if(statusList["streamStatus"]["emitMode"] === "BROADCAST"){ + let idArr = exportComponent.pickupTarget(io.sockets.adapter.rooms, statusList["clients"], target, "TO") + for(let i=0;i 0) { + json["video"] = videoBuff[statusList["clients"][String(idArr[i])][target]["arr"]]; + if(statusList["streamStatus"]["glitch"]) json = exportComponent.glitchStream(json); + } + io.to(idArr[i]).emit('chunkFromServer',json); + if(statusList["clients"][String(idArr[i])][target]["arr"] < audioBuff[target].length){ + statusList["clients"][String(idArr[i])][target]["arr"]++; + } else { + statusList["clients"][String(idArr[i])][target]["arr"] = 0; + } + } + } else { + json["audio"] = audioBuff[target].shift(); + audioBuff[target].push(json["audio"]); + if(target in videoBuff && videoBuff[target].length > 0){ + json["video"] = videoBuff[target].shift(); + videoBuff[target].push(json["video"]); + if(statusList["streamStatus"]["glitch"]) json = exportComponent.glitchStream(json); + } + io.to(targetID).emit('chunkFromServer', json); + } + } else { + console.log("no target"); + //json["audio"] = ""; + //json["video"] = ""; + //json["sampleRate"] = 44100; + //console.log(json); + //io.emit('chunkFromServer', json); } - } else { - console.log("no target"); - //json["audio"] = ""; - //json["video"] = ""; - //json["sampleRate"] = 44100; - //console.log(json); - //io.emit('chunkFromServer', json); - } - break; - } - },Number(statusList["clients"][sockID]["STREAMS"][target]["LATENCY"] * Math.random())); + break; + } + },Number(statusList["clients"][sockID]["STREAMS"][target]["LATENCY"] * Math.random())); } else { let idArr = []; switch(target){ @@ -1028,85 +1158,100 @@ const streamReq = (target, sockID) => { break; } } + } else if(target === "droneChat") { + console.log("stream request for droneChat"); + io.emit('streamReqFromServer', "droneChat"); } } const chunkFromClient = (data, sourceId) => { - let json = { - "glitch": false - }; - //console.log(data); - if(data["target"]){ - audioBuff[data["target"]].push(data["audio"]); - videoBuff[data["target"]].push(data["video"]); - } else { - // console.log(data); - if(audioBuff["CHAT"].length === 0) audioBuff["CHAT"].push(""); - if(videoBuff["CHAT"].length === 0) videoBuff["CHAT"].push(""); - console.log(audioBuff["CHAT"].length); - console.log(videoBuff["CHAT"].length); - } - //console.log(data["target"] + " length: " + String(audioBuff[data["target"]].length)); - //console.log(statusList["clients"][sourceId]); - let sampleRate = String(statusList["clients"][sourceId]["STREAMS"]["CHAT"]["RATE"]); - if(statusList["streamStatus"]["streamFlag"]["CHAT"]){ - let idArr = [] - idArr = exportComponent.pickupTarget(io.sockets.adapter.rooms, statusList["clients"], "CHAT", "TO") - //console.log(idArr); - if(idArr.length > 0){ - let clientRate = false; - for(let i=0;i 0){ + let clientRate = false; for(let i=0;i audioBuff[statusList["clients"][String(idArr[i])]["STREAMS"]["CHAT"]["arr"]]) minItem = audioBuff[statusList["clients"][String(idArr[i])]["STREAMS"]["CHAT"]["arr"]]; - } - if(minItem != undefined && minItem > 0){ - for(let i=0; i audioBuff[statusList["clients"][String(idArr[i])]["STREAMS"]["CHAT"]["arr"]]) minItem = audioBuff[statusList["clients"][String(idArr[i])]["STREAMS"]["CHAT"]["arr"]]; + + } + if(minItem != undefined && minItem > 0){ + for(let i=0; i{ - /* - for(let key in data["audio"]){ - if(data["audio"][key] > 0){ - rtnAudio[key] = data["audio"][key]; - } else { - //rtnAudio[key] = 0; - rtnAudio[key] = data["audio"][key] * -1; + if("video" in data && ~data.video.indexOf("data:image/jpeg;base64,")){ + let rtnVideo = "data:image/jpeg;base64,"; + let baseImgString = data["video"].split("data:image/jpeg;base64,")[1]; + //let str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + let str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + //console.log("body; " + String(baseString.length)); + //console.log(baseString); + //rtnJson["video"] += baseImgString.replace(str[Math.floor(Math.random()*str.length)], str[Math.floor(Math.random()*str.length)]); + rtnVideo += baseImgString.replace(str[Math.floor(Math.random()*str.length)], str[Math.floor(Math.random()*str.length)]); + + rtnJson["video"] = rtnVideo.replace(String(Math.floor(Math.random() + 10)), String(Math.floor(Math.random() + 10))); + //data["audio"].forEach((value,index,arr)=>{ + /* + for(let key in data["audio"]){ + if(data["audio"][key] > 0){ + rtnAudio[key] = data["audio"][key]; + } else { + //rtnAudio[key] = 0; + rtnAudio[key] = data["audio"][key] * -1; + } + } + //}); + rtnJson["audio"] = rtnAudio;*/ + //console.log(rtnJson); + //console.log(data.audio[String(1)]); + /* + if(data.audio != undefined){ + rtnJson.audio = new Float32Array(8192); + //console.log(rtnJson.audio); + //console.log(data.audio.length) + + for(let i=0;i { src.start(); // console.log("alert"); } -const click = () => { +const click = (frequency) => { + clickOsc.frequency.value = frequency || 440 modules.textPrint(ctx, canvas, "CLICK") let t0 = audioContext.currentTime; // clickGain.gain.value = 0.7; @@ -208,39 +212,80 @@ let image; let receive; let receive_ctx; const onAudioProcess = (e) => { - if(videoMode != "none"){ + if(videoMode.mode != "none"){ + //consol.log(videoMode); let bufferData = new Float32Array(bufferSize); e.inputBuffer.copyFromChannel(bufferData, 0); - switch(videoMode){ - case "record": - modules.chunkEmit({"audio":bufferData, "video":funcToBase64(buffer, video), "target": "PLAYBACK"},socket); - break; - case "chat": - chatBuffer["audio"] = bufferData; - chatBuffer["video"] = funcToBase64(buffer, video); - chatBuffer["target"] = "CHAT"; - break; - case "pastBuff": - streamBuffer.push({ - "audio": bufferData, - "video": funcToBase64(buffer, video) - }); + if(videoMode.option != "drone"){ + switch(videoMode.mode){ + case "record": + modules.chunkEmit({"audio":bufferData, "video":funcToBase64(buffer, video), "target": "PLAYBACK"},socket); break; - case "pastPlay": - let beforeChunk = {}; - if(streamBuffer.length>0){ - beforeChunk = streamBuffer.shift(); - } else { - beforeChunk = {"audio": bufferData, "video": funcToBase64(buffer, video)}; - } - playAudioStream(beforeChunk["audio"],bufferRate,gainVal["SECBEFORE"],false); - playVideo(beforeChunk["video"]); - console.log(streamBuffer.length); + case "chat": + chatBuffer["audio"] = bufferData; + chatBuffer["video"] = funcToBase64(buffer, video); + chatBuffer["target"] = "CHAT"; + break; + case "pastBuff": streamBuffer.push({ "audio": bufferData, "video": funcToBase64(buffer, video) - }) - break; + }); + break; + case "pastPlay": + let beforeChunk = {}; + if(streamBuffer.length>0){ + beforeChunk = streamBuffer.shift(); + } else { + beforeChunk = {"audio": bufferData, "video": funcToBase64(buffer, video)}; + } + playAudioStream(beforeChunk["audio"],bufferRate,gainVal["SECBEFORE"],false); + playVideo(beforeChunk["video"]); + console.log(streamBuffer.length); + streamBuffer.push({ + "audio": bufferData, + "video": funcToBase64(buffer, video) + }) + break; + /* + case "droneChat": + chatBuffer["audio"] = bufferData; + chatBuffer["video"] = modules.toBase64(buffer, video); + chatBuffer["target"] = "DRONECHAT"; + //console.log(droneBuff); + //if(droneBuff != undefined || droneBuff != {}){ + if("audio" in droneBuff){ + //console.log(droneBuff.sampleRate); + //console.log(droneBuff.gain); + playAudioStream(droneBuff["audio"],droneBuff["sampleRate"],droneBuff["gain"],false); + playVideo(droneBuff["video"]); + } else { + //console.log("debug"); + modules.textPrint(ctx, canvas, stringsClient); + //ssu? + } + break; + */ + } + } else { + //if(videoMode.option === "drone"){ + console.log(droneBuff) + if(droneBuff != undefined && droneBuff != {} && droneflag){ + if("audio" in droneBuff) playAudioStream(droneBuff["audio"],droneBuff["sampleRate"],droneBuff["gain"],droneBuff.glitch); + if("video" in droneBuff){ + playVideo(droneBuff["video"]); + } else { + modules.textPrint(ctx, canvas, stringsClient); + } + console.log("play"); + if(droneBuff.target === "CHAT"){ + chatBuffer["audio"] = bufferData; + chatBuffer["video"] = modules.toBase64(buffer, video); + chatBuffer["target"] = droneBuff.target; + } else { + socket.emit('wavReqFromClient', data["target"]); + } + } } } if(timelapseFlag){ @@ -252,22 +297,38 @@ const onAudioProcess = (e) => { } } const playAudioStream = (flo32arr, sampleRate, volume, glitch) => { - let audio_buf = audioContext.createBuffer(1, bufferSize, sampleRate), - audio_src = audioContext.createBufferSource(); - let audioData = new Float32Array(bufferSize); - for(let i = 0; i < audioData.length; i++){ - audioData[i] = flo32arr[i] * volume; - } - audio_buf.copyToChannel(audioData, 0); - // console.log(audio_buf); - audio_src.buffer = audio_buf; - audio_src.connect(masterGain); - /*if(glitch){ - convolver.buffer = audio_buf; - audio_src.connect(convolver); - }*/ - audio_src.start(0); + //if(!glitch){ + let audio_src = audioContext.createBufferSource(); + let audioData = new Float32Array(bufferSize); + for(let i = 0; i < audioData.length; i++){ + audioData[i] = flo32arr[i] * volume; + } + if(!glitch){ + console.log(sampleRate) + let audio_buf = audioContext.createBuffer(1, bufferSize, sampleRate) + audio_buf.copyToChannel(audioData, 0); + audio_src.buffer = audio_buf; + audio_src.connect(masterGain); + } else { + console.log("glitch") + let audio_buf = audioContext.createBuffer(1, bufferSize, convolver.context.sampleRate) + audio_buf.copyToChannel(audioData, 0); + // console.log(audio_buf); + + audio_src.buffer = audio_buf; + convolver.buffer = audio_buf; + audio_src.connect(convolver); + } + //let timeOut = audio_src.buffer.duration * 1000; + audio_src.start(0); + /* + droneflag = false + setTimeout(()=>{ + droneflag = true + },timeOut);*/ + //} } +droneflag = true; //video record/play ここまで const initialize = () =>{ @@ -340,6 +401,40 @@ const initialize = () =>{ receive_ctx = receive.getContext("2d"); }; +//metronome +let rhythmProperty = { + "bpm": 60, + "interval": 1000, + "score": [1,1,1,1], + "timbre": 440 +}; +let metronome; +let metronomeCount = 0; +const startRhythm = (interval) =>{ + metronome = setInterval(()=>{ + if(rhythmProperty.score[metronomeCount] === 1){ + switch(rhythmProperty.timbre){ + default: + click(rhythmProperty.timbre) + /* + clickOsc.frequency.value = rhythmProperty.timbre + clickGain.gain.setValueAtTime(gainVal["CLICK"], t0); + clickGain.gain.setTargetAtTime(0,t0,0.03); + */ + } + } + if(metronomeCount+1 < rhythmProperty.score.length){ + metronomeCount++ + } else { + metronomeCount = 0 + } + },interval); +} + +const stopRhythm = () => { + clearInterval(metronome); +} + //keyboard let stringsClient = ""; @@ -502,8 +597,10 @@ const renderStart=()=> { } /* socket */ - socket.emit('connectFromClient', client); +socket.on('connectFromServer', (data) => { + rhythmProperty = data.rhythm +}) socket.on('stringsFromServer', (data) =>{ modules.whitePrint(ctx, canvas); @@ -555,6 +652,7 @@ socket.on('streamListFromServer', (data) =>{ socket.on('streamReqFromServer', (data) => { switch(data){ case "CHAT": + case "droneChat": //if(chatBuffer!= {}){ socket.emit('chunkFromClient', chatBuffer); /*} else { @@ -571,36 +669,62 @@ socket.on('streamReqFromServer', (data) => { socket.on('oscFromServer',(data) => { let uint8arr = osc.toBuffer(data); }); - - +/* +const playGlitchedURL = (url) => { + if(~url.indexOf("data:image/jpeg;base64,")){ + let audioURL = "data:audio/wav;base64," + url.split("data:image/jpeg;base64,")[1].slice(0,-2) + "gAA=="; + console.log(audioURL); + let buff = Base64Binary.decodeArrayBuffer(audioURL); + audioContext.decodeAudioData(buff, (audioData)=>{ + let audioSrc = audioContext.createBufferSource() + audioSrc.buffer = audioData + audioSrc.connect(masterGain); + audioSrc.start(0); + }); + // 再生 たぶんdecodeaudiodataして再生 + } +} +*/ socket.on('chunkFromServer', (data) => { - //if(videoMode === "chat"){ - if(videoMode != "record"){ - if(videoMode != "chat") videoMode = "chat"; - if(data["audio"] != undefined && data["audio"] != "") { - let chunkGain = 0.7; - if(data["target"] in gainVal){ - chunkGain = gainVal[data["target"]]; + //if(videoMode.mode === "chat"){ + if(videoMode.mode != "record"){ + if(videoMode.mode != "chat" && data.target === "CHAT") videoMode.mode = "chat"; + //if(data.target === "DRONECHAT" && videoMode.mode === "droneChat"){ + if(videoMode.option === "drone"){ + droneBuff = data; + //socket.emit('wavReqFromClient', data["target"]); + console.log("wavReq"); + socket.emit('chunkFromClient', chatBuffer); + } else { + if(data["audio"] != undefined && data["audio"] != "") { + let chunkGain = 0.7; + if(data["target"] in gainVal){ + chunkGain = gainVal[data["target"]]; + } + //let playsampleRate = 44100 + //if(data.sampleRate != undefined) { + let playsampleRate = Number(data.sampleRate) + //} + console.log(playsampleRate); + //playAudioStream(data["audio"],Number(data["sampleRate"]),chunkGain,data["glitch"]); + playAudioStream(data["audio"],playsampleRate,chunkGain,data["glitch"]); + //if(data.glitch) playGlitchedURL(data.video); + } + if(data["video"] != undefined && data["video"] != "") { + playVideo(data["video"]); + } else if(data.target != "CHAT"){ + modules.whitePrint(ctx, canvas); + modules.textPrint(ctx, canvas, data["target"]); + } else { + modules.whitePrint(ctx, canvas); + } } - if(data["sampleRate"] != undefined){ - playAudioStream(data["audio"],data["sampleRate"],chunkGain,data["glitch"]); + if(data["target"] === "CHAT"){ + socket.emit('AckFromClient', "CHAT"); } else { - playAudioStream(data["audio"],44100,chunkGain,data["glitch"]); + socket.emit('wavReqFromClient', data["target"]); } } - if(data["video"] != undefined && data["video"] != "") { - playVideo(data["video"]); - } else { - modules.whitePrint(ctx, canvas); - modules.textPrint(ctx, canvas, data["target"]); - } - if(data["target"] === "CHAT"){ - socket.emit('AckFromClient', "CHAT"); - // console.log("ack"); - } else { - socket.emit('wavReqFromClient', data["target"]); - } - } }); @@ -792,12 +916,12 @@ const doCmd = (cmd) => { case "RECORD": case "REC": videoStop(); - videoMode = "record"; + videoMode.mode = "record"; modules.whitePrint(ctx, canvas); modules.textPrint(ctx, canvas, "RECORD"); setTimeout(() => { - if(videoMode === "record"){ - videoMode = "none"; + if(videoMode.mode === "record"){ + videoMode.mode = "none"; modules.whitePrint(ctx, canvas); } }, 5000); //時間は考え中 @@ -815,7 +939,7 @@ const doCmd = (cmd) => { streamBuffer = []; modules.whitePrint(ctx, canvas); modules.textPrint(ctx, canvas, String(cmd["property"]) + "SEC BEFORE"); - videoMode = "pastBuff"; + videoMode.mode = "pastBuff"; if(cmd["rate"] != undefined){ bufferRate = cmd["rate"]; } else { @@ -823,9 +947,48 @@ const doCmd = (cmd) => { } setTimeout(()=>{ modules.whitePrint(ctx, canvas); - videoMode = "pastPlay"; + videoMode.mode = "pastPlay"; },cmd["property"] * 1000); break; + case "DRONE": + if(cmd.property){ + //if(videoMode.option != "drone"){ + videoMode.option = "drone" + modules.whitePrint(ctx, canvas); + modules.textPrint(ctx, canvas, cmd["cmd"]); + setTimeout(()=>{ + modules.whitePrint(ctx, canvas); + },500) + } else { + videoMode.option = "none" + modules.whitePrint(ctx, canvas); + modules.textPrint(ctx, canvas, "UNDRONE"); + setTimeout(()=>{ + modules.whitePrint(ctx, canvas); + },500) + } + break; + case "METRONOME": + //console.log(cmd.property); + //if(cmd.type === "param") { + if(cmd.property === "STOP"){ + stopRhythm(); + } else { + modules.whitePrint(ctx, canvas); + modules.textPrint(ctx, canvas, "BPM:" + String(Math.floor(cmd.property.bpm * 10)/10)) + rhythmProperty = cmd.property; + console.log(rhythmProperty); + if(cmd.trig){ + stopRhythm(); + setTimeout(()=>{ + modules.whitePrint(ctx, canvas); + startRhythm(rhythmProperty.interval); + },rhythmProperty.interval) + } + //} + //if(cmd.trig) startRhythm(); + } + break; case "PREV": pastPresent(cmd["property"]); break; @@ -856,12 +1019,16 @@ const doCmd = (cmd) => { mode = "none" }, cmd["property"]["duration"]); break; + case "METRONOME": + modules.textPrint(ctx, canvas, "DUBUG"); + break; + default: console.log(cmd["cmd"]); for(let key in streamList){ if(key === cmd["cmd"]){ // console.log(cmd["cmd"]); - videoMode = "chat"; + videoMode.mode = "chat"; modules.whitePrint(ctx, canvas); modules.textPrint(ctx, canvas, cmd["cmd"]); setTimeout(()=> { @@ -912,16 +1079,17 @@ const stop = () => { // modules.textPrint(ctx, canvas, ""); mode = "none"; modules.textPrint(ctx, canvas, "STOP"); + stopRhythm(); } const videoStop = () => { - switch (videoMode) { + switch (videoMode.mode) { case "chunkEmit": break; case "beforePlay": case "beforeBuff": default: - videoMode = "none"; + videoMode.mode = "none"; break; } } @@ -933,7 +1101,7 @@ const pastPresent = (status) =>{ if(key === "SINEWAVE" && status[key]){ doCmd({"cmd":key, "property": Number(status[key])}); } else if(key === "SECBEFORE" && status[key]){ - videoMode = "pastPlay"; + videoMode.mode = "pastPlay"; } else if(status[key]){ doCmd({"cmd":key}); } @@ -970,7 +1138,7 @@ const stopLapse = ()=>{ /* const emitInterval = 120000; setInterval(() => { - // if(videoMode === "none"){ + // if(videoMode.mode === "none"){ // console.log("送信"); timelapseFlag = true; // } diff --git a/views/client.ejs b/views/client.ejs index 4717028..d0cb6c2 100644 --- a/views/client.ejs +++ b/views/client.ejs @@ -7,6 +7,7 @@ +
@@ -19,7 +20,7 @@ var buffer = document.createElement('canvas'); var client = "<%= title %>"; var mode = "none"; //"osc" or "feedback" or "whitenoise" - var videoMode = "none"; //"record" or "playback" + var videoMode = {"mode": "none", "option": "none"}; //"record" or "playback" var timelapseMode = false; var strings = ""; var serverFlag = false; diff --git a/webpack.config.js b/webpack.config.js old mode 100644 new mode 100755 index e5aaea6..676891e --- a/webpack.config.js +++ b/webpack.config.js @@ -16,8 +16,7 @@ module.exports = { // メインとなるJavaScriptファイル(エントリーポイント) entry: { client: './src/client.js', - ctrl: './src/ctrl.js', - ios: './src/ios.js' + ctrl: './src/ctrl.js' } , // entry: scripts, // ファイルの出力設定