1 (изменено: Alectric, 2019-02-06 18:15:28)

Тема: AHK: Аудио компрессор для windows 7,8,10

Вот скрипт аудио-компрессора для Windows 7 на основе VA.ahk.
Подумал что кому-нибудь пригодится.

Компрессор нужен для выравнивания громкости.
Т.е. если воспроизводится тихий звук в плеере или еще где-либо - компрессор повысит громкость; если звук слишком громкий, то соответственно понизит.
Уровни срабатывания и задержка выставляются в "GUI", как и другие настройки.

Наведите курсор на элемент управления чтобы увидеть описание.

Подробнее.

#NoEnv
#SingleInstance,off
AutoTrim,Off
CoordMode,Mouse,Screen
;CoordMode,ToolTip
Menu,Tray,UseErrorLevel
process,priority,,high
;SendMode,Input
SetBatchLines,-1
SetControlDelay,0
;SetKeyDelay,0
SetWinDelay,-1
SetWorkingDir,%A_ScriptDir%
StringCaseSense,On
DetectHiddenWindows,On
#Include VA.ahk
#NoTrayIcon
IID_IASM2:="{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}"
IID_IASC2:="{bfb7ff88-7239-4fc9-8fa2-07c950be9c6d}"
IID_ISAV:="{87CE5498-68D6-44E5-9215-6DA47EF883D8}"
IID_AM:="{C02216F6-8C67-4B5B-9D00-D008E73E0064}"
global Message, wP, lP, MainNotExist, borderX, App, guiid, AppCount, MainWeight:=175
, Weight:=186, WM_HSCROLL:=0x114, guiexist, exit, ListWin, List, AppEXE, WheelVol
OnMessage(0x1002,"Message")
if !winexist("Compressor Win 7 Main")
  MainNotExist=1
onexit,exit

App=%0%
Appexe=%1%
AppPID=%2%
AppTurnOn=%3%

WinGet,ActiveWin,id,A
Menu,Tray,NoStandard
if !App
{
  if !MainNotExist
  {
    msgbox,Программа уже открыта.
    alreadyexit:=1
    exitapp
  }
  OnMessage(WM_HSCROLL, "WM_HSCROLL")
  Menu,Tray,Icon
  Menu,Tray,Icon,%A_ScriptDir%\va.ico
}
else if MainNotExist
{
  Menu,Tray,Icon
  Menu,Tray,Icon,%A_ScriptDir%\va.ico
}
Menu,Tray,add,Нормализация громкости,ShowWin
Menu,Tray,add,Exit,Exit
Menu,Tray,default,Нормализация громкости

if !App
  Settingspath:="SOFTWARE\AlectricSoft\Compressor"
else
  Settingspath:="SOFTWARE\AlectricSoft\Compressor\" appexe
if !App
  SettingsDefault=
(
dovol=40
dovoltime=0
FadeIn=1
FadeInSpeed=0.7
FadeOut=0
FadeOutSpeed=0.7
flatdown=2
flatup=3
gain=1
GuiX=0
GuiY=0
Hide=0
Impulse=1
Impulsesettime=300
linearity=1
Mixer=0
multiplier=30
notebook=0
otvol=0
otvoltime=300
resettimeset=100
ResetToNull=0
smoothdo=0
smoothot=1
timerflatset=150
TurnOn=1
WheelVol=0
work=1
)
else
  SettingsDefault=
(
dovol=35
dovoltime=0
FadeIn=1
FadeInSpeed=0.7
FadeOut=0
FadeOutSpeed=0.7
flatdown=2
flatup=3
gain=0.75
GuiX=0
GuiY=0
Hide=0
Impulse=1
Impulsesettime=300
linearity=1.0
Mixer=0
multiplier=30
notebook=1
otvol=0
otvoltime=300
resettimeset=100
ResetToNull=0
smoothdo=0
smoothot=1
timerflatset=150
TurnOn=1
WheelVol=0
work=0
)
gosub,loadSettings
if (App and !work and TurnOn and AppTurnOn)
{
  TurnOn:=0
  work:=1
}
process,exist
CompressorPID:=errorlevel
ListWin.= CompressorPID "`,"

if (GuiX>a_screenwidth)
  GuiX-=(GuiX-a_screenwidth+200)
if (GuiY>a_screenheight)
  GuiY-=(GuiY-a_screenheight+200)

if !App
{
  audioMeter:=VA_GetAudioMeter()
  vol:=newvol:=newvolset:=multiplier
  returnvol:=VA_GetMasterVolume()
  VA_SetMasterVolume(newvol,"","")
}
else
{
  if winexist("Compressor for " . AppPID)
  {
    winclose,% "Compressor for " . AppPID
    sleep,300
  }
  gosub,GetVolumeObject
  VA_ISimpleAudioVolume_GetMasterVolume(AppVol,vol)
  vol*=100
  newvol:=newvolset:=vol
}
VA_GetDevicePeriod("capture", devicePeriod)
VarSetCapacity(involValues, 8)

linearityS:=linearity*10
Gui,2:font,s8,Tahoma
Gui,2:+hwndhlinearity +ToolWindow +AlwaysOnTop
Gui,2:Add,Slider,+hwndS_0 xm  ym w20 h200 Vertical Invert Center NoTicks Range0-100 vlinty_0
Gui,2:Add,Slider,+hwndS_1 x+1 ym w20 h200 Vertical Invert Center NoTicks Range0-100 vlinty_1
Gui,2:Add,Slider,+hwndS_2 x+1 ym w20 h200 Vertical Invert Center NoTicks Range0-100 vlinty_2
Gui,2:Add,Slider,+hwndS_3 x+1 ym w20 h200 Vertical Invert Center NoTicks Range0-100 vlinty_3
Gui,2:Add,Slider,+hwndS_4 x+1 ym w20 h200 Vertical Invert Center NoTicks Range0-100 vlinty_4
Gui,2:Add,Slider,+hwndS_5 x+1 ym w20 h200 Vertical Invert Center NoTicks Range0-100 vlinty_5
Gui,2:Add,Slider,+hwndS_6 x+1 ym w20 h200 Vertical Invert Center NoTicks Range0-100 vlinty_6
Gui,2:Add,Slider,+hwndS_7 x+1 ym w20 h200 Vertical Invert Center NoTicks Range0-100 vlinty_7
Gui,2:Add,Slider,+hwndS_8 x+1 ym w20 h200 Vertical Invert Center NoTicks Range0-100 vlinty_8
Gui,2:Add,Slider,+hwndS_9 x+1 ym w20 h200 Vertical Invert Center NoTicks Range0-100 vlinty_9
Gui,2:Add,Slider,+hwndS_10 x+1 ym w20 h200 Vertical Invert Center NoTicks Range0-100 vlinty_10
Gui,2:Add,text,+hwndS_20 xm y+5 w20 Center,0
Gui,2:Add,text,+hwndS_21 x+1 yp w20 Center,10
Gui,2:Add,text,+hwndS_22 x+1 yp w20 Center,20
Gui,2:Add,text,+hwndS_23 x+1 yp w20 Center,30
Gui,2:Add,text,+hwndS_24 x+1 yp w20 Center,40
Gui,2:Add,text,+hwndS_25 x+1 yp w20 Center,50
Gui,2:Add,text,+hwndS_26 x+1 yp w20 Center,60
Gui,2:Add,text,+hwndS_27 x+1 yp w20 Center,70
Gui,2:Add,text,+hwndS_28 x+1 yp w20 Center,80
Gui,2:Add,text,+hwndS_29 x+1 yp w20 Center,90
Gui,2:Add,text,+hwndS_30 x+1 yp w20 Center,100
Gui,2:Add,text,+hwndS_31 xm y+5 w20 Center,0
Gui,2:Add,text,+hwndS_32 x+1 yp w20 Center,10
Gui,2:Add,text,+hwndS_33 x+1 yp w20 Center,20
Gui,2:Add,text,+hwndS_34 x+1 yp w20 Center,30
Gui,2:Add,text,+hwndS_35 x+1 yp w20 Center,40
Gui,2:Add,text,+hwndS_36 x+1 yp w20 Center,50
Gui,2:Add,text,+hwndS_37 x+1 yp w20 Center,60
Gui,2:Add,text,+hwndS_38 x+1 yp w20 Center,70
Gui,2:Add,text,+hwndS_39 x+1 yp w20 Center,80
Gui,2:Add,text,+hwndS_40 x+1 yp w20 Center,90
Gui,2:Add,text,+hwndS_41 x+1 yp w20 Center,100
Gui,2:Add,Slider,+hwndS_11 xm y+10 w230 Center NoTicks Range1-100 vlinearityS AltSubmit gChangelinearity,% linearity*10
Gui,2:Add,text,+hwndS_12 xm+10 y+20,10.00000
Gui,2:Add,button,+hwndS_13 x+10 yp-4 gDefaultlinty gDefaultlinty,Поумолчанию ;
control,disable,,,ahk_id %S_0%
control,disable,,,ahk_id %S_1%
control,disable,,,ahk_id %S_2%
control,disable,,,ahk_id %S_3%
control,disable,,,ahk_id %S_4%
control,disable,,,ahk_id %S_5%
control,disable,,,ahk_id %S_6%
control,disable,,,ahk_id %S_7%
control,disable,,,ahk_id %S_8%
control,disable,,,ahk_id %S_9%
control,disable,,,ahk_id %S_10%

