AVAudioPlayer isPlaying crashing app - objective-c

I'm using an AVAudioPlayer to manage some sounds but the isPlaying method seems to be crashing.
done when I initiate the page:
self.soundClass = [AVAudioPlayer alloc];
how I play the sound:
-(void)playSound:(NSString *)fileName:(NSString *)fileExt {
if ( [self.soundClass isPlaying] ){
[self.soundClass pause];
}
else if (newSoundFile == currentSoundFile) {
[self.soundClass play];
}
else {
NSLog(#"PlaySound with two variable passed function");
[[NSBundle mainBundle] pathForResource: fileName ofType:fileExt]], &systemSoundID);
[self.soundClass initWithContentsOfURL:[NSURL fileURLWithPath: [[NSBundle mainBundle] pathForResource: fileName ofType:fileExt]] error:nil];
[self.soundClass prepareToPlay];
[self.soundClass play];
}
self.currentSoundFile = fileName;
}
My soundClass is pretty empty right now:
soundclass.h
#import <UIKit/UIKit.h>
#import <AudioToolbox/AudioToolbox.h>
#import<AVFoundation/AVFoundation.h>
#interface SoundClass : AVAudioPlayer <AVAudioPlayerDelegate> {
}
#end
SoundClass.m
#import "SoundClass.h"
#implementation SoundClass
-(void)dealloc {
[super dealloc];
}
#end
Do you see anything here I might be doing wrong? It crashes right at if ( isPlaying )

You point to space that is allocated for an instance of AVAudioPlayer in the first line you list, but you don't actually initialize an instance. In Cocoa, "alloc" is 99.9% of the time followed by some form of -init (like -initWithContentsOfURL:error: in the case of AVAudioPlayer).
Also, "soundClass" is an odd name for an instance variable. You should read up on the difference between a class (the blueprint of an object) and an instance of a class (an actual object built from the blueprint). Solid knowledge of this concept is critical to your understanding of Cocoa (and all object-oriented) programming.

Related

pointer loop to integer conversion?

