您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
chin-chin
// ==UserScript== // @name epiano // @namespace https://epiano.jp/ // @version 0.5 // @description // @match https://epiano.jp/sp/* // @grant none // @run-at document-start // @noframes // @description chin-chin // ==/UserScript== window.MIDIACCESS_BACK = navigator.requestMIDIAccess; navigator.requestMIDIAccess = null; function releaseBufferA(key, uid) { const id = uid + key; if (id in playings) { for (i in playings[id]) { const ar = playings[id][i]; const time = window.context.currentTime; const source = ar[0] const gain = ar[1]; gain.setValueAtTime(gain.value, time); gain.linearRampToValueAtTime(gain.value * 0.1, time + 0.16); gain.linearRampToValueAtTime(0.0, time + 0.4); source.stop(time + 0.41); } delete playings[id]; } } function playBufferA(key,vol,uid){ if(vol == undefined){ vol = DEFAULT_VELOCITY; } if(key in buffers){ const source = window.context.createBufferSource(); source.buffer = buffers[key]; const gainNode = window.context.createGain(); gainNode.connect(window.context.destination); gainNode.gain.value = vol * ($(".volume").get(0).value); source.connect(gainNode); source.start(0); if(!playings[uid+key]){ playings[uid+key] = []; } playings[uid+key].push([source,gainNode.gain]); } } function ease(t, totalTime, min, max) { max -= min; t = t / totalTime; if (t < 0.43) { return max * (t / 2.3) + min; } return max * t * t + min; } function releaseSustainA() { window.gSustain = false; for (const msg of window.PENDING_MIDI_MESSAGES) { releaseA(msg); } window.PENDING_MIDI_MESSAGES.clear(); } function pressA(id, vol) { const newVol = ease(vol, 1.5, 0.0, 2.0) * 3.0; if (window.PENDING_MIDI_MESSAGES.has(id)) { releaseBufferA(id, loginInfo.myID); if (!$("#disconnect").is(":checked")) { socket.emit('r', id); } window.PENDING_MIDI_MESSAGES.delete(id) } playPianoA(window.MIDI_KEY_NAMES[id - 21], loginInfo.myID, newVol); if (!window.DISCONNECT.is(":checked")) { socket.emit('p', window.MIDI_KEY_NAMES[id - 21], newVol); } } function releaseA(id) { if (window.gSustain) { window.PENDING_MIDI_MESSAGES.add(id); } else { releaseBufferA(window.MIDI_KEY_NAMES[id - 21], loginInfo.myID); if (!window.DISCONNECT.is(":checked")) { socket.emit('r', window.MIDI_KEY_NAMES[id - 21]); } } } function playPianoA(id, uid, vol) { if (ignoreList[uid]) { return; } var newVol = vol; if (newVol > 2.0 || newVol < -1) { newVol = 2.0; ignoreList[uid] = 1 } playBufferA(id, newVol, uid); const pikaColor = uid == loginInfo.myID ? "#00FF00" : "#FF0000"; if(!window.DISCONNECT.is(":checked")){ $("[uid="+uid+"]").css("backgroundColor", pikaColor) .stop(true) .show() .animate({ top: "5px" }, 100).animate({ top: "0px" }, 100) } setTimeout(function(){ $("[uid="+uid+"]").css("backgroundColor","") },200); //鍵盤の動作発動 if (id in pianoKeyObj) { pianoKeyObj[id].dispatchEvent(uid == loginInfo.myID ? "mousedownSelf" : "mousedownOther"); } } function updateList(list) { var htmls = new Array(); $(list).each(function (i) { var uid = list[i]; var isIgnore = ignoreList[uid] ? "class='ignore' style='text-decoration:line-through;background:#999'" : ""; htmls.push("<span class=user " + isIgnore + " uid=" + uid + ">" + uid + "</span>"); }); $("#users").html(htmls.join("")); $("#onlineNumber").html(htmls.length); } window.addEventListener('load', function () { // ペダル用 解放待機中のMIDIメッセージ if (window.PENDING_MIDI_MESSAGES == undefined) { window.PENDING_MIDI_MESSAGES = new Set(); } window.gSustain = false; window.DISCONNECT = $("#disconnect"); $(document).off("pressSustain"); $(document).off("releaseSustain"); socket.off('p'); socket.off('r'); //弾く socket.on('p',function(id,uid,vol){ if(!window.DISCONNECT.is(":checked")){ playPianoA(id,uid,vol); } }); //離す socket.on('r',function(id,uid){ if(!window.DISCONNECT.is(":checked")){ releaseBufferA(id,uid); } }); navigator.requestMIDIAccess = window.MIDIACCESS_BACK; (function () { window.MIDI_KEY_NAMES = ["a-1", "as-1", "b-1"]; var bare_notes = "c cs d ds e f fs g gs a as b".split(" "); for (var oct = 0; oct < 7; oct++) { for (var i in bare_notes) { window.MIDI_KEY_NAMES.push(bare_notes[i] + oct); } } window.MIDI_KEY_NAMES.push("c7"); if (navigator.requestMIDIAccess) { $("#connectJava").hide(); navigator.requestMIDIAccess({sysex:false}).then( function (midi) { function midimessagehandler(evt) { switch(evt.data[0] & 0xf0) { // NOTE_ON case 0x90: pressA(evt.data[1], evt.data[2] / 127.0); return; // NOTE_OFF case 0x80: releaseA(evt.data[1]); return; case 0xB0: if (evt.data[1] == 64) { if (evt.data[2] > 0) { window.gSustain = true; } else { releaseSustainA(); } } return; } } function plug() { if (midi.inputs.size > 0) { var ul = document.createElement("ul"); var inputs = midi.inputs.values(); for (var input_it = inputs.next(); input_it && !input_it.done; input_it = inputs.next()) { var input = input_it.value; input.onmidimessage = midimessagehandler; console.log("input", input); var li = document.createElement("li"); li.textContent = input.name; ul.appendChild(li); } $("body").prop("midi", input.name) $("#alert").hide().html("MIDIデバイス:" + input.name).slideDown("fast", function () { if (timerId) { clearTimeout(timerId); } timerId = setTimeout(function () { $("#alert").slideUp("slow") }, 5000); }); new Notification({ title: "MIDI Inputs In Use", html: ul.innerHTML, duration: 4000 }); } if (gMidiOutTest && midi.outputs.size > 0) { var outputs = midi.outputs.values(); for (var output_it = outputs.next(); output_it && !output_it.done; output_it = outputs.next()) { var output = output_it.value; console.log("output", output); } gMidiOutTest = function (note_name, vel, delay_ms) { var note_number = MIDI_KEY_NAMES.indexOf(note_name); if (note_number == -1) return; note_number = note_number + 9 - MIDI_TRANSPOSE; var outputs = midi.outputs.values(); for (var output_it = outputs.next(); output_it && !output_it.done; output_it = outputs.next()) { var output = output_it.value; output.send([0x90, note_number, vel], window.performance.now() + delay_ms); } } } } midi.addEventListener("statechange", function (evt) { if (evt instanceof MIDIConnectionEvent) { plug(); } }); plug(); }, function (err) { console.log(err); }); } })(); addJS_Node(updateList); }) addJS_Node(releaseSustainA); addJS_Node(pressA); addJS_Node(releaseA); addJS_Node(playPianoA); addJS_Node(playBufferA); addJS_Node(releaseBufferA); addJS_Node(ease); function addJS_Node(text, s_URL, funcToRun, runOnLoad) { var D = document; var scriptNode = D.createElement('script'); if (runOnLoad) { scriptNode.addEventListener("load", runOnLoad, false); } scriptNode.type = "text/javascript"; if (text) scriptNode.textContent = text; if (s_URL) scriptNode.src = s_URL; if (funcToRun) scriptNode.textContent = '(' + funcToRun.toString() + ')()'; var targ = D.getElementsByTagName('head')[0] || D.body || D.documentElement; targ.appendChild(scriptNode); }