Gui,1:font,s8,Tahoma
Gui,1:Margin,0,4

Gui,1:Add,Button,+hwndE_1 x0 y0 w%MainWeight% h0 BackgroundGray
ControlGetPos,Left,,MainWeight,,,ahk_id %E_1%

Gui,1:+owner -sysmenu +ToolWindow +hwndguiid
if (!App or MainNotExist)
{
  if !App
    Gui,1:+resize
  Gui,1:+alwaysontop
}
else
{
  Gui,1:+0x40000000 -0x80000000
  Gui,1:add,groupbox,x0 y0 w170 h470,%appexe%
}
;-------------------------------------------------------------------------------------------------
Gui,1:Add,Button,+hwndE_2 x54 y0 h7 w31 GReloadSettings
Gui,1:Add,Button,+hwndE_46 x130 y240  GlinearitySettings,_/
Gui,1:Add,Slider,+hwndE_3 x10 y12 w20 h210 Vertical Invert Center NoTicks Range0-100 vmultiplier,%multiplier%
Gui,1:Add,Slider,+hwndE_4 x+2 yp w20 h210 Vertical Invert NoTicks votvol,%otvol%
Gui,1:Add,Progress,+hwndE_5 x+2 yp+6 w6 h198 Vertical cGray vVolumein
Gui,1:Add,Progress,+hwndE_6 x+0 yp w20 h198 Vertical cBlue vVolumeout
Gui,1:Add,Progress,+hwndE_7 x+0 yp w6 h198 Vertical cGray vVolumein2
Gui,1:Add,Slider,+hwndE_8 x+2 yp-6 w20 h210 Vertical Invert Left NoTicks vdovol,%dovol%
Gui,1:Add,Slider,+hwndE_9 x+2 yp-2 h214 Backgroundyelow Vertical Thick20 Invert Center NoTicks vnewvolset,%newvol%
Gui,1:Add,Slider,+hwndE_10 x+2 yp h214 Range0-200 Vertical Thick20 Invert Center NoTicks vSetgain,% tmpgain:=round(gain*100)
;-------------------------------------------------------------------------------------------------
Gui,1:Add,text,+hwndE_11 x8 y+1 w20 vmultipliertext Center
Gui,1:Add,text,+hwndE_12 x+3 yp w20 votvoltext Center
Gui,1:Add,text,+hwndE_13 x+9 yp w20 vOutvoltext Center
Gui,1:Add,text,+hwndE_14 x+7 yp w20 vdovoltext Center
Gui,1:Add,text,+hwndE_15 x+5 yp w20 vvolnow Center
Gui,1:Add,text,+hwndE_16 x+7 yp w20 vgainset Center
;-------------------------------------------------------------------------------------------------
Gui,1:Add,CheckBox,+hwndE_17 x33 y+5 Checked%smoothot% vsmoothot,smooth
Gui,1:Add,CheckBox,+hwndE_18 x+6 yp Checked%smoothdo% vsmoothdo
;-------------------------------------------------------------------------------------------------
Gui,1:Add,Edit,+hwndE_19 x23 y+6 w35 -Multi Center votvoltime,%otvoltime%
Gui,1:Add,text,+hwndE_20 x+1 yp+3 w24 Center,ms
Gui,1:Add,Edit,+hwndE_21 x+1 yp-3 w35 -Multi Center vdovoltime,%dovoltime%
Gui,1:Add,text,+hwndE_22 x+1 yp+3 w40 vnewvolsettext Center
;-------------------------------------------------------------------------------------------------
Gui,1:Add,Edit,+hwndE_23 x23 y+10 w35 -Multi Center vflatup,%flatup%
Gui,1:Add,text,+hwndE_24 x+1 yp+3 w24 Center vdevicePeriodtext
Gui,1:Add,Edit,+hwndE_25 x+1 yp-3 w35 -Multi Center vflatdown,%flatdown%
Gui,1:Add,Edit,+hwndE_26 x+1 yp w35 -Multi Center vtimerflatset,%timerflatset%
;-------------------------------------------------------------------------------------------------
Gui,1:Add,Progress,x5 y+6 w159 h2 BackgroundGray ;-------------------------------------------------------
;-------------------------------------------------------------------------------------------------
Gui,1:Add,Edit,+hwndE_27 x5 y+6 w50 -Multi Center vresettimeset,%resettimeset%
Gui,1:Add,CheckBox,+hwndE_28 x+6 yp+3 w60 Checked%FadeIn% vFadeIn,Fade In
Gui,1:Add,Edit,+hwndE_29 x+3 yp-3 w40 -Multi Center vFadeInSpeed,%FadeInSpeed%
Gui,1:Add,CheckBox,+hwndE_30 x61 y+1 w61 Checked%FadeOut% vFadeOut,Fade Out
Gui,1:Add,Edit,+hwndE_31 x+2 yp+3 w40 -Multi Center vFadeOutSpeed,%FadeOutSpeed%
Gui,1:Add,CheckBox,+hwndE_32 x10 y+3 w150 Checked%ResetToNull% vResetToNull,Сбрасывать до нуля ;
;-------------------------------------------------------------------------------------------------
Gui,1:Add,Progress,x5 y+6 w159 h2 BackgroundGray ;-------------------------------------------------------
;-------------------------------------------------------------------------------------------------
Gui,1:Add,CheckBox,+hwndE_34 x10 y+10 w57 Checked%Impulse% vImpulse,Impulse
Gui,1:Add,Edit,+hwndE_35 x+1 w50 yp-3 -Multi Center vImpulsesettime,%Impulsesettime%
Gui,1:Add,text,+hwndE_36 x+1 yp+3 w20 Center,ms
Gui,1:Add,text,+hwndE_37 x+1 yp w30 left vLastImpulse
;-------------------------------------------------------------------------------------------------
Gui,1:Add,Progress,x5 y+10 w159 h2 BackgroundGray ;------------------------------------------------------
;-------------------------------------------------------------------------------------------------
Gui,1:Add,CheckBox,+hwndE_39 x10 y+10 w150 +multi Checked%work% vwork,Нормализация включена
if !App
{
  Gui,1:Add,CheckBox,+hwndE_40 x10 w150 +multi Checked%Hide% vHide,Скрывать при переходе на другое окно ;
  Gui,1:Add,CheckBox,+hwndE_41 x10 w70 +multi Checked%notebook% gNotebooke vnotebook,Ноутбук ;
  Gui,1:Add,CheckBox,+hwndE_43 x10 y+9 w160 +multi Checked%Mixer% gMixer vMixer,Микшер ;
  Gui,1:Add,CheckBox,+hwndE_38 x10 y+5 w160 +multi Checked%WheelVol% vWheelVol,Регулировать громкость роликом мыши ;
  Gui,1:Add,Progress,x170 y4 w3 h550 BackgroundBlue Vertical ;------------------------------------------------------
  Gui,1:Add,Button,+hwndE_44 x187 y472 w70 h30 GRefrash,Обновить ;
  Gui,1:Add,CheckBox,+hwndE_45 xp y+3 w160 +multi Checked%TurnOn% vTurnOn,Всегда включать нормализацию для новых приложений ;
}
else
  Gui,1:Add,Progress,x167 y7 w3 h460 BackgroundBlue Vertical ;------------------------------------------------------
