苏紫方璇 发表于 2020-8-15 12:37

利用Core Audio API控制进程音量

最近总是需要把某个进程音量调小,过一会再恢复。调小,没问题,但是恢复却不太方便。
例如系统音量为40,你需要用鼠标或方向键正好把进程的音量也调整为40。多了,系统音量就会增加,导致其他进程声音小。很是烦人。
虽然多一点少一点没什么关系,但是对于我这种强迫症的来说,不可以。

经过多方搜索,找到了一类com接口,可以调整单个进程的音量,于是就了解了一下。
下面直接放代码,如果同样需要学习此方面的内容,请见帖子最下方参考资料

```
#include <windows.h>
#include <stdio.h>
#include <atlcomcli.h>
#include <mmdeviceapi.h>
#include <endpointvolume.h>
#include <audioclient.h>
#include <audiopolicy.h>


const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
const IID IID_IAudioEndpointVolume = __uuidof(IAudioEndpointVolume);
const IID IID_IAudioSessionManager2 = __uuidof(IAudioSessionManager2);
const IID IID_IAudioSessionControl2 = __uuidof(IAudioSessionControl2);
const IID IID_ISimpleAudioVolume = __uuidof(ISimpleAudioVolume);
const IID IID_IAudioSessionControl = __uuidof(IAudioSessionControl);

int main()
{
        CComPtr<IMMDeviceEnumerator> pIMMEnum;
        CComPtr<IAudioEndpointVolume> pEndVol;
        CComPtr<ISimpleAudioVolume> pSimVol;
        CComPtr<IMMDevice> pImmDev;

        HRESULT hr = CoInitialize(NULL);
        //创建IMMDeviceEnumerator
        hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, (LPVOID *)&pIMMEnum);
        if (hr != S_OK)
        {
                printf("error\n");
                getchar();
                return -1;
        }
        //获取IMMDevice
        hr = pIMMEnum->GetDefaultAudioEndpoint(eRender, eConsole, &pImmDev);

        //获取EndpointVolume
        hr = pImmDev->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, (LPVOID *)&pEndVol);

        //获取当前音量
        float vol = 0;
        hr = pEndVol->GetMasterVolumeLevelScalar(&vol);

        printf("主音量:%d%%\n", int((vol + 0.005) * 100));
       
        /////////控制单个进程音量
        CComPtr<IAudioSessionManager2> pSessMag;
        CComPtr<IAudioSessionEnumerator> pSessEnum;
        hr = pImmDev->Activate(IID_IAudioSessionManager2, CLSCTX_ALL, NULL, (LPVOID *)&pSessMag);
        hr = pSessMag->GetSessionEnumerator(&pSessEnum);
        int nCount;
        hr = pSessEnum->GetCount(&nCount);

        CComPtr<IAudioSessionControl> pSessCtrl;
        CComPtr<IAudioSessionControl2> pSessCtrl2;
        DWORD pid;
        for (int i = 0; i < nCount; i++)
        {
                pSessCtrl = NULL;
                pSessCtrl2 = NULL;
                pSimVol = NULL;

                hr = pSessEnum->GetSession(i, &pSessCtrl);
                hr = pSessCtrl->QueryInterface(IID_IAudioSessionControl2, (LPVOID *)&pSessCtrl2);
                hr = pSessCtrl2->GetProcessId(&pid);
                hr = pSessCtrl2->QueryInterface(IID_ISimpleAudioVolume, (LPVOID *)&pSimVol);
                hr = pSimVol->GetMasterVolume(&vol);
                printf("Pid:%d vol:%d%%\n", pid, int((vol + 0.005) * 100));
                //设置所有程序音量为最大
                hr = pSimVol->SetMasterVolume(1.0, NULL);
        }

        CoUninitialize();
        getchar();
        return 0;
}
```

代码比较简单,就是一步一步获取接口,然后调用取数据就可以了
com调用代码写的不多,如果哪里有问题还请指教。

参考资料:https://docs.microsoft.com/en-us/windows/win32/coreaudio/core-audio-apis-in-windows-vista

wushaominkk 发表于 2020-8-20 12:57

宝丽金 发表于 2020-8-17 20:47
学会做事前就先学会做人。

如果有建议可以相互探讨,请不要妄加指责!共创和谐论坛人人有责!

情系吾爱 发表于 2020-8-15 13:00

前排顶贴,虽然看不懂但是我用论坛的FxSound把耳机调到最大就免开音响了:lol懒人福利

syx594 发表于 2020-8-15 13:11

这样的大神必须支持

wu8511128 发表于 2020-8-15 13:50

学习了,大佬

宝丽金 发表于 2020-8-17 01:28

也不见得有傻技术?自以为是!

苏紫方璇 发表于 2020-8-17 13:23

本帖最后由 苏紫方璇 于 2020-8-17 13:24 编辑

宝丽金 发表于 2020-8-17 01:28
也不见得有傻技术?自以为是!
确实,代码确实没啥技术含量,我帖子里也说了,代码很简单。具体代码和叙述方面有什么错误,还请指出,能不阴阳怪气不

宝丽金 发表于 2020-8-17 20:47

苏紫方璇 发表于 2020-8-17 13:23
确实,代码确实没啥技术含量,我帖子里也说了,代码很简单。具体代码和叙述方面有什么错误,还请指出,能 ...

学会做事前就先学会做人。

luxuryang 发表于 2020-8-18 15:58

不错 受教了

__夏雨夜 发表于 2021-1-20 22:25

版主大大 能私发一份MagiCEXIF1.09版本给我么、几个月前在别的帖子给您留言 可能您没看到
页: [1]
查看完整版本: 利用Core Audio API控制进程音量