AVAudioPlayer not playing any sound - objective-c
I'm working on an iOS application that needs to play some sounds using the AVFoundation framework. The workspace structure in Xcode 4 contains two projects:
Workspace
The application itself (main project)
A utility library
After building the utility library, it results in a static library which is used in the main application as a framework.
So, when trying to play a sound inside the main application by using the code below, it works as expected.
NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
NSString *path = [NSString stringWithFormat:#"%#/sound.mp3", resourcePath];
NSURL *url = [NSURL fileURLWithPath:path];
NSError *error = nil;
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url
error:&error];
[audioPlayer play];
In contrast, when trying to play exactly the same sound (or any other) inside the utility library using the same code as above, no sound is played at all, even though error is nil and the audioPlayer property values are the right ones (number of channels, duration).
I've made sure the AVFoundation framework is in both projects.
Also, my class uses the AVAudioPlayerDelegate protocol and implements these two methods:
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag;
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error;
None of these methods is called after trying to play the sound.
If I use the AudioToolbox framework instead, then it plays the sound. But I'm interested in using AVFoundation for several reasons.
Any idea of what is going on? Am I missing something about AVFoundation? Could it be related to using AVAudioPlayer from inside a static library?
Thanks in advance.
I found the solution and it's related to something I didn't mention and didn't think about: I'm compiling with Automatic Reference Counting (ARC).
ARC inserts a release call to the audio player, so it's deallocated right after leaving the method where it is created. It has nothing to do with AVAudioPlayer but with ARC.
In order to solve this issue, I just created an AVAudioPlayer attribute to the class that deals with sounds so that it is not released anymore by ARC. Well, at least, it's not released until the instance of this class is released.
For more information about ARC, refer to Automatic Reference Counting: Zeroing Weak References with details on why I had this issue.
Yes, absolutely; ARC was the reason with my code as well.
I introduced a property:
#property (strong, nonatomic) AVAudioPlayer *audioPlayer;
and that made everything work out fine.
use this it will work definitely....
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayback error:nil];
NSURL *url = [NSURL fileURLWithPath:#"path of the sound file :)"];
_player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[_player setDelegate:self];
[_player prepareToPlay];
[_player play];
Have you configured the AVAudioSession?
I had a similar problem and fixed it using something like this:
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:NULL];
or
[audioSession setCategory:AVAudioSessionCategoryPlayback error:NULL];
Hope it helps.
Even having audioPlayer var declared in the class scope, it won't play.
At least on iOS 10 iPhone 5c physical device.
play() result is true so no errors appear to happen.
Had to add this (Swift 3, 4) and now it plays the sound correctly.
let session = AVAudioSession.sharedInstance()
try! session.setCategory(AVAudioSessionCategoryPlayback)
I have created open source project for simple audio player. Take a look at it if you have any problems with playing audio in iOS (in background too) : https://github.com/wzbozon/DKAudioPlayer
I had the same issue. I had resolved it by adding below line in .h file:
#property (strong, nonatomic) AVAudioPlayer *audioPlayer;
And in .m file :
NSError *error;
NSString *soundFilePath = [NSString stringWithFormat:#"%#/dancepechance.mp3",
[[NSBundle mainBundle] resourcePath]];
NSURL *url = [NSURL fileURLWithPath:soundFilePath];
self.audioPlayer = [[AVAudioPlayer alloc]
initWithContentsOfURL:url
error:&error];
NSLog(#"Error %#",error);
[self.audioPlayer prepareToPlay];
[self.audioPlayer play];
You can use AVPlayerViewController from AVKit instead for both audio and video. Code is available for both swift and objective c here.
for me this did the job
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback)
} catch {
assertionFailure("Failed to configure `AVAAudioSession`: \(error.localizedDescription)")
}
Please stay on the page for some time, I was facing same issue. and use sleep to resolve it.
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
pathForResource:#"sounds-1027-are-you-kidding"
ofType:#"mp3"]];
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc]
initWithContentsOfURL:url
error:nil];
[audioPlayer play];
sleep(2);
Related
AVAudioPlayer or PlaySystemSoundID?
I have an iOS app which is going to provide a sound pad for the user - i.e. when they tap a button a short sound clip is played. At the moment, the app is designed around using SystemSoundID. Would it now be advised to use AVAudioPlayer now over this? If so, what would be the ideal code to use? Would it be the standard: NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"yoursoundfile" ofType:#"mp3"]]; AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil]; [audioPlayer play];
Objective-C - AVAudioPlayer
I found that using AVAudioFoundation should be the easiest way to play an mp3 on objective-c, but I don't know what I'm doing wrong here. No sound on either the device or the simulator. I imported the framework and all the other "normal" things, but it just keep not playing. What is wrong in this code? NSString *path = [[NSBundle mainBundle] pathForResource:#"DuomoDiFirenze" ofType:#"mp3"]; AVAudioPlayer *theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL]; [theAudio prepareToPlay]; [theAudio play];
Do you compile with ARC? if so make sure to keep a reference to the AVAudioPlayer instance as else ARC will make sure to release it for you and the audio playback will stop immediately.
So when you declare AVAudioPlayer * theAudio as a property of whichever object you are using it it, it will work. That's the only thing you are missing.
Play Audio iOS Objective-C
I'm trying to get an audio file playing in my iOS app. This is my current code NSString *soundFilePath = [NSString stringWithFormat:#"%#/test.m4a", [[NSBundle mainBundle] resourcePath]]; NSLog(#"%#",soundFilePath); NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath]; audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil]; [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; [[AVAudioSession sharedInstance] setActive: YES error: nil]; [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; [audioPlayer setVolume:1.0]; audioPlayer.delegate = self; [audioPlayer stop]; [audioPlayer setCurrentTime:0]; [audioPlayer play]; I've being checking a bunch of other posts but they all generally do the same thing. I'm not getting an error, but I don't hear any audio playing on the simulator or device. This is the path I get for the audio file on the simulator /Users/username/Library/Application Support/iPhone Simulator/5.1/Applications/long-numbered-thing/BookAdventure.app/test.m4a Any help is appreciated!
Maybe you should try using the NSBundle method pathForResource:ofType: method to create the path to the file. The following code should successfully play an audio file. I have only used it with an mp3, but I imagine it should also work with m4a. If this code does not work, you could try changing the format of the audio file. For this code, the audio file is located in the main project directory. /* Use this code to play an audio file */ NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"test" ofType:#"m4a"]; NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath]; AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil]; player.numberOfLoops = -1; //Infinite [player play]; EDIT Ok, so try this: NSString *soundFilePath = [NSString stringWithFormat:#"%#/test.m4a",[[NSBundle mainBundle] resourcePath]]; NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath]; AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil]; player.numberOfLoops = -1; //Infinite [player play]; Also, make sure you do the proper imports: #import <AudioToolbox/AudioToolbox.h> #import <AVFoundation/AVFoundation.h>
You need to store a strong reference to 'AVAudioPlayer' #property (strong) AVAudioPlayer *audioPlayer; And if you are sure that your audio file is in following Bundle Resources, it should play. Project>Build Phases>Copy
To play file with extension .caf, .m4a, .mp4, .mp3,.wav, .aif Download following two files from GitHub SoundManager.h SoundManager.m Add these files to your project Also add audio files to resource folder (sample files) mysound.mp3, song.mp3 Import header file in desired file #import "SoundManager.h" And add following two lines in -(void)viewDidLoad [SoundManager sharedManager].allowsBackgroundMusic = YES; [[SoundManager sharedManager] prepareToPlay]; Use following line to play sound (mysound.mp3) [[SoundManager sharedManager] playSound:#"mysound" looping:NO]; Use following line to stop the sound (mysound.mp3) [[SoundManager sharedManager] stopSound:#"mysound"]; Also you can play music (song.mp3) as [[SoundManager sharedManager] playMusic:#"song" looping:YES]; And can be stop music as [[SoundManager sharedManager] stopMusic]; Complete Documentation is on GitHub
First import this framework to your file #import <AVFoundation/AVFoundation.h> Then declare an instance of AVAudioPlayer. AVAudioPlayer *audioPlayer; NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"Name of your audio file" ofType:#"type of your audio file example: mp3"]; NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath]; audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil]; audioPlayer.numberOfLoops = -1; [audioPlayer play];
To play your bundle audio file using below code if you generate the system sound ID for(int i = 0 ;i< 5;i++) { SystemSoundID soundFileObject; NSString *audioFileName = [NSString stringWithFormat:#"Alarm%d",i+1]; NSURL *tapSound = [[NSBundle mainBundle] URLForResource: audioFileName withExtension: #"caf"]; // Store the URL as a CFURLRef instance CFURLRef soundFileURLRef = (__bridge CFURLRef) tapSound; // Create a system sound object representing the sound file. AudioServicesCreateSystemSoundID ( soundFileURLRef, &soundFileObject ); [alarmToneIdList addObject:[NSNumber numberWithUnsignedLong:soundFileObject]]; } You can play the sound by using below code AudioServicesPlaySystemSound([[alarmToneIdList objectAtIndex:row]unsignedLongValue]); To achieve this below framework need to add in your Xcode AudioToolbox Finally below header files are needs to be import in controller #import AudioToolbox/AudioToolbox.h #import AudioToolbox/AudioServices.h
Updated for Swift 4 Playing from main bundle - iOS 11 only import AVFoundation var player: AVAudioPlayer? The following code loads the sound file and plays it, returning an error if necessary. guard let url = Bundle.main.url(forResource: "test", withExtension: "m4a") else { return } do { try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback) try AVAudioSession.sharedInstance().setActive(true) guard let player = player else { return } player.play() } catch let error { // Prints a readable error print(error.localizedDescription) }
Swift 4.2 var soundFilePath = "\(Bundle.main.resourcePath ?? "")/test.m4a" var soundFileURL = URL(fileURLWithPath: soundFilePath) var player = try? AVAudioPlayer(contentsOf: soundFileURL) player?.numberOfLoops = -1 //Infinite player?.play()
Breakpoint triggers on device but not simulator
I have a weird situation where Xcode only catches the break point when running on the actual iPhone device, not the simulator. -(IBAction)ping1:(id)sender { // this is the break point NSString *path = [[NSBundle mainBundle] pathForResource:#"dontforgetme" ofType:#"mp3"]; AVAudioPlayer *sound = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL]; [sound play]; } Another problem is that when the button is touched, then ping1 is called and the sound plays, but only for one second or less even though the MP3 file has a 3 minute long sound. I don't understand any of this. How can it be happening? How can I find the problem?
AVPlayer Can't Play
I want to play a remote mp3 with AVPlayer. I can't make it work and I can't see the reason why it doesn't work. Code: NSString *urlstr=#"..some link to a mp3" NSURL *url=[NSURL URLWithString:urlstr]; self.player = [[[AVPlayer alloc] initWithURL:url] retain]; [player play]; The link is valid. If I load it in a webView it plays right away. Please help.
I have get a solution. Please try the following code: NSString *urlstr=#"http://www.3rdeyelab.com/mp3/mp3/tailtoddle_lo.mp3" NSURL *url=[NSURL URLWithString:urlstr]; AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:url]; player = [[AVPlayer playerWithPlayerItem:playerItem] retain]; [player play]; player.actionAtItemEnd = AVPlayerActionAtItemEndNone; Hope it will work for you!!!
If you use a local link as URL, so you should initiate url with fileURLWithPath method: NSURL *url = [NSURL fileURLWithPath:urlstr];
The NSURLConnection class, regardless of whether the URL is local or remote, should always be used whenever a URL is concerned. It's the only thread-safe, non-intrusive means of loading a AVPlayerItem or AVAsset. Remember: your app shares the iPhone with other apps; and, this is the way to be responsible insodoing.