iPhone Load Audio File Question - iphone

I am currently loading an audio file inside of a button. I am assuming there is a more efficient way to load this file instead of every time the button is pressed. Where should this be loaded? Globally, inside viewdidload. I'm loading it like the code below.
NSString *path = [[NSBundle mainBundle] pathForResource:#"click" ofType:#"mp3"];
AVAudioPlayer* theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate=self;

viewDidLoad is a good idea -- will let you free up the memory in viewDidUnload too in case you are short on memory. You could also implement getters and setters in the code below by synthesizing theAudio and using self.theAudio
#interface myClass {
AVAudioPlayer *theAudio;
}
#implementation myClass {
- (void) viewDidLoad {
NSString *path = [[NSBundle mainBundle] pathForResource:#"click" ofType:#"mp3"];
theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate=self;
}
- (void) viewDidUnload {
[theAudio release];
}
}

Related

My Application crashes when playing a sound

I am trying to play a sound on the click of a button. But when I run the app it crashes and I get Thread 1 : signal SIGABRT.
This is my code:
.h file
#import <AVFoundation/AVFoundation.h>
#interface HljodViewController : UIViewController <AVAudioPlayerDelegate>{
}
-(IBAction)playsound;
.m file
-(IBAction)playsound {
NSString *path = [[NSBundle mainBundle] pathForResource:#"Geese_4" ofType:#"mp3"];
AVAudioPlayer* theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.numberOfLoops = 1;
[theAudio play];
}
No one can tell you how to solve your issue if you don't capture the NSError. I suggest you do the following:
NSError *outError = nil;
AVAudioPlayer* theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:&outError];
if (outError)
{
NSLog(#"%#", [outError localizedDescription]);
}
... // continue on to happy time
try this:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive:YES error:nil];
NSString *path = [[NSBundle mainBundle] pathForResource:#"yourfile" ofType:#"mp3"];
NSError *error;
AVAudioPlayer *sound = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:&error];
[sound play];

How do I auto play Audio files?

Heres what I have:
-(void)awakeFromNib {
NSString *path = [[NSBundle mainBundle] pathForResource:***AUDIOFILE*** ofType:#"mp3"];
AVAudioPlayer* theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path]
error:NULL];
[theAudio play];
The coding is fine, except I don't know how to call out my resource for the sound to play or whatever.
If your Audio file is inside your project then you just need to give Filename without extension in place of *AUDIOFILE*.
It is good practice to use [theAudio prepareToPlay] method for AVAudioPlayer.

Audio Controller stop button

I am trying to make an audio controller, but the stop button doesn't work. But I don't know why. How is this caused and how can I solve it?
.h
#import <UIKit/UIKit.h>
#import <AVFoundation/AVAudioPlayer.h>
#interface myprojectViewController : UIViewController {
AVAudioPlayer* theAudio;
}
- (IBAction)start:(id)sender;
- (IBAction)stop:(id)sender;
#end
.m
- (IBAction)start:(id)sender{
NSString *path = [[NSBundle mainBundle] pathForResource:#"LE" ofType:#"wav"];
AVAudioPlayer* theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate = self;
[theAudio play];
}
- (IBAction)stop:(id)sender{
[theAudio stop];
}
'theAudio' is a local variable in your start() method. You've declared it as a local variable, so it is out of scope in your stop() method, and you have an invalid reference. You need to use the class variable 'theAudio. Change :
AVAudioPlayer* theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
to
self.theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];

AVAudioPlayer Leak and Crash

