2011-04-05 65 views
2

對於C開發人員來說,可能是一個非常簡單的問題,但是我對C很陌生,我並沒有完全掌握它背後的所有概念。所以,現在,我使用此代碼來連接2個緩衝器(audioData和silenceData),然後用它們來流一些音頻:C中的緩衝區(無符號字符*)連接

typedef struct { 
    unsigned char * data; 
    UInt32 size;  
} SoundData; 

    SoundData audioData; 
      audioData.data = audioFiles[currentSoundDataIndex]; 
      audioData.size = audioFilesSize[currentSoundDataIndex]; 

    SoundData silenceData; 
       silenceData.size = 44100*2*fabs(silenceDuration-0.049f); 
       silenceData.data = malloc(silenceData.size);   
       memset(silenceData.data,0,silenceData.size); 

       //beat data 
    SoundData beatData; 
       beatData.size = (audioData.size + silenceData.size);  
       beatData.data = malloc(beatData.size); 

       for (int i=0; i<audioData.size; i++) { 
        beatData.data[i] = audioData.data[i]; 
       } 

       for (int i=audioData.size; i<beatData.size; i++) { 
        beatData.data[i] = silenceData.data[i-audioData.size]; 
       } 

這工作得很好,但我有一種感覺,必須有一個更好的辦法做到這一點,一些內置的功能可能?

+0

嘛'memcpy'很可能是有用的。 – Erik 2011-04-05 19:49:07

+0

奇怪的是,因爲我嘗試過,它失敗了(聲音完全改變!),也許我沒有正確使用,雖然它非常簡單,但會再次嘗試... – 2011-04-05 19:50:58

+0

爲什麼選擇C++標記? C++解決方案會有所不同。 – Cubbi 2011-04-05 19:55:15

回答

2

我肯定會使用memcpy() ...它要快得多,因爲該標準庫函數使用編譯器內在或手動編碼的彙編,以字節爲單位的一個緩衝的複製大大加快到另一個緩衝區以至於它可以針對您的處理器平臺進行優化。這比for循環快多了......

因此,例如:

unsigned char* temp_buffer_loc = beatData.data; 
memcpy(temp_buffer_loc, audioData.data, audioData.size); 

//now put silence data at the end of the buffer 
temp_buffer_loc += audioData.size; 
memset(temp_buffer_loc, 0, silenceData.size); 
+0

這個工作就像一個魅力(雖然我相信任何上述解決方案會有),但我最喜歡它,因爲它使用已知數量的字節上的memset,而不是malloc - 沉默緩衝區,這使得代碼看起來更好(少代碼),也可能是優化(?) – 2011-04-05 20:21:54

+0

那麼,主要的優化是這些標準庫的內存函數通常使用匯編來完成繁重的工作。對於for循環(包括用於循環測試的代碼分支),需要大量的彙編代碼行可快速彙總爲大約三個或四個命令,以設置源地址,目標地址,複製次數,和/或用什麼來填充緩衝區。因此,對於簡單的內存複製功能,您會丟失大量的速度手動編碼循環。循環可以進行優化,但它們不會像特定命令那樣快。 – Jason 2011-04-05 20:40:02

+0

順便說一句,是的,不必分配,然後將零緩衝區從'silentData.data'複製到'beatData.data'將節省一些CPU週期 – Jason 2011-04-06 04:14:18

3

這一次,而不是使用循環,您可以使用memcpy,這是更快,即:

memcpy(beatData.data, audioData.data, audioData.size); 
+1

我會使用'memmove()';它始終有效。在這種情況下使用'memcpy()'是安全的,但由於它並不總是有效,所以我更喜歡使用'memmove()'更安全。因人而異。 – 2011-04-05 19:54:08

+0

感謝您的建議。 – MByD 2011-04-05 19:55:13

+0

好吧,試試吧,不過,我之前嘗試過,聲音改變了,可能我沒有使用它,因爲它應該會再試一次並更新問題! – 2011-04-05 19:55:51

2

這將是有意義與memcpy以取代那些for循環。否則沒關係。

memcpy(beatData.data, audioData.data, audioData.size); 
memcpy(beatData.data + audioData.size, silenceData.data, silenceData.size); 

實際上,您創建的靜音數據只是一堆零。它應該真正被存儲以便稍後被附加到另一個緩衝區。所以第二個memcpy應替換爲memset

memcpy(beatData.data, audioData.data, audioData.size); 
memcpy(beatData.data + audioData.size, 0, beatData.size - audioData.size);