私はiPhone用のVOIPベースのアプリを書いています。ユーザーが画面を押したときに音声に不具合が発生するという奇妙な問題が発生しています。これは、電話自体の音量アップ/ダウンボタンを押したときにも発生します。数日間のデバッグの後、循環バッファと関係があることがわかりました。私はここのものと私のものを交換しました:
http://atastypixel.com/blog/a-simple-fast-circular-buffer-implementation-for-audio-processing/
これはグリッチを引き起こしませんが、レイテンシーは私のもののほぼ4倍長いので、レイテンシーを最小限に抑える必要があり、アプリで何が起こっているのか理解できません。
設定:
http://www.stefanpopp.de/2011/capture-iphone-microphone/基本的なアプリを作成するためにいくらかフォローしましたが、設定や機能などが異なります。このaudioProcessorクラスのプロパティを持つViewControllerがあります。このクラスには、循環バッファー用の変数があります。記録コールバックでデータを送信しますが、これはすべて問題ありません。CFSocketコールバックでは、ネットワークからこのバッファーにデータを追加し、次に再生コールバックがこのバッファーからデータをプルしてシステムに渡します。
再生中のある時点で、ユーザーがUIイベントをトリガーすると、すべてが地獄に落ち、この奇妙なデータが表示されます。ある種のスレッドの問題を推測していますが、この分野での経験はほとんどまたはまったくありません。助けていただければ幸いです。相対コードは次のとおりです。
ネットワークコールバック-バッファへのデータの追加:
static void addDataToBuffer(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *info)
{
AudioUnitCBufferProduce(&audioProcessor->auCBuffer, (uint8_t*)[(__bridge NSData *)data bytes], [(__bridge NSData *)data length]);
}
Audio Unitの再生-バッファからデータをコピーし、ioDataを指す「targetBuffer」に配置します。
static OSStatus playbackCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
uint8_t *targetBuffer = (uint8_t*)ioData->mBuffers[0].mData;
AudioUnitCBufferConsume(&audioProcessor->auCBuffer, targetBuffer, inNumberFrames);
return noErr;
}
バッファ初期化:
void AudioUnitCBufferInit(AudioUnitCBuffer *b)
{
// create array of bytes of length specified, fill with silence
uint8_t buffer[2048];
for(int i = 0; i < 2048; i++)
{
buffer[i] = 0xd5;
}
// init buffer elements
b->buffer = buffer;
b->consumer = buffer;
b->producer = buffer;
b->length = 2048;
}
バッファープロデューサー/コンシューマー:
これは、関数へのポインターを渡してから、このポインターにデータが入力されるように記述されています。データがない場合、ポインターには無音のALAW16進値が入力されます。これにより、オーディオユニットのコードが小さく保たれます。これは、バッファが常にデータを提供することを保証するためです。これはまた、一時的な場所にコピーしてから、上記のリンクが使用するバッファにそれをmemcpyするよりも高速であり、私のニーズにははるかに遅くなります。
inline static void AudioUnitCBufferProduce(AudioUnitCBuffer *b, uint8_t *bytes, int32_t len)
{
//printf("\n\ninside producer: len %i \n\n", len);
while(len--)
{
// if producer catches up with consumer, skip a byte
if (b->producer+1 == b->consumer)
{
//printf("b->producer+1 == b->consumer == continue \n");
continue;
}
else
{
//printf("b->producer+1 != b->consumer == add byte \n");
*b->producer = *bytes++;
b->producer++;
if(b->producer == &b->buffer[b->length-1])
{
//printf("\n\nproducer == end, skipping \n\n");
b->producer = b->buffer;
}
}
}
}
inline static void AudioUnitCBufferConsume(AudioUnitCBuffer *b, uint8_t *bytes, int32_t len)
{
while(len--)
{
// if producer catches up with consumer, skip a byte
if (b->consumer == b->producer)
{
*bytes++ = 0xd5;
}
else
{
*bytes++ = *b->consumer;
b->consumer++;
if(b->consumer == &b->buffer[b->length-1])
{
b->consumer = b->buffer;
}
}
}
}