Skip to content

Commit

Permalink
Merge pull request #38 from orchetect/dev
Browse files Browse the repository at this point in the history
Stability improvements
  • Loading branch information
orchetect authored Sep 19, 2021
2 parents 8d9cc7b + 293caa3 commit ca01e68
Show file tree
Hide file tree
Showing 26 changed files with 861 additions and 328 deletions.
31 changes: 31 additions & 0 deletions Sources/MIDIKit/Common/Types/UMPWord.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// UMPWord.swift
// MIDIKit • https://github.com/orchetect/MIDIKit
//

extension MIDI {

/// Universal MIDI Packet Word: Type representing four 8-bit bytes
public typealias UMPWord = UInt32

}

extension MIDI.UMPWord {

/// Internal: Pack a UInt32 with four 8-bit bytes.
@inline(__always) internal init(
_ byte0: MIDI.Byte,
_ byte1: MIDI.Byte,
_ byte2: MIDI.Byte,
_ byte3: MIDI.Byte
) {

self =
(Self(byte0) << 24) +
(Self(byte1) << 16) +
(Self(byte2) << 8) +
Self(byte3)

}

}
202 changes: 128 additions & 74 deletions Sources/MIDIKit/Events/Event/Event rawBytes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ extension MIDI.Event {
let bytePair = value.bytePair
return [0xE0 + channel.uInt8Value, bytePair.lsb, bytePair.msb]


// ----------------------
// MARK: System Exclusive
// ----------------------
Expand All @@ -85,6 +86,7 @@ extension MIDI.Event {
+ data
+ [0xF7]


// -------------------
// MARK: System Common
// -------------------
Expand Down Expand Up @@ -113,6 +115,7 @@ extension MIDI.Event {

return [0xF6]


// ----------------------
// MARK: System Real Time
// ----------------------
Expand Down Expand Up @@ -149,7 +152,7 @@ extension MIDI.Event {

extension MIDI.Event {

public var umpRawBytes: [MIDI.Byte] {
public var umpRawWords: [MIDI.UMPWord] {

#warning("> this is incomplete and needs testing; for the time being MIDIKit will only use MIDI 1.0 event raw bytes")

Expand Down Expand Up @@ -200,10 +203,12 @@ extension MIDI.Event {

let mtAndGroup = (messageType.rawValue.uInt8Value << 4) + group

return [mtAndGroup,
0x90 + channel.uInt8Value,
note.uInt8Value,
velocity.uInt8Value]
let word = MIDI.UMPWord(mtAndGroup,
0x90 + channel.uInt8Value,
note.uInt8Value,
velocity.uInt8Value)

return [word]

case .noteOff(note: let note,
velocity: let velocity,
Expand All @@ -212,10 +217,12 @@ extension MIDI.Event {

let mtAndGroup = (messageType.rawValue.uInt8Value << 4) + group

return [mtAndGroup,
0x80 + channel.uInt8Value,
note.uInt8Value,
velocity.uInt8Value]
let word = MIDI.UMPWord(mtAndGroup,
0x80 + channel.uInt8Value,
note.uInt8Value,
velocity.uInt8Value)

return [word]

case .polyAftertouch(note: let note,
pressure: let pressure,
Expand All @@ -224,10 +231,12 @@ extension MIDI.Event {

let mtAndGroup = (messageType.rawValue.uInt8Value << 4) + group

return [mtAndGroup,
0xA0 + channel.uInt8Value,
note.uInt8Value,
pressure.uInt8Value]
let word = MIDI.UMPWord(mtAndGroup,
0xA0 + channel.uInt8Value,
note.uInt8Value,
pressure.uInt8Value)

return [word]

case .cc(controller: let controller,
value: let value,
Expand All @@ -236,32 +245,38 @@ extension MIDI.Event {

let mtAndGroup = (messageType.rawValue.uInt8Value << 4) + group

return [mtAndGroup,
0xB0 + channel.uInt8Value,
controller.uInt8Value,
value.uInt8Value]
let word = MIDI.UMPWord(mtAndGroup,
0xB0 + channel.uInt8Value,
controller.uInt8Value,
value.uInt8Value)

return [word]

case .programChange(program: let program,
channel: let channel,
group: let group):

let mtAndGroup = (messageType.rawValue.uInt8Value << 4) + group

return [mtAndGroup,
0xC0 + channel.uInt8Value,
program.uInt8Value,
0x00] // pad an empty byte to fill 4 bytes
let word = MIDI.UMPWord(mtAndGroup,
0xC0 + channel.uInt8Value,
program.uInt8Value,
0x00) // pad an empty byte to fill 4 bytes

return [word]

case .chanAftertouch(pressure: let pressure,
channel: let channel,
group: let group):

let mtAndGroup = (messageType.rawValue.uInt8Value << 4) + group

return [mtAndGroup,
0xD0 + channel.uInt8Value,
pressure.uInt8Value,
0x00] // pad an empty byte to fill 4 bytes
let word = MIDI.UMPWord(mtAndGroup,
0xD0 + channel.uInt8Value,
pressure.uInt8Value,
0x00) // pad an empty byte to fill 4 bytes

return [word]

case .pitchBend(value: let value,
channel: let channel,
Expand All @@ -271,10 +286,13 @@ extension MIDI.Event {

let bytePair = value.bytePair

return [mtAndGroup,
0xE0 + channel.uInt8Value,
bytePair.lsb,
bytePair.msb]
let word = MIDI.UMPWord(mtAndGroup,
0xE0 + channel.uInt8Value,
bytePair.lsb,
bytePair.msb)

return [word]


// ----------------------
// MARK: System Exclusive
Expand All @@ -288,7 +306,11 @@ extension MIDI.Event {

let mtAndGroup = (messageType.rawValue.uInt8Value << 4) + group

return [mtAndGroup, 0xF0] + manufacturer.bytes + data + [0xF7]
_ = manufacturer
_ = data
_ = group

return []

case .sysExUniversal(universalType: let universalType,
deviceID: let deviceID,
Expand All @@ -301,14 +323,15 @@ extension MIDI.Event {

let mtAndGroup = (messageType.rawValue.uInt8Value << 4) + group

return [mtAndGroup,
0xF0,
MIDI.Byte(universalType.rawValue),
deviceID.uInt8Value,
subID1.uInt8Value,
subID2.uInt8Value]
+ data
+ [0xF7]
_ = universalType
_ = deviceID
_ = subID1
_ = subID2
_ = data
_ = group

return []


// -------------------
// MARK: System Common
Expand All @@ -319,10 +342,12 @@ extension MIDI.Event {

let mtAndGroup = (messageType.rawValue.uInt8Value << 4) + group

return [mtAndGroup,
0xF1,
byte,
0x00] // pad an empty byte to fill 4 bytes
let word = MIDI.UMPWord(mtAndGroup,
0xF1,
byte,
0x00) // pad an empty byte to fill 4 bytes

return [word]

case .songPositionPointer(midiBeat: let midiBeat,
group: let group):
Expand All @@ -331,36 +356,47 @@ extension MIDI.Event {

let bytePair = midiBeat.bytePair

return [mtAndGroup,
0xF2,
bytePair.lsb,
bytePair.msb]
let word = MIDI.UMPWord(mtAndGroup,
0xF2,
bytePair.lsb,
bytePair.msb)

return [word]

case .songSelect(number: let number,
group: let group):

let mtAndGroup = (messageType.rawValue.uInt8Value << 4) + group

return [mtAndGroup,
0xF3,
number.uInt8Value,
0x00] // pad an empty byte to fill 4 bytes
let word = MIDI.UMPWord(mtAndGroup,
0xF3,
number.uInt8Value,
0x00) // pad an empty byte to fill 4 bytes

return [word]

case .unofficialBusSelect(group: let group):

let mtAndGroup = (messageType.rawValue.uInt8Value << 4) + group

return [mtAndGroup,
0xF5,
0x00, 0x00] // pad empty bytes to fill 4 bytes
let word = MIDI.UMPWord(mtAndGroup,
0xF5,
0x00, // pad empty bytes to fill 4 bytes
0x00) // pad empty bytes to fill 4 bytes

return [word]

case .tuneRequest(group: let group):

let mtAndGroup = (messageType.rawValue.uInt8Value << 4) + group

return [mtAndGroup,
0xF6,
0x00, 0x00] // pad empty bytes to fill 4 bytes
let word = MIDI.UMPWord(mtAndGroup,
0xF6,
0x00, // pad empty bytes to fill 4 bytes
0x00) // pad empty bytes to fill 4 bytes

return [word]


// ----------------------
// MARK: System Real Time
Expand All @@ -370,49 +406,67 @@ extension MIDI.Event {

let mtAndGroup = (messageType.rawValue.uInt8Value << 4) + group

return [mtAndGroup,
0xF8,
0x00, 0x00] // pad empty bytes to fill 4 bytes
let word = MIDI.UMPWord(mtAndGroup,
0xF8,
0x00, // pad empty bytes to fill 4 bytes
0x00) // pad empty bytes to fill 4 bytes

return [word]

case .start(group: let group):

let mtAndGroup = (messageType.rawValue.uInt8Value << 4) + group

return [mtAndGroup,
0xFA,
0x00, 0x00] // pad empty bytes to fill 4 bytes
let word = MIDI.UMPWord(mtAndGroup,
0xFA,
0x00, // pad empty bytes to fill 4 bytes
0x00) // pad empty bytes to fill 4 bytes

return [word]

case .continue(group: let group):

let mtAndGroup = (messageType.rawValue.uInt8Value << 4) + group

return [mtAndGroup,
0xFB,
0x00, 0x00] // pad empty bytes to fill 4 bytes
let word = MIDI.UMPWord(mtAndGroup,
0xFB,
0x00, // pad empty bytes to fill 4 bytes
0x00) // pad empty bytes to fill 4 bytes

return [word]

case .stop(group: let group):

let mtAndGroup = (messageType.rawValue.uInt8Value << 4) + group

return [mtAndGroup,
0xFC,
0x00, 0x00] // pad empty bytes to fill 4 bytes
let word = MIDI.UMPWord(mtAndGroup,
0xFC,
0x00, // pad empty bytes to fill 4 bytes
0x00) // pad empty bytes to fill 4 bytes

return [word]

case .activeSensing(group: let group):

let mtAndGroup = (messageType.rawValue.uInt8Value << 4) + group

return [mtAndGroup,
0xFE,
0x00, 0x00] // pad empty bytes to fill 4 bytes
let word = MIDI.UMPWord(mtAndGroup,
0xFE,
0x00, // pad empty bytes to fill 4 bytes
0x00) // pad empty bytes to fill 4 bytes

return [word]

case .systemReset(group: let group):

let mtAndGroup = (messageType.rawValue.uInt8Value << 4) + group

return [mtAndGroup,
0xFF,
0x00, 0x00] // pad empty bytes to fill 4 bytes
let word = MIDI.UMPWord(mtAndGroup,
0xFF,
0x00, // pad empty bytes to fill 4 bytes
0x00) // pad empty bytes to fill 4 bytes

return [word]

}

Expand Down
1 change: 1 addition & 0 deletions Sources/MIDIKit/IO/API/APIVersion.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ extension MIDI.IO.APIVersion {
public static func bestForPlatform() -> Self {

if #available(macOS 11, iOS 14, macCatalyst 14, tvOS 14, watchOS 7, *) {
#warning("> switch to new API in future")
// return legacy for now, since new API is buggy;
// in future, this should return .newCoreMIDI when new API is more stable
return .legacyCoreMIDI
Expand Down
Loading

0 comments on commit ca01e68

Please sign in to comment.