I have an app that is nearly finished but encountered an annoying problem. In the app, I want to play a sound when I tap on some object, then the object disappears. This is the piece of code I used:
In Object.h
#import <UIKit/UIKit.h>
#import <AudioToolbox/AudioServices.h>
#interface Object: UIView {
UIImageView *image;
CGPoint location;
SystemSoundID soundFileID;
}
In Object.m
- (void)initWithSound {
//a bunch of code to define the image and location
NSString *soundPath = [[NSBundle mainBundle] pathForResource:#"Sound" ofType:#"caf"];
CFURLRef soundURL = (CFURLRef)[NSURL fileURLWithPath:soundPath];
AudioServicesCreateSystemSoundID(soundURL, &soundFileID);
return self;
}
Then in my mainViewController, several objects will be created upon user's action and added to the screen at different locations with different images. Upon tapping on the object itself, it will create a sound and disappear.
In Object.m
- (void)tapped {
AudioServicesPlaySystemSound(soundFileID);
image.image = nil;
[self removeFromSuperview];
}
Everything works find in the simulator. But when I tried that in iPhone, the object disappears on tapping as expected but the sound just doesn't play. Tried on a 3G and a 3GS, both don't play the sound. I think this should work. Am I making any mistakes? Thanks for any help.
EDIT: Just think of something that I don't know related or not. I'm also using the microphone to detect sound input from the user by AVAudioRecorder. Not sure if this would affect the audio output.
Finally found where the problem is!!
It turns out that I have to I have to set up an audio session. It's just that! Obviously I need more study on the audio and video things.
Just for someone who may run into the same situation as me, here is the code I added in the viewDidLoad method:
AVAudioSession * audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error: &error];
[audioSession setActive:YES error: &error];
Related
I'm having a problem with AudioServicesPlaySystemSound in my iOS app.
I have a method defined to play a system sound. When I call the method from viewDidLoad, I can hear the sound play, but when I call it from a button handler, I do not hear the sound play.
Here's the code from my view controller:
SystemSoundID startSound = 0;
-(void)playStartSound
{
AudioServicesPlaySystemSound(startSound);
}
-(void)viewDidLoad
{
NSURL *urlStart = [[NSBundle mainBundle] URLForResource:#"Beep" withExtension:#"wav"];
AudioServicesCreateSystemSoundID((CFURLRef)urlStart, &startSound);
[self playStartSound];
[super viewDidLoad];
}
- (IBAction)start:(id)sender
{
[self playStartSound];
}
The IBAction method is associated with a button. When I select the button, the playStartSound method gets called, but the sound is not audible.
The system sound is not disposed of with AudioServicesDisposeSystemSoundID until the dealloc method is called.
I've tried calling AudioServicesCreateSystemSoundID from within playStartSound, but it didn't make any difference.
The app also uses AV Foundation, Media Player, Core Media, Core Video, and Core Location. I'm wondering if one of these might be interfering with AudioToolbox?
UPDATE: I just put together a simple app that just contains the above code and a button and the sound plays just fine when I select the button.
So then I removed all the video capture code from my controller and now the audio plays fine.
This was not working because I had an active video capture session in my application.
AudioServicesPlaySystemSound will not play when there is an active video capture session.
NSString *soundPath = [[NSBundle mainBundle] pathForResource:#"7777" ofType:#"mp3"];
SystemSoundID soundID;
AudioServicesCreateSystemSoundID((__bridge CFURLRef)([NSURL fileURLWithPath: soundPath]), &soundID);
AudioServicesPlaySystemSound (soundID);
Hey try like that it will play
I have searched for this answer and have not found it.
I have music that plays in the background when my iPhone app is launched. But I want a button so that users can mute the music. There are sound effects within the app also so sliding the mute button on the side of the device won't cut it.
This is the current code I have for the AVAudioPlayer.
- (void)viewDidLoad{
#if TARGET_IPHONE_SIMULATOR
//here code for use when execute in simulator
#else
//in real iphone
NSString *path = [[NSBundle mainBundle] pathForResource:#"FUNKYMUSIC" ofType:#"mp3"];
AVAudioPlayer *TheAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
TheAudio.delegate = self;
[TheAudio play];
TheAudio.numberOfLoops = -1;
#endif
}
Can anyone help me out the code needed for a simple button to simply stop the music and start it again.
Thanks in advanced.
Put this code in the viewcontroller.h file:
-(IBAction) btnStop:(id)sender;
Put this code in the viewcontroller.m file:
-(IBAction) btnStop:(id)sender {
[TheAudio stop];
//Whatever else you want to do when the audio is stopped
}
In the Interface builder, connect a button to this action, so when it is clicked this action will be called.
That should make the music stop.
Its easier to display code in an answer:
-(IBAction) playerPlay:(id)sender {
if([player isPlaying]) {
[player stop];
}
if(![player isPlaying]) {
[player play];
}
}
I'll explain:
The [player isPlaying] method checks to see if the audio is playing. If the audio is playing, everything in the brackets is executed (in this situation, the audio stops playing).
Because of the "!" in ![player isPlaying], the method is made the opposite of what it usually is. This means that if the player is NOT playing, everything in the brackets is executed (in this situation, the audio starts playing).
All of this is enclosed in the IBAction, so that it is executed when the button is clicked.
For future reference, the correct format for an If statement in Objective-C is:
if(thing to check for) {
things that happen if the thing that is check for is correct;
}
The word "then" is never actually used, but it is the same thing and whatever is in the brackets.
Hope this helps!
Alright I have two problems. I'm using AVAudioPlayer to play a simple audio file in .caf format. What I'm trying to do is have a play and pause button. Here is a sample of a simple IBAction to play the audio from a button.
- (IBAction) clear {
NSString *path = [[NSBundle mainBundle] pathForResource:#"clear" ofType:#"caf"];
AVAudioPlayer* myAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
myAudio.delegate = self;
myAudio.volume = 1.0;
myAudio.numberOfLoops = 0;
[myAudio play];
}
So when I go ahead and create another IBAction with the method...
- (IBAction) stopaudio {
[myAudio stop];
audioPlayer.currentTime = 0;
}
I compile and xcode tells me that myAudio in the stopaudio IBAction is not defined. How do I fix it so I'm able to access myAudio in another IBAction?
My Second question is that I'm using NavigationController to setup a TableView, when I make a selection it takes me to a UIView with a back button to go back to the TableView. What I'm trying to do is to kill any audio that I have playing in the UIView when I go back to the TableView. The code above is part of the code that I'm going to have in the UIView.
Also one quick question. Lets say I have an audio file that is 1 minute long. Clicking play again will overlap a new instance of that audio before the old instance is done playing. How can I check to see if myAudio is playing and not allow it to be played again until myAudio is finished playing?
Thank You!
First of all, you should read the documentation. It will remove almost all of your questions. Nevertheless, to have access to your instance of AVAudioPlayer from all methods of your class, you should define it in your .h file. To stop your player on returning to the previous screen, call [myAudio stop] in your viewWillDisappear:(BOOL)animated method. About your last question. If you define myAudio in your .h file, you will be able to check if it is playing now. smth like
- (IBAction) clear {
if(![myAudio isPlaying]){
[myAudio play];
}
}
i have created a application that plays movie on button click..my application is running without any warning or error. But i am not able to see the movie don't know why?
I have added the Media player framework and also imported the #import in viewController.h
my button action code is as follow...
-(IBAction)playMyMovie:(id)sender{
NSBundle *bundle =[NSBundle mainBundle];
NSString *moviePath = [bundle pathForResource:#"jumps" ofType:#"mov"];
NSURL *movieURL = [[NSURL fileURLWithPath:moviePath] retain];
MPMoviePlayerController *theMovie =[[MPMoviePlayerController alloc] initWithContentURL:movieURL];
theMovie.scalingMode = MPMovieScalingModeAspectFill;
[theMovie play];
}
Please tell me what i am missing..
in iPhone simulator you could not play movie properly.
test the applcation on iPhone (Real instrument).
It will work fine.
You are creating a MPMoviePlayerController. It has a view property - that is its view. It is your job to put that view into your interface. If you don't, you won't see anything.
try add this line before the [theMovie play]
[self.view addSubview:theMovie.view];
and also remember to setFullScreen:
[self.theMovie setFullscreen:YES];
if you dont want fullscreen but want to embed into the view, you can ignore the "setFullscreen", but set the frame for the MPMoviePlayerController view:
[self.theMovie.view setFrame:CGRectMake("add in the size you want here")];
I am implementing a sound effect that plays while a user is dragging a UISlider.
In a previous question, I used AudioServicesPlaySystemSound() but that type of sound can't be halted. I need the sound to halt when the user is not actively dragging the slider but has not released it.
Now I am creating a sound using an AVAudioPlayer object. I initialize it in my View Controller like this:
#interface AudioLatencyViewController : UIViewController <AVAudioPlayerDelegate> {
AVAudioPlayer *player1;
}
#implementation AudioLatencyViewController
#property (nonatomic, retain) AVAudioPlayer *player1;
#synthesize player1;
-(void)viewDidLoad {
[super viewDidLoad];
// the sound file is 1 second long
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"tone1" ofType:#"caf"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:soundFilePath];
AVAudioPlayer *newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
[fileURL release];
self.player1 = newPlayer;;
[newPlayer release];
[self.player1 prepareToPlay];
[self.player1 setDelegate:self];
}
I have two methods to control the sound. The first one plays the sound whenever the slider is being moved. It is connected to the UISlider's Value Changed event in Interface Builder.
-(IBAction)sliderChanged:(id)sender;
{
// only play if previous sound is done. helps with stuttering
if (![self.player1 isPlaying]) {
[self.player1 play];
}
}
The second method halts the sound when the user releases the slider button. It's connected to the UISlider's Touch Up Inside event.
-(IBAction)haltSound;
{
[self.player1 stop];
}
This works when the slider button is moved then released quickly, but if you hold down the button longer than two or three seconds, the sound repeats (good) then breaks up (bad). From then on, the sound won't play again (super bad).
I have tried setting the sound to loop using:
[self.player1 setNumberOfLoops:30];
...but that leads to the app freezing (plus locking up the Simulator).
What can I do to debug this problem?
When a user is holding the UISlider, Value Changed gets called MANY MANY times (any time the user moves just a slight amount). I would use Touch Down instead.
You might want to still try using the loop for this route...
I like the idea of playing a sound while the user is moving the slider though. Let me know how it works out.
deggstand#gmail.com