AVAudioPlayer makes my game look laggy - ios

When I use AVAudioPlayers for sound effects in my game, they cause the game to look laggy. I'm not the only one facing this problem, but from what I've found on here/other sites they don't seem to come up with an answer to solve it. Therefore I'm asking once and for all... What can I do? I've tried to use prepareToPlay in the viewDidLoad, but it doesn't help.
Here's some code on how I use the AVAudioPlayer:
NSString *StartTap=[[NSBundle mainBundle]pathForResource:#"Tap" ofType:#"mp3"];
StartSound=[[AVAudioPlayer alloc]initWithContentsOfURL: [NSURL fileURLWithPath:StartTap] error:NULL];
StartSound.numberOfLoops=-0;
And then I call:
[StartSound play];

Related

Multiple AVPlayers ducking?

I have a relatively simple setup involving 1 AVPlayer looping some ambient audio in the background and a second player playing a shorter sound at certain points.
What I've observed is that when the short sound is played, I hear the ambient clip cut out for about a second while there is a staticy pop. It then proceeds to continue playing while the short sound is played at the same time. This only happens on device - it's not noticeable on the sim, which seems to point to a potential performance issue.
I can't quite figure out why the first AVPlayer has this blip. Here is the code for the ambient player:
NSString *path = [[NSBundle mainBundle] pathForResource:kAmbientTrack ofType:#"mp3"];
_ambientPlayer = [AVPlayer playerWithURL:[NSURL fileURLWithPath:path]];
[self.ambientPlayer play];
It's slightly more complex, as I also listen for a notification when it ends and the restart it, but this issue happens even during the initial play before any looping occurs.
So while that is going in the background, I play another clip like so:
self.announcementPlayer = [[AVPlayer alloc] initWithURL:[myObject audioPathUrl]];
[self.announcementPlayer play];
So nothing too unique there - just two AVPlayers playing.
The only other piece of interest is how I set up the audio session when the app launches.
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:nil];
I'm doing this to allow the user to play music from other apps in the background.
I think my code is pretty straight forward, and really have no idea why I would be getting this blip.
I fixed this somewhat by changing the audio players to be AVAudioPlayers. That resolved the popping in most cases. However, I still get the ducking. Specifically, if I play an AVAudioPlayer and, while it's still playing, I start to load an AVPlayer, it cuts off the AVAudioPlayer for about a second. Here's what I'm talking about:
[myAVAudioPlayer play];
AVPlayer *player = [AVPlayer playerWithURL:[self.currentExercise videoPathUrl]];
The addition of that second line causes the first second or so of myAVAudioPlayer to be silent.

Objective-C: Making AVPlayer plays in all the app controllers (or in the background)

I'm making a news iOS app, i want to implement a live audio streaming in all the pages like the picture below:
The orange view is a UIView that says "Live Streaming" (in Arabic), it exists in all the viewControllers, i want to let the AVPlayer plays when the user clicks on it and still plays even if the user navigates to other viewControllers.
I can't seem to find a good solution or tutorial about this, sorry if this is a noob question cause i'm new to iOS.
So how can i do that ? and where(in which viewController) should i put the AVPlayer declaration ?
Thanks in advance.
If you are testing in the simulator, the change of views will not continue the audio in the background. If it is not working your device try this:
NSURL *url = [NSURL URLWithString: yourURLHere];
AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:avAsset];
AVPlayer *audioPlayer = [AVPlayer playerWithPlayerItem:playerItem];
//This enables background music playing
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[audioPlayer play];
Place this code in your viewDidLoad method, before [super viewDidLoad];
I found two links that exaplin some of the issues on this:
Play Music in Background
Play Audio from Internet
If this does not work, I would recommend placing a bounty on the question as it seems your issue's are a little more in depth than a simple solution.
I found the solution, i had to make a singleton class.
The singleton class allow only one object to be used in the entire iOS application by all the ViewControllers.
And i did put all the needed methods like play and pause in the singleton class and i accessed them from all the ViewControllers.
If anybody wants an example, please ask in the comments.