;-------------------------------------------------------------------------------------------------
;-------------------------------------------------------------------------------------------------
Gui,1:Add,Button,+hwndE_42 x165 y0 h5 w5 GExit,-
;-------------------------------------------------------------------------------------------------
if !App
{
  Gui,1:+0x100000
  Gui,1:Show,NA x%GuiX% y%GuiY% w170 h552,Compressor Win 7 Main
  gosub,mixer
  UpdateScrollBar(guiid,MainWeight+MainWeight*AppCount,E_1)
}
else
{
  if hwndP:=winexist("Compressor Win 7 Main")
  {
    Notebook:=1
    Gui,1:-border
    guiexist:=0
;    if !isWindowFullScreen(AppPID)
;    {
      SetParent(guiid,hwndP,,(Left+MainWeight+MainWeight))
      Gui,1:Show,NA w170 h460,Compressor for %AppPID%
;      winactivate,ahk_id %ActiveWin%
      guiexist:=1
;    }
;    else
;      lategui:=1
  }
  else
    Gui,1:Show,NA x%GuiX% y%GuiY% w170 h521,Compressor for %AppPID%
}

control,disable,,,ahk_id %E_9%

GuiControl,,multipliertext,%multiplier%
GuiControl,,otvoltext,%otvol%
GuiControl,,dovoltext,%dovol%
GuiControl,,devicePeriodtext,%devicePeriod%
GuiControl,,Setgain,% tmpgain


if (!App and hide)
  Gui,1:hide
if !lategui
  guiexist:=!hide

if !App
{
  gosub,guiexisttoapps
  Gui,5:+hwndInfoWinHWND -Caption +ToolWindow +AlwaysOnTop +E0x08000020
  Gui,5:Color,Gray
  Gui,5:Margin,0,0
  Gui,5:font,s60,Castellar
  Gui,5:add,text,x30 y180 w180 center vInfoVolume,123
  Gui,5:Add,Progress,x55 y5 w180 h170 cwhite BackgroundGray vInfoVolumep2
  Gui,5:Add,Progress,x55 y10 w180 h160 cBlack BackgroundGray vInfoVolumep
  WinSet,Transparent,255,ahk_id %InfoWinHWND%
  Gui,5:Show,center NoActivate,Volume
  WinSet,TransColor,Gray,ahk_id %InfoWinHWND%
  Gui,5:hide
  ;------------------------------------------------------------------------
  Gui,4:+hwndImageHWND -Caption +ToolWindow +E0x08000020
  Gui,4:Color,white
  Gui,4:Margin,0,0
  SetParent(ImageHWND,InfoWinHWND,0,0)
  WinSet,Region,0-60 20-60 40-0 50-0 50-180 40-180 20-120 0-120 ,ahk_id %ImageHWND%
  Gui,4:Show, w300 h300 NoActivate,Image
  WinSet,Transparent,255,ahk_id %ImageHWND%
  WinMove,ahk_id %ImageHWND%,,0,0
  ;------------------------------------------------------------------------
  Gui,3:+hwndImage2HWND -Caption +ToolWindow +E0x08000020
  Gui,3:Color,black
  Gui,3:Margin,0,0
  SetParent(Image2HWND,ImageHWND,0,0)
  WinSet,Region,2-62 22-62 42-2 48-2 48-178 42-178 22-118 2-118 ,ahk_id %Image2HWND%
  Gui,3:Show, w300 h300 NoActivate,Image
  WinSet,Transparent,255,ahk_id %Image2HWND%
  WinMove,ahk_id %Image2HWND%,,0,0
}

loop:
loop
{
  if Message
  {
    Message:=
    if wP=1
      exit:=1
    else if wP=2
      guiexist:=lP
    else if wP=3
    {
      winmove,ahk_id %guiid%,,% MainWeight+(MainWeight-11)*(lP-1),0
      WinSet,redraw,,ahk_id %guiid%
    }
;    else if wP=4
;      ListWin.=lP "`,"
  }
  if (App and exit)
    goto,exit
  if !notebook
    savegain:=gain, gain:=1
  if Fail
  {
    sleep,1000
    if !App
    {
      ObjRelease(AudioMeter)
      audioMeter:=VA_GetAudioMeter()
      if audioMeter
        Fail:=0
    }
    else
    {
      gosub,GetVolumeObject
      if AppVol
        Fail:=0
      else
        exit:=1
    }
    continue
  }
  sleep,% devicePeriod+10
  voltime:= oldvoltime="" ? 0 : a_tickcount-oldvoltime
  oldvoltime:=a_tickcount

  VA_IAudioMeterInformation_GetPeakValue(audioMeter,involValue)
  if (old_involValue=involValue)
  {
    resetcompressor+=1
    if !App
    {
      if (resetcompressor=1000)
      {
        resetcompressor:=
        ObjRelease(AudioMeter)
        audioMeter:=VA_GetAudioMeter()
      }
      else if !audioMeter
        Fail:=1
    }
    else
    {
      if (resetcompressor=200)
      {
        resetcompressor:=
        gosub,GetVolumeObject
      }
      else if !AppVol
        Fail:=1
    }
    if (resetcompressor>100)
      sleep,10
;tooltip,% resetcompressor "`n" AppVol "`n" AudioMeter "`n" Fail
  }
  else
    resetcompressor:=
  old_involValue:=involValue
  Old_invol:=invol
  invol:=VA_Scalar2dB(involValue**linearity,0,1)*100
  Outvol:=newvol*invol/100/gain
  if (Outvol<0 or resetnow)
    Outvol:=0
;  invol:=round(invol)
;  Outvol:=round(Outvol)
;  tooltip,"%invol%"`n"%Outvolcoeff%"`n"%Outvol%"
  if !App
    vol:=round(VA_GetMasterVolume(),2)
  else
  {
    VA_ISimpleAudioVolume_GetMasterVolume(AppVol,vol)
    vol*=100
  }
;tooltip,% """" round(vol) """`n""" round(newvol) """`n""" gain """" """`n""" newvol """"
  if (round(newvol)<100 and round(vol)!=round(newvol))
  {
;tooltip,% round(vol) "`n" round(newvol) "`n" gain
    wait:=200+voltime
    if (notebook and !App)
    {
      resetnow:=1
      if !App
      {
        gain:=gain<0 ? 0 : gain>2 ? 2 : gain
        gain:=(gain*100+(vol-newvol)*3)/100
        tmpgain:=Round(gain*100)
        GuiControl,,Setgain,% tmpgain
        GuiControl,,newvolset,% vol
        tooltip,% tmpgain
        settimer,removetooltip,-1000
      }
      if gain=0
        vol:=newvol:=0
;tooltip,% """" vol """`n""" newvol """`n""" gain
    }
    newvolset:=newvol:=vol
    if guiexist
      GuiControl,,newvolset,% round(newvol)
  }
  if !winactive("ahk_exe SndVol.exe")
    wait:=0
  else if (wait and !GetKeyState("lbutton","P"))
    wait:=wait>0 ? wait-voltime : 0
  temp4+=1
  if (App and temp4>100)
  {
    hwndP:=winexist("Compressor Win 7 Main")
    temp4:=
    if (!MainNotExist and !hwndP) or (MainNotExist and hwndP)
      exit:=1
  }
; fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
  if (work and gain!=0 and !wait)
    gosub,Align
; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

  if (hide and guiexist)
  {
    winget,pid,PID,A
    if !instr(ListWin,pid+0)
    {
;tooltip,% ListWin "`n" guiid+0 "`n" id+0
      wingetpos,GuiX,GuiY,,,ahk_id %guiid%
      guiexist:=0
      Gui,1:hide
      if !App
        gosub,guiexisttoapps
    }
  }
;tooltip,%ottime%`n%volmaxtime%`n%resettime%`n%newvol%`n
;tooltip,% gain "`n" newvol

; --------------------------------------------------------------------------
  temp3+=1
  if (Mixer and temp3>100)
  {
    temp3:=
    loop,parse,List,`,
    {
      if !a_loopfield
        continue
      process,exist,% a_loopfield
      if !errorlevel
      {
        PostMessage,0x1002,1,,,% "ahk_pid " Compr%a_loopfield%
        AppCount--
        ListWin:=RegExReplace(ListWin, Compr%a_loopfield% "`,", "")
        List:=RegExReplace(List, a_loopfield "`,", "")
        gosub,Refrash
      }
    }
    ; GetDefaultAudioEndpoint
    ObjRelease(DAE)
    try DAE:=VA_GetDevice()
    ; activate the session manager
    ObjRelease(IASM2)
    try VA_IMMDevice_Activate(DAE,IID_IASM2,0,0,IASM2)
    ; enumerate sessions for on this device
    ObjRelease(IASE)
    try VA_IAudioSessionManager2_GetSessionEnumerator(IASM2,IASE)
    try VA_IAudioSessionEnumerator_GetCount(IASE,Count)
    AppCount:=
    Loop,% Count
    {
      ; Get the IAudioSessionControl object
      ObjRelease(IASC)
      try VA_IAudioSessionEnumerator_GetSession(IASE,A_Index-1,IASC)
      ; Query the IAudioSessionControl for an IAudioSessionControl2 object
      ObjRelease(IASC2)
      try IASC2:=ComObjQuery(IASC,IID_IASC2)
      ; Get the sessions process ID
      try VA_IAudioSessionControl2_GetProcessID(IASC2,SPID)
      process,exist,% SPID
      if (!SPID or !ErrorLevel)
        continue
      WinGet,ProcName%SPID%,ProcessName,ahk_pid %SPID%
      if (ProcName%SPID%="explorer.exe")
        continue

      AppCount++
      if !instr(List,SPID)
      {
        List.= SPID "`,"
        if a_iscompiled
          run,% a_scriptfullpath " " ProcName%SPID% " " SPID " " TurnOn,,UseErrorLevel,RPID
        else
          run,% """" a_ahkPath """ """ a_scriptfullpath """ " ProcName%SPID% " " SPID " " TurnOn,,UseErrorLevel,RPID
        Compr%SPID%:=RPID
        ListWin.= RPID+0 "`,"
        winwait,% "ahk_pid " Compr%SPID%,,3
        gosub,Refrash
      }
    }
  ;tooltip,% a_tickcount "`n" AppCount "`n`n" list "`n" class "`t|" ahkPath "|"
  }
