在windows平台下采集输入设备的音频数据资料已经很多了,但是采集声卡回放设备的方法却比较少,在此写下本人开发的一个用于采集声卡回放输出设备(桌面声音)的音频数据,并做重采样处理的功能模块;当然同时也支持从输入设备中采集音频数据。
在实现过程中使用了MMDevice API等较新的接口,该接口在windows vista之后的版本才出现,所以在此提供的代码只支持windows vista以后的版本,包括vista。
由于在windows下不同的声卡可以输出不同的音频格式,比如采样率、位深、声道数,所以从声卡设备中获取到的PCM数据格式与每台PC的声卡设置保持一致,因此必须在采集到PCM数据后统一做一次重采样处理,后面提供的代码中将最终输出双声道,s16、44100格式的PCM数据,以便后续处理。其中数据的重采样借助的是libsamplerate开源代码库,其可以使用VS工具直接编译。大家如果需要直接使用一下提供的代码的话需要自己去下载并静态编译libsamplerate库。
下面只贴出头文件,其它代码请到本人的已上传资料中下载;
#pragma once
#include <list>
#include <string>
#include <stdint.h>
#include <mmdeviceapi.h>
#include <Audioclient.h>
#include <propsys.h>
#include <Functiondiscoverykeys_devpkey.h>
#include "../libsamplerate/samplerate.h"
#pragma comment(lib, "libsamplerate.lib")
using namespace std;
#ifdef C64
typedef long long PARAM;
typedef unsigned long long UPARAM;
#else
typedef long PARAM;
typedef unsigned long UPARAM;
#endif
typedef char *LPSTR;
typedef const char *LPCSTR;
typedef wchar_t *WSTR;
typedef const wchar_t *CWSTR;
typedef TCHAR *TSTR;
typedef const TCHAR *CTSTR;
#define DEFAULT_SAMPLE_RATE 44100
#define KSAUDIO_SPEAKER_4POINT1 (KSAUDIO_SPEAKER_QUAD|SPEAKER_LOW_FREQUENCY)
#define KSAUDIO_SPEAKER_3POINT1 (KSAUDIO_SPEAKER_STEREO|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY)
#define KSAUDIO_SPEAKER_2POINT1 (KSAUDIO_SPEAKER_STEREO|SPEAKER_LOW_FREQUENCY)
#define SafeRelease(var) if(var) {var->Release(); var = NULL;}
enum edges {
edgeLeft = 0x01,
edgeRight = 0x02,
edgeTop = 0x04,
edgeBottom = 0x08,
};
struct AudioDeviceInfo
{
string strID;
string strName;
~AudioDeviceInfo() {strID.empty(); strName.empty();}
};
union TripleToLong
{
LONG val;
struct
{
WORD wVal;
BYTE tripleVal;
BYTE lastByte;
};
};
struct NotAResampler
{
SRC_STATE *resampler;
uint64_t jumpRange;
};
enum AudioDeviceType {
ADT_PLAYBACK,
ADT_RECORDING
};
class CDesktopAudioDevice
{
public:
CDesktopAudioDevice(void);
~CDesktopAudioDevice(void);
bool Init(bool isPlayBack, const string devGUID = "Default");
void StartCapture();
void StopCapture();
int QueryAudioBuffer(string &outData);
int GetAudioDevices(list<AudioDeviceInfo *> &deviceList, AudioDeviceType deviceType, bool bConnectedOnly);
bool GetDefaultDevice(string &strVal, AudioDeviceType deviceType);
bool GetDefaultMicID(string &strVal);
bool GetDefaultSpeakerID(string &strVal);
protected:
wchar_t* MByteToWChar(uint32_t CodePage,LPCSTR lpcszSrcStr);
char* WCharToMByte(uint32_t CodePage,LPCWSTR lpcwszSrcStr);
bool GetNextBuffer(string &buffer, uint32_t &numFrames);
void FreeData();
protected:
list<AudioDeviceInfo *> m_DeviceList;
string m_CurDeviceID;
string m_CurDeviceName;
IMMDeviceEnumerator *mmEnumerator_;
IMMDevice *mmDevice_;
IAudioClient *mmClient_;
IAudioCaptureClient *mmCapture_;
uint32_t m_SampleWindowSize;
DWORD m_InputChannelMask;
WORD m_InputChannels;
uint32_t m_InputSamplesPerSec;
uint32_t m_InputBufferSize;
uint32_t m_InputBitsPerSample;
bool m_bFloat;
NotAResampler *m_pResampler;
double m_ResampleRatio;
uint8_t *m_pBlankBuffer, *m_pTempResampleBuffer;
uint8_t *m_pDataOutputBuffer;
uint8_t *m_pTmpBuffer;
};
本文出自 “大师兄” 博客,请务必保留此出处http://cto521.blog.51cto.com/9652841/1585759
来源:oschina
链接:https://my.oschina.net/u/2984038/blog/780226