オーディオキューサービスプログラミングガイド



Audio Queue Services Programming Guide



前書き

Audio Queueサービスはより高度なサービスです。これにより、アプリケーションは、ハードウェアインターフェイスを知らなくても、オーディオの録音と再生にハードウェア(マイクやスピーカーなど)を使用できます。同時に、オーディオキューサービスはいくつかの高度な機能をサポートしています。細かいタイミング制御と、スケジュールされた再生と同期のサポートを提供します。これを使用して、複数のオーディオキューの再生を同期し、オーディオをビデオに同期することができます。

Audio Queue Serviceは、CocoaアプリケーションおよびMac OSXコマンドラインツールで使用できる純粋なCインターフェイスです。オーディオキューサービスに焦点を合わせ続けるために、このドキュメントのコード例は、Core AudioSDKのC ++クラスを使用して簡略化されている場合があります。ただし、オーディオキューサービスを使用するためにSDKおよびC ++言語は必要ありません。



オーディオキュー

この章では、オーディオキューの機能、アーキテクチャ、および内部動作について学習します。オーディオキュー、オーディオキューバッファ、およびオーディオキューは、オーディオの録音と再生のためのコールバック関数に導入されます。オーディオキューのステータスとパラメータについても学ぶことができます。

オーディオキューとは何ですか?

オーディオキューは、iOSおよびMacプラットフォームでオーディオを再生および録音するためのソフトウェアオブジェクトです。これはAudioQueueRefタイプで表され、AudioQueue.hヘッダーファイルで宣言されます。



オーディオキューは次のことを行います。

  • オーディオハードウェアを接続する
  • 管理メモリ
  • 使用されるコーデックは、必要に応じてオーディオ形式を圧縮します
  • オーディオの録音と再生

オーディオキューの構造

すべてのオーディオキューはほぼ同じ構造で、次のコンポーネントがあります。

  • オーディオキューバッファのセット。各バッファは、一部のオーディオデータの一時的なリポジトリです。
  • バッファキュー、オーディオキューバッファの順序付きリスト
  • 定義する必要があるのは、オーディオキューコールバック関数です。

構造は、オーディオキューが録音用か再生用かによって異なります。違いは、オーディオキューが入力と出力を接続する方法と、コールバック関数の役割です。



録音されたオーディオキュー

録音されたオーディオキュー、使用済みAudioQueueNewInput関数は次の構造で作成されます。

録音オーディオキューの入力側は、通常、マイクなどの外部オーディオハードウェアに接続されます。 iOSでは、音声はヘッドセットに接続されたマイクまたはデバイスから送信されます。 Mac OS Xでは、デフォルトで、オーディオはシステムのデフォルトのオーディオ入力デバイスから送られます。これは、システム環境設定でユーザーが設定します。

録音されたオーディオキューの出力は、コールバック関数です。ディスクに録音するとき、コールバックはオーディオキューから受信した新しいオーディオデータのバッファをオーディオファイルに書き込みます。ただし、録音オーディオキューは他の方法で使用できます。たとえば、リアルタイムオーディオアナライザで使用することもできます。この場合、コールバックはディスクに書き込む代わりに、オーディオデータをアプリケーションに直接提供します。

各オーディオキューは、録音されているか再生されているかに関係なく、1つ以上のオーディオキューバッファを備えています。これらのバッファは、バッファキューと呼ばれる特定の順序で配置されます。示されているように、オーディオキューバッファには、データが入力される順序に従って番号が付けられます。これは、コールバックに切り替えられる順序と同じです。

再生用のオーディオキュー

再生されたオーディオキュー、使用済みAudioQueueNewOutput関数は次の構造で作成されます。

再生オーディオキューでは、コールバックは入力側にあります。コールバックは、ディスク(またはその他のソース)からオーディオデータを取得し、それをオーディオキューに渡す役割を果たします。再生するデータがなくなると、再生コールバックはオーディオキューにも停止するように指示します。

オーディオキューバッファ

オーディオキューバッファはオーディオキューバッファですAudioQueueBuffer AudioQueue.hで宣言されたデータ構造のタイプに:

typedef struct AudioQueueBuffer { const UInt32 mAudioDataBytesCapacity void *const mAudioData UInt32 mAudioDataByteSize void *mUserData } AudioQueueBuffer typedef AudioQueueBuffer *AudioQueueBufferRef Copy code