; --------------------------------------------------------------------------
  temp2++
  if (temp2>1000)
  {
    mousegetpos,,,mwin
    WinGet,mpid,PID,ahk_id %mwin%
    if (lategui and mpid and mpid!=AppPID)
    {
      lategui:=0
      SetParent(guiid,hwndP,,(Left+MainWeight+MainWeight))
      Gui,1:Show,NA w170 h460,Compressor for %AppPID%
      guiexist:=1
    }
  }
  if guiexist
  {
    VA_IAudioMeterInformation_GetChannelsPeakValues(audioMeter, 2, &involValues)
    involL:=VA_Scalar2dB(NumGet(involValues, 0, "float")**linearity,0,1)*100
    involR:=VA_Scalar2dB(NumGet(involValues, 4, "float")**linearity,0,1)*100
    Gui,1:submit,nohide
    gain:=Setgain/100
    tmpgain:=Round(gain*100)
    GuiControl,,Volumein,%involL%
    GuiControl,,Volumein2,%involR%
    GuiControl,,Volumeout,%Outvol%
    Outvolshow+=1
    Outvoltextt+=Outvol
    if !work
    {
;tooltip,% vol "`t" newvol "`n" newvolset
      if (round(vol)!=round(newvolset))
      {
        if !App
          VA_SetMasterVolume(round(newvolset),"","")
        else
          VA_ISimpleAudioVolume_SetMasterVolume(AppVol,newvolset/100)
        vol:=newvolset
      }
    }
    if (Outvolshow>10)
    {
      Outvolshowt:=Outvoltextt/Outvolshow
      GuiControl,,Outvoltext,% Round(Outvolshowt)
      Outvolshow:=
      Outvoltextt:=
      GuiControl,,volnow,% Round(newvol)
      GuiControl,,gainset,% tmpgain

    }
    if (multipliertext!=multiplier)
    {
      multipliertext:=multiplier
      GuiControl,,multipliertext,%multipliertext%
    }
    if (otvoltext!=otvol)
    {
      otvoltext:=otvol
      if (otvol>dovol)
      {
        temp:=otvol+1
        GuiControl,,dovol,%temp%
        GuiControl,,dovoltext,%temp%
      }
      GuiControl,,otvoltext,%otvol%
    }
    if (dovoltext!=dovol)
    {
      dovoltext:=dovol
      if (dovol<otvol)
      {
        temp:=dovol-1
        GuiControl,,otvol,%temp%
        GuiControl,,otvoltext,%temp%
      }
      GuiControl,,dovoltext,%dovol%
    }

    temp1+=1
    if (temp1>100 and !tooltipshow)
    {
      temp1:=
      if !FadeOut
        control,enable,,,ahk_id %E_27%
      else
        control,disable,,,ahk_id %E_27%
      if !work
        control,enable,,,ahk_id %E_9%
      else
        control,disable,,,ahk_id %E_9%
      if notebook
        control,enable,,,ahk_id %E_10%
      else
        control,disable,,,ahk_id %E_10%
;      if (!App or MainNotExist)
;      {
;        Gui,1:-AlwaysOnTop
;        Gui,1:+AlwaysOnTop
;      }
    }
    if (A_TimeIdle>300 and !tooltipshow)
    {
      tooltipshow:=1
      mousegetpos,,,mwin,mctrl
      if (mctrl and (mwin=guiid or mwin=hlinearity or mwin=hwndP))
      {
        ControlGet,hElement,hwnd,,%mctrl%,ahk_id %mwin%
        if (hElement=E_38)
          tooltip,Если курсор мыши находится над панелью задач.
        else if (hElement=E_2)
          tooltip,Сбросить настройки.
        else if (hElement=E_3)
          tooltip,Уровень громкости`, к которому`nстремится выходной уровень.
        else if (hElement=E_4)
          tooltip,Уровень сигнала`, ниже которого`nгромкость будет нарастать`nс интервалом %otvoltime% ms.
        else if (hElement=E_8)
          tooltip,Уровень сигнала`, выше которого`nгромкость будет убывать`nс интервалом %dovoltime% ms.
        else if (hElement=E_9)
          tooltip,Текущий уровень громкости.`n`nМожно регулировать только`,`n если нормализация выключена.
        else if (hElement=E_10)
          tooltip,% "Усиление.`nПроцент от уровня стремления`n" tmpgain "`% от " multiplier
        else if (hElement=E_5)
          tooltip,Входной уровень.`nЛевый канал.
        else if (hElement=E_6)
          tooltip,Выходной уровень`nсигнала.
        else if (hElement=E_7)
          tooltip,Входной уровень.`nПравый канал.
        else if (hElement=E_17)
          tooltip,Сглаживание при`nвозрастании громкости.
        else if (hElement=E_18)
          tooltip,Сглаживание при`nубывании громкости.
        else if (hElement=E_19)
          tooltip,Задержка при возрастании`,`nесли уровень ниже %otvol%
        else if (hElement=E_21)
          tooltip,Задержка при убывании`,`nесли уровень выше %dovol%
        else if (hElement=E_23)
          tooltip,% "Скорость увеличения громкости`nпри ""стремлении"" к " multiplier "`n" flatup " единиц громкости за " timerflatset*voltime " милисекунд (" timerflatset " цикл(ов) программы)."
        else if (hElement=E_25)
          tooltip,% "Скорость уменьшения громкости`nпри ""стремлении"" к " multiplier "`n" flatdown " единиц громкости за " timerflatset*voltime " милисекунд (" timerflatset " цикл(ов) программы)."
        else if (hElement=E_26)
          tooltip,Количество циклов/измерений для усреднения.
        else if (hElement=E_22)
          tooltip,Последний интервал срабатывания.
        else if (hElement=E_24)
          tooltip,Текущее состояние`n"стремления" к %multiplier%
        else if (hElement=E_27)
          tooltip,Время отсутствия сигнала`, через которое произойдет`nсброс громкости на %multiplier%`n`nЕсли задать 0 - то громкость не будет сбрасываться.
        else if (hElement=E_28)
          tooltip,Восстанавливать громкость`nпосле сброса на %multiplier%
        else if (hElement=E_29)
          tooltip,Скорость восстановления.`n%FadeInSpeed% единиц громкости за %voltime% милисекунд (1 цикл программы).
        else if (hElement=E_30)
          tooltip,Псевдо-FadeOut.`nПостепенно уменьшает громкость до %multiplier%`,`n если звуков не воспроизводится.
        else if (hElement=E_31)
          tooltip,Скорость затухания.`n%FadeOutSpeed% единиц громкости за %voltime% милисекунд (1 цикл программы).
        else if (hElement=E_32)
          tooltip,Сбрасывать громкость почти до нуля`,`n вместо %multiplier%.
        else if (hElement=E_34)
          tooltip,Гасить импульсы короче`, чем %Impulsesettime% милисекунд.
        else if (hElement=E_37)
          tooltip,Длительность последнего восстановленного импульса.
        else if (hElement=E_41)
          tooltip,Режим "Ноутбук".`nРегулирует уровни нормализации синхронно с`nрегулировкой громкости в системе пользователем.
        else if (hElement=E_35)
          tooltip,Длинна импульса для гашения.
        else if (hElement=E_42)
          tooltip,Сохранить настройки и выйти.
        else if (hElement=E_43)
          tooltip,Активирует режим микшера.`nТ.е. нармализацию для всех`n приложений в отдельности.
        else if (hElement=E_46)
          tooltip,Настройки линейности громкости.
        else if instr(S_20 "," S_21 "," S_22 "," S_23 "," S_24 "," S_25 "," S_26 "," S_27 "," S_28 "," S_29 "," S_30,hElement)
          tooltip,Фактический уровень`nгромкости на входе.
        else if instr(S_31 "," S_32 "," S_33 "," S_34 "," S_35 "," S_36 "," S_37 "," S_38 "," S_39 "," S_40 "," S_41,hElement)
          tooltip,Уровень который обрабатывет компрессор.
      }
    }
    else if (A_TimeIdle<100 and tooltipshow)
    {
      tooltipshow:=
      tooltip
    }
  }
}
return