I want to play multiple audio files (.WAV) using IBAction and AVAudioPlayer. Unfortunatelly the sound plays but if I play the sound many times, my application crashes. Can you help me?
Here's my code.
ViewController.h
#import <UIKit/UIKit.h>
#import <AVFoundation/AVAudioPlayer.h>
#interface ViewController : UIViewController <AVAudioPlayerDelegate>
{
NSString *Path;
}
- (IBAction)Sound1;
- (IBAction)Sound2;
- (IBAction)Sound3;
- (IBAction)Sound4;
#end
ViewController.m
#import <AVFoundation/AVAudioPlayer.h>
#import "ViewController.h"
#implementation ViewController
AVAudioPlayer *Media;
- (IBAction)Sound1
{
Path = [[NSBundle mainBundle] pathForResource:#"Sound1" ofType:#"wav"];
Media = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:Path] error:NULL];
[Media setDelegate:self];
[Media play];
}
- (IBAction)Sound2
{
Path = [[NSBundle mainBundle] pathForResource:#"Sound2" ofType:#"wav"];
Media = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:Path] error:NULL];
[Media setDelegate:self];
[Media play];
}
- (IBAction)Sound3
{
Path = [[NSBundle mainBundle] pathForResource:#"Sound3" ofType:#"wav"];
Media = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:Path] error:NULL];
[Media setDelegate:self];
[Media play];
}
- (IBAction)Sound4
{
Path = [[NSBundle mainBundle] pathForResource:#"Sound4" ofType:#"wav"];
Media = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:Path] error:NULL];
[Media setDelegate:self];
[Media play];
}
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
[player release];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (void)dealloc
{
[Media Release];
[super dealloc];
}
#end
There are a couple things that look wrong in your code:
(1). There are no method Release, [Media Release] should be [Media release];
(2). If you play Sound2 while Sound1 is still playing, you leak Media instance:
Media = [[AVAudioPlayer alloc] initWithContentsOfURL:...
This allocates new player and overwrites old one without releasing it first;
(3). It is usually bad idea to release calling object in delegate;
(4). I'd also suggest to rename Media to media and Path to path.
So playing action should look like this:
- (IBAction)playSound1
{
path = [[NSBundle mainBundle] pathForResource:#"Sound1" ofType:#"wav"];
media = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
[media play];
[media release];
}

Choose a file randomly from Resources folder in iOS

I have one thousand .mp3 files in my Resources folder within an iOS 4.2 XCode project.
For now I can select one file from the folder ( and play it ) with the following code in my .m file: ( Given the file name of "AFile.mp3" )
-(IBAction)playSound {
NSString *path = [[NSBundle mainBundle] pathForResource:#"AFile"ofType:#"mp3"];
AVAudioPLayer* theAudio =[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate = self;
[theAudio play];
}
I'd like to be able to have the code choose an .mp3 randomly, play it, then select another file and play them all until they have all been played at least once. I assume I will need to use an NSArray, but am uncertain on how to proceeed.
I changed the code to the following, and am not getting any errors when I run this in the iOS Simulator. No File appears to be played when I run it though? When I launch the app, it quits, but does not log any errors in the Debugger..
Updated code:
-(IBAction)playSound {
NSArray *array = [[NSBundle mainBundle] pathsForResourcesOfType:#".mp3" inDirectory:#"Resources"];
NSString *randomPath = [array objectAtIndex:arc4random() % [array count]];
AVAudioPlayer* theAudio =[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath: randomPath] error: NULL;
theAudio.delegate = self;
[theAudio play];
}
How can an I set up a simple array of the 1000 .mp3 files, and have the method play one at random?
AVAudioPlayer* theAudio=[[AVAudioPlayer alloc]initWithContentsofURL: [NSURL arrayURLWithPath:array] error:NULL];
should be:
AVAudioPlayer* theAudio=[[AVAudioPlayer alloc]initWithContentsofURL: [NSURL URLWithString:[array objectAtIndex:11]] error:NULL];
therefore the number '11' is a random file path. To get randomness you can use this:
int randomNumber = random()%1000; // random number between 0 and 1000
and then use randomNumber instead of 11
To play each file only one time you can play let's say song number four one time and then remove this item from your array. The next time you generate a random number use 999 instead of 1000 and so on till it gets to 1.
//EDIT: try following:
-(IBAction)playSound {
NSArray *array = [[NSBundle mainBundle] pathsForResourcesOfType:#".mp3" inDirectory:#"Resources"];
int rndm = arc4random() % [array count];
if (rndm<0) rndm*=-1;
NSString *randomPath = [array objectAtIndex:rndm];
AVAudioPlayer* theAudio =[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath: randomPath] error: NULL;
theAudio.delegate = self;
[theAudio play];
}
Use this snippet. from a previous SO answer
NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];
NSArray *dirContents = [[NSFileManager defaultManager] directoryContentsAtPath:bundleRoot];
NSArray *onlyJPGs = [dirContents filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"self ENDSWITH '.jpg'"]];
then get the array count.. and use random to get the random integer number and file.
Ok after looking into the apple documents here is the error. Somehow the even if we specify a custom directory it seems to be only for reference. The other mistake that I have found is that we only need to specify the extension without the "."
NSArray *audioPathArray = [[NSBundle mainBundle] pathsForResourcesOfType:#"mp3" inDirectory:nil];
NSLog(#"%d",[audioPathArray count]);
NSString *path = [audioPathArray objectAtIndex:arc4random() % [audioPathArray count]];
NSURL *randomPath = [[NSURL alloc]initFileURLWithPath:path];
AVAudioPlayer *theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:randomPath error:NULL];
[theAudio play];
This is what worked for me. Hope it helps you out.
Well, if you already have a reference to the array on which you would like to retrieve a random element from, then it's dead simple:
NSString *randomPath = [array objectAtIndex:arc4random_uniform([array count])];
Also, arc4random() is much better than rand()
Got it working on my project
When you import the Resources folder to your project select "Create folder references for any added folders". This will actually maintain the directory structure in your [NSBundle mainBundle].
You can then pull the contents like so:
NSString * bundlePath = [NSBundle mainBundle] bundlePath];
NSString * resourceFolderPath = [NSString stringWithFormat:#"%#/Resources", bundlePath];
NSArray * resourceFiles = [[NSFileManager defaultManager] directoryContentsAtPath:resourceFolderPath error:nil];
resourceFiles should contain a list of the contents of your Resources directory.
NSInteger randomFileIndex = arc4random() % [resourceFiles count];
NSString * randomFile = [resourceFiles objectAtIndex:randomFileIndex];