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
|
import WebMidi from 'webmidi'
import { params } from './jx8p'
let output;
let channel = 1
function init(){
build()
bind()
WebMidi.enable(ready)
}
function ready(err) {
if (err) {
console.error('webmidi failed to initialize')
return
}
if (!WebMidi.outputs.length) {
console.error('no MIDI output found')
}
console.log(WebMidi.inputs)
console.log(WebMidi.outputs)
output = WebMidi.outputs[0]
}
function build(){
const section_template = document.querySelector('#section_template').innerHTML
const checkbox_template = document.querySelector('#checkbox_template').innerHTML
const range_template = document.querySelector('#range_template').innerHTML
const enum_template = document.querySelector('#enum_template').innerHTML
const params_by_tag = params.reduce((a,b,i) => {
const tag = b.tag || b.name.split(' ')[0]
b.index = i
if (a[tag]) {
a[tag].push(b)
} else {
a[tag] = [b]
}
return a
}, {})
Object.keys(params_by_tag).map(tag => {
const els = params_by_tag[tag].map(param => {
let t, options;
switch (param.type) {
case 'checkbox':
t = checkbox_template.replace(/{name}/, param.name)
.replace(/{param_name}/, param.name.replace(/ /g, '_'))
.replace(/{index}/, param.index)
break
case 'range':
t = range_template.replace(/{name}/, param.name)
.replace(/{param_name}/, param.name.replace(/ /g, '_'))
.replace(/{index}/, param.index)
.replace(/{min}/, param.range[0])
.replace(/{max}/, param.range[1])
.replace(/{value}/, Math.floor((param.range[1] - param.range[0]) / 2))
break
case 'enum':
options = param.values.map(a => '<option value="' + a[0] + '">' + a[1] + '</option>')
t = enum_template.replace(/{name}/, param.name)
.replace(/{param_name}/, param.name.replace(/ /g, '_'))
.replace(/{index}/, param.index)
.replace(/{options}/, options)
.replace(/{value}/, param.values[0][0])
break
default:
console.log('unknown type', param)
t = ""
break
}
return t
}).filter(t => !!t)
let t = section_template.replace(/{name}/, tag).replace(/{els}/, els.join(''))
document.querySelector('#params').innerHTML += t
})
}
function bind(){
toArray(document.querySelectorAll('#params input[type=range]')).forEach(el => {
const index = el.dataset.index
const param = params[index]
el.addEventListener('input', () => {
update_param(param, el.value)
})
})
toArray(document.querySelectorAll('#params input[type=checkbox]')).forEach(el => {
const index = el.dataset.index
const param = params[index]
el.addEventListener('input', () => {
const isChecked = el.checked
const value = isChecked ? param.on : param.off
update_param(param, value)
})
})
toArray(document.querySelectorAll('#params select')).forEach(el => {
const index = el.dataset.index
const param = params[index]
el.addEventListener('input', () => {
update_param(param, el.value)
})
})
document.querySelector('#randomize').addEventListener('click', randomize)
}
function update_param(param, value){
if (param.fourteen) {
const msb = value >> 7
const lsb = value & 127
output.sendControlChange(param.fourteen[0], msb, channel)
output.sendControlChange(param.fourteen[1], lsb, channel)
} else {
output.sendControlChange(param.cc, value, channel)
}
}
function randint(n) {
return Math.floor(Math.random() * n)
}
function randomize(){
params.forEach(param => {
let value
if (param.randomize === false) return
if (param.type === 'range') {
value = randint(param.range[1])
update_param(param, value)
document.querySelector("input[name=" + param.name.replace(/ /g, '_') + "]").value = value
}
})
}
function toArray(a){
return Reflect.apply(Array.prototype.slice, a, [])
}
init()
|