私はAudioQueueServices APIを使用して、iPhoneのTCPソケット接続を介してサーバーからストリーミングされたオーディオを再生しています。ソケット接続から満たされたバッファーを再生できますが、AudioQueueにAudioQueueOutputCallback関数を呼び出させることができないようで、アイデアがありません。
ハイレベルなデザイン
- データはソケット接続からプレーヤーに渡され、メモリ内の循環バッファにすぐに書き込まれます。
- AudioQueueBuffersが使用可能になると、データは循環バッファーから使用可能なAudioQueueBufferにコピーされ、すぐに再キューイングされます。(または、私のコールバックが発生した場合)
何が起こるのですか
バッファはすべて正常にいっぱいになり、キューに入れられ、オーディオストリームがはっきりと聞こえます。テストでは、多数のバッファー(15)を使用し、それらすべてがシームレスに再生されますが、AudioQueueOutputCallbackが呼び出されることはないため、すべてが完全に機能しているように見えても、これらのバッファーを再キューイングすることはありません。コールバックが呼び出されないことを前提として、コールバックを待たずに、書き込まれたデータに基づいてバッファーのエンキューを駆動すると、オーディオストリームを無期限に再生し、バッファーを再利用して再エンキューすることができます。コールバックによって明示的に返されていました。その事実です。必要に応じてバッファを再利用しながらストリームを完全に再生できるため、最も混乱します。コールバックが呼び出されないのはなぜですか?
おそらく関連するコード
ストリームのフォーマットは、16ビットリニアPCM、8 kHz、モノラルです。
_streamDescription.mSampleRate = 8000.0f;
_streamDescription.mFormatID = kAudioFormatLinearPCM;
_streamDescription.mBytesPerPacket = 2;
_streamDescription.mFramesPerPacket = 1;
_streamDescription.mBytesPerFrame = sizeof(AudioSampleType);
_streamDescription.mChannelsPerFrame = 1;
_streamDescription.mBitsPerChannel = 8 * sizeof(AudioSampleType)
_streamDescription.mReserved = 0;
_streamDescription.mFormatFlags = (kLinearPCMFormatFlagIsBigEndian |
kLinearPCMFormatFlagIsPacked);
私のプロトタイプとコールバックの実装は次のとおりです。派手なものはなく、これまでに見たすべての例とほとんど同じです。
// Prototype, declared above the class's @implementation
void AQBufferCallback(void* inUserData, AudioQueueRef inAudioQueue, AudioQueueBufferRef inAudioQueueBuffer);
// Definition at the bottom of the file.
void AQBufferCallback(void* inUserData, AudioQueueRef inAudioQueue, AudioQueueBufferRef inAudioQueueBuffer) {
printf("callback\n");
[(MyAudioPlayer *)inUserData audioQueue:inAudioQueue didAquireBufferForReuse:inAudioQueueBuffer];
}
次のようにAudioQueueを作成します。
OSStatus status = 0;
status = AudioQueueNewOutput(&_streamDescription,
AQBufferCallback, // <-- Doesn't work...
self,
CFRunLoopGetCurrent(),
kCFRunLoopCommonModes,
0,
&_audioQueue);
if (status) {
// This is not called...
NSLog(@"Error creating new audio output queue: %@", [MyAudioPlayer stringForOSStatus:status]);
return;
}
そして、私はこのようにバッファをエンキューします。この時点で、ローカルバッファにはコピー用の正しい量のデータが含まれていることがわかります。
memcpy(aqBuffer->mAudioData, localBuffer, kAQBufferSize);
aqBuffer->mAudioDataByteSize = kAQBufferSize;
OSStatus status = AudioQueueEnqueueBuffer(_audioQueue, aqBuffer, 0, NULL);
if (status) {
// This is also not called.
NSLog(@"Error enqueueing buffer %@", [MyAudioPlayer stringForOSStatus:status]);
}
私を救ってください。