AVAudioPlayer doesn't load sound - iphone

For whatever reason, I'm having trouble loading up a sound with the AVAudioPlayer. I am testing it on my iPad device.
My code is fairly straight forward, nothing fancy. The framework is imported, delegate implemented. In my viewDidLoad method:
NSString *path = [[NSBundle mainBundle] pathForResource:#"sound" ofType:#"mp3"];
AVAudioPlayer *theAudio = [[AVAudioPlayer alloc]
initWithContentsOfURL:[NSURL fileURLWithPath:path]
error:NULL];
[theAudio setDelegate:self];
[theAudio prepareToPlay];
[theAudio play];
This fails to play the audio. However, by coincidence, when I show a UIAlertView immediately after, I can hear the first 2 seconds of the audio clip play. That is, my app loads, I hear two seconds of audio, then the alert pops up and cuts off the audio.
So it would appear the AVAudioPlayer code somewhat seems to work.
Any idea on whats going on and how I can simply get the audio to play?

The problem is that you are using ARC, and therefore that the AVAudioPlayer is deallocated when the variable goes out of scope. You have to declare the theAudio variable as an instance variable, and assign it in the viewDidLoad. So, in your .h file:
#interface MyViewController : UIViewController {
AVAudioPlayer *theAudio;
...
}
...
#end
Then, get rid of the AVAudioPlayer * from the line where you assign theAudio in viewDidLoad. This will cause your view controller to retain the audio player, and thus will prevent the player from being deallocated before playback.

Related

What Is the Easiest way to Play Sound on the Iphone?

What Is the Easiest way to Play Sound on the Iphone? I have an mp3 file, I'd rather keep it and not convert it to other format.
The simplest way I know of to play an MP3 file is to use the AVAudioPlayer class. Basically, just do (skipping error checking, setting delegate for detecting completion, etc):
NSURL* soundUrl = [[NSBundle mainBundle] URLForResource:#"soundFile" withExtension:#"mp3"];
AVAudioPlayer* player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundUrl error:&err];
[player play];
First add AVFoundation Framework to the project [Goto Target> Right click on project>Build Phases>Link Binary with Library> Click on +> select AVFoundation> Add]
// get file path
NSString *soundPath = [[NSBundle mainBundle] pathForResource: fileNameToPlay ofType:#"mp3"];
// allocate and refer to file
AVAudioPlayer *player =[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath: soundPath] error: NULL];
// set delegate
player. delegate = self;
// play
[player play];
Apparently this turned out to be quite a mess, but I found a solution. I'm running XCode 4.4.1.
Here are the steps that worked for me:
Drag mp3 file from finder into XCode project -> Supporting Files. Make sure to copy the file. let's assume the file name is sound.mp3.
Add AVFoundation framework to your project.
import < AVFoundation/AVFoundation.h>
#property (strong) AVAudioPlayer* soundPlayer;
use the following code to init the player and play the mp3:
NSURL *chemin = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/sound.mp3", [[NSBundle mainBundle] resourcePath]]];
NSError *error;
self.soundPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:chemin error:&error];
[self.soundPlayer play];
Now at this point, I got an exception which is described here: AVFoundation iOS 5
In short it means that there is probably a bug in the simulator which shouldn't happen on the device. In my case I turned all exception on, which stopped my code from executing. What you should do is to remove the option of throwing all exceptions.
In addition, in my case it's 3-5 seconds until it first play the sound, so be patient when you don't get the sound right away. After it play for the first time, it will play instantly.

AVAudio Player gets delayed while loading for the first time

