我目前正在尝试录制音频并使用SDL处理它,但我遇到了处理步骤所需的16位PCM音频的麻烦。我运行的设备仅支持AUDIO_F32格式。所以我的AudioSpec如下;
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
应该是32位浮点音频定义为unsigned char
。我已经尝试了下面的代码,但似乎没有给出正确的结果;
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 :(得分: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;
}