The code is suppose to make a sound either yes or yes 3 play when clicked, but I get an error before I begin to debug that says rand cannot be statically allocated, but I can't put a * there because it's an integer. I am getting a conversion error when I do that. I also tried putting a * before sound, and that solved the error issue but when the button is clicked it wont play anything. So what do I do?
#import "ViewController.h"
#import <AVFoundation/AVAudioPlayer.h>
#interface ViewController ()
#end
#implementation
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}//this is where the error breakpoint is that you show me how to make
- (IBAction)Yes {
NSInteger rand = arc4random_uniform(2);
NSString sound = rand == 0 ? #"yes" : #"yes 3";
NSURL *url = [[NSBundle mainBundle] URLForResource:sound withExtension:#"mp3"];
AVAudioPlayer* audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[audioPlayer play];
}
#end
I've seen this many times before, and it has to do with the fact that your audio player variable is being released before it has a chance to play the file.
You need to create a property for the audio player in your header:
#property (nonatomic, strong) AVAudioPlayer *audioPlayer;
Then in your method access that property instead of the local variable:
- (IBAction)YES {
NSInteger rand = arc4random_uniform(2);
NSString *sound = rand == 0 ? #"yes" : #"yes 3";
NSURL *url = [[NSBundle mainBundle] URLForResource:sound withExtension:#"mp3"];
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[self.audioPlayer play];
}
Note that this has absolutely nothing to do with the sound variable you're messing with. You should be using the * to indicate a pointer when creating that variable, as shown above.

IOS can I use AVAudioPlayer on the appDelegate?

I have a TabBarController with two tabs and I want to play music on both tabs. Right now I have my code on the main appDelegate
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
pathForResource:#"My Song"
ofType:#"m4a"]]; // My Song.m4a
NSError *error;
self.audioPlayer = [[AVAudioPlayer alloc]
initWithContentsOfURL:url
error:&error];
if (error)
{
NSLog(#"Error in audioPlayer: %#",
[error localizedDescription]);
} else {
//audioPlayer.delegate = self;
[audioPlayer prepareToPlay];
}
but I'm getting the error Program received signal: "SIGABRT" on UIApplicationMain
Is there a better way to accomplish what I'm trying to do? If this is how I should do it, where do I start checking for problems?
yes you can use AVAudioPlayer in App Delegate.
What you need to do is:-
In appDelegate.h file do:-
#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioToolbox.h>
AVAudioPlayer *_backgroundMusicPlayer;
BOOL _backgroundMusicPlaying;
BOOL _backgroundMusicInterrupted;
UInt32 _otherMusicIsPlaying;
Make backgroundMusicPlayer property and sythesize it.
In appDelegate.m file do:-
Add these lines in did FinishLaunching method
NSError *setCategoryError = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&setCategoryError];
// Create audio player with background music
NSString *backgroundMusicPath = [[NSBundle mainBundle] pathForResource:#"SplashScreen" ofType:#"wav"];
NSURL *backgroundMusicURL = [NSURL fileURLWithPath:backgroundMusicPath];
NSError *error;
_backgroundMusicPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:backgroundMusicURL error:&error];
[_backgroundMusicPlayer setDelegate:self]; // We need this so we can restart after interruptions
[_backgroundMusicPlayer setNumberOfLoops:-1]; // Negative number means loop forever
Now implement delegate methods
#pragma mark -
#pragma mark AVAudioPlayer delegate methods
- (void) audioPlayerBeginInterruption: (AVAudioPlayer *) player {
_backgroundMusicInterrupted = YES;
_backgroundMusicPlaying = NO;
}
- (void) audioPlayerEndInterruption: (AVAudioPlayer *) player {
if (_backgroundMusicInterrupted) {
[self tryPlayMusic];
_backgroundMusicInterrupted = NO;
}
}
- (void)tryPlayMusic {
// Check to see if iPod music is already playing
UInt32 propertySize = sizeof(_otherMusicIsPlaying);
AudioSessionGetProperty(kAudioSessionProperty_OtherAudioIsPlaying, &propertySize, &_otherMusicIsPlaying);
// Play the music if no other music is playing and we aren't playing already
if (_otherMusicIsPlaying != 1 && !_backgroundMusicPlaying) {
[_backgroundMusicPlayer prepareToPlay];
if (soundsEnabled==YES) {
[_backgroundMusicPlayer play];
_backgroundMusicPlaying = YES;
}
}
}

AVAudioPlayer is leaking, where should i release it??

i m trying to play background.mp3 files as my game playback file ,and it works fine
but it leaking memory
#interface slots2ViewController : UIViewController <AVAudioPlayerDelegate>
{
AVAudioPlayer *PlayBack;
}
#property(nonatomic, retain) AVAudioPlayer *PlayBack ;
.m file
#synthesize PlayBack;
-(void)LoadnPlaySound
{
NSString *SubDir = [NSString stringWithFormat:#"AudioFiles/Theme%d",SlotId];
NSURL* file_url2 = nil;
file_url2 = [[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:#"background"ofType:#"mp3" inDirectory:SubDir ]];
AVAudioPlayer* TmpPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:file_url2 error:nil];
self.PlayBack = TmpPlayer;
self.PlayBack.delegate = self;
[TmpPlayer release];
[self.PlayBack prepareToPlay];
[self.PlayBack play];
[release file_url2];
}
-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)ThePlayer successfully:(BOOL)flag
{
[self.PlayBack play];
}
memory leak instrument says [self.PlayBack prepareToPlay] is the point of 100% leak
i m calling LoadnPlaySound whenever i m changing the theme.
also do i need to release self.PlayBack if yes then where

How to call a method defined in another class

I have a class named as Backgroundmusic.h file is
#import "UIKit/UIKit.h"
#import "AVFoundation/AVFoundation.h"
#import "AudioToolbox/AudioToolbox.h"
#interface Backgroundmusic : NSObject{
}
-(void)playBgmusic:(BOOL) issoundon;
#end
Backgroundmusic.m is
-(void)playBgmusic:(BOOL)issoundon {
//AVAudioPlayer *myExampleSound; //this variable can be named differently
if ( issoundon==TRUE) {
NSString *path =[[NSBundle mainBundle] pathForResource:"bg" ofType:#"wav"];
SystemSoundID soundID;
AudioServicesCreateSystemSoundID((CFURLRef) [NSURL fileURLWithPath:path]
,&soundID);
AudioServicesPlaySystemSound(soundID);
}
else {
NSString *path =[[NSBundle mainBundle] pathForResource:nil ofType:#"wav"];
SystemSoundID soundID;
AudioServicesCreateSystemSoundID((CFURLRef) [NSURL fileURLWithPath:path]
,&soundID);
AudioServicesPlaySystemSound(soundID);
}
}
Basically what i am trying to do is setting a background music to my app at the time of beginning and allow the user to stop it in the middle
so in my xAppdelegate.m i have called this function as
- (void)applicationDidFinishLaunching:(UIApplication *)application {
Backgroundmusic *bgm=[[Backgroundmusic alloc] init];
[bgm playBgmusic:TRUE];
}
but at this time my app terminates can someone tell me whats the issue here???
what the error message you are getting ? When application terminate you can check that in gdb window. It will show the proper error message. Post that error message in this thread.

AVAudioPlayerdelegate

I receive this error for this code-
warning: class 'BeatMaker' does not implement the 'AVAudioPlayerDelegate' protocol
-(IBAction)playBeat3 {
NSString *path = [[NSBundle mainBundle] pathForResource:#"beat3" ofType:#"mp3"];
AVAudioPlayer* theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate = self;
[theAudio play];
}
Can anyone help me with this?
You've told your AVAudioPlayer instance that your BeatMaker class implements the AVAudioPlayerDelegate protocol with this line:
theAudio.delegate = self;
But apparently your BeatMaker class hasn't told the compiler that it is actually an AVAudioPlayerDelegate. You would do that in the header file:
#interface BeatMaker : NSObject <AVAudioPlayerDelegate> { ... }
Then you would have to make sure that you have implemented all the required functions of the AVAudioPlayerDelegate protocol in your BeatMaker class.
In this case, there are no required functions for the protocol, so if you are just copying code and you don't actually want to recieve messages from theAudio, you can just delete the line assigning self to the delegate property of theAudio.