1

作成中のアプリで SpeakHere オーディオ クラスを使用しており、再生と録音を同時に行う必要があります。

ユニバーサル アプリ ビルド (iPad と iPhone をターゲット) で 3.2 デバイス ターゲットの最新の SDK を使用しています。

このアプリは、MPMoviePlayerController を使用してストリーミング ムービーを再生し、オーディオを同時に記録します。

これは iPhone で 100% 完璧に動作します。

ただし、クライアントの iPad では 100% 失敗します。 ログには、AudioSession が単にアクティブ化を拒否している !act エラーが表示されます。そして、私が彼から受け取ったすべてのログ ファイルには、コールバック関数に返される多数の中断とルートの変更 (つまり、カテゴリ) が含まれています。**iPhone では、このようなものはまったく表示されません。ログは、レコードが作成され、指定されたファイルに記録されたことのみを示しています。中断もルート変更もナンセンスもありません。

関連するログは次のとおりです。

Jul 10 07:15:21 iPad mediaserverd[15502] <Error>: [07:15:21.464 <0x1207000>] AudioSessionSetClientPlayState: Error adding running client - session not active
Sat Jul 10 07:15:21 iPad mediaserverd[15502] <Error>: [07:15:21.464 <AudioQueueServer>] AudioQueue: Error '!act' from AudioSessionSetClientPlayState(15642)

両方のコールバック関数をスタブ化して、中断の発生とルートの変更を (理由と共に) 記録するだけにしました。文字通り何もしないので、わざわざコードを投稿するつもりはありません。ただし、iPad で記録を開始しようとすると、これらのログが何度も表示されます。

Apple DevフォーラムとStackOverflowで見つけることができるほぼすべての投稿を読みましたが、同じ問題を抱えている人や、iPadの動作の違いを説明するApple Docsの関連するメモを見つけることができないようです. -- 注: iPad には、不一致の Begin Interruption 呼び出しが終了しないなど、修正された他の欠陥のある動作がいくつか表示されました (そのため、セッションを非アクティブ化することはありませんでした)。

AudioQueue または AudioSession コードからの初期化またはアクティベーションの呼び出しが失敗したことを示すログを受け取りません。録音を開始しようとすると、単に失敗します。-- AudioSessionSetActive(true); を強制しようとさえしました。サウンド システムを使用しようとするたびに呼び出しを行っても、これらのエラーが引き続き発生します。

初期化呼び出しに関連するコードは次のとおりです。

//Initialize the Sound System
    OSStatus error = AudioSessionInitialize(NULL, NULL, interruptionListener, self);
    if (error){ printf("ERROR INITIALIZING AUDIO SESSION! %d\n", (int)error); }
    else {
        //must set the session active first according to devs talking about some defect....         
        error = AudioSessionSetActive(true); 
        if (error) NSLog(@"AudioSessionSetActive (true) failed");

        UInt32 category = kAudioSessionCategory_PlayAndRecord;  
        error = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(category), &category);
        if (error) printf("couldn't set audio category!\n");

        error = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, propListener, self);
        if (error) printf("ERROR ADDING AUDIO SESSION PROP LISTENER! %d\n", (int)error);

        //Force mixing!
        UInt32 allowMixing = true;
        error = AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof (allowMixing), &allowMixing );
        if (error) printf("ERROR ENABLING MIXING PROPS! %d\n", (int)error);

        UInt32 inputAvailable = 0;
        UInt32 size = sizeof(inputAvailable);           
        // we do not want to allow recording if input is not available
        error = AudioSessionGetProperty(kAudioSessionProperty_AudioInputAvailable, &size, &inputAvailable);
        if (error) printf("ERROR GETTING INPUT AVAILABILITY! %d\n", (int)error);
        isInputAvailable = (inputAvailable) ? YES : NO;


        //iPad doesn't require the routing changes, branched to help isolate iPad behavioral issues
        if(! [Utils GetMainVC].usingiPad){
            //redirect to speaker?  //this only resets on a category change!
            UInt32 doChangeDefaultRoute = 1;        
            error = AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryDefaultToSpeaker, sizeof (doChangeDefaultRoute), &doChangeDefaultRoute);
            if (error) printf("ERROR CHANGING DEFAULT ROUTE PROPS! %d\n", (int)error);

            //this resets with interruption and/or route changes
            UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker; 
            error = AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute,sizeof (audioRouteOverride),&audioRouteOverride);
            if (error) printf("ERROR SPEAKER ROUTE PROPS! %d\n", (int)error);
        }

        // we also need to listen to see if input availability changes
        error = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioInputAvailable, propListener, self);
        if (error) printf("ERROR ADDING AUDIO SESSION PROP LISTENER! %d\n", (int)error);

        error = AudioSessionSetActive(true); 
        if (error) NSLog(@"AudioSessionSetActive (true) failed");
    }

    // Allocate our singleton instance for the recorder & player object
    myRecorder = new AQRecorder();
    myPlayer = new AQPlayer();

後でビデオの loadstate コールバックで、あらかじめ決められたファイルパスへの記録を開始しようとします。

myRecorder->StartRecord((CFStringRef)myPathStr);

そして、オーディオ録音は完全に失敗します。

お時間をいただきありがとうございます。

4

1 に答える 1

0

これは奇妙な問題であることが判明しました。

1)録音と再生のみを使用すると、コードはiPadで完全に実行されます。

2)ムービーの再生を追加し、ルーティングの変更を呼び出さないでください。iPadでは問題なく動作します。

どういうわけか、Movie Playerの再生の存在は、何らかの方法でAudioSessionを変更するのに十分であり、ルートの変更を強制すると(ヘッドフォンの代わりにデバイスのスピーカーを使用するなど)、AudioSessionが非アクティブになります。

于 2010-07-13T18:26:46.197 に答える