1

を使用して読み取ったオーディオ データを処理しようとしていますExtAudioFile。ただし、このデータを循環バッファーに入れようとすると、いくつかの不具合が聞こえます。

以下のコード例では、データを「inBuffer」から直接「outBuffer」に渡します (どちらもTPCircularBufferMichael Tyson によるタイプです)。両方のバッファーのサイズは 10 xnumberOfFrames * sizeof(float)です。クライアント ストリーム フォーマットは、フロート サンプルを使用したモノラルです。

データを処理しなくても、これらの不具合が聞こえるのはなぜですか? 循環バッファーがなければ、サウンドは適切にストリーミングされます。私は何を間違っていますか、それとも別のアプローチがより良いでしょうか?

static OSStatus recordingCallback(
                                  void*                       inRefCon,
                                  AudioUnitRenderActionFlags* ioActionFlags,
                                  const AudioTimeStamp*       inTimeStamp,
                                  UInt32                      inBusNumber,
                                  UInt32                      inNumberFrames,
                                  AudioBufferList*            ioData){
    PlayAudioFile* player = (__bridge PlayAudioFile*)inRefCon;
    Info *info = (Info *)player.info;


    ExtAudioFileRead(info->extAudioFile, &inNumberFrames, info->inputBuffer);

    if (inNumberFrames == 0) {
        ExtAudioFileSeek(info->extAudioFile, 0);
    }

    // Put data in circular buffer
     TPCircularBufferProduceBytes(info->inBuffer, info->inputBuffer->mBuffers[0].mData, info->inputBuffer->mBuffers[0].mDataByteSize);


    UInt32 frameSize = inNumberFrames*sizeof(float);
    if (info->inBuffer->fillCount >= frameSize) {
        int32_t availableBytes;

        float *tail = TPCircularBufferTail(info->inBuffer, &availableBytes);
        if (availableBytes > frameSize){
            memcpy(info->tempBuffer, tail, frameSize);
            TPCircularBufferConsume(info->inBuffer, frameSize);

            // Currently, data is not processed but just put to the output buffer

            TPCircularBufferProduceBytes(info->outBuffer, info->tempBuffer, frameSize);
        }
    }

    return noErr;
}



static OSStatus renderCallback(
                               void*                       inRefCon,
                               AudioUnitRenderActionFlags* ioActionFlags,
                               const AudioTimeStamp*       inTimeStamp,
                               UInt32                      inBusNumber,
                               UInt32                      inNumberFrames,
                               AudioBufferList*            ioData){
    PlayAudioFile* player = (__bridge PlayAudioFile*)inRefCon;
    Info *info = (Info *)play.info;

    for (int i=0; i < ioData->mNumberBuffers; i++) {
        AudioBuffer buffer = ioData->mBuffers[i];

        if (info->outBuffer->fillCount > ioData->mBuffers[0].mDataByteSize) {

            int32_t availableBytes;
            float *tail = TPCircularBufferTail(info->outBuffer, &availableBytes);

            memcpy(buffer.mData, tail, buffer.mDataByteSize);
            TPCircularBufferConsume(info->outBuffer, buffer.mDataByteSize);

   /* Messaging is not used for this example
            // Notify delegate
            if ([player.delegate respondsToSelector:@selector(player:audioBuffer:bufferSize:)])
            {
                [player.delegate player:player
                            audioBuffer:buffer.mData
                             bufferSize:inNumberFrames];
            }
    */
        }
        else {
            memset((char*)ioData->mBuffers[i].mData, 0, ioData->mBuffers[i].mDataByteSize  * info->clientFormat.mBytesPerFrame);

        }
    }
    return noErr;
}

編集 以下の回答に基づいて、コールバック関数の外部でメモリを割り当てて解放し、循環バッファのサイズを大きくしてコードを修正しました。残念ながら、サウンドは循環バッファーがない場合よりもさらに悪くなります。これらの不具合には別の理由があるのでしょうか?

4

1 に答える 1

0

オーディオ コールバック内でメモリの割り当てまたは解放を行うべきではありません。また、Objective C メッセージを送信する必要もありません。

レンダー コールバックは、常にデータをバッファー リスト バッファーに入れる必要があります。しかし、あなたのコードにはそうするためのelseステートメントがありません。レンダー コールバックを開始する前に、より大きな循環バッファーを試して、十分に事前に入力されていることを確認してください。

于 2016-03-01T15:34:06.153 に答える