c++ - WASAPI 环回 : Save wave file

标签 c++ wav file-format wasapi audioformat

我想使用 WASAPI 录制系统的音频输出,然后将其保存为 .wav 文件。

到目前为止,我在 WASAPI 上遵循了这些指南:

https://msdn.microsoft.com/en-us/library/windows/desktop/dd316551%28v=vs.85%29.aspx https://msdn.microsoft.com/en-us/library/windows/desktop/dd370800%28v=vs.85%29.aspx

我使用

获取缓冲区数据
audioCaptureClient->GetBuffer(&data, &numFramesAvailable, &flags, NULL, NULL);

然后,我正在处理这些数据,只需将其写入 .wav 文件的末尾即可:

size_t dataSize = format.nChannels * (format.wBitsPerSample / 8) * numFramesAvailable;
fwrite(data, dataSize, 1, fp);

format 是从 audioClient->GetMixFormat(&format) 接收的 WAVEFORMATEX:

cbSize:          22
nAvgBytesPerSec: 352800
nBlockAlign:     8
nChannels:       2
nSamplesPerSec:  44100
wBitsPerSample:  32
wFormatTag:      65534 (WAVE_FORMAT_EXTENSIBLE)

显然 WAVE_FORMAT_EXTENSIBLE 的子类型是 Float:

WAVEFORMATEXTENSIBLE *waveformatextensible = (WAVEFORMATEXTENSIBLE *)format;
if (IsEqualGUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, waveformatextensible->SubFormat)) { // true

在将所有捕获的数据写入文件之前,我填写了标题(在 http://www.topherlee.com/software/pcm-tut-wavformat.html 之后):

UINT32 sizePlaceholder = 0;
UINT32 fmtLength = 16;

// RIFF Header
fputs("RIFF", fp);                       // offset 0 (0x00)
fwrite(&sizePlaceholder, 4, 1, fp);      // offset 4 (0x04)
fputs("WAVE", fp);                       // offset 8 (0x08)
// fmt-Section
fputs("fmt ", fp);                         // offset 12 (0x0C)
fwrite(&fmtLength, 4, 1, fp);              // offset 16 (0x10)
fwrite(&format.wFormatTag, 2, 1, fp);      // offset 20 (0x14)
fwrite(&format.nChannels, 2, 1, fp);       // offset 22 (0x16)
fwrite(&format.nSamplesPerSec, 4, 1, fp);  // offset 24 (0x18)
fwrite(&format.nAvgBytesPerSec, 4, 1, fp); // offset 28 (0x1C)
fwrite(&format.nBlockAlign, 2, 1, fp);     // offset 32 (0x20)
fwrite(&format.wBitsPerSample, 2, 1, fp);  // offset 34 (0x22)
// Data-Section
fputs("data", fp);                         // offset 36 (0x24)
fwrite(&sizePlaceholder, 4, 1, fp);        // offset 40 (0x28)

在完成写入 3 秒的数据后,我使用 fwrite 填写文件大小和数据段大小的占位符。


文件不可读。我怀疑它与 WAVE_FORMAT_EXTENSIBLE 有关,但我无法弄清楚。

我尝试覆盖 format 的几个元素,例如:

cbSize = 0;
wFormatTag = WAVE_FORMAT_IEEE_FLOAT;

生成一个可读的 .wav 文件,但在其中播放一些咔哒声时静音(我尝试录制一首歌)。

wFormatTag = WAVE_FORMAT_PCM;

正在产生所有随机噪声。

最佳答案

所以,经过长时间的试验,我终于找到了解决方案。

代码存在多个问题。

  1. WAVE_FORMAT_EXTENSIBLE 使用文件布局,有点不同。看到这个很棒link了解更多详情。
  2. 我没有在 fopen 中设置二进制模式,所以音频数据被破坏了,因为 fwrite 检测到换行符 (\n)数据并添加一个回车符 (\r)。我不得不使用 fopen("foo.wav", "wb") 而不是 fopen("foo.wav", "w")

第二个问题是决定性的原因,因为我已经尝试用 WAVE_FORMAT_IEEE_FLOAT 标签替换 WAVE_FORMAT_EXTENSIBLE 标签,这应该有效,因为附加信息.wav 文件不需要工作。

关于c++ - WASAPI 环回 : Save wave file,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30692623/

相关文章:

python - 在python 3中使用numpy将wav文件混合在一起

c++ - wav 文件中的字节顺序

javascript - html5 + javascript 播放波浪声音

encryption - 如何打开 .txt.enc 文件?

python - python列表列表的用户可读文件格式

geometry - 将 Wavefront .obj 转换为 .off

c++ - 如何获得 std::uniform_int_distribution 的实现不可知版本?

c++ - 将堆栈字符串与堆字符串连接会产生奇怪的结果

c++ - 头文件中定义的函数原型(prototype)错误

c++ - alignof(T*) 对于所有可能的类型都相同吗? sizeof(T*) 呢?