Iphone audio only working in Simulator NOT in Device - iphone

I have set up part of my app to play a sound. Simple - but only is working in Simulator.
Initing audio session this way:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
// Custom initialization
}
AudioSessionInitialize(NULL,NULL,NULL,NULL);
AudioSessionSetActive(YES);
return self;
}
Playing sound, setting completion calback, and checking for file this way:
NSString *path = [[NSBundle mainBundle] pathForResource:fileName ofType:#"mp3"];
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:path], &soundID);
AudioServicesAddSystemSoundCompletion (soundID,NULL,NULL,
completionCallback,
(void*) self);
if([[NSFileManager defaultManager] fileExistsAtPath:path])
{
NSLog(#"Playing Sound" );
AudioServicesPlaySystemSound(soundID);
}
else {
NSLog(#"NO SOUND");
}
In Simulator, the file is found, sound plays, and completion happens. In device, file is found, sound does not play, and completion is never called.
Any ideas? Thank you very much, both my forehead and my desk appreciate any replies...:)

OK,
So there were a few things I changed to get this working. DOn't have the code in front of me, will try to add later.
I stopped using the system sound and started using AVAudioPlayer instead.
I didn't have my UIView set up as the audio delegate
Was not starting the audio session. Now am starting the audio session in the initNib function(I saw tutrorials that said to use awakeFromNib, but the awakeFromNib never fired...)

Related

AVAudioPlayer plays in iOS Simulator but not on the iPhone [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I'm building an app which has to play a mp3 file. For that issue, I'm using AVAudioPlayer following the indications I have been reading from others post.
But my problem is, the code (I have attached bellow) works on the iOS Simulator, but when I try to use it in my iPhone, it doesn't work...
I hope any of you could help me with this issue.
File .h:
#import "UIKit/UIKit.h"
#import "AVFoundation/AVFoundation.h"
#interface ViewController : UIViewController <AVAudioPlayerDelegate>
#property (strong, nonatomic) AVAudioPlayer *player;
#end
File .m:
#import "ViewController.h"
#implementation ViewController
#synthesize player;
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"beep_7" ofType:#"mp3"];
NSLog(#"Audio path: %#", soundFilePath);
NSError *error;
self.player =[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:soundFilePath] error:&error];
if (error) {
NSLog(#"Error in audioPlayer: %#",[error localizedDescription]);
}
else {
[self.player setDelegate:self];
[self.player setNumberOfLoops:3]; //just to make sure it is playing my file several times
self.player.volume = 1.0f;
if([self.player prepareToPlay]) //It is always ready to play
NSLog(#"It is ready to play");
else
NSLog(#"It is NOT ready to play ");
if([self.player play]) //It is always playing
NSLog(#"It should be playing");
else
NSLog(#"An error happened");
}
}
-(void)audioPlayerDecodeErrorDidOccur: (AVAudioPlayer *)player error:(NSError *)error {
NSLog(#"audioPlayerDecodeErrorDidOccur -> Error in audioPlayer: %#",[error localizedDescription]);
}
-(void)audioPlayerDidFinishPlaying: (AVAudioPlayer *)player successfully:(BOOL)flag{
NSLog(#"audioPlayerDidFinishPlaying");
}
-(void)audioPlayerBeginInterruption:(AVAudioPlayer *)player{
NSLog(#"audioPlayerBeginInterruption");
}
-(void)audioPlayerEndInterruption:(AVAudioPlayer *)player{
NSLog(#"audioPlayerEndInterruption");
}
#end
The first thing to check when the audio (or image) is working (shown) in the simulator and not on the device is the spelling of the audio - file you are trying to access.
Since Mac OSX is NOT case sensitive but iOS is this means that an image spelled iMage.png and accessed as image.png in your code will show in the simulator but NOT on your iPhone.
The other thing to check could be that you have accidentally hit the physical mute button on your iPhone. (Happened to me last week)
Hope it helps!

How does my app recognize that a song finished?

I´m working on my first app. It plays an mp3 song. Everything works fine, but I need the app to recognize that the sound finished, then change the button “pause” image to the “play” one. I can already do that, but just when the button is pressed, not when song ends.
Another issue is that when the song restarts after stop->play, it doesn´t continue playing at the previous volume setting (got a slider). The player starts at maximum volume. I can change the volume slider position, but I am not able to make the app respect the set volume when restarts.
Any help will be very appreciated!
Thnx a lot.
When using "AVAudioPlayerDelegate protocol delegate", please do not forget to set delegate (for example) as follows:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle] pathForResource:#"33fr" ofType:#"mp3"];
NSURL *fileURL = [NSURL fileURLWithPath:path];
NSError *error = nil;
myPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:&error];
if (error) {
NSLog(#"error = %#", error);
return;
}
[myPlayer setDelegate:self]; <<=== HERE!
}
I uploaded sample code here. Please check it. ->
http://yahoo.jp/box/X7Hxfk
I have not done much of Objective-C but it looks like you need to implement a delegate.
I quote: "You implement a delegate to handle interruptions (such as an incoming phone call) and to update the user interface when a sound has finished playing."
I am just reading the AVAudioPlayer Class Reference here:
https://developer.apple.com/library/mac/#documentation/AVFoundation/Reference/AVAudioPlayerClassReference/Reference/Reference.html#//apple_ref/doc/uid/TP40008067
you can use the AVAudioPlayerDelegate protocol delegate
After the audio player is finished playing the song (if it does so
successfully), the audio PlayerDidFinishPlaying:successfully: delegate
method will be called in the delegate object of the audio player. We
can implement this method like below (this method is defined in the
AVAudioPlayerDelegate protocol):
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
if (flag)
{
NSLog(#"Audio player stopped correctly.");
}
else
{ NSLog(#"Audio player did not stop correctly.");
}
if ([player isEqual:self.audioPlayer])
{ self.audioPlayer = nil;
}
else
{ /* This is not the player */ }
}
in .h file add delegate like below code
#interface yourViewController : UIViewController <AVAudioPlayerDelegate>

Can not call method from another view controller in Objective C, iPhone SDK

At my StartWorkoutViewController.m I trigger:
#import "WorkoutViewController.h"
#implementation StartWorkoutViewController
- (IBAction) start
{
[firstViewController performSelector:#selector(callMyAction)];
WorkoutViewController *ViewCon = [[WorkoutViewController alloc]init];
[ViewCon callMyAction];
[ViewCon release];
}
then at my WorkOutViewController.h I added this:
- (void)callMyAction;
and at my WorkOutViewController.m I added this:
#import "StartWorkoutViewController.h"
-(void)viewWillAppear:(BOOL)animated{
NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/achtergrondgeluid.mp3", [[NSBundle mainBundle] resourcePath]]];
NSError *error;
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
audioPlayer.numberOfLoops = -1;
[audioPlayer play];
}
-(void)callMyAction{
NSLog(#"suckers");
[audioPlayer pause];
}
Now my NSLog (#"suckers") triggers very well from the StarWorkoutViewController, but for some reason the audioPlayer does nothing, any idea? Also setting labels in the Workout ViewController from the callMyAction in this file. Don't work! Any idea? Thanks!
The reason nothing is happening is because your are calling the pause method before the player even starts playing. viewWillAppear does not get called until it is visually on the screen. It actually doesn't always get called even then but that is another issue entirely. So if you want to pause the player it needs to actually be playing. If you put that viewWillAppear code in viewDidLoad it will probably work as expected.
Currently your code is doing this:
Load WorkoutViewController
Pause Audio
WorkourViewController become visible (actually this may never happen as I am not seeing it being added to any windows or anything).
Plays audio.

Crashes when using AVAudioPlayer on iPhone

I am trying to use AVAudioPlayer to play some sounds in quick succession. When I invoke the sound-playing function less frequently so that the sounds play fully before the function is invoked again, the application runs fine. But if I invoke the function quickly in rapid succession (so that sounds are played while the previous sounds are still being played), the app eventually crashes after ~20 calls to the function, with the message "EXC_BAD_ACCESS". Here is code from the function:
NSString *nsWavPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:wavFileName];
AVAudioPlayer* theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:nsWavPath] error:NULL];
theAudio.delegate = self;
[theAudio play];
As mentioned in another thread, I implemented the following delegate function:
- (void) audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
if(!flag)
NSLog(#"audio did NOT finish successfully\n");
[player release];
}
But the app still crashes after around ~20 rapid calls to the function. Any idea what I'm doing wrong?
First off: Make sure you're not trying to play a sound a second time that has already been released via [player release]; If you are, you'll get that error message right away. Once you release the player associated with a specific sound, you cannot play the file again like you have shown here. Try commenting out that line of code and see if it still happens.
I've also run into an issue where AVAudioPlayer allocates 32kb everytime a new player is created and if you have enough sounds you can run out of memory and get a crash. I highly doubt this is your problem though since it doesn't typically throw that error code.
EXC_BAD_ACCESS is typically from trying to access a pointer that no longer exists (such as your player object) for most of the cases I've seen on this forum
I found a better solution to this problem.
You simply need to active/deactivate your AVAudioSession.
For example: In you viewDidLoad method put this:
NSError *activationError = nil;
[[AVAudioSession sharedInstance] setActive:YES error:&activationError];
Then, you can play a sound in whatever method like this:
... some awesome code ...
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
[self.audioPlayer setDelegate:self];
[self.audioPlayer setVolume: 0.7f];
[self.audioPlayer setNumberOfLoops:0];
if ([self.audioPlayer prepareToPlay]) {
[self.audioPlayer play];
}
....
And finally, (no matters if sound was finished playing), when you're done with sounds then just do this:
// I've made it on the view's callback
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.audioPlayer stop];
[self setAudioPlayer:nil];
NSError *activationError = nil;
[[AVAudioSession sharedInstance] setActive:NO
error:&activationError];
.... etc, etc...
}
And that's all :)
Your app will never crash again with an EXC_BAD_ACCESS.
Hope this helps you and avoid that hacky [self retain] / [self release]
From the Apple's Audio Session Programming Guide:
https://developer.apple.com/library/ios/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/ConfiguringanAudioSession/ConfiguringanAudioSession.html

Can you see anything wrong in this code?

NSString *path = [[NSBundle mainBundle] pathForResource:[arraySub objectAtIndex:indexPathHere.row] ofType:#"mp3"];
NSURL *file = [[NSURL alloc] initFileURLWithPath:path];
AVAudioPlayer *myPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:file error:nil];
self.player = myPlayer;
[player prepareToPlay];
[player setDelegate:self];
[self.player play];
NSTimeInterval lenghtMusic = player.duration;
if (player.currentTime == lenghtMusic) {
NSLog(#"It worked");
[tableThing deselectRowAtIndexPath:indexPathHere animated:YES];
[myPlayer autorelease];
[file autorelease];
}
Can you see anything wrong?
Apparently, the "if"-statement never gets called...
If I read your code correctly you are trying to find out when the player has finished playing and then you want to deselect the current rode and release the player. Your problem is that you start the player and then immediately checks where it is currently playing. Unless you have an almost 0 length file the currentTime and length will NEVER be equal.
If that is what you are trying to do you should use the AVAudioPlayerDelegate Protocol and especially the:
– audioPlayerDidFinishPlaying:successfully:
method that is called when the player is finished.
So you need to change your class that controls the player by editing the .h file to use the AVAudioPlayerDelegate Protocol. Obviously keep extending whatever you were before.
#interface YourClass <AVAudioPlayerDelegate>
#end
In your .m file:
Then when you have created and assigned your player instance:
[player setDelegate:self];
In the .m file also add the method
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
// Your success code goes here
}
You are comparing double's with ==, which is almost always false due to round-off errors.
Compare with a range e.g.
if (fabs(player.currentTime - lenghtMusic) < 0.0001) {
...
}
I'm a noob iPhone dev, but are you sure that player.currentTime is a NSTimeInterval? That looks like the most obvious candidate.
Also, I'd log out what your player.currentTime is and what lenghtMusic is before your if and that'll probably let you know what's going on.