上記の構造ではmAudioDataバッファ自体を指すフィールド:再生または記録されているオーディオデータの一時的なブロックのコンテナとして機能するメモリのブロック。他のフィールドは、オーディオキューがバッファを管理するのに役立ちます。

オーディオキューは、アプリケーションで指定された任意の数のバッファを使用できます。ただし、通常は3つと指定されています。これにより、一方がデータをディスクに書き込み、もう一方が新しいデータを入力できるようになります。ディスクI / Oレイテンシーなどを補正する必要がある場合は、3番目のバッファーを使用できます。

オーディオキューは、バッファのメモリ管理を提供します。

  • AudioQueueAllocateBuffer関数を呼び出すと、オーディオキューはバッファを割り当てます。
  • AudioQueue Dispose関数を呼び出してオーディオキューを解放すると、キューはそのバッファを解放します。

これにより、アプリケーションに追加された記録および再生機能の堅牢性が向上します。また、リソースの使用を最適化するのにも役立ちます。

バッファキューとエンキュー

録音プロセス

再生プロセス

再生プロセスを制御する

オーディオキューバッファは、常にキューに入れられた順序で再生されます。ただし、オーディオキューサービスはAudioQueueEnqueueBufferWithParametersを使用します。この関数を使用すると、再生プロセスをある程度制御できます。この機能により、次のことが可能になります。

  • バッファの正確な再生時間を設定します。これにより、同期をサポートできます。
  • オーディオキューバッファの最初または最後でフレームをトリミングします。これにより、先頭または末尾のミュートを削除できます。
  • バッファの粒度で再生ゲインを設定します

オーディオキューコールバック関数

一般に、オーディオキューサービスを使用するほとんどのプログラミング作業には、オーディオキューコールバック関数の記述が含まれます。

録音または再生中に、オーディオキューコールバックは、それを所有するオーディオキューによって繰り返し呼び出されます。呼び出し間の時間は、オーディオキューバッファの容量によって異なり、通常は0.5秒から数秒の範囲です。

録音または再生のいずれの場合でも、オーディオキューコールバックの役割の1つは、オーディオキューバッファをバッファキューに戻すことです。コールバックの使用AudioQueueEnqueueBufferこの関数は、バッファーキューの最後にバッファーを追加します。再生の場合、さらに制御が必要な場合は、再生の制御で説明されているように、代わりにAudioQueueEnqueueBufferWithParameters関数を使用できます。

オーディオキューを録音するためのコールバック機能

このセクションでは、オーディオをディスクファイルに録音する一般的なケースで書き込まれるコールバックについて説明します。これがAudioQueue.hヘッダーファイルで宣言された録音されたオーディオキューコールバックのプロトタイプです。

AudioQueueInputCallback ( void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, const AudioTimeStamp *inStartTime, UInt32 inNumberPacketDescriptions, const AudioStreamPacketDescription *inPacketDescs ) Copy code

録音オーディオキューは、コールバックが呼び出されたときにコールバックを提供します。次のオーディオデータセットのすべてのコンテンツをオーディオファイルに書き込む必要があります。

オーディオキューの再生機能

AudioQueueOutputCallback ( void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer ) Copy code

再生オーディオキューは、コールバックが呼び出されたときにコールバックを提供します。次のオーディオデータセットのコンテンツは、オーディオファイルから読み取る必要があります。

コーデックとオーディオデータ形式を使用する

オーディオキューサービスは、さまざまなオーディオ形式に従って使用する必要のあるコーデック(オーディオデータのエンコードとデコード)を変換できます。録音または再生アプリケーションは、インストールされているコーデックのオーディオ形式を使用でき、さまざまなオーディオ形式を処理するためにカスタムコードを作成する必要はありません。簡単に言えば、コールバックは特定のオーディオデータ形式を知る必要はありません。

下の写真はそれがどのように機能するかを示しています。各オーディオキューは1つのオーディオデータ形式に対応し、オーディオデータ形式が使用されます。AudioStreamBasicDescription説明。 mFormatIDフィールド設定に価値がある場合、オーディオキューは対応するコーデックを使用し、サンプルレートとそのチャンネル数を定義します。

