SKAudioNode play sound once - swift

I can't seem to find much information about SKAudioNode. How do i play a sound only once? I do not want to repeat the sound.
What i am trying to accomplish is to play a short laser sound each time a bullet spawns, in spritekit.

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.

if you are trying to do sound effects, you use SKAction.playSoundFileNamed(...) on the sprite that is creating the effect. SKAudioNode is more for having music playing in your game
Example:
//we have ship as an SKSpriteNode
//lets fire laser
ship.runAction(SKAction.playSoundFileNamed("pewpewpew.caf",waitForCompletion:false));

Related

Audio volume change is lagging

Im playing two tracks in sync. This works well, they sound like one song.
What im trying to do is allow player to switch one track on and of by toggling mute or setting volume to 0 or 1. The muted track continues playing in sync with other track but cant be heard.
But the volume change /muting is lagging. So even if you switch the sound on exactly on beat you wont hear that beat cause it takes a split second for the code to react. There must be a way to make the change instant?
Below is a part of the music manager that handles this. The full code also includes how sound is loaded and starts playing and can be seen here:
https://github.com/Lautaro/AudioTest/blob/master/Assets/MusicManager.cs
// Update is called once per frame
void Update()
{
if (Input.anyKeyDown)
{
if (Input.GetKeyDown(KeyCode.Space))
{
Toggle();
}
}
}
void Toggle()
{
var clip = Sources.First(s => s.clip.name == "ExtraBeat");
// Same result if setting clip.volume instead of mute
clip.mute = !clip.mute;
}
The complete project with audio tracks can be cloned here. Use space to toggle sound.
https://github.com/Lautaro/AudioTest.git

Is there a way of changing playback position using AudioKit / AKPlayer?

Been scratching my head with this one, to no avail.
Am just trying to find out how to instantly change the current playback position when using the AKAudioPlayer provided by AudioKit.
player.playhead is read-only, so cant be changed.
changing player.startTime whilst the player is already playing seems to change the playback position in terms of the reported .playhead position but the actual audio being played does not change position - am I missing something here?
Obviously I can stop audio and restart at new position but a several second expensive CPU gap is not desirable for a a simple mp3 / wav file player!
Any ideas?
We've added a new player called AKPlayer which will also allow scanning through the file. The player will stream from disk by default. This player is designed to fix some of the shortcomings in AKAudioPlayer.
OK Aurelius pointed me in the right direction of a new class introduced a couple weeks ago called AKClipPlayer
Like the standard Apple AV class you can now set the .currentTime property (in seconds) (the AKAudioPlayer class did not allow this) - it seems to stop playback doing this though so don't forget to .play() your node right after - there is no glitch or pause, is seamless on an old iPhone6S

Cocos Denshion: Play sound effect in sync with music

I am making a music game and when the user presses a note it will produce a sound. The sound naturally needs to play immediately when the user presses, so they can tell whether they are in time with the music. However, it feels as if the sound is lagging, especially when note presses become quicker.
My background .m4a music file is played with AVAudioPlayer. I chose to use this over Cocos Denshion as I have access to the currentTime property. I may be wrong, but I dont think I can access this with CocosDenshion.
I made a .wav file which is extremely short (less than a second). I preload my sound effect on init:
[[SimpleAudioEngine sharedEngine] preloadEffect:#"Assist.wav"];
Then to play the sound effect, in CCTouchesBegan I call:
[[SimpleAudioEngine sharedEngine] playEffect:#"Assist.wav"];
After that it calls my code to determine the users timing and awards points. Any idea why it might be lagging, or a better way to play sound effects in time with music?
EDIT: Ive tried a few things recently with no results. First I tried playing the sounds automatically as they came up to the appropriate time in the song. Still had the lag, so I dont think it is touch events being slow. I also tried 3 different sound libraries.
However, when I ran in the simulator, it seemed to not be laggy. Does anyone have an idea? Im clueless and its a major feature I cant really take out...
you should avoid this code:- [[SimpleAudioEngine sharedEngine] preloadEffect:#"Assist.wav"];
with the start of app you should load your framework SimpleAudioEngine by writing this code :-
//SimpleAudioEngine *palySound; made object in .h file.
palySound=[SimpleAudioEngine sharedEngine];
and whenever you want to play sound you can write: [palySound playEffect:#"Assist.wav"];
I am not sure what you're doing in your SoundEngine, but in my own experience, the best way to not get lag to play a sound is to assign an AVAudioPlayer for each sound file (unless you want to start messing around with AudioQueues).
Here it is an example:
Let's assume that you have an AVAudioPlayer *assistPlayer; in your current view controller.
In your viewDidLoad initialize it with your sound:
NSURL *wavURL = [[NSBundle mainBundle] URLForResource:#"Assist" withExtension:#"wav"];
assistPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:wavURL error:nil];
Then, in your IBAction where you want to play the file, just do:
[assistPlayer play];
You shouldn't get any lag.
Did you try Finch? It claims to play sounds with low latency, and it is also just a wrapper around OpenAL.
Other than that, I'm really not experienced with OpenAL, but can think of two possible reasons for your lag:
The main thread is too busy - Try to offload work from it to other
threads.
Perhaps OpenAL is defined with too large of a buffer, so the pipeline loads the entire sound into the buffer (or a big chunk of it), and only afterwards the playback starts.

Why is there a delay when I play a sound in Cocos2d?

I am sure there is a way to do this, and I don't know how, and am new to sound in Cocos2d. I am using SimpleAudioEngine.h as directed to in Ray Wenderlich's wonderful tutorial (Part 1). The problem is, there is a delay when it plays a sound. I KNOW for a fact that there is a way to get rid of the delay, because, just look at all the games that are already out for iPhone!! Note that I am doing this on the Simulator, not on a real device, if that makes a difference. Any help is appreciated. Thanks!!
Have you tried preloadEffect? preload audio effects at initialize before calling playEffect:.
[[SimpleAudioEngine sharedEngine] preloadEffect:#"pew-pew-lei.caf"];
This fix might not work. If the sound engine is not initialized properly, it will never preload properly.
Another possibility of sound stuttering: your code might be asking for multiple resource files at the same time, and if you are not multi-threading, it can affect the sound effects.
To test for this: comment out your code when the sound effects play. If the sound effects do not stutter with your code commented out, that means your code is 'keeping the device or thread busy'.
I found this issue when I played an explosion animation. When I commented out the animation code, the sound effect did not stutter the game play.

Playing a a number of different sounds using AVAudioPlayer

I have a few single hit sounds(small sound effects) which I want to play when a button is pressed. Should I declare the player and then initialize the sound to the player in the IBAction of the button if I want to play different sounds on different buttons?
Or is there a method to call which you specify the sound as you play it?
the [audioPlayer play] statement plays what is already initialized or added to the player. How can I setup the play and call it at different places with some predefined sound?
Thanks
There's a bit of delay whenever you start playing a sound even if it's already loaded and all you have to do is hit [audioPlayer play]
If you need to initialize it before you play it i'd imagine the delay would be much more noticeable.
I think i'd make a separate audio player for each sound and populate an array with them. Keep an eye out for memory low messages and unload the objects if necessary but i don't think it will require much overhead.