Align:
; ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if !resetnow
{
  if (Outvol<=otvol and Outvol!=0)
  {
    ottime+=voltime
    if guiexist
      GuiControl,+cBlue,Volumeout
    if (ottime>1 and Outvol!=0 and guiexist and round(newvol)!=100)
      GuiControl,,newvolsettext,%ottime%
    if (ottime>otvoltime)
    {
      ottime:=1
      if otvoltime=0
        newvol+=2
      else if smoothot
        newvol+=1
      else
        newvol+=5
      if newvol<=100
        change=1
    }
  }
  else if ottime!=
  {
    if guiexist
      GuiControl,+cGreen,Volumeout
    ottime:=
  }
; \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  if (Outvol>dovol and Outvol!=0)
  {
    if (Impulse and !ImpulseExist)
    {
      saveinlevel:=Outvol-5
      savelevel:=newvol
      Impulsetime:=
      ImpulseExist:=1
    }
    if guiexist
    {
      GuiControl,+cRed,Volumeout
      GuiControl,,newvolsettext,%volmaxtime%
    }
    if (Outvol>Outvoltmp)
      Outvoltmp:=Outvol
    volmaxtime+=voltime
    if (volmaxtime>dovoltime)
    {
      volmaxtime:=1
      if dovoltime=0
      {
        if smoothdo
          newvol-=(newvol-dovol*gain)/10+1
        else
          newvol-=(Outvol-dovol)*gain
;            newvol:=(dovol*75+otvol*25)/invol
      }
      else if smoothdo
        newvol-=(newvol-dovol*gain)/10+1
      else
        newvol-=(newvol-dovol*gain)/6+1
      change:=1
    }
    newvol:=newvol<1 ? 1 : newvol
  }
  else if volmaxtime!=
  {
    if guiexist
      GuiControl,+cGreen,Volumeout
    Outvoltmp:=
    volmaxtime:=
  }
; //////||||||||||||||||||||||\\\\\\\\\\\\\\\\\\\\\\\///////////\|||||||||||||\\\\\/////////
  if (Outvol!=0 and Impulse)
  {
    if ImpulseExist
    {
      if (Old_invol<invol)
        ImpulseIn:=1
      else if (Old_invol>invol)
        ImpulseIn:=0
      if ImpulseIn
        Impulsetime+=voltime
      else if (Impulsetime<Impulsesettime and saveinlevel>Outvol)
      {
        rise:=1
        if guiexist
          GuiControl,,LastImpulse,% Impulsetime
      }
      else if (Impulsetime>Impulsesettime)
      {
        rise:=
        ImpulseExist:=
        Impulsetime:=
      }
    }
    if (rise and newvol<savelevel and Impulsetime>0)
    {
      Impulsetime+=voltime
      newvol++
      change:=1
    }
    if (rise and (newvol>savelevel or Impulsetime>Impulsesettime*2))
    {
      rise:=
      ImpulseExist:=
      Impulsetime:=
    }
  }
}
; //////////////////////////////////////////////////////////////////////////////
  if (Outvol>0 and resetdone and FadeIn)
  {
    newvol+=FadeInSpeed
    change:=1
    if (Outvol>multiplier or newvol>100)
      resetdone:=
  }
; //////////////////////////////////////////////////////////////////////////////
  if (FadeOut and Outvol=0 and round(newvol/gain)>(ResetToNull ? 1 : multiplier))
  {
    FadeOutRun:=1
    newvol-=FadeOutSpeed
    change:=1
    if (!ResetToNull and round(newvol/gain)<multiplier+FadeOutSpeed)
      resetnow:=1
  }
  if (FadeOutRun and Outvol>0)
  {
    FadeOutRun:=
    resetnow:=2
  }

; \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  if ((!FadeOut and resettimeset and Outvol=0 and round(newvol/gain)!=(ResetToNull ? 1 : multiplier)) or resetnow)
  {
    resettime+=voltime
    if guiexist
      GuiControl,,newvolsettext,%resettime%
    if (resettime>resettimeset or resetnow)
    {
      resetdone:=1
      if resetnow!=2
        newvol:=(ResetToNull ? 1 : multiplier*gain)
      change:=1
      resetnow:=
    }
  }
  else if resettime!=
    resettime:=
; ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
  if (timerflat>timerflatset and Outvol!=0)
  {
    if (minvol>maxvol)
      newvol+=flatup
    else if (minvol<maxvol)
      newvol-=flatdown
    if guiexist
      if (minvol>maxvol)
        GuiControl,,devicePeriodtext,^
      else if (minvol<maxvol)
        GuiControl,,devicePeriodtext,v
    change:=1
    timerflat:=minvol:=maxvol:=0
  }
  else
  {
    timerflat+=1
    if (Outvol>multiplier+(flatup+flatdown)/2)
      maxvol+=1
    else if (Outvol<multiplier-(flatup+flatdown)/2)
      minvol+=1
    else
    {
      if (guiexist and !flatcange)
      {
        GuiControl,,devicePeriodtext,|
        flatcange:=1
      }
      else
        flatcange:=
      timerflat:=0
    }
  }
  newvol:=round(newvol,2)
  newvol:= newvol<0 ? 0 : newvol>100 ? 100 : newvol
  if (change and newvol!=oldvol)
  {
;tooltip,% a_tickcount "`n" newvol
    change:=
    if guiexist
      GuiControl,,newvolset,% newvol
    if !App
      VA_SetMasterVolume(newvol,"","")
    else
      VA_ISimpleAudioVolume_SetMasterVolume(AppVol,newvol/100)
  }
  oldvol:=newvol
; --------------------------------------------------------------------------
return

guisize:
if App
  return
;if (a_cursor!="SizeWE")
;{
;  send,{lbutton up}
;  winmove,ahk_id %guiid%,,,,,595
;}
wingetpos,,,w,h,ahk_id %guiid%
if (w>MainWeight+14+MainWeight*AppCount)
{
  send,{lbutton up}
  winmove,ahk_id %guiid%,,,,% MainWeight+10+MainWeight*AppCount
}
if (w<(AppCount?MainWeight*2:MainWeight))
{
  send,{lbutton up}
  winmove,ahk_id %guiid%,,,,% (AppCount?MainWeight*2:MainWeight)+14
}
UpdateScrollBar(guiid,MainWeight+MainWeight*AppCount,E_1)
if !GetKeyState("lButton","P")
  WinSet,redraw,,ahk_id %guiid%
return

ShowWin:
tmpgain:=Round(gain*100)
guiexist:=1
Gui,1:show
gosub,guiexisttoapps
WinSet,redraw,,ahk_id %guiid%
gosub,Refrash
return

guiexisttoapps:
loop,parse,List,`,
  if a_loopfield
    PostMessage,0x1002,2,% guiexist,,% "ahk_pid " Compr%a_loopfield%
return

Notebooke:
gain:=savegain
resetnow:=1
return

Mixer:
Gui,1:submit,nohide
if Mixer
{
  winmove,ahk_id %guiid%,,,,% MainWeight*2
  UpdateScrollBar(guiid,MainWeight+MainWeight*AppCount,E_1)
}
else
{
  loop,parse,List,`,
  {
    if !a_loopfield
      continue
    PostMessage,0x1002,1,,,% "ahk_pid " Compr%a_loopfield%
    AppCount--
    List:=RegExReplace(List, a_loopfield "`,", "")
  }
  winmove,ahk_id %guiid%,,,,% MainWeight+11
  UpdateScrollBar(guiid,MainWeight,E_1)
}
return

