SKAction plays sound loop with a pause - ios

Loop is playing fine, except one thing: a little pause between iterations. Code:
var bgMusic = SKAction.repeatActionForever(SKAction.playSoundFileNamed("MenuSound.mp3", waitForCompletion: true))

Your pause is probably caused by a silent period at the end of your music/sound file. Use a sound editor app to cut out the dead air at the end of the file.

Related

How can I pause SCNAudioPlayer playback in ARKit?

I'm trying to implement a play/pause button for positional audio attached to a node in an ARKit scene. I want the user to be able to pause the audio, then resume it from the paused point at a later time. So removeAudioPlayer() is no good, as this resets the audio back to the start when it is reattached.
The only pause method associated with SCNAudioPlayers that I can find is buried deep down in:
myAudioPlayer.audioNode?.engine?.pause()
But this doesn't seem to have any effect. Strangely
myAudioPlayer.audioNode?.engine?.stop()
Does stop the audio from playing, but then you can't start it again afterwards!
My code for creating the audioPlayer is as follows:
audioSource = SCNAudioSource(fileNamed: "audio.caf")!
audioSource.loops = false
audioSource.isPositional = true
audioSource.shouldStream = false
audioSource.load()
// then a bit later...
audioPlayer = SCNAudioPlayer(source: audioSource)
myARNode.addAudioPlayer(audioPlayer)
Notice that no 'play' method is needed. The audio just starts playing as soon as you attach it to the node. And the lack of straight play() and pause() methods as top-level properties of SCNAudioPlayer makes me wonder if it's possible at all. This seems slightly crazy however, as it's a pretty rudimentary aspect of working with audio.
Does anyone know if this can be done?
Thanks in advance.
To stop audio engine use 2 sec delay. Pause doesn't work here (I'm using Xcode 12.2).
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
player.audioNode?.engine?.stop()
}

First time audio playing getting slow my Sprite Kit game?

I'm new with Sprite Kit, I have a short sound effect to play in a function. I have tried AVFoundation and SKAudioNode like below in that function. But I discovered It triggers some stuck for my SKActions. How Can I solve this playing problem. It looks waiting for completion or something different?
let audioNode = SKAudioNode(fileNamed: "catch")
audioNode.autoplayLooped = false
self.addChild(audioNode)
let playAction = SKAction.play()
audioNode.run(playAction)
There is another action for playing sound file,
you can use
SKAction.playSoundFileNamed("catch", waitForCompletion: false)
instead of SKAction.play().
There is a complete explanation of what waitForCompletion is doing in Apple Documentation

SpriteKit background music not looping forever

I'm making a simple SpriteKit game with two scenes, and I want the background music to loop unconditionally through both scenes. Right now, I'm using
if soundIsPlaying == false {
runAction(SKAction.repeatActionForever(backgroundMusicEffect), withKey: "backgroundMusic")
soundIsPlaying = true
}
in my menu scene where backgroundMusicEffect is a global variable
let backgroundMusicEffect = SKAction.playSoundFileNamed("content/divertimentoK131.mp3", waitForCompletion: true)
When I play my game, the music never loops. It always stops after one play. If I remove the if-else statement, the music plays over itself every time I reenter the menu.
Is there a better way to play background music? What am I doing wrong?
I believe that the way you are doing it, after the first time looping, every iteration after is "complete" since the sound is finished. You would need to create a new SKAction instance every time if you want to get this to loop.
This of course is a bad idea, since playSoundFileNamed is designed to only play a sound file once with as little over head as possible.
As #Alessandro Omano has commented, use SKAudioNode to get sound playing in a loop. This is my preferred way of doing in, but you limit yourself to >= iOS 9 users.
If you have to support iOS 8 users (At this point I would say why bother) then you need to look into the AVFoundation sections of the libs to get audio going, or use OpenAL.

iOS AVAudioPlayer play sound again

Hey I have a couple of AVAudioPlayers containing one sound each. If I press the same button a couple of times, it should repeat the sound from the beginning. If I press another button afterwards, the running sound shall be stopped in order to "make room" for the new one.
The code I am using for that:
-(void) plays:(int)p{ // p is the index of the sound being triggered
if([players[p] isPlaying])
{ // setting the time back to 0 makes
players[p].currentTime = 0.0; // the player automatically play again
}
else
{
[players[p] play]; // if not playing, start playing
}
if(last!=p)
{ // if the last sound is different from the current
[players[last] stop]; // stop the last one
players[last].currentTime = 0.0;} // put its position back to 0
last=p; // set the 'last' variable
}
However, hitting the same button again ends up in a little delay (maybe 20ms) in which no sound is heard. This is the time, the AVAudioPlayer seems to need to "rewind" the track in order to play it again. One Idea to get around this would be to create multiple objects of AVAudioPlayer for each sound but that'd make some awful code! Any ideas on how to make this process quicker?
Thanks, Alex
EDIT: playing 2 different sounds works perfectly fine, I can't hear any delay in between them as I prepareToPlay all the sounds beforehand.
I know how to eliminate the 20ms gap, but first consider if you want to.
Imagine if you jumped immediately from the mid-point of the sound file to the beginning with no gap at all. Better yet, download Audacity and hear how it sounds. Because of the discontinuity, you are going to get an unpleasant crackling or pop sound. Perhaps that 1 fiftieth of a second of silence actually sounds better than immediately restarting.
If you want an uninterrupted audio stream, you're going to have to put away the easy AVAudioPlayer interface and build an AUGraph. Of course, this means learning a complex audio interface and learning all about audio formats. And then you have to figure out what data you're going to stuff into your audio stream.
How would you make your loop sounds nice? You might try fading out at the touch point, and then fading back in. Or you could search for the zero crossings at the beginning and end of your loop (zero crossings are the place where the value of your sound wave is 0. They happen all the time in a mono output, but might be harder to find if your output is stereo.) In the end will this sound nicer than the 20 ms of silence? Get out Audacity and experiment with looping before you enter the long road of learning the AUGraph interace.
To the same song, how about stopping it, then prepareToPlay and play?

Looped sound Hiccups

I have a sound file I wish to loop like the engine of a vehicle.
The sound I have is 1 second long and it is a .wav file.
I'm quite certain the file is cut to be seamless,
it loops perfectly in Audacity.
I'm calling the sound with this code:
let playEngineSound = SKAction.playSoundFileNamed("engine.wav", waitForCompletion: true)
let engineSoundLoop = SKAction.repeatActionForever(playEngineSound)
self.runAction(EngineSoundLoop, withKey: "engine sound")
I use "withKey" to be able to cancel it later.
The Sound comes out fine but there is a small but distinctive hiccup where the sound seems to be reloading or waiting for the other to stop completely before starting the new loop.
Any help would be much appreciated!
Edit: After trying the AVAudioPlayer route, it plays flawlessly, someone knows anything about the behaviour? I still want to go purely SKAction if possible.

Resources