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

midi: Decoded KeySignature, NoteOn and Controller events

This commit is contained in:
twystd 2024-08-14 19:52:15 -07:00
parent a1385caf36
commit 3276641208
5 changed files with 294 additions and 58 deletions

View File

@ -3,6 +3,7 @@
- [ ] add to probe group
- [x] move delta into events
- [ ] tests
- [ ] discard unknown chunks
- formats
- [ ] format 0
@ -25,15 +26,16 @@
- [ ] end of track
- [x] tempo
- [ ] SMPTE offset
- [ ] key signature
- [x] key signature
- [ ] check key mappings
- [ ] time signature
- [ ] sequencer specific event
- midi events
- [ ] note off
- [ ] note on
- [x] note on
- [ ] polyphonic pressure
- [ ] controller
- [x] controller
- [ ] program change
- [ ] channel pressure
- [ ] pitch bend

View File

@ -1,7 +1,10 @@
package midi
import (
"fmt"
"github.com/wader/fq/pkg/decode"
"github.com/wader/fq/pkg/scalar"
)
type MetaEventType uint8
@ -27,6 +30,119 @@ const (
TypeSequencerSpecificEvent MetaEventType = 0x7f
)
const (
keyCMajor = 0x0001
keyGMajor = 0x0101
keyDMajor = 0x0201
keyAMajor = 0x0301
keyEMajor = 0x0401
keyBMajor = 0x0501
keyFSharpMajor = 0x0601
keyCSharpMajor = 0x0701
keyFMajor = 0x0801
keyBFlatMajor = 0x0901
keyEFlatMajor = 0x0a01
keyAFlatMajor = 0x0b01
keyDFlatMajor = 0x0c01
keyGFlatMajor = 0x0d01
keyCFlatMajor = 0x0e01
keyAMinor = 0x0000
keyEMinor = 0x0100
keyBMinor = 0x0200
keyASharpMinor = 0x0300
keyDSharpMinor = 0x0400
keyGSharpMinor = 0x0500
keyCSharpMinor = 0x0600
keyFSharpMinor = 0x0700
keyDMinor = 0x0800
keyGMinor = 0x0900
keyCMinor = 0x0a00
keyFMinor = 0x0b00
keyBFlatMinor = 0x0c00
keyEFlatMinor = 0x0d00
keyAFlatMinor = 0x0e00
)
var keys = scalar.UintMapSymStr{
keyCMajor: "C major",
keyGMajor: "G major",
keyDMajor: "D major",
keyAMajor: "A major",
keyEMajor: "E major",
keyBMajor: "B major",
keyFSharpMajor: "F♯ major",
keyCSharpMajor: "C♯ major",
keyFMajor: "F major",
keyBFlatMajor: "B♭ major",
keyEFlatMajor: "E♭ major",
keyAFlatMajor: "A♭ major",
keyDFlatMajor: "D♭ major",
keyGFlatMajor: "G♭ major",
keyCFlatMajor: "C♭ major",
keyAMinor: "A minor",
keyEMinor: "E minor",
keyBMinor: "B minor",
keyASharpMinor: "A♯ minor",
keyDSharpMinor: "D♯ minor",
keyGSharpMinor: "G♯ minor",
keyCSharpMinor: "C♯ minor",
keyFSharpMinor: "F♯ minor",
keyDMinor: "D minor",
keyGMinor: "G minor",
keyCMinor: "C minor",
keyFMinor: "F minor",
keyBFlatMinor: "B♭ minor",
keyEFlatMinor: "E♭ minor",
keyAFlatMinor: "A♭ minor",
}
func decodeMetaEvent(d *decode.D, event uint8) {
switch MetaEventType(event) {
case TypeTrackName:
d.FieldStruct("TrackName", decodeTrackName)
return
case TypeTempo:
d.FieldStruct("Tempo", decodeTempo)
return
case TypeTimeSignature:
d.FieldStruct("TimeSignature", decodeTimeSignature)
return
case TypeKeySignature:
d.FieldStruct("KeySignature", decodeKeySignature)
return
case TypeEndOfTrack:
d.FieldStruct("EndOfTrack", decodeEndOfTrack)
return
// TypeSequenceNumber MetaEventType = 0x00
// TypeText MetaEventType = 0x01
// TypeCopyright MetaEventType = 0x02
// TypeInstrumentName MetaEventType = 0x04
// TypeLyric MetaEventType = 0x05
// TypeMarker MetaEventType = 0x06
// TypeCuePoint MetaEventType = 0x07
// TypeProgramName MetaEventType = 0x08
// TypeDeviceName MetaEventType = 0x09
// TypeMIDIChannelPrefix MetaEventType = 0x20
// TypeMIDIPort MetaEventType = 0x21
// TypeSMPTEOffset MetaEventType = 0x54
// TypeSequencerSpecificEvent MetaEventType = 0x7f
}
// ... unknown event - flush remaining data
fmt.Printf("UNKNOWN META EVENT:%02x\n", event)
var N int = int(d.BitsLeft())
d.Bits(N)
}
func decodeTrackName(d *decode.D) {
d.FieldUintFn("delta", vlq)
d.FieldU8("status")
@ -84,6 +200,20 @@ func decodeTimeSignature(d *decode.D) {
})
}
func decodeKeySignature(d *decode.D) {
d.FieldUintFn("delta", vlq)
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
d.FieldValueUint("key", key, keys)
}
}
func decodeEndOfTrack(d *decode.D) {
d.FieldUintFn("delta", vlq)
d.FieldU8("status")

View File

@ -106,61 +106,14 @@ func decodeEvent(d *decode.D) {
// ... meta event?
if status == 0xff {
switch MetaEventType(event) {
case TypeTrackName:
d.FieldStruct("TrackName", decodeTrackName)
return
case TypeTempo:
d.FieldStruct("Tempo", decodeTempo)
return
case TypeTimeSignature:
d.FieldStruct("TimeSignature", decodeTimeSignature)
return
case TypeEndOfTrack:
d.FieldStruct("EndOfTrack", decodeEndOfTrack)
return
// TypeSequenceNumber MetaEventType = 0x00
// TypeText MetaEventType = 0x01
// TypeCopyright MetaEventType = 0x02
// TypeInstrumentName MetaEventType = 0x04
// TypeLyric MetaEventType = 0x05
// TypeMarker MetaEventType = 0x06
// TypeCuePoint MetaEventType = 0x07
// TypeProgramName MetaEventType = 0x08
// TypeDeviceName MetaEventType = 0x09
// TypeMIDIChannelPrefix MetaEventType = 0x20
// TypeMIDIPort MetaEventType = 0x21
// TypeSMPTEOffset MetaEventType = 0x54
// TypeKeySignature MetaEventType = 0x59
// TypeSequencerSpecificEvent MetaEventType = 0x7f
}
decodeMetaEvent(d, event)
return
}
// ... sysex event
// ... midi event?
switch MidiEventType(status & 0xf0) {
case TypeProgramChange:
d.FieldStruct("ProgramChange", decodeProgramChange)
return
// TypeNoteOff MidiEventType = 0x80
// TypeNoteOn MidiEventType = 0x90
// TypePolyphonicPressure MidiEventType = 0xa0
// TypeController MidiEventType = 0xb0
// TypeProgramChange MidiEventType = 0xc0
// TypeChannelPressure MidiEventType = 0xd0
// TypePitchBend MidiEventType = 0xe0
}
fmt.Printf(">>>>>>>>>>> UNKNOWN: %02x %02x\n", status, event)
// ... unknown event - flush remaining data
var N int = int(d.BitsLeft())
d.Bits(N)
decodeMIDIEvent(d, status)
}
func peekEvent(d *decode.D) (uint64, uint8, uint8) {

View File

@ -1,7 +1,10 @@
package midi
import (
"fmt"
"github.com/wader/fq/pkg/decode"
"github.com/wader/fq/pkg/scalar"
)
type MidiEventType byte
@ -16,6 +19,146 @@ const (
TypePitchBend MidiEventType = 0xe0
)
var controllers = scalar.UintMapSymStr{
// High resolution continuous controllers (MSB)
0: "Bank Select (MSB)",
1: "Modulation Wheel (MSB)",
2: "Breath Controller (MSB)",
4: "Foot Controller (MSB)",
5: "Portamento Time (MSB)",
6: "Data Entry (MSB)",
7: "Channel Volume (MSB)",
8: "Balance (MSB)",
10: "Pan (MSB)",
11: "Expression Controller (MSB)",
12: "Effect Control 1 (MSB)",
13: "Effect Control 2 (MSB)",
16: "General Purpose Controller 1 (MSB)",
17: "General Purpose Controller 2 (MSB)",
18: "General Purpose Controller 3 (MSB)",
19: "General Purpose Controller 4 (MSB)",
// High resolution continuous controllers (LSB)
32: "Bank Select (LSB)",
33: "Modulation Wheel (LSB)",
34: "Breath Controller (LSB)",
36: "Foot Controller (LSB)",
37: "Portamento Time (LSB)",
38: "Data Entry (LSB)",
39: "Channel Volume (LSB)",
40: "Balance (LSB)",
42: "Pan (LSB)",
43: "Expression Controller (LSB)",
44: "Effect Control 1 (LSB)",
45: "Effect Control 2 (LSB)",
48: "General Purpose Controller 1 (LSB)",
49: "General Purpose Controller 2 (LSB)",
50: "General Purpose Controller 3 (LSB)",
51: "General Purpose Controller 4 (LSB)",
// Switches
64: "Sustain On/Off",
65: "Portamento On/Off",
66: "Sostenuto On/Off",
67: "Soft Pedal On/Off",
68: "Legato On/Off",
69: "Hold 2 On/Off",
// Low resolution continuous controllers
70: "Sound Controller 1 (TG: Sound Variation; FX: Exciter On/Off)",
71: "Sound Controller 2 (TG: Harmonic Content; FX: Compressor On/Off)",
72: "Sound Controller 3 (TG: Release Time; FX: Distortion On/Off)",
73: "Sound Controller 4 (TG: Attack Time; FX: EQ On/Off)",
74: "Sound Controller 5 (TG: Brightness; FX: Expander On/Off)",
75: "Sound Controller 6 (TG: Decay Time; FX: Reverb On/Off)",
76: "Sound Controller 7 (TG: Vibrato Rate; FX: Delay On/Off)",
77: "Sound Controller 8 (TG: Vibrato Depth; FX: Pitch Transpose On/Off)",
78: "Sound Controller 9 (TG: Vibrato Delay; FX: Flange/Chorus On/Off)",
79: "Sound Controller 10 (TG: Undefined; FX: Special Effects On/Off)",
80: "General Purpose Controller 5",
81: "General Purpose Controller 6",
82: "General Purpose Controller 7",
83: "General Purpose Controller 8",
84: "Portamento Control",
88: "High Resolution Velocity Prefix",
91: "Effects 1 Depth (Reverb Send Level)",
92: "Effects 2 Depth (Tremelo Depth)",
93: "Effects 3 Depth (Chorus Send Level)",
94: "Effects 4 Depth (Celeste Depth)",
95: "Effects 5 Depth (Phaser Depth)",
// RPNs / NRPNs
96: "Data Increment",
97: "Data Decrement",
98: "Non-Registered Parameter Number (LSB)",
99: "Non-Registered Parameter Number (MSB)",
100: "Registered Parameter Number (LSB)",
101: "Registered Parameter Number (MSB)",
// Channel Mode messages
120: "All Sound Off",
121: "Reset All Controllers",
122: "Local Control On/Off",
123: "All Notes Off",
124: "Omni Mode Off",
125: "Omni Mode On ",
126: "Mono Mode On",
127: "Poly Mode On",
}
func decodeMIDIEvent(d *decode.D, status uint8) {
switch MidiEventType(status & 0xf0) {
case TypeNoteOn:
d.FieldStruct("NoteOn", decodeNoteOn)
return
case TypeController:
d.FieldStruct("Controller", decodeController)
return
case TypeProgramChange:
d.FieldStruct("ProgramChange", decodeProgramChange)
return
// TypeNoteOff MidiEventType = 0x80
// TypePolyphonicPressure MidiEventType = 0xa0
// TypeProgramChange MidiEventType = 0xc0
// TypeChannelPressure MidiEventType = 0xd0
// TypePitchBend MidiEventType = 0xe0
}
// ... unknown event - flush remaining data
fmt.Printf("UNKNOWN MIDI EVENT: %02x\n", status)
var N int = int(d.BitsLeft())
d.Bits(N)
}
func decodeNoteOn(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("note")
d.FieldU8("velocity")
}
func decodeController(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("controller", controllers)
d.FieldU8("value")
}
func decodeProgramChange(d *decode.D) {
d.FieldUintFn("delta", vlq)
d.FieldUintFn("channel", func(d *decode.D) uint64 {

View File

@ -35,8 +35,16 @@ ff
03
0f 41 63 6f 75 73 74 69 63 20 47 75 69 74 61 72
00 c0 19 00 90 30 48
00ff 5902 0001 00b0
6500 00b0 6400 00b0 0606 8360 8030 4000
00 c0 19
00 90 30 48
00
ff
59
02 00 01
00 b0 65 00
00b0 6400 00b0 0606 8360 8030 4000
9032 4883 6080 3240 0090 3448 8360 8034
4000 9035 4883 6080 3540 00ff 2f00