参考文档:

  • 主要的代码参考了官方文档的 Capturing a Stream 和 Loopback Recording 两篇
  • WAVHead 代码参考了 C++生成简单WAV文件(三)——根据简谱生成菊花台

直接上代码

主体代码:

#include "pch.h"
#include "WAVHead.h"using namespace std;//-----------------------------------------------------------
// Record an audio stream from the default audio capture
// device. The RecordAudioStream function allocates a shared
// buffer big enough to hold one second of PCM audio data.
// The function uses this buffer to stream data from the
// capture device. The main loop runs every 1/2 second.
//-----------------------------------------------------------// REFERENCE_TIME time units per second and per millisecond
#define REFTIMES_PER_SEC  10000000
#define REFTIMES_PER_MILLISEC  10000#define EXIT_ON_ERROR(hres)  \if (FAILED(hres)) { goto Exit; }
#define SAFE_RELEASE(punk)  \if ((punk) != NULL)  \{ (punk)->Release(); (punk) = NULL; }const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
const IID IID_IAudioClient = __uuidof(IAudioClient);
const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient);vector<BYTE> body;
unsigned int recordCount = 20;// 2147483648;HRESULT RecordAudioStream()
{HRESULT hr;REFERENCE_TIME hnsRequestedDuration = REFTIMES_PER_SEC;REFERENCE_TIME hnsActualDuration;UINT32 bufferFrameCount;UINT32 numFramesAvailable;IMMDeviceEnumerator *pEnumerator = NULL;IMMDevice *pDevice = NULL;IAudioClient *pAudioClient = NULL;IAudioCaptureClient *pCaptureClient = NULL;WAVEFORMATEX *pwfx = NULL;UINT32 packetLength = 0;BOOL bDone = FALSE;BYTE *pData;DWORD flags;hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL,IID_IMMDeviceEnumerator, (void**)&pEnumerator);EXIT_ON_ERROR(hr)hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice);EXIT_ON_ERROR(hr)hr = pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pAudioClient);EXIT_ON_ERROR(hr)// 因为接下来要手动指定音频格式,所以就不需要了// hr = pAudioClient->GetMixFormat(&pwfx);// EXIT_ON_ERROR(hr)WAVEFORMATEX waveFormat;waveFormat.wFormatTag = WAVE_FORMAT_PCM;waveFormat.nChannels = 2;waveFormat.nSamplesPerSec = 48000;waveFormat.nAvgBytesPerSec = 192000;waveFormat.wBitsPerSample = 16;waveFormat.nBlockAlign = 4;waveFormat.cbSize = 0;pwfx = &waveFormat;hr = pAudioClient->Initialize(   AUDCLNT_SHAREMODE_SHARED,AUDCLNT_STREAMFLAGS_LOOPBACK,hnsRequestedDuration, 0, pwfx, NULL);EXIT_ON_ERROR(hr)// Get the size of the allocated buffer.hr = pAudioClient->GetBufferSize(&bufferFrameCount);EXIT_ON_ERROR(hr)hr = pAudioClient->GetService(IID_IAudioCaptureClient, (void**)&pCaptureClient);EXIT_ON_ERROR(hr)// Notify the audio sink which format to use.// 如上一行注释,以下的代码是将获取到的音频格式传给另外的类(自己定义的),同样的,因为// 手动制定了音频格式,所以就不需要通知了// hr = pMySink->SetFormat(pwfx);// EXIT_ON_ERROR(hr)// Calculate the actual duration of the allocated buffer.hnsActualDuration = (double)REFTIMES_PER_SEC * bufferFrameCount / pwfx->nSamplesPerSec;hr = pAudioClient->Start();  // Start recording.EXIT_ON_ERROR(hr)// Each loop fills about half of the shared buffer.while (bDone == FALSE && recordCount > 0){// Sleep for half the buffer duration.// 如需降低延迟,可删除以下代码Sleep(hnsActualDuration / REFTIMES_PER_MILLISEC / 2);hr = pCaptureClient->GetNextPacketSize(&packetLength);EXIT_ON_ERROR(hr)while (packetLength != 0){// Get the available data in the shared buffer.hr = pCaptureClient->GetBuffer(&pData, &numFramesAvailable, &flags, NULL, NULL);EXIT_ON_ERROR(hr)if (flags & AUDCLNT_BUFFERFLAGS_SILENT){pData = NULL;  // Tell CopyData to write silence.}// Copy the available capture data to the audio sink.// 如上一行注释,以下代码是将捕获到的音频数据传给另外的类处理,因为接下// 来就要在这里处理了,所以也不需要了// hr = pMySink->CopyData(pData, numFramesAvailable, &bDone);// EXIT_ON_ERROR(hr)int dataSize = numFramesAvailable * 4;for (int i = 0; i < dataSize; i++) {BYTE tem = pData[i];body.push_back(pData[i]);}hr = pCaptureClient->ReleaseBuffer(numFramesAvailable);EXIT_ON_ERROR(hr)hr = pCaptureClient->GetNextPacketSize(&packetLength);EXIT_ON_ERROR(hr)}recordCount--;}hr = pAudioClient->Stop();  // Stop recording.EXIT_ON_ERROR(hr)Exit:// CoTaskMemFree(pwfx);SAFE_RELEASE(pEnumerator)SAFE_RELEASE(pDevice)SAFE_RELEASE(pAudioClient)SAFE_RELEASE(pCaptureClient)return hr;
}int main() {CoInitialize(NULL);RecordAudioStream();CoUninitialize();WAVHead head;head.setSize(body.size());ofstream ocout;ocout.open("1214.wav", ios::out | ios::binary);ocout.write((char*)&head, sizeof head);for (BYTE n : body) {ocout.write((char*)&n, 1);}ocout.close();return 0;
}