Play audio file multiple times after a very short time?

I have an audio file that is 2 seconds long. Im trying to play that many times before it is done playing. But when I try it with AVAudioPlayer by creating a new instance of it, it sounds like it stops the audio that was played before and plays the new one instead of playing them at the same time. Should I use another way to play sounds or is this not achievable?
Code:
NSURL *url = [[NSBundle mainBundle] URLForResource:#"PistolShootSound" withExtension:#"mp3"];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[audioPlayer play];
audioPlayer is declared in the header file.
Have you used AVAudioPlayer's property numberOfLoops to play audio file repeatedly?
UPDATE: I didn't understand your goal before. If you want to play short files many times you could use AudioServices. Here is a good example of how to use it.

Playing AVAudioPlayer causes delay

I use AVAudioPlayer object to play an aif sound file that should go on unless the game is over. I have an ivar of AVAudioPlayer called backgroundPlayer and I set it up in viewDidLoad method:
-(void)viewDidLoad{
NSURL *backgroundURL=[NSURL fileURLWithPath:[[NSBundle
mainBundle]pathForResource:#"bgLoop" ofType:#"aif"]];
backgroundPlayer=[[[AVAudioPlayer alloc] initWithContentsOfURL:backgroundURL
error:nil] retain];
backgroundAudioPlayer.numberOfLoops=-1;
}
And then I play it in viewWillAppear method:
-(void)viewWillAppear:(BOOL)animated{
TrafficAppDelegate *delegate=[UIApplication sharedApplication].delegate;
if (delegate.shouldPlaySFX)
[backgroundPlayer play];
}
With this all set when I push my button to push the view controller to the stack I hangs for about 2-3 seconds and only after that the view appears. If I comment the [backgroundPlayer play] command in viewWillAppear method the delay goes away. Shouldn't I use AVAudioPlayer class for playing this kind of sounds? I mean the sound can go on for minutes, even hours.If the choose is not the issue then what can cause the delay? Thanks in advance
Have you tried this case after adding [backgroundPlayer prepareToPlay] in your code? I believe this will solve the delay issue.
It happens the first time you try to play a sound. You can play short silent sound in your appdelegate to make the AVAudioPlayer responsive when you really need it.

Sounds playing over each other using AVAudioPlayer

Right, sorry if i seem like a noob, but i'm new to xcode. I'm currently making a soundboard, and i've got all the buttons to work and play sounds from them.
However, if one sound is playing, when i press another button, rather than stopping the original sound, it just plays over it, so i was wandering if anyone knew how to fix this?
Here's the code i'm using for the buttons:
- (IBAction)playsound {
NSString *path = [[NSBundle mainBundle] pathForResource:#"Gold" ofType:#"mp3"];
AVAudioPlayer* myAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
myAudio.delegate = self;
myAudio.volume = 2.0;
myAudio.numberOfLoops = 0;
[myAudio play];
}
I'd be really grateful if someone could help me out.
Thanks.
If the other sound is still playing, you need to tell it to stop. You probably want to look into using the calling the stop method on the other AVAudioPlayer. So, something like where you have:
[myAudio play];
...insert a method call just before that to tell the other sound to stop.
[myOtherAudioThatsPlaying stop];
[myAudio play];
It might make sense to also browse the AVAudioPlayer documentation.
While bobtiki's answer is formally correct, it only makes sense to call the stop method if you want to do something useful with the sound after it has stopped, for example start playing it again. Since you just want to get rid of it, I recommend have the player just get deallocated, which automatically makes the sound stop playing.
So, instead of
AVAudioPlayer* myAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
add an instance variable to your class:
AVAudioPlayer* myAudio;
then just use
myAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
Everytime a new sound is played, myAudio gets assigned a new pointer and the old AVAudioPlayer just gets deallocated.

Resources