Message(wParam,lParam,Msg,hwnd)
{
;msgbox,% wParam "`t" lParam "`t" Msg "`t" hwnd "`n" guiid "`n" Weight,100,,2
  Message:=1
  wP:=wParam
  lP:=lParam
}

removetooltip:
tooltip
return

; 0000000000000000000000000000000000000000000000000000000000000
ReloadSettings:
ReloadSettings:=1
exit:
guiclose:
if !alreadyexit
{
  if (!App and !guiexist)
  {
    Gui,1:show,NA
    Gui,1:submit,nohide
    sleep,100
  }
  wingetpos,GuiX,GuiY,,,ahk_id %guiid%
  if !ReloadSettings
  {
    if !notebook
      gain:=savegain
    gosub,SaveSettings
  }
  else
    Regdelete,HKCU,%Settingspath%
  if !App
  {
    loop,parse,List,`,
      if a_loopfield
        PostMessage,0x1002,1,,,% "ahk_pid " Compr%a_loopfield%
;    VA_SetMasterVolume(multiplier*2>100 ? 100 : multiplier,"","")
    VA_SetMasterVolume(returnvol,"","")
  }
  else
    VA_ISimpleAudioVolume_SetMasterVolume(AppVol,1)
  alreadyexit:=1
}
exitapp
; 0000000000000000000000000000000000000000000000000000000000000

Refrash:
offset:=0
PostMessage,WM_HSCROLL,0x6,,,ahk_id %guiid%
sleep,300
loop,parse,List,`,
{
  if !a_loopfield
    continue
  if winexist("ahk_pid " Compr%a_loopfield%)
    PostMessage,0x1002,3,a_index-offset,,% "ahk_pid " Compr%a_loopfield%
  else
  {
    List:=RegExReplace(List, a_loopfield "`,", "")
    offset++
    AppCount--
  }
}
gosub,guisize
return

linearitySettings:
GuiControl,,%S_11%,% linearity*10
gosub,Changelinearity
gui,2:show,NA
return

Defaultlinty:
GuiControl,,%S_11%,10
Changelinearity:
gui,2:submit,NoHide
loop,11
{
  tmp1:=a_index-1
  tmp2:=tmp1/10
  tmp3:=a_index+30
  linty_%tmp1%:=VA_Scalar2dB(tmp2**(linearityS/10),0,1)*100
  GuiControl,,% S_%tmp1%,% linty_%tmp1%
  GuiControl,,% S_%tmp3%,% round(linty_%tmp1%)
}
GuiControl,,%S_12%,% linearity:=round(linearityS/10,1)
return

SaveSettings:
if Settingspath=
  Settingspath:="SOFTWARE\Unknown_AHK_Script"
loop,parse,SettingsDefault,`n
{
  Loop,parse,a_loopfield,=
  {
    if a_index=1
    {
      Setting:=a_loopfield
      Break
    }
  }
  save:=%Setting%
  RegWrite,REG_SZ,HKCU,%Settingspath%,%Setting%,%Save%
}
LoadSettings:
if Settingspath=
  Settingspath:="SOFTWARE\Unknown_AHK_Script"
loop,parse,SettingsDefault,`n
{
  Loop,parse,a_loopfield,=
  {
    if a_index=1
      Setting:=a_loopfield
    else if a_index=2
      Default:=a_loopfield
    else
      Default.="=" a_loopfield
  }
  RegRead,%Setting%,HKCU,%Settingspath%,%Setting%
  if errorlevel
  {
    RegWrite,REG_SZ,HKCU,%Settingspath%,%Setting%,%Default%
    RegRead,%Setting%,HKCU,%Settingspath%,%Setting%
  }
}
Return

GetVolumeObject:
Process,Exist,%AppPID%
if !ErrorLevel
  return
PID:=AppPID
; GetDefaultAudioEndpoint
ObjRelease(DAE)
DAE:=VA_GetDevice()
; activate the session manager
ObjRelease(IASM2)
VA_IMMDevice_Activate(DAE,IID_IASM2,0,0,IASM2)
; enumerate sessions for on this device
ObjRelease(IASE)
VA_IAudioSessionManager2_GetSessionEnumerator(IASM2,IASE)
VA_IAudioSessionEnumerator_GetCount(IASE,Count)
Loop,% Count
{
  ObjRelease(IASC)
  VA_IAudioSessionEnumerator_GetSession(IASE,A_Index-1,IASC)
  ; Query the IAudioSessionControl for an IAudioSessionControl2 object
  ObjRelease(IASC2)
  IASC2:=ComObjQuery(IASC,IID_IASC2)
  ; Get the sessions process ID
  VA_IAudioSessionControl2_GetProcessID(IASC2,SPID)
  process,exist,% SPID
  if (!SPID or !ErrorLevel)
    continue
  if (app and SPID=PID)
  {
    ObjRelease(AppVol)
    AppVol:=ComObjQuery(IASC2,IID_ISAV)
    ObjRelease(audioMeter)
    AudioMeter:=ComObjQuery(IASC,IID_AM)
    break
  }
}
return

;
; ISimpleAudioVolume : {87CE5498-68D6-44E5-9215-6DA47EF883D8}
;
VA_ISimpleAudioVolume_SetMasterVolume(this, ByRef fLevel, GuidEventContext="") {
    return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "float", fLevel, "ptr", VA_GUID(GuidEventContext))
}
VA_ISimpleAudioVolume_GetMasterVolume(this, ByRef fLevel) {
    return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "float*", fLevel)
}
VA_ISimpleAudioVolume_SetMute(this, ByRef Muted, GuidEventContext="") {
    return DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "int", Muted, "ptr", VA_GUID(GuidEventContext))
}
VA_ISimpleAudioVolume_GetMute(this, ByRef Muted) {
    return DllCall(NumGet(NumGet(this+0)+6*A_PtrSize), "ptr", this, "int*", Muted)
}

SetParent(hwnd,hNewParent,ClassNN="",x=0,y=0)
{
  if ClassNN
    ControlGet,hNewParent,Hwnd,,%ClassNN%,ahk_id %hNewParent%
  oldParent:=DllCall("SetParent","ptr",hwnd,"ptr",hNewParent)
  WinMove,ahk_id %hwnd%,,%x%,%y%
  return oldParent
}

UpdateScrollBar(hwnd, ScrollWeight,ctrl)
{
global
  PostMessage,WM_HSCROLL,0x6,,,ahk_id %guiid%
   static SIF_RANGE := 0x1, SIF_PAGE := 0x2, SB_HORZ := 0
   WinGetPos,,,GuiWidth,, ahk_id %hwnd%
   VarSetCapacity(si, 28, 0)
   NumPut(28, si) ; cbSize
   NumPut(SIF_RANGE | SIF_PAGE, si, 4)
   NumPut(ScrollWeight, si, 12) ; nMax
   NumPut(GuiWidth, si, 16) ; nPage
   DllCall("SetScrollInfo", Ptr, hwnd, UInt, SB_HORZ, Ptr, &si, UInt, 1)

   ; Scroll contents of window and invalidate uncovered area.
;   DllCall("ScrollWindow", Ptr, hwnd, Int, 1, Int, 0, Ptr, 0, Ptr, 0)

   ControlGetPos,Left,,,,,ahk_id %ctrl%

   Right := MainWeight+MainWeight*AppCount
   if (Left < 0 && Right < GuiWidth)
   {
      x := (a := Abs(Left)) > (b := GuiWidth-Right) ? b : a
      DllCall("ScrollWindow", Ptr, hwnd, Int, x, Int, 0, Ptr, 0, Ptr, 0)
   }
}