pch.h

#ifndef PCH_H
#define PCH_H// TODO: 添加要在此处预编译的标头
#include <iostream>
#include <fstream>
#include <vector>#include <dshow.h>
#include <Windows.h>
#include <winerror.h>
#include <mmdeviceapi.h>
#include <Functiondiscoverykeys_devpkey.h>#include <Audioclient.h>
#include <audiopolicy.h>#endif //PCH_H

WAVHead.h

#pragma once
class WAVHead
{
public:WAVHead();~WAVHead();void setSize(int);long int getsa();long int getsize();
private:char RIFFChunkID[4];        // 4 Bytes  文档标识 long int RIFFChunkSize;        // 4 Bytes  文件数据长度char Format[4];               // 4 Bytes  文件格式类型char FMTChunkID[4];           // 4 Bytes  格式快标识long int FMTChunkSize;     // 4 Bytes  格式快长度short int AudioFormat;     // 2 Bytes  编码格式代码short int NumChannels;        // 2 Bytes  声道个数long int SampleRate;        // 4 Bytes  采样频率long int ByteRate;          // 4 Bytes  数据传输速率short int BlockAlign;     // 2 Bytes  数据块对齐位short int BitsPerSample;  // 2 Bytes  采样位数char DataChunkID[4];        // 2 Byteslong int DataChunkSize;};

WAVHead.cpp

#include "pch.h"
#include "WAVHead.h"WAVHead::WAVHead()
{strcpy(RIFFChunkID, "RIFF");RIFFChunkSize = 0;strcpy(Format, "WAVE");strcpy(FMTChunkID, "fmt ");FMTChunkSize = 16;AudioFormat = 1;NumChannels = 2;SampleRate = 48000;ByteRate = 192000;BlockAlign = 4;BitsPerSample = 16;strcpy(DataChunkID, "data");DataChunkSize = 0;
}WAVHead::~WAVHead()
{
}void WAVHead::setSize(int size) {RIFFChunkSize = size + 30;DataChunkSize = size;
}
long int WAVHead::getsa() {return SampleRate;
}
long int WAVHead::getsize() {return DataChunkSize;
}

接下来修改 RealTek HD 音频管理器 里的设置为 16位 48000Hz

关于最后一行注释掉的代码:

CoTaskMemFree(pwfx);

官方文档 CoTaskMemFree function 中说道:

Frees a block of task memory previously allocated through a call to the CoTaskMemAlloc
or CoTaskMemRealloc function.

因为 pwfx 并不是由 CoTaskMemAlloc or CoTaskMemRealloc 分配的,所以也就不用调用 CoTaskMemFree 释放。

使用WASAPI捕获声卡音频相关推荐

