Dev1an / Swift-Atem

Blackmagic Design Atem network protocol implementation in swift 5.1 using NIO 2
MIT License
58 stars 27 forks source link

Xcode 14 Beta and fatal error when initializing FixedWidthIntegers #21

Open adamtow opened 2 years ago

adamtow commented 2 years ago

Running the Xcode 14 beta, I'm seeing fatal errors when initializing variables from messages sent from the ATEM. Seems like the code here is triggering the error:

init(from slice: ArraySlice<UInt8>) {
    self.init(bigEndian: slice.withUnsafeBufferPointer {
        $0.baseAddress!.withMemoryRebound(to: Self.self, capacity: 1) {$0.pointee}
    })
}

Building the same code using Xcode 13.4.1 does not result in an error when running.

This particular message causes an error to happen is AEBP which returns information when a Fairlight Audio Mixer Source Equalizer Band has changed:

extension Message.Did {
    /// Informs a controller that a source's equalizer settings have changed
    public struct ChangeFairlightMixerSourceEqualizerBand: SerializableMessage {
        public static let title = Message.Title(string: "AEBP")

        public let index: AudioSource
        public let sourceId: Int64
        public let band: UInt8
        public let bandEnabled: Bool
        public let supportedShapes: FairlightEqualizerBandShape
        public let shape: FairlightEqualizerBandShape
        public let supportedFrequencyRanges: FairlightEqualizerFrequencyRange
        public let frequencyRange: FairlightEqualizerFrequencyRange
        public let frequency: UInt32
        public let gain: Int32
        public let qFactor: Int16

        public init(with bytes: ArraySlice<UInt8>) throws {
            self.index = AudioSource(rawValue: UInt16(from: bytes[relative: Position.index]))
            self.sourceId = Int64(from: bytes[relative: Position.sourceId])
            self.band = bytes[relative: Position.band]
            self.bandEnabled = bytes[relative: Position.bandEnabled].firstBit
            self.supportedShapes = FairlightEqualizerBandShape(rawValue: bytes[relative: Position.supportedShapes])
            self.shape = FairlightEqualizerBandShape(rawValue: bytes[relative: Position.shape])
            self.supportedFrequencyRanges = FairlightEqualizerFrequencyRange(rawValue: bytes[relative: Position.supportedFrequencyRanges])
            self.frequencyRange = FairlightEqualizerFrequencyRange(rawValue: bytes[relative: Position.frequencyRange])
            self.frequency = UInt32(from: bytes[relative: Position.frequency])
            self.gain = Int32(from: bytes[relative: Position.gain])
            self.qFactor = Int16(from: bytes[relative: Position.qFactor])
        }

        public init(index: AudioSource, sourceId: Int64, band: UInt8, bandEnabled: Bool, supportedShapes: FairlightEqualizerBandShape, shape: FairlightEqualizerBandShape, supportedFrequencyRanges: FairlightEqualizerFrequencyRange, frequencyRange: FairlightEqualizerFrequencyRange, frequency: UInt32, gain: Int32, qFactor: Int16) {
            self.index = index
            self.sourceId = sourceId
            self.band = band
            self.bandEnabled = bandEnabled
            self.supportedShapes = supportedShapes
            self.shape = shape
            self.supportedFrequencyRanges = supportedFrequencyRanges
            self.frequencyRange = frequencyRange
            self.frequency = frequency
            self.gain = gain
            self.qFactor = qFactor
        }

        public var dataBytes: [UInt8] {
            .init(unsafeUninitializedCapacity: 36) { (buffer, count) in
                buffer.write(index.rawValue.bigEndian, at: Position.index.lowerBound)
                buffer.write(sourceId.bigEndian, at: Position.sourceId.lowerBound)
                buffer[Position.band] = band
                buffer[Position.bandEnabled] = bandEnabled ? 1 : 0
                buffer[Position.supportedShapes] = supportedShapes.rawValue
                buffer[Position.shape] = shape.rawValue
                buffer[Position.supportedFrequencyRanges] = supportedFrequencyRanges.rawValue
                buffer[Position.frequencyRange] = frequencyRange.rawValue
                buffer.write(frequency.bigEndian, at: Position.frequency.lowerBound)
                buffer.write(gain.bigEndian, at: Position.gain.lowerBound)
                buffer.write(qFactor.bigEndian, at: Position.qFactor.lowerBound)
                count = 36
            }
        }

