Hello all,
I've an app which uses the MPAudioPlayerController to access the iPod music library, and an AVAudioPlayer to overlay audio on top of the music. I've used this documentation as a guide. Specifically:
Finally, you can enhance a category to automatically lower the volume of other audio when your audio is playing. This could be used, for example, in an exercise application. Say the user is exercising along to their iPod when your application wants to overlay a verbal message—for instance, “You’ve been rowing for 10 minutes.” To ensure that the message from your application is intelligible, apply the kAudioSessionProperty_OtherMixableAudioShouldDuck property to the audio session. When ducking takes place, all other audio on the device—apart from phone audio—lowers in volume.
But I'm not seeing this behavior. In fact, what I see (or hear, rather) is that if I setup the AudioSession with kAudioSessionProperty_OtherMixableAudioShouldDuck set to true, the MPAudioPlayerController initial volume gets reduced, and if I then call pause (and then play again) on the MPAudioPlayerController the volume level gets increased to "normal" levels. Playing the AVAudioPlayer does not have any affect on the audio level...
So I've set up a simple test case to reproduce this.
In a ViewController header:
#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
@interface MusicPlayerVolumeTestViewController : UIViewController <AVAudioPlayerDelegate>
{
UIButton *musicButton;
UIButton *soundButton;
AVAudioPlayer *audioPlayer;
MPMusicPlayerController *musicPlayerController;
}
@property (nonatomic, retain) IBOutlet UIButton *musicButton;
@property (nonatomic, retain) IBOutlet UIButton *soundButton;
@property (nonatomic, retain) MPMusicPlayerController *musicPlayerController;
- (IBAction)musicAction;
- (IBAction)soundAction;
@end
and in the implementation:
- (void)viewDidLoad
{
[super viewDidLoad];
//Setup our Audio Session
OSStatus status = AudioSessionInitialize(NULL, NULL, NULL, NULL);
//We want our audio to play if the screen is locked or the mute switch is on
UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
status = AudioSessionSetProperty (kAudioSessionProperty_AudioCategory, sizeof (sessionCategory), &sessionCategory);
//We want our audio to mix with other app's audio
UInt32 shouldMix = true;
status = AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof (shouldMix), &shouldMix);
//Enable "ducking" of the iPod volume level while our sounds are playing
UInt32 shouldDuck = true;
AudioSessionSetProperty(kAudioSessionProperty_OtherMixableAudioShouldDuck, sizeof(shouldDuck), &shouldDuck);
//Activate our audio session
AudioSessionSetActive(YES);
//Setup the Music Player to access the iPod music library
self.musicPlayerController = [MPMusicPlayerController applicationMusicPlayer];
[self.musicPlayerController setShuffleMode: MPMusicShuffleModeSongs];
[self.musicPlayerController setRepeatMode: MPMusicRepeatModeNone];
[self.musicPlayerController setQueueWithQuery:[MPMediaQuery songsQuery]];
//Setup a AVAudioPlayer sound to overlay against the Music Player audio
NSURL *soundURL = [NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"overlay" ofType:@"mp3"]];
NSError *error = nil;
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundURL error: &error];
if (!audioPlayer)
{
NSLog(@"Could not create audio effect player: %@", [error localizedDescription]);
}
[audioPlayer prepareToPlay];
}
- (IBAction)musicAction
{
if (self.musicPlayerController.playbackState == MPMusicPlaybackStatePlaying)
{
[self.musicPlayerController pause];
}
else if (self.musicPlayerController.playbackState == MPMusicPlaybackStateStopped
|| self.musicPlayerController.playbackState == MPMusicPlaybackStatePaused)
{
[self.musicPlayerController play];
}
}
- (IBAction)soundAction
{
if (audioPlayer.playing)
{
[audioPlayer pause];
}
else
{
[audioPlayer play];
}
}
I've wired up a couple UIButtons. One for the musicAction (used for playing/pausing the MPMusicPlayerController) and one for the soundAction (used for playing/pausing the AVAudioPlayer).
As mentioned, If I tap the musicAction button, the music plays, but at a reduced volume level, and if I tap the soundAction button, the overlay plays, but has no affect on the volume of the MPMusicPlayerController. And, more bug-like, is that when I pause and then play the MPMusicPlayerController the volume of the music increases to the level it would have been if I did not setup the AudioSession.
I'm interested to know if anyone else has had this experience, and if so if you've found a work around (or can tell me that I'm doing something wrong). Otherwise, I guess I'm off to Radar.
Many thanks,
Levi