How to stop a sound action in swift spriteKit - ios

i am a swift beginner trying to build a game with a sound in it. i use swift SpriteKit and also AVFoundation as my sound starter. Below is the action i call
whenever i want a sound action in the game. The sound (background music) plays
alright but just wouldn't stop when the game is over.
self.runAction(SKAction.playSoundFileNamed("Sound/Gameplay.wav", waitForCompletion: false))
Can somebody please help me get this issue behind me? thanks.

You could pause and resume the music?
var gameMusic = AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Gameplay", ofType: "wav")!), error: nil)
//call playBackgroundMusic func
playBackgroundMusic()
func playBackgroundMusic(){
gameMusic.play()
}
func pauseBackgroundMusic(){
gameMusic.pause()
}
if(gameOver){
pauseBackgroundMusic()
}

Related

Is there a way of pausing background music(such as spotify) then play a sound file, then play the background music again in an ios application?

Is there a way of pausing background music (such as Spotify) then play a sound file, then play the background music again in an ios application?
I've tried to use AVAudioPlayer and AVAudioSession. I tried this:
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, mode: AVAudioSessionModeDefault, options: [AVAudioSessionCategoryOptions.duckOthers])
But it doesn't seem to work.
I really appreciate any tips!
You can play and pause Apple's music app songs with this code:
import MediaPlayer
let musicPlayer = MPMusicPlayerApplicationController.systemMusicPlayer
musicPlayer.playbackState == .paused || musicPlayer.playbackState == .stopped ? musicPlayer.play() : musicPlayer.stop()
So, you can sandwich the code that plays your audio file between 2 calls to the above code.
import MediaPlayer
let musicPlayer = MPMusicPlayerApplicationController.systemMusicPlayer
if (self.musicPlayer.playbackState == .playing) {
musicPlayer.stop()
}
//Play your audio file
self.musicPlayer.play()
You might want to use this code to set a playing queue if no song was playing initially.
musicPlayer.setQueue(with: .songs())

How to track the number of loops in AVAudioFoundation

I am making an audio player in my iOS project.
I setup the play(audioOfUrl:URL, for times:Int)method by passing the name of the url and how many times the audio file will be play as following:
func play(audioOfUrl:URL, for times:Int) {
let urlPath = audioOfUrl
loopsLeftOver = times
do {
let audio = try AVAudioPlayer.init(contentsOf: urlPath)
audioPlayer = audio
audio.play()
audio.numberOfLoops = times - 1
} catch let error {
print(error.localizedDescription)
}
}
there will be a pause() and resume() as well, What I need to do is keep track of how many loops the audio player leftover.
For example, if I call the play method like this:
play(audioOfUrl:audioUrl, for times:5)
I need to keep eyes on the times leftover as the audio player running.
I try to use the AVAudioPlayerDelegate method, but it is not working, how to keep eyes on the audio.numberOfLoops? Thanks in advance.
You can subscribe for AVPlayerItemDidPlayToEndTime notification and count how many times the handler of this notification has been called.
NotificationCenter.default.addObserver(self, selector:#selector(playerItemDidReachEnd(_:)),
name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
object: audioPlayer.currentItem)

Keep AVAudioPlayer sound in the memory

I use AVAudioPlayer to play a click sound if the user taps on a button.
Because there is a delay between the tap and the sound, I play the sound once in viewDidAppear with volume = 0
I found that if the user taps on the button within a time period the sound plays immediately, but after a certain time there is a delay between the tap and the sound in this case also.
It seems like in the first case the sound comes from cache of the initial play, and in the second case the app has to load the sound again.
Therefore now I play the sound every 2 seconds with volume = 0 and when the user actually taps on the button the sound comes right away.
My question is there a better approach for this?
My goal would be to keep the sound in cache within the whole lifetime of the app.
Thank you,
To avoid audio lag, use the .prepareToPlay() method of AVAudioPlayer.
Apple's Documentation on Prepare To Play
Calling this method preloads buffers and acquires the audio hardware
needed for playback, which minimizes the lag between calling the
play() method and the start of sound output.
If player is declared as an AVAudioPlayer then player.prepareToPlay() can be called to avoid the audio lag. Example code:
struct AudioPlayerManager {
var player: AVAudioPlayer? = AVAudioPlayer()
mutating func setupPlayer(soundName: String, soundType: SoundType) {
if let soundURL = Bundle.main.url(forResource: soundName, withExtension: soundType.rawValue) {
do {
player = try AVAudioPlayer(contentsOf: soundURL)
player?.prepareToPlay()
}
catch {
print(error.localizedDescription)
}
} else {
print("Sound file was missing, name is misspelled or wrong case.")
}
}
Then play() can be called with minimal lag:
player?.play()
If you save the pointer to AVAudioPlayer then your sound remains in memory and no other lag will occur.
First delay is caused by sound loading, so your 1st playback in viewDidAppear is right.

Swift 2.0 Playing custom sound in app delegate while in background mode

I am using Google Cloud messaging to push notifications to my iOS app written in Swift 2.0 xCode 7.1. GCM doesn't allow custom notification sounds.
See here: https://developers.google.com/cloud-messaging/http-server-ref
So I turned off the default sound and am trying to play a sound whenever 'didReceiveRemoteNotification' is called. My problem is the sound is not playing when in background mode..however if I put the code(below) in 'didFinishLaunchingWithOptions' it works perfectly, just not when I want it to play.
I have added the background more in info.plist. Like I said its working just not when a push notification arrives.
let alertSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("GMNotification", ofType: "wav")!)
print(alertSound)
//var error:NSError?
do {
try self.audioPlayer = AVAudioPlayer(contentsOfURL: alertSound, fileTypeHint:nil)
self.audioPlayer.prepareToPlay()
self.audioPlayer.play()
print("PLAY !!!")
} catch {
print("Error ???")
}
Can anyone help please?
You must create a shared instance "Singelton" to play sound. Refer back to:
Swift - AVAudioPlayer, sound doesn't play correctly
This should tell you how it can be done

Sound not playing AudioToolbox Swift

I'm trying to play an alarm sound, but when I've implemented the code, it runs, but no sound is played. What is the problem?
Here is my code (the important bits):
import UIKit
//Timer Sound
let timerSoundURL = NSBundle.mainBundle().URLForResource("alarm", withExtension: "caf")
var timerSoundID: SystemSoundID = 0
override func viewDidLoad() {
//Setup sound for timer
AudioServicesCreateSystemSoundID(timerSoundURL, &timerSoundID)
}
//Plays sound
override func viewDidAppear(animated: Bool) {
AudioServicesPlaySystemSound(timerSoundID);
NSLog("Play sound")
}
Your code looks fine, but you are probably testing it in the Simulator. If so, that's your mistake. AudioServicesPlaySystemSound doesn't work in the Simulator.
Run your code on an actual device and all will be well (except that you've got a memory leak, but that's another matter entirely - the point is, you'll hear the sound, if the resource is valid, when you run on the device).

Resources