WM_HSCROLL(wParam, lParam, msg, hwnd)
{
   static SIF_ALL=0x17, SCROLL_STEP=10
   bar := 0 ; SB_HORZ=0, SB_VERT=1

   VarSetCapacity(si, 28, 0)
   NumPut(28, si, "UInt") ; cbSize
   NumPut(SIF_ALL, si, 4, "UInt") ; fMask
   if !DllCall("GetScrollInfo", Ptr, hwnd, Int, bar, Ptr, &si)
     return

   VarSetCapacity(rect, 16)
   DllCall("GetClientRect", Ptr, hwnd, Ptr, &rect)

   new_pos := NumGet(si, 20, "UInt") ; nPos

   action := wParam & 0xFFFF
   if action = 0 ; SB_LINEUP
     new_pos -= SCROLL_STEP
   else if action = 1 ; SB_LINEDOWN
     new_pos += SCROLL_STEP
   else if action = 2 ; SB_PAGEUP
     new_pos -= NumGet(rect, 12, "Int") - SCROLL_STEP
   else if action = 3 ; SB_PAGEDOWN
     new_pos += NumGet(rect, 12, "Int") - SCROLL_STEP
   else if (action = 5 || action = 4) ; SB_THUMBTRACK || SB_THUMBPOSITION
     new_pos := wParam>>16
   else if action = 6 ; SB_TOP
     new_pos := NumGet(si, 8, "Int") ; nMin
   else if action = 7 ; SB_BOTTOM
     new_pos := NumGet(si, 12, "Int") ; nMax
   else
     return

   min := NumGet(si, 8, "Int") ; nMin
   max := NumGet(si, 12, "Int") - NumGet(si, 16, "UInt") ; nMax-nPage
   new_pos := new_pos > max ? max : new_pos
   new_pos := new_pos < min ? min : new_pos

   old_pos := NumGet(si, 20, "Int") ; nPos
   x := old_pos-new_pos

   ; Scroll contents of window and invalidate uncovered area.
   DllCall("ScrollWindow", Ptr, hwnd, Int, x, Int, y, UInt, 0, UInt, 0)

   ; Update scroll bar.
   NumPut(new_pos, si, 20, "Int") ; nPos
   DllCall("SetScrollInfo", Ptr, hwnd, Int, bar, Ptr, &si, Int, 1)

  if !GetKeyState("lButton","P")
    WinSet,redraw,,ahk_id %guiid%
}


#if (!App and (UnderSomething() or UnderApp()))
$*wheelup::
if work
{
  if notebook
  {
    gain+=0.05
    newvol+=2
    gosub,wheeeel
    gosub,wheeeeeeel
  }
  else
  {
    newvol++
    gosub,wheeeel
  }
}
else
{
  newvol++
  gosub,wheeeel
}
settimer,removetooltip,-1000
return

$*wheeldown::
if work
{
  if notebook
  {
    gain-=0.05
    gosub,wheeeeeeel
  }
  else
  {
    newvol--
    gosub,wheeeel
  }
}
else
{
  newvol--
  gosub,wheeeel
}
settimer,removetooltip,-1000
return

#if

wheeeel:
newvol:= newvol<0 ? 0 : newvol>100 ? 100 : newvol
GuiControl,,newvolset,% newvol
VA_SetMasterVolume(newvol,"","")
if UnderSomething()
{
  if !InfoShow
  {
    InfoShow:=1
    Gui,5:Show,center NoActivate
    Gui,5:+AlwaysOnTop
  }
  GuiControl,5:,InfoVolume,% Round(newvol)
  GuiControl,5:,InfoVolumep2,% Round(newvol)
  GuiControl,5:,InfoVolumep,% Round(newvol)
  settimer,HideInfo,-1000
}
return

wheeeeeeel:
wait:=200+voltime
gain:=gain<0 ? 0 : gain>2 ? 2 : gain
tmpgain:=Round(gain*100)
GuiControl,,Setgain,% tmpgain
if UnderSomething()
{
  if !InfoShow
  {
    InfoShow:=1
    Gui,5:Show,center NoActivate
    Gui,5:+AlwaysOnTop
  }
  GuiControl,5:,InfoVolume,% tmpgain
  GuiControl,5:,InfoVolumep2,% tmpgain//2
  GuiControl,5:,InfoVolumep,% tmpgain//2
  settimer,HideInfo,-1000
}
if gain=0
  vol:=newvol:=0
return

HideInfo:
InfoShow:=0
Gui,5:Hide
return

isWindowFullScreen(WinID)
{
  WinGet,WinMinMax,MinMax,ahk_pid %WinID%
  WinGetPos,WinX,WinY,WinW,WinH,ahk_pid %WinID%
  if (WinMinMax=0 and WinX=0 and WinY=0 and WinW=A_ScreenWidth and WinH=A_ScreenHeight)
  {
    WinGetClass,WinClass,ahk_pid %WinID%
    WinGet,WinProcessName,ProcessName,ahk_pid %WinID%
    SplitPath,WinProcessName,,,WinProcessExt
    if (WinClass!="Progman" and WinClass!="WorkerW" and WinProcessExt!="scr")
      return true
  }
}

UnderApp()
{
  global ListWin
  mousegetpos,,,w
  winget,pid,PID,ahk_id %w%
  if instr(ListWin,pid+0)
    return 1
}

UnderSomething()
{
  if !WheelVol
    return
;-----------------
; Ниже можно добавлять условия, в которых возможна регулировка громкости роликом
  mousegetpos,x,y,w
;  wingetclass,c,ahk_id %w%
;  if (c="Shell_TrayWnd")
;    return 1
  if (y>a_screenheight-32)
    return 1
}

Update
Обновлен код:
упрощены некоторые функции;
добавлено описание настройкам при наведении мыши.

Update 2
Добавлено:
кнопка сброса настроек по умолчанию;
настройка времени сброса громкости при тишине;
Fade In - быстрое нарастание после "тишины" и настройка ее скорости.

Update 3
Исправлены некоторые мелкие ошибки.

Update 4
Сменилась формула расчета входной громкости и ограничителя громкости в режиме "без сглаживания с 0 задержкой".

Update 5
Устранена небольшая ошибка в "доводке звука до центра громкости", ничего серьезного.

Update 6
Добавлена функция гашения коротких импульсов заданной длинны.

Update 7
Теперь можно пользоваться на ноутбуке. Просто поставьте галочку "Ноутбук" в настройках.

Update 8
Исправил мелкие ошибки после добавления нового режима.

Update 9
Поправил интерфейс.

Update 10
Добавил "псевдо-FadeOut" - при отсутствии сигнала, с заданной скоростью уменьшает громкость.

Update 11
Исправление ошибок.

Update 12
Улучшен "детектор" импульсов, теперь "гашение импульсов" соответствует описанию.
Добавлена возможность сбрасывать громкость до нуля (почти) вместо "установленной".

Update 13
Добавлен Микшер. Теперь можно активировать нормализацию для каждого приложения в отдельности.

Старая версия сохранена в архиве.

Update 14
Исправление ошибок.

Update 15
Ещё несколько ошибок исправлено.

Update 16
И ещё несколько ошибок исправлено.

Update 17
Исправлена ошибка запуска компонентов микшера.

Update 18
Исправлена ошибка с пропаданием окна настроек.
Компоненты микшера теперь используют PID процесса вместо имени процесса.
Если задать "время отсутствия сигнала" = 0, то громкость не будет сбрасываться.

Update 19
Исправление мелких ошибок.

Update 20
Добавлена возможность регулировать громкость роликом над панелью задач. Включается в настройках.
Также можете сами добавить условия, в которых регулировка роликом активна, в конце исходного скрипта (отмечено комментарием).

Update 21
Добавлена настройка "Количество измерений для усреднения" в "доводке звука до центра". Мелкие доработки.
Изменён путь настроек: старый - "SOFTWARE\DF\Compressor"; новый - "SOFTWARE\AlectricSoft\Compressor".

Update 22
Ещё раз исправлена линейность звука.
Добавлена настройка линейности звука.

Update 23
Исправлена ошибка при использовании полно-экранных приложений и "Микшера", эти приложения могут не корректно завершаться, т.к. не поддерживают "сворачивания".

Update 24
Исправлены ошибки интерфейса при измененном масштабе в Windows.

В прикрепленном файле: скомпилированный вариант (для тех у кого проблемы), иконка и исходники.
Ссылка рабочая! Не смотрите на следующие посты.

Post's attachments

Compressor_win7.zip 465.88 kb, 2 downloads since 2019-02-06 

You don't have the permssions to download the attachments of this post.
Win 7 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

2

Re: AHK: Аудио компрессор для windows 7,8,10

Сссылка битая, архив тоже.
Вкратце расскажите что делает скрипт.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.01 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

3 (изменено: Alectric, 2013-08-22 18:18:47)