        public var debugDescription: String { return """
Did.ChangeFairlightMixerSourceEqualizerBand {
    index: \(index),
    sourceId: \(sourceId),
    band: \(band),
    bandEnabled: \(bandEnabled),
    supportedShapes: \(supportedShapes),
    shape: \(shape),
    supportedFrequencyRanges: \(supportedFrequencyRanges),
    frequencyRange: \(frequencyRange),
    frequency: \(frequency),
    gain: \(gain),
    qFactor: \(qFactor),
}
"""
        }

        enum Position {
            static let index = 0..<2
            static let sourceId = 8..<16
            static let band = 16
            static let bandEnabled = 17
            static let supportedShapes = 18
            static let shape = 19
            static let supportedFrequencyRanges = 20
            static let frequencyRange = 21
            static let frequency = 24..<28
            static let gain = 28..<32
            static let qFactor = 32..<34
        }
    }
}

and the code to call it out:

import Foundation
import Atem

var enabled: Bool = false

let address: String
if CommandLine.arguments.count > 1 {
    address = CommandLine.arguments[1]
} else {
    print("Enter switcher IP address: ", terminator: "")
    address = readLine() ?? "10.1.0.210"
}
print("Trying to connect to switcher with IP address", address)

let controller = try Controller(ipAddress: address) { connection in
    connection.when { (change: Did.ChangeFairlightMixerSourceEqualizerBand) in
        print(change)
    }

    connection.when { (connected: Config.InitiationComplete) in
        print(connected)
        print("Type 0 or 1 and <enter> to change the Audio Follow Video setting.")
    }

    connection.whenDisconnected = {
        print("Disconnected")
    }
}

while true {
    _ = readLine() ?? "1"
}
Dev1an commented 2 years ago

Interesting. Which beta is it? And may I ask:

adamtow commented 2 years ago

This has been happening since Beta 1 of Xcode 14, and we're on Beta 4. I extracted the contents of the slice where it crashed, but when I put it into a non-network code sample, the array slice was processed correctly (see below):

// This array slice for the AEBP message did not cause a crash
let testArrayWorks: [UInt8] = [0x00, 0x01, 0x74, 0x62, 0x6F, 0x61, 0x72, 0x64, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x33, 0x10, 0x01, 0x01, 0x65, 0x64, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x03, 0x43]

debugPrint("testWorks")
let msg = try Message.Did.ChangeFairlightMixerSourceEqualizerBand(with: testArrayWorks[0..<testArrayWorks.count])
debugPrint(msg.debugDescription)

// This array slice for the AEBP message caused a crash on a real device
let testArrayCrash: [UInt8] = [0x00, 0x01, 0x00, 0x08, 0x01, 0x54, 0xB2, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x01, 0x01, 0x2D, 0x01, 0x0F, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x70, 0x68]

debugPrint("testCrash")
let msg2 = try Message.Did.ChangeFairlightMixerSourceEqualizerBand(with: testArrayCrash[0..<testArrayCrash.count])
debugPrint(msg2.debugDescription)

The error that I'm seeing is NIO-ELT-0-#0 (2): Fatal error It's occurring when trying to process the Int64 value for the sourceId. This is running off of an ATEM Mini Extreme ISO or ATEM Mini Pro.

Stack trace:

