https://www.youtube.com/watch?v=ns0lo12Lavw
実行ファイルは概要欄にて
var key = {
//白鍵キー設定
C3:'1',D3:'2',E3:'3',F3:'4',G3:'5',A3:'6',B3:'7',
C4:'8',D4:'9',E4:'0',F4:'-',G4:'=',A4:'Backspace',B4:'Delete',C5:'Escape',
//黒鍵キー設定
'C#3':'Shift+1',
'D#3':'Shift+2',
'F#3':'Shift+3',
'G#3':'Shift+4',
'A#3':'Shift+5',
'C#4':'Shift+6',
'D#4':'Shift+7',
'F#4':'Shift+8',
'G#4':'Shift+9',
'A#4':'Shift+0',
}
//Keys 列挙型
//https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.forms.keys
//http://liliumrubellum.blog10.fc2.com/blog-entry-278.html
var WindowsKeys = {
'`':'Oemtilde','-':'OemMinus','=':'Oemplus',Backspace:'Back',
1:'D1',2:'D2',3:'D3',4:'D4',5:'D5',6:'D6',7:'D7',8:'D8',9:'D9',0:'D0',
'[':'OemOpenBrackets',']':'OemCloseBrackets','\\':'OemPipe',
';':'OemSemicolon',"'":'OemQuotes',
Shift:'ShiftKey',',':'Oemcomma','.':'OemPeriod','/':'OemQuestion',
Control:'ControlKey',
NUM0:'NumPad0',NUM1:'NumPad1',NUM2:'NumPad2',NUM3:'NumPad3',NUM4:'NumPad4',
NUM5:'NumPad5',NUM6:'NumPad6',NUM7:'NumPad7',NUM8:'NumPad8',NUM9:'NumPad9',
Esc:'Escape',Ctrl:'ControlKey',//FF14表記
}
addEventListener('WebBridgeLoaded',e=>{
_exe = e.detail
//_exe.openDeveloperTools()
console.log(_exe)
function input(type,a){
var s = a.shift()
_exe.dispatch({type:type,key:WindowsKeys[s]||s})
if(a.length>0) var id = setInterval(e=>{
if(a.length>0){
var s = a.shift()
_exe.dispatch({type:type,key:WindowsKeys[s]||s})
}else{
clearInterval(id)
}
},10)
}
var listener = {
NoteOn : a=>input('keydown',a),
NoteOff : a=>input('keyup',a.reverse()),
}
new MIDIKeyboard().message(e=>{
var k = key[e.key]
var s = e.key.replace('#','Sharp')
if(k) listener[e.type](k.split('+'))
if(e.type=='NoteOn'){
$('#MIDI').append($('<li>').addClass(s).append(
`${e.name} ${e.key} = ${k||'none'}`
))
}else{
$('#MIDI li.'+s).remove()
}
}).status(e=>{
$('#MIDI').append($('<li>').append(e.type+': '+e.name))
})
$('body').append($('<ul id="MIDI">'))
})
class MIDIKeyboard{
constructor(){
this.notes = 'C,C#,D,D#,E,F,F#,G,G#,A,A#,B'.split(',')
this.type = {0x80:'NoteOff',0x90:'NoteOn'}
this.status(e=>{}).message(e=>{})
navigator.requestMIDIAccess().then(r=>{
r.inputs.forEach(v=>{
this.onstatus({type:v.state,name:`${v.name} / ${v.manufacturer}`})
this.initInput(v)
})
},console.log)
}
status(f){ this.onstatus = f;return this}
message(f){ this.onmessage = f;return this}
initInput(v){
v.onmidimessage = e=>{
if(this.type[e.data[0]]){
var [type,noteNumber,velocity] = e.data
var n = this.notes[noteNumber%12]
var o = Math.floor(noteNumber/12)-1
this.onmessage({
type : this.type[type],
key : n+o,
keyCode : noteNumber,
note : n,
octave : o,
name : v.name,
})
}
}
}
}