# SoundSet

Changes various settings of a sound device (master mute, master volume, etc.)

SoundSet, NewSetting [, ComponentType, ControlType, DeviceNumber]

#### Parameters

NewSetting | Percentage number between -100 and 100 inclusive (it can be a floating point number or expression). If the number begins with a plus or minus sign, the current setting will be adjusted up or down by the indicated amount. Otherwise, the setting will be set explicitly to the level indicated by NewSetting. For ControlTypes with only two possible settings -- namely ONOFF, MUTE, MONO, LOUDNESS, STEREOENH, and BASSBOOST -- any positive number will turn on the setting and a zero will turn it off. However, if the number begins with a plus or minus sign, the setting will be toggled (set to the opposite of its current state).
ComponentType | If omitted or blank, it defaults to the word MASTER. Otherwise, it can be one of the following words: MASTER (synonymous with SPEAKERS), DIGITAL, LINE, MICROPHONE, SYNTH, CD, TELEPHONE, PCSPEAKER, WAVE, AUX, ANALOG, HEADPHONES, or N/A. If the sound device lacks the specified ComponentType, ErrorLevel will indicate the problem. The component labeled Auxiliary in some mixers might be accessible as ANALOG rather than AUX. If a device has more than one instance of ComponentType (two of type LINE, for example), usually the first contains the playback settings and the second contains the recording settings. To access an instance other than the first, append a colon and a number to this parameter. For example: Analog:2 is the second instance of the analog component.
ControlType | If omitted or blank, it defaults to VOLUME. Otherwise, it can be one of the following words: VOLUME (or VOL), ONOFF, MUTE, MONO, LOUDNESS, STEREOENH, BASSBOOST, PAN, QSOUNDPAN, BASS, TREBLE, EQUALIZER, or the number of a valid control type (see soundcard analysis script). If the specified ComponentType lacks the specified ControlType, ErrorLevel will indicate the problem.
DeviceNumber | If this parameter is omitted, it defaults to 1 (the first sound device), which is usually the system's default device for recording and playback. Specify a number higher than 1 to operate upon a different sound device. This parameter can be an expression.

#### ErrorLevel

ErrorLevel is set to 0 if the command succeeded. Otherwise, it is set to one of the following phrases:

Invalid Control Type or Component Type
Can't Open Specified Mixer
Mixer Doesn't Support This Component Type
Mixer Doesn't Have That Many of That Component Type
Component Doesn't Support This Control Type
Can't Get Current Setting
Can't Change Setting

#### Remarks

On Windows Vista or later, SoundSet and SoundGet affect only the script itself (this may be resolved in a future version). There are at least two ways to work around this:

1) In the properties dialog for the file "AutoHotkey.exe" (or a compiled script), change the compatibility setting to "Windows XP".

2) Have the script send volume-control keystrokes to change the master volume for the entire system. For example:

    Send {Volume_Up}  ; Raise the master volume by 1 interval (typically 5%).
    Send {Volume_Down 3}  ; Lower the master volume by 3 intervals.
    Send {Volume_Mute}  ; Mute/unmute the master volume.

To discover the capabilities of the sound devices (mixers) installed on the system -- such as the available component types and control types -- run the soundcard analysis script.

When SoundSet changes the volume of a component, all of that component's channels (e.g. left and right) are set to the same level. In other words, any off-center "balance" that may have been set previously is lost. This can be avoided for the WAVE component by using SoundSetWaveVolume instead, which attempts to preserve the existing balance when changing the volume level.

Use SoundGet to retrieve the current value of a setting.

#### Related

SoundGet, SoundGetWaveVolume, SoundSetWaveVolume, SoundPlay