  1. WASAPI 捕获指定设备的音频

    #include "stdafx.h"#include <MMDeviceAPI.h> #include <AudioClient.h> #include ...

  2. 主板声卡坏了会不会有电流声_拯救无声电脑,还能升级音质,独立声卡音频转接头来解决...

    生活中很多微小的数码配件,它们其貌不扬,但是功能却多种多样,如果你从未见过会对它们知之甚少,但是在需要的时候会解决很大的问题,比如这款内置了独立声卡的3.5mm音频转接头,就提供了USB供电的转音频与 ...

  3. java录制声音(采集声卡音频数据)

    采用java官方API--TargetDataLine,从声卡中采集音频数据达到录音效果,采集的数据为PCM裸流需要转为wav格式的话参照--PCM转WAV . 示例代码: import java.i ...

  4. android 声卡音频策略小记

    5.1 以前应该是在 hardware/libhardware_legacy/audio/AudioPolicyManagerBase.cpp 5.1 的时候 Android5.1/framework ...

  5. windows音频声卡采集

    作者: 使徒保罗 邮箱:297329588szh@163.com 声明: 欢迎交流学习,如有任何疑问,请通过邮箱联系本人 环境: win10 64位+qt5.7(MINGW) 参考:[微软还回录音文档 ...

  6. 音频编辑开发SDK Audio DJ Studio for .NET Crack

    11.7版本--Audio DJ Studio for .NET是 MultiMedia Soft 开发的 .NET Windows Forms 自定义控件,可以轻松地向使用Microsoft Vis ...

  7. .NET NAudio音频录制方法 2021-02-13

    .NET NAudio音频录制方法 写在前面 文章主要内容 说明 检测录音电平 调节录音电平 开始录音 调整音频 保存音频 关于作者 讨论 SomeONe Clint Nate Greenwood C ...

  8. WDM在不同Windows版本上的音频支持

    "Windows音频驱动"翻译系列总目录: https://blog.csdn.net/danteLiujie/article/details/102530417 目录 1. 实现 ...

  9. FFMPEG常用的一些命令介绍:音频录制、视频录制

    1.视频和音频单独抓取 如果指定输入格式和设备,则ffmpeg可以直接捕获视频和音频. Linux下捕获摄像头的数据保存成视频文件: # ffmpeg -f video4linux2 -s 1280x ...

最新文章

  1. 什么是okr,和kpi的区别在哪里
  2. 五分钟搞懂MySQL索引下推
  3. Bypass WAF实战总结
  4. 写在这个公众号关注者达到7000之际,Jerry有话对大家说
  5. java final const_Java 中的final 和C++ 中的const 有什么区别?
  6. 1-算法 排序 选择排序
  7. Windows 10如何强制删除多余的语言包
  8. mysql热块争用_Oracle 索引热块引起的latch争用实例分析(转)
  9. C+++之insert()
  10. LINUX 下安装git
  11. ENVI学习总结(二)——基于自带定位信息的几何校正
  12. NPOI2.0学习(三)
  13. 51单片机c语言烧录软件,51单片机烧写程序的方法
  14. (转)【JSON工具】一个JSON格式化查看工具——HIJSON
  15. Python tkinter库之Canvas 根据函数解析式或参数方程画出图像
  16. pktgen-dpdk 进行rfc2544测试
  17. 收集了一下WINDDOWS VISTA密码破解的方法
  18. 硬盘克隆 计算机更换硬盘,换硬盘数据怎么办 看一招本地磁盘对拷
  19. UNIAPP nvue 地图 markers 不显示
  20. 在Windows 7中使用AppLocker限制对程序的访问

热门文章

  1. 解决方案Solution
  2. Hadamard积的介绍
  3. 【Git配置技巧】01. 配置文件git config介绍
  4. 正则表达式验证IP地址合法性
  5. Linux下的文本编辑器和Windows的编辑器
  6. 愉快的舞会c++_项目经理和开发人员如何才能(愉快地!)给出实际的发货日期...
  7. H5页面保存base64图片到本地
  8. 计算机教师信息化大赛作品,全国“xx杯”计算机专业类说课大赛优秀作品:信息化色彩搭配训练说课课件.ppt...
  9. 清除bios密码的N种方法
  10. 搭建指标体系的底层逻辑