現在、iOS で Audio Queue Services を使用する方法を学んでいます。このために、Audio Queue Services Programming Guide - Recording Audioに従いました。これは機能します。
コールバック関数がマイクから入力データを受け取ったときに、UI 要素 (パワー メーター) を更新したいと思います。ここで問題が発生します。
パワーメーターを更新するためにコールバック関数からビュー/ビューコントローラーに呼び出す良い方法がわかりません。私はこれを試しました:ガイドで説明されているstate を管理するカスタム構造体に、ビュー コントローラーへのポインターを追加しました。
struct AQRecorderState {
AudioStreamBasicDescription mDataFormat; // 2
AudioQueueRef mQueue; // 3
AudioQueueBufferRef mBuffers[kNumberBuffers]; // 4
AudioFileID mAudioFile; // 5
UInt32 bufferByteSize; // 6
SInt64 mCurrentPacket; // 7
bool mIsRunning; // 8
void* mViewController; // <- I've added this line
};
記録を開始するときに、このポインターを初期化します。これは、スタート ボタンが TouchUp イベントを受け取ったときに呼び出されるビュー コントローラーのメソッドで行われます。
- (IBAction)startAudioRecording:(id)sender {
struct AQRecorderState* aqData = createAQRecorderState();
void* pViewControllerAsVoidPointer = (__bridge void*) self;
aqData->mViewController = pViewControllerAsVoidPointer;
//...
構造体を割り当てる createAQRecorderState() メソッドは次のようになります。
struct AQRecorderState* createAQRecorderState() {
struct AQRecorderState* pAqData = (struct AQRecorderState*) malloc(sizeof(AQRecorderState));
initializeAQRecorderState(*pAqData); // sets members of the struct; does not set pointer to view controller
return pAqData;
}
私の知る限り、記録を開始するときに作成した構造体のインスタンスそのものが、コールバック関数への後の呼び出しに配信されます。このため、ビュー コントローラーを呼び出すために、次のコードをコールバック関数に追加しました。
void HandleInputBuffer(
void *aqData,
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer,
const AudioTimeStamp *inStartTime,
UInt32 inNumPackets,
const AudioStreamPacketDescription *inPacketDesc
) {
//...
NSLog(@"interesting part start");
void* pViewControllerAsVoidPtr = pAqData->mViewController;
NSLog(@"localized pointer to void");
ViewController* pViewController = (__bridge ViewController*) pViewControllerAsVoidPtr; //EXC_BAD_ACCESS
NSLog(@"localized pointer to ViewController");
//...
}
ただし、ブリッジされたポインター変換を行うと、上記のマークされた行のコールバック関数で EXC_BAD_ACCESS (コード = 1、アドレス = 0xffffffff) を取得します。次に、これをデバッガーで確認しましたが、実際にはメソッドの実行中に保存したアドレスを保持してpViewControllerAsVoidPtr
いません。pAqData->mViewController
startAudioRecording:
そのポインターが変更されるのはなぜですか? または、代わりに: UI を更新するためにコールバック関数からビュー コントローラーに正しく呼び出す方法は?