Re: AHK: Аудио компрессор для windows 7,8,10

Как тогда архивы загружать на сайт если битая ссылка получается (в архиве VA.ahk, сам скрипт и иконка для скрипта)?

Компрессор нужен для выравнивания громкости.
Т.е. если воспроизводится тихий звук в плеере или еще где-либо - компрессор повысит громкость; если звук слишком громкий, то соответственно понизит.
Уровни срабатывания и задержка выставляются в Gui, а также доводка звука до "центра" громкости.

В основном скрипт пригодился бы для меломанов и занимающихся звуком/музыкой.
И лучше всего использовать на стационарных компьютерах с аудиосистемой и регулировать громкость на аудиосистеме, в смысле на ноутбуке к примеру невозможно будет настроить громкость так как она выравняется скриптом.
Настройки сохраняются в реестре.


PS: Кстати если кто-нибудь знает как осуществить функции VA.ahk (определение пиковой выходной громкости сигнала) на Win XP, буду безмерно благодарен.

Здесь VA.ahk https://dl.dropbox.com/u/20532918/Lib/VA-2.3.zip
Если ссылка ниже опять битая.

Post's attachments

VA.ahk 32.63 kb, 22 downloads since 2013-08-22 

You don't have the permssions to download the attachments of this post.
Win 7 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

4

Re: AHK: Аудио компрессор для windows 7,8,10

Компрессор нужен для выравнивания громкости.

Штука нужная.

Как тогда архивы загружать на сайт если битая ссылка получается (в архиве VA.ahk, сам скрипт и иконка для скрипта)?

Пишет архив повреждён. В ZIP`e у меня нормально всегда выкладывались.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.01 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

5 (изменено: Alectric, 2014-04-06 07:10:05)

Re: AHK: Аудио компрессор для windows 7,8,10

Выкладываю файл который нормально открывается, скачиваю сам и он не открывается...

Win 7 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

6 (изменено: Zanoza, 2013-08-24 02:09:31)

Re: AHK: Аудио компрессор для windows 7,8,10

Приложение очень полезное , давно искал подобное. Особенно при просмотре фильмов ночью.

Win10 x64

7

Re: AHK: Аудио компрессор для windows 7,8,10

Хоть кому-то пригодилось. )

Win 7 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

8 (изменено: serzh82saratov, 2013-08-24 20:13:54)

Re: AHK: Аудио компрессор для windows 7,8,10

Конечно. Вещь серьёзная. Тут только код курить и курить. Сейчас бытовой  возможности нет проверить. Меня эта фича в Xonar DG не устраивает. Долго искал стороннее сравнить. Так что пригодится точно!

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.30.01 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

9

Re: AHK: Аудио компрессор для windows 7,8,10

Объясните непосвящённым, что эта штука должна делать.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

10

Re: AHK: Аудио компрессор для windows 7,8,10

Протестил - (Windws 7 x64) -работает отлично! Спасибо автору . И всем большое  спасибо за поддержку!!!

Win10 x64

11 (изменено: Alectric, 2014-04-05 08:10:45)

Re: AHK: Аудио компрессор для windows 7,8,10

teadrinker пишет:

Объясните непосвящённым, что эта штука должна делать.

В 3-ем посте описано.

Win 7 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

12 (изменено: Alectric, 2014-04-06 07:11:15)

Re: AHK: Аудио компрессор для windows 7,8,10

Update: Обновил код в 1-ом посте.

Обнаружилась странная проблема: на компе у друга почему-то скрипт сильно "ест" ресурс процессора (30 - 50% на 2х ядерном).
Прошу желающих протестировать скомпилированный скрипт и отписаться.

Win 7 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

13 (изменено: Irbis, 2014-04-05 11:17:53)

Re: AHK: Аудио компрессор для windows 7,8,10

На планшете с win 8.1 включенный скрипт потребляет 0.1% .. 0.8% ресурсов процессора, по сведениям диспетчера задач.

Upd:Если "поиграть" с уровнями, чтобы скрипт постоянно был в работе, нагрузка возрастает до ~3.5%, что тоже вряд ли попадает в категорию 'сильно "ест" ресурс'.

14 (изменено: Alectric, 2014-05-05 18:02:59)

Re: AHK: Аудио компрессор для windows 7,8,10

Исправил проблему с утечкой памяти и ресурса процессора.

В цикле был повторный запрос, на случай, если звуковое устройство не будет отвечать (занято другим процессом или служба Windows Audio отключалась на короткое время):

      audioMeter:=VA_GetAudioMeter()
      VA_GetDevicePeriod("capture", devicePeriod)

Заменил его воспроизведением стандартного тихого звука и последующей проверкой (~каждые 15 сек), если проверка не пройдет скрипт перезапустится.


Спустя 37 минут:
Нет... ошибся, проблема с утечкой еще существует...


Спустя 8 минут:
Нашел условия возникновения утечки: при запуске этого скрипта через другой командой "Run".

    run,Compressor_win7.ahk,,UseErrorLevel

Причину не могу понять.

При том, что при использовании простого скрипта запуска:

f1::
    run,Compressor_win7.ahk,,UseErrorLevel
return

- все в порядке...


Спустя некоторое время:
Так и не понял происходящего, решил использовать другой метод запуска, при котором все в порядке.
Т.е. проблема решена.

Win 7 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

15 (изменено: define, 2014-05-22 11:41:10)

Re: AHK: Аудио компрессор для windows 7,8,10

в 3-ем посте - VA.ahk -по ссылкам две разные сборки, какую использовать?

решил использовать другой метод запуска, при котором все в порядке.

А каком методе идет речь?

16 (изменено: Alectric, 2014-05-22 22:00:04)

Re: AHK: Аудио компрессор для windows 7,8,10

define пишет:

в 3-ем посте - VA.ahk -по ссылкам две разные сборки, какую использовать?

Можно использовать любую сборку, конечно если одна из них не "битая".

define пишет:

А каком методе идет речь?

Это у меня была проблема, когда этот скрипт запускал другой мой скрипт функцией "Run", так что не обращайте внимания на то, как я сам с собой разговаривал , с этим скриптом компрессора все в порядке.

Win 7 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

17 (изменено: Alectric, 2014-08-13 20:39:02)

Re: AHK: Аудио компрессор для windows 7,8,10

Update 4
Сменилась формула расчета входной громкости и ограничителя громкости в режиме "без сглаживания с 0 задержкой".
Теперь "ограничение" работает более линейно относительно "ощущаемой" громкости.

Win 7 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

18

Re: AHK: Аудио компрессор для windows 7,8,10

Сделал файл compressor.ahk вставил в него код. В той же папке положил VA.ahk и при запуске выдает ошибку.
https://dl.dropboxusercontent.com/u/5519283/temp/ahk_audio_compressor.jpg
Помогите плиз. Давно ищу подобную программу.

19

Re: AHK: Аудио компрессор для windows 7,8,10

vasotelvi, Вам сюда.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

20 (изменено: Alectric, 2014-08-13 20:45:39)

Re: AHK: Аудио компрессор для windows 7,8,10

Update 5
Устранена небольшая ошибка в "доводке звука до центра громкости", ничего серьезного.

Win 7 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

21

Re: AHK: Аудио компрессор для windows 7,8,10

Update 6
Добавлена функция гашения коротких импульсов заданной длинны.

Win 7 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

22

Re: AHK: Аудио компрессор для windows 7,8,10

Update 7
Теперь можно пользоваться на ноутбуке. Просто поставьте галочку "Ноутбук" в настройках.

Если встретите ошибки - пишите.

Win 7 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

23 (изменено: Alectric, 2015-01-13 17:10:48)

Re: AHK: Аудио компрессор для windows 7,8,10

Update 8 - 17:52 13.01.2015
Исправил мелкие, но неприятные, ошибки после добавления нового режима.

Win 7 x64
AHK v1.1.24.00
                       Справка тебе в помощь.

24 (изменено: mate26, 2015-05-06 13:15:07)

Re: AHK: Аудио компрессор для windows 7,8,10

Очень необходимая вещь. Очень прошу объяснить назначение регуляторов

P.S. Извините, разобрался... Нужно было немного курсор задержать на регуляторе.

25 (изменено: Alectric, 2015-05-24 09:21:50)

Re: AHK: Аудио компрессор для windows 7,8,10

Если кому не лень проверте работает ли на Win 10.

Win 7 x64
AHK v1.1.24.00
                       Справка тебе в помощь.