Golang与MIDI编程指南:从入门到实战
Golang与MIDI编程指南:从入门到实战 是否有人成功编写过一个简单的Go语言应用程序,能够在macOS上读取MIDI文件(最好是MIDI鼓文件)并播放它?我知道有gomidi/midi这个包,但似乎没有关于实际执行读取和播放MIDI文件这种看似显而易见操作的有用示例。
这个想法是为了找到一种简单的方法,从命令行或Finder预览鼓MIDI文件,因为macOS中用于MIDI文件的快速查看功能已被移除(我相信是从v10.8开始被弃用)。
嗨,马克,
感谢你的回复。我之前真是走投无路了,甚至都在考虑Python的解决方案!你能想象吗?我一定会去看看那个新包的,不过得等到明天了。冰箱里有些啤酒在等着我,它们可不会自己喝掉 ;)
干杯, 卡尔
更多关于Golang与MIDI编程指南:从入门到实战的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你好,马克。
感谢你的回复!我目前有点忙,但我一定会查看你新增的内容。如果我有任何问题,我一定会使用问题跟踪器!
祝好,
卡尔
你好 Carl,
我是 https://gitlab.com/gomidi/midi 的作者,偶然看到了你的消息(对于问题或请求,使用 issue 跟踪器会更好)。
我写了一个新的包 gitlab.com/gomidi/midi/player 来简化 SMF/MIDI 文件的播放。
请看一下——在 gitlab.com/gomidi/midi/player/example/smfplayer 中还有一个简单的 CLI 播放器作为示例。
谢谢!
是的,可以使用Go在macOS上读取和播放MIDI文件。以下是一个完整的示例,使用gomidi/midi包读取MIDI文件并通过CoreAudio播放:
package main
import (
"fmt"
"os"
"time"
"gitlab.com/gomidi/midi"
"gitlab.com/gomidi/midi/reader"
"gitlab.com/gomidi/midi/writer"
_ "gitlab.com/gomidi/midi/drivers/portmididrv" // macOS音频驱动
)
func main() {
// 打开MIDI文件
file, err := os.Open("drums.mid")
if err != nil {
panic(err)
}
defer file.Close()
// 创建MIDI读取器
rd := reader.New(
reader.NoLogger(),
reader.Each(func(pos *reader.Position, msg midi.Message) {
// 处理MIDI消息
handleMIDIMessage(msg)
}),
)
// 读取并播放MIDI文件
err = reader.ReadSMFFile(rd, file)
if err != nil {
panic(err)
}
}
func handleMIDIMessage(msg midi.Message) {
// 打开MIDI输出端口
out, err := midi.FindOutPort("IAC Driver Bus 1") // macOS IAC驱动
if err != nil {
// 如果没有IAC驱动,使用虚拟端口
out, err = midi.NewOut("Virtual MIDI Port", 0)
if err != nil {
panic(err)
}
}
defer out.Close()
// 创建写入器
wr := writer.New(out)
// 发送MIDI消息
writer.Write(wr, msg)
// 根据MIDI消息类型处理时序
switch v := msg.(type) {
case midi.NoteOn:
fmt.Printf("NoteOn: Channel=%d Key=%d Velocity=%d\n",
v.Channel(), v.Key(), v.Velocity())
time.Sleep(time.Duration(v.Duration()) * time.Millisecond)
case midi.NoteOff:
fmt.Printf("NoteOff: Channel=%d Key=%d\n",
v.Channel(), v.Key())
}
}
对于更简单的命令行播放器,这里有一个使用portmidi驱动的版本:
package main
import (
"flag"
"log"
"os"
"gitlab.com/gomidi/midi"
"gitlab.com/gomidi/midi/reader"
"gitlab.com/gomidi/midi/smf"
"gitlab.com/gomidi/portmididrv"
)
func main() {
// 解析命令行参数
filePath := flag.String("file", "", "MIDI file path")
flag.Parse()
if *filePath == "" {
log.Fatal("请指定MIDI文件路径: -file <path>")
}
// 初始化portmidi驱动
drv, err := portmididrv.New()
if err != nil {
log.Fatal(err)
}
defer drv.Close()
// 打开默认MIDI输出
out, err := drv.OpenOut(0)
if err != nil {
log.Fatal(err)
}
defer out.Close()
// 打开MIDI文件
file, err := os.Open(*filePath)
if err != nil {
log.Fatal(err)
}
defer file.Close()
// 读取SMF文件
smfReader := smf.NewReader(file)
smf, err := smfReader.Read()
if err != nil {
log.Fatal(err)
}
// 创建播放器
play := reader.New(
reader.NoLogger(),
reader.Writer(out),
reader.SMF(smf),
reader.TicksPerQuarterNote(smf.TimeFormat.(smf.MetricTicks).Ticks4th()),
)
// 播放MIDI
err = play.Read()
if err != nil {
log.Fatal(err)
}
log.Println("播放完成")
}
安装依赖:
go get gitlab.com/gomidi/midi
go get gitlab.com/gomidi/portmididrv
运行:
go run player.go -file drums.mid
这个实现可以读取标准的MIDI鼓文件,并通过macOS的音频系统播放。对于鼓文件,需要注意MIDI通道10通常用于打击乐(根据GM标准)。

