简体   繁体   English

WASAPI Loopback:保存波形文件

[英]WASAPI Loopback: Save wave file

I want to record the system's audio output using WASAPI and then saving it to a .wav file.我想使用 WASAPI 记录系统的音频输出,然后将其保存到 .wav 文件。

So far I've followed these guides on WASAPI:到目前为止,我已经在 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 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

I get the buffer data using我使用获取缓冲区数据

audioCaptureClient->GetBuffer(&data, &numFramesAvailable, &flags, NULL, NULL);

then, I'm processing this data, by just writing it at the end of the .wav file:然后,我正在处理这些数据,只需将其写入 .wav 文件的末尾:

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

format is a WAVEFORMATEX received from audioClient->GetMixFormat(&format) : format是从audioClient->GetMixFormat(&format)接收到的WAVEFORMATEX

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

Apparently the subtype of WAVE_FORMAT_EXTENSIBLE is Float:显然WAVE_FORMAT_EXTENSIBLE的子类型是 Float:

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

Before writing all the captured data to the file I fill in the headers (following http://www.topherlee.com/software/pcm-tut-wavformat.html ):在将所有捕获的数据写入文件之前,我填写标题(遵循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)

After finishing writing 3 seconds of data I fill in the placeholders for the file size and the data section size using fwrite .写完 3 秒的数据后,我使用fwrite填充文件大小和数据段大小的占位符。


The file is not being readable.该文件不可读。 I suspect it has to do with WAVE_FORMAT_EXTENSIBLE , but I couldn't figure it out.我怀疑它与WAVE_FORMAT_EXTENSIBLE ,但我无法弄清楚。

I tried overwriting several elements of format like:我尝试覆盖几个format元素,例如:

cbSize = 0;
wFormatTag = WAVE_FORMAT_IEEE_FLOAT;

Producing a readable .wav file, but playing as silence with some clicks in it (I tried recording a song).生成一个可读的 .wav 文件,但在其中播放一些点击时静音(我尝试录制一首歌)。

wFormatTag = WAVE_FORMAT_PCM;

is producing all random noise.正在产生所有随机噪声。

So, finally after long hours of experimenting I found the solution.所以,经过长时间的试验,我终于找到了解决方案。

There were multiple problems with the code.代码存在多个问题。

  1. WAVE_FORMAT_EXTENSIBLE uses a file layout, being a bit different. WAVE_FORMAT_EXTENSIBLE使用文件布局,有点不同。 See this great link for more details.有关更多详细信息,请参阅此重要链接
  2. I did not set binary mode in fopen , so the audio data got corrupted, because fwrite detects newlines ( \\n ) in the data and adds a carriage return ( \\r ).我没有在fopen设置二进制模式,所以音频数据被破坏了,因为fwrite检测到数据中的换行符 ( \\n ) 并添加一个回车符 ( \\r )。 I had to use fopen("foo.wav", "wb") instead of fopen("foo.wav", "w") .我不得不使用fopen("foo.wav", "wb")而不是fopen("foo.wav", "w")

The second problem, was the decisive reason, because I already tried replacing the WAVE_FORMAT_EXTENSIBLE -tag with the WAVE_FORMAT_IEEE_FLOAT -tag, which should have worked, because the additional information are not needed for a .wav file to work.第二个问题是决定性的原因,因为我已经尝试用WAVE_FORMAT_EXTENSIBLE标签替换WAVE_FORMAT_IEEE_FLOAT标签,这应该可以工作,因为 .wav 文件不需要附加信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM