2016-03-01 63 views
1

我正在嘗試處理使用ExtAudioFile讀取的音頻數據。但是,當我嘗試將這些數據放入循環緩衝區時,我聽到幾個故障。當使用ExtAudioFile和循環緩衝區讀取數據時出現毛刺

在下面的示例代碼中,我將數據從「inBuffer」直接傳遞給「outBuffer」(Michael Tyson的TPCircularBuffer類型)。兩個緩衝區的大小都是10 x numberOfFrames * 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; 
} 

基於下面我通過分配和回調函數外釋放內存,並通過增加循環緩衝器的大小修改代碼中的答案編輯 。不幸的是,聲音比沒有循環緩衝區的情況下還要糟糕。這些毛刺會有其他原因嗎?

回答

0

分配或釋放內存不應在音頻回調中完成。也不應該發送Objective C消息。

渲染回調應始終將數據放入緩衝區列表緩衝區。但是你的代碼缺少一個else語句來這麼做。嘗試更大的循環緩衝區,並確保在開始渲染回調之前充分預先填充。

+0

我通過在回調函數之外分配和釋​​放內存來修改代碼(請參閱更新後的問題)並增加緩衝區大小。然而,聲音只是略有改善(但可能是主觀的)。關於Objective-C消息,是否有另一種方式通知代表新的音頻? – Gerard

+0

At已經有一段時間了,但似乎分配內存和objective-c消息確實是潛在的故障(不幸的是,我的代碼中仍然有一些Objective-C消息)。你的回答對我很有價值! – Gerard