2 razorenhua Razorenhua 于 2013.11.08 11:40 提问

windows系统音量控制,API函数调用出错

最近在开发一个项目过程中遇到一些问题,问题具体如下:
项目中我需要控制系统音量,也就是麦克风以及扬声器音量,于是我找到了一个CVolume类,代码如下:

//Volume.h
include "MMSystem.h"
define HMIXER_NUM_MAX 10
class CVolume
{
public:
CVolume(void);
public:
~CVolume(void);

public:
HMIXER m_hMixer[HMIXER_NUM_MAX];
BOOL m_barrOpened[HMIXER_NUM_MAX];
HMIXER m_hMixerMic;
HMIXER m_hMixerSpk;
int m_iMixerNums;
MIXERLINE m_MixerLineMicrophone;

BOOL MixerOpen();
void MixerClose();
BOOL m_bIsOpen;
BOOL GetMicrophoneID();
BOOL GetMicrophoneLevel(DWORD* dwLevel, DWORD* dwLevelMax);
BOOL SetMicrophoneLevel(DWORD dwLevel);
BOOL GetSpeakerLevel(DWORD* dwLevel, DWORD* dwLevelMax);
BOOL SetSpeakerLevel(DWORD dwLevel);

};
//Volume.cpp
include "stdafx.h"
include "Volume.h"
CVolume::CVolume(void)
{
m_bIsOpen = FALSE;
m_iMixerNums = 0;
m_hMixerMic = 0;
m_hMixerSpk = 0;
for (int i = 0; i < HMIXER_NUM_MAX; i ++)
m_barrOpened[i] = FALSE;
}

CVolume::~CVolume(void)
{
MixerClose();
}

BOOL CVolume::MixerOpen()
{
m_iMixerNums = mixerGetNumDevs();
if (mixerGetNumDevs() < 1)
return FALSE;
m_iMixerNums = min(m_iMixerNums, HMIXER_NUM_MAX);
m_bIsOpen = FALSE;
for (int i = 0; i < m_iMixerNums; i ++)
{
MMRESULT mmresult = mixerOpen(&m_hMixer[i], (UINT)i, 0, 0, MIXER_OBJECTF_MIXER);

if (mmresult == MMSYSERR_NOERROR)
{
m_barrOpened[i] = TRUE;
m_bIsOpen = TRUE;
}
}
return m_bIsOpen;
}

void CVolume::MixerClose()
{
if (m_bIsOpen)
{
for (int i = 0; i < m_iMixerNums; i ++)
{
if (m_barrOpened[i])
{
mixerClose(m_hMixer[i]);
m_barrOpened[i] = FALSE;
}
}
m_bIsOpen = FALSE;
}
}

BOOL CVolume::GetMicrophoneID()
{
MMRESULT mmresult;
if (!m_bIsOpen)
return FALSE;
m_MixerLineMicrophone.cbStruct = sizeof(m_MixerLineMicrophone);
m_MixerLineMicrophone.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
for (int i = 0; i < m_iMixerNums; i ++)
{
mmresult = mixerGetLineInfo((HMIXEROBJ)m_hMixer[i], &m_MixerLineMicrophone,
MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE);
if (mmresult == MMSYSERR_NOERROR)
{
m_hMixerMic = m_hMixer[i];
break;
}
}
if (m_hMixerMic == 0)
return FALSE;
DWORD dwConnections = m_MixerLineMicrophone.cConnections;
DWORD dwLineID = 0;
for (DWORD i = 0; i < dwConnections; i++)

{

m_MixerLineMicrophone.dwSource = i;

MMRESULT mr = mixerGetLineInfo((HMIXEROBJ)m_hMixerMic, &m_MixerLineMicrophone,

MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_SOURCE);

if (mr != MMSYSERR_NOERROR)

{

break;

}

if (m_MixerLineMicrophone.dwComponentType == MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE)

{

dwLineID = m_MixerLineMicrophone.dwLineID;

break;

}

}

if (dwLineID == 0)

{

return FALSE;

}
return TRUE;
}

