views:

1028

answers:

2

We have a game that is very close to being released, but we have one extremely annoying problem. One on of our Beta testers phones, he can't hear any of the in game sound effects. He can, however, hear the background music and the title screen music just fine.

The background and title music are both being played via AVAudioPlayer (they are longer, we need looping and volume control, etc). The sound effects are simply being played with AudioServicesPlaySystemSound (they are very short, we don't need precise control or to know when they end, etc). This works on most iPhones, but not on this one. All of this is being played with an audio session of AVAudioSessionCategorySoloAmbient.

So I have two questions: - First, is this an acceptable implementation? i.e. is there something I missed that says you can't mix these two frameworks, or a reason why its a bad idea to mix them? - Second, has anyone seen something like this before? If so, did you find a way around it?

Additional background note: I can pretty conclusively say that on his phone, it is the mixing of the two frameworks. He was able to hear sounds until roughly the same build where we added the title screen music. Also, if I change one of the sounds to work through an AVAudioPlayer, he's able to hear it. Unfortunately, I can't simply move the sounds into AVAudioPlayers because it just doesn't perform well at all, and I need better synchronization.

+2  A: 

I have two apps on the app store that mix those two frameworks. AVAudioPlayer for sounds that require start and stop and volume control and AudioServices toolbox for short little beeps and clicks. The only think I can think of, off the top of my head, is that the volume of AVAudioPlayer seems to be controlled separately from the AudioServices sounds. So check to make sure that the tester doesn't have sounds turned off (with the vibrate mode switch) or the volume turned way down.

If this doesn't help, tell me more about your sounds/code and I can add some code to my app to see if I can get the same behavior. Of course, sounds like most your testers don't have this problem, and I probably won't see it either.

mahboudz
I'm going to mark your answer as accepted, as you've answered my main question (can you mix the two). I think this tester's phone may be a fluke, as I've seen it work on a bunch of others.
Bdebeez
+2  A: 

EDIT 2:
I've determined the cause of the error. The two different audio frameworks play on two different volume settings. There is the main volume (that's what shows up once you are in the app, and has no title on it) and the ringer volume (that's what shows up when you're on the home screen without any app loaded). The AVAudioPlayer calls play with the main volume setting. As I have set the category to AVAudioSessionCategorySoloAmbient (see code below), this is the volume control that will be adjusted if you use the volume rocker inside the app. The SystemSounds, however, are played at the Ringer Volume. This will NOT come up inside the app, and as such does not allow the user to adjust their settings during the game.

It's easy to see the possible confusion for the user: Let's say they have their ringer set to low, or even off. They start playing the game. They hear the title screen music (AVAudioPlayer) and are able to turn the volume up or down and it responds normally. Then they start the game and the sound effects play (SystemSounds), and they hear nothing because the ringer volume is low/off. In an effort to hear the sound effects, they bump up the volume and the background music responds accordingly. So from this point of view, it definitely looks like the sound effects just aren't playing.

If you have this similar situation, have your user make sure that their ringer volume is up before playing the game and their mute switch is on (i.e. not muted). You can also verify all of this by doing the test yourself - drop your ringer volume and bump your in-app volume up. Your SystemSounds should drop out of the mix.

Original answer: In re-digging through all of the docs, I found the answer. I wasn't properly activating the audio session. Previously I only had this code to set the category:

NSError *setCategoryError = nil; 
BOOL    categoryWasSet    = [[AVAudioSession sharedInstance] 
                              setCategory: AVAudioSessionCategorySoloAmbient 
                              error: &setCategoryError];

But I needed to also add the following code to explicitly activate the audio session:

NSError *activationError  = nil;
BOOL    activationSuccess = [[AVAudioSession sharedInstance]
                              setActive: YES 
                              error: &activationError];

I've re-tested with this user, and it has completely fixed the issue. Hope that helps anyone who might have a similar problem.

EDIT: This doesn't seem to have resolved the issue after all. I got a false positive from my tester, and when examined more in detail it seems that he didn't actually hear the SystemSound generated sounds.

Bdebeez
I wonder if it is worth sending that user a simple test app that plays two sounds, plus a lot of NSLogs for things like AVAudioSession settings, and volumes, etc.
mahboudz
Yeah, that's a great idea and was thinking the same thing. I'll report back if I can find anything interesting.
Bdebeez
Oddly enough, I was able to reproduce this on the Simulator - and I see a message that there was an error setting the Category. I'm not exactly sure how to respond to that. I could perhaps not play the MP3 title music (because w/o the category I wouldn't have access to the HW decoders).The truly ironic thing is that when I had this test user pulls logs from his phone, the first test run to get the logs actually worked and played all sounds :) So I think its pretty conclusive that its mostly a fluke, and is probably related to getting the category set properly.
Bdebeez
FOLLOW-UP: I ended up launching like this, but I've revamped the audio system to OpenAL. Mixing OpenAL and AVAudioPlayer does NOT produce this two-channel issue (i.e. everything ends up on the volume, is modifiable inside of the app, and the ringer volume is ignored)
Bdebeez