Sessão de áudio “Ducking” Quebrado no iOS 4 ...?

Eu tenho um aplicativo que usa o MPAudioPlayerController para acessar a biblioteca de músicas do iPod e um AVAudioPlayer para sobrepor o áudio em cima da música. Eu useiesta documentação é um guia. Especificamente:

Por fim, você pode aprimorar uma categoria para diminuir automaticamente o volume de outro áudio quando o áudio estiver sendo reproduzido. Isso pode ser usado, por exemplo, em um aplicativo de exercícios. Digamos que o usuário esteja exercitando o iPod quando o aplicativo quiser sobrepor uma mensagem verbal - por exemplo, "Você está remando por 10 minutos". Para garantir que a mensagem do aplicativo seja inteligível, aplique a propriedade kAudioSessionProperty_OtherMixableAudioShouldDuck à propriedade sessão de áudio. Quando ocorre o abaixamento, todo o outro áudio no dispositivo - além do áudio do telefone - diminui o volume.

Mas não estou vendo esse comportamento. De fato, o que eu vejo (ouço) é que, se eu configurar o AudioSession com kAudioSessionProperty_OtherMixableAudioShouldDuck definido como true, o volume inicial do MPAudioPlayerController será reduzido e, se eu chamar pausa (e depois reproduzir novamente) no MPAudioPlayerController, o nível do volume aumenta para níveis "normais". A reprodução do AVAudioPlayer não afeta o nível de áudio ...

Então, eu configurei um caso de teste simples para reproduzir isso.

Em um cabeçalho ViewController:

#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

e na implementação:

- (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];
    }
}

Eu conectei alguns UIButtons. Um para o musicAction (usado para reproduzir / pausar o MPMusicPlayerController) e outro para o soundAction (usado para reproduzir / pausar o AVAudioPlayer).

Como mencionado, se eu tocar no botão musicAction, a música será reproduzida, mas em um nível de volume reduzido, e se eu tocar no botão soundAction, a sobreposição será reproduzida, mas não afetará o volume do MPMusicPlayerController. E, mais parecido com um bug, é que, quando faço uma pausa e reproduzo o MPMusicPlayerController, o volume da música aumenta para o nível que seria se eu não tivesse configurado o AudioSession.

Estou interessado em saber se alguém já teve essa experiência e, em caso afirmativo, se você encontrou uma solução alternativa (ou pode me dizer que estou fazendo algo errado). Caso contrário, acho que vou para o Radar.

Muito Obrigado,

Levi

questionAnswers(3)

yourAnswerToTheQuestion