Initialization Catch-22?

Hi All.

I’m trying to implement the AudioQueue example from Apple in Swift, and keep it as Swifty as I can. I’ve run into a problem where I have a let ivar for the AudioQueue, but the only way to initialize that let ivar is to pass a block to the function that creates the AudioQueue. I get the error, "Variable 'self.mQueue' used before being initialized”. Is there any way to get around this catch?

Thanks!

-Kenny

The code follows.

———8<————8<————
class PDAudioPlayer {
    static let kNumberBuffers :Int = 3 // 1
    //var mDataFormat:AudioStreamBasicDescription // 2
    let mQueue :AudioQueueRef // 3
    //var mBuffers :[AudioQueueBufferRef] // 4
    //var mAudioFile :AudioFileID? // 5
    var bufferByteSize :UInt32? // 6
    var mCurrentPacket :Int64? // 7
    var mNumPacketsToRead :UInt32? // 8
    var mPacketDescs :UnsafePointer<AudioStreamPacketDescription>? // 9
    var mIsRunning: Bool = false // 10
    
    let dispatchQueue :DispatchQueue
    let source :PDFileAudioSource
    var audioBuffers :[PDAudioBuffer]
    
    init?(source:PDFileAudioSource) {
        self.source = source
        self.dispatchQueue = DispatchQueue(label:"AudioPlayer", qos:.default, attributes:, autoreleaseFrequency:.workItem, target:nil)
        self.audioBuffers = [PDAudioBuffer]()

        var tempAudioQueue :AudioQueueRef?
        var dataFormat = source.mDataFormat
        let status = AudioQueueNewOutputWithDispatchQueue(&tempAudioQueue, &dataFormat, 0, self.dispatchQueue) { [weak self] (queue, buffer) in // ERROR on this line
            guard let this = self else {
                return // block
            }
            guard let audioBuffer = this.audioBufferForAudioQueueBuffer(aqBuffer:buffer) else {
                return // block
            }
            this.source.fillBuffer(audioBuffer)
        }
        if status != 0 {
            return nil
        }
        guard let audioQueue = tempAudioQueue else {
            return nil
        }
        self.mQueue = audioQueue
    }

    private func audioBufferForAudioQueueBuffer(aqBuffer:AudioQueueBufferRef) -> PDAudioBuffer? {
        for buffer in self.audioBuffers {
            if buffer.audioQueueBuffer == aqBuffer {
                return buffer
            }
        }
        return nil
    }
}

I’m trying to implement the AudioQueue example from Apple in Swift, and keep it as Swifty as I can. I’ve run into a problem where I have a let ivar for the AudioQueue, but the only way to initialize that let ivar is to pass a block to the function that creates the AudioQueue. I get the error, "Variable 'self.mQueue' used before being initialized”. Is there any way to get around this catch?

The compiler cannot guarantee that the code running inside your block does not try to use mQueue before it is initialized. Swift strictly enforces its initialization rules, so the compiler rejects your code.

One common solution is to change mQueue into an implicitly-unwrapped optional var. The compiler still can't tell if your block object uses mQueue before it is initialized, but if it does it will get a well-defined runtime error due to the nil IUO. That well-defined error is sufficient to pacify the initialization rules.

Another solution might be to divide your data into two different types. It looks like the block object only needs to access self.audioBuffers and self.source. You might be able to box those two fields into a separate class type and have the block object capture a reference to that object only. Then the initialization order is simple enough for the compiler to understand:
1. PDAudioPlayer.init() initializes a source+audioBuffers object.
2. PDAudioPlayer.init() calls AudioQueueNewOutputWithDispatchQueue(), passing it a block that captures a reference to the fully-initialized source+audioBuffers object.
3. PDAudioPlayer.init() uses the results of #1 and #2 to complete its own initialization or return nil.
This adds an extra allocation and extra indirection to each PDAudioPlayer object, but as long as you don't have millions of these things the performance difference should be negligible.

···

On Sep 25, 2017, at 6:12 PM, Kenny Leung via swift-users <swift-users@swift.org> wrote:

———8<————8<————
class PDAudioPlayer {
    static let kNumberBuffers :Int = 3 // 1
    //var mDataFormat:AudioStreamBasicDescription // 2
    let mQueue :AudioQueueRef // 3
    //var mBuffers :[AudioQueueBufferRef] // 4
    //var mAudioFile :AudioFileID? // 5
    var bufferByteSize :UInt32? // 6
    var mCurrentPacket :Int64? // 7
    var mNumPacketsToRead :UInt32? // 8
    var mPacketDescs :UnsafePointer<AudioStreamPacketDescription>? // 9
    var mIsRunning: Bool = false // 10
    
    let dispatchQueue :DispatchQueue
    let source :PDFileAudioSource
    var audioBuffers :[PDAudioBuffer]
    
    init?(source:PDFileAudioSource) {
        self.source = source
        self.dispatchQueue = DispatchQueue(label:"AudioPlayer", qos:.default, attributes:, autoreleaseFrequency:.workItem, target:nil)
        self.audioBuffers = [PDAudioBuffer]()

        var tempAudioQueue :AudioQueueRef?
        var dataFormat = source.mDataFormat
        let status = AudioQueueNewOutputWithDispatchQueue(&tempAudioQueue, &dataFormat, 0, self.dispatchQueue) { [weak self] (queue, buffer) in // ERROR on this line
            guard let this = self else {
                return // block
            }
            guard let audioBuffer = this.audioBufferForAudioQueueBuffer(aqBuffer:buffer) else {
                return // block
            }
            this.source.fillBuffer(audioBuffer)
        }
        if status != 0 {
            return nil
        }
        guard let audioQueue = tempAudioQueue else {
            return nil
        }
        self.mQueue = audioQueue
    }

    private func audioBufferForAudioQueueBuffer(aqBuffer:AudioQueueBufferRef) -> PDAudioBuffer? {
        for buffer in self.audioBuffers {
            if buffer.audioQueueBuffer == aqBuffer {
                return buffer
            }
        }
        return nil
    }
}

Hi Kenny,

You could use a lazy var and initialise it with a closure.

class PDAudioPlayer {

    //Would be created lazily when first invoked
    lazy var mQueue : AudioQueueRef = {

        //create an audioQueue and return that instance
        return audioQueue
    }()
}

Thanks and regards,
Muthu

···

On 26 Sep 2017, at 9:12 AM, Kenny Leung via swift-users <swift-users@swift.org> wrote:

Hi All.

I’m trying to implement the AudioQueue example from Apple in Swift, and keep it as Swifty as I can. I’ve run into a problem where I have a let ivar for the AudioQueue, but the only way to initialize that let ivar is to pass a block to the function that creates the AudioQueue. I get the error, "Variable 'self.mQueue' used before being initialized”. Is there any way to get around this catch?

Thanks!

-Kenny

The code follows.

———8<————8<————
class PDAudioPlayer {
    static let kNumberBuffers :Int = 3 // 1
    //var mDataFormat:AudioStreamBasicDescription // 2
    let mQueue :AudioQueueRef // 3
    //var mBuffers :[AudioQueueBufferRef] // 4
    //var mAudioFile :AudioFileID? // 5
    var bufferByteSize :UInt32? // 6
    var mCurrentPacket :Int64? // 7
    var mNumPacketsToRead :UInt32? // 8
    var mPacketDescs :UnsafePointer<AudioStreamPacketDescription>? // 9
    var mIsRunning: Bool = false // 10
    
    let dispatchQueue :DispatchQueue
    let source :PDFileAudioSource
    var audioBuffers :[PDAudioBuffer]
    
    init?(source:PDFileAudioSource) {
        self.source = source
        self.dispatchQueue = DispatchQueue(label:"AudioPlayer", qos:.default, attributes:, autoreleaseFrequency:.workItem, target:nil)
        self.audioBuffers = [PDAudioBuffer]()

        var tempAudioQueue :AudioQueueRef?
        var dataFormat = source.mDataFormat
        let status = AudioQueueNewOutputWithDispatchQueue(&tempAudioQueue, &dataFormat, 0, self.dispatchQueue) { [weak self] (queue, buffer) in // ERROR on this line
            guard let this = self else {
                return // block
            }
            guard let audioBuffer = this.audioBufferForAudioQueueBuffer(aqBuffer:buffer) else {
                return // block
            }
            this.source.fillBuffer(audioBuffer)
        }
        if status != 0 {
            return nil
        }
        guard let audioQueue = tempAudioQueue else {
            return nil
        }
        self.mQueue = audioQueue
    }

