获取与设置windows系统下音频设备音量

一、获取设备音量

不同系统获取音量的方法是有差别的,比如vista和win7获取音量的方式就是不同的,因此,我们应该首先获取系统的信息,然后根据系统信息,用其对应的方法获取音量。

1、OSVERSIONINFO

系统信息结构体

以下结构体均用于检索或设置系统信息。

ANIMATIONINFO
HW_PROFILE_INFO
MINIMIZEDMETRICS
NONCLIENTMETRICS
OSVERSIONINFO
SYSTEM_INFO 

使用说明
       在OSVERSIONINFO数据结构中包含操作系统版本信息。这些信息包括主要和次要版本号,一个内部版本号,一个平台标识符,以及操作系统的说明性文本。GetVersionEx函数将使用这个结构体。
 
结构体原型:

typedef struct _OSVERSIONINFO
{
    DWORD dwOSVersionInfoSize;
    DWORD dwMajorVersion;
    DWORD dwMinorVersion;
    DWORD dwBuildNumber;
    DWORD dwPlatformId;
    TCHAR szCSDVersion[ 128 ];
} OSVERSIONINFO;
 

成员说明:
1)dwOSVersionInfoSize
       以字节为单位,指定这个数据结构的大小。须在调用GetVersionEx(OSVERSIONINFO)函数之前,将这个成员设置为sizeof(OSVERSIONINFO)。
2)dwMajorVersion
       标识操作系统的主版本号。例如,对于Windows NT 3.51版,其主版本号为3;对于Windows NT 4.0版,其主版本号为4。
3)dwMinorVersion
       标识操作系统的次要版本号。例如,对于Windows NT 3.51版,其次要版本号为51;对于Windows NT 4.0版本,其次要版本号为0。
4)dwBuildNumber
       Windows NT:标识操作系统的内部版本号。
Windows 95:低位字标识操作系统数的内部版本号。高位字包含了主要和次要版本号。
5)dwPlatformId
       标识操作系统平台。这个成员可以是下列值之一:
6)szCSDVersion
       Windows NT:包含一个以NULL结尾的字符串,如“Service Pack 3”,就表明系统上安装了最新的Service Pack。如果没有安装Service Pack,该字符串为空。
     Windows 95:包含一个以NULL结尾的字符串,提供了对操作系统的任意补充信息。


应用:

OSVERSIONINFO osVer;
	osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	::GetVersionEx( &osVer );
	if( osVer.dwMajorVersion==6 )
	{
        GetAudioOuputVolum_Vita();
    }
    else
    {
        GetAudioOuputVolum_Win7();
    }

2、vista下获取设备音量

int GetAudioOutputVolumn_Vista(const std::string &deviceName)
{
    IMMDeviceEnumerator* pEnumerator;
    IMMDeviceCollection* pCollection = NULL;
    IMMDevice *pDevice = NULL;
    IPropertyStore *pProperties=NULL;  
    IAudioEndpointVolume *pVolumeAPI=NULL;  
    UINT deviceCount = 0;

    float fVolume = -1;

    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_STATE_ACTIVE , &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( SUCCEEDED(hr) )
                {
                    if (varName.vt != VT_LPWSTR || 
                        (wstr2str(varName.pwszVal).find(deviceName) != 0)) //传入的值可能不完整,需要前部分匹配
                    {
                        continue;
                    }
                    hr=pDevice->Activate(__uuidof(IAudioEndpointVolume),CLSCTX_ALL,NULL,(void **)(&pVolumeAPI));  
                    if (hr==S_OK)  
                    {  
                        hr = pVolumeAPI->GetMasterVolumeLevelScalar( &fVolume );
                        if (S_OK == hr) break;
                    } 
                }

                SAFE_RELEASE(pProperties);  
            }  

            SAFE_RELEASE(pDevice);  
        }  
    }  

releasepCollection:  
    SAFE_RELEASE(pCollection);  
releasepEnumerator:  
    SAFE_RELEASE(pEnumerator);  
    return  fVolume*100;
}

3、win7下获取设备音量

windows下主要有这几个API:

mixerOpen和mixerClose函数用来打开和关闭混音器设备 

mixerGetNumDevs可以确定系统中有多少混音器设备 

mixerGetDevCaps函数可以确定混音器设备的能力 

mixerGetLineInfo可以检索指定音频线路的信息 

mixerGetLineControls用于检索一个或者多个与音频线路相关的控制的通用信息 

mixerGetControlDetails用于检索与某个音频线路相关的一个控制的属性 

mixerSetControlDetails用于设置制定控制的属性。


