8
votes

I know, I have to set the AudioSession to the 'playback' category, which allows audio even when the mute switch is on. This is what I do, but sound still gets muted when switch is on.

 UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
 AudioSessionSetProperty(kAudioSessionProperty_AudioCategory,sizeof(sessionCategory), &sessionCategory);

 SystemSoundID soundID;
 NSString *path = [[NSBundle mainBundle] pathForResource:soundString ofType:@"wav"];    

 AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:path],&soundID);
 AudioServicesPlaySystemSound (soundID);


EDIT: by the way, the app is a soundpad. Playing sound is the sole purpose of the app. Here's what Apple Doc says about this:

Use this category for an application whose audio playback is of primary importance. Your audio plays even with the screen locked and with the Ring/Silent switch set to silent.


EDIT 2: with the mute switch on, sound wont even play through the headphones. I know the user is king. I know the mute switch has its purpose. That is not the question. I'm trying to get an answer on the fact that setting the AudioSession category to kAudioSessionCategory_MediaPlayback doesn't have the expected result.


EDIT 3: following Jonathan Watmough's suggestion, I set the AudioServices kAudioServicesPropertyIsUISound property, but still no luck. Am I missing something?

// set the session property
UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory,sizeof(sessionCategory), &sessionCategory);

// creates soundID
SystemSoundID soundID;
NSString *path = [[NSBundle mainBundle] pathForResource:soundString ofType:@"wav"];    
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:path],&soundID);

// Jonathan Watmough suggestion
UInt32 flag = 0;
AudioServicesSetProperty(kAudioServicesPropertyIsUISound, sizeof(UInt32), &soundID, sizeof(UInt32), &flag);

AudioServicesPlaySystemSound (soundID);
5
Seems downright malicious to play sound when the user has muted their phone. If the system level stuff doesn't do it why should your app. Unless your app is "nuclear reactor meltdown warning" I see NO reason why your app should be allowed to interrupt a meeting, wedding or funeral with noise.Matt Mitchell
From the Apple Doc: "Use this category for an application whose audio playback is of primary importance. Your audio plays even with the screen locked and with the Ring/Silent switch set to silent."samvermette
So what classifies as primary importance to you? I guess at the end of the day they have opened your app as I forgot that your app can't execute actions without them opening it but even still it if they have their phone muted and get no noise that seems desired behaviour.Matt Mitchell
I would respect the user's wishes. Sit back a little and think this through, The keypad making noises when I have muted the phone is NOT proper behavior.Romain Hippeau
There are definitely times when playing sound with the mute switch is perfectly fine, and Sam's case seems to be one of those. If the purpose of action the user is performing is to play a sound or music, it seems perfectly fine to do it whether the silent switch is on or off. This is the behavior of the iPod application.David Barry

5 Answers

4
votes

Well to add on Jonathan Watmough's answer, indeed it doesn't seem possible to let AudioServicesSystemSound overwrite the mute switch. What I ended up doing is using OpenAL to play the sounds, which will play just fine following the Audio Session category you specify. Here's how I setup the Audio session:

AudioSessionInitialize(NULL, NULL, NULL, NULL);
UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory,sizeof(sessionCategory), &sessionCategory);
AudioSessionSetActive(YES);

To play the sounds, I used Finch, a simple OpenAL-based sound effect player for iPhone.

1
votes

I haven't tried it yet, but you may want to change the property on your loaded sound:

kAudioServicesPropertyIsUISound A UInt32 value, where 1 means that, for the audio file specified by a system sound passed in the inSpecifier parameter, the System Sound server respects the user setting in the Sound Effects preference and is silent when the user turns off sound effects. This property is set to 1 by default. Set it to 0 for the system sound to always play when passed to AudioServicesPlaySystemSound, regardless of the user's setting in sound preferences. Available in iPhone OS 2.0 and later. Declared in AudioServices.h.

I'd expect that having done everything else right, setting the property to 0 will tell the system that your sound is an app sound, and not a 'UI' sound and hence subject to muting.

EDIT: It looks like it can't be done with system sounds. If you go through OpenAL, you will obviously be able to play with the mute button set.

I built the SysSound sample, and added the following code to set the flag as you did above, and it doesn't play on mute at all.

 // Set the sound to always play
    int setTo0 = 0;
    AudioServicesSetProperty( kAudioServicesPropertyIsUISound,0,nil,
                             4,&setTo0 );
0
votes

You are calling setActive:error: for the AVAudioSession somewhere right? Here is the code that I use to initialize. But I'm not using system sounds, I'm using AVAudioPlayer to play sounds.

avSession = [AVAudioSession sharedInstance];    // init session, important

// allow other audio to mix, such as iPod
const UInt32 categoryProp = kAudioSessionCategory_MediaPlayback;
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(categoryProp), &categoryProp);

UInt32 category = kAudioSessionCategory_MediaPlayback;
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(category), &category);

// Allow our audio to mix with any iPod audio that is playing
AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof(setProperty_YES), &setProperty_YES);

[avSession setActive:YES error:nil];
0
votes

I cannot find it explicitly mentioned in the docs, but I would expect the AudioServicesPlaySystemSound() ignores your audio session configuration.

If you want to control the session mixing and other properties you need to use AVAudioPlayer instead e.g.:

NSError *err;
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayback error:&err];
[session setActive:YES error:&err];

NSString *path = [[NSBundle mainBundle] pathForResource:@"Basso" ofType:@"aiff"];    
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:&err];
[player prepareToPlay];
[player play];
0
votes

i am using the below code to solve my issue

AudioSessionInitialize(NULL, NULL, NULL, NULL); UInt32   
sessionCategory = kAudioSessionCategory_MediaPlayback;    
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory,sizeof(sessionCategory),
&sessionCategory); AudioSessionSetActive(YES);