2017-08-24 34 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 

変換は1バイトではなく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

大変ありがとうございます、今私はちょっと気が気になりません。なぜ2番目の方法で32765ではなく32767を掛けているのですか? – Thys

+0

あなたの2番目の提案はまた私に次のエラーを与えます。 '( '__wrap_iter ')をポインタ型 'const float *'にキャストできません。 – Thys

+0

コードを修正しましたが、end()メソッドが正しく使用されませんでした。 –

関連する問題