2016-04-14 24 views
1

我有一個關於什麼我認爲歸結爲C語法和內存考慮的問題。我在處理一些音頻的Objective-C類中有一個回調,其中一個參數是bufferListInOut。它代表我想轉換爲立體聲的單聲道音頻信號。這裏是我的代碼:在一個結構中擴展一個數組C

static void tap_ProcessCallback(MTAudioProcessingTapRef tap, 
          CMItemCount numberFrames, 
          MTAudioProcessingTapFlags flags, 
          AudioBufferList *bufferListInOut, 
          CMItemCount *numberFramesOut, 
          MTAudioProcessingTapFlags *flagsOut){ 

    // Retrieve mono audio data into bufferListInOut 
    MTAudioProcessingTapGetSourceAudio(tap, numberFrames, bufferListInOut, NULL, NULL, NULL); 

    // Copy the mono channel's data 
    float *channelLeft = malloc(numberFrames * sizeof(float)); 
    channelLeft = bufferListInOut->mBuffers[0].mData; 

    // Attempt to create a second channel which is (currently) a copy of the first 
    bufferListInOut->mNumberBuffers = 2; // 2 for stereo, 1 for mono 
    bufferListInOut->mBuffers[1].mNumberChannels = 1; 
    bufferListInOut->mBuffers[1].mDataByteSize = numberFrames * sizeof(Float32); 
    bufferListInOut->mBuffers[1].mData = channelLeft; 

    // Set number of frames out 
    *numberFramesOut = numberFrames; 
} 

一些注意事項:

  • 在這段代碼中,新的渠道僅僅是一個副本原件,但在實踐中,將進行一些處理。
  • 的命名是有點不可思議,但確實mNumberBuffers,就是要2 mNumberChannels意味着是1

這崩潰與渲染的EXC_BAD_ACCESS錯誤線向下行。所以,我的問題是什麼是正確的方式來添加一個新的緩衝區結構?我不經常鑽研C,所以我確信我在這裏錯過了一些基礎知識。任何指針都會很棒。謝謝閱讀。

+0

你的問題是?這篇文章中沒有一個。 – Sanuuu

+1

這是複雜的東西,但是馬上就要分配內存並將其分配給'channelLeft',然後立即重新分配'channelLeft',從而泄漏內存。我想你想'memcpy(channelLeft,bufferListInOut-> mBuffers [0] .mData,numberFrames * sizeof(float));'。 – trojanfoe

+0

@Sanuuu感謝您的評論。我剛纔澄清了這個問題。 – Rogare

回答

3

你不能做你正在嘗試的事情,至少在你試圖做到這一點。類型AudioBufferList被聲明爲:

struct AudioBufferList { UInt32 mNumberBuffers; AudioBuffer mBuffers[1]; }; 

。這是一個可變大小結構一個經典的C圖案。爲N創建一個struct緩衝存儲器的單個塊與大小分配:

sizeof(UInt32) + N * sizeof(AudioBuffer) 

該塊的地址被分配給一個變量AudioBufferList *和場mNumberBuffers設置爲N。你不可能不能簡單地增加mNumberBuffers增加數組的大小,而是你必須分配一個新的完整的結構,或者現有的realloc增加內存塊的大小,如果可能的話或分配一個新的,並複製現有的數據進入它,如果沒有。

鑑於你的tap_ProcessCallback()函數傳遞了一個AudioBuuferList *值並且不返回一個,所以它不可能改變它傳遞的結構體的大小(即緩衝區的數量)。

正如評論中指出的那樣,當您打算複製內存時,您也正在做指針分配 - 請參閱memcpy和朋友。

所以你需要重新設計 - 你的目標是可能的,而不是你如何和在哪裏嘗試它。

HTH

+0

您好@CRD,感謝您的解釋,非常有幫助!只是爲了確保我遵循,當你說「沒有辦法[tap_ProcessCallback()]可以改變結構的大小......需要重新設計」你是說用函數參數,因爲它們是(我們不幸無法控制),不可能改變緩衝區的數量? – Rogare

+1

正確。該函數正在傳遞調用者'AudioBufferList'的地址。正如所寫,它無法將此地址的調用者值更改爲新的擴大結構的值。 – CRD

+0

如果將函數參數更改爲「AudioBufferList ** bufferListInOut」(當然,更新代碼內部以及函數調用的任何位置),則可以更改調用者值。那麼...我仍然有-50錯誤(kAudio_ParamError)。 – tontonCD

相關問題