我有一个方法可以很好地处理传入的MIDI消息。
它在所有输入设备上监听,而不仅仅是在第一个输入设备上监听。
我想使用RxJS observables编写它。
这是有效的(非RxJS可观察的)之一:
public initMidiInputBis() {
if (navigator.requestMIDIAccess) {
console.log('This browser supports MIDI');
navigator.requestMIDIAccess().then(
(midiAccess: WebMidi.MIDIAccess) => this.onMIDISuccess(midiAccess),
(midiAccess: WebMidi.MIDIAccess) => this.onMIDIFailure(midiAccess)
);
} else {
console.log('This browser does not support MIDI');
}
}
private onMIDISuccess(midiAccess: WebMidi.MIDIAccess) {
for (const inputDevice of Array.from(midiAccess.inputs)) {
inputDevice[1].onmidimessage = (message: WebMidi.MIDIMessageEvent) => this.onMIDIMessage(message);
}
}
private onMIDIFailure(error: any) {
console.log('The browser could not access any MIDI device');
console.log(error);
}
以上方法工作正常,VMPK虚拟键盘被视为输入MIDI设备,并且已收到其MIDI消息。
这是我尝试使用可观察对象再次编写它:
public initMidiInput() {
if (navigator.requestMIDIAccess) {
console.log('This browser supports MIDI');
const midiAccess$: Observable<WebMidi.MIDIAccess> = from(navigator.requestMIDIAccess());
const midiInput$: Observable<WebMidi.MIDIInput> = midiAccess$.pipe(
map((midiAccess: WebMidi.MIDIAccess) => {
return midiAccess.inputs.values().next().value;
})
);
midiInput$.pipe(
flatMap((midiInput: WebMidi.MIDIInput) => this.midiMessageAsObservable(midiInput)),
).subscribe((message: WebMidi.MIDIMessageEvent) => {
this.onMIDIMessage(message);
});
midiAccess$.subscribe(midiAccess => {
this.logOutputDevices(midiAccess);
});
} else {
console.log('This browser does not support MIDI');
}
}
使用上述方法,VMPK虚拟键盘不会被视为输入MIDI设备。
此方法包含下面的代码行midiAccess.inputs.values().next().value;
,该行仅检索第一个输入MIDI设备。
如何考虑所有输入MIDI设备?
更新:添加一些记录器后,我可以看到VMPK
虚拟键盘被列为输入设备:
MIDIInput {onmidimessage: null, connection: "closed", id: "2A23249CBCD506F53AE4731A4FE186844C42191D517EC71DFC9813E84A1D2F87", manufacturer: "", name: "VMPK Output", …}
connection: "closed"
id: "2A23249CBCD506F53AE4731A4FE186844C42191D517EC71DFC9813E84A1D2F87"
manufacturer: ""
name: "VMPK Output"
onmidimessage: null
onstatechange: null
state: "connected"
type: "input"
version: "ALSA library version 1.1.6"
我感到困惑的是,在连接状态时其连接已关闭。
这是我记录以上输出的方式:
const midiAccess$: Observable<WebMidi.MIDIAccess> = from(navigator.requestMIDIAccess());
const midiInput$: Observable<WebMidi.MIDIInput> = midiAccess$.pipe(
map((midiAccess: WebMidi.MIDIAccess) => {
Array.from(midiAccess.inputs.entries()).forEach(entry => {
console.log('Key: ' + entry[0]);
console.log(entry[1]);
});
return midiAccess.inputs.values().next().value;
})
);
答案 0 :(得分:1)
我可以使用以下方法解决该问题:
public initMidiInput() {
if (navigator.requestMIDIAccess) {
console.log('This browser supports MIDI');
const midiAccess$: Observable<WebMidi.MIDIAccess> = from(navigator.requestMIDIAccess());
midiAccess$.pipe(
flatMap((midiAccess: WebMidi.MIDIAccess) => {
return midiAccess.inputs;
}),
map((midiInput) => {
return midiInput[1];
}),
filter((midiInput: WebMidi.MIDIInput) => midiInput !== undefined),
flatMap((midiInput: WebMidi.MIDIInput) => this.midiMessageAsObservable(midiInput)),
).subscribe((message: WebMidi.MIDIMessageEvent) => {
this.onMIDIMessage(message);
});
midiAccess$.subscribe(midiAccess => {
this.logOutputDevices(midiAccess);
});
} else {
console.log('This browser does not support MIDI');
}
}
private midiMessageAsObservable(inputDevice: WebMidi.MIDIInput): Observable<WebMidi.MIDIMessageEvent> {
const source: Subject<WebMidi.MIDIMessageEvent> = new Subject<WebMidi.MIDIMessageEvent>();
inputDevice.onmidimessage = (note: WebMidi.MIDIMessageEvent) => source.next(note);
return source.asObservable();
}
我不得不删除对.next()
方法的调用,并返回地图的值。
答案 1 :(得分:0)
尝试一下。
import { of, from, throwError } from 'rxjs';
import { map, switchMap, catchError } from 'rxjs/operators';
public initMidiInput() {
if (navigator.requestMIDIAccess) {
console.log('This browser supports MIDI');
of(navigator.requestMIDIAccess())
.pipe(
map((midiAccess: WebMidi.MIDIAccess) => midiAccess.inputs),
switchMap((inputs) => from(inputs)),
catchError(error => {
return throwError(error);
})
)
.subscribe(inputDevice => {
inputDevice[1].onmidimessage = (message: WebMidi.MIDIMessageEvent) => this.onMIDIMessage(message);
}, error => {
console.log('The browser could not access any MIDI device');
console.log(error);
});
}
}