1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
define.class('$system/base/midi', function (require, exports){
exports.midiAttributes = {
message:Config({type:Event}),
noteoff:Config({type:Event}),
noteon:Config({type:Event}),
polypressure:Config({type:Event}),
controlchange:Config({type:Event}),
programchange:Config({type:Event}),
aftertouch:Config({type:Event}),
pitchbend:Config({type:Event})
}
this.Input = define.class(function midiInput($system$base$node){
this.atMidiData = function(data){
var ch = data[0] & 16
var hi = data[0] >> 4
if(hi === 0x8) return this.noteoff = this.message = {ch:ch, type:'noteoff', key:data[1], value:data[2]}
if(hi === 0x9) return this.noteon = this.message = {ch:ch, type:'noteon', key:data[1], value:data[2]}
if(hi === 0xa) return this.polypressure = this.message = {ch:ch, type:'polypressure', key:data[1], value:data[2]}
if(hi === 0xb) return this.controlchange = this.message = {ch:ch, type:'controlchange', ctrl:data[1], value:data[2]}
if(hi === 0xc) return this.programchange = this.message = {ch:ch, type:'programchange', value:data[1]}
if(hi === 0xd) return this.aftertouch = this.message = {ch:ch, type:'aftertouch', value:data[1]}
if(hi === 0xe) return this.pitchbend = this.message = {ch:ch, type:'pitchbend', value:(data[2]<<7) + data[1]}
}
this.attributes = exports.midiAttributes
})
this.Output = define.class(function midiOutput($system$base$node){
this.atConstructor = function(send){
this.send = send
}
this.attributes = exports.midiAttributes
this.alloff = function(ch){
if(!ch) ch = 0
this.send([0xb<<4|ch, 121, 0])
this.send([0xb<<4|ch, 120, 0])
}
for(var key in exports.midiAttributes){
this[key] = function(event){
var ev = event.value
ev.type = event.key
this.message = ev
}
}
this.message = function(event){
var m = event.value
var ch = m.ch || 0
if(m.type === 'noteoff')return this.send([0x8<<4|ch, m.key, m.value])
if(m.type === 'noteon')return this.send([0x9<<4|ch, m.key, m.value])
if(m.type === 'polypressure')return this.send([0xa<<4|ch, m.key, m.value])
if(m.type === 'controlchange')return this.send([0xb<<4|ch, m.ctrl, m.value])
if(m.type === 'programchange')return this.send([0xc<<4|ch, m.value])
if(m.type === 'aftertouch') return this.send([0xd<<4|ch, m.value])
if(m.type === 'pitchbend')return this.send([0xe<<4|ch, m.value&127, m.value>>7])
}
})
function iterIO(slot, id, cb){
return new Promise(function(resolve, reject){
navigator.requestMIDIAccess().then(function(result){
var i =0
for(var item of result[slot]){
if(typeof id === 'number' && id === i ||
typeof id === 'string' && item[1].name === id ||
typeof id === 'object' && id.match && item[1].name.match(id)){
return resolve(cb(item[1]))
}
i++
}
})
})
}
this.openInput = function(id){
return iterIO('inputs', id, function(input){
var inp = new this.Input()
inp._midi_ = input
inp.close = function(){
this._midi_.close()
}
input.onmidimessage = function(message){
inp.atMidiData(message.data)
}
return inp
}.bind(this))
}
this.openOutput = function(id){
return iterIO('outputs', id, function(output){
var out = this.Output(function(buf){
output.send(buf)
})
out._midi_ = output
out.close = function(){
this._midi_.close()
}
return out
}.bind(this))
}
this.getIO = function(){
return new Promise(function(resolve, reject){
navigator.requestMIDIAccess().then(function(result){
var res = {inputs:[], outputs:[]}
for(var item of result.inputs) res.inputs.push(item[1].name)
for(var item of result.outputs) res.outputs.push(item[1].name)
resolve(res)
})
})
}
this.atConstructor = function(){
}
})
|