AVAudioPlayer leaks? - iphone

I've got a problem and don't know how to handle it. Tyring to build an app with sound and animation. It gives me a level 1 and then level 2 memory warning. I've tried build and analyze and i got all these potential leaks. If I release theAudio the sound won't play. Any hints?
Here is a part of the code and the leakes I've got
- (IBAction)playsound2
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"cat" ofType:#"mp3"];
AVAudioPlayer* theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
*- **Method returns an Objective-C object with a +1 retain count (owning reference)***
theAudio.delegate = self;
[theAudio play];
***- Object allocated on line 302 and stored into 'theAudio' is no longer referenced after this point and has a retain count of +1 (object leaked)***
cat1.hidden = 0;
cat.hidden = 1;
[cat1 startAnimating];
cat.center = cat1.center;
[self performSelector:#selector(loadAnimations) withObject:nil afterDelay:1.0];
catLabel.hidden = 0;
}

Here is the solution for the same problem asked so far.
- (AVAudioPlayer *)audioPlayerWithContentsOfFile:(NSString *)path {
NSData *audioData = [NSData dataWithContentsOfFile:path];
AVAudioPlayer *player = [AVAudioPlayer alloc];
if([player initWithData:audioData error:NULL]) {
[player autorelease];
} else {
[player release];
player = nil;
}
return player;
}
And for better idea you can follow this.

You have to state an instance variable for the AVAudioPlayer class instance.
//Instance variable:
{
AVAudioPlayer* theAudio;
}
- (IBAction)playsound2
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"cat" ofType:#"mp3"];
if (!theAudio ) {
theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
if (theAudio ) {
theAudio.delegate = self;
[theAudio play];
}
}
cat1.hidden = 0;
cat.hidden = 1;
[cat1 startAnimating];
cat.center = cat1.center;
[self performSelector:#selector(loadAnimations) withObject:nil afterDelay:1.0];
catLabel.hidden = 0;
}

Related

Can AVFoundation play Audio and get Details of it On the IOS 5.0 Simulator?