BOOL CVolume::GetMicrophoneLevel(DWORD* dwLevel, DWORD* dwLevelMax)
{
MMRESULT mmresult;
MIXERCONTROL mxc;

MIXERLINECONTROLS mxlc;
if (!m_bIsOpen)
return FALSE;
mxlc.cbStruct = sizeof(MIXERLINECONTROLS);

mxlc.dwLineID = m_MixerLineMicrophone.dwLineID;

mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;

mxlc.cControls = 1;

mxlc.cbmxctrl = sizeof(MIXERCONTROL);

mxlc.pamxctrl = &mxc;

mmresult = mixerGetLineControls(

reinterpret_cast(m_hMixerMic),

&mxlc,

MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE);

if (mmresult != MMSYSERR_NOERROR)

return FALSE;
MIXERCONTROLDETAILS_UNSIGNED mxcdVolume;

MIXERCONTROLDETAILS mxcd;

mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);

mxcd.dwControlID = mxc.dwControlID;

mxcd.cChannels = 1;

mxcd.cMultipleItems = 0;

mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);

mxcd.paDetails = &mxcdVolume;

mmresult = mixerGetControlDetails(

reinterpret_cast(m_hMixerMic),

&mxcd,

MIXER_GETCONTROLDETAILSF_VALUE);

if (mmresult != MMSYSERR_NOERROR)

return FALSE;
*dwLevel = mxcdVolume.dwValue;
*dwLevelMax = mxc.Bounds.dwMaximum;
return TRUE;
}

BOOL CVolume::SetMicrophoneLevel(DWORD dwLevel)
{
MMRESULT mmresult;
MIXERCONTROL mxc;

MIXERLINECONTROLS mxlc;
if (!m_bIsOpen)
return FALSE;
mxlc.cbStruct = sizeof(MIXERLINECONTROLS);

mxlc.dwLineID = m_MixerLineMicrophone.dwLineID;

mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;

mxlc.cControls = 1;

mxlc.cbmxctrl = sizeof(MIXERCONTROL);

mxlc.pamxctrl = &mxc;

mmresult = mixerGetLineControls(

reinterpret_cast(m_hMixerMic),

&mxlc,

MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE);

if (mmresult != MMSYSERR_NOERROR)

return FALSE;
MIXERCONTROLDETAILS_UNSIGNED mxcdVolume_Set =

{

dwLevel

};

MIXERCONTROLDETAILS mxcd_Set;

mxcd_Set.cbStruct = sizeof(MIXERCONTROLDETAILS);

mxcd_Set.dwControlID = mxc.dwControlID;

mxcd_Set.cChannels = 1;

mxcd_Set.cMultipleItems = 0;

mxcd_Set.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);

mxcd_Set.paDetails = &mxcdVolume_Set;

mmresult = mixerSetControlDetails(reinterpret_cast(m_hMixerMic),

&mxcd_Set,

MIXER_OBJECTF_HMIXER |

MIXER_SETCONTROLDETAILSF_VALUE);

return (mmresult == MMSYSERR_NOERROR);
}

