4

私はOpenALを使用してゲームサウンドを再生し、標準AVを使用してbg音楽を再生しています。最近、着信後、bg musicがまだ再生されている間は、すべてのオープンサウンドが機能しないことがわかりました。アプリを強制的に停止して再開すると、音が再び表示されます。smbdは、着信中/着信後にOpenalに何が起こっているかを知っていますか?

4

2 に答える 2

2

わかりました、解決策を見つけたようです。私はobj-cサウンドマネージャーを使用しているので、AVAudioSession(およびAVAudioPlayer)のbeginInterruptionおよびendInterruptionデリゲートメソッドをクラスに追加しました。

beginInterruptionは次のようになります。

alcMakeContextCurrent(NULL);

endInterruptionは次のようになります。

    NSError * audioSessionError = NULL;
    [audioSession setCategory:soundCategory error:&audioSessionError];
    if (audioSessionError)
    {
        Log(@"ERROR - SoundManager: Unable to set the audio session category");
        return;
    }

    // Set the audio session state to true and report any errors
    audioSessionError = NULL;
    [audioSession setActive:YES error:&audioSessionError];
    if (audioSessionError)
    {
        Log(@"ERROR - SoundManager: Unable to set the audio session state to YES with error %d.", (int) result);
        return;
    }

        //music players handling
    bool plays = false;
    if (musicPlayer[currentPlayer] != nil)
        plays = [musicPlayer[currentPlayer] isPlaying];
    if (musicPlayer[currentPlayer] != nil && !plays)
        [musicPlayer[currentPlayer] play];

    alcMakeContextCurrent(context);

はい、これはopenALサウンドのみを使用している場合に機能します。ただし、長いトラックを再生するには、AVAudioPlayerを使用する必要があります。しかし、ここに再びアップルの魔法があります!OpenALサウンドと一緒に音楽を再生すると、奇妙なことが起こります。着信をキャンセルすると、AVAudioSessionDelegate::endInterruptionとAVAudioPlayerDelegate::audioPlayerEndInterruptionが呼び出されることはありません。beginInterruptionのみであり、endではありません。AppDelegate :: applicationWillEnterForegroundでさえ呼び出されず、アプリは私たちが戻ってきたことを知りません。

ただし、幸いなことに、AppDelegate :: applicationDidBecomeActiveメソッドでendInterruptionを呼び出すことができ、openALコンテキストが復元されます。そしてこれはうまくいきます!

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    if (MySoundMngr != nil)
    {
        [MySoundMngr endInterruption];
    }

    // Restart any tasks that were paused and so on....
}
于 2012-12-03T17:41:07.523 に答える
0

これを理解するのに苦労したので、ここに私の答えを追加したいと思いました。これはすべて特にXamarinにありますが、一般的に適用され、@ Tertiumの答えに似ていると思います

  • 状況によっては、iOS がオーディオを中断するのを防ぐことができます (たとえば、電話がかかってきたが拒否した場合)。AVAudioSession.SharedInstance().SetPrefersNoInterruptionsFromSystemAlerts(true, out NSError err);

  • 場合によっては、まだ中断されることがあります (たとえば、電話を受けるなど)。これらをキャッチするにはAVAudioSession.Notifications.ObserveInteruption(myAudioInterruptionHandler);、アプリの起動時に行う必要があります。

このハンドラー内で、次のように、シャットダウンするか復帰するかを決定できます。

void myAudioInterruptionHandler(object sender, AVAudioSessionInterruptionEventArgs args) {
  args.Notification.UserInfo.TryGetValue(
    new NSString("AVAudioSessionInterruptionTypeKey"),
    out NSObject typeKey
  );
  bool isBeginningInterruption = (typeKey.ToString() == "1");
  // ...
}

中断開始

中断が始まったら、再生中のオーディオをすべて停止します (アプリに基づいて独自に処理する必要がありますが、おそらくAL.SourceStopすべてを呼び出す必要があります)。次に、批判的に、

ContextHandle audioContextHandle = Alc.GetCurrentContext();
Alc.MakeContextCurrent(ContextHandle.Zero);

これをすぐに行わないと、iOS が ALC コンテキストを焼き尽くしてしまいます。AudioRouteChangedthis is too lateのハンドラーがある場合は、ハンドラーで実行する必要があることに注意してくださいAudioInterruption

中断終了

中断から戻ったら、まず iOS オーディオ セッションを再起動します。 AVAudioSession.SharedInstance().SetActive(true);

優先入力をリセットする必要がある場合もあります (常にデフォルトの入力を使用する場合、この手順はオプションだと思います)。AVAudioSession.SharedInstance().SetPreferredInput(Input, out NSError err)

次に、コンテキストを復元します Alc.MakeContextCurrent(audioContextHandle);

于 2021-05-19T20:44:33.203 に答える