2010-07-20 6 views
8

Tengo una aplicación que utiliza el MPAudioPlayerController para acceder a la biblioteca de música del iPod, y un AVAudioPlayer para superponer el audio en la parte superior de la música. Utilicé this documentation como guía. Específicamente:Sesión de audio "Ducking" Roto en iOS 4 ...?

Finalmente, puede mejorar una categoría para bajar automáticamente el volumen de otro audio cuando se reproduce el audio. Esto podría usarse, por ejemplo, en una aplicación de ejercicio. Supongamos que el usuario se está ejercitando junto a su iPod cuando su aplicación desea superponer un mensaje verbal, por ejemplo, "ha estado remando durante 10 minutos". Para asegurarse de que el mensaje de su aplicación sea inteligible, aplique la propiedad kAudioSessionProperty_OtherMixableAudioShouldDuck al sesión de audio Cuando tiene lugar la inhibición, el resto del audio del dispositivo, además del audio del teléfono, baja de volumen.

Pero no estoy viendo este comportamiento. De hecho, lo que veo (u oigo, más bien) es que si configuro la AudioSession con kAudioSessionProperty_OtherMixableAudioShouldDuck establecido en true, el volumen inicial de MPAudioPlayerController se reduce, y si llamo pausa (y luego vuelvo a reproducir) en el MPAudioPlayerController el nivel de volumen se incrementa a niveles "normales". La reproducción de AVAudioPlayer no tiene ningún efecto en el nivel de audio ...

Así que configuré un caso de prueba simple para reproducir esto.

En una cabecera 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 

y en la ejecución:

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

he cableado de un par UIButtons. Uno para MusicAction (usado para reproducir/pausar el MPMusicPlayerController) y otro para soundAction (usado para reproducir/pausar el AVAudioPlayer).

Como mencioné, si toco el botón musicAction, la música se reproduce, pero a un nivel de volumen reducido, y si toco el botón soundAction, la superposición se reproduce, pero no afecta el volumen del MPMusicPlayerController. Y, más parecido a un error, es que cuando hago una pausa y luego reproduzco el MPMusicPlayerController, el volumen de la música aumenta al nivel que hubiera tenido si no hubiera configurado AudioSession.

Me interesa saber si alguien más ha tenido esta experiencia, y si es así, si ha encontrado un trabajo alternativo (o puede decirme que estoy haciendo algo mal). De lo contrario, supongo que me iré a Radar.

Muchas gracias,

Levi

Respuesta

2

La documentación no es clara acerca de lo que el comportamiento esperado de atenuación se supone que es, pero lo que he encontrado es que si configura su sesión de audio para agachándose, cuando activas la sesión de audio, se apaga, y cuando la desactivas, desaparece. Así que tienes que seguir activando y desactivando la sesión de audio para esquivar la música solo para tu pista de sonido.

Un error que encontré es que si desactiva la sesión de audio mientras está dentro del método audioPlayerDidFinishPlaying:successfully: de su AVAudioPlayerDelegate, no se elimina la oscilación y el volumen se mantiene en el mismo nivel. Ya he archivado un radar sobre esto, pero no hace daño si otros archivos similares. De hecho, probablemente les presione un poco para arreglarlo.

Lo que está haciendo es iniciar la sesión de audio y mantenerla activada, por lo que se agacha inmediatamente y se mantiene agachada, para que no escuche más la música cuando reproduce un sonido. El problema con el volumen de música que vuelve a subir después de pausar y reproducir la música suena como un error.

3

Ducking no se relaciona automáticamente con sus sonidos de reproducción de ninguna manera. Cuando enciendes ducking, patos de sonido de fondo. Cuando desaparece y desactiva su sesión de audio, el sonido de fondo vuelve a su nivel original.

Así que no enciéndalo en su viewDidLoad. No lo encienda hasta que esté a punto de reproducir el sonido. Eso hace que el sonido de fondo se agache. Cuando el sonido termine de reproducirse, apague la pantalla y active y vuelva a activar su sesión de audio. Eso causa que el sonido de fondo se desactive:

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

Utilicé esta publicación cuando tuve un problema similar y tuve problemas para conseguir que funcione de forma coherente. Funcionaría por un tiempo y luego se quedaría atascado "agachado". Pasé mucho tiempo investigando y depurando esto y finalmente llamé a Apple. Me dijeron que mirara el código de muestra de la ruta de navegación. Seguí ese ejemplo y todo funcionó bien.

Aquí es código de ejemplo de Apple:

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

El soporte/desarrollador en Apple también dijo que ver el orden de cómo y cuándo se establecen las propiedades de sesión. Ese aparentemente fue el truco. Después de leer una gran cantidad de publicaciones aquí y en otros lugares, tuve configuraciones que entraron en conflicto entre sí. Empezar de cero y seguir el ejemplo de la miga de pan lo hizo funcionar. No he tenido un problema desde entonces.

he publicado la misma respuesta aquí:

How to unduck AVAudioSession

Para mí esta respuesta era secreto comercial limítrofe ya que era muy difícil conseguir trabajo y no había aplicaciones de trabajo en el mercado. Para mí, ver un ejemplo de trabajo, que era simplemente el sonido de esquivar y desatar valía su peso en oro.

Además, mencioné a Apple que esto era un problema conocido y que no estaban de acuerdo. Ellos no estaban al tanto de ningún problema aquí. Efectivamente si sigues el ejemplo de breadcrumb, funciona sin ninguna sesión extraña deactivate y reactive, etc., etc.

Cuestiones relacionadas