Skaudionode() Crashes When Plugging In/Out Headphones

SKAudioNode() crashes when plugging in/out headphones

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()
}
}
}

AVAudioEngine crashes when plug headphones in or out

You need to register to the AVAudioEngineConfigurationChangeNotification notification and do the necessary steps to update the output node.

SKAudioNode not load sound from url

i think you try AVAudioPlayer

var resourcePath = url  //your url
var objectData = Data(contentsOf: NSURL(string: resourcePath)!)
var error: Error!
do {
audioPlayer = try AVAudioPlayer(objectData)
}
catch let error {
}
audioPlayer.numberOfLoops = 0
audioPlayer.volume = 1.0
audioPlayer.prepareToPlay()
if audioPlayer == nil {
print("\(error.description)")
}
else {
audioPlayer.play()
}

SKAudioNode else/if off/on Case

Every time you are pressing the sound button you are creating a new instance of SKAudioNode which probably causes the sound issues.

Take theses two lines

let playguitar: SKAudioNode
playguitar = SKAudioNode(fileNamed: "guitar.wav")

out of

 func fireTurnsOnOff() {...

Than put

  let playguitar: SKAudioNode

above DidMoveToView as a class/global property and

  playguitar = SKAudioNode(fileNamed: "guitar.wav")  

inside didMoveToView.

SKAudioNode play sound once

Unfortunately, what @KnightOfDragon says is not correct (but I do not have enough reputation to comment).

SKAudioNode has been introduced in iOS 9 and is meant as a replacement for SKAction.playSoundFileNamed(...) as it is much more powerful (You can add it as a child to a SpriteKit SKNode and if the attribute positional is set to true, 3D audio mixing is added automatically).

In order to play a sound once with SKAudioNode use the following code:

if #available(iOS 9, *) {
let pling = SKAudioNode(fileNamed: "pling.wav")
// this is important (or else the scene starts to play the sound in
// an infinite loop right after adding the node to the scene).
pling.autoplayLooped = false
someNode.addChild(pling)
someNode.runAction(SKAction.sequence([
SKAction.waitForDuration(0.5),
SKAction.runBlock {
// this will start playing the pling once.
pling.runAction(SKAction.play())
}
])
}
else {
// do it the old way
}

Update

Have a look here, how to use Actions on audio nodes: SKAction->Audio-Stuff. The documentation says:

Use SKAction playSoundFileNamed:waitForCompletion: only for short incidentals.
Use AVAudioPlayer for long running background music.

This does not mean, that a SKAudioNode should not be used for one-time audio. With playSoundFileNamed you cannot change the volume or pause/stop playback and so on.

Assign the SKAction returned when running play() on an SKAudioNode?

SKAction.play()

returns an SKAction, and

mySoundNode.run(SKAction.play())

runs that action on mySoundNode. The run() method returns Void ("nothing"), so with

var mySoundAction = mySoundNode.run(SKAction.play())

you run the "play" action on the node and assign () to var mySoundAction. What you perhaps meant is

var mySoundAction = SKAction.play()
// ...
self.run(mySoundAction)

AVAudioEngine not posting notification in SpriteKit

The original Cocoa name of the notification is AVAudioEngineConfigurationChangeNotification, but the Swift constant is called AVAudioEngineConfigurationChange. Therefore you can handle the notification by using either:

let notificationName = Notification.Name("AVAudioEngineConfigurationChangeNotification")

or

let notificationName = Notification.Name.AVAudioEngineConfigurationChange

Your selector should then be called when plugging-in/unplugging headphones.

This appears to only be a partial solution for SpriteKit audio flakiness. I tried the following inside the notification handler:

try? self.audioEngine.start() 

I was able to stop the crash, but my SKAudioNode wouldn't make any sound after the plug/unplug event, until the process was restarted.

Volume of SKAudioNode

if you ctrl-click on the action on the code in Xcode it pops up with the details of the parameters

class func changeVolume(to v: Float, duration: TimeInterval) ->
SKAction

Description - Creates an action that changes an audio node’s volume to
a new value. When the action executes, the audio node’s volume
animates from its current value to its new value. For more
information, see AVAudio3DMixing.

This action - v The new value for the volume. The value should be
between 0.0 (silence) and 1.0 (maximum value for source audio),
inclusive.

duration - The duration of the animation, in seconds.

Returns A new action object.

SDKs iOS 9.0+, macOS 10.11+, tvOS 9.0+, watchOS 2.0+



Related Topics



Leave a reply



Submit