我是靠谱客的博主 重要路灯,最近开发中收集的这篇文章主要介绍windows采集音频1、 定义线程类定义回调定义实现类3、main主函数中测试4、执行结果,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
1、 定义线程类
线程类比较简单,使用标准c++ 的thread,线程类的Run函数为纯虚函数。
/*
Author:钱波
email: 418511899@qq.com
wei: 18091589062
func :线程类
time: 2018年5月30日
*/
#ifndef _TTHREAD_RUN_ABLE_H_
#define _TTHREAD_RUN_ABLE_H_
#include <mutex>
#include <queue>
#include <thread>
#include <atomic>
#include <condition_variable>
using namespace std;
class TThreadRunable
{
private:
//线程
thread _thread;
//等待信号
std::mutex _signal_mutex;
std::condition_variable _cond;
protected:
//char _running = false;
char _stop = true;
//锁定运行状态
std::mutex _mutex;
public:
TThreadRunable()
{}
virtual ~TThreadRunable()
{}
public:
char * status(){
return &_stop;
}
void Join()
{
if (_thread.joinable())
_thread.join();
}
bool IsStop()
{
return _stop == 1 ? true : false;
}
void WaitForSignal()
{
std::unique_lock<std::mutex> ul(_signal_mutex);
_cond.wait(ul);
}
void Notify()
{
_cond.notify_one();
}
virtual int Start()
{
if (_stop == 0)
return -1;
_stop = 0;
_thread = std::thread(std::bind(&TThreadRunable::Run, this));
return 0;
}
virtual void Stop()
{
_stop = 1; // true;
}
virtual void Run() = 0;
};
#endif
定义回调
typedef void(*VoiceCallback)(uint8_t *data, int len);
回调函数注入实现后,在线程中获取函数后,就调用回调函数。
定义实现类
#include <windows.h>
#include <windowsx.h>
#include <mmdeviceapi.h>
#include <Audioclient.h>
#include <process.h>
#include <avrt.h>
#include "TThreadRunable.h"
typedef void(*VoiceCallback)(uint8_t *data, int len);
class CAudioCapThread:public TThreadRunable
{
public:
enum {SPEAKER = 1,MICPHONE};
public:
CAudioCapThread();
~CAudioCapThread();
//开始捕获
int Start();
//停止捕获
void Stop();
void SetDeiveType(int nType);
int GetDeviceType();
IMMDevice * GetDevice();
WAVEFORMATEX * GetWaveFormat();
DWORD GetDataSize();
VoiceCallback m_callback = NULL;
void Run();
protected:
bool m_bInit;
bool Init();
void SaveFormat(WAVEFORMATEX * wf);
void OnCaptureData(LPBYTE pData, INT iDataLen);
WAVEFORMATEX m_WaveFormat;
int m_nDeviceType = 1;
IMMDevice * m_pDevice = NULL;
IMMDevice * GetDefaultDevice(int nType);
DWORD m_dwDataSize;
};
#include "AudioCapThread.h"
#define REFTIMES_PER_SEC 10000000
#define REFTIMES_PER_MILLISEC 10000
#pragma comment(lib, "Avrt.lib")
CAudioCapThread::CAudioCapThread()
{
m_dwDataSize = 0;
m_bInit = false;
//::InitializeCriticalSection(&m_cs);
}
CAudioCapThread::~CAudioCapThread()
{
}
void CAudioCapThread::SetDeiveType(int nType)
{
m_nDeviceType = nType;
}
int CAudioCapThread::GetDeviceType()
{
return m_nDeviceType;
}
void CAudioCapThread::OnCaptureData(LPBYTE pData, INT iDataLen)
{
if (m_callback != NULL)
m_callback(pData, iDataLen);
}
IMMDevice * CAudioCapThread::GetDefaultDevice(int nType)
{
IMMDevice *pDevice = nullptr;
IMMDeviceEnumerator *pMMDeviceEnumerator = nullptr;
HRESULT hr = CoCreateInstance(
__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_ALL,
__uuidof(IMMDeviceEnumerator),
(void**)&pMMDeviceEnumerator);
if (FAILED(hr))
return nullptr;
if (nType == CAudioCapThread::MICPHONE)
hr = pMMDeviceEnumerator->GetDefaultAudioEndpoint((EDataFlow)eCapture, eConsole, &pDevice);
else if (nType == CAudioCapThread::SPEAKER)
hr = pMMDeviceEnumerator->GetDefaultAudioEndpoint((EDataFlow)eRender, eConsole, &pDevice);
else
pDevice = nullptr;
if (pMMDeviceEnumerator)
{
pMMDeviceEnumerator->Release();
pMMDeviceEnumerator = nullptr;
}
return pDevice;
}
bool CAudioCapThread::Init()
{
if (m_bInit)
return true;
m_pDevice = GetDefaultDevice(m_nDeviceType);
if (!m_pDevice)
return false;
m_dwDataSize = 0;
m_bInit = true;
return true;
}
DWORD CAudioCapThread::GetDataSize()
{
DWORD dwSize = m_dwDataSize;
return dwSize;
}
IMMDevice * CAudioCapThread::GetDevice()
{
return m_pDevice;
}
void CAudioCapThread::Run()
{
CoInitialize(NULL);
HRESULT hr = 0;
IAudioClient *pAudioClient = nullptr;
WAVEFORMATEX *pWfx = nullptr;
IAudioCaptureClient *pAudioCaptureClient = nullptr;
DWORD nTaskIndex = 0;
HANDLE hTask = nullptr;
bool bStarted(false);
int nDeviceType = 0;
IMMDevice * pDevice = m_pDevice;
REFERENCE_TIME hnsRequestedDuration = REFTIMES_PER_SEC;
REFERENCE_TIME hnsActualDuration;
UINT bufferFrameCount = 0;
if (!pDevice )
return ;
do
{
hr = pDevice->Activate(__uuidof(IAudioClient), CLSCTX_ALL, nullptr, (void**)&pAudioClient);
if (FAILED(hr))
break;
hr = pAudioClient->GetMixFormat(&pWfx);
if (FAILED(hr))
break;
SaveFormat(pWfx);
nDeviceType = GetDeviceType();
if (nDeviceType == CAudioCapThread::MICPHONE)
hr = pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, 0, 0, pWfx, 0);
else if (nDeviceType == CAudioCapThread::SPEAKER)
hr = pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_LOOPBACK, 0, 0, pWfx, 0);
else
break;
if (FAILED(hr))
break;
hr = pAudioClient->GetBufferSize(&bufferFrameCount);
if (FAILED(hr))
break;
hr = pAudioClient->GetService(__uuidof(IAudioCaptureClient), (void**)&pAudioCaptureClient);
if (FAILED(hr))
break;
hnsActualDuration = (double)REFTIMES_PER_SEC * bufferFrameCount / pWfx->nSamplesPerSec;
if (nDeviceType == CAudioCapThread::MICPHONE)
hTask = AvSetMmThreadCharacteristics(L"Audio", &nTaskIndex);
else
hTask = AvSetMmThreadCharacteristics(L"Capture", &nTaskIndex);
if (!hTask)
break;
hr = pAudioClient->Start();
if (FAILED(hr))
break;
bStarted = true;
UINT32 uiNextPacketSize(0);
BYTE *pData = nullptr;
UINT32 uiNumFramesToRead;
DWORD dwFlags;
while (1)
{
if (IsStop())
break;
Sleep(hnsActualDuration / REFTIMES_PER_MILLISEC / 2);
hr = pAudioCaptureClient->GetNextPacketSize(&uiNextPacketSize);
if (FAILED(hr))
break;
while (uiNextPacketSize != 0)
{
hr = pAudioCaptureClient->GetBuffer(
&pData,
&uiNumFramesToRead,
&dwFlags,
nullptr,
nullptr);
if (FAILED(hr))
break;
if (dwFlags & AUDCLNT_BUFFERFLAGS_SILENT)
{
pData = NULL;
}
OnCaptureData(pData, uiNumFramesToRead * pWfx->nBlockAlign);
pAudioCaptureClient->ReleaseBuffer(uiNumFramesToRead);
hr = pAudioCaptureClient->GetNextPacketSize(&uiNextPacketSize);
if (FAILED(hr))
break;
}
}
} while (0);
if (hTask)
{
AvRevertMmThreadCharacteristics(hTask);
hTask = nullptr;
}
if (pAudioCaptureClient)
{
pAudioCaptureClient->Release();
pAudioCaptureClient = nullptr;
}
if (pWfx)
{
CoTaskMemFree(pWfx);
pWfx = nullptr;
}
if (pAudioClient)
{
if (bStarted)
{
pAudioClient->Stop();
}
pAudioClient->Release();
pAudioClient = nullptr;
}
}
void CAudioCapThread::SaveFormat(WAVEFORMATEX * wf)
{
if (!wf)
return;
memcpy(&m_WaveFormat, wf, sizeof(WAVEFORMATEX));
return;
}
WAVEFORMATEX * CAudioCapThread::GetWaveFormat()
{
return &m_WaveFormat;
}
int CAudioCapThread::Start()
{
if (!m_bInit)
Init();
TThreadRunable::Start();
return 0;
}
void CAudioCapThread::Stop()
{
if (m_bInit == false)
return ;
TThreadRunable::Stop();
Join();
if (m_pDevice)
{
m_pDevice->Release();
m_pDevice = NULL;
}
m_bInit = false;
}
3、main主函数中测试
#include "AudioCapThread.h"
#include <conio.h>
void voice_Callback(uint8_t *data, int len)
{
printf("the length is %dn", len);
}
int main()
{
CoInitialize(NULL);
CAudioCapThread thread;
//thread.Init();
thread.m_callback = voice_Callback;
thread.Start();
thread.Join();
printf("test");
CoUninitialize();
return 0;
}
4、执行结果
当系统开始播放时,回调函数开始显示有数据,停止播放时,回调函数停止响应
即使系统静音,依然可以捕获声音。
最后
以上就是重要路灯为你收集整理的windows采集音频1、 定义线程类定义回调定义实现类3、main主函数中测试4、执行结果的全部内容,希望文章能够帮你解决windows采集音频1、 定义线程类定义回调定义实现类3、main主函数中测试4、执行结果所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复