    private func audioBufferForAudioQueueBuffer(aqBuffer:AudioQueueBufferRef) -> PDAudioBuffer? {
        for buffer in self.audioBuffers {
            if buffer.audioQueueBuffer == aqBuffer {
                return buffer
            }
        }
        return nil
    }
}

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Hi Muthu.

Thanks for the suggestion.

I don’t want to do that because failure to create the AudioQueue should mean failure to create the AudioPlayer itself.

-Kenny

···

On Sep 25, 2017, at 6:33 PM, somu subscribe <somu.subscribe@gmail.com> wrote:

Hi Kenny,

You could use a lazy var and initialise it with a closure.

class PDAudioPlayer {

    //Would be created lazily when first invoked
    lazy var mQueue : AudioQueueRef = {

        //create an audioQueue and return that instance
        return audioQueue
    }()
}

Thanks and regards,
Muthu

On 26 Sep 2017, at 9:12 AM, Kenny Leung via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

Hi All.

I’m trying to implement the AudioQueue example from Apple in Swift, and keep it as Swifty as I can. I’ve run into a problem where I have a let ivar for the AudioQueue, but the only way to initialize that let ivar is to pass a block to the function that creates the AudioQueue. I get the error, "Variable 'self.mQueue' used before being initialized”. Is there any way to get around this catch?

Thanks!

-Kenny

The code follows.

———8<————8<————
class PDAudioPlayer {
    static let kNumberBuffers :Int = 3 // 1
    //var mDataFormat:AudioStreamBasicDescription // 2
    let mQueue :AudioQueueRef // 3
    //var mBuffers :[AudioQueueBufferRef] // 4
    //var mAudioFile :AudioFileID? // 5
    var bufferByteSize :UInt32? // 6
    var mCurrentPacket :Int64? // 7
    var mNumPacketsToRead :UInt32? // 8
    var mPacketDescs :UnsafePointer<AudioStreamPacketDescription>? // 9
    var mIsRunning: Bool = false // 10
    
    let dispatchQueue :DispatchQueue
    let source :PDFileAudioSource
    var audioBuffers :[PDAudioBuffer]
    
    init?(source:PDFileAudioSource) {
        self.source = source
        self.dispatchQueue = DispatchQueue(label:"AudioPlayer", qos:.default, attributes:, autoreleaseFrequency:.workItem, target:nil)
        self.audioBuffers = [PDAudioBuffer]()

        var tempAudioQueue :AudioQueueRef?
        var dataFormat = source.mDataFormat
        let status = AudioQueueNewOutputWithDispatchQueue(&tempAudioQueue, &dataFormat, 0, self.dispatchQueue) { [weak self] (queue, buffer) in // ERROR on this line
            guard let this = self else {
                return // block
            }
            guard let audioBuffer = this.audioBufferForAudioQueueBuffer(aqBuffer:buffer) else {
                return // block
            }
            this.source.fillBuffer(audioBuffer)
        }
        if status != 0 {
            return nil
        }
        guard let audioQueue = tempAudioQueue else {
            return nil
        }
        self.mQueue = audioQueue
    }

    private func audioBufferForAudioQueueBuffer(aqBuffer:AudioQueueBufferRef) -> PDAudioBuffer? {
        for buffer in self.audioBuffers {
            if buffer.audioQueueBuffer == aqBuffer {
                return buffer
            }
        }
        return nil
    }
}

_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users

Hi Howard.

Yes, this would make it compile, but it still would not solve the issues that make it wrong in my mind:

1. I would have to make it a var, but it should not be mutable.

2. It’s not optional. Without it, the PDAudioPlayer class could not function.

Of course, this is just being stubbornly pedantic about the code, but the whole point of this project is an exercise in pedantry.

