Swift: How to play short sounds longer - ios

I'm working on a SpriteKit project using Swift and I wanted to play my 1 sec long sound longer. For instance, the sound file is "beep" - I want it to be extended to something like "beeeep" or "beeeeeeeeep". I'm tried several options to play a sound file, but I can't find a way to extend it.
Currently, I'm using SKAction to play sound:
var beep = SKAction.playSoundFileNamed("beep.caf", waitForCompletion: false)
runAction(beep)
Anyone knows how to do this?

AVAudioPlayer has a rate property which lets you play at half to double speed. If half works, you can use that.
If that does not work, you can use AVComposition to create a composite track from your sound file. You can select portions of the sound file and stitch them together anyway you like.

Related

How do you fast forward or rewind audio (like a song) for a certain time interval with AV Audio Player in Swift 5?

I need help using AV Audio Player, a Swift tool I'm not very familiar with. I need to know how to fast forward and/or rewind audio time with AV Audio Player in Swift 5. There is a currentTime() property for AV Audio Player that may be helpful in doing this, but I'm not sure how to use it.
You are correct: Set the AVAudioPlayer's currentTime. It measures the position (time) within the song, in seconds. (It calls this a TimeInterval, but that's just a Double signifying seconds or a fraction thereof.)
As the documentation remarks:
By setting this property you can seek to a specific point in a sound file or implement audio fast-forward and rewind functions.

Swift SpriteKit playing audio in the background

I have an app which needs to play audio in the background...
Is this possible using Swift and SpriteKit with SKActions...
Or is it possible another way..
A nudge in the right direction would be very helpful.
SKAction is really easy to use with sounds, but sometimes you might want to do more.
In that case, you would want to use AVAudioPlayerinstead of it.
In order to not write your own "player", I suggest you to use an existing one. Here is one I've already used (SKTAudio) : https://github.com/raywenderlich/SKTUtils/blob/master/SKTUtils/SKTAudio.swift
Here is how to use it :
// For background audio (playing continuously)
SKTAudio.sharedInstance().playBackgroundMusic("yourBackgroundMusic.mp3") // Start the music
SKTAudio.sharedInstance().pauseBackgroundMusic() // Pause the music
SKTAudio.sharedInstance().resumeBackgroundMusic() // Resume the music
// For short sounds
SKTAudio.sharedInstance().playSoundEffect("sound.wav") // Play the sound once
As you can see, you'll be able to either play short sound (as you might already have done with SKAction) and even background music that will play in loop as you're looking for.
After trying out a few things I stumbled upon a reasonable solution. For playing music in a loop you can set up an SKAudioNode and set the AutoPlayedLoop = true. Then call the "play music" method in when Scene loads.
Now, if you want a sound effect you can use an SKAudioNode for that as well. I found that the sound effect started repeating and so to counteract that I simply created a play-stop sequence. Essentially, every time the sound effect was triggered it would run this sequence, hence, it only sounded once, as intended. There was a cut off to the sound effect however, so I created a simple colour shade method for about 1 second and added this to the sequence. Now the sequence produced was play-shade-stop. Every time the sound effect ran this sequence the dormant shade action would give it a 1 second lag and allow it to play fully and then it would stop as intended. Based on the sound effect you can use the dormant shade action to compensate as required, sometimes longer, sometimes shorter.
Well, here is the code. It's pretty straightforward and you don't need to create a whole AVPlayer class for it.
func playerhitfx() {
let fx:SKAudioNode = SKAudioNode(fileNamed: "playerfx")
let play: SKAction = SKAction.play()
let stop: SKAction = SKAction.stop()
let shade: SKAction = SKAction.colorize(with: UIColor.clear, colorBlendFactor: 1, duration: 1)
let volume: SKAction = SKAction.changeVolume(to: 3, duration: 0)
let seq: SKAction = SKAction.sequence([play,shade,stop])
fx.run(seq)
fx.run(volume)
self.addChild(fx)
}
Furthermore, you can adjust the volume properties having all audio as AudioNodes, to create a good audio mix between the music in the background and the sound effects and also to pronounce certain other effects over others. Hope this helps.
By the way, you can't cast an SKAudioNode into an AVAudioNode, just to bare in mind.

