SKAudioNode() crashes when plugging in/out headphones
Asked Answered
I

2

12

I am using a SKAudioNode() to play background music in my game. I have a play/pause function and everything is working fine until I plug in my headphones. There is no sound at all and when I call the pause/play function I get this error

AVAudioPlayerNode.mm:333: Start: required condition is false: _engine->IsRunning() com.apple.coreaudio.avfaudio', reason: 'required condition is false: _engine->IsRunning()

Does anyone knows what this means?

Code:

import SpriteKit

class GameScene: SKScene {

let loop = SKAudioNode(fileNamed: "gameloop.mp3")
let play = SKAction.play()
let pause = SKAction.pause()
var isPlaying = Bool()

override func didMoveToView(view: SKView) {  
    loop.runAction(play)
    isPlaying = true
    self.addChild(loop)
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    _ = touches.first as UITouch!

    for _ in touches {
        if isPlaying {
            loop.runAction(pause)
            isPlaying = false
        } else {
            loop.runAction(play)
            isPlaying = true
        } 
    }
}
}
Incriminate answered 26/2, 2016 at 21:31 Comment(16)
Possible duplicate of AVAudioEngine crashes when plug headphones in or outMcadoo
AVAudioEngineConfigurationChangeNotification was no help to me :( I found that question beforeIncriminate
Damn. Are you running on a simulator? I seem to recall running into a similar issue recently..Mcadoo
no, I am testing on my deviceIncriminate
could you explain the order you are doing things? Start app,music plays, plug headphones in, tap screen crash?Blood
You are going to be my new hero, Knight :) starting app - hearing sound - pluggin in headphones - no sound on headphones - touching screen twice - crashIncriminate
works fine for me, what version of iOSBlood
really, hmm. I am building on 9.2.1. do you hear the music while headphones are pluged in?Incriminate
yes, I am using an iPad mini 2 on 9.2.1, no crashing. Also if you need me to respond faster, do @name so it notifies a personBlood
I've found it takes apple a few iterations of spritekit to get these new features working properly =/ a lot of the time they seem a little half bakedGillie
@Blood I guess there is no problem on ipads, only on iphones :( I found this post forums.developer.apple.com/thread/…Incriminate
Does that code fix it for you? I would test but i need my phone to stay in ios8 for testingBlood
@Blood Thx for your help, I posted my workaround without using SKAudioNode()Incriminate
@Incriminate It is a shame that SKAudioNode is currently broken like this. Still, I hope (and hope dies last lol) that there is a solution for this and I would like to start a bounty on this question. It is viewed only 34 times so far, and I just want to give it one more chance. Let me know if you agree.Teal
@Teal This would be great! Thank you. Hopefully someone knows a solution :)Incriminate
@Incriminate No responses so far...I forgot to mention that you should probably uncheck your accepted answer, because it can confuse people and make them think that issue is solved. Still there are three more days (one day + grace period) so you may try to un-accept your answer, and accept it later if question remain unanswered...Teal
I
2

I was not able fix it, but by using AVAudioPlayer() I found a good workaround. Thank you all for supporting me!

import SpriteKit
import AVFoundation

class GameScene: SKScene {    
    var audioPlayer = AVAudioPlayer()  

    override func didMoveToView(view: SKView) {        
        initAudioPlayer("gameloop.mp3")        
    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {        
        _ = touches.first as UITouch!
        for _ in touches {
            toggleBackgroundMusic()            
        }        
    }

    func initAudioPlayer(filename: String) {        
        let url = NSBundle.mainBundle().URLForResource(filename, withExtension: nil)
        guard let newURL = url else {
            print("Could not find file: \(filename)")
            return
        }
        do {
            audioPlayer = try AVAudioPlayer(contentsOfURL: newURL)
            audioPlayer.numberOfLoops = -1
            audioPlayer.prepareToPlay()
            audioPlayer.play()
        } catch let error as NSError {
            print(error.description)
        }        
    }

    func toggleBackgroundMusic() {        
        if audioPlayer.playing {
            audioPlayer.pause()
        } else {
            audioPlayer.play()
        }        
    }    
}
Incriminate answered 28/2, 2016 at 16:27 Comment(0)
M
2

SKScene has a property named audioEngine that is stopped in certain circumstances. If you´re using ReplayKit for example, playing a recorded gameplay movie in the RPPreviewController hi-jacks the audio and stops it, so when you dismiss it, the audioEngine is no longer running.

I had this issue and solved it by doing a simple check and starting the audioEngine again. Try this:

if !self.audioEngine.isRunning {
    do {
        try self.audioEngine.start()
    } catch {
        //handle error
    }
}
Madalena answered 12/6, 2017 at 12:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.