-Kenny

···

On Sep 25, 2017, at 10:35 PM, Howard Lovatt <howard.lovatt@gmail.com> wrote:

You could try making mQueue a force unwrapped optional or initialize it to a failed queue before overwriting on last line of `init`.

On Tue, 26 Sep 2017 at 11:39 am, Kenny Leung via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
Hi Muthu.

Thanks for the suggestion.

I don’t want to do that because failure to create the AudioQueue should mean failure to create the AudioPlayer itself.

-Kenny

On Sep 25, 2017, at 6:33 PM, somu subscribe <somu.subscribe@gmail.com <mailto:somu.subscribe@gmail.com>> wrote:

Hi Kenny,

You could use a lazy var and initialise it with a closure.

class PDAudioPlayer {

    //Would be created lazily when first invoked
    lazy var mQueue : AudioQueueRef = {

        //create an audioQueue and return that instance
        return audioQueue
    }()
}

Thanks and regards,
Muthu

On 26 Sep 2017, at 9:12 AM, Kenny Leung via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

Hi All.

I’m trying to implement the AudioQueue example from Apple in Swift, and keep it as Swifty as I can. I’ve run into a problem where I have a let ivar for the AudioQueue, but the only way to initialize that let ivar is to pass a block to the function that creates the AudioQueue. I get the error, "Variable 'self.mQueue' used before being initialized”. Is there any way to get around this catch?

Thanks!

-Kenny

The code follows.

———8<————8<————
class PDAudioPlayer {
    static let kNumberBuffers :Int = 3 // 1
    //var mDataFormat:AudioStreamBasicDescription // 2
    let mQueue :AudioQueueRef // 3
    //var mBuffers :[AudioQueueBufferRef] // 4
    //var mAudioFile :AudioFileID? // 5
    var bufferByteSize :UInt32? // 6
    var mCurrentPacket :Int64? // 7
    var mNumPacketsToRead :UInt32? // 8
    var mPacketDescs :UnsafePointer<AudioStreamPacketDescription>? // 9
    var mIsRunning: Bool = false // 10
    
    let dispatchQueue :DispatchQueue
    let source :PDFileAudioSource
    var audioBuffers :[PDAudioBuffer]
    
    init?(source:PDFileAudioSource) {
        self.source = source
        self.dispatchQueue = DispatchQueue(label:"AudioPlayer", qos:.default, attributes:, autoreleaseFrequency:.workItem, target:nil)
        self.audioBuffers = [PDAudioBuffer]()

        var tempAudioQueue :AudioQueueRef?
        var dataFormat = source.mDataFormat
        let status = AudioQueueNewOutputWithDispatchQueue(&tempAudioQueue, &dataFormat, 0, self.dispatchQueue) { [weak self] (queue, buffer) in // ERROR on this line
            guard let this = self else {
                return // block
            }
            guard let audioBuffer = this.audioBufferForAudioQueueBuffer(aqBuffer:buffer) else {
                return // block
            }
            this.source.fillBuffer(audioBuffer)
        }
        if status != 0 {
            return nil
        }
        guard let audioQueue = tempAudioQueue else {
            return nil
        }
        self.mQueue = audioQueue
    }

    private func audioBufferForAudioQueueBuffer(aqBuffer:AudioQueueBufferRef) -> PDAudioBuffer? {
        for buffer in self.audioBuffers {
            if buffer.audioQueueBuffer == aqBuffer {
                return buffer
            }
        }
        return nil
    }
}

_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users
--
-- Howard.

I know were you are coming from, but:

  1. In other languages it would be the equivalent of an force unwrapped
optional and you could get a NullPointerException (or worse - core dump).
Using a force unwrapped optional just levels the playing field!

  2. You could make it private(set) which would de-risk the var bit.

  3. See below.

class AssignOnce<T: AnyObject> {
    weak var value: T? = nil { // Use a weak var to avoid a retain cycle.
        willSet {
            guard value == nil else {
                fatalError("Can only be set once.")
            }
        }
    }
}
class InitSelfDependency {
    let dependsUponSelf = AssignOnce<InitSelfDependency>()
    init() {
        dependsUponSelf.value = self
    }
}
let i = InitSelfDependency()
i.dependsUponSelf