Playing Motor Sound Effects for iOS SpriteKit Game... AVAudioPlayer vs SKAction vs?

I am developing a driving game using SpriteKit and am having trouble with engine sound effects.
I want to have two different engine sounds. One for when the throttle button is being pressed and one for when the throttle button is not being pressed. One of the two sounds will be playing constantly while the game is going.
What is the best approach? Should my sound files be extremely short (0.10 seconds or less) and looped or should they be fairly long and just turned on and off? Should I use SKAction to play the sounds or AVAudioPlayer or something else? I have tried using AVAudioPlayer but every time I pause and play the player (switching the throttle on or off), the frame rate of the game momentarily drops. Any help is appreciated!
Based on the comment left by LearnCocos2D, I looked into ObjectAL. For those not familiar with ObjectAL, it is designed to be a simple and intuitive interface to OpenAL and AVAudioPlayer. You can download and find more information about it here...
http://kstenerud.github.io/ObjectAL-for-iPhone/index.html
For my audio clip I used 3 to 5 second long .caf audio file of a motor sound. ObjectAL allowed me to continuously loop and vary the pitch of the audio file. By varying the pitch, I could simulate the motor at different speeds.
Below is a sample of the code...
Two member variables or you can set them as properties...
ALBuffer *_buffer;
ALSource *_source;
Method to initialize the motor sound effect...
- (void)initializeSound
{
// We'll let OALSimpleAudio deal with the device and context.
// Since we're not going to use it for playing effects, don't give it any sources.
[OALSimpleAudio sharedInstance].reservedSources = 0;
_source = [ALSource source];
_buffer = [[OpenALManager sharedInstance] bufferFromFile:#"EngineSound.caf"];
_source.pitch = 0.30; // Start at low pitch for engine idle.
[_source play:_buffer loop:YES];
}
Inside my SKScene's update method I adjust the pitch according to speed.
- (void)update:(CFTimeInterval)currentTime
{
CGFloat enginePitch;
// Code to calculate desired enginePitch value based on vehicle speed.
_source.pitch = enginePitch;
}
Because of an alleged bug in SpriteKit, I did have an issue with a gpus_ReturnNotPermittedKillClient EXC_BAD_ACCESS error when closing the app. I found the fix here...
https://stackoverflow.com/a/19283721/3148272
I would suggest using AVAudioPlayer. You need to have it in property and not create every time you want to play something.
SKAction is bad in a way that you can't stop or cancel it (even by removing action).

Create a crossfader with AvAudioPlayer

How I can create a crossfader between two sound track with AVAudioplayer?
I must use AVAudiomix? But... how I should use?
AVAudioPlayer does not support using an AVAudioMix. You could try to fade out the playing yourself by directly setting the playback volume but getting the timing right between two AVAudioPlayers will be difficult as AVAudioPlayer is known to have very high and unpredictable latency when starting to play.
One way to accomplish this is to use AVPlayer and AVPlayerItem and AVComposition. You can setup the composition to overlay the two audio files by your desired amount and setup the AVAudioMix fade out the first and fade in the second. This method will let you have precise control over when the audio files play relative to one another.

Play a beep that loop and change the frequency/speed

I am creating an iphone application that use audio.
I want to play a beep sound that loop indefinitely.
I found an easy way to do that using the upper layer AVAudioPlayer and the numberOfLoops set to "-1". It works fine.
But now I want to play this audio and be able to change the rate / speed. It may works like the sound played by a car when approaching an obstacle. At the beginning the beep has a low frequency and this frequency accelerate till reaching a continuous sound biiiiiiiiiiiip ...
It seems this is not feasible using the high layer AVAudioPlayer, but even looking at AudioToolBox I found no solution.
Any help?
Take a look at Dave Dribin's A440 sample application, which plays a constant 440 Hz tone on the iPhone / iPad. It uses the lower-level Audio Queue Services, but it does what you're asking (short of the realtime tone adjustment, which would just require a tweak of the existing code).

Resources