3

I have a AVAudioPlayerNode that I'm scheduling a lot of buffers on using the following:

node.scheduleBuffer(buffer, at: nil, options: .interrupts, completionHandler: completeFunc)

But I'm having a bit of a problem. If I play another buffer interrupting the currently playing buffer, the completion handler for the buffer getting interrupted is still being called. I guess this makes sense, but I can't seem to find a way to check if the file actually COMPLETED playing or if it was interrupted. Is there a way I can do this?

Any answers will help!

MysteryPancake
  • 1,125
  • 1
  • 13
  • 36
  • If anyone reading this question needs more context, I'm using the completion handler to run a function that schedules a buffer that runs a completion handler that runs the function that runs the completion handler... in a big loop, and at some point I need to disrupt the loop. Currently I'm doing it by stopping and then playing the audio node, but this method causes a noticeable gap in the sound – MysteryPancake Oct 31 '16 at 10:33

1 Answers1

2

You will need an interruption state variable that is referenced in the completion handler and toggled by the interrupting code. Here's some shorthand code that makes some assumptions on how you're looping through buffers:

var node: AVAudioPlayerNode!
var loopingBuffers: [AVAudioPCMBuffer] = [buffer1, buffer2, buffer3]
var interruptBuffers = false // state variable to handle the interruption

func scheduleNextBuffer() {
    /* code to find the next buffer in the loopingBuffers queue */

    // assuming you have instantiated an AVAudioPlayerNode elsewhere
    node.scheduleBuffer(nextBuffer, completionHandler: bufferCompletion)
}

func bufferCompletion() {
    // check the state variable to make certain the completionHandler isn't being triggered by a scheduling interruption
    guard !interruptBuffers else { return }
    scheduleNextBuffer()
}

func interruptBuffers() {
    let newBuffers: [AVAudioPCMBuffer] = [buffer4, buffer5, buffer6]

    interruptBuffers = true

    node.scheduleBuffer(buffer4, at: nil, options: .interrupts, completionHandler: bufferCompletion)

    // cleanup your state and queue up your new buffers
    interruptBuffers = false
    loopingBuffers = newBuffers
}
lastcommit
  • 106
  • 4