1

While I have read several solutions to changing the volume using Powershell:

How can I mute/unmute my sound from PowerShell

Change audio level from powershell?

I couldnt find anything that changes the balance. Something like:

#Sets left channel volume to 20%
Set-Speaker -LeftChannel 20

#Sets right channel volume to 80%
Set-Speaker -RightChannel 80

Just to be clear, Im talking about modifying this:

enter image description here

I need it to set a startup script that maintains my current (or last) volume but keeps the left channel always at 20%

Thanks

riahc3
  • 857
  • 4
  • 10
  • 23

2 Answers2

1

To take zett42's functional collection of ideas and a small mistake at the end and actually put it together into an answer:

  1. Get the code from the AudioManager.cs gist and put it in a file AudioManager.cs where the script will be
  2. In that AudioManager.cs file, make GetMasterVolumeObject() public so it is more convenient to use from a helper class, by replacing the line:
private static IAudioEndpointVolume GetMasterVolumeObject()

with

public static IAudioEndpointVolume GetMasterVolumeObject()
  1. Now in your PowerShell script you can do:
Add-Type -TypeDefinition $(
    $(Get-Content -Path "AudioManager.cs" -Raw) + 
    @'
        public static class AudioSettings { 
                public static void SetChannelVolumeLevel(uint channelNumber, float newLevel)
                {
                    VideoPlayerController.IAudioEndpointVolume masterVol = null;
                    try
                    {
                        masterVol = VideoPlayerController.AudioManager.GetMasterVolumeObject();
                        if (masterVol == null)
                            return;

                        masterVol.SetChannelVolumeLevelScalar(channelNumber, newLevel/100, Guid.Empty);
                    }
                    finally
                    {
                        if (masterVol != null)
                            Marshal.ReleaseComObject(masterVol);
                    }
                }               
                
        }       
'@)

[AudioSettings]::SetChannelVolumeLevel(0, 60)
[AudioSettings]::SetChannelVolumeLevel(1, 40)
rakslice
  • 8,742
  • 4
  • 53
  • 57
0

As explained here, you need to call SetChannelVolumeLevel or SetChannelVolumeLevelScalar method of IAudioEndpointVolume. The interop method is included in this Gist, but it is missing a convenient wrapper method.

For getting started, you need to include the C# code in PowerShell using Add-Type:

Add-Type -TypeDefinition @'
-paste C# code here-
'@

Add this method to class AudioManager:

        /// <summary>
        /// Sets the channel volume to a specific level
        /// </summary>
        /// <param name="channelNumber">Channel number, which can be 0..(numberOfChannels-1)</param>
        /// <param name="newLevel">Value between 0 and 100 indicating the desired scalar value of the volume</param>
        public static void SetChannelVolumeLevel(uint channelNumber, float newLevel)
        {
            IAudioEndpointVolume masterVol = null;
            try
            {
                masterVol = GetMasterVolumeObject();
                if (masterVol == null)
                    return;

                masterVol.SetChannelVolumeLevelScalar(channelNumber, newLevel/100, Guid.Empty);
            }
            finally
            {
                if (masterVol != null)
                    Marshal.ReleaseComObject(masterVol);
            }
        }      

I've inserted it before line private static IAudioEndpointVolume GetMasterVolumeObject(), but it doesn't really matter where you put it within the class.

Now you can call it from PowerShell like this:

[VideoPlayerController.AudioManager]::SetChannelVolumeLevelScalar(0, 60)
[VideoPlayerController.AudioManager]::SetChannelVolumeLevelScalar(1, 40)

On my system it moves both left and right volume equally but I propably suffer from locked balance. There is a registry tweak described here which didn't work for me though.

zett42
  • 25,437
  • 3
  • 35
  • 72