AudioQueueInput に重大な問題がありました。すべての Audio Queue Buffer を 512 サンプル (44.1kHz サンプリング レート) のサイズで割り当てます。私のコールバック関数は次のように書かれています:
void MyAudioQueueInputCallback (
void *inUserData,
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer,
const AudioTimeStamp *inStartTime,
UInt32 inNumberPacketDescriptions,
const AudioStreamPacketDescription *inPacketDescs
)
{
ANSampleInput *input = (__bridge ANSampleInput *)inUserData;
Float32 * samples = (Float32 *)inBuffer->mAudioData;
Float32 * data = malloc(input.framesPerBuffer * sizeof(Float32 *));
memcpy(data, samples, input.framesPerBuffer * input->audioFormat.mBytesPerFrame );
AudioQueueEnqueueBuffer(input->audioQueue, inBuffer, 0, NULL);
for (int i = 0; i < 512; i ++) {
printf("%f",data[i]);
}
}
このコードはテスト目的で作成されているため、他のメソッドは追加していません。しかし、この単純なコードだけで問題が発生します。
ボタンを押して録音を開始すると、データ配列に生の PCM 値が入力されます。しかし、数秒後にデータはすべてゼロになりました。
この問題は、最初に iPod touch 4 でプロジェクトをテストするときに発生します。その前に、iPhone シミュレーターですべてが機能しています (データはゼロではありません) (非常に低いレイテンシー)。おそらく、iPod touch 4 の CPU は、非常に低遅延のコールバックを処理するには十分に強力ではないのではないかと考えました。しかし、今では何の理由もなく、私のiPhoneシミュレーターにも同じ問題があります(デバッガーにポップアップする情報によると、レイテンシーも高いです)。
コードを確認しましたが、多くのサンプル コードと同じだと思います。シミュレーターも機能しないので、今は本当に混乱しています。
AudioQueueInput の初期化コードは次のとおりです。
- (id)initWithSampleRate:(NSUInteger)rate bufferSampleCount:(NSUInteger)sampleNumber
{
if ((self = [super init])) {
self.sampleRate = rate;
audioFormat.mFormatID = kAudioFormatLinearPCM;
audioFormat.mChannelsPerFrame = 1;
audioFormat.mBitsPerChannel = 8 * sizeof(Float32);
audioFormat.mFramesPerPacket = 1;
audioFormat.mSampleRate = rate;
audioFormat.mBytesPerFrame = sizeof(Float32);
audioFormat.mBytesPerPacket = sizeof(Float32);
audioFormat.mFormatFlags = kAudioFormatFlagIsNonInterleaved | kAudioFormatFlagIsPacked | kAudioFormatFlagIsFloat;
OSStatus status = AudioQueueNewInput(&audioFormat, MyAudioQueueInputCallback,
(void *)CFBridgingRetain(self), CFRunLoopGetCurrent(),
kCFRunLoopDefaultMode, 0, &audioQueue);
if (status != noErr) {
return nil;
}
self.framesPerBuffer = sampleNumber;
for (int i = 0; i < kBufferCount; i++) {
status = AudioQueueAllocateBuffer(audioQueue, sizeof(Float32) * self.framesPerBuffer, &buffers[i]);
if (status != noErr) {
for (int j = i - 1; j >= 0; j--) {
AudioQueueFreeBuffer(audioQueue, buffers[j]);
}
AudioQueueDispose(audioQueue, NO);
return nil;
}
AudioQueueEnqueueBuffer(audioQueue, buffers[i], 0, NULL);
}
}
return self;
}
誰か助けてください!
編集:
偶然にも、for ループを削除してサンプル配列のすべての値を出力すると、サンプル配列に何らかのプロセスがあったとしても正常に動作しました。printf は FFT アルゴリズムよりも時間がかかるはずがないため、奇妙です。とにかく、それは今動作します。