web midi api
MIDIAccessについて
まず、flagsからWebMIDIAPIを有効にし、browserを再起動します。
次に、サーバーサイドや非対応の対策nativeRma
を用意します。
const options = { sysex: true, software: true }
const supported =
typeof navigator !== 'undefined' && // @ts-ignore
typeof navigator.requestMIDIAccess === 'function'
const nativeRma = () => {
if (!supported) console.warn('Cannot supported Web MIDI API') // @ts-ignore
else return navigator.requestMIDIAccess(options)
}
次のようにするとIllegal invocation
エラーが起きます。
(ネイティブのコードなので、他に代入できません。)
nativeRma = navigator.requestMMIDIAccess
// TypeError: Failed to execute 'requestMIDIAccess' on 'Navigator': Illegal invocation
Promiseで取得できるMIDIAccessから、各MIDIPortを操作できます。
const change = (access: MIDIAccess) => {}
const error = console.error
nativeRma()?.then(change, error)
onstatechangeについて
change内でMIDIAccess.onstatechange
を指定すると、
port
が変化するごとに実行してくれます。
onstatechange
はMIDIPort
からも指定できます。
MIDIAccess {
onstatechange: (e: MIDIConnectionEvent) => void
inputs: maplike <DOMString, MIDIInput>;
outputs: maplike <DOMString, MIDIInput>;
sysexEnabled: boolean
}
MIDIPort {
onstatechange: (e: MIDIConnectionEvent) => void
Promise<MIDIPort> open
Promize<MIDIPort> close
}
maplikeなので、clear(), delete(), set()
が使用できません。
maplikeのkey名が長く、get(), has()
も使いにくいです。
ですので、size, keys(), values(), entries(), forEach()
を主に使います。
onmidimessage, sendについて
MIDIInput.onmidimessage
からデータを受け取り、MIDIOutput.send
からデータを送信します。
両方ともMIDIPort
を継承しているため、onstatechange
を指定することもできます。
MIDIInput extends MIDIPort {
onmidimessage: (e: MIDIMessageEvent) => void
}
MIDIOutput extends MIDIPort {
send (data, timestamp) => void
clear () => void
}
Eventについて
onstatechange
の引数のMIDIConnectionEvent
と,
onmidimessage
の引数のMIDIMessageEvent
は
Event
から継承されているので、
addEventListenner
で関数を登録したり
timeStamp
で時間を計測したりできます。
interface MIDIConnectionEvent extends Event {
target: MIDIAccess
port: MIDIPort
}
interface MIDIMessageEvent extends Event {
data: Unit8Array
}