AVAudioPlayer not playing any sound
Asked Answered
B

10

64

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.

Balustrade answered 4/11, 2011 at 23:9 Comment(3)
Can you tell us what the error variable outputs? The one from here AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];Baseline
@Maudicus, as I said, error is nil after playing the sound. I found the solution and it's related to something I didn't mention and didn't think about: I'm compiling with ARC. ARC inserts a release call to the audio player, so it's deallocated right after leaving the method where it is created, as explained hereBalustrade
I'm sorry I had copied your code and it worked. Missed your statement about error being nil. I'm glad it's resolvedBaseline
B
170

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.

Balustrade answered 7/12, 2011 at 13:8 Comment(6)
This had happened to me before, in a circumstance that had nothing to do with AVAudioPlayer, and even I forgot this solution when running into a problem with AVAudioPlayer inexplicably not playing sounds. Good thing to remember about ARC!Pedagogy
I know this is an old topic, but rather than create a new question asking the same thing, can you please explain to me like I am five years old what this means? I made an iOS app, I have a submit button, and when the calculations are done, it plays a sound. I made a simplified version first as an OS X app which worked fine, but as an iOS app, using the AVAudioPlayer rather than NSSound or something it doesn't work, and 50% of the time will cause the app to crash.Legionary
@JonathanWeinraub Sorry, but it's hard to tell without seeing any code. Your crashes and AVAudioPlayer issues can be related to several reasons.Balustrade
thnx a lot. Had the same problem.Oraliaoralie
I needed multiple players, so as opposed to multiple properties, I created an NSMutableDictionary and stored the players with the key as the lastPathComponent.Defray
This is correct. Because it plays the sound async, your AVAudioPlayer object is lost before the sound is playedHardiman
C
39

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.

Camey answered 18/4, 2012 at 9:31 Comment(1)
Do you still do alloc initWithContentsOfUrl??Cahn
S
32

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];
Subzero answered 7/3, 2014 at 7:19 Comment(2)
The AVAudioSession did the trick for me. Without it, I could only play the sound in the simulator, not on the device.Foliated
This helped me a lot!Shanda
K
21

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.

Kattie answered 5/12, 2011 at 11:30 Comment(2)
I already answered Madicus about this, but I didn't post it as a direct answer to my question, because I couldn't (probably because StackOverflow doesn't allow auto-answering during the first hours/days). The official answer is here now. :) Thanks anyway!Balustrade
Add that to your viewDidLoad method. Setting up the session after recording but before playback doesn't work. Also, without setting up the session, it worked in simulator but not on device.Panettone
G
6

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)
Gliadin answered 5/11, 2017 at 20:52 Comment(0)
R
1

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

Reprobative answered 23/1, 2014 at 17:25 Comment(0)
B
0

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];
Babiche answered 29/6, 2016 at 10:3 Comment(0)
W
0

You can use AVPlayerViewController from AVKit instead for both audio and video. Code is available for both swift and objective c here.

Williawilliam answered 10/8, 2018 at 19:36 Comment(0)
N
0

for me this did the job

do {
     try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback)
    } catch {
        assertionFailure("Failed to configure `AVAAudioSession`: \(error.localizedDescription)")
    }
Northeastwards answered 29/6, 2020 at 12:23 Comment(0)
W
-1

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);

Whitecap answered 16/10, 2014 at 5:50 Comment(3)
Try to avoid using sleep, dispatch_after is a much better alternative.Foliated
This code will make audioPlayer instance be alive for 2 secs. This makes the code dependent on the length of the audio file and will not work for any audio file. Besides, it'll suspend the calling thread for 2 secs which, in most situations, won't be the desired behavior.Balustrade
This is a hackish but creative solution that has its advantages and disadvantages. In my case I'm trying to alert the user to new info. Freezing all activity in the App for a second while playing an alert sound is actually a good way to get the user's attention. So this actually aligns with my needs. It does not deserve a down-vote.Kasper

© 2022 - 2025 — McMap. All rights reserved.