···

On Tue, 26 Sep 2017 at 4:44 pm, Kenny Leung via swift-users < swift-users@swift.org> wrote:

Hi Howard.

Yes, this would make it compile, but it still would not solve the issues
that make it wrong in my mind:

1. I would have to make it a var, but it should not be mutable.

2. It’s not optional. Without it, the PDAudioPlayer class could not
function.

Of course, this is just being stubbornly pedantic about the code, but the
whole point of this project is an exercise in pedantry.

-Kenny

On Sep 25, 2017, at 10:35 PM, Howard Lovatt <howard.lovatt@gmail.com> > wrote:

You could try making mQueue a force unwrapped optional or initialize it to
a failed queue before overwriting on last line of `init`.

On Tue, 26 Sep 2017 at 11:39 am, Kenny Leung via swift-users < > swift-users@swift.org> wrote:

Hi Muthu.

Thanks for the suggestion.

I don’t want to do that because failure to create the AudioQueue should
mean failure to create the AudioPlayer itself.

-Kenny

On Sep 25, 2017, at 6:33 PM, somu subscribe <somu.subscribe@gmail.com> >> wrote:

Hi Kenny,

You could use a lazy var and initialise it with a closure.

class PDAudioPlayer {

    //Would be created lazily when first invoked
    lazy var mQueue : AudioQueueRef = {

        //create an audioQueue and return that instance
        return audioQueue
    }()
}

Thanks and regards,
Muthu

On 26 Sep 2017, at 9:12 AM, Kenny Leung via swift-users < >> swift-users@swift.org> wrote:

Hi All.

I’m trying to implement the AudioQueue example from Apple in Swift, and
keep it as Swifty as I can. I’ve run into a problem where I have a let ivar
for the AudioQueue, but the only way to initialize that let ivar is to pass
a block to the function that creates the AudioQueue. I get the error,
"Variable 'self.mQueue' used before being initialized”. Is there any way to
get around this catch?

Thanks!

-Kenny

The code follows.

———8<————8<————
class PDAudioPlayer {
    static let kNumberBuffers :Int = 3 // 1
    //var mDataFormat:AudioStreamBasicDescription //
2
    let mQueue :AudioQueueRef // 3
    //var mBuffers :[AudioQueueBufferRef] // 4
    //var mAudioFile :AudioFileID? //
5
    var bufferByteSize :UInt32? // 6
    var mCurrentPacket :Int64? // 7
    var mNumPacketsToRead :UInt32? // 8
    var mPacketDescs :UnsafePointer<AudioStreamPacketDescription>? // 9
    var mIsRunning: Bool = false // 10

    let dispatchQueue :DispatchQueue
    let source :PDFileAudioSource
    var audioBuffers :[PDAudioBuffer]

    init?(source:PDFileAudioSource) {
        self.source = source
        self.dispatchQueue = DispatchQueue(label:"AudioPlayer", qos:.
default, attributes:, autoreleaseFrequency:.workItem, target:nil)
        self.audioBuffers = [PDAudioBuffer]()

        var tempAudioQueue :AudioQueueRef?
        var dataFormat = source.mDataFormat
        let status = AudioQueueNewOutputWithDispatchQueue(&tempAudioQueue,
&dataFormat, 0, self.dispatchQueue) { [weak self] (queue, buffer) in
// ERROR on this line
            guard let this = self else {
                return // block
            }
            guard let audioBuffer = this.audioBufferForAudioQueueBuffer(aqBuffer:buffer)
else {
                return // block
            }
            this.source.fillBuffer(audioBuffer)
        }
        if status != 0 {
            return nil
        }
        guard let audioQueue = tempAudioQueue else {
            return nil
        }
        self.mQueue = audioQueue
    }

    private func audioBufferForAudioQueueBuffer(aqBuffer:
AudioQueueBufferRef) -> PDAudioBuffer? {
        for buffer in self.audioBuffers {
            if buffer.audioQueueBuffer == aqBuffer {
                return buffer
            }
        }
        return nil
    }
}

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

