core-audio - Audio Session "Ducking"在 iOS 4 中损坏...?

标签 core-audio ios4 avaudioplayer mpmusicplayercontroller

我有一个应用程序,它使用 MPAudioPlayerController 来访问 iPod 音乐库,并使用 AVAudioPlayer 将音频叠加在音乐上。我用过this documentation作为指导。具体来说:

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.

但我没有看到这种行为。事实上,我看到(或者听到的是)的是,如果我将 AudioSession 设置为 kAudioSessionProperty_OtherMixableAudioShouldDuck 设置为 true,则 MPAudioPlayerController 初始音量会减小,如果我随后在 MPAudioPlayerController 上调用暂停(然后再次播放)音量级别增加到“正常”水平。播放 AVAudioPlayer 对音频电平没有任何影响...

所以我设置了一个简单的测试用例来重现这一点。

在 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

并在实现中:

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

我已经连接了几个 UIButton。一个用于 musicAction(用于播放/暂停 MPMusicPlayerController),一个用于 soundAction(用于播放/暂停 AVAudioPlayer)。

如上所述,如果我点击 musicAction 按钮,则会播放音乐,但音量会降低;如果我点击 soundAction 按钮,则会播放叠加层,但不会影响 MPMusicPlayerController 的音量。而且,更类似错误的是,当我暂停然后播放 MPMusicPlayerController 时,音乐的音量会增加到我没有设置 AudioSession 时的水平。

我很想知道是否有其他人有过这种经历,如果有的话,您是否找到了解决方法(或者可以告诉我我做错了什么)。否则,我想我要去雷达了。

非常感谢,

李维

最佳答案

当我遇到类似问题并且无法使其一致工作时,我使用了这篇文章。它会工作一段时间,然后就会陷入“隐藏”状态。我花了很多时间研究和调试这个问题,最后才给苹果打电话。他们告诉我查看面包屑示例代码。我按照这个例子进行操作,一切正常。

这是苹果的示例代码:

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

Apple 的支持/开发人员还表示要注意他们设置 session 属性的方式和时间的顺序。这显然就是其中的伎俩。在阅读了这里和其他地方的很多帖子后,我的设置相互冲突。从头开始并遵循面包屑示例使其发挥作用。从那以后我就没有遇到过任何问题。

我在这里发布了相同的答案:

How to unduck AVAudioSession

对我来说,这个答案几乎是商业 secret ,因为它很难工作,而且市场上有可用的应用程序。对我来说,看到一个工作示例(几乎只是声音闪避和取消闪避)是值得的。

此外,我向 Apple 提到这是一个已知问题,但他们不同意。他们不知道这里有任何问题。果然,如果您按照面包屑示例进行操作,它就可以正常工作,不会出现任何奇怪的 session 停用和 react 等情况。

关于core-audio - Audio Session "Ducking"在 iOS 4 中损坏...?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3293651/

相关文章:

iOS - 连接混音器、remoteio 和动态处理器的 AudioFormat 问题

ios - CoreAudio 的首选语言

ios-simulator - LLVM 错误 : Cannot yet select: error

ios - 可以在我的 iOS 应用程序中使用 Apple 系统声音吗?

swift - 如何在 Swift 4 中将 HTTP 基本身份验证传递给 AVAudioPlayer

objective-c - 实时获取 macOS 输出设备音频缓冲区

ios - 在不移除混音器总线或停止/启动图的情况下停止总线渲染回调

ios - 使用 ios 5.0 测试时应用程序崩溃

ios - 在 staticLibrary 中加密字符串时出错

ios - AVAudioPlayer 在模拟器上工作但不在真实设备上工作