BOOL CVolume::GetSpeakerLevel(DWORD* dwLevel, DWORD* dwLevelMax)
{
MMRESULT mmr;
MIXERLINE mxl;
MIXERCONTROL mxc;
MIXERLINECONTROLS mxlc;
MIXERCONTROLDETAILS mxcd;
MIXERCONTROLDETAILS_UNSIGNED mxcdVolume;
if (!m_bIsOpen)
return FALSE;
for (int i = 0; i < m_iMixerNums; i ++)
{
mxl.cbStruct = sizeof(mxl);
mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
mmr = mixerGetLineInfo((HMIXEROBJ)m_hMixer[i], &mxl, MIXER_OBJECTF_HMIXER|MIXER_GETLINEINFOF_COMPONENTTYPE);
if ( mmr == MMSYSERR_NOERROR)
{
m_hMixerSpk = m_hMixer[i];
break;
}
}
if (m_hMixerSpk == 0)
return FALSE;
mxlc.cbStruct = sizeof(mxlc);
mxlc.dwLineID = mxl.dwLineID;
mxlc.cControls = mxl.cControls;
mxlc.dwControlID = MIXERCONTROL_CONTROLTYPE_VOLUME;
mxlc.cbmxctrl = sizeof(mxc);
mxlc.pamxctrl = &mxc;
mmr = mixerGetLineControls((HMIXEROBJ)m_hMixerSpk, &mxlc, MIXER_OBJECTF_HMIXER|MIXER_GETLINECONTROLSF_ONEBYTYPE);
mxcd.cbStruct = sizeof(mxcd);
mxcd.dwControlID = mxc.dwControlID;
mxcd.cChannels = 1;
mxcd.cMultipleItems = 0;
mxcd.cbDetails = sizeof(mxcdVolume);
mxcd.paDetails = &mxcdVolume;
mmr = mixerGetControlDetails((HMIXEROBJ)m_hMixerSpk, &mxcd,
MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE);

if (mmr != MMSYSERR_NOERROR)

return FALSE;
*dwLevel = mxcdVolume.dwValue;
*dwLevelMax = mxc.Bounds.dwMaximum;
return TRUE;
}

BOOL CVolume::SetSpeakerLevel(DWORD dwLevelPercent)
{
MMRESULT mmr;
MIXERLINE mxl;
MIXERCONTROL mxc;
MIXERLINECONTROLS mxlc;
MIXERCONTROLDETAILS mxcd;
MIXERCONTROLDETAILS_UNSIGNED mxcdVolume;
if (!m_bIsOpen)
return FALSE;
mxl.cbStruct = sizeof(mxl);
mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
mmr = mixerGetLineInfo((HMIXEROBJ)m_hMixerSpk, &mxl, MIXER_OBJECTF_HMIXER|MIXER_GETLINEINFOF_COMPONENTTYPE);
mxlc.cbStruct = sizeof(mxlc);
mxlc.dwLineID = mxl.dwLineID;
mxlc.cControls = mxl.cControls;
mxlc.dwControlID = MIXERCONTROL_CONTROLTYPE_VOLUME;
mxlc.cbmxctrl = sizeof(mxc);
mxlc.pamxctrl = &mxc;
mmr = mixerGetLineControls((HMIXEROBJ)m_hMixerSpk, &mxlc, MIXER_OBJECTF_HMIXER|MIXER_GETLINECONTROLSF_ONEBYTYPE);
MIXERCONTROLDETAILS_UNSIGNED mxcdVolume_Set =

{

dwLevelPercent

};

mxcd.cbStruct = sizeof(mxcd);
mxcd.dwControlID = mxc.dwControlID;
mxcd.cChannels = 1;
mxcd.cMultipleItems = 0;
mxcd.cbDetails = sizeof(mxcdVolume);
mxcd.paDetails = &mxcdVolume_Set;
mmr = mixerSetControlDetails((HMIXEROBJ)m_hMixerSpk, &mxcd,
MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE);

return (mmr == MMSYSERR_NOERROR);

}
可以看到这个类结构还是非常简单明了的,但是却出现了意想不到的错误,我在基于对话框项目程序中调用volumeControl.MixerOpen()函数时,volumeControl是我添加的CVolume类,编译连接都没有出现问题,在运行程序时出现:Unhandled exception at 0x0002bfc0 in CSHowlingSupress.exe: 0xC0000005: Access violation.
我知道问题肯定是出现在MixerOpen函数中,于是我在MixerOpen入口处设置断点,这时我发现mixerGetNumDevs函数 CXX0017: Error: symbol "mixerGetNumDevs" not found。 也就是说这个函数根明就没有申明,调用了空指针。但是我实在搞不明白,mixerGetNumDevs不是WIN API 函数吗,需要用的库函数Winmm.lib我也加在项目属性中添加了,怎么还会出现这种问题呢,我无语了。我电脑安装了有两块声卡,Realtek High Definition Audio和RME Fireface UC。哪位大神能帮我看看啊,感激不尽!

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!