int GetAudioOutputVolumn_Win7(const std::string &deviceName)
{
    MMRESULT          rc;     // 多媒体函数返回结果变量
    HMIXER            hMixer; // 混合器设备句柄
    MIXERLINE         mxl;    // 音频线路标准状态信息结构体
    MIXERLINECONTROLS mxlc;   // 音频线路控制器集合信息结构体
    MIXERCONTROL      mxc;    // 单个音频线路控制器信息结构体

    // 打开混合器设备
    rc = mixerOpen(&hMixer, // 返回的设备句柄
        0,       // 单声卡的设备ID为零
        0,       // 不使用回调机制
        0,       // 回调函数参数
        0);      // MIXER_OBJECTF_MIXER宏的值,表示任选有效设备ID

    // 打开混合器设备无错的话,则
    if (MMSYSERR_NOERROR == rc)
    {
        // MIXERLINE 结构体变量清零
        ZeroMemory(&mxl, sizeof(MIXERLINE));

        mxl.cbStruct = sizeof(MIXERLINE); // 微软用此办法判断版本
        // 指出需要获取的通道,声卡的音频输出用MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
        mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;

        // 取得混合器设备的指定线路信息
        rc = mixerGetLineInfo((HMIXEROBJ)hMixer,
            &mxl,
            // 取得MIXERLINE::dwComponentType指定类型的第一个音频线路信息
            MIXER_GETLINEINFOF_COMPONENTTYPE);

        // 取得混合器设备的指定线路信息成功的话,则
        if (MMSYSERR_NOERROR == rc)
        {
            // MIXERCONTROL 结构体变量清零
            ZeroMemory(&mxc, sizeof(MIXERCONTROL));

            mxc.cbStruct = sizeof(mxc); // 微软用此办法判断版本

            // MIXERLINECONTROLS 结构体变量清零
            ZeroMemory(&mxlc, sizeof(MIXERLINECONTROLS));

            mxlc.cbStruct = sizeof(mxlc); // 微软用此办法判断版本

            mxlc.dwLineID = mxl.dwLineID; // 上面取得的声卡音频输出线路标识
            // 控制类型为控制音量
            mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
            mxlc.cControls = 1;          // 使用 MIXERCONTROL 结构体变量个数
            mxlc.pamxctrl = &mxc;        // MIXERCONTROL 结构体变量指针
            mxlc.cbmxctrl = sizeof(mxc); // MIXERCONTROL 结构体变量字节大小

            // 取得控制器信息
            rc = mixerGetLineControls((HMIXEROBJ)hMixer,
                &mxlc,
                MIXER_GETLINECONTROLSF_ONEBYTYPE);

            // 取得控制器信息成功的话,则
            if (MMSYSERR_NOERROR == rc)
            {
                // 获取控制器中的值的音量范围:mxc.Bounds.lMinimum到mxc.Bounds.lMaximum.
                MIXERCONTROLDETAILS        mxcd;      // 控制器的状态信息
                MIXERCONTROLDETAILS_SIGNED volStruct; // 音量结构体变量(就一个成员量)

                // MIXERCONTROLDETAILS 结构体变量清零
                ZeroMemory(&mxcd, sizeof(mxcd));

                mxcd.cbStruct = sizeof(mxcd);       // 微软用此办法判断版本
                mxcd.dwControlID = mxc.dwControlID; // 上面取得的控制器标识
                mxcd.paDetails = &volStruct;        // 音量结构体变量指针
                mxcd.cbDetails = sizeof(volStruct); // 音量结构体变量字节大小
                mxcd.cChannels = 1;                 // 取得或设置全部通道

                //  获取控制器中的值的音量范围:mxc.Bounds.lMinimum到mxc.Bounds.lMaximum. 

                // 获得音量值
                rc = mixerGetControlDetails((HMIXEROBJ)hMixer,
                    &mxcd,
                    MIXER_GETCONTROLDETAILSF_VALUE);

                if (MMSYSERR_NOERROR == rc)
                {
                    long step = ( mxc.Bounds.lMaximum - mxc.Bounds.lMinimum ) /100;

                    int index = ( volStruct.lValue - mxc.Bounds.lMinimum) /step ;
                    printf("音量:%X", volStruct.lValue);
                    return index;
                }
            }
        }
    }
}

二、设置设备音量

设置音量和获取音量大部分代码都是相同的,就几句不一样。

1、Vista下设置设备音量

int SetAudioOutputVolum_Vista(int volumnIndex)
{
    IMMDeviceEnumerator* pEnumerator;
    IMMDeviceCollection* pCollection = NULL;
    IMMDevice *pDevice = NULL;
    IPropertyStore *pProperties=NULL;  
    IAudioEndpointVolume *pVolumeAPI=NULL;  
    UINT deviceCount = 0;

    float fVolume = -1;

    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_STATE_ACTIVE , &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( SUCCEEDED(hr) )
                {
                    hr=pDevice->Activate(__uuidof(IAudioEndpointVolume),CLSCTX_ALL,NULL,(void **)(&pVolumeAPI));  
                    if (hr==S_OK)  
                    {  
                        float volumnLevel = (float)volumnIndex /100;
                        hr = pVolumeAPI->SetMasterVolumeLevelScalar( volumnLevel, NULL );
                    } 
                }
                SAFE_RELEASE(pProperties);  
            }  
            SAFE_RELEASE(pDevice);  
        }  
    }  
