首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WASAPI回圈:保存波形文件

WASAPI回圈:保存波形文件
EN

Stack Overflow用户
提问于 2015-06-07 10:47:23
回答 1查看 1.9K关注 0票数 1

我想使用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

我使用以下方法获取缓冲区数据

代码语言:javascript
复制
audioCaptureClient->GetBuffer(&data, &numFramesAvailable, &flags, NULL, NULL);

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

代码语言:javascript
复制
size_t dataSize = format.nChannels * (format.wBitsPerSample / 8) * numFramesAvailable;
fwrite(data, dataSize, 1, fp);

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

代码语言:javascript
复制
cbSize:          22
nAvgBytesPerSec: 352800
nBlockAlign:     8
nChannels:       2
nSamplesPerSec:  44100
wBitsPerSample:  32
wFormatTag:      65534 (WAVE_FORMAT_EXTENSIBLE)

显然,WAVE_FORMAT_EXTENSIBLE的子类型是Float:

代码语言:javascript
复制
WAVEFORMATEXTENSIBLE *waveformatextensible = (WAVEFORMATEXTENSIBLE *)format;
if (IsEqualGUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, waveformatextensible->SubFormat)) { // true

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

代码语言:javascript
复制
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的几个元素,例如:

代码语言:javascript
复制
cbSize = 0;
wFormatTag = WAVE_FORMAT_IEEE_FLOAT;

生成一个可读的.wav文件,但只需在其中单击就可以保持沉默(我试着录制一首歌)。

代码语言:javascript
复制
wFormatTag = WAVE_FORMAT_PCM;

都会产生随机噪音。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-06-09 20:11:04

所以,经过长时间的实验,我终于找到了解决办法。

代码有多个问题。

  1. WAVE_FORMAT_EXTENSIBLE使用文件布局,有点不同。有关更多细节,请参见这个伟大的链接
  2. 我没有在fopen中设置二进制模式,因此音频数据被损坏,因为fwrite检测数据中的换行符(\n)并添加回车(\r)。我不得不使用fopen("foo.wav", "wb")而不是fopen("foo.wav", "w")

第二个问题是决定性的原因,因为我已经尝试用应该有效的WAVE_FORMAT_EXTENSIBLE-tag替换WAVE_FORMAT_IEEE_FLOAT-tag,因为.wav文件不需要额外的信息。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30692623

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档