1
1
mirror of https://github.com/wader/fq.git synced 2024-11-29 23:27:12 +03:00
fq/format/midi/metaevents.go
2024-08-25 17:48:31 -07:00

435 lines
9.2 KiB
Go

package midi
import (
"fmt"
"github.com/wader/fq/pkg/decode"
"github.com/wader/fq/pkg/scalar"
)
type MetaEventType uint8
const (
TypeSequenceNumber MetaEventType = 0x00
TypeText MetaEventType = 0x01
TypeCopyright MetaEventType = 0x02
TypeTrackName MetaEventType = 0x03
TypeInstrumentName MetaEventType = 0x04
TypeLyric MetaEventType = 0x05
TypeMarker MetaEventType = 0x06
TypeCuePoint MetaEventType = 0x07
TypeProgramName MetaEventType = 0x08
TypeDeviceName MetaEventType = 0x09
TypeMIDIChannelPrefix MetaEventType = 0x20
TypeMIDIPort MetaEventType = 0x21
TypeTempo MetaEventType = 0x51
TypeSMPTEOffset MetaEventType = 0x54
TypeTimeSignature MetaEventType = 0x58
TypeKeySignature MetaEventType = 0x59
TypeEndOfTrack MetaEventType = 0x2f
TypeSequencerSpecificEvent MetaEventType = 0x7f
)
var metaevents = scalar.UintMapSymStr{
0xff00: "Sequence Number",
0xff01: "Text",
0xff02: "Copyright",
0xff03: "Track Name",
0xff04: "Instrument Name",
0xff05: "Lyric",
0xff06: "Marker",
0xff07: "Cue Point",
0xff08: "Program Name",
0xff09: "Device Name",
0xff20: "MIDI Channel Prefix",
0xff21: "MIDI Port",
0xff51: "Tempo",
0xff54: "SMPTE Offset",
0xff58: "Time Signature",
0xff59: "Key Signature",
0xff2f: "End Of Track",
0xff7f: "Sequencer Specific Event",
}
var framerates = scalar.UintMapSymUint{
0: 24,
1: 25,
2: 29,
3: 30,
}
func decodeMetaEvent(d *decode.D, event uint8, ctx *context) {
ctx.running = 0x00
ctx.casio = false
delta := func(d *decode.D) {
dt := d.FieldUintFn("delta", vlq)
d.FieldValueUint("tick", ctx.tick)
ctx.tick += dt
}
switch MetaEventType(event) {
case TypeSequenceNumber:
d.FieldStruct("SequenceNumber", func(d *decode.D) {
d.FieldStruct("time", delta)
d.FieldU16("event", metaevents)
decodeSequenceNumber(d)
})
case TypeText:
d.FieldStruct("Text", func(d *decode.D) {
d.FieldStruct("time", delta)
d.FieldU16("event", metaevents)
decodeText(d)
})
case TypeCopyright:
d.FieldStruct("Copyright", func(d *decode.D) {
d.FieldStruct("time", delta)
d.FieldU16("event", metaevents)
decodeCopyright(d)
})
case TypeTrackName:
d.FieldStruct("TrackName", func(d *decode.D) {
d.FieldStruct("time", delta)
d.FieldU16("event", metaevents)
decodeTrackName(d)
})
case TypeInstrumentName:
d.FieldStruct("InstrumentName", func(d *decode.D) {
d.FieldStruct("time", delta)
d.FieldU16("event", metaevents)
decodeInstrumentName(d)
})
case TypeLyric:
d.FieldStruct("Lyric", func(d *decode.D) {
d.FieldStruct("time", delta)
d.FieldU16("event", metaevents)
decodeLyric(d)
})
case TypeMarker:
d.FieldStruct("Marker", func(d *decode.D) {
d.FieldStruct("time", delta)
d.FieldU16("event", metaevents)
decodeMarker(d)
})
case TypeCuePoint:
d.FieldStruct("CuePoint", func(d *decode.D) {
d.FieldStruct("time", delta)
d.FieldU16("event", metaevents)
decodeCuePoint(d)
})
case TypeProgramName:
d.FieldStruct("ProgramName", func(d *decode.D) {
d.FieldStruct("time", delta)
d.FieldU16("event", metaevents)
decodeProgramName(d)
})
case TypeDeviceName:
d.FieldStruct("DeviceName", func(d *decode.D) {
d.FieldStruct("time", delta)
d.FieldU16("event", metaevents)
decodeDeviceName(d)
})
case TypeMIDIChannelPrefix:
d.FieldStruct("TypeMIDIChannelPrefix", func(d *decode.D) {
d.FieldStruct("time", delta)
d.FieldU16("event", metaevents)
decodeMIDIChannelPrefix(d)
})
case TypeMIDIPort:
d.FieldStruct("TypeMIDIPort", func(d *decode.D) {
d.FieldStruct("time", delta)
d.FieldU16("event", metaevents)
decodeMIDIPort(d)
})
case TypeTempo:
d.FieldStruct("Tempo", func(d *decode.D) {
d.FieldStruct("time", delta)
d.FieldU16("event", metaevents)
decodeTempo(d)
})
case TypeSMPTEOffset:
d.FieldStruct("SMPTEOffset", func(d *decode.D) {
d.FieldStruct("time", delta)
d.FieldU16("event", metaevents)
decodeSMPTEOffset(d)
})
case TypeTimeSignature:
d.FieldStruct("TimeSignature", func(d *decode.D) {
d.FieldStruct("time", delta)
d.FieldU16("event", metaevents)
decodeTimeSignature(d)
})
case TypeKeySignature:
d.FieldStruct("KeySignature", func(d *decode.D) {
d.FieldStruct("time", delta)
d.FieldU16("event", metaevents)
decodeKeySignature(d)
})
case TypeEndOfTrack:
d.FieldStruct("EndOfTrack", func(d *decode.D) {
d.FieldStruct("time", delta)
d.FieldU16("event", metaevents)
decodeEndOfTrack(d)
})
case TypeSequencerSpecificEvent:
d.FieldStruct("SequencerSpecific", func(d *decode.D) {
d.FieldStruct("time", delta)
d.FieldU16("event", metaevents)
decodeSequencerSpecificEvent(d)
})
default:
flush(d, "unknown meta event (%02x)", event)
}
}
func decodeSequenceNumber(d *decode.D) {
d.FieldUintFn("sequenceNumber", func(d *decode.D) uint64 {
data := vlf(d)
seqno := uint64(0)
if len(data) > 0 {
seqno += uint64(data[0])
}
if len(data) > 1 {
seqno <<= 8
seqno += uint64(data[1])
}
return seqno
})
}
func decodeText(d *decode.D) {
d.FieldStrFn("text", func(d *decode.D) string {
return string(vlf(d))
})
}
func decodeCopyright(d *decode.D) {
d.FieldStrFn("copyright", func(d *decode.D) string {
return string(vlf(d))
})
}
func decodeTrackName(d *decode.D) {
d.FieldStrFn("name", func(d *decode.D) string {
return string(vlf(d))
})
}
func decodeInstrumentName(d *decode.D) {
d.FieldStrFn("instrument", func(d *decode.D) string {
return string(vlf(d))
})
}
func decodeLyric(d *decode.D) {
d.FieldStrFn("lyric", func(d *decode.D) string {
return string(vlf(d))
})
}
func decodeMarker(d *decode.D) {
d.FieldStrFn("marker", func(d *decode.D) string {
return string(vlf(d))
})
}
func decodeCuePoint(d *decode.D) {
d.FieldStrFn("cue", func(d *decode.D) string {
return string(vlf(d))
})
}
func decodeProgramName(d *decode.D) {
d.FieldStrFn("program", func(d *decode.D) string {
return string(vlf(d))
})
}
func decodeDeviceName(d *decode.D) {
d.FieldStrFn("device", func(d *decode.D) string {
return string(vlf(d))
})
}
func decodeMIDIChannelPrefix(d *decode.D) {
d.FieldUintFn("channel", func(d *decode.D) uint64 {
channel := uint64(0)
data := vlf(d)
for _, b := range data {
channel <<= 8
channel |= uint64(b & 0x00ff)
}
return channel
})
}
func decodeMIDIPort(d *decode.D) {
d.FieldUintFn("port", func(d *decode.D) uint64 {
channel := uint64(0)
data := vlf(d)
for _, b := range data {
channel <<= 8
channel |= uint64(b & 0x00ff)
}
return channel
})
}
func decodeTempo(d *decode.D) {
d.FieldUintFn("tempo", func(d *decode.D) uint64 {
tempo := uint64(0)
data := vlf(d)
for _, b := range data {
tempo <<= 8
tempo |= uint64(b & 0x00ff)
}
return tempo
})
}
func decodeSMPTEOffset(d *decode.D) {
d.FieldStruct("offset", func(d *decode.D) {
var data []uint8
d.FieldStrFn("bytes", func(d *decode.D) string {
data = vlf(d)
return fmt.Sprintf("%v", data)
})
if len(data) > 0 {
d.FieldUintFn("framerate", func(d *decode.D) uint64 {
return uint64((data[0] >> 6) & 0x03)
}, framerates)
d.FieldValueUint("hour", uint64(data[0]&0x01f))
}
if len(data) > 1 {
d.FieldValueUint("minute", uint64(data[1]))
}
if len(data) > 2 {
d.FieldValueUint("second", uint64(data[2]))
}
if len(data) > 3 {
d.FieldValueUint("frames", uint64(data[3]))
}
if len(data) > 4 {
d.FieldValueUint("fractions", uint64(data[4]))
}
})
}
func decodeTimeSignature(d *decode.D) {
d.FieldStruct("signature", func(d *decode.D) {
var data []uint8
d.FieldStrFn("bytes", func(d *decode.D) string {
data = vlf(d)
return fmt.Sprintf("%v", data)
})
if len(data) > 0 {
d.FieldValueUint("numerator", uint64(data[0]))
}
if len(data) > 1 {
denominator := uint64(1)
for i := uint8(0); i < data[1]; i++ {
denominator <<= 1
}
d.FieldValueUint("denominator", denominator)
}
if len(data) > 2 {
d.FieldValueUint("ticksPerClick", uint64(data[2]))
}
if len(data) > 3 {
d.FieldValueUint("thirtySecondsPerQuarter", uint64(data[3]))
}
})
}
func decodeKeySignature(d *decode.D) {
d.FieldUintFn("key", func(d *decode.D) uint64 {
data := vlf(d)
key := uint64(0)
if len(data) > 0 {
key <<= 8
key |= uint64(data[0]) & 0x00ff
}
if len(data) > 1 {
key <<= 8
key |= uint64(data[1]) & 0x00ff
}
return key
}, keys)
}
func decodeEndOfTrack(d *decode.D) {
d.FieldUintFn("length", func(d *decode.D) uint64 {
return uint64(len(vlf(d)))
})
}
func decodeSequencerSpecificEvent(d *decode.D) {
d.FieldStruct("info", func(d *decode.D) {
var data []uint8
d.FieldStrFn("bytes", func(d *decode.D) string {
data = vlf(d)
return fmt.Sprintf("%v", data)
})
if len(data) > 2 && data[0] == 0x00 {
d.FieldValueStr("manufacturer", fmt.Sprintf("%02X%02X", data[1], data[2]), manufacturers)
if len(data) > 3 {
d.FieldValueStr("data", fmt.Sprintf("%v", data[3:]))
}
} else if len(data) > 0 {
d.FieldValueStr("manufacturer", fmt.Sprintf("%02x", data[0]), manufacturers)
if len(data) > 1 {
d.FieldValueStr("data", fmt.Sprintf("%v", data[1:]))
}
}
})
}