使用Windows API控制语音输入音量

语音输入的音量控制比较麻烦,写此文章以增强记忆。

// 打开mixer
	MMRESULT rc;
	HMIXER hMixer;
	UINT mixerID;
	rc = mixerGetID((HMIXEROBJ)hWaveIn,&mixerID,MIXER_OBJECTF_HWAVEIN);
	rc = mixerOpen(&hMixer,mixerID,(DWORD)this->m_hWnd,0,CALLBACK_WINDOW);
	if (rc != MMSYSERR_NOERROR)
	{
		MessageBox(_T("mixerOpen Error!"));
		return;
	}
	// mixerGetLineInfo
	MIXERLINE mixerLine;
	ZeroMemory(&mixerLine,sizeof(MIXERLINE));
	mixerLine.cbStruct	= sizeof(MIXERLINE);
	mixerLine.dwComponentType	= MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
	rc = mixerGetLineInfo((HMIXEROBJ)hMixer, &mixerLine,MIXER_GETLINEINFOF_COMPONENTTYPE);
	if (rc != MMSYSERR_NOERROR)
	{
		MessageBox(_T("mixerGetLineInfo Error!"));
		return;
	}

	// 获取麦克风的LineID
	DWORD dwConnections = mixerLine.cConnections;
	DWORD dwLineID = -1;
	for (DWORD i=0; i<dwConnections; i++)
	{
		mixerLine.dwSource = i;
		rc = mixerGetLineInfo((HMIXEROBJ)hMixer,&mixerLine,MIXER_OBJECTF_HMIXER|MIXER_GETLINEINFOF_SOURCE);
		if ( rc == MMSYSERR_NOERROR )
		{
			if (mixerLine.dwComponentType == MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE)
			{
				dwLineID = mixerLine.dwLineID;
				break;
			}
		}
	}
	if (dwLineID == -1)
	{
		return;
	}
	// mixerGetLineControls
	MIXERCONTROL mxControl;
	MIXERLINECONTROLS mxLineControls;	
	ZeroMemory(&mxLineControls,sizeof(mxLineControls));
	mxLineControls.cbStruct		= sizeof(mxLineControls);
	mxLineControls.dwLineID		= dwLineID;
	mxLineControls.dwControlType= MIXERCONTROL_CONTROLTYPE_VOLUME;
	mxLineControls.cControls	= 1;
	mxLineControls.cbmxctrl		= sizeof(mxControl);
	mxLineControls.pamxctrl		= &mxControl;
	ZeroMemory(&mxControl,sizeof(mxControl));
	mxControl.cbStruct	= sizeof(mxControl);
	rc = mixerGetLineControls((HMIXEROBJ)hMixer,&mxLineControls,MIXER_GETLINECONTROLSF_ONEBYTYPE);
	if (rc != MMSYSERR_NOERROR)
	{
		MessageBox(_T("mixerGetLineControls Error!"));
		return;
	}
	// get volume
	MIXERCONTROLDETAILS mxControlDetails;
	MIXERCONTROLDETAILS_SIGNED volStruct;
	ZeroMemory(&mxControlDetails,sizeof(mxControlDetails));
	mxControlDetails.cbStruct	= sizeof(mxControlDetails);
	mxControlDetails.dwControlID= mxControl.dwControlID;
	mxControlDetails.cChannels	= 1;
	mxControlDetails.cbDetails	= sizeof(volStruct);
	mxControlDetails.paDetails	= &volStruct;
	rc = mixerGetControlDetails((HMIXEROBJ)hMixer,&mxControlDetails,MIXER_GETCONTROLDETAILSF_VALUE);
	if (rc != MMSYSERR_NOERROR)
	{
		MessageBox(_T("mixerGetControlDetails Error!"));
		return;
	}
	long step = (mxControl.Bounds.lMaximum - mxControl.Bounds.lMinimum) / 100;
	int index = (volStruct.lValue - mxControl.Bounds.lMinimum) / step;
	//set volume
	volStruct.lValue = 65535;
	ZeroMemory(&mxControlDetails,sizeof(mxControlDetails));
	mxControlDetails.cbStruct	= sizeof(mxControlDetails);
	mxControlDetails.dwControlID= mxControl.dwControlID;
	mxControlDetails.cChannels	= 1;
	mxControlDetails.cbDetails	= sizeof(volStruct);
	mxControlDetails.paDetails	= &volStruct;
	rc = mixerSetControlDetails((HMIXEROBJ)hMixer,&mxControlDetails,MIXER_GETCONTROLDETAILSF_VALUE);
	if (rc != MMSYSERR_NOERROR)
	{
		MessageBox(_T("mixerGetControlDetails Error!"));
		return;
	}

