I have a music player app on ipad. I download m4a files from a server and save them to doc dir. I also use Core Data to save the playlist info. I have over 1000 songs and my table loads perfectly and plays perfectly. I can play the playlists thru with no problems. BUT... every once in a while one song does not play. NO SOUND! I can press the cell to play the song or goto the next song and everything works again. So this problem is random and intermittent. It's never the same song that gets stuck. I cant give you any debug statements, cus like I said, it's so random and intermittent that it's hard to duplicate. I'm wondering if it's an ARC problem. Please help, as this app is going to production very soon.
Relative code:
// setup music session
NSError *error = nil;
[[AVAudioSession sharedInstance] setDelegate: self];
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: &error];
[[AVAudioSession sharedInstance] setActive: YES error: &error];
NSLog(#"error AVAudioSession:%#", [error description]);
AVAudioPlayer *player = [[AVAudioPlayer alloc] init];
NSString *fullPath = fullPath = [self.docDirPath stringByAppendingPathComponent:filename];
NSURL *musicFileURL = [[NSURL alloc] initFileURLWithPath:fullPath];
// getting song from docDir
NSData *songData = [[NSData alloc] initWithContentsOfURL:musicFileURL];
player = [player initWithData:songData error:&error];
NSLog(#"error player reg:%#", [error description]);
//NSLog(#"playing %# at index:%d", musicFileURL, index);
self.appPlayer = player;
[self.appPlayer prepareToPlay];
[self.appPlayer setEnableRate: YES];
[self.appPlayer setDelegate: self];
[self.appPlayer play];
If you use ARC a good point to start to solve your problem is to watch the reference counting in Instruments. I had the problem as well. None of my files were playing. I've seen in Instruments that the AVAudioPlayer instance was released BEFORE the sound started to play. At least it looked like it was released. After i've stored the reference of AVAudioPlayer in the core data model the bug was fixed! In another project without ARC the same code did work without storing the reference.
or you can try to use strong instead of retain in the property declaration
#property(nonatomic, strong) AVAudioPlayer *player;
Related
I have saved a recording to my Temp directory and can verify this using iExplorer
The file path structure is TempFolder/UserID/SoundName001.wav
The bit I save to the database is UserID/SoundName001.wav
Here is the code I use to play the file
#property (nonatomic, strong) AVAudioPlayer *player;
-(void) playSound: (NSIndexPath*)recordingIndex {
NSArray *recording = [recordingArray objectAtIndex:recordingIndex.item-1];
NSString *filePath = [NSString stringWithFormat:#"%#%#",NSTemporaryDirectory(),[recording objectAtIndex:2]];
NSURL *recorderURL = [[NSURL alloc] initFileURLWithPath: filePath];
self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:recorderURL error:nil];
[self.player prepareToPlay];
[self.player setMeteringEnabled:YES];
[self.player setDelegate:self];
[self.player play];
}
I set a breakpoint and recorderURL returns the following file:///private/var/mobile/Containers/Data/Application/0883D0DC-B1FD-4D06-A7BB-EBD9EEF5D607/tmp/1/Dog001.wav
When I call this method, nothing happens, no crash, no sound...
Am I missing something obvious here?
Did you check the silent switch on your device? I think AVPlayer doesn't play sound if the silent switch is turned on. Try putting this line of code:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
in your viewDidLoad or before [self.player play]; and see if the audio plays.
Encountering a very weird issue. I'm trying to use AVAudioPlayer to play a simple sound file from disk. I maintain a strong reference to it via a property so ARC doesn't kill it prematurely. As I said in the title, I get no sound, errors and no delegate methods are called--including didFinishPlaying (which I would expect). The only thing that seems to "happen" is I hear two quiet clicks...
Now this is the weird part...if I set a breakpoint just before [_player play], then step over, the audio plays fine!! This basically confirms to me that I have set things up correctly, and makes me think that something else is stepping on the shared AVAudioSession from another thread? I'm not sure. The total lack of delegate calls is very odd--it seems that something should be called whenever AVAudioPlayer finishes.
I am also using OpenEars for speech recognition, but I call suspendListening on it before attempting to play the audio. I have also tried disabling OpenEars entirely, to try and isolate it as a cause--but this had no effect, either. Very perplexing. Appreciate any help!
-(void)playAudioNoteWithPath:(NSString *)filePath
{
NSError *error = nil;
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord
withOptions:AVAudioSessionCategoryOptionAllowBluetooth
error:&error];
if (error) {
DLog(#"ERROR setting audio session category: %#", [error localizedDescription]);
}
NSURL *URL = [NSURL URLWithString:filePath];
if (!URL) {
DLog(#"No file path!!");
}
_player = [[AVAudioPlayer alloc] initWithContentsOfURL:URL
error:&error];
if (error) {
DLog(#"ERROR initializing audio player: %#", [error debugDescription]);
}
_player.delegate = self;
[_player prepareToPlay];
// Setting a breakpoint here will cause playback to succeed.
if (![_player play]) {
DLog(#"ERROR playing!!");
}
}
Well, I seem to have found a fix, though I'm not sure why...since it's not that much code, I just moved it into the calling class. So the calling class now plays AudioNotes directly, instead of AudioNotes playing themselves. Now it works.
Here I used to play the songs using AVAudioPlayer Framework. Hopefully it's playing, but if I click on other songs from the Songslist I will check the condition :
if(player.isPlaying == YES)
{
[player stop];
// And also i need to release or remove the existing NSDATA from the Player. otherwise the player won't release the existing data. So the memory pressure occurring in my project.
}
self.audioPlayer = [self.audioPlayer initWithData:m_currentMusic.fileData error:&error];
[self.audioPlayer prepareToPlay];
[self.audioPlayer play];
AVAudioPlayer#data is a read-only non-retained property. So, the data is not retained and you have no need to releease it (it's assigned as by default).
However, as I said, it's read-only so you can't set it if you wish to change tracks. You also shouldn't call init... on an already initialied object, as in your code:
self.audioPlayer=[self.audioPlayer initWithData:m_currentMusic.fileData error:&error];
I believe the intended action for what you want is to relesae your existing self.audioPlayer and re-create a new one, as follows:
// stop player as in your original code...
[self.audioPlayer release];
AVAudioPlayer *newPlayer = [[AVAudioPlayer alloc] initWithData:m_currentMusic.fileData error:&error];
self.audioPlayer = newPlayer;
[self.audioPlayer setDelegate:self];
[newPlayer release];
Note that the release will cause your original track data to be reclaimed (as it's non-retained).
See also Core Audio Overview
I have tried everything I can find to try and get my app to play an mp3. I have a few 2-3 second mp3s that play as sound effects that work, but I am trying to play a 15s mp3 without any luck.
NSError *error;
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource: #"test" withExtension: #"mp3"] error:&error];
if (error) {
NSLog(#"Error creating audio player: %#", [error userInfo]);
} else {
if([audioPlayer play] == FALSE) {
NSLog(#"Fail %#", error);
}
}
NSTimer* myTimer = [NSTimer scheduledTimerWithTimeInterval: 15.0 target: self
selector: #selector(stopMusic) userInfo: nil repeats: NO];
I doubt the timer has anything to do with it but thought I would include it just in case. Basically my error checks are not getting triggered at all. It "should" be playing properly but no sound is coming out, and no errors are being displayed.
I have tried a few other things to try and get this working, and I have tried without the timer. I can't find a decent guide. I don't need a full blown media player, just some background music for an UIScreenViewController.
I have also tried the following code, which works good with short MP3s, not with the longer MP3 I want to play.
NSString *path = [[NSBundle mainBundle] pathForResource:#"bgmusic" ofType:#"mp3"];
NSURL *pathURL = [NSURL fileURLWithPath : path];
AudioServicesCreateSystemSoundID((__bridge CFURLRef)pathURL, &audioEffect);
AudioServicesPlaySystemSound(audioEffect);
Please help, I have spent hours trying to sort this. It seems apple re-jig their audio every time they release an OS.
I did a little testing for you: It turned out that music files aren't added to target by default in Xcode 5. Therefore URLForResource:error: likely returns nil.
Try removing the mp3 from your project. Then add it again and this time make shure you add it to your target:
The other thing is: It seems like you're defining the AVAudioPlayer inside a method. You normally set up a #property for your audio player because otherwise its life is limited to the method - and the music stops playing after you reach the end of the method.
I have a problem with the AVPlayer playing in background mode, like a lot of people here and everywhere on the web. I've done what I think is supposed to work, but is still doesn't... I think my problem might be where I set and use my AudioSession and AVPlayer.
1) The "audio" key is in UIBackgroundModes of my Info.plist
2) AudioSession set like this in AppDelegate (initialised in didFinishLaunchingWithOptions):
AVAudioSession *audio = [[AVAudioSession alloc]init];
[audio setCategory:AVAudioSessionCategoryPlayback error:nil];
[audio setActive:YES error:nil];
3) I use an AVPlayer (not AVAudioPlayer) also implemented in AppDelegate. (initialised in didFinishLaunchingWithOptions, after the AudioSession), right after the AudioSession
// Load the array with the sample file
NSString *urlAddress = #"http://mystreamadress.mp3";
//Create a URL object.
self.urlStream = [NSURL URLWithString:urlAddress];
self.player = [AVPlayer playerWithURL:urlStream];
//Starts playback
[player play];
And still, the audio is suspended everytime the app goes in background (when I press the "Home" button).
By the way, the problem was just with the simulator. Works fine on the iOS devices