#0  0x00000001a56b932c in _swift_runtime_on_report ()
#1  0x00000001a574e8d8 in _swift_stdlib_reportFatalErrorInFile ()
#2  0x00000001a53721b0 in closure #1 in closure #1 in closure #1 in _assertionFailure(_:_:file:line:flags:) ()
#3  0x00000001a5371ef4 in closure #1 in closure #1 in _assertionFailure(_:_:file:line:flags:) ()
#4  0x00000001a5371cec in closure #1 in _assertionFailure(_:_:file:line:flags:) ()
#5  0x00000001a537184c in _assertionFailure(_:_:file:line:flags:) ()
#6  0x00000001a5371b90 in _fatalErrorMessage(_:_:file:line:flags:) ()
#7  0x00000001004804a8 in _swift_se0333_UnsafePointer_withMemoryRebound ()
#8  0x000000010048014c in closure #1 in FixedWidthInteger.init(from:) at /Users/adam/Development/swift-atem-plus/Sources/Atem/Utilities/IntOperators.swift:18
#9  0x000000010048019c in partial apply for closure #1 in FixedWidthInteger.init(from:) ()
#10 0x00000001a53688cc in ArraySlice.withUnsafeBufferPointer<τ_0_0>(_:) ()
#11 0x000000010047ff80 in FixedWidthInteger.init(from:) at /Users/adam/Development/swift-atem-plus/Sources/Atem/Utilities/IntOperators.swift:17
#12 0x00000001002a2650 in Message.Did.ChangeFairlightMixerSourceEqualizerBand.init(with:) at /Users/adam/Development/swift-atem-plus/Sources/Atem/Messages/FairlightAudio+Dynamics.swift:1627
#13 0x00000001002a3a5c in protocol witness for DeserializableMessage.init(with:) in conformance Message.Did.ChangeFairlightMixerSourceEqualizerBand ()
#14 0x00000001001edeec in MessageParser.message(from:) at /Users/adam/Development/swift-atem-plus/Sources/Atem/MessageHandler.swift:91
#15 0x00000001001eea2c in PureMessageHandler.handle(rawMessage:) at /Users/adam/Development/swift-atem-plus/Sources/Atem/MessageHandler.swift:54
#16 0x00000001001eec10 in PureMessageHandler.handle(messages:) at /Users/adam/Development/swift-atem-plus/Sources/Atem/MessageHandler.swift:62
#17 0x00000001001dce24 in ControllerHandler.channelRead(context:data:) at /Users/adam/Development/swift-atem-plus/Sources/Atem/Controller.swift:36
#18 0x0000000100467680 in protocol witness for _ChannelInboundHandler.channelRead(context:data:) in conformance HandlerWithTimer ()
#19 0x00000001000a5a38 in ChannelHandlerContext.invokeChannelRead(_:) at /Users/adam/Library/Developer/Xcode/DerivedData/swift-atem-plus-clgyggiojrmkrdfiftaqreynemgz/SourcePackages/checkouts/swift-nio/Sources/NIOCore/ChannelPipeline.swift:1688
#20 0x00000001000a2450 in ChannelPipeline.fireChannelRead0(_:) at /Users/adam/Library/Developer/Xcode/DerivedData/swift-atem-plus-clgyggiojrmkrdfiftaqreynemgz/SourcePackages/checkouts/swift-nio/Sources/NIOCore/ChannelPipeline.swift:897
#21 0x00000001000a7f38 in ChannelPipeline.SynchronousOperations.fireChannelRead(_:) at /Users/adam/Library/Developer/Xcode/DerivedData/swift-atem-plus-clgyggiojrmkrdfiftaqreynemgz/SourcePackages/checkouts/swift-nio/Sources/NIOCore/ChannelPipeline.swift:1158
#22 0x00000001001c47a0 in DatagramChannel.singleReadFromSocket() at /Users/adam/Library/Developer/Xcode/DerivedData/swift-atem-plus-clgyggiojrmkrdfiftaqreynemgz/SourcePackages/checkouts/swift-nio/Sources/NIOPosix/SocketChannel.swift:593
#23 0x00000001001c38d4 in DatagramChannel.readFromSocket() at /Users/adam/Library/Developer/Xcode/DerivedData/swift-atem-plus-clgyggiojrmkrdfiftaqreynemgz/SourcePackages/checkouts/swift-nio/Sources/NIOPosix/SocketChannel.swift:542
#24 0x0000000100144580 in BaseSocketChannel.readable0() at /Users/adam/Library/Developer/Xcode/DerivedData/swift-atem-plus-clgyggiojrmkrdfiftaqreynemgz/SourcePackages/checkouts/swift-nio/Sources/NIOPosix/BaseSocketChannel.swift:1061
#25 0x000000010014571c in BaseSocketChannel.readable() at /Users/adam/Library/Developer/Xcode/DerivedData/swift-atem-plus-clgyggiojrmkrdfiftaqreynemgz/SourcePackages/checkouts/swift-nio/Sources/NIOPosix/BaseSocketChannel.swift:1045
#26 0x000000010014665c in protocol witness for SelectableChannel.readable() in conformance BaseSocketChannel<τ_0_0> ()
#27 0x00000001001a2708 in SelectableEventLoop.handleEvent<τ_0_0>(_:channel:) at /Users/adam/Library/Developer/Xcode/DerivedData/swift-atem-plus-clgyggiojrmkrdfiftaqreynemgz/SourcePackages/checkouts/swift-nio/Sources/NIOPosix/SelectableEventLoop.swift:394
#28 0x00000001001a3bac in closure #2 in closure #2 in SelectableEventLoop.run() at /Users/adam/Library/Developer/Xcode/DerivedData/swift-atem-plus-clgyggiojrmkrdfiftaqreynemgz/SourcePackages/checkouts/swift-nio/Sources/NIOPosix/SelectableEventLoop.swift:471
#29 0x00000001001a7de8 in partial apply for closure #2 in closure #2 in SelectableEventLoop.run() ()
#30 0x00000001001b5aa4 in Selector.whenReady0(strategy:onLoopBegin:_:) at /Users/adam/Library/Developer/Xcode/DerivedData/swift-atem-plus-clgyggiojrmkrdfiftaqreynemgz/SourcePackages/checkouts/swift-nio/Sources/NIOPosix/SelectorKqueue.swift:258
#31 0x00000001001ae7d4 in Selector.whenReady(strategy:onLoopBegin:_:) at /Users/adam/Library/Developer/Xcode/DerivedData/swift-atem-plus-clgyggiojrmkrdfiftaqreynemgz/SourcePackages/checkouts/swift-nio/Sources/NIOPosix/SelectorGeneric.swift:286
#32 0x00000001001a3874 in closure #2 in SelectableEventLoop.run() at /Users/adam/Library/Developer/Xcode/DerivedData/swift-atem-plus-clgyggiojrmkrdfiftaqreynemgz/SourcePackages/checkouts/swift-nio/Sources/NIOPosix/SelectableEventLoop.swift:461
#33 0x00000001001a6cd0 in partial apply for closure #2 in SelectableEventLoop.run() ()
#34 0x000000010019ea40 in closure #1 in withAutoReleasePool<τ_0_0>(_:) at /Users/adam/Library/Developer/Xcode/DerivedData/swift-atem-plus-clgyggiojrmkrdfiftaqreynemgz/SourcePackages/checkouts/swift-nio/Sources/NIOPosix/SelectableEventLoop.swift:25
#35 0x000000010019eaa4 in partial apply for closure #1 in withAutoReleasePool<τ_0_0>(_:) ()
#36 0x00000001acddead4 in autoreleasepool<τ_0_0>(invoking:) ()
#37 0x000000010019e9d4 in withAutoReleasePool<τ_0_0>(_:) at /Users/adam/Library/Developer/Xcode/DerivedData/swift-atem-plus-clgyggiojrmkrdfiftaqreynemgz/SourcePackages/checkouts/swift-nio/Sources/NIOPosix/SelectableEventLoop.swift:24
#38 0x00000001001a2ab8 in SelectableEventLoop.run() at /Users/adam/Library/Developer/Xcode/DerivedData/swift-atem-plus-clgyggiojrmkrdfiftaqreynemgz/SourcePackages/checkouts/swift-nio/Sources/NIOPosix/SelectableEventLoop.swift:460
#39 0x0000000100174b74 in static MultiThreadedEventLoopGroup.runTheLoop(thread:parentGroup:canEventLoopBeShutdownIndividually:selectorFactory:initializer:_:) at /Users/adam/Library/Developer/Xcode/DerivedData/swift-atem-plus-clgyggiojrmkrdfiftaqreynemgz/SourcePackages/checkouts/swift-nio/Sources/NIOPosix/MultiThreadedEventLoopGroup.swift:89
#40 0x0000000100175100 in closure #1 in static MultiThreadedEventLoopGroup.setupThreadAndEventLoop(name:parentGroup:selectorFactory:initializer:) at /Users/adam/Library/Developer/Xcode/DerivedData/swift-atem-plus-clgyggiojrmkrdfiftaqreynemgz/SourcePackages/checkouts/swift-nio/Sources/NIOPosix/MultiThreadedEventLoopGroup.swift:110
#41 0x000000010017a70c in partial apply for closure #1 in static MultiThreadedEventLoopGroup.setupThreadAndEventLoop(name:parentGroup:selectorFactory:initializer:) ()
#42 0x00000001001d16b4 in thunk for @escaping @callee_guaranteed (@guaranteed NIOThread) -> () ()
#43 0x00000001001d575c in closure #1 in static ThreadOpsPosix.run(handle:args:detachThread:) at /Users/adam/Library/Developer/Xcode/DerivedData/swift-atem-plus-clgyggiojrmkrdfiftaqreynemgz/SourcePackages/checkouts/swift-nio/Sources/NIOPosix/ThreadPosix.swift:105
#44 0x00000001001d5818 in @objc closure #1 in static ThreadOpsPosix.run(handle:args:detachThread:) ()
#45 0x00000001011c1890 in _pthread_start ()
adamtow commented 2 years ago