#### Examples

    ; BASIC EXAMPLES:
    SoundSet, 50  ; Set the master volume to 50%
    SoundSet +10  ; Increase master volume by 10%
    SoundSet -10  ; Decrease master volume by 10%
    SoundSet, 1, Microphone, mute  ; mute the microphone
    SoundSet, +1, , mute  ; Toggle the master mute (set it to the opposite state)
    SoundSet, +20, Master, bass  ; Increase bass level by 20%.
    if ErrorLevel
        MsgBox, The BASS setting is not supported for MASTER.

    ; SOUNDCARD ANALYSIS
    ; Use the following script to discover your soundcard's capabilities (component types and control types).
    ; It displays the results in a simple ListView.

    SetBatchLines -1
    SplashTextOn,,, Gathering Soundcard Info...

    ; Most of the pure numbers below probably don't exist in any mixer, but they're queried for completeness.
    ; The numbers correspond to the following items (in order): CUSTOM, BOOLEANMETER, SIGNEDMETER, PEAKMETER,
    ; UNSIGNEDMETER, BOOLEAN, BUTTON, DECIBELS, SIGNED, UNSIGNED, PERCENT, SLIDER, FADER, SINGLESELECT, MUX,
    ; MULTIPLESELECT, MIXER, MICROTIME, MILLITIME
    ControlTypes = VOLUME,ONOFF,MUTE,MONO,LOUDNESS,STEREOENH,BASSBOOST,PAN,QSOUNDPAN,BASS,TREBLE,EQUALIZER,0x00000000, 0x10010000,0x10020000,0x10020001,0x10030000,0x20010000,0x21010000,0x30040000,0x30020000,0x30030000,0x30050000,0x40020000,0x50030000,0x70010000,0x70010001,0x71010000,0x71010001,0x60030000,0x61030000

    ComponentTypes = MASTER,HEADPHONES,DIGITAL,LINE,MICROPHONE,SYNTH,CD,TELEPHONE,PCSPEAKER,WAVE,AUX,ANALOG,N/A

    ; Create a ListView and prepare for the main loop:
    Gui, Add, Listview, w400 h400 vMyListView, Component Type|Control Type|Setting|Mixer
    LV_ModifyCol(4, "Integer")
    SetFormat, Float, 0.2  ; Limit number of decimal places in percentages to two.

    Loop  ; For each mixer number that exists in the system, query its capabilities.
    {
        CurrMixer := A_Index
        SoundGet, Setting,,, %CurrMixer%
        if ErrorLevel = Can't Open Specified Mixer  ; Any error other than this indicates that the mixer exists.
            break

        ; For each component type that exists in this mixer, query its instances and control types:
        Loop, parse, ComponentTypes, `,
        {
            CurrComponent := A_LoopField
            ; First check if this component type even exists in the mixer:
            SoundGet, Setting, %CurrComponent%,, %CurrMixer%
            if ErrorLevel = Mixer Doesn't Support This Component Type
                continue  ; Start a new iteration to move on to the next component type.
            Loop  ; For each instance of this component type, query its control types.
            {
                CurrInstance := A_Index
                ; First check if this instance of this instance even exists in the mixer:
                SoundGet, Setting, %CurrComponent%:%CurrInstance%,, %CurrMixer%
                ; Checking for both of the following errors allows this script to run on older versions:
                if ErrorLevel in Mixer Doesn't Have That Many of That Component Type,Invalid Control Type or Component Type
                    break  ; No more instances of this component type.
                ; Get the current setting of each control type that exists in this instance of this component:
                Loop, parse, ControlTypes, `,
                {
                    CurrControl := A_LoopField
                    SoundGet, Setting, %CurrComponent%:%CurrInstance%, %CurrControl%, %CurrMixer%
                    ; Checking for both of the following errors allows this script to run on older versions:
                    if ErrorLevel in Component Doesn't Support This Control Type,Invalid Control Type or Component Type
                        continue
                    if ErrorLevel  ; Some other error, which is unexpected so show it in the results.
                        Setting := ErrorLevel
                    ComponentString := CurrComponent
                    if CurrInstance > 1
                        ComponentString = %ComponentString%:%CurrInstance%
                    LV_Add("", ComponentString, CurrControl, Setting, CurrMixer)
                }  ; For each control type.
            }  ; For each component instance.
        }  ; For each component type.
    }  ; For each mixer.

    Loop % LV_GetCount("Col")  ; Auto-size each column to fit its contents.
        LV_ModifyCol(A_Index, "AutoHdr")

    SplashTextOff
    Gui, Show
    return

    GuiClose:
    ExitApp