--
-- Howard.

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

--
-- Howard.

Hi Greg.

Thanks for the insight. In this case, I think I’m saved because I don’t actually need to capture self in the block. I guess I was just too far along on my train to realize that. I think this will work and it will keep the code simple and neat.

I guess we'll see as I complete this project whether I really have everything I need for the callback block. I may have to resort to one of the other measures you all have suggested.

Thanks again!

-Kenny

···

On Sep 26, 2017, at 12:40 AM, Greg Parker <gparker@apple.com> wrote:

On Sep 25, 2017, at 6:12 PM, Kenny Leung via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

I’m trying to implement the AudioQueue example from Apple in Swift, and keep it as Swifty as I can. I’ve run into a problem where I have a let ivar for the AudioQueue, but the only way to initialize that let ivar is to pass a block to the function that creates the AudioQueue. I get the error, "Variable 'self.mQueue' used before being initialized”. Is there any way to get around this catch?

The compiler cannot guarantee that the code running inside your block does not try to use mQueue before it is initialized. Swift strictly enforces its initialization rules, so the compiler rejects your code.

One common solution is to change mQueue into an implicitly-unwrapped optional var. The compiler still can't tell if your block object uses mQueue before it is initialized, but if it does it will get a well-defined runtime error due to the nil IUO. That well-defined error is sufficient to pacify the initialization rules.

Another solution might be to divide your data into two different types. It looks like the block object only needs to access self.audioBuffers and self.source. You might be able to box those two fields into a separate class type and have the block object capture a reference to that object only. Then the initialization order is simple enough for the compiler to understand:
1. PDAudioPlayer.init() initializes a source+audioBuffers object.
2. PDAudioPlayer.init() calls AudioQueueNewOutputWithDispatchQueue(), passing it a block that captures a reference to the fully-initialized source+audioBuffers object.
3. PDAudioPlayer.init() uses the results of #1 and #2 to complete its own initialization or return nil.
This adds an extra allocation and extra indirection to each PDAudioPlayer object, but as long as you don't have millions of these things the performance difference should be negligible.

———8<————8<————
class PDAudioPlayer {
    static let kNumberBuffers :Int = 3 // 1
    //var mDataFormat:AudioStreamBasicDescription // 2
    let mQueue :AudioQueueRef // 3
    //var mBuffers :[AudioQueueBufferRef] // 4
    //var mAudioFile :AudioFileID? // 5
    var bufferByteSize :UInt32? // 6
    var mCurrentPacket :Int64? // 7
    var mNumPacketsToRead :UInt32? // 8
    var mPacketDescs :UnsafePointer<AudioStreamPacketDescription>? // 9
    var mIsRunning: Bool = false // 10
    
    let dispatchQueue :DispatchQueue
    let source :PDFileAudioSource
    var audioBuffers :[PDAudioBuffer]
    
    init?(source:PDFileAudioSource) {
        self.source = source
        self.dispatchQueue = DispatchQueue(label:"AudioPlayer", qos:.default, attributes:, autoreleaseFrequency:.workItem, target:nil)
        self.audioBuffers = [PDAudioBuffer]()

        var tempAudioQueue :AudioQueueRef?
        var dataFormat = source.mDataFormat
        let status = AudioQueueNewOutputWithDispatchQueue(&tempAudioQueue, &dataFormat, 0, self.dispatchQueue) { [weak self] (queue, buffer) in // ERROR on this line
            guard let this = self else {
                return // block
            }
            guard let audioBuffer = this.audioBufferForAudioQueueBuffer(aqBuffer:buffer) else {
                return // block
            }
            this.source.fillBuffer(audioBuffer)
        }
        if status != 0 {
            return nil
        }
        guard let audioQueue = tempAudioQueue else {
            return nil
        }
        self.mQueue = audioQueue
    }

    private func audioBufferForAudioQueueBuffer(aqBuffer:AudioQueueBufferRef) -> PDAudioBuffer? {
        for buffer in self.audioBuffers {
            if buffer.audioQueueBuffer == aqBuffer {
                return buffer
            }
        }
        return nil
    }
}