I am trying to figure out how to hook up a button to play a sound programmatically without using IB. I have the code to play the sound, but have no way of hooking the button up to play the sound? any help?
here is my code that I'm using:
- (void)playSound
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"boing_1" ofType:#"wav"];
AVAudioPlayer* myAudio = [[AVAudioPlayer alloc]
initWithContentsOfURL:[NSURL fileURLWithPath:path error:NULL]];
myAudio.delegate = self;
myAudio.volume = 2.0;
myAudio.numberOfLoops = 1;
[myAudio play];
}
[button addTarget:self action:#selector(playSound) forControlEvents:UIControlEventTouchUpInside];
UIButton inherits its target/action methods from UIControl.
To hook up the button, make your playSound method the handler for the button's UIControlEventTouchUpInside event. Assuming this is in a view controller, you might want to put this in the viewDidLoad method:
[button addTarget:self action:#selector(playSound) forControlEvents:UIControlEventTouchUpInside];
FYI, you're leaking memory because you're alloc-ing an object but never release-ing it.
You should create a new AVAudioPlayer member for the class to avoid this.
#interface MyViewController : ...
{
...
AVAudioPlayer* myAudio;
...
}
- (void)playSound
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"boing_1" ofType:#"wav"];
[myAudio release];
myAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path error:NULL]];
myAudio.delegate = self;
myAudio.volume = 2.0;
myAudio.numberOfLoops = 1;
[myAudio play];
}
Don't forget to put [myAudio release] in your dealloc method.
(I did this without declaring myAudio as a #property, but that's not strictly necessary)
Related
I'm facing a very strange issue, my requirement is to play a sound on the button click and this is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *path=[[NSBundle mainBundle] pathForResource:#"button-3" ofType:#"mp3"];
tapSound=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL]];
[tapSound prepareToPlay];
tapSound.delegate=self;
//creating the button in view did load and button is declared in .h
btn=[UIButton buttonWithType:UIButtonTypeCustom];
btn.frame=CGRectMake(x, y, 58,58);
[btn addTarget:self action:#selector(btnClkd:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
//click method
-(void)btnClkd:(UIButton*)sender
{
[tapSound play];
}
But when I run the code and click the button my app gets crashed and got this error: "Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIButton play]: unrecognized selector sent to instance 0x758c790' "
But if I play the sound anywhere else but not on the click of the button then it get played without any issue.I dont know why this is happening? Please help me
Do this:
-(void)btnClkd:(UIButton*)sender
{
NSString *path=[[NSBundle mainBundle] pathForResource:#"button-3" ofType:#"mp3"];
tapSound = nil;
tapSound=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL]];
[tapSound prepareToPlay];
tapSound.delegate=self;
[tapSound play];
}
Try this one . Add in your .h file
.h file
#import <AVFoundation/AVFoundation.h>
#import <AudioUnit/AudioUnit.h>
AVAudioPlayer *player1;
#property(nonatomic ,retain)AVAudioPlayer *player1;
in your .m file
#synthesize player1;
- (void)viewDidLoad
{
[super viewDidLoad];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"button-3" ofType:#"mp3"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:soundFilePath];
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
[fileURL release];
self.player1 = audioPlayer;
[audioPlayer release];
[self.player1 prepareToPlay];
[self.player1 setDelegate:self];
[pool release];
//creating the button in view did load and button is declared in .h
btn=[UIButton buttonWithType:UIButtonTypeCustom];
btn.frame=CGRectMake(x, y, 58,58);
[btn addTarget:self action:#selector(btnClkd:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
-(void)btnClkd:(UIButton*)sender {
[self.player1 play];
}
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];
}
i am an n00b and seeking help.
Now i can start a Soundfile with Following code:
- (void)addButtonSpeaker {
UIButton *buttonSpeaker = [UIButton buttonWithType:UIButtonTypeCustom];
[buttonSpeaker setFrame:CGRectMake(650, 930, 63, 66)];
[buttonSpeaker setBackgroundImage:[UIImage imageNamed:#"buttonLesen.png"]
forState:UIControlStateNormal];
[buttonSpeaker addTarget:self action:#selector(playAudio)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:buttonSpeaker];
}
- (void)playAudio {
NSString *path = [[NSBundle mainBundle] pathForResource:#"Vorwort" ofType:#"mp3"];
AVAudioPlayer* theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL
fileURLWithPath:path] error:NULL];
self.audioPlayer = theAudio;
[theAudio release];
[theAudio play];
}
With the same Button i would like to stop and play the sound.
Maybe i am searching for the wrong thing, but i can´t find the proper information on the web.
It would be really helpful if someone could give me a LINK to a tutorial or something like this.
thanks in advance
Planky
Create the AVAudioPlayer player object on loadView or somewhere.
- (void)loadView {
// Some code here
NSString *path = [[NSBundle mainBundle] pathForResource:#"Vorwort" ofType:#"mp3"];
AVAudioPlayer* theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
self.audioPlayer = theAudio;
[theAudio release];
// Some code here
}
Then inside the button's action(change the action name to toggleAudio as others suggested), you can get the property isPlaying to see whether audio is playing or not, and do the respective actions.
- (void)toggleAudio { // original name is playAudio
if ([self.audioPlayer isPlaying]) {
[self.audioPlayer pause];
// Or, [self.audioPlayer stop];
} else {
[self.audioPlayer play];
}
}
How to stop background music when changing views? I have no clue. If i press a button which takes me to a new view, there is new background music. But the old background music (which goes in an infinite loop) keeps on going. Please help! also sample some code please, here is mine:
- (void)viewDidLoad {
NSString *path = [[NSBundle mainBundle] pathForResource:#"MathMusic2" ofType:#"wav"];
AVAudioPlayer* theAudio= [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate = self;
[theAudio play];
theAudio.numberOfLoops = -1;
[super viewDidLoad];
}
I just need to know how to make the background music from the new view stop playing. And vice versa when i press the back button from the new view
Create a property for the AVAudioPlayer *theAudio so you can access the audioPlayer from any point in your class.
Header file of viewController
...
AVAudioPlayer *theAudio;
...
#property (nonatomic, retain) AVAudioPlayer *theAudio;
Implentation file of viewController
...
#synthesize theAudio;
...
- (void)viewDidLoad {
NSString *path = [[NSBundle mainBundle] pathForResource:#"MathMusic2" ofType:#"wav"];
self.theAudio= [[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL]] autorelease];
theAudio.delegate = self;
[theAudio play];
theAudio.numberOfLoops = -1;
[super viewDidLoad];
}
If viewWillDisappear is called you can then just stop the audio with
- (void)viewWillDisappear
{
[theAudio stop];
}
it gaves errors in here :
"theAudio.delegate = self;" as something like assigning to id...
its yellow anyway..
still when i change view and go to another class music not stoping....
I'll keep it short and sweet - I'm building an application just for practice before I buy myself the iPhone Developer Program.
I'm experimenting with the AVFoundation.framework and I keep running into a bug which will only let me play the first sound I initialize in my code. Do you think any of you could help me out? Thanks in advance!! :)
view controller
-(IBAction)play {
if (segments.selectedSegmentIndex == 0) {
NSLog(#"Segment = 0");
NSBundle *bundle = [NSBundle mainBundle];
NSString *path = [bundle pathForResource:#"meow" ofType:#"wav"];
if (path != nil) {
NSURL *url = [NSURL fileURLWithPath:path];
AVAudioPlayer *player = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:NULL];
[player prepareToPlay];
[player play];
}
}
else if (segments.selectedSegmentIndex == 1) {
NSLog(#"Segment = 1");
NSBundle *bundle = [NSBundle mainBundle];
NSString *path2 = [bundle pathForResource:#"meowloud" ofType:#"wav"];
if (path2 != nil) {
NSURL *url2 = [NSURL fileURLWithPath:path2];
AVAudioPlayer *player2 = [[AVAudioPlayer alloc]initWithContentsOfURL:url2 error:NULL];
[player2 prepareToPlay];
[player2 play];
// [player2 release];
}
}
text1.textColor = [UIColor clearColor];
text2.textColor = [UIColor clearColor];
text3.textColor = [UIColor clearColor];
text4.textColor = [UIColor clearColor];
}
When this code gets executed, only the meow.wav is executed, no matter which segment is selected.
Your code has a couple of memory leaks. You allocate instances of AVAudioPlayer in your play method, but you never release those instances. See Cocoa's memory management qguidelines for details. Since the AVAudioPlayer instances need to remain in memory to play, the easiest solution is to add a member variable to your viewController class and set it up as a retain property.
For the sake of Don't Repeat Yourself (DRY), I would also suggest adding a method which encapsulates all of the code needed to play a single wav file.
Here is how I would write this view controller:
MyViewController.h
#interface MyViewController : UIViewController
{
AVAudioPlayer *player;
}
#property(nonatomic, retain) AVAudioPlayer *player;
- (void)playWavFile:(NSString *)fileName;
- (IBAction)play;
#end
MyViewController.m
#synthesize player;
- (void)dealloc {
[player release];
}
- (void)playWavFile:(NSString *)fileName {
NSBundle *bundle = [NSBundle mainBundle];
NSString *path = [bundle pathForResource:fileName ofType:#"wav"];
if (path != nil) {
AVAudioPlayer *newPlayer;
NSURL *url = [NSURL fileURLWithPath:path];
newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url
error:NULL];
[self setPlayer:newPlayer];
[newPlayer release];
[newPlayer prepareToPlay];
[newPlayer play];
}
}
- (IBAction)play {
if (segments.selectedSegmentIndex == 0) {
[self playWavFile:#"meow"];
}
else if (segments.selectedSegmentIndex == 1) {
[self playWavFile:#"meowloud"];
}
}