第四行,获取hWaveIn句柄的代码如下:

// 检查设备
	if ( ! waveInGetNumDevs() )
	{
		MessageBeep(MB_ICONEXCLAMATION);
		MessageBox(_T("找不到语音输入设备!"));
		return FALSE;
	}

	// format of voice: 16 bits,11.025KHz,Mono audio
         WAVEFORMATEX format;
	format.cbSize			= 0;
	format.nAvgBytesPerSec	= 11025;	//数据率
	format.nBlockAlign		= 1;		//每样点的字节数
	format.nChannels		= 1;		//单声道,Mono/立体声
	format.nSamplesPerSec	= 11025;	//采样率
	format.wBitsPerSample	= 8;		//采样精度
	format.wFormatTag		= WAVE_FORMAT_PCM;

// 打开语音输入设备
		if ( (result=waveInOpen(&hWaveIn, WAVE_MAPPER,&format,(DWORD)hwnd, 0, CALLBACK_WINDOW)) != MMSYSERR_NOERROR )
		{
			TCHAR szErrorText[100] = {0};
			if (waveInGetErrorText(result,szErrorText,sizeof(szErrorText)) == MMSYSERR_NOERROR)
			{
				MessageBeep(MB_ICONEXCLAMATION);
				MessageBox(szErrorText,_T("WaveIn Open Error!"),MB_ICONEXCLAMATION|MB_OK);
			} 
			else
			{
				MessageBeep(MB_ICONEXCLAMATION);
				MessageBox(_T("Unknown Error"),_T("WaveIn Open Error!"),MB_ICONEXCLAMATION|MB_OK);
			}
			hWaveIn = NULL;
			return;
		}

当然使用完了别忘了关闭:

waveInReset(hWaveIn);
		waveInClose(hWaveIn);

		hWaveIn = NULL;

当然,一般情况下,语音输入设备的ID号是0,所以也可以直接用以下代码打开mixer设备:

rc = mixerOpen(&hmx,0,(DWORD)this->m_hWnd,0,CALLBACK_WINDOW);

mixerOpen函数中使用CALLBACK_WINDOW的目的是在改变了系统输入音量后能够及时的在窗口中更新。其对应的Windows消息是MM_MIXM_CONTROL_CHANGE.

//添加响应消息宏
ON_MESSAGE(MM_MIXM_CONTROL_CHANGE,OnVolumeChanged)


LRESULT CSendVoiceDlg::OnVolumeChanged(WPARAM wParam, LPARAM lParam)
{
    // 此消息有两个参数
     // 第一个参数WPARAM, 表示MIXER设备句柄,即上面代码中的hMixer
    // 第二个参数LPARAM, 表示MIXERCONTROL结构中的dwControlID成员。
    return 0;
}


//下面是一个例子
LRESULT CSendVoiceDlg::OnVolumeChanged(WPARAM wParam, LPARAM lParam)
{
	CSliderCtrl* pSlider = (CSliderCtrl*)GetDlgItem(IDC_SLIDER1);
	HMIXER hMixer = (HMIXER)wParam;
	DWORD dwControlID = (DWORD)lParam;

	MIXERCONTROLDETAILS mxControlDetails;
	MIXERCONTROLDETAILS_SIGNED volStruct;
	ZeroMemory(&mxControlDetails,sizeof(mxControlDetails));
	mxControlDetails.cbStruct	= sizeof(mxControlDetails);
	mxControlDetails.dwControlID= dwControlID;
	mxControlDetails.cChannels	= 1;
	mxControlDetails.cbDetails	= sizeof(volStruct);
	mxControlDetails.paDetails	= &volStruct;
	MMRESULT rc = mixerGetControlDetails((HMIXEROBJ)hMixer,&mxControlDetails,MIXER_GETCONTROLDETAILSF_VALUE);
	if (rc != MMSYSERR_NOERROR)
	{
		MessageBox(_T("mixerGetControlDetails Error!"));
		return 0;
	}
// 	long step = (mxControl.Bounds.lMaximum - mxControl.Bounds.lMinimum) / 100;
// 	int index = (volStruct.lValue - mxControl.Bounds.lMinimum) / step;

	pSlider->SetPos(volStruct.lValue);
	return 0;
}

 

你可能感兴趣的:(使用Windows API控制语音输入音量)