需求:根据现场环境,自动调节音量
一,思路
用一个线程不停采集PCM数据,并转化为分贝数。根据事先设定好的分贝区间,来实时检测现场的分贝数,并动态调整电脑的音量。
二,参考
(1)https://blog.csdn.net/weixin_38416696/article/details/98953072 Qt采集PCM数据
(2)https://blog.csdn.net/zouli415/article/details/79702359 PCM转分贝
(3)调整电脑音量,具体链接忘了
#pragma once
#define MAX_VOL 100
class MixerWrap
{
public:
MixerWrap(void){};
public:
virtual ~MixerWrap(void){};
static void MicphoneBoost(bool bIsBoost);
static void MicphoneMut(bool bIsMut);
static void StereoMix(bool bIsMix);
static bool MicphoneMut_W7(bool bIsMut,float fVolume); //设置麦克风音量
static int GetMicphone_W7(DWORD &pdwVolume); //获取麦克风音量
static void MicphoneBoost_W7(float fValue);//设置麦克风增强等级
static void GetMicphoneLevel(float &fValue); //获取麦克风增强等级
static void GetMicphoneLevelData(float &nMin, float &nMax, float &nStep); //获取麦克风最小值,最大值和增量
static bool GetSpeakerValue_W7(float &fVolume); //获取喇叭音量
static bool SetSpeakerValue_W7(float fVolume); //设置喇叭音量
static bool MutSpeaker_W7(bool bMute,float fVolume);
//立体声混音音量调节
static void StereoMixVolume(int nVolume);
static void OutPutMicphoneVolume(int nVolume);
static void InPutMicphoneVolume(int nVolume);
static int SelectRecordIn(DWORD dwSrcType);
static int SelectRecordInByName(WCHAR* szSrcName);
};
#include "StdAfx.h"
#include "MixerWrap.h"
#include
#include
#include
#include
#include
using namespace std;
#include
#include
#include
#include
#define TOWCHAT(x) QStringLiteral(x).toStdWString().data()
#define SAFE_RELEASE(punk) \
if ((punk) != NULL) \
#define EXIT_ON_ERROR(hres) if (FAILED(hres)) { goto Exit; }
#define SAFE_RELEASE(punk) if ((punk) != NULL) { (punk)->Release(); (punk) = NULL; }
HRESULT getMicrophoneBoostVolumeLevel(IMMDevice *pEndptDev, IAudioVolumeLevel** ppVolumeLevel)
{
HRESULT hr = S_OK;
DataFlow flow;
IDeviceTopology *pDeviceTopology = NULL;
IConnector *pConnFrom = NULL;
IConnector *pConnTo = NULL;
IPart *pPartPrev = NULL;
IPart *pPartNext = NULL;
*ppVolumeLevel = NULL;
wchar_t microphoneBoostName[] = L"麦克风加强";//if your system language is English,the name is "microphone boost"
if (pEndptDev == NULL)
{
EXIT_ON_ERROR(hr = E_POINTER)
}
// Get the endpoint device's IDeviceTopology interface.
hr = pEndptDev->Activate(
__uuidof(IDeviceTopology), CLSCTX_ALL, NULL,
(void**)&pDeviceTopology);
EXIT_ON_ERROR(hr)
// The device topology for an endpoint device always
// contains just one connector (connector number 0).
hr = pDeviceTopology->GetConnector(0, &pConnFrom);
SAFE_RELEASE(pDeviceTopology)
EXIT_ON_ERROR(hr)
// Make sure that this is a capture device.
hr = pConnFrom->GetDataFlow(&flow);
EXIT_ON_ERROR(hr)
if (flow != Out)
{
// Error -- this is a rendering device.
//EXIT_ON_ERROR(hr = AUDCLNT_E_WRONG_ENDPOINT_TYPE)
}
// Outer loop: Each iteration traverses the data path
// through a device topology starting at the input
// connector and ending at the output connector.
while (TRUE)
{
BOOL bConnected;
hr = pConnFrom->IsConnected(&bConnected);
EXIT_ON_ERROR(hr)
// Does this connector connect to another device?
if (bConnected == FALSE)
{
// This is the end of the data path that
// stretches from the endpoint device to the
// system bus or external bus. Verify that
// the connection type is Software_IO.
ConnectorType connType;
hr = pConnFrom->GetType(&connType);
EXIT_ON_ERROR(hr)
if (connType == Software_IO)
{
break; // finished
}
EXIT_ON_ERROR(hr = E_FAIL)
}
// Get the connector in the next device topology,
// which lies on the other side of the connection.
hr = pConnFrom->GetConnectedTo(&pConnTo);
EXIT_ON_ERROR(hr)
SAFE_RELEASE(pConnFrom)
// Get the connector's IPart interface.
hr = pConnTo->QueryInterface(
__uuidof(IPart), (void**)&pPartPrev);
EXIT_ON_ERROR(hr)
SAFE_RELEASE(pConnTo)
// Inner loop: Each iteration traverses one link in a
// device topology and looks for input multiplexers.
while (TRUE)
{
PartType parttype;
IPartsList *pParts;
// Follow downstream link to next part.
hr = pPartPrev->EnumPartsOutgoing(&pParts);
EXIT_ON_ERROR(hr)
hr = pParts->GetPart(0, &pPartNext);
pParts->Release();
EXIT_ON_ERROR(hr)
hr = pPartNext->GetPartType(&parttype);
EXIT_ON_ERROR(hr)
LPWSTR pName;
if (SUCCEEDED(pPartNext->GetName(&pName)))
{
// Failure of the following call means only that
// the part is not a boost (micrphone boost).
if (wcscmp(microphoneBoostName,pName) == 0)
{
//get IAudioVolumeLevel to control volume
hr = pPartNext->Activate(CLSCTX_ALL, __uuidof(IAudioVolumeLevel), (void**)ppVolumeLevel);
goto Exit;
}
CoTaskMemFree(pName);
}
GUID subType;
pPartNext->GetSubType(&subType);
if (parttype == Connector)
{
// We've reached the output connector that
// lies at the end of this device topology.
hr = pPartNext->QueryInterface(
__uuidof(IConnector),
(void**)&pConnFrom);
EXIT_ON_ERROR(hr)
SAFE_RELEASE(pPartPrev)
SAFE_RELEASE(pPartNext)
break;
}
SAFE_RELEASE(pPartPrev)
pPartPrev = pPartNext;
pPartNext = NULL;
}
}
Exit:
SAFE_RELEASE(pConnFrom)
SAFE_RELEASE(pConnTo)
SAFE_RELEASE(pPartPrev)
SAFE_RELEASE(pPartNext)
return hr;
}
void MixerWrap::MicphoneBoost(bool bIsBoost)
{
int mixerNum ;//总的混音器数量
HMIXER hMixer; //混音器设备句柄
MMRESULT mmr;//函数调用返回
MIXERCAPS MixerCaps; //混音器设备能力信息
MIXERLINE MixerLine;//线路的信息
//获取当前系统总的混音器数量
mixerNum= mixerGetNumDevs();
bool ifFind =false;
for(int i=0;iGetDefaultAudioEndpoint(eCapture, eMultimedia, &defaultDevice);
deviceEnumerator->Release();
deviceEnumerator = NULL;
IAudioVolumeLevel* pIaudioVolumeLevel;
getMicrophoneBoostVolumeLevel(defaultDevice,&pIaudioVolumeLevel);
defaultDevice->Release();
defaultDevice = NULL;
if (pIaudioVolumeLevel==NULL)
{
return ;
}
pIaudioVolumeLevel->SetLevel(0,fValue,NULL);//0-30
return ;
}
void MixerWrap::GetMicphoneLevel(float &fValue)
{
HRESULT hr=NULL;
CoInitialize(NULL);
IMMDeviceEnumerator *deviceEnumerator = NULL;
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER,
__uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator);
IMMDevice *defaultDevice = NULL;
if (hr != S_OK)
{
return ;
}
hr = deviceEnumerator->GetDefaultAudioEndpoint(eCapture, eMultimedia, &defaultDevice);
deviceEnumerator->Release();
deviceEnumerator = NULL;
IAudioVolumeLevel* pIaudioVolumeLevel;
getMicrophoneBoostVolumeLevel(defaultDevice,&pIaudioVolumeLevel);
defaultDevice->Release();
defaultDevice = NULL;
if (pIaudioVolumeLevel==NULL)
{
return ;
}
pIaudioVolumeLevel->GetLevel(0,&fValue);//0-30
return ;
}
void MixerWrap::GetMicphoneLevelData(float &nMin, float &nMax, float &nStep)
{
HRESULT hr=NULL;
CoInitialize(NULL);
IMMDeviceEnumerator *deviceEnumerator = NULL;
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER,
__uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator);
IMMDevice *defaultDevice = NULL;
if (hr != S_OK)
{
return ;
}
hr = deviceEnumerator->GetDefaultAudioEndpoint(eCapture, eMultimedia, &defaultDevice);
deviceEnumerator->Release();
deviceEnumerator = NULL;
IAudioVolumeLevel* pIaudioVolumeLevel;
getMicrophoneBoostVolumeLevel(defaultDevice,&pIaudioVolumeLevel);
defaultDevice->Release();
defaultDevice = NULL;
if (pIaudioVolumeLevel==NULL)
{
return ;
}
pIaudioVolumeLevel->GetLevelRange(0,&nMin, &nMax, &nStep);//0-30
}
void MixerWrap::MicphoneMut(bool bIsMut)
{
int mixerNum ;//总的混音器数量
HMIXER hMixer; //混音器设备句柄
MMRESULT mmr;//函数调用返回
MIXERCAPS MixerCaps; //混音器设备能力信息
MIXERLINE MixerLine;//线路的信息
//获取当前系统总的混音器数量
mixerNum= mixerGetNumDevs();
bool ifFind =false;
for(int i=0;idwValue= nVolume;
mmr = mixerSetControlDetails((HMIXEROBJ)hMixer, &MixerControlDetails, MIXER_SETCONTROLDETAILSF_VALUE);
free(pMixerControlDetails_Unsigned);
//关闭混音器
mixerClose(hMixer);
}
return ;
}
void MixerWrap::OutPutMicphoneVolume(int nVolume)
{
int mixerNum ;//总的混音器数量
HMIXER hMixer; //混音器设备句柄
MMRESULT mmr;//函数调用返回
MIXERCAPS MixerCaps; //混音器设备能力信息
MIXERLINE MixerLine;//线路的信息
//获取当前系统总的混音器数量
mixerNum= mixerGetNumDevs();
bool ifFind =false;
for(int i=0;idwValue= nVolume;
mmr = mixerSetControlDetails((HMIXEROBJ)hMixer, &MixerControlDetails, MIXER_SETCONTROLDETAILSF_VALUE);
free(pMixerControlDetails_Unsigned);
/*MIXERCONTROLDETAILS MixerControlDetails;
PMIXERCONTROLDETAILS_BOOLEAN pMixerControlDetails_Boolean;
pMixerControlDetails_Boolean = (PMIXERCONTROLDETAILS_BOOLEAN)malloc(1 * sizeof(MIXERCONTROLDETAILS_BOOLEAN));
memset(&MixerControlDetails,0,sizeof(MixerControlDetails));
MixerControlDetails.cbStruct = sizeof(MixerControlDetails);
MixerControlDetails.dwControlID = MixerControl.dwControlID;
MixerControlDetails.cChannels =1;
MixerControlDetails.cMultipleItems =0;
MixerControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
MixerControlDetails.paDetails = &pMixerControlDetails_Boolean[0];
pMixerControlDetails_Boolean[0].fValue = bIsMut;
mmr = mixerSetControlDetails((HMIXEROBJ)hMixer, &MixerControlDetails, MIXER_SETCONTROLDETAILSF_VALUE);
free(pMixerControlDetails_Boolean);*/
//关闭混音器
mixerClose(hMixer);
}
return ;
}
void MixerWrap::InPutMicphoneVolume(int nVolume)
{
int mixerNum ;//总的混音器数量
HMIXER hMixer; //混音器设备句柄
MMRESULT mmr;//函数调用返回
MIXERCAPS MixerCaps; //混音器设备能力信息
MIXERLINE MixerLine;//线路的信息
//获取当前系统总的混音器数量
mixerNum= mixerGetNumDevs();
bool ifFind =false;
for(int i=1;idwValue= nVolume;
mmr = mixerSetControlDetails((HMIXEROBJ)hMixer, &MixerControlDetails, MIXER_SETCONTROLDETAILSF_VALUE);
free(pMixerControlDetails_Unsigned);
/*MIXERCONTROLDETAILS MixerControlDetails;
PMIXERCONTROLDETAILS_BOOLEAN pMixerControlDetails_Boolean;
pMixerControlDetails_Boolean = (PMIXERCONTROLDETAILS_BOOLEAN)malloc(1 * sizeof(MIXERCONTROLDETAILS_BOOLEAN));
memset(&MixerControlDetails,0,sizeof(MixerControlDetails));
MixerControlDetails.cbStruct = sizeof(MixerControlDetails);
MixerControlDetails.dwControlID = MixerControl.dwControlID;
MixerControlDetails.cChannels =1;
MixerControlDetails.cMultipleItems =0;
MixerControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
MixerControlDetails.paDetails = &pMixerControlDetails_Boolean[0];
pMixerControlDetails_Boolean[0].fValue = bIsMut;
mmr = mixerSetControlDetails((HMIXEROBJ)hMixer, &MixerControlDetails, MIXER_SETCONTROLDETAILSF_VALUE);
free(pMixerControlDetails_Boolean);*/
//关闭混音器
mixerClose(hMixer);
}
return ;
}
bool MixerWrap::GetSpeakerValue_W7(float &fVolume)
{
IMMDeviceEnumerator* pEnumerator;
IMMDeviceCollection *pCollection = NULL;
IMMDevice *pDevice=NULL;
IPropertyStore *pProperties=NULL;
IAudioEndpointVolume *pVolumeAPI=NULL;
IAudioAutoGainControl* pAutoGain=NULL;
UINT deviceCount = 0;
CoInitializeEx(NULL, COINIT_MULTITHREADED);
HRESULT hr=CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL,CLSCTX_ALL, __uuidof(IMMDeviceEnumerator),(void**)&pEnumerator);
if (hr != S_OK)
{
printf("CoCreateInstance Failed!/n");
return 0;
}
hr = pEnumerator->EnumAudioEndpoints(/*eCapture*/ eRender, DEVICE_STATE_ACTIVE, &pCollection);
//hr = pEnumerator->EnumAudioEndpoints( eRender , DEVICE_STATEMASK_ALL , &pCollection );
if (hr != S_OK)
{
printf("EnumAudioEndpoints Failed!/n");
goto releasepEnumerator;
}
hr = pCollection->GetCount(&deviceCount);
if (hr != S_OK)
{
printf("GetCount Failed!/n");
goto releasepCollection;
}
for (UINT dev=0;devItem(dev,&pDevice);
if (hr == S_OK)
{
hr = pDevice->OpenPropertyStore(STGM_READ,&pProperties);
if (hr == S_OK)
{
PROPVARIANT varName;
PropVariantInit(&varName);
hr = pProperties->GetValue(PKEY_Device_FriendlyName, &varName);
if (hr == S_OK )
{
//::MessageBox(NULL,varName.pwszVal,_T("提示信息"),MB_OK | MB_ICONINFORMATION);
// if (wcsstr(varName.pwszVal,_T("扬声器"))!=NULL)
{
//hr=pDevice->Activate(__uuidof(IAudioAutoGainControl),CLSCTX_ALL,NULL,(void **)(&pAutoGain));
hr=pDevice->Activate(__uuidof(IAudioEndpointVolume),CLSCTX_ALL,NULL,(void **)(&pVolumeAPI));
if (hr==S_OK)
{
UINT chanelCount = 0;
hr =pVolumeAPI->GetChannelCount(&chanelCount);
for (int i=0;iGetMasterVolumeLevelScalar(&fVolumeTemp);
if(fabsf(fVolumeTemp -0) > 0.00001)
fVolume = 100 * fVolumeTemp + 0.5;
}
SAFE_RELEASE(pVolumeAPI);
}
}
}
SAFE_RELEASE(pProperties);
}
SAFE_RELEASE(pDevice);
}
}
releasepCollection:
SAFE_RELEASE(pCollection);
releasepEnumerator:
SAFE_RELEASE(pEnumerator);
return 0;
}
bool MixerWrap::SetSpeakerValue_W7(float fVolume) //设置喇叭音量
{
IMMDeviceEnumerator* pEnumerator;
IMMDeviceCollection *pCollection = NULL;
IMMDevice *pDevice=NULL;
IPropertyStore *pProperties=NULL;
IAudioEndpointVolume *pVolumeAPI=NULL;
IAudioAutoGainControl* pAutoGain=NULL;
GUID m_guidMyContext;
UINT deviceCount = 0;
CoInitializeEx(NULL, COINIT_MULTITHREADED);
HRESULT hr=CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL,CLSCTX_ALL, __uuidof(IMMDeviceEnumerator),(void**)&pEnumerator);
if (hr != S_OK)
{
printf("CoCreateInstance Failed!/n");
return 0;
}
hr = pEnumerator->EnumAudioEndpoints(/*eCapture*/ eRender, DEVICE_STATE_ACTIVE, &pCollection);
//hr = pEnumerator->EnumAudioEndpoints( eRender , DEVICE_STATEMASK_ALL , &pCollection );
if (hr != S_OK)
{
printf("EnumAudioEndpoints Failed!/n");
goto releasepEnumerator;
}
hr = pCollection->GetCount(&deviceCount);
if (hr != S_OK)
{
printf("GetCount Failed!/n");
goto releasepCollection;
}
for (UINT dev=0;devItem(dev,&pDevice);
if (hr == S_OK)
{
hr = pDevice->OpenPropertyStore(STGM_READ,&pProperties);
if (hr == S_OK)
{
PROPVARIANT varName;
PropVariantInit(&varName);
hr = pProperties->GetValue(PKEY_Device_FriendlyName, &varName);
if (hr == S_OK )
{
//::MessageBox(NULL,varName.pwszVal,_T("提示信息"),MB_OK | MB_ICONINFORMATION);
// if (wcsstr(varName.pwszVal,_T("扬声器"))!=NULL)
{
//hr=pDevice->Activate(__uuidof(IAudioAutoGainControl),CLSCTX_ALL,NULL,(void **)(&pAutoGain));
hr=pDevice->Activate(__uuidof(IAudioEndpointVolume),CLSCTX_ALL,NULL,(void **)(&pVolumeAPI));
if (hr==S_OK)
{
UINT chanelCount = 0;
hr =pVolumeAPI->GetChannelCount(&chanelCount);
for (int i=0;i MAX_VOL)
fVolume = MAX_VOL;
pVolumeAPI->SetMasterVolumeLevelScalar((float)fVolume / MAX_VOL, &m_guidMyContext);
}
SAFE_RELEASE(pVolumeAPI);
}
}
}
SAFE_RELEASE(pProperties);
}
SAFE_RELEASE(pDevice);
}
}
releasepCollection:
SAFE_RELEASE(pCollection);
releasepEnumerator:
SAFE_RELEASE(pEnumerator);
return 0;
}
bool MixerWrap::MutSpeaker_W7(bool bMute,float fVolume)
{
//::MessageBox(NULL,_T("MutSpeaker_W7"),_T("提示信息"),MB_OK | MB_ICONINFORMATION);
IMMDeviceEnumerator* pEnumerator;
IMMDeviceCollection *pCollection = NULL;
IMMDevice *pDevice=NULL;
IPropertyStore *pProperties=NULL;
IAudioEndpointVolume *pVolumeAPI=NULL;
IAudioAutoGainControl* pAutoGain=NULL;
UINT deviceCount = 0;
CoInitializeEx(NULL, COINIT_MULTITHREADED);
HRESULT hr=CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL,CLSCTX_ALL, __uuidof(IMMDeviceEnumerator),(void**)&pEnumerator);
if (hr != S_OK)
{
printf("CoCreateInstance Failed!/n");
return 0;
}
hr = pEnumerator->EnumAudioEndpoints(/*eCapture*/ eRender, DEVICE_STATE_ACTIVE, &pCollection);
//hr = pEnumerator->EnumAudioEndpoints( eRender , DEVICE_STATEMASK_ALL , &pCollection );
if (hr != S_OK)
{
printf("EnumAudioEndpoints Failed!/n");
goto releasepEnumerator;
}
hr = pCollection->GetCount(&deviceCount);
if (hr != S_OK)
{
printf("GetCount Failed!/n");
goto releasepCollection;
}
for (UINT dev=0;devItem(dev,&pDevice);
if (hr == S_OK)
{
hr = pDevice->OpenPropertyStore(STGM_READ,&pProperties);
if (hr == S_OK)
{
PROPVARIANT varName;
PropVariantInit(&varName);
hr = pProperties->GetValue(PKEY_Device_FriendlyName, &varName);
/* char temp[20];
sprintf_s(temp,"%d\0",hr);
_bstr_t strStr = temp;
LPCSTR lpctStrName = strStr;
::MessageBox(NULL,(LPCWSTR)lpctStrName,_T("提示信息"),MB_OK | MB_ICONINFORMATION);*/
if (hr == S_OK )
{
//::MessageBox(NULL,varName.pwszVal,_T("提示信息"),MB_OK | MB_ICONINFORMATION);
if (wcsstr(varName.pwszVal,TOWCHAT("扬声器"))!=NULL)
{
//hr=pDevice->Activate(__uuidof(IAudioAutoGainControl),CLSCTX_ALL,NULL,(void **)(&pAutoGain));
hr=pDevice->Activate(__uuidof(IAudioEndpointVolume),CLSCTX_ALL,NULL,(void **)(&pVolumeAPI));
if (hr==S_OK)
{
UINT chanelCount = 0;
hr =pVolumeAPI->GetChannelCount(&chanelCount);
for (int i=0;iGetVolumeRange(&minLevel,&maxLevel,&stepLevel);
float fVolumeTemp;
pVolumeAPI->GetMasterVolumeLevelScalar(&fVolumeTemp);
if(fVolume != NULL)
fVolume = 100 * fVolumeTemp + 0.5;
pVolumeAPI->SetChannelVolumeLevelScalar(i,fVolume,NULL);
int test=55;
}
hr = pVolumeAPI->SetMute(bMute,NULL);
SAFE_RELEASE(pVolumeAPI);
}
}
}
SAFE_RELEASE(pProperties);
}
SAFE_RELEASE(pDevice);
}
}
releasepCollection:
SAFE_RELEASE(pCollection);
releasepEnumerator:
SAFE_RELEASE(pEnumerator);
return 0;
}
int MixerWrap::GetMicphone_W7(DWORD &pdwVolume)
{
IMMDeviceEnumerator* pEnumerator;
IMMDeviceCollection *pCollection = NULL;
IMMDevice *pDevice=NULL;
IPropertyStore *pProperties=NULL;
IAudioEndpointVolume *pVolumeAPI=NULL;
UINT deviceCount = 0;
GUID m_guidMyContext;
CoInitializeEx(NULL, COINIT_MULTITHREADED);
HRESULT hr=CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL,CLSCTX_ALL, __uuidof(IMMDeviceEnumerator),(void**)&pEnumerator);
if (hr != S_OK)
{
//printf("CoCreateInstance Failed!/n");
return 0;
}
hr = pEnumerator->EnumAudioEndpoints(eCapture /*eRender*/, DEVICE_STATE_ACTIVE, &pCollection);
//hr = pEnumerator->EnumAudioEndpoints( eRender , DEVICE_STATEMASK_ALL , &pCollection );
if (hr != S_OK)
{
// printf("EnumAudioEndpoints Failed!/n");
goto releasepEnumerator;
}
//::MessageBox(NULL,_T("MicphoneMut_W7"),_T("提示信息"),MB_OK | MB_ICONINFORMATION);
hr = pCollection->GetCount(&deviceCount);
if (hr != S_OK)
{
//printf("GetCount Failed!/n");
goto releasepCollection;
}
for (UINT dev=0;devItem(dev,&pDevice);
if (hr == S_OK)
{
hr = pDevice->OpenPropertyStore(STGM_READ,&pProperties);
if (hr == S_OK)
{
PROPVARIANT varName;
PropVariantInit(&varName);
//hr = pProperties->GetValue(PKEY_Device_BusTypeGuid, &varName);
hr = pProperties->GetValue(PKEY_Device_FriendlyName, &varName);
if (hr == S_OK )
{
if (wcsstr(varName.pwszVal,TOWCHAT("麦克风"))!=NULL)
{
hr=pDevice->Activate(__uuidof(IAudioEndpointVolume),CLSCTX_ALL,NULL,(void **)(&pVolumeAPI));
if (hr==S_OK)
{
float fVolume;
pVolumeAPI->GetMasterVolumeLevelScalar(&fVolume);
pdwVolume = 100 * fVolume + 0.5;
SAFE_RELEASE(pVolumeAPI);
}
}
}
SAFE_RELEASE(pProperties);
}
SAFE_RELEASE(pDevice);
}
}
releasepCollection:
SAFE_RELEASE(pCollection);
releasepEnumerator:
SAFE_RELEASE(pEnumerator);
return 0;
}
bool MixerWrap::MicphoneMut_W7(bool bMute,float fVolume)
{
IMMDeviceEnumerator* pEnumerator;
IMMDeviceCollection *pCollection = NULL;
IMMDevice *pDevice=NULL;
IPropertyStore *pProperties=NULL;
IAudioEndpointVolume *pVolumeAPI=NULL;
UINT deviceCount = 0;
GUID m_guidMyContext;
CoInitializeEx(NULL, COINIT_MULTITHREADED);
HRESULT hr=CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL,CLSCTX_ALL, __uuidof(IMMDeviceEnumerator),(void**)&pEnumerator);
if (hr != S_OK)
{
//printf("CoCreateInstance Failed!/n");
return 0;
}
hr = pEnumerator->EnumAudioEndpoints(eCapture /*eRender*/, DEVICE_STATE_ACTIVE, &pCollection);
//hr = pEnumerator->EnumAudioEndpoints( eRender , DEVICE_STATEMASK_ALL , &pCollection );
if (hr != S_OK)
{
// printf("EnumAudioEndpoints Failed!/n");
goto releasepEnumerator;
}
//::MessageBox(NULL,_T("MicphoneMut_W7"),_T("提示信息"),MB_OK | MB_ICONINFORMATION);
hr = pCollection->GetCount(&deviceCount);
if (hr != S_OK)
{
//printf("GetCount Failed!/n");
goto releasepCollection;
}
for (UINT dev=0;devItem(dev,&pDevice);
if (hr == S_OK)
{
hr = pDevice->OpenPropertyStore(STGM_READ,&pProperties);
if (hr == S_OK)
{
PROPVARIANT varName;
PropVariantInit(&varName);
//hr = pProperties->GetValue(PKEY_Device_BusTypeGuid, &varName);
hr = pProperties->GetValue(PKEY_Device_FriendlyName, &varName);
if (hr == S_OK )
{
//if (wcsstr(varName.pwszVal,_T("Line In"))!=NULL)
//if (wcsstr(varName.pwszVal,_T("线路输入"))!=NULL)
//::MessageBox(NULL,varName.pwszVal,_T("提示信息"),MB_OK | MB_ICONINFORMATION);
if (wcsstr(varName.pwszVal,TOWCHAT("麦克风"))!=NULL)
{
hr=pDevice->Activate(__uuidof(IAudioEndpointVolume),CLSCTX_ALL,NULL,(void **)(&pVolumeAPI));
if (hr==S_OK)
{
hr = pVolumeAPI->SetMute(bMute,NULL);
// hr = pVolumeAPI->SetChannelVolumeLevelScalar(0,fVolume,NULL);
pVolumeAPI->SetMasterVolumeLevelScalar((float)fVolume / 100,&m_guidMyContext);
SAFE_RELEASE(pVolumeAPI);
}
}
}
SAFE_RELEASE(pProperties);
}
SAFE_RELEASE(pDevice);
}
}
releasepCollection:
SAFE_RELEASE(pCollection);
releasepEnumerator:
SAFE_RELEASE(pEnumerator);
return 0;
}
int MixerWrap::SelectRecordIn(DWORD dwSrcType)
{
try{
HMIXER m_hmx; //混音器设备句柄
MMRESULT mmr = mixerOpen(&m_hmx, 1, 0, 0L, MIXER_OBJECTF_MIXER);
MIXERLINE mxl;
mxl.cbStruct = sizeof(mxl);
mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
mixerGetLineInfo((HMIXEROBJ)m_hmx, &mxl,MIXER_GETLINEINFOF_COMPONENTTYPE);
LPMIXERCONTROL pmxctrl ;
DWORD cbmxctrls = sizeof(*pmxctrl) * (UINT)mxl.cControls;
pmxctrl = (LPMIXERCONTROL)LocalAlloc(LPTR, cbmxctrls);
MIXERLINECONTROLS mxlctrl={sizeof(mxlctrl),mxl.dwLineID,0,mxl.cControls,sizeof(MIXERCONTROL),pmxctrl};
mixerGetLineControls((HMIXEROBJ)m_hmx, &mxlctrl,MIXER_GETLINECONTROLSF_ALL);
DWORD i;
for(i=0; i < mxl.cControls; i++)
if (MIXERCONTROL_CT_CLASS_LIST == (pmxctrl[i].dwControlType&MIXERCONTROL_CT_CLASS_MASK))
break;
wchar_t temp[50];
swprintf(temp,L"mxl.cControls:%d ",mxl.cControls);
_bstr_t strStr = temp;
// ::MessageBox(NULL,(LPCWSTR)strStr,_T("提示信息"),MB_OK | MB_ICONINFORMATION);
if (i < mxl.cControls)
{
BOOL bOneItemOnly = FALSE;
switch (pmxctrl[i].dwControlType)
{
case MIXERCONTROL_CONTROLTYPE_MUX:
case MIXERCONTROL_CONTROLTYPE_SINGLESELECT:
bOneItemOnly = TRUE;
}
DWORD cChannels = mxl.cChannels, cMultipleItems = 0;
if (MIXERCONTROL_CONTROLF_UNIFORM & pmxctrl[i].fdwControl)
cChannels = 1;
if (MIXERCONTROL_CONTROLF_MULTIPLE & pmxctrl[i].fdwControl)
cMultipleItems = pmxctrl[i].cMultipleItems;
// Get the text description of each item
LPMIXERCONTROLDETAILS_LISTTEXT plisttext =(LPMIXERCONTROLDETAILS_LISTTEXT)
malloc(cChannels * cMultipleItems * sizeof(MIXERCONTROLDETAILS_LISTTEXT));
MIXERCONTROLDETAILS mxcd = {sizeof(mxcd), pmxctrl[i].dwControlID,cChannels,(HWND)cMultipleItems, sizeof(MIXERCONTROLDETAILS_LISTTEXT),(LPVOID) plisttext};
mixerGetControlDetails((HMIXEROBJ)m_hmx, &mxcd,MIXER_GETCONTROLDETAILSF_LISTTEXT);
LPMIXERCONTROLDETAILS_BOOLEAN plistbool =(LPMIXERCONTROLDETAILS_BOOLEAN)
malloc(cChannels * cMultipleItems * sizeof(MIXERCONTROLDETAILS_BOOLEAN));
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
mxcd.paDetails = plistbool;
mixerGetControlDetails((HMIXEROBJ)m_hmx, &mxcd,MIXER_GETCONTROLDETAILSF_VALUE);
wchar_t temp[50];
swprintf(temp,L"cMultipleItems:%d ",cMultipleItems);
_bstr_t strStr = temp;
// ::MessageBox(NULL,(LPCWSTR)strStr,_T("提示信息"),MB_OK | MB_ICONINFORMATION);
for (DWORD j=0; j
三,实现
void CountThread::runWork()
{
{
QMutexLocker locker(&m_mStop);
m_bStop=false;
}
unsigned long currentVolume;
MixerWrap::GetMicphone_W7(currentVolume);//当前麦克风音量
while (1) {
QMutexLocker locker(&m_mStop);
if(m_bStop)
return;
if (!m_streamIn || !m_streamIn->isOpen())
return;
int len1 = m_audioInput->bytesReady();
//if (len1 < 6400) {
// LOG(DEBUG)<<"bytesReady too small"<< len1;
// break;
// }
if(len1>0)
LOG(DEBUG)<<"bytesReady "<< len1;
QByteArray byteArray(len1, 0);//pcm数据
qint64 len2 = m_streamIn->read(byteArray.data(), len1);
const char *pcmdata = byteArray.data();
int db = getPCMDB(pcmdata,len2);
if(db>0){
LOG(DEBUG)<
void CountThread::adjustVolume(int db,unsigned long ¤tVolume)
{
if(m_currentMode==MUTE){ //静音模式 不控制音量
return;
}
int realMinDB = MIN_DB;
int realMaxDB = MAX_DB;
if(m_currentMode==INTERACT){ //互动模式 音量控制在 MIN_DB+10 MAX_DB+10 之间
realMaxDB+=10;
realMinDB+=10;
}
if(db>realMaxDB){//当前分贝 大于上限,则不断降低麦克风音量
MixerWrap::MicphoneMut_W7(false,--currentVolume);
}
if(db