2017-08-24 69 views
1

我目前正在嘗試使用SDL錄製音頻並對其進行處理,但我在運行時遇到了一些麻煩,無法獲取處理步驟所需的16位PCM音頻。我運行的設備僅支持AUDIO_F32格式。所以我的AudioSpec如下;將Uint8(浮點AUDIO_F32)轉換爲int16_t(16位PCM)

SDL_AudioSpec wanted; 
SDL_zero(wanted); 

wanted.freq = 48000; 
wanted.format = AUDIO_F32SYS; 
wanted.channels = 1; 
wanted.samples = 4096; 
wanted.callback = NULL; 

現在我不得不跟隨包含錄製音頻的緩衝區;

std::vector<Uint8> buffered; 

我該如何去將Uint8轉換爲16位PCM格式?如果我是正確的,Uint8應該是定義爲unsigned char的32位浮點音頻。我已經嘗試了下面的代碼,但它似乎沒有給出正確的結果;

std::vector<int16_t> pcm_buffer; 
for(const Uint8& sample : buffered) 
{ 
    float sampleFloat = (float) sample; 
    sampleFloat *= 32767; 

    int16_t sampleInt = (int16_t) sampleFloat; 
    pcm_buffer.push_back(sampleInt); 
} 

我有一種感覺,我完全誤會我在做什麼,所以我希望有人能指出我在正確的方向。

+0

這是真正的代碼?我有一個預感,Uint應該是'Uint8'。如果你用手工輸入:請考慮複製+粘貼。 –

+0

我不得不編輯部分代碼,因爲我正在做很多試驗,而且我的代碼很亂,但它確實應該是Uint8。 – Thys

回答

1

F32格式是4字節的浮點數,但是你有緩衝區作爲字節緩衝區。您錯過了將字節轉換爲浮動的步驟。這是錯誤的行:

float sampleFloat = (float) sample 

轉換應該對4字節塊,而不是單個字節進行操作。比較:

std::vector<Uint8> buffered = ...; 
std::vector<int16_t> pcm_buffer; 
assert(buffered.size() % 4 == 0); 
for(for size_t i = 0; i < buffered.size(); i += 4) 
{ 
    float sampleFloat = *(float*)(buffered.data() + i); 
    sampleFloat *= 32767; 

    int16_t sampleInt = (int16_t) sampleFloat; 
    pcm_buffer.push_back(sampleInt); 
} 

我認爲這也是合理的assert(buffered.data() % 4 == 0)以及由於對齊和走樣規則。

您還可以投本身的循環和彩車的迭代陣列之外,像

std::vector<Uint8> buffered = ...; 
const float* p = (const float*)buffered.data(); 
const float* pe = p + buffered.size()/4; 
for (; p < pe; ++p) { 
    int16_t sampleInt = *p * 32767; 
} 
+0

非常感謝,現在我覺得有點愚蠢>。<問題;爲什麼在第二種方法中,你乘以32765而不是32767? – Thys

+0

你的第二個建議也給了我下面的錯誤; '不能從類型'iterator'(aka'__wrap_iter ')轉換爲指針類型'const float *'' – Thys

+0

我修正了代碼,end()方法被錯誤地使用了。 –