window如何采集回放设备声音 并重采样
2016-11-03 00:00
267 查看
在windows平台下采集输入设备的音频数据资料已经很多了,但是采集声卡回放设备的方法却比较少,在此写下本人开发的一个用于采集声卡回放输出设备(桌面声音)的音频数据,并做重采样处理的功能模块;当然同时也支持从输入设备中采集音频数据。
在实现过程中使用了MMDevice API等较新的接口,该接口在windows vista之后的版本才出现,所以在此提供的代码只支持windows vista以后的版本,包括vista。
由于在windows下不同的声卡可以输出不同的音频格式,比如采样率、位深、声道数,所以从声卡设备中获取到的PCM数据格式与每台PC的声卡设置保持一致,因此必须在采集到PCM数据后统一做一次重采样处理,后面提供的代码中将最终输出双声道,s16、44100格式的PCM数据,以便后续处理。其中数据的重采样借助的是libsamplerate开源代码库,其可以使用VS工具直接编译。大家如果需要直接使用一下提供的代码的话需要自己去下载并静态编译libsamplerate库。
下面只贴出头文件,其它代码请到本人的已上传资料中下载;
本文出自 “大师兄” 博客,请务必保留此出处http://cto521.blog.51cto.com/9652841/1585759
在实现过程中使用了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
相关文章推荐
- window如何采集回放设备声音 并重采样
- 听单测试,测试你的回放声音的设备与耳朵听音分辨能力。
- 底层设备接口函数回放声音
- 如何解决Windows 10系统下设备的声音问题
- Linux 下如何通过两个或多个输出设备播放声音
- iOS如何获取设备声音和振动功能
- 底层设备接口函数回放声音
- Windows7下如何同步播放通过麦克等设备输入进来的声音————windows7侦听麦克风
- 用底层设备接口函数回放声音
- video_replay如何捕获和回放WebRTC视频流
- 无法识别usb设备如何解决
- 如何在Global.asax文件中实现定时采集新闻
- 如何查看android设备的PID和VID
- 如何屏蔽window.open打开窗口标题栏的url显示
- 如何解决LUnix 操作系统下设备无法umount的问题
- 教你如何深度解析Windows7的设备驱动管理原理
- 如何编译ffmpeg以支持dshow设备
- 如何实现浏览器兼容版的window.getComputedStyle
- 高效率视频播放: 如何使用3D API 进行视频的高质量回放(1)
- 如何写DOS下的设备驱动程序(二)