Open3
TinyGoでmidiデバイスを動かすメモ

MIDIデバイスをPICOで作ってみたところ。
サンプルコード
package main
import (
"fmt"
"machine"
"machine/usb/midi"
"time"
)
// Try it easily by opening the following site in Chrome.
// https://www.onlinemusictools.com/kb/
func main() {
led := machine.LED
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
m := midi.New()
m.SetHandler(func(b []byte) {
led.Set(!led.Get())
fmt.Printf("% X\r\n", b)
})
chords := []struct {
name string
keys []midi.Note
}{
{name: "C ", keys: []midi.Note{midi.C4, midi.E4, midi.G4}},
{name: "G ", keys: []midi.Note{midi.G3, midi.B3, midi.D4}},
{name: "Am", keys: []midi.Note{midi.A3, midi.C4, midi.E4}},
{name: "F ", keys: []midi.Note{midi.F3, midi.A3, midi.C4}},
}
index := 0
current := false
for {
current = !current
if current {
for _, c := range chords[index].keys {
m.NoteOff(0, 0, c, 0x40)
}
index = (index + 1) % len(chords)
} else {
for _, c := range chords[index].keys {
m.NoteOn(0, 0, c, 0x40)
}
}
time.Sleep(500 * time.Millisecond)
}
}
このサイトで試す: https://webmidi-examples.glitch.me/
このフォームからMIDIメッセージをデバイスに送ったところ。パケットの送信はされている。
しかし、受け取り側のログはちゃんと出ず、以降受信できなくなってしまう。
Webブラウザの側のタブがタイムアウトしたのちクラッシュする。
環境はWindows11+Edgeブラウザですー。

おそらくNote-offがパケットキャプチャに出てこないんだけどこのあたりでエンドポイントの送受信が固まってしまっているような挙動です。

package main
import (
"fmt"
"machine"
"machine/usb/midi"
"time"
)
// Try it easily by opening the following site in Chrome.
// https://www.onlinemusictools.com/kb/
func main() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
led := machine.LED
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
ch := make(chan []byte, 64)
m := midi.New()
m.SetHandler(func(b []byte) {
ch <- b //fmt.Printf("%X\r\n", b)
})
chords := []struct {
name string
keys []midi.Note
}{
{name: "C ", keys: []midi.Note{midi.C4, midi.E4, midi.G4}},
{name: "G ", keys: []midi.Note{midi.G3, midi.B3, midi.D4}},
{name: "Am", keys: []midi.Note{midi.A3, midi.C4, midi.E4}},
{name: "F ", keys: []midi.Note{midi.F3, midi.A3, midi.C4}},
}
fmt.Printf("%v\n", chords)
index := 0
current := false
tick := time.NewTicker(500 * time.Millisecond)
for {
select {
case v := <-ch:
fmt.Printf("%X\n", v)
case <-tick.C:
current = !current
if current {
for _, c := range chords[index].keys {
m.NoteOff(0, 0, c, 0x40)
}
index = (index + 1) % len(chords)
} else {
for _, c := range chords[index].keys {
m.NoteOn(0, 0, c, 0x40)
}
}
}
}
}
CDC(fmt.PrintX)を受信ハンドラで使わないようにしたら安定した?
出力してなくてもCDCがらみの問い合わせ自体はある。頻度は低くなるけど止まる可能性はある?
これらの競合を避けようとMutex入れたら割り込みハンドラが死んだ。