NSString *path = [[NSBundle mainBundle] pathForResource:#"hit-pipe" ofType:#"wav"];
audioPlayer =[[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:path] error:nil];
[self.audioPlayer setDelegate:self];
[self.audioPlayer prepareToPlay];
[self.audioPlayer play];
It takes time to load the sound for the first time.
It takes time to load because it is loading the file. There will always be a tiny bit of usually unnoticeable lag when you play an AVAudioPlayer, and more lag when you load the file. How much lag depends on the size and file format of your file. If it is a problem, try allocating and loading your AVAudioPlayer earlier or using a smaller sound file.
You could put the code to load when the app is loading (for example in init or viewDidLoad). Then call audioplayer play when you need to play it. I'm doing this for my app and I did not notice any delay. It plays instantly when I call it.

AVAudioPlayer Help: Playing multiple sounds simultaneously, stopping them all at once, and working around Automatic Reference Counting

I am trying to create buttons that play single sound files and one button that stops all of the sounds that are currently playing. If the user clicks multiple buttons or the same button in a short amount of time, the app should be playing all of the sounds simultaneously. I have accomplished this without much difficulty using the System Sound Services of iOS. However, the System Sound Services play the sounds through the volume that the iPhone's ringer is set to. I am now trying to use the AVAudioPlayer so that users can play the sounds through the media volume. Here is the code that I am currently (yet unsuccessfully) using the play the sounds:
-(IBAction)playSound:(id)sender
{
AVAudioPlayer *audioPlayer;
NSString *soundFile = [[NSBundle mainBundle] pathForResource:#"Hello" ofType:#"wav"];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:soundFile] error:nil];
[audioPlayer prepareToPlay];
[audioPlayer play];
}
Whenever I run this code in the iPhone Simulator, it does not play the sound but does display a ton of output. When I run this on my iPhone, the sound simply does not play. After doing some research and testing, I found that the audioPlayer variable is being released by Automatic Reference Counting. Also, this code works when the audioPlayer variable is defined as an instance variable and a property in my interface file, but it does not allow me to play multiple sounds at once.
First thing's first: How can I play an infinite number of sounds at once using the AVAudioPlayer and sticking with Automatic Reference Counting? Also: When these sounds are playing, how can I implement a second IBAction method to stop playing all of them?
First off, put the declaration and alloc/init of audioplayer on the same line. Also, you can only play one sound per AVAudioPlayer BUT you can make as many as you want simultaneously. And then to stop all of the sounds, maybe use a NSMutableArray, add all of the players to it, and then iterate though and [audioplayer stop];
//Add this to the top of your file
NSMutableArray *soundsArray;
//Add this to viewDidLoad
soundsArray = [NSMutableArray new]
//Add this to your stop method
for (AVAudioPlayer *a in soundsArray) [a stop];
//Modified playSound method
-(IBAction)playSound:(id)sender {
NSString *soundFile = [[NSBundle mainBundle] pathForResource:#"Hello" ofType:#"wav"];
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:soundFile] error:nil];
[soundsArray addObject:audioPlayer];
[audioPlayer prepareToPlay];
[audioPlayer play];
}
That should do what you need.

Memory Management Help with Sounds being played - iPhone Programmingv

I'm beginning iPhone programming and I am trying to make a little test app which plays a sound when you press a button. This question is pretty noob so bear with me. Pretty much I'm trying to figure out how to handle the memory situation. Where do I release the instances created so as to avoid memory issues? Right now if I click on the button multiple times quickly the app crashes. I tried declaring everything in viewDidLoad and putting the release in the dealloc method, but under this design I have to wait until the entire sound is done playing before being able to play the sound again. I want to be able to press the button in the middle of a sound being played and "interrupt it" if that makes sense.
The way its written now is when you press a button, this method is called and the sound is played
-(IBAction)buttonPressed:(id)sender{
NSString *path = [[NSBundle mainBundle] pathForResource:#"filename" ofType:#"mp3"];
AVAudioPlayer* theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error: NULL];
theAudio.delegate = self;
[theAudio play];
}
In this set up it works so that I can "interrupt" an already playing sound by pressing the button again and the sound restarts. However pressing it quickly makes the app crash.
You should release immediately before you exit the method like so:
-(IBAction)buttonPressed:(id)sender{
NSString *path = [[NSBundle mainBundle] pathForResource:#"filename" ofType:#"mp3"];
AVAudioPlayer* theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error: NULL];
theAudio.delegate = self;
[theAudio play];
[theAudio release];
}
or something like that.
Because when you alloc/init a local variable you assign it a retain count of +1. But when you exit the method the reference to that var is still living and you can't access it, which leads in memory leaking. Try to begin from: Memory Management. Good luck.

AVAudioPlayer not responding

I initialize an AVAudioPlayer instance:
NSString* path = [[NSBundle mainBundle] pathForResource:#"foo" ofType:#"wav"];
AVAudioPlayer* player =[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:nil]; //Returned object not nil, indicating that the file has loaded successfully
BOOL b = [player prepareToPlay]; //returns TRUE
BOOL b2 = [player play];
//returns TRUE, goes immediately to the next line since asynchronous
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]; //wait 1 sec
printf("%10.4f\n",player.duration); //duration is 2s
printf("%10.4f\n",player.currentTime); //position remains 0
/* There is no sound output, player is also stuck since position==0 */
Does anyone know why the AVAudioPlayer is not responding? Is there something that I am overlooking while initializing, playing the audioplayer? Boilerplate code maybe?
I am running this on the iPhone simulator. Also, AudioServicesPlaySystemSound() works for the same file, which is puzzling, but this indicates that sound playback might work with AVAudioPlayer as well.
I have 2 quick suggestions:
Check to see if that path actually gives you data. Alloc a NSData object using [[NSData alloc] initWithContentsOfFile:path] and inspect it in the debugger to see if you're actually loading that wav file.
I wrote a sample project that uses AVAudioPlayer here: AVAudioPlayer Example. As the code is pretty much the same as yours, the only thing I can imagine is that there is a problem with your data.
Check those out and see if it gets you anywhere!
I have just had a similar problem. I am not sure if it is the same solution, but my application records audio through the iphone and then plays it back to the user.
I thought I was doing the correct thing by telling my audio session that it was going to record data, so I did the following:
[audioSession setCategory:AVAudioSessionCategoryRecord error:nil];
Using this setting playback worked on the Simulator but not on the device.... the didFinishPlaying event never got raised.
I removed this line after realising I didn't need it an audio playback started working correctly. Now I just need to work out why it is so quiet :)
Paul