Can the Above be Done using only AVFoundation.framework?
i Tried doing a few experiment but i can't really get it to work
(sorry newbie here please do tell me where to put the codes at Example: ViewController or the MainView)
These are my code,(UI Components are inside as i'm do not want use interface builder)
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
NSError *error;
buttonPlay = [[UILabel alloc] initWithFrame:CGRectMake(0, 350, 100, 50)];
buttonPlay.text = #"Play";
// Get the file path to the song to play.
NSString* path;
NSURL* url;
path = [[NSBundle mainBundle] pathForResource:#"Bring_Me_To_Life.mp3" ofType:nil];
url = [NSURL fileURLWithPath:path];
NSData *_objectData = [NSData dataWithContentsOfURL:url];
//Initialize the AVAudioPlayer.
audioPlayer = [[AVAudioPlayer alloc] initWithData:_objectData error:&error];
// Preloads the buffer and prepares the audio for playing.
audioPlayer.numberOfLoops = 0;
audioPlayer.volume = 1.0f;
[audioPlayer prepareToPlay];
if (audioPlayer == nil)
NSLog(#"%#", [error description]);
else
[audioPlayer play];
[self addSubview:buttonPlay];
}
return self;
}
-(void)touchesBegan:(CGPoint)location{
if(CGRectContainsPoint(buttonPlay.frame, location)){
NSLog(#"Dec from Chl %f",[audioPlayer peakPowerForChannel:0]);
NSLog(#"Length of Clip %f",[audioPlayer duration]);
}
}
try this
audioPlayer=[[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];

UIButtons event Touch up Inside not work properly?

My question is little abmigious ,thats why I posted all my code,so I request to every one please test all this code before giving me the Answer.Thanx
In my application i create all UIButtons programmatically and then save all these UIButtons in NSMutableArray. Here is my code:-
-(void)button:(id)sender
{
int btnn = 0;
int spacex = 152;
int spacey=20;
int k=0;
saveBtn = [[NSMutableArray alloc] init];
for (int i=0; i<48; i++)
{
if (btnn>6)
{
spacey=spacey+25;
spacex = 152;
btnn = 0;
}
else
{
btnn++ ;
k++;
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(spacex, spacey, 25.0, 25.0);
int idx;
idx = arc4random()%[arr count];
NSString* titre1 = [arr objectAtIndex:idx];
[btn setTitle: titre1 forState: UIControlStateNormal];
[btn setTitleColor: [UIColor yellowColor] forState: UIControlStateNormal];
[btn.titleLabel setFont:[UIFont fontWithName:#"TimesNewRomanPS-BoldMT" size:22.0]];
spacex = spacex + 25;
btn.tag=k;
[btn addTarget:self action:#selector(aMethod:)forControlEvents:UIControlEventTouchUpInside];
[saveBtn addObject:btn];
[self.view addSubview:btn];
}
}
}
Now in (aMethod:) I add click sound on Each UIButton TouchUpInside event. Here is my code.
- (void)aMethod:(id)sender
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"button-17" ofType:#"wav"];
AVAudioPlayer* theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate=self;
[theAudio play];
}
Every thing work fine in start of my application , but continiously clicking the UIButtons approximatilly after 100 clicks i hear no sound of click and when i click on Next UIButtons touchup inside event its crash.Can any body help me in this issue.Thanx
app due to uncaught exception NSInternalInconsistencyException, reason: Could not load NIB in bundle: NSBundle </Users/moon/Library/Application Support/iPhone Simulator/4.1/Applications/3E14E5D6-4D1B-4DAC-A2B9-07667E99C399/soundtesting.app‌​> (loaded) with name secondclass
Ah, yes. What we have here is a failure to understand log messages. Your UIButton, which I can only assume pushes a new view onto the stack, is referencing a NIB that simply doesn't exist. It's a naming issue, not a button issue. Most likely, I would check for any calls to -initWithNibName: and see if your NIB really is named "secondclass.". Remember, iOS file names are CaSe SeNsITive.
//.h
...
#property (nonatomic, retain) AVAudioPlayer * player;
//.m
-(void)viewDidLoad
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"button-17" ofType:#"wav"];
player=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
player.delegate=self;
//in MRC, use [path release];
}
-(void)someMethod:(id)sender
{
[player play];
}
The reason might me memory leak for playing same audio these many times it may fill memory use this code for playing audio
- (id)initWithNibName:(NSString*)nibName bundle:(NSBundle*)nibBundleOrNil
{
if (self = [super initWithNibName:nibName bundle:nibBundleOrNil]) {
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"button-17" ofType:#"wav"];
theAudio = [AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:filePath] error:NULL];
}
return self;
}
- (IBAction)playSound
{
[theAudio play];
}
- (void)dealloc
{
[theAudio release];
[super dealloc];
}
You have a memory issue. When you do :
- (void)aMethod:(id)sender
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"button-17" ofType:#"wav"];
AVAudioPlayer* theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate=self;
[theAudio play];
}
1/ path is never released
2/ theAudio is never release
So you need to release theAudio in delegate method :
– audioPlayerDidFinishPlaying:successfully:
And you need to release path like this :
- (void)aMethod:(id)sender
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"button-17" ofType:#"wav"];
AVAudioPlayer* theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate=self;
[theAudio play];
[path release];
}
I think your problem should be solved.
I test your code . Changes in your aMethod following code. Though this I can get tag value.
- (void)aMethod:(id)sender
{
UIButton *btn=(UIButton *)sender;
NSLog(#"\n\n\nselectedbutton tag === %d \n\n\n",btn.tag );
NSString *path = [[NSBundle mainBundle] pathForResource:#"button-17" ofType:#"wav"];
NSURL *url = [[NSURL alloc] initFileURLWithPath:path];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:NULL];
audioPlayer.delegate = self;
[audioPlayer prepareToPlay];
[audioPlayer play];
}

Audio (mp3) file issue, file is not played at number of button press

I have set music file on button click in the memory game application.
Music is properly played, for some time but after the number of the buttons click looses the sound effect from the applcation.
-(void)setButtons_AsPerTheMatrixSelection
{
for ( i = 0 ; i < cv ; ++i )
{
for ( j = 0 ; j < ch ; ++j )
{
btnMatrix = [[[UIButton alloc] initWithFrame:CGRectMake(10+pw*j, 51+ph*i, width, height)] autorelease];
btnMatrix.tag = i*ch+j;
btnMatrix.userInteractionEnabled = TRUE;
bulImageStatus = FALSE;
[btnMatrix addTarget:self action:#selector(changeImage:) forControlEvents:UIControlEventTouchUpInside];
[btnMatrix setImage:imgDefaultBG forState:UIControlStateNormal];
[viewWithButtons addSubview:btnMatrix];
[arrButton addObject:btnMatrix];
}
}
}
-(void)changeImage:(id)sender
{
NSString *musicPath = [[NSBundle mainBundle] pathForResource:#"ding" ofType:#"mp3"];
if (musicPath)
TapSoud = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:musicPath] error:nil];
[TapSoud setDelegate:self];
[TapSoud prepareToPlay];
[TapSoud play];
}
This is working perfectly for number of presses but after certain click i am not able to play this button click tone.
what can be the issue & how can be solved this issue.
Is there any other way to play audio file?
Please suggest the appropriate solution.
Thanks.
AVAudioPlayer is alloced over and over but never released.
try this.
-(void)changeImage:(id)sender
{
NSString *musicPath = [[NSBundle mainBundle] pathForResource:#"ding" ofType:#"mp3"];
if (musicPath) {
if(TapSoud){ // TapSound ?
[TapSoud release];
TapSoud = nil;
}
TapSoud = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL
fileURLWithPath:musicPath] error:nil];
}
[TapSoud setDelegate:self];
[TapSoud prepareToPlay];
[TapSoud play];
}
Use same AVAudioPlayer refrence every time u play:
-(void)changeImage:(id)sender
{
NSString *musicPath = [[NSBundle mainBundle] pathForResource:#"ding" ofType:#"mp3"];
if (musicPath) {
if(!TapSoud){ // check TapSound has reference
TapSoud = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:musicPath] error:nil];
[TapSoud setDelegate:self]
}
else
{
NSNumber *time = [NSNumber numberWithDouble:0];
//NSTimeInterval interval = [time doubleValue];
[TapSoud playAtTime:[time doubleValue];// Smae Sound played at time 0:00
}
}
}

stopping an AVAudioPlayer

here is my code
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"95" ofType:#"wav"];
NSError *activationError = nil;
NSError *audioPlayerInitError = nil;
[[AVAudioSession sharedInstance] setActive: YES error:&activationError];
NSURL *newURL = [NSURL fileURLWithPath:soundFilePath];
musicPlayer1 = [[AVAudioPlayer alloc] initWithContentsOfURL:newURL error:&audioPlayerInitError];
if (musicPlayer1) {
[musicPlayer1 stop];
[musicPlayer1 release];
musicPlayer1 = nil;
}
else {
[musicPlayer1 prepareToPlay];
[musicPlayer1 setVolume:.8];
[musicPlayer1 setNumberOfLoops:-1]; // -1 means play indefintely
[musicPlayer1 setDelegate: self];
[musicPlayer1 play];
}
}
I am rying to start and stop the AVAudioPlay with the same button (musicPlayer1 is in the header). Now when i touch the button it does not play anything. Help please?
You're creating a new instance of AVAudioPlayer each time. You need to hold onto the reference to the object somewhere, and refer back to that. Add a field to your view controller class:
#private AVAudioPlayer *currentAudio;
And then in this method, make the following changes:
if (currentAudio) {
[currentAudio stop];
[currentAudio release];
currentAudio = nil;
} else {
// what you already have goes here
}

iphone piano app doesnt play notes as expected

Im making a piano test app, all the keyboard is sounding now playing notes that I've recorded using garage band, but I have some problems:
-the notes are 5 seconds long (minimum time of garage band), so a note cannot be repeated, I have to wait until the actual note about 1 sec sound and then silence for about 4 sec,
also sometimes notes cannot be played as expected,
Im using AVFoundation.framework,,
tried with AudioToolbox.framework, but it gives problems with my 4.1 ipod touch (doesnt work!!) but in the simulator looks fine
I also checked OpenAL, and ObjectAL, but seem a bit to much for just playing notes??
here the code
#import "pianoViewController.h"
#implementation pianoViewController
#synthesize myMusic;
#synthesize myMusic2;
#synthesize myMusic3;
#synthesize myMusic4;
#synthesize myMusic5;
#synthesize myMusic6;
#synthesize myMusic7;
#synthesize myMusic8;
#synthesize myMusic9;
#synthesize myMusic10;
#synthesize myMusic11;
#synthesize myMusic12;
-(IBAction)Play{
[myMusic play];
}
-(IBAction)Play2{
[myMusic2 play];
}
.
.
.
- (void)viewDidLoad {
NSString *pathToMusicFile = [[NSBundle mainBundle] pathForResource:#"c3" ofType:#"aif"];
myMusic = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:pathToMusicFile] error:NULL];
myMusic.delegate = self;
myMusic.numberOfLoops = 0;
myMusic.volume = 1.0;
NSString *pathToMusicFile2 = [[NSBundle mainBundle] pathForResource:#"c#" ofType:#"aif"];
myMusic2 = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:pathToMusicFile2] error:NULL];
myMusic2.delegate = self;
myMusic2.numberOfLoops = 0;
myMusic2.volume = 1.0;
NSString *pathToMusicFile3 = [[NSBundle mainBundle] pathForResource:#"d" ofType:#"aif"];
myMusic3 = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:pathToMusicFile3] error:NULL];
myMusic3.delegate = self;
myMusic3.numberOfLoops = 0;
myMusic3.volume = 1.0;
//[super viewDidLoad];
NSString *pathToMusicFile4 = [[NSBundle mainBundle] pathForResource:#"d#" ofType:#"aif"];
myMusic4 = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:pathToMusicFile4] error:NULL];
myMusic4.delegate = self;
myMusic4.numberOfLoops = 0;
myMusic4.volume = 1.0;
//[super viewDidLoad];
NSString *pathToMusicFile5 = [[NSBundle mainBundle] pathForResource:#"e" ofType:#"aif"];
myMusic5 = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:pathToMusicFile5] error:NULL];
myMusic5.delegate = self;
myMusic5.numberOfLoops = 0;
myMusic5.volume = 1.0;
NSString *pathToMusicFile6 = [[NSBundle mainBundle] pathForResource:#"f" ofType:#"aif"];
myMusic6 = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:pathToMusicFile6] error:NULL];
myMusic6.delegate = self;
myMusic6.numberOfLoops = 0;
myMusic6.volume = 1.0;
NSString *pathToMusicFile7 = [[NSBundle mainBundle] pathForResource:#"f#" ofType:#"aif"];
myMusic7 = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:pathToMusicFile7] error:NULL];
myMusic7.delegate = self;
myMusic7.numberOfLoops = 0;
myMusic7.volume = 1.0;
NSString *pathToMusicFile8 = [[NSBundle mainBundle] pathForResource:#"g" ofType:#"aif"];
myMusic8 = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:pathToMusicFile8] error:NULL];
myMusic8.delegate = self;
myMusic8.numberOfLoops = 0;
myMusic8.volume = 1.0;
NSString *pathToMusicFile9 = [[NSBundle mainBundle] pathForResource:#"g#" ofType:#"aif"];
myMusic9 = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:pathToMusicFile9] error:NULL];
myMusic9.delegate = self;
myMusic9.numberOfLoops = 0;
myMusic9.volume = 1.0;
NSString *pathToMusicFile10 = [[NSBundle mainBundle] pathForResource:#"a" ofType:#"aif"];
myMusic10 = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:pathToMusicFile10] error:NULL];
myMusic10.delegate = self;
myMusic10.numberOfLoops = 0;
myMusic10.volume = 1.0;
NSString *pathToMusicFile11 = [[NSBundle mainBundle] pathForResource:#"a#" ofType:#"aif"];
myMusic11 = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:pathToMusicFile11] error:NULL];
myMusic11.delegate = self;
myMusic11.numberOfLoops = 0;
myMusic11.volume = 1.0;
NSString *pathToMusicFile12 = [[NSBundle mainBundle] pathForResource:#"b" ofType:#"aif"];
myMusic12 = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:pathToMusicFile12] error:NULL];
myMusic12.delegate = self;
myMusic12.numberOfLoops = 0;
myMusic12.volume = 1.0;
[super viewDidLoad];
}
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end
So is there a way so that i can use AVFoundation to play multiple notes quickly? (almost overlapping like with AudioToolbox)
or what do you suggest?
thank you!
Instead of shoe-horning in a fix for something that shouldn't be a problem, I suggest instead that you use some audio editing software that does not have a minimum track length restriction.
One such example, which is Mac compatible and free, is Audacity: http://audacity.sourceforge.net/
Also, OpenAL is perfect for playing lots of short sounds, potentially overlapping. I think you can have 32 playing at once if you like.