上の図に示すように、最初のステップで、アプリケーションは使用するオーディオデータ形式をオーディオキューに通知し、録音を開始します。 2番目のステップでは、オーディオキューはコーデックを使用して新しいオーディオデータを取得し、指定した形式に従って変換します。次に、オーディオキューはコールバックを呼び出して、適切に形成されたオーディオデータを含むバッファを処理します。 3番目の部分では、コールバックがフォーマットされたオーディオデータをディスクに書き込みます。繰り返しますが、コールバックはデータ形式を知る必要はありません。

次の図は、オーディオ再生の再生方法を示しています。

  • 最初のステップで、アプリケーションはオーディオキューに再生するオーディオデータの形式を指示し、再生を開始します。
  • 2番目のステップでは、オーディオキューがコールバックを呼び出して、オーディオファイルからデータを読み取ります。コールバックは、データを元の形式でオーディオキューに渡します。
  • 3番目のステップでは、オーディオキューは適切なコーデックを使用してから、オーディオを宛先に送信します。

オーディオキューは、Mac OS Xにネイティブであるか、サードパーティによって提供されているかに関係なく、インストールされているコーデックを使用できます。

オーディオキューの制御とステータス

オーディオキューには、作成から処理までのライフサイクルがあります。アプリケーションはこのライフサイクルを管理し、AudioQueue.hヘッダーファイルで宣言されている6つの関数を使用して、オーディオキューの状態を制御します。

  • 開始(AudioQueueStart) 。呼び出して録音または再生を開始します。
  • プライム(AudioQueuePrime) 。再生の場合は、AudioQueueStartを呼び出す前に呼び出して、オーディオキューですぐに再生できるデータがあることを確認します。この機能は録音には関係ありません。
  • 停止(AudioQueueStop) .Callを呼び出して、オーディオキューをリセットし(AudioQueueResetについては、以下の説明を参照)、録音または再生を停止します。再生するデータがなくなると、再生オーディオキューコールバックがこの関数を呼び出します。
  • 一時停止(AudioQueuePause) バッファに影響を与えたり、オーディオキューをリセットしたりせずに、録音または再生を一時停止するために呼び出します。再開するには、AudioQueueStart関数を呼び出します。
  • フラッシュ(AudioQueueFlush) 。最後のオーディオキューバッファをエンキューした後に呼び出して、バッファリングされたすべてのデータ、および処理中のすべてのオーディオデータが記録または再生されるようにします。
  • リセット(AudioQueueReset) .Callを呼び出して、オーディオキューをすぐに無音にし、以前にスケジュールされた使用からすべてのバッファを削除し、すべてのデコーダとDSPの状態をリセットします。

AudioQueueStopを使用できます。関数は同期モードまたは非同期モードです。

  • 同期 以前にバッファリングされたオーディオデータに関係なく、停止はすぐに行われます。
  • 非同期 停止は、キューに入れられたすべてのバッファが再生または記録された後に発生します。

録音

オーディオキューを使用する際に注意すべき問題

ここに私の使用法をリストします。Audio Queueその間に発生した問題、および注意が必要な問題。

オーディオバッファキューに長い間オーディオデータがない場合、再生コールバックは終了します。

use Audio Queueオーディオの再生とは、オーディオキューに長期間データがない場合、再生コールバックが自動的に停止することです。したがって、空のオーディオデータをオーディオキューにコピーした場合でも、再生の自動コールバックを回避できます。

サンプルコードは次のとおりです。

