Skip to content

Commit

Permalink
midi: reworked sysex and metaevent 'struct' events to decode as byte …
Browse files Browse the repository at this point in the history
…arrays
  • Loading branch information
twystd committed Aug 20, 2024
1 parent ce02d6e commit a337ff0
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 113 deletions.
8 changes: 6 additions & 2 deletions format/midi/TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,21 @@
- [ ] format 0
- [ ] format 1
- [ ] format 2
- [x] key signatures
- (?) example queries
- tempo changes
- key changes
- notes
- (?) add to probe group
- (?) tick field

- [ ] fix gaps
- [x] fix gaps
- [x] SequencerSpecificEvent
- [x] SMPTEOffset
- [x] TimeSignature
- [x] SysExMessage
- [ ] SysEx - 'continued' flag
- [x] SysExContinuation
- [x] SysEx - 'continued' flag

- meta events
- [x] sequence number
Expand All @@ -39,8 +41,10 @@
- [x] end of track
- [x] tempo
- [x] SMPTE offset
- [ ] map frame rates
- [x] key signature
- [x] time signature
- [ ] map denominator
- [x] sequencer specific event
- [x] map manufacturer
- [x] check key mappings
Expand Down
104 changes: 45 additions & 59 deletions format/midi/metaevents.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,12 +253,15 @@ func decodeSMPTEOffset(d *decode.D) {
d.FieldU8("event")

d.FieldStruct("offset", func(d *decode.D) {
N := int(d.FieldUintFn("length", vlq))
data := d.PeekBytes(N)
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 {
d.BytesLen(1)
rr := (data[0] >> 6) & 0x03

switch rr {
Expand All @@ -278,35 +281,24 @@ func decodeSMPTEOffset(d *decode.D) {
return 0
}
})

d.FieldValueUint("hour", uint64(data[0]&0x01f))
}

if len(data) > 1 {
d.FieldUintFn("minute", func(d *decode.D) uint64 {
d.BytesLen(1)
return uint64(data[1])
})
d.FieldValueUint("minute", uint64(data[1]))
}

if len(data) > 2 {
d.FieldUintFn("second", func(d *decode.D) uint64 {
d.BytesLen(1)
return uint64(data[2])
})
d.FieldValueUint("second", uint64(data[2]))
}

if len(data) > 3 {
d.FieldUintFn("frames", func(d *decode.D) uint64 {
d.BytesLen(1)
return uint64(data[3])
})
d.FieldValueUint("frames", uint64(data[3]))
}

if len(data) > 4 {
d.FieldUintFn("fractions", func(d *decode.D) uint64 {
d.BytesLen(1)
return uint64(data[4])
})
d.FieldValueUint("fractions", uint64(data[4]))
}
})
}
Expand All @@ -316,33 +308,35 @@ func decodeTimeSignature(d *decode.D) {
d.FieldU8("status")
d.FieldU8("event")
d.FieldStruct("signature", func(d *decode.D) {
N := int(d.FieldUintFn("length", vlq))
data := d.PeekBytes(N)
var data []uint8
d.FieldStrFn("bytes", func(d *decode.D) string {
data = vlf(d)

d.FieldUintFn("numerator", func(d *decode.D) uint64 {
d.BytesLen(1)
return uint64(data[0])
return fmt.Sprintf("%v", data)
})

d.FieldUintFn("denominator", func(d *decode.D) uint64 {
d.BytesLen(1)
denominator := uint16(1)
for i := uint8(0); i < data[1]; i++ {
denominator *= 2
}
if len(data) > 0 {
d.FieldValueUint("numerator", uint64(data[0]))
}

return uint64(denominator)
})
if len(data) > 1 {
d.FieldUintFn("denominator", func(d *decode.D) uint64 {
denominator := uint16(1)
for i := uint8(0); i < data[1]; i++ {
denominator *= 2
}

d.FieldUintFn("ticksPerClick", func(d *decode.D) uint64 {
d.BytesLen(1)
return uint64(data[2])
})
return uint64(denominator)
})
}

d.FieldUintFn("thirtySecondsPerQuarter", func(d *decode.D) uint64 {
d.BytesLen(1)
return uint64(data[3])
})
if len(data) > 2 {
d.FieldValueUint("ticksPerClick", uint64(data[2]))
}

if len(data) > 3 {
d.FieldValueUint("thirtySecondsPerQuarter", uint64(data[3]))
}
})
}

Expand Down Expand Up @@ -376,33 +370,25 @@ func decodeSequencerSpecificEvent(d *decode.D) {
d.FieldU8("status")
d.FieldU8("event")

d.FieldStruct("message", func(d *decode.D) {
N := int(d.FieldUintFn("length", vlq))
data := d.PeekBytes(N)
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.FieldStrFn("manufacturer", func(d *decode.D) string {
d.BytesLen(3)
return fmt.Sprintf("%02X%02X", data[1], data[2])
}, manufacturers)
d.FieldValueStr("manufacturer", fmt.Sprintf("%02X%02X", data[1], data[2]), manufacturers)

if len(data) > 3 {
d.FieldStrFn("data", func(d *decode.D) string {
d.BytesLen(N - 3)
return fmt.Sprintf("%v", data[3:])
})
d.FieldValueStr("data", fmt.Sprintf("%v", data[3:]))
}

} else if len(data) > 0 {
d.FieldStrFn("manufacturer", func(d *decode.D) string {
d.BytesLen(1)
return fmt.Sprintf("%02x", data[0])
}, manufacturers)
d.FieldValueStr("manufacturer", fmt.Sprintf("%02x", data[0]), manufacturers)
if len(data) > 1 {
d.BytesLen(N - 1)
d.FieldStrFn("data", func(d *decode.D) string {
return fmt.Sprintf("%v", data[1:])
})
d.FieldValueStr("data", fmt.Sprintf("%v", data[1:]))
}
}
})
Expand Down
92 changes: 45 additions & 47 deletions format/midi/sysex.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,69 +36,67 @@ func decodeSysExEvent(d *decode.D, status uint8, ctx *context) {
func decodeSysExMessage(d *decode.D, ctx *context) {
d.FieldUintFn("delta", vlq)
d.FieldU8("status")
d.FieldStruct("message", func(d *decode.D) {
N := int(d.FieldUintFn("length", vlq))
data := d.PeekBytes(N)

if N < 1 {
ctx.casio = true
} else {
d.FieldStrFn("manufacturer", func(d *decode.D) string {
d.BytesLen(1)

return fmt.Sprintf("%02X", data[0])
}, manufacturers)

if N > 1 {
d.FieldStrFn("data", func(d *decode.D) string {
d.BytesLen(int(N) - 1)

if data[len(data)-1] == 0xf7 {
ctx.casio = false
} else {
ctx.casio = true
}

if data[len(data)-1] == 0xf7 {
return fmt.Sprintf("%v", data[1:len(data)-1])
} else {
return fmt.Sprintf("%v", data[1:])
}
})
var bytes []uint8
d.FieldStrFn("bytes", func(d *decode.D) string {
bytes = vlf(d)
return fmt.Sprintf("%v", bytes)
})

if len(bytes) < 1 {
ctx.casio = true
} else {
id := fmt.Sprintf("%02X", bytes[0])

d.FieldValueStr("manufacturer", id, manufacturers)

if len(bytes) > 1 {
if bytes[len(bytes)-1] == 0xf7 {
ctx.casio = false
} else {
ctx.casio = true
}

if bytes[len(bytes)-1] == 0xf7 {
d.FieldValueStr("data", fmt.Sprintf("%v", bytes[1:len(bytes)-1]))
} else {
d.FieldValueStr("data", fmt.Sprintf("%v", bytes[1:]))
}
}
})
}

if ctx.casio {
d.FieldValueBool("continued", true)
}
}

func decodeSysExContinuation(d *decode.D, ctx *context) {
d.FieldUintFn("delta", vlq)
d.FieldU8("status")
d.FieldStruct("message", func(d *decode.D) {
N := int(d.FieldUintFn("length", vlq))
d.FieldStrFn("data", func(d *decode.D) string {
data := vlf(d)

d.FieldStrFn("data", func(d *decode.D) string {
data := d.BytesLen(N)
if len(data) > 0 && data[len(data)-1] == 0xf7 {
ctx.casio = false
return fmt.Sprintf("%v", data[:len(data)-1])
} else {
ctx.casio = true
return fmt.Sprintf("%v", data)
}
})
if len(data) > 0 && data[len(data)-1] == 0xf7 {
ctx.casio = false
} else {
ctx.casio = true
}

if len(data) > 0 && data[len(data)-1] == 0xf7 {
return fmt.Sprintf("%v", data[:len(data)-1])
} else {
return fmt.Sprintf("%v", data)
}
})
}

func decodeSysExEscape(d *decode.D, ctx *context) {
d.FieldUintFn("delta", vlq)
d.FieldU8("status")
d.FieldStruct("message", func(d *decode.D) {
N := int(d.FieldUintFn("length", vlq))
d.FieldStrFn("data", func(d *decode.D) string {
data := vlf(d)

d.FieldStrFn("data", func(d *decode.D) string {
data := d.BytesLen(N)
return fmt.Sprintf("%v", data)
})
return fmt.Sprintf("%v", data)
})

ctx.casio = false
Expand Down
11 changes: 6 additions & 5 deletions format/midi/testdata/test.fqtest
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ $ ./fq -d midi dv test.mid
0x20| ff | . | status: 255 0x2b-0x2c (1)
0x20| 58 | X | event: 88 0x2c-0x2d (1)
| | | signature{}: 0x2d-0x32 (5)
0x20| 04 | . | length: 4 0x2d-0x2e (1)
0x20| 04 | . | numerator: 4 0x2e-0x2f (1)
0x20| 02| .| denominator: 4 0x2f-0x30 (1)
0x30|18 |. | ticksPerClick: 24 0x30-0x31 (1)
0x30| 08 | . | thirtySecondsPerQuarter: 8 0x31-0x32 (1)
0x20| 04 04 02| ...| bytes: "[4 2 24 8]" 0x2d-0x32 (5)
0x30|18 08 |.. |
| | | numerator: 4
| | | denominator: 4 0x32-0x32 (0)
| | | ticksPerClick: 24
| | | thirtySecondsPerQuarter: 8
| | | [3]{}: EndOfTrack 0x32-0x36 (4)
0x30| 00 | . | delta: 0 0x32-0x33 (1)
0x30| ff | . | status: 255 0x33-0x34 (1)
Expand Down

0 comments on commit a337ff0

Please sign in to comment.