Open3

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

NoboNoboNoboNobo

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ブラウザですー。

NoboNoboNoboNobo

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

NoboNoboNoboNobo
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入れたら割り込みハンドラが死んだ。