1
1
mirror of https://github.com/wader/fq.git synced 2024-11-23 00:57:15 +03:00

midi: Decoded MIDIChannelPrefix, MIDIPort and SequencerSpecific metaevents

This commit is contained in:
twystd 2024-08-16 18:30:05 -07:00
parent 2a16748391
commit 109719f25d
4 changed files with 101 additions and 26 deletions

View File

@ -1,6 +1,6 @@
# TODO
- [ ] update fork from master
- [x] update forked master branch
- [ ] discard unknown chunks
- [ ] tests
- [ ] format 0
@ -17,25 +17,26 @@
- [ ] format 2
- meta events
- [ ] sequence number
- [ ] text
- [ ] copyright
- [x] sequence number
- [x] text
- [x] copyright
- [x] track name
- [ ] instrument name
- [ ] lyric
- [ ] marker
- [ ] cue point
- [ ] program name
- [ ] device name
- [ ] MIDI channel prefix
- [ ] MIDI port
- [ ] end of track
- [x] instrument name
- [x] lyric
- [x] marker
- [x] cue point
- [x] program name
- [x] device name
- [x] MIDI channel prefix
- [x] MIDI port
- [x] end of track
- [x] tempo
- [ ] SMPTE offset
- [x] SMPTE offset
- [x] key signature
- [ ] check key mappings
- [x] time signature
- [ ] sequencer specific event
- [ ] map manufacturer
- midi events
- [x] note off
@ -44,7 +45,7 @@
- [ ] map note name
- [ ] polyphonic pressure
- [x] controller
- [ ] program change
- [x] program change
- [ ] channel pressure
- [ ] pitch bend

View File

@ -140,6 +140,14 @@ func decodeMetaEvent(d *decode.D, event uint8) {
d.FieldStruct("DeviceName", decodeDeviceName)
return
case TypeMIDIChannelPrefix:
d.FieldStruct("TypeMIDIChannelPrefix", decodeMIDIChannelPrefix)
return
case TypeMIDIPort:
d.FieldStruct("TypeMIDIPort", decodeMIDIPort)
return
case TypeTempo:
d.FieldStruct("Tempo", decodeTempo)
return
@ -160,9 +168,9 @@ func decodeMetaEvent(d *decode.D, event uint8) {
d.FieldStruct("EndOfTrack", decodeEndOfTrack)
return
// TypeMIDIChannelPrefix MetaEventType = 0x20
// TypeMIDIPort MetaEventType = 0x21
// TypeSequencerSpecificEvent MetaEventType = 0x7f
case TypeSequencerSpecificEvent:
d.FieldStruct("SequencerSpecificEvent", decodeSequencerSpecificEvent)
return
}
// ... unknown event - flush remaining data
@ -275,6 +283,40 @@ func decodeDeviceName(d *decode.D) {
})
}
func decodeMIDIChannelPrefix(d *decode.D) {
d.FieldUintFn("delta", vlq)
d.FieldU8("status")
d.FieldU8("event")
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("delta", vlq)
d.FieldU8("status")
d.FieldU8("event")
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("delta", vlq)
d.FieldU8("status")
@ -377,10 +419,10 @@ func decodeKeySignature(d *decode.D) {
d.FieldU8("status")
d.FieldU8("event")
bytes := vlf(d)
if len(bytes) > 1 {
key := (uint64(bytes[0]) << 8) & 0xff00
key |= (uint64(bytes[1]) << 0) & 0x00ff
data := vlf(d)
if len(data) > 1 {
key := (uint64(data[0]) << 8) & 0xff00
key |= (uint64(data[1]) << 0) & 0x00ff
d.FieldValueUint("key", key, keys)
}
@ -393,3 +435,24 @@ func decodeEndOfTrack(d *decode.D) {
vlf(d)
}
func decodeSequencerSpecificEvent(d *decode.D) {
d.FieldUintFn("delta", vlq)
d.FieldU8("status")
d.FieldU8("event")
data := vlf(d)
if len(data) > 2 && data[0] == 0x00 {
d.FieldValueStr("manufacturer", fmt.Sprintf("%02X%02X%02X", data[0], data[1], data[2]))
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]))
if len(data) > 1 {
d.FieldValueStr("data", fmt.Sprintf("%v", data[1:]))
}
}
}

View File

@ -5,7 +5,6 @@ package midi
import (
"bytes"
"embed"
"fmt"
"github.com/wader/fq/format"
"github.com/wader/fq/pkg/decode"
@ -101,8 +100,6 @@ func decodeMTrk(d *decode.D) {
func decodeEvent(d *decode.D) {
_, status, event := peekEvent(d)
fmt.Printf(">> status:%02x event:%02x\n", status, event)
// ... meta event?
if status == 0xff {
decodeMetaEvent(d, event)

View File

@ -116,6 +116,10 @@ func decodeMIDIEvent(d *decode.D, status uint8) {
d.FieldStruct("NoteOn", decodeNoteOn)
return
case TypePolyphonicPressure:
d.FieldStruct("PolyphonicPressure", decodePolyphonicPressure)
return
case TypeController:
d.FieldStruct("Controller", decodeController)
return
@ -124,7 +128,6 @@ func decodeMIDIEvent(d *decode.D, status uint8) {
d.FieldStruct("ProgramChange", decodeProgramChange)
return
// TypePolyphonicPressure MidiEventType = 0xa0
// TypeProgramChange MidiEventType = 0xc0
// TypeChannelPressure MidiEventType = 0xd0
// TypePitchBend MidiEventType = 0xe0
@ -162,6 +165,17 @@ func decodeNoteOn(d *decode.D) {
d.FieldU8("velocity")
}
func decodePolyphonicPressure(d *decode.D) {
d.FieldUintFn("delta", vlq)
d.FieldUintFn("channel", func(d *decode.D) uint64 {
b := d.BytesLen(1)
return uint64(b[0] & 0x0f)
})
d.FieldU8("pressure")
}
func decodeController(d *decode.D) {
d.FieldUintFn("delta", vlq)
d.FieldUintFn("channel", func(d *decode.D) uint64 {