Skip to content

Commit

Permalink
midi: accomodated MIDI event running status
Browse files Browse the repository at this point in the history
  • Loading branch information
twystd committed Aug 17, 2024
1 parent 0226fc6 commit b2e71a3
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 61 deletions.
5 changes: 3 additions & 2 deletions format/midi/TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@
- [x] key signature
- [ ] check key mappings
- [x] time signature
- [ ] sequencer specific event
- [x] sequencer specific event
- [ ] map manufacturer
- [ ] Use FieldUTF8String

- midi events
- [x] note off
Expand All @@ -48,7 +49,7 @@
- [x] program change
- [x] channel pressure
- [x] pitch bend
- [ ] running status
- [x] running status

- sysex events
- [ ] message
Expand Down
21 changes: 18 additions & 3 deletions format/midi/midi.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,25 @@ func decodeMTrk(d *decode.D) {

d.FieldArray("events", func(d *decode.D) {
d.FramedFn(int64(length)*8, func(d *decode.D) {
var running uint8 = 0x000

for d.BitsLeft() > 0 {
decodeEvent(d)
_, status, _ := peekEvent(d)
if status < 0x80 {
status = running
} else if status == 0xff || status == 0xf0 || status == 0xf7 {
running = 0x00
} else {
running = status
}

decodeEvent(d, running)
}
})
})
}

func decodeEvent(d *decode.D) {
func decodeEvent(d *decode.D, running uint8) {
_, status, event := peekEvent(d)

// ... meta event?
Expand All @@ -109,7 +120,11 @@ func decodeEvent(d *decode.D) {
// ... sysex event

// ... midi event?
decodeMIDIEvent(d, status)
if status < 0x80 {
decodeMIDIEvent(d, running)
} else {
decodeMIDIEvent(d, status)
}
}

func peekEvent(d *decode.D) (uint64, uint8, uint8) {
Expand Down
107 changes: 51 additions & 56 deletions format/midi/midievents.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,33 +107,77 @@ var controllers = scalar.UintMapSymStr{
func decodeMIDIEvent(d *decode.D, status uint8) {
event := status & 0xf0

channel := func(d *decode.D) uint64 {
b := d.PeekBytes(1)
if b[0] >= 0x80 {
d.BytesLen(1)
}

return uint64(status & 0x0f)
}

switch MidiEventType(event) {
case TypeNoteOff:
d.FieldStruct("NoteOff", decodeNoteOff)
d.FieldStruct("NoteOff", func(d *decode.D) {
d.FieldUintFn("delta", vlq)
d.FieldUintFn("channel", channel)

decodeNoteOff(d)
})
return

case TypeNoteOn:
d.FieldStruct("NoteOn", decodeNoteOn)
d.FieldStruct("NoteOn", func(d *decode.D) {
d.FieldUintFn("delta", vlq)
d.FieldUintFn("channel", channel)

decodeNoteOn(d)
})
return

case TypePolyphonicPressure:
d.FieldStruct("PolyphonicPressure", decodePolyphonicPressure)
d.FieldStruct("PolyphonicPressure", func(d *decode.D) {
d.FieldUintFn("delta", vlq)
d.FieldUintFn("channel", channel)

decodePolyphonicPressure(d)
})
return

case TypeController:
d.FieldStruct("Controller", decodeController)
d.FieldStruct("Controller", func(d *decode.D) {
d.FieldUintFn("delta", vlq)
d.FieldUintFn("channel", channel)

decodeController(d)
})
return

case TypeProgramChange:
d.FieldStruct("ProgramChange", decodeProgramChange)
d.FieldStruct("ProgramChange", func(d *decode.D) {
d.FieldUintFn("delta", vlq)
d.FieldUintFn("channel", channel)

decodeProgramChange(d)
})
return

case TypeChannelPressure:
d.FieldStruct("ChannelPressure", decodeChannelPressure)
d.FieldStruct("ChannelPressure", func(d *decode.D) {
d.FieldUintFn("delta", vlq)
d.FieldUintFn("channel", channel)

decodeChannelPressure(d)
})
return

case TypePitchBend:
d.FieldStruct("PitchBend", decodePitchBend)
d.FieldStruct("PitchBend", func(d *decode.D) {
d.FieldUintFn("delta", vlq)
d.FieldUintFn("channel", channel)

decodePitchBend(d)
})
return
}

Expand All @@ -146,82 +190,33 @@ func decodeMIDIEvent(d *decode.D, status uint8) {
}

func decodeNoteOff(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 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 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 {
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 {
b := d.BytesLen(1)

return uint64(b[0] & 0x0f)
})

d.FieldU8("program")
}

func decodeChannelPressure(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 decodePitchBend(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.FieldUintFn("bend", func(d *decode.D) uint64 {
data := d.BytesLen(2)

Expand Down

0 comments on commit b2e71a3

Please sign in to comment.