FWIW, I found this code which is another take on your `init(from slice: ArraySlice' method which does not cause a crash on Xcode 14, but I am not sure how reliable long-term it is (esp. since I'm commenting out the precondition or assert clauses). I'm adding the available check since I'm working on two different versions of the package depending on if its being built for iOS 15 (on Xcode 13.4.1) or iOS 16 (on Xcode 14).

extension FixedWidthInteger {
    init<I>(from iterator: inout I)
    where I: IteratorProtocol, I.Element == UInt8 {
        self = stride(from: 0, to: Self.bitWidth, by: 8).reduce(into: 0) {
            $0 |= Self(truncatingIfNeeded: iterator.next()!) &<< $1
        }
    }

    init<C>(from bytes: C) where C: Collection, C.Element == UInt8 {
        //      precondition(bytes.count == (Self.bitWidth+7)/8)
        //      let bitWidth = (Self.bitWidth+7)/8
        //      debugPrint("Bytes Count: \(bytes.count) Bitwidth: \(bitWidth)")
        //      assert(bytes.count == (Self.bitWidth+7)/8)
        var iter = bytes.reversed().makeIterator()
        self.init(from: &iter)
    }

    init(from slice: ArraySlice<UInt8>) {       
        if #available(iOS 16, OSX 12, *) {
            self.init(from: Array(slice))

        } else {
            self.init(bigEndian: slice.withUnsafeBufferPointer {
                $0.baseAddress!.withMemoryRebound(to: Self.self, capacity: 1) {$0.pointee}
            })
        }
    }

    var bytes: [UInt8] {
        let byteCount = bitWidth >> 3
        return [UInt8](unsafeUninitializedCapacity: byteCount) { (pointer, count) in
            UnsafeMutableRawPointer(pointer.baseAddress!).bindMemory(to: Self.self, capacity: 1).pointee = bigEndian
            count = byteCount
        }
    }
}
adamtow commented 2 years ago

You can run the Simulator target in swift-atem and the sample code above to replicate the error too. The fatal error may occur on a different message like _VMC.

0x10048036c <+324>: bl     0x100480428               ; _swift_se0333_UnsafePointer_withMemoryRebound at <compiler-generated>
**->  0x100480370 <+328>: stur   x21, [x29, #-0x78]**
    0x100480374 <+332>: cbnz   x21, 0x100480398          ; <+368> at IntOperators.swift:40:21
    0x100480378 <+336>: b      0x10048037c               ; <+340> at IntOperators.swift

NIO-ELT-0-#0 (2): Fatal error

Command: Optional("_VMC")
"Getting array slice: [95, 77, 65, 67]"
Swift/arm64e-apple-macos.swiftinterface:23320: Fatal error
2022-07-29 09:45:13.856773-0700 Audio[40176:3315934] Swift/arm64e-apple-macos.swiftinterface:23320: Fatal error
Dev1an commented 2 years ago

Well actually I can't run your code because it has references to a lot of other types that I don't have... But where does FairlightAudio+Dynamics.swift:1627 point to in your Message.Did.ChangeFairlightMixerSourceEqualizerBand.init(with:) intialiser code?

adamtow commented 2 years ago

This should help you out:

public struct FairlightEqualizerBandShape: OptionSet {
    public let rawValue: UInt8
    public init(rawValue: UInt8) {
        self.rawValue = rawValue
    }

    public static let lowShelf = Self(rawValue: 1 << 0)
    public static let lowPass = Self(rawValue: 1 << 1)
    public static let bandPass = Self(rawValue: 1 << 2)
    public static let notch = Self(rawValue: 1 << 3)
    public static let highPass = Self(rawValue: 1 << 4)
    public static let highShelf = Self(rawValue: 1 << 5)

    public static let options: [FairlightEqualizerBandShape] =
        [
            .lowShelf,
            .lowPass,
            .bandPass,
            .notch,
            .highPass,
            .highShelf
        ]
}

public struct FairlightEqualizerFrequencyRange: OptionSet {
    public let rawValue: UInt8
    public init(rawValue: UInt8) {
        self.rawValue = rawValue
    }

    public static let low = Self(rawValue: 1 << 0)
    public static let midLow = Self(rawValue: 1 << 1)
    public static let midHigh = Self(rawValue: 1 << 2)
    public static let high = Self(rawValue: 1 << 3)

    public static let options: [FairlightEqualizerFrequencyRange] =
        [
            .low,
            .midLow,
            .midHigh,
            .high
        ]
}

extension Message.Did {

    /// Informs a controller that a source's equalizer settings have changed
    public struct ChangeFairlightMixerSourceEqualizerBand: SerializableMessage {
        public static let title = Message.Title(string: "AEBP")

        public let index: AudioSource
        public let sourceId: Int64
        public let band: UInt8
        public let bandEnabled: Bool
        public let supportedShapes: FairlightEqualizerBandShape
        public let shape: FairlightEqualizerBandShape
        public let supportedFrequencyRanges: FairlightEqualizerFrequencyRange
        public let frequencyRange: FairlightEqualizerFrequencyRange
        public let frequency: UInt32
        public let gain: Int32
        public let qFactor: Int16

        public init(with bytes: ArraySlice<UInt8>) throws {
            debugPrint(bytes)
            self.index = AudioSource(rawValue: UInt16(from: bytes[relative: Position.index]))
            self.sourceId = Int64(from: bytes[relative: Position.sourceId])
            self.band = bytes[relative: Position.band]
            self.bandEnabled = bytes[relative: Position.bandEnabled].firstBit
            self.supportedShapes = FairlightEqualizerBandShape(rawValue: bytes[relative: Position.supportedShapes])
            self.shape = FairlightEqualizerBandShape(rawValue: bytes[relative: Position.shape])
            self.supportedFrequencyRanges = FairlightEqualizerFrequencyRange(rawValue: bytes[relative: Position.supportedFrequencyRanges])
            self.frequencyRange = FairlightEqualizerFrequencyRange(rawValue: bytes[relative: Position.frequencyRange])
            self.frequency = UInt32(from: bytes[relative: Position.frequency])
            self.gain = Int32(from: bytes[relative: Position.gain])
            self.qFactor = Int16(from: bytes[relative: Position.qFactor])
        }

        public init(index: AudioSource, sourceId: Int64, band: UInt8, bandEnabled: Bool, supportedShapes: FairlightEqualizerBandShape, shape: FairlightEqualizerBandShape, supportedFrequencyRanges: FairlightEqualizerFrequencyRange, frequencyRange: FairlightEqualizerFrequencyRange, frequency: UInt32, gain: Int32, qFactor: Int16) {
            self.index = index
            self.sourceId = sourceId
            self.band = band
            self.bandEnabled = bandEnabled
            self.supportedShapes = supportedShapes
            self.shape = shape
            self.supportedFrequencyRanges = supportedFrequencyRanges
            self.frequencyRange = frequencyRange
            self.frequency = frequency
            self.gain = gain
            self.qFactor = qFactor
        }

        public var dataBytes: [UInt8] {
            .init(unsafeUninitializedCapacity: 36) { (buffer, count) in
                buffer.write(index.rawValue.bigEndian, at: Position.index.lowerBound)
                buffer.write(sourceId.bigEndian, at: Position.sourceId.lowerBound)
                buffer[Position.band] = band
                buffer[Position.bandEnabled] = bandEnabled ? 1 : 0
                buffer[Position.supportedShapes] = supportedShapes.rawValue
                buffer[Position.shape] = shape.rawValue
                buffer[Position.supportedFrequencyRanges] = supportedFrequencyRanges.rawValue
                buffer[Position.frequencyRange] = frequencyRange.rawValue
                buffer.write(frequency.bigEndian, at: Position.frequency.lowerBound)
                buffer.write(gain.bigEndian, at: Position.gain.lowerBound)
                buffer.write(qFactor.bigEndian, at: Position.qFactor.lowerBound)
                count = 36
            }
        }

        public var debugDescription: String { return """
Did.ChangeFairlightMixerSourceEqualizerBand {
    index: \(index),
    sourceId: \(sourceId),
    band: \(band),
    bandEnabled: \(bandEnabled),
    supportedShapes: \(supportedShapes),
    shape: \(shape),
    supportedFrequencyRanges: \(supportedFrequencyRanges),
    frequencyRange: \(frequencyRange),
    frequency: \(frequency),
    gain: \(gain),
    qFactor: \(qFactor),
}
"""
        }

        enum Position {
            static let index = 0..<2
            static let sourceId = 8..<16
            static let band = 16
            static let bandEnabled = 17
            static let supportedShapes = 18
            static let shape = 19
            static let supportedFrequencyRanges = 20
            static let frequencyRange = 21
            static let frequency = 24..<28
            static let gain = 28..<32
            static let qFactor = 32..<34
        }
    }
}
adamtow commented 2 years ago

@Dev1an Were you able to reproduce this on your end?

adamtow commented 2 years ago

There are some comments about changes to unaligned access to data in buffer pointers that might be relevant?

https://developer.apple.com/documentation/Xcode-Release-Notes/xcode-14-release-notes?changes=_2

adamtow commented 1 year ago

Here's another possible workaround that does not result in crashes in my limited testing. From this link:

https://stackoverflow.com/questions/52080844/fatal-error-when-using-withmemoryrebound-in-ios-swift

init(from slice: ArraySlice<UInt8>) {
        self.init(bigEndian: slice.withUnsafeBufferPointer {
            let uint = UnsafeRawBufferPointer($0).bindMemory(to: Self.self)

            return uint.baseAddress!.pointee
        })
}
iosmoon38 commented 1 year ago

@Dev1an, I am facing the same issue. Any plan to fix it in the upcoming release? @adamtow. the solution works for me but every time I need to change that init method when package reload.

Note:- I am using Xcode 14.2

adamtow commented 1 year ago

@iosmoon38 you can create a fork of this repo and just include the fix above. Then, the code won't get replaced everything you update the package.

iosmoon38 commented 1 year ago

@adamtow, Thanks for giving me solution. fork is worked for me.

iOS-38 commented 5 months ago

@Dev1an, is there any chance to fix this issue in the upcoming release?