2010-07-20 6 views
8

J'ai une application qui utilise MPAudioPlayerController pour accéder à la bibliothèque musicale iPod, et un AVAudioPlayer pour superposer l'audio sur la musique. J'ai utilisé this documentation comme guide. Plus précisément:Session audio "Ducking" Broken dans iOS 4 ...?

Enfin, vous pouvez améliorer une catégorie pour réduire automatiquement le volume des autres fichiers audio lors de la lecture de votre fichier audio. Cela pourrait être utilisé, par exemple, dans une application d'exercice. Supposons que l'utilisateur s'exerce sur son iPod lorsque votre application souhaite superposer un message verbal, par exemple, «Vous avez ramé pendant 10 minutes». Pour vous assurer que le message de votre application est intelligible, appliquez la propriété kAudioSessionProperty_OtherMixableAudioShouldDuck au session audio. Lorsque l'atténuation est effectuée, tous les autres sons de l'appareil, à l'exception de l'audio du téléphone, diminuent en volume.

Mais je ne vois pas ce comportement. En fait, ce que je vois (ou entend, plutôt), c'est que si je configure l'AudioSession avec kAudioSessionProperty_OtherMixableAudioShouldDuck réglé sur true, le volume initial de MPAudioPlayerController est réduit, et si j'appelle ensuite pause (puis relance) sur le MPAudioPlayerController le niveau de volume passe à des niveaux "normaux". La lecture de l'AVAudioPlayer n'a aucun effet sur le niveau audio ...

J'ai donc configuré un scénario de test simple pour reproduire ceci.

Dans un en-tête 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 

et dans la mise en œuvre:

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

J'ai câblé un couple UIButtons. Un pour le musicAction (utilisé pour lire/mettre en pause le MPMusicPlayerController) et un pour le soundAction (utilisé pour jouer/mettre en pause le AVAudioPlayer). Comme je l'ai mentionné, si j'appuie sur le bouton musicAction, la musique est lue, mais à un volume réduit, et si j'appuie sur le bouton soundAction, la superposition est lue, mais n'a aucun effet sur le volume du MPMusicPlayerController. Et, plus bête, c'est que lorsque je fais une pause puis que je joue sur MPMusicPlayerController, le volume de la musique augmente au niveau qu'elle aurait atteint si je n'avais pas configuré l'AudioSession.

Je suis curieux de savoir si quelqu'un d'autre a eu cette expérience, et si oui, si vous avez trouvé un travail (ou peut me dire que je fais quelque chose de mal). Sinon, je suppose que je pars pour Radar.

Un grand merci,

Levi

Répondre

2

La documentation n'est pas clair sur ce que le comportement attendu de ducking est censé être, mais ce que j'ai trouvé est que si vous configurez votre session audio pour esquiver, lorsque vous activez la session audio, il se penche, et quand vous le désactivez, il se faufile. Donc, vous devez continuer à activer et désactiver la session audio pour éviter la musique juste pour votre signal sonore.

Un bug que j'ai trouvé est que si vous désactivez la session audio alors que dans la méthode audioPlayerDidFinishPlaying:successfully: de votre AVAudioPlayerDelegate, le ducking n'est pas supprimé, et le volume est maintenu au même niveau. J'ai déjà déposé un radar sur ce sujet, mais ça ne fait pas de mal si d'autres fichiers similaires. En fait, il y aura probablement de la pression sur eux pour le réparer.Ce que vous faites est de démarrer la session audio et de la garder en marche, de sorte qu'elle se bloque immédiatement et reste couchée, de sorte qu'elle n'évite pas la musique plus loin quand vous jouez un son. Le problème avec le volume de musique remontant après avoir fait une pause et joué de la musique sonne comme un bug.

3

Le dévers n'est pas automatiquement lié aux sons que vous jouez. Lorsque vous activez le ducking, fond sonore canards. Lorsque vous désactivez l'atténuation et désactivez votre session audio, le son d'arrière-plan revient à son niveau d'origine.

Donc ne pas activer le ducking dans votre viewDidLoad. Ne l'allumez pas tant que vous n'êtes pas sur le point de jouer le son. Cela provoque le bruit de fond à se baisser. Lorsque votre son est joué, désactivez-le et basculez votre session audio inactive et active à nouveau. Cela provoque le bruit de fond à Unduck:

UInt32 duck = 0; 
AudioSessionSetProperty(kAudioSessionProperty_OtherMixableAudioShouldDuck, 
         sizeof(duck), &duck); 
AudioSessionSetActive(false); 
AudioSessionSetActive(true); 
9

J'ai utilisé ce poste lorsque j'avais un problème similaire et que j'avais du mal à le faire fonctionner de manière cohérente. Cela fonctionnerait pendant un moment et ensuite resterait coincé "esquivé". J'ai passé beaucoup de temps à chercher et à déboguer ceci et finalement j'ai juste appelé Apple. Ils m'ont dit de regarder l'exemple de code de fil d'Ariane. J'ai suivi cet exemple et tout a bien fonctionné.

Voici le code exemple d'Apple:

http://developer.apple.com/library/ios/#samplecode/Breadcrumb/Introduction/Intro.html

Le support/développeur chez Apple a également dit de regarder l'ordre de comment et quand ils définissent les propriétés de session. C'était apparemment le truc. Après avoir lu beaucoup de messages ici et ailleurs, j'avais des paramètres qui étaient en conflit les uns avec les autres. En partant de zéro et en suivant l'exemple des miettes de pain, cela a fonctionné. Je n'ai pas eu de problème depuis.

J'ai posté la même réponse ici:

How to unduck AVAudioSession

Pour moi, cette réponse était secret commercial limite car il était si difficile de faire fonctionner et il y avait des applications travaillant sur le marché. Pour moi, voir un exemple de travail, qui était à peu près juste le son de ducking et de défaire, valait son pesant d'or.

En outre, j'ai mentionné à Apple que c'était un problème connu et qu'ils n'étaient pas d'accord. Ils n'étaient au courant d'aucun problème ici. Effectivement si vous suivez l'exemple de fil d'Ariane cela fonctionne avec toute session étrange désactiver et réactif, etc., etc.