1
1
mirror of https://github.com/wader/fq.git synced 2024-11-26 10:33:53 +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 # TODO
- [ ] update fork from master - [x] update forked master branch
- [ ] discard unknown chunks - [ ] discard unknown chunks
- [ ] tests - [ ] tests
- [ ] format 0 - [ ] format 0
@ -17,25 +17,26 @@
- [ ] format 2 - [ ] format 2
- meta events - meta events
- [ ] sequence number - [x] sequence number
- [ ] text - [x] text
- [ ] copyright - [x] copyright
- [x] track name - [x] track name
- [ ] instrument name - [x] instrument name
- [ ] lyric - [x] lyric
- [ ] marker - [x] marker
- [ ] cue point - [x] cue point
- [ ] program name - [x] program name
- [ ] device name - [x] device name
- [ ] MIDI channel prefix - [x] MIDI channel prefix
- [ ] MIDI port - [x] MIDI port
- [ ] end of track - [x] end of track
- [x] tempo - [x] tempo
- [ ] SMPTE offset - [x] SMPTE offset
- [x] key signature - [x] key signature
- [ ] check key mappings - [ ] check key mappings
- [x] time signature - [x] time signature
- [ ] sequencer specific event - [ ] sequencer specific event
- [ ] map manufacturer
- midi events - midi events
- [x] note off - [x] note off
@ -44,7 +45,7 @@
- [ ] map note name - [ ] map note name
- [ ] polyphonic pressure - [ ] polyphonic pressure
- [x] controller - [x] controller
- [ ] program change - [x] program change
- [ ] channel pressure - [ ] channel pressure
- [ ] pitch bend - [ ] pitch bend

View File

@ -140,6 +140,14 @@ func decodeMetaEvent(d *decode.D, event uint8) {
d.FieldStruct("DeviceName", decodeDeviceName) d.FieldStruct("DeviceName", decodeDeviceName)
return return
case TypeMIDIChannelPrefix:
d.FieldStruct("TypeMIDIChannelPrefix", decodeMIDIChannelPrefix)
return
case TypeMIDIPort:
d.FieldStruct("TypeMIDIPort", decodeMIDIPort)
return
case TypeTempo: case TypeTempo:
d.FieldStruct("Tempo", decodeTempo) d.FieldStruct("Tempo", decodeTempo)
return return
@ -160,9 +168,9 @@ func decodeMetaEvent(d *decode.D, event uint8) {
d.FieldStruct("EndOfTrack", decodeEndOfTrack) d.FieldStruct("EndOfTrack", decodeEndOfTrack)
return return
// TypeMIDIChannelPrefix MetaEventType = 0x20 case TypeSequencerSpecificEvent:
// TypeMIDIPort MetaEventType = 0x21 d.FieldStruct("SequencerSpecificEvent", decodeSequencerSpecificEvent)
// TypeSequencerSpecificEvent MetaEventType = 0x7f return
} }
// ... unknown event - flush remaining data // ... 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) { func decodeTempo(d *decode.D) {
d.FieldUintFn("delta", vlq) d.FieldUintFn("delta", vlq)
d.FieldU8("status") d.FieldU8("status")
@ -377,10 +419,10 @@ func decodeKeySignature(d *decode.D) {
d.FieldU8("status") d.FieldU8("status")
d.FieldU8("event") d.FieldU8("event")
bytes := vlf(d) data := vlf(d)
if len(bytes) > 1 { if len(data) > 1 {
key := (uint64(bytes[0]) << 8) & 0xff00 key := (uint64(data[0]) << 8) & 0xff00
key |= (uint64(bytes[1]) << 0) & 0x00ff key |= (uint64(data[1]) << 0) & 0x00ff
d.FieldValueUint("key", key, keys) d.FieldValueUint("key", key, keys)
} }
@ -393,3 +435,24 @@ func decodeEndOfTrack(d *decode.D) {
vlf(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 ( import (
"bytes" "bytes"
"embed" "embed"
"fmt"
"github.com/wader/fq/format" "github.com/wader/fq/format"
"github.com/wader/fq/pkg/decode" "github.com/wader/fq/pkg/decode"
@ -101,8 +100,6 @@ func decodeMTrk(d *decode.D) {
func decodeEvent(d *decode.D) { func decodeEvent(d *decode.D) {
_, status, event := peekEvent(d) _, status, event := peekEvent(d)
fmt.Printf(">> status:%02x event:%02x\n", status, event)
// ... meta event? // ... meta event?
if status == 0xff { if status == 0xff {
decodeMetaEvent(d, event) decodeMetaEvent(d, event)

View File

@ -116,6 +116,10 @@ func decodeMIDIEvent(d *decode.D, status uint8) {
d.FieldStruct("NoteOn", decodeNoteOn) d.FieldStruct("NoteOn", decodeNoteOn)
return return
case TypePolyphonicPressure:
d.FieldStruct("PolyphonicPressure", decodePolyphonicPressure)
return
case TypeController: case TypeController:
d.FieldStruct("Controller", decodeController) d.FieldStruct("Controller", decodeController)
return return
@ -124,7 +128,6 @@ func decodeMIDIEvent(d *decode.D, status uint8) {
d.FieldStruct("ProgramChange", decodeProgramChange) d.FieldStruct("ProgramChange", decodeProgramChange)
return return
// TypePolyphonicPressure MidiEventType = 0xa0
// TypeProgramChange MidiEventType = 0xc0 // TypeProgramChange MidiEventType = 0xc0
// TypeChannelPressure MidiEventType = 0xd0 // TypeChannelPressure MidiEventType = 0xd0
// TypePitchBend MidiEventType = 0xe0 // TypePitchBend MidiEventType = 0xe0
@ -162,6 +165,17 @@ func decodeNoteOn(d *decode.D) {
d.FieldU8("velocity") 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) { func decodeController(d *decode.D) {
d.FieldUintFn("delta", vlq) d.FieldUintFn("delta", vlq)
d.FieldUintFn("channel", func(d *decode.D) uint64 { d.FieldUintFn("channel", func(d *decode.D) uint64 {