void AudioPlayer::handleTVUWebRTCAudioOutputBuffer(void * aqData,AudioQueueRef inAQ , AudioQueueBufferRef inBuffer) { TVUWebRTCManager *webRTCManager = [TVUWebRTCManager shareInstance] if (!webRTCManager) { return } if (webRTCManager.isEndupCall) { NSLog(@'isEndupCall is YES...') }else{ NSLog(@'isEndupCall is NO...') } RTCPeerConnection *rtcPeerConn = [webRTCManager getNewestPeerConnection] if (rtcPeerConn == NULL || rtcPeerConn == nil) { // [mLock unlock] return } Int8_t * source = [rtcPeerConn getPlayoutAudioBuffer] // Copy empty audio data to the buffer queue if (source == NULL || source == nil) { inBuffer->mAudioDataByteSize = kTVUWebRTCAudioDataByteSize memset(inBuffer->mAudioData,0,kTVUWebRTCAudioDataByteSize) AudioQueueEnqueueBuffer(inAQ,inBuffer,0,NULL) // [mLock unlock] return } inBuffer->mAudioDataByteSize = kTVUWebRTCAudioDataByteSize if ([rtcPeerConn isWebRTCPlayoutActived] || [rtcPeerConn isWebRTCAudioFrameAvailable]) { memset(inBuffer->mAudioData,0,kTVUWebRTCAudioDataByteSize) AudioQueueEnqueueBuffer(inAQ,inBuffer,0,NULL) // [mLock unlock] return } // demon add , caculate volume db caculateVolumeDB(inBuffer, 0, k_Mono) memcpy(inBuffer->mAudioData, source, kTVUWebRTCAudioDataByteSize) AudioQueueEnqueueBuffer(inAQ,inBuffer,0,NULL) // [mLock unlock] return } Copy code

AudioQueueのいくつかのメソッド

AudioQueueStop

機能:オーディオの再生または録音を停止します

説明:オーディオキューが別のオーディオサービスによって使用されていない場合、この機能はオーディオキューをリセットし、キューに関連付けられているオーディオハードウェアを停止します。同期停止は、オーディオキューにオーディオコンテンツがあるかどうかに関係なく、すぐに再生または録音されます。非同期停止は、オーディオキューのオーディオデータが再生されるまで、再生または録音を停止しません。

パラメータ:

inAQ :停止するオーディオキュー

inImmediate値がyesの場合、値がNOの場合、同期はすぐに停止し、非同期で停止し、オーディオキューのコンテンツが再生されるか録音が完了するまで待機します。

注意:

  • このメソッドは、オーディオキューでオーディオデータが再生されていないときに自動的に呼び出されます。
  • オーディオキューがすぐに停止すると、通常、保留中のすべてのバッファコールバックが停止中に呼び出されます。ただし、呼び出し元のスレッドがバッファーコールバックに応答する場合、AudioQueueStopが戻った後に追加のバッファーコールバックが発生する可能性があります。

メソッドのプロトタイプ:

extern OSStatus AudioQueueStop( AudioQueueRef inAQ, Boolean inImmediate) __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0) Copy code

AudioQueuePause

機能:オーディオの再生または録音を一時停止します

説明:一時停止キューは、バッファに影響を与えたり、オーディオキューを再充電したりすることはありません。オーディオキューを使用して再生または録音を再開するには、AudioQueueStartを呼び出します

メソッドのプロトタイプ:

extern OSStatus AudioQueuePause( AudioQueueRef inAQ) __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0) Copy code

AudioQueueFlush

機能:オーディオキューのデコーダーステータスをリセットします

説明:この関数は、すべてのオーディオキューが再生された後、すべてのデコーダーステータス情報をクリアします。この関数は、エンコードされたオーディオと同じバッファシーケンスで呼び出す必要があります。そうしないと、キューに入れられた次のバッファセットで一部のオーディオが再生されない場合があります。 AudioQueueFlushを呼び出す必要がないのは、inImmediate = falseでAudioQueueStopを使用する場合のみです。 (この操作は内部でAudioQueueFlushを呼び出します。)

さらに、AudioQueueStopを呼び出す前にこの関数を呼び出すこともできます。これは、すぐに停止するか、再生するか、またはバッファリングされたすべてのデータとプロセスの途中のすべてのデータを確実に停止または再生するかどうかによって異なります。 。

関数プロトタイプ:

extern OSStatus AudioQueueFlush( AudioQueueRef inAQ) __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0) Copy code

AudioQueueReset

機能:オーディオキューをリセットする

説明:この関数は、オーディオキューを即座にリセットし、オーディオキューのバッファーをフラッシュし、以前にスケジュールされた使用からすべてのバッファーを削除し、デコーダーとデジタルシグナルプロセッシング(DSP)のステータス情報をリセットします。

注:リセットプロセス中に、保留中のすべてのバッファーコールバックが通常呼び出されますが、呼び出し元のスレッドがバッファーコールバックに応答する場合、AudioQueueResetが戻った後に追加のバッファーコールバックが発生する可能性があります。

関数プロトタイプ:

extern OSStatus AudioQueueReset( AudioQueueRef inAQ) __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0)Copy code

転載:https://juejin.im/post/5cdb8a88518825123570f4f3