1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
package main
import (
"container/list"
"flag"
"fmt"
"os"
"time"
"gitlab.com/gomidi/midi"
"gitlab.com/gomidi/midi/mid"
"gitlab.com/gomidi/midi/midimessage"
"gitlab.com/gomidi/midi/smf"
"go.terinstock.com/midifi/pkg/ttymididrv"
)
var (
drv mid.Driver
midiSerial string
)
func init() {
flag.StringVar(&midiSerial, "com", "", "The serial port of the MIDI synth")
}
func main() {
flag.Parse()
drv = ttymididrv.New(midiSerial, 38400)
defer drv.Close()
outs, err := drv.Outs()
if err != nil {
fmt.Printf("err: %v\n", err)
os.Exit(-1)
}
out := outs[0]
err = out.Open()
if err != nil {
fmt.Printf("err: %v\n", err)
os.Exit(-1)
}
defer out.Close()
if flag.NArg() == 0 {
flag.Usage()
os.Exit(-1)
}
f, err := os.Open(flag.Arg(0))
if err != nil {
fmt.Println("unable to load SMF file")
os.Exit(-2)
}
defer f.Close()
fmt.Printf("file: %s\n", flag.Arg(0))
mf := mid.NewReader(mid.NoLogger())
mf.SMFHeader = func(header smf.Header) {
fmt.Printf("file format: %s\n", header.Format.String())
fmt.Printf("number of tracks: %d\n", header.NumTracks)
fmt.Printf("time format: %s\n", header.TimeFormat.String())
fmt.Println("===========")
}
events := &list.List{}
mf.Msg.Each = func(pos *mid.Position, msg midi.Message) {
addEvent(events, Event{track: pos.Track, abs: pos.AbsoluteTicks, msg: msg})
}
mf.ReadSMF(f)
w := mid.WriteTo(out)
var lastDur time.Duration
for event := events.Front(); event != nil; event = event.Next() {
dur := *mf.TimeAt(event.Value.(Event).abs)
if lastDur != dur {
<-time.After(dur - lastDur)
lastDur = dur
}
msg := event.Value.(Event).msg
if midimessage.IsLive(msg) {
fmt.Printf("%s\n", msg.String())
w.Write(msg)
}
}
}
type Event struct {
track int16
abs uint64
msg midi.Message
}
func addEvent(l *list.List, evt Event) {
if l.Front() == nil {
l.PushBack(evt)
return
}
for cur := l.Front(); cur != nil; cur = cur.Next() {
peek := cur.Next()
if peek == nil {
l.InsertAfter(evt, cur)
return
}
if peek.Value.(Event).abs >= evt.abs {
l.InsertAfter(evt, cur)
return
}
}
}
|