Set windows volume from 0 to 100

Viewed 151

I want to set the volume of an audio endpoint like in windows directly from 0 to 100

public override void SetVolume(int volume) {
    NativeInterfaces.IMMDeviceEnumerator enumerator = NativeClasses.ComObjectFactory.CreateInstance(new Guid(NativeGuids.MM_DEVICE_ENUMERATOR)) as NativeInterfaces.IMMDeviceEnumerator;
    
    enumerator.GetDefaultAudioEndpoint(
        NativeEnums.EDataFlow.eCapture | NativeEnums.EDataFlow.eRender,
        NativeEnums.ERole.eConsole,
        out NativeInterfaces.IMMDevice device
    );

    device.Activate(new Guid(NativeGuids.I_AUDIO_ENDPOINT_VOLUME), 0x1, IntPtr.Zero, out object volumeObj);
    NativeInterfaces.IAudioEndpointVolume audioEndpointVolume = volumeObj as NativeInterfaces.IAudioEndpointVolume;
    audioEndpointVolume.SetMasterVolumeLevelScalar(volume / 100.0f, new Guid());
}

When I run this code my volume is still on 50 although I passed 60 as a parameter. When I call GetMasterVolumeLevelScalar it outputs 0.6 so the code worked but it seems like I use the wrong method. So how to set between 0 and 100?

EDIT: Volume Mixer enter image description here

1 Answers

Solution 1: Master Volume

public override void SetMasterVolume(int volume) {
    NativeInterfaces.IMMDeviceEnumerator enumerator = NativeClasses.ComObjectFactory.CreateInstance(new Guid(NativeGuids.MM_DEVICE_ENUMERATOR)) as NativeInterfaces.IMMDeviceEnumerator;

    enumerator.GetDefaultAudioEndpoint(
        NativeEnums.EDataFlow.eRender,
        NativeEnums.ERole.eConsole,
        out NativeInterfaces.IMMDevice device
    );

    device.Activate(new Guid(NativeGuids.I_AUDIO_ENDPOINT_VOLUME), 0x1, IntPtr.Zero, out object volumeObj);
    NativeInterfaces.IAudioEndpointVolume audioEndpointVolume = volumeObj as NativeInterfaces.IAudioEndpointVolume;
    audioEndpointVolume.SetMasterVolumeLevelScalar(volume / 100.0f, new Guid());
}

Solution 2: Process specific volume

public override void SetVolume(List<int> pids, int volume) {
    NativeInterfaces.IMMDeviceEnumerator enumerator = NativeClasses.ComObjectFactory.CreateInstance(new Guid(NativeGuids.MM_DEVICE_ENUMERATOR)) as NativeInterfaces.IMMDeviceEnumerator;

    enumerator.EnumAudioEndpoints(
        NativeEnums.EDataFlow.eRender,
        0x00000001,
        out NativeInterfaces.IMMDeviceCollection deviceCollection
    );

    deviceCollection.GetCount(out uint collectionCount);

    for (uint i = 0; i < collectionCount; i++) {
        deviceCollection.Item(i, out NativeInterfaces.IMMDevice device);
        device.Activate(new Guid(NativeGuids.I_AUDIO_SESSION_MANAGER_2), 0, IntPtr.Zero, out object obj);
        NativeInterfaces.IAudioSessionManager2 audioSessionManager = obj as NativeInterfaces.IAudioSessionManager2;

        audioSessionManager.GetSessionEnumerator(out NativeInterfaces.IAudioSessionEnumerator sessionEnumerator);
        sessionEnumerator.GetCount(out int count);

        for (int j = 0; j < count; j++) {
            sessionEnumerator.GetSession(j, out NativeInterfaces.IAudioSessionControl control);
            NativeInterfaces.IAudioSessionControl2 control2 = control as NativeInterfaces.IAudioSessionControl2;
            control2.GetProcessId(out int pid);

            if (pids.Contains(pid)) {
                NativeInterfaces.ISimpleAudioVolume audioVolume = control as NativeInterfaces.ISimpleAudioVolume;
                audioVolume.SetMasterVolume(volume / 100.0f, Guid.Empty);
            }
        }
    }
}

Note: Solution 2 sets the volume relative to the current master volume. So if the current master volume is at 50 and you set the volume of an audio session to 50 it is set to 25.

Related