Web MIDI API を使用して MIDI キーボードにアクセス
Web MIDI API を使うと、ブラウザから、現在 Mac / PC に接続されている MIDI デバイスにアクセスすることができます。さらにそのデバイスから MIDI メッセージを受け取った際に、どんなことをするかというハンドラを定義することができます。
これを使って、MIDI キーボードから MIDI メッセージが送られて来た時に、ここまでで作った synth インスタンスへ値を送って演奏すればいいわけです。
注意してほしいポイントが一つあって、Codesandbox のエディター画面からは Web MIDI API を実行するとエラーが出てしまいます。Open In New Window を押して全画面モードにしてください。そこでは正常に Web MIDI API を実行することができます。
以下のソースが完成系です。(getMIDIInputDevicesgetMIDIMessage はこれから作っていきます。) 流れとしては以下のようになります。
    synth インスタンスを作成する。
    getMIDIInputDevices でブラウザから、Mac / PC に接続されている MIDI デバイスを全て取得する。
    MIDI デバイスが MIDI メッセージを受け取った際に実行するハンドラを定義する(o.onmidimessage = getMIDIMessage(synth)))
    getMIDIMessage(synth) は高階関数、つまり関数を返す関数になっている。引数として synth インスタンスを渡すことで、そのシンセを実行するハンドラを登録できる。
index.js
1
import Synth from '/src/Synth'
2
import createAudioContext from '/src/WebAudioAPI/createAudioContext'
3
import getMIDIInputDevices from '/src/MIDI/getMIDIInputDevices'
4
import getMIDIMessage from '/src/MIDI/getMIDIMessage'
5
6
const audioContext = createAudioContext()
7
const destination = audioContext.destination
8
9
// synth インスタンスを作成
10
const synth = new Synth({
11
audioContext,
12
nextNode: destination,
13
})
14
15
// MIDI device にアクセスして、
16
// MIDI message を受け取った際に起動させるハンドラを登録する
17
const start = async () => {
18
// MIDI デバイスを取得する
19
const MidiInputDevices = await getMIDIInputDevices()
20
console.log({ MidiInputDevices })
21
if (MidiInputDevices) {
22
// 全ての MIDI デバイスへ
23
// MIDI メッセージを受け取った際に起動するハンドラを付与する
24
// getMIDIMessage がハンドラ
25
// ハンドラで使用する synth インスタンスを渡す
26
MidiInputDevices.forEach(o => (o.onmidimessage = getMIDIMessage(synth)))
27
}
28
}
29
30
start()
31
Copied!

getMIDIInputDevices

getMIDIInputDevices.js
1
const getMIDIInputDevices = async () => {
2
try {
3
// MIDI デバイスにアクセスする
4
const access = await navigator.requestMIDIAccess({
5
sysex: false,
6
})
7
// acess.inputs(と outputs).values にデバイス一覧があるが
8
// イテレータオブジェクトなので扱いにくい
9
// そこで array に変換する
10
const MidiInputDevices = Array.from(access.inputs.values())
11
const MidiOutputDevice = Array.from(access.outputs.values())
12
13
console.log(
14
'midiIn and midiOut devices',
15
MidiInputDevices,
16
MidiOutputDevice
17
)
18
19
// 今回は inputs しか使わないので、これを返す
20
return MidiInputDevices
21
} catch (error) {
22
console.error('[ERROR] requestMIDIAccess()', error)
23
24
return false
25
}
26
}
27
28
export default getMIDIInputDevices
29
Copied!
コードはシンプルで、MIDI デバイスにアクセスして input 用の部分だけを取り出して返す関数です。ポイントは以下です。
    async / await を使用してrequestMIDIAccess をしている。このメソッドは promise ベースで動いているので async / await を使って可動性をあげました。こちらの方がいいでしょう。
    access.inputs.values() と access.outputs.values() の値はイテーレーターオブジェクトで、扱いが面倒なので Array.from() を使って配列に変換しています。
    最後に MidiInputDevices を返します。これは今アクセスできる MIDI デバイスを扱うためのものが全て入った配列です。
さて次は、返した MidiInputDevices を使って、MIDI メッセージを受け取った時の処理を追加します。
Last modified 3yr ago
Copy link