diff --git a/README.md b/README.md index 81c1dbb..0c53ccf 100644 --- a/README.md +++ b/README.md @@ -8,14 +8,14 @@ For past/future changes to this project refer to: [CHANGELOG](CHANGELOG.md) ## Tested against -- Basic 1.0.8.8 -- Banana 2.0.6.8 -- Potato 3.0.2.8 +- Basic 1.0.8.8 +- Banana 2.0.6.8 +- Potato 3.0.2.8 ## Requirements -- [Voicemeeter](https://voicemeeter.com/) -- Powershell 5.1+ or Powershell 7.2+ +- [Voicemeeter](https://voicemeeter.com/) +- Powershell 5.1+ or Powershell 7.2+ ## Installation @@ -35,9 +35,9 @@ When prompted you will need to accept PSGallery as a trusted repository. More Info: -- [PowerShellGet](https://docs.microsoft.com/en-us/powershell/scripting/gallery/installing-psget?view=powershell-7.1) -- [NuGet](https://www.powershellgallery.com/packages/NuGet/1.3.3) -- [PSGallery](https://docs.microsoft.com/en-gb/powershell/scripting/gallery/overview?view=powershell-7.1) +- [PowerShellGet](https://docs.microsoft.com/en-us/powershell/scripting/gallery/installing-psget?view=powershell-7.1) +- [NuGet](https://www.powershellgallery.com/packages/NuGet/1.3.3) +- [PSGallery](https://docs.microsoft.com/en-gb/powershell/scripting/gallery/overview?view=powershell-7.1) #### Direct download: @@ -75,14 +75,14 @@ finally { $vmr.Logout() } Voicemeeter factory function can be: -- Get-RemoteBasic -- Get-RemoteBanana -- Get-RemotePotato +- Get-RemoteBasic +- Get-RemoteBanana +- Get-RemotePotato Added in `v3` you may also use the following entry/exit points: -- Connect-Voicemeeter -- Disconnect-Voicemeeter +- Connect-Voicemeeter +- Disconnect-Voicemeeter `Connect-Voicemeeter` takes a single parameter `Kind`. @@ -115,31 +115,31 @@ $vmr.Logout() The following strip commands are available: -- mute: boolean -- mono: boolean -- mc: boolean -- k: int, from 0 to 4 -- solo: boolean -- A1-A5: boolean -- B1-B3: boolean -- limit: int, from -40 to 12 -- gain: float, from -60.0 to 12.0 -- label: string -- reverb: float, from 0.0 to 10.0 -- delay: float, from 0.0 to 10.0 -- fx1: float, from 0.0 to 10.0 -- fx2: float, from 0.0 to 10.0 -- pan_x: float, from -0.5 to 0.5 -- pan_y: float, from 0.0 to 1.0 -- color_x: float, from -0.5 to 0.5 -- color_y: float, from 0.0 to 1.0 -- fx_x: float, from -0.5 to 0.5 -- fx_y: float, from 0.0 to 1.0 -- postreverb: boolean -- postdelay: boolean -- postfx1: boolean -- postfx2: boolean -- gainlayer0-gainlayer7: float +- mute: boolean +- mono: boolean +- mc: boolean +- k: int, from 0 to 4 +- solo: boolean +- A1-A5: boolean +- B1-B3: boolean +- limit: int, from -40 to 12 +- gain: float, from -60.0 to 12.0 +- label: string +- reverb: float, from 0.0 to 10.0 +- delay: float, from 0.0 to 10.0 +- fx1: float, from 0.0 to 10.0 +- fx2: float, from 0.0 to 10.0 +- pan_x: float, from -0.5 to 0.5 +- pan_y: float, from 0.0 to 1.0 +- color_x: float, from -0.5 to 0.5 +- color_y: float, from 0.0 to 1.0 +- fx_x: float, from -0.5 to 0.5 +- fx_y: float, from 0.0 to 1.0 +- postreverb: boolean +- postdelay: boolean +- postfx1: boolean +- postfx2: boolean +- gainlayer0-gainlayer7: float for example: @@ -157,15 +157,15 @@ mc, k for virtual strips only. The following strip.comp commands are available: -- knob: float, from 0.0 to 10.0 -- gainin: float, from -24.0 to 24.0 -- ratio: float, from 1.0 to 8.0 -- threshold: float, from -40.0 to -3.0 -- attack: float, from 0.0 to 200.0 -- release: float, from 0.0 to 5000.0 -- knee: float, 0.0 to 1.0 -- gainout: float, from -24.0 to 24.0 -- makeup: boolean +- knob: float, from 0.0 to 10.0 +- gainin: float, from -24.0 to 24.0 +- ratio: float, from 1.0 to 8.0 +- threshold: float, from -40.0 to -3.0 +- attack: float, from 0.0 to 200.0 +- release: float, from 0.0 to 5000.0 +- knee: float, 0.0 to 1.0 +- gainout: float, from -24.0 to 24.0 +- makeup: boolean for example: @@ -177,13 +177,13 @@ $vmr.strip[3].comp.attack = 8.5 The following strip.gate commands are available: -- knob: float, from 0.0 to 10.0 -- threshold: float, from -60.0 to -10.0 -- damping: float, from -60.0 to -10.0 -- bpsidechain: int, from 100 to 4000 -- attack: float, from 0.0 to 1000.0 -- hold: float, from 0.0 to 5000.0 -- release: float, from 0.0 to 5000.0 +- knob: float, from 0.0 to 10.0 +- threshold: float, from -60.0 to -10.0 +- damping: float, from -60.0 to -10.0 +- bpsidechain: int, from 100 to 4000 +- attack: float, from 0.0 to 1000.0 +- hold: float, from 0.0 to 5000.0 +- release: float, from 0.0 to 5000.0 for example: @@ -195,7 +195,7 @@ $vmr.strip[3].gate.threshold = -40.5 The following strip.denoiser commands are available: -- knob: float, from 0.0 to 10.0 +- knob: float, from 0.0 to 10.0 for example: @@ -205,8 +205,8 @@ $vmr.strip[3].denoiser.knob = 5 #### AppGain | AppMute -- `AppGain(amount, gain)` : string, float -- `AppMute(amount, mutestate)` : string, boolean +- `AppGain(amount, gain)` : string, float +- `AppMute(amount, mutestate)` : string, boolean for example: @@ -215,19 +215,33 @@ $vmr.strip[5].AppGain("Spotify", 0.5) $vmr.strip[5].AppMute("Spotify", $true) ``` +#### levels + +The following strip.level commands are available: + +- PreFader() +- PostFader() +- PostMute() + +for example: + +```powershell +$vmr.strip[2].levels.PreFader() -Join ', ' | Write-Host +``` + ### Bus The following bus commands are available: -- mute: bool -- mono: bool -- limit: int, from -40 to 12 -- gain: float, from -60.0 to 12.0 -- label: string -- returnreverb: float, from 0.0 to 10.0 -- returndelay: float, from 0.0 to 10.0 -- returnfx1: float, from 0.0 to 10.0 -- returnfx2: float, from 0.0 to 10.0 +- mute: bool +- mono: bool +- limit: int, from -40 to 12 +- gain: float, from -60.0 to 12.0 +- label: string +- returnreverb: float, from 0.0 to 10.0 +- returndelay: float, from 0.0 to 10.0 +- returnfx1: float, from 0.0 to 10.0 +- returnfx2: float, from 0.0 to 10.0 for example: @@ -239,22 +253,22 @@ $vmr.bus[3].returnreverb = 5.7 The following bus.mode members are available: -- normal: boolean -- amix: boolean -- bmix: boolean -- repeat: boolean -- composite: boolean -- tvmix: boolean -- upmix21: boolean -- upmix41: boolean -- upmix61: boolean -- centeronly: boolean -- lfeonly: boolean -- rearonly: boolean +- normal: boolean +- amix: boolean +- bmix: boolean +- repeat: boolean +- composite: boolean +- tvmix: boolean +- upmix21: boolean +- upmix41: boolean +- upmix61: boolean +- centeronly: boolean +- lfeonly: boolean +- rearonly: boolean The following bus.mode commands are available: -- Get(): returns the current bus mode. +- Get(): returns the current bus mode. for example: @@ -264,18 +278,30 @@ $vmr.bus[0].mode.centeronly = $true $vmr.bus[0].mode.Get() ``` +#### levels + +The following strip.level commands are available: + +- All() + +for example: + +```powershell +$vmr.bus[2].levels.All() -Join ', ' | Write-Host +``` + ### Strip|Bus #### device The following strip.device | bus.device commands are available: -- name: string -- sr: int -- wdm: string -- ks: string -- mme: string -- asio: string +- name: string +- sr: int +- wdm: string +- ks: string +- mme: string +- asio: string for example: @@ -291,8 +317,8 @@ wdm, ks, mme, asio are defined as write only. The following strip.eq | bus.eq commands are available: -- on: boolean -- ab: boolean +- on: boolean +- ab: boolean for example: @@ -303,8 +329,8 @@ $vmr.bus[0].eq.ab = $false #### FadeTo | FadeBy -- `FadeTo(amount, time)` : float, int -- `FadeBy(amount, time)` : float, int +- `FadeTo(amount, time)` : float, int +- `FadeBy(amount, time)` : float, int Modify gain to or by the selected amount in db over a time interval in ms. @@ -319,9 +345,9 @@ $vmr.bus[0].FadeBy(-10, 500) Three modes defined: state, stateonly and trigger. -- State runs associated scripts -- Stateonly does not run associated scripts -- Index range (0, 69) +- State runs associated scripts +- Stateonly does not run associated scripts +- Index range (0, 69) ```powershell $vmr.button[3].state = $true @@ -333,19 +359,19 @@ $vmr.button[5].trigger = $true ### VBAN -- vmr.vban.enable: Toggle VBAN on or off. Accepts a boolean value. +- vmr.vban.enable: Toggle VBAN on or off. Accepts a boolean value. For each vban in/out stream the following parameters are defined: -- on: boolean -- name: string -- ip: string -- port: int from 1024 - 65535 -- sr: int (11025, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000) -- channel: int from 1 to 8 -- bit: int 16 or 24 -- quality: int from 0 to 4 -- route: int from 0 to 8 +- on: boolean +- name: string +- ip: string +- port: int from 1024 - 65535 +- sr: int (11025, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000) +- channel: int from 1 to 8 +- bit: int 16 or 24 +- quality: int from 0 to 4 +- route: int from 0 to 8 SR, channel and bit are defined as readonly for instreams. Attempting to write to those parameters will throw an error. They are read and write for outstreams. @@ -366,16 +392,16 @@ Certain 'special' commands are defined by the API as performing actions rather t The following methods are available: -- show -- hide -- restart -- shutdown -- Load(filepath) +- show +- hide +- restart +- shutdown +- Load(filepath) The following properties are write only and accept boolean values: -- showvbanchat -- lock +- showvbanchat +- lock example: @@ -391,18 +417,18 @@ $vmr.command.Load("path/to/filename.xml") The following methods are available: -- play -- stop -- pause -- record -- ff -- rew +- play +- stop +- pause +- record +- ff +- rew The following properties accept boolean values. -- loop -- A1 - A5 -- B1 - B3 +- loop +- A1 - A5 +- B1 - B3 example: @@ -460,9 +486,9 @@ will load a config file at profiles/banana/config.psd1 for Voicemeeter Banana. Access to lower level Getters and Setters are provided with these functions: -- `$vmr.Getter(param)`: For getting the value of a parameter expected to return a value other than string. -- `$vmr.Getter_String(param)`: For getting the value of any parameter expected to return a string. -- `$vmr.Setter(param, value)`: For setting the value of any parameter. +- `$vmr.Getter(param)`: For getting the value of a parameter expected to return a value other than string. +- `$vmr.Getter_String(param)`: For getting the value of any parameter expected to return a string. +- `$vmr.Setter(param, value)`: For setting the value of any parameter. ```powershell $vmr.Getter('Strip[2].Mute') @@ -471,7 +497,7 @@ $vmr.Setter('Strip[4].Label', 'stripname') $vmr.Setter('Strip[0].Gain', -3.6) ``` -- `$vmr.SendText`: Set parameters by script +- `$vmr.SendText`: Set parameters by script ```powershell $vmr.SendText("strip[0].mute=1;strip[2].gain=3.8;bus[1].eq.On=1") @@ -479,17 +505,17 @@ $vmr.Setter('Strip[0].Gain', -3.6) Access to lower level polling functions are provided with these functions: -- `$vmr.PDirty`: Returns true if a parameter has been updated. -- `$vmr.MDirty`: Returns true if a macrobutton has been updated. +- `$vmr.PDirty`: Returns true if a parameter has been updated. +- `$vmr.MDirty`: Returns true if a macrobutton has been updated. ### Run tests Run tests using .\tests\pre-commit.ps1 which accepts the following parameters: -- `kind`: Run tests of this kind -- `tag`: Run tests tagged with this marker (currently `higher` or `lower`) -- `num`: Run this number of tests -- `log`: Write summary log file +- `kind`: Run tests of this kind +- `tag`: Run tests tagged with this marker (currently `higher` or `lower`) +- `num`: Run this number of tests +- `log`: Write summary log file Run tests from repository root in a subshell and write logs, like so: @@ -497,4 +523,4 @@ Run tests from repository root in a subshell and write logs, like so: ### Official Documentation -- [Voicemeeter Remote C API](https://github.com/onyx-and-iris/Voicemeeter-SDK/blob/update-docs/VoicemeeterRemoteAPI.pdf) +- [Voicemeeter Remote C API](https://github.com/onyx-and-iris/Voicemeeter-SDK/blob/update-docs/VoicemeeterRemoteAPI.pdf) diff --git a/lib/base.ps1 b/lib/base.ps1 index c621e84..543fd94 100644 --- a/lib/base.ps1 +++ b/lib/base.ps1 @@ -23,7 +23,7 @@ function Login { New-Variable -Name vmExe -Value 0 if ( $kindId -eq "basic" ) { $vmExe = 1 } - elseif ( $kindId -eq "banana" ) { $vmExe = 2 } + elseif ( $kindId -eq "banana" ) { $vmExe = 2 } elseif ( $kindId -eq "potato" ) { $vmExe = $(if ([Environment]::Is64BitOperatingSystem) { 6 } else { 3 }) } @@ -203,3 +203,18 @@ function Set_By_Script { Write-Warning $_.Exception.ErrorMessage() } } + +function Get_Level { + param( + [int64]$MODE, [int64]$INDEX + ) + New-Variable -Name ptr -Value 0.0 + try { + $retval = [int][Voicemeeter.Remote]::VBVMR_GetLevel($MODE, $INDEX, [ref]$ptr) + if ($retval) { throw [CAPIError]::new($retval, $MyInvocation.MyCommand) } + } + catch [CAPIError] { + Write-Warning $_.Exception.ErrorMessage() + } + [float]$ptr +} \ No newline at end of file diff --git a/lib/binding.ps1 b/lib/binding.ps1 index bd69faf..ad23456 100644 --- a/lib/binding.ps1 +++ b/lib/binding.ps1 @@ -47,6 +47,9 @@ function Setup_DLL { [DllImport(@"$dll")] public static extern int VBVMR_SetParameters(String param); + + [DllImport(@"$dll")] + public static extern int VBVMR_GetLevel(Int64 mode, Int64 index, ref float ptr); "@ Add-Type -MemberDefinition $Signature -Name Remote -Namespace Voicemeeter -PassThru | Out-Null diff --git a/lib/bus.ps1 b/lib/bus.ps1 index c8198f8..ba2c9f0 100644 --- a/lib/bus.ps1 +++ b/lib/bus.ps1 @@ -33,6 +33,7 @@ class IBus { class Bus : IBus { [Object]$mode [Object]$eq + [Object]$levels Bus ([int]$index, [Object]$remote) : base ($index, $remote) { AddBoolMembers -PARAMS @('mono', 'mute') @@ -41,6 +42,7 @@ class Bus : IBus { $this.mode = [Mode]::new($index, $remote) $this.eq = [Eq]::new($index, $remote) + $this.levels = [Levels]::new($index, $remote) } [void] FadeTo ([single]$target, [int]$time) { @@ -52,6 +54,37 @@ class Bus : IBus { } } +class Levels : IBus { + [int]$init + [int]$offset + + Levels ([int]$index, [Object]$remote) : base ($index, $remote) { + $this.init = $index * 8 + $this.offset = 8 + } + + [float] Convert([float]$val) { + if ($val -gt 0) { + return [math]::Round(20 * [math]::Log10($val), 1) + } + else { + return -200.0 + } + } + + [System.Collections.ArrayList] Getter([int]$mode) { + [System.Collections.ArrayList]$vals = @() + $this.init..$($this.init + $this.offset - 1) | ForEach-Object { + $vals.Add($this.Convert($(Get_Level -MODE $mode -INDEX $_))) + } + return $vals + } + + [System.Collections.ArrayList] All() { + return $this.Getter(3) + } +} + class Mode : IBus { [System.Collections.ArrayList]$modes diff --git a/lib/strip.ps1 b/lib/strip.ps1 index fdd7253..3158855 100644 --- a/lib/strip.ps1 +++ b/lib/strip.ps1 @@ -27,6 +27,8 @@ class IStrip { } class Strip : IStrip { + [Object]$levels + Strip ([int]$index, [Object]$remote) : base ($index, $remote) { AddBoolMembers -PARAMS @('mono', 'solo', 'mute') AddIntMembers -PARAMS @('limit') @@ -35,6 +37,8 @@ class Strip : IStrip { AddChannelMembers AddGainlayerMembers + + $this.levels = [Levels]::new($index, $remote) } [string] ToString() { @@ -50,6 +54,52 @@ class Strip : IStrip { } } +class Levels : IStrip { + [int]$init + [int]$offset + + Levels ([int]$index, [Object]$remote) : base ($index, $remote) { + $p_in = $remote.kind.p_in + if ($index -lt $p_in) { + $this.init = $index * 2 + $this.offset = 2 + } + else { + $this.init = ($p_in * 2) + (($index - $p_in) * 8) + $this.offset = 8 + } + } + + [float] Convert([float]$val) { + if ($val -gt 0) { + return [math]::Round(20 * [math]::Log10($val), 1) + } + else { + return -200.0 + } + } + + [System.Collections.ArrayList] Getter([int]$mode) { + [System.Collections.ArrayList]$vals = @() + $this.init..$($this.init + $this.offset - 1) | ForEach-Object { + $vals.Add($this.Convert($(Get_Level -MODE $mode -INDEX $_))) + } + return $vals + } + + [System.Collections.ArrayList] PreFader() { + return $this.Getter(0) + } + + [System.Collections.ArrayList] PostFader() { + return $this.Getter(1) + } + + [System.Collections.ArrayList] PostMute() { + return $this.Getter(2) + } +} + class PhysicalStrip : Strip { [Object]$comp [Object]$gate