releasepCollection:  
    SAFE_RELEASE(pCollection);  
releasepEnumerator:  

    SAFE_RELEASE(pEnumerator);  
    return  fVolume*100;
}


2、Win7下设置设备音量

int SetAudioOutputVolum_Win7(int volumnIndex)
{

    MMRESULT          rc;     // 多媒体函数返回结果变量
    HMIXER            hMixer; // 混合器设备句柄
    MIXERLINE         mxl;    // 音频线路标准状态信息结构体
    MIXERLINECONTROLS mxlc;   // 音频线路控制器集合信息结构体
    MIXERCONTROL      mxc;    // 单个音频线路控制器信息结构体

    // 打开混合器设备
    rc = mixerOpen(&hMixer, // 返回的设备句柄
        0,       // 单声卡的设备ID为零
        0,       // 不使用回调机制
        0,       // 回调函数参数
        0);      // MIXER_OBJECTF_MIXER宏的值,表示任选有效设备ID

    // 打开混合器设备无错的话,则
    if (MMSYSERR_NOERROR == rc)
    {
        // MIXERLINE 结构体变量清零
        ZeroMemory(&mxl, sizeof(MIXERLINE));

        mxl.cbStruct = sizeof(MIXERLINE); // 微软用此办法判断版本
        // 指出需要获取的通道,声卡的音频输出用MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
        mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;

        // 取得混合器设备的指定线路信息
        rc = mixerGetLineInfo((HMIXEROBJ)hMixer,
            &mxl,
            // 取得MIXERLINE::dwComponentType指定类型的第一个音频线路信息
            MIXER_GETLINEINFOF_COMPONENTTYPE);

        // 取得混合器设备的指定线路信息成功的话,则
        if (MMSYSERR_NOERROR == rc)
        {
            // MIXERCONTROL 结构体变量清零
            ZeroMemory(&mxc, sizeof(MIXERCONTROL));

            mxc.cbStruct = sizeof(mxc); // 微软用此办法判断版本

            // MIXERLINECONTROLS 结构体变量清零
            ZeroMemory(&mxlc, sizeof(MIXERLINECONTROLS));

            mxlc.cbStruct = sizeof(mxlc); // 微软用此办法判断版本

            mxlc.dwLineID = mxl.dwLineID; // 上面取得的声卡音频输出线路标识
            // 控制类型为控制音量
            mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
            mxlc.cControls = 1;          // 使用 MIXERCONTROL 结构体变量个数
            mxlc.pamxctrl = &mxc;        // MIXERCONTROL 结构体变量指针
            mxlc.cbmxctrl = sizeof(mxc); // MIXERCONTROL 结构体变量字节大小

            // 取得控制器信息
            rc = mixerGetLineControls((HMIXEROBJ)hMixer,
                &mxlc,
                MIXER_GETLINECONTROLSF_ONEBYTYPE);

            // 取得控制器信息成功的话,则
            if (MMSYSERR_NOERROR == rc)
            {
                // 获取控制器中的值的音量范围:mxc.Bounds.lMinimum到mxc.Bounds.lMaximum.
                MIXERCONTROLDETAILS        mxcd;      // 控制器的状态信息
                MIXERCONTROLDETAILS_SIGNED volStruct; // 音量结构体变量(就一个成员量)

                // MIXERCONTROLDETAILS 结构体变量清零
                ZeroMemory(&mxcd, sizeof(mxcd));

                mxcd.cbStruct = sizeof(mxcd);       // 微软用此办法判断版本
                mxcd.dwControlID = mxc.dwControlID; // 上面取得的控制器标识
                mxcd.paDetails = &volStruct;        // 音量结构体变量指针
                mxcd.cbDetails = sizeof(volStruct); // 音量结构体变量字节大小
                mxcd.cChannels = 1;                 // 取得或设置全部通道

                //  获取控制器中的值的音量范围:mxc.Bounds.lMinimum到mxc.Bounds.lMaximum. 

                // 获得音量值
                rc = mixerGetControlDetails((HMIXEROBJ)hMixer,
                    &mxcd,
                    MIXER_GETCONTROLDETAILSF_VALUE);

                if (MMSYSERR_NOERROR == rc)
                {
                    long step = ( mxc.Bounds.lMaximum - mxc.Bounds.lMinimum ) /100;
                    volStruct.lValue = volumnIndex*step;	 // 想要设置的值  
                    rc = mixerSetControlDetails((HMIXEROBJ)hMixer,  
                        &mxcd,  
                        MIXER_SETCONTROLDETAILSF_VALUE);  

                    if (MMSYSERR_NOERROR == rc)  
                    {  
                        return 1;
                    }  
                }
            }
        }
    }
}

 
  



你可能感兴趣的:(c++,Windows,C++编程)