From 0c60c5e6c544b116921ece28e915511c775b26ed Mon Sep 17 00:00:00 2001 From: pblivingston <71585805+pblivingston@users.noreply.github.com> Date: Tue, 9 Dec 2025 11:14:12 -0500 Subject: [PATCH 1/5] Create io.ps1 - IOControl - IOLevels - IOEq - IODevice --- lib/io.ps1 | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 lib/io.ps1 diff --git a/lib/io.ps1 b/lib/io.ps1 new file mode 100644 index 0000000..07982b9 --- /dev/null +++ b/lib/io.ps1 @@ -0,0 +1,151 @@ +class IOControl : IRemote { + IOControl ([int]$index, [Object]$remote) : base ($index, $remote) { + AddBoolMembers -PARAMS @('mute') + AddFloatMembers -PARAMS @('gain') + AddStringMembers -PARAMS @('label') + } + + [void] FadeTo ([single]$target, [int]$time) { + $this.Setter('FadeTo', "($target, $time)") + } + + [void] FadeBy ([single]$target, [int]$time) { + $this.Setter('FadeBy', "($target, $time)") + } +} + +class IOLevels : IRemote { + IOLevels ([int]$index, [Object]$remote) : base ($index, $remote) { + } + + hidden [single] Convert([single]$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 + } +} + +class IOEq : IRemote { + [System.Collections.ArrayList]$channel + [string]$kindOfEq + + IOEq ([int]$index, [Object]$remote, [string]$kindOfEq) : base ($index, $remote) { + $this.kindOfEq = $kindOfEq + + AddBoolMembers -PARAMS @('on', 'ab') + + $this.channel = @() + for ($ch = 0; $ch -lt $remote.kind.eq_ch[$this.kindOfEq]; $ch++) { + $this.channel.Add([EqChannel]::new($ch, $remote, $this.identifier())) + } + } + + [void] Load ([string]$filename) { + $param = 'Command.Load{0}Eq[{1}]' -f $this.kindOfEq, $this.index + $this.remote.Setter($param, $filename) + } + + [void] Save ([string]$filename) { + $param = 'Command.Save{0}Eq[{1}]' -f $this.kindOfEq, $this.index + $this.remote.Setter($param, $filename) + } +} + +class EqChannel : IRemote { + [System.Collections.ArrayList]$cell + [string]$eqId + + EqChannel ([int]$index, [Object]$remote, [string]$eqId) : base ($index, $remote) { + $this.eqId = $eqId + + $this.cell = @() + $cellCount = $this.remote.kind.cells + for ($c = 0; $c -lt $cellCount; $c++) { + $this.cell.Add([EqCell]::new($c, $remote, $this.identifier())) + } + } + + [string] identifier () { + return '{0}.Channel[{1}]' -f $this.eqId, $this.index + } +} + +class EqCell : IRemote { + [string]$channelId + + EqCell ([int]$index, [Object]$remote, [string]$channelId) : base ($index, $remote) { + $this.channelId = $channelId + + AddBoolMembers -PARAMS @('on') + AddIntMembers -PARAMS @('type') + AddFloatMembers -PARAMS @('f', 'gain', 'q') + } + + [string] identifier () { + return '{0}.Cell[{1}]' -f $this.channelId, $this.index + } +} + +class IODevice : IRemote { + IODevice ([int]$index, [Object]$remote) : base ($index, $remote) { + } + + hidden $_name = $($this | Add-Member ScriptProperty 'name' ` + { + $this.Getter_String('name') + } ` + { + return Write-Warning ("ERROR: $($this.identifier()).name is read only") + } + ) + + hidden $_sr = $($this | Add-Member ScriptProperty 'sr' ` + { + [int]$this.Getter('sr') + } ` + { + return Write-Warning ("ERROR: $($this.identifier()).sr is read only") + } + ) + + hidden $_wdm = $($this | Add-Member ScriptProperty 'wdm' ` + { + return Write-Warning ("ERROR: $($this.identifier()).wdm is write only") + } ` + { + param([string]$arg) + return $this.Setter('wdm', $arg) + } + ) + + hidden $_ks = $($this | Add-Member ScriptProperty 'ks' ` + { + return Write-Warning ("ERROR: $($this.identifier()).ks is write only") + } ` + { + param([string]$arg) + return $this.Setter('ks', $arg) + } + ) + + hidden $_mme = $($this | Add-Member ScriptProperty 'mme' ` + { + return Write-Warning ("ERROR: $($this.identifier()).mme is write only") + } ` + { + param([string]$arg) + return $this.Setter('mme', $arg) + } + ) +} \ No newline at end of file From 126e6172cb532244debc4c9acec1f5a2c7774dcd Mon Sep 17 00:00:00 2001 From: pblivingston <71585805+pblivingston@users.noreply.github.com> Date: Tue, 9 Dec 2025 11:37:23 -0500 Subject: [PATCH 2/5] implement io classes prelim pester tests for potato pass --- lib/Voicemeeter.psm1 | 3 +-- lib/bus.ps1 | 38 +++++----------------------- lib/device.ps1 | 52 -------------------------------------- lib/eq.ps1 | 60 -------------------------------------------- lib/strip.ps1 | 38 +++++----------------------- 5 files changed, 13 insertions(+), 178 deletions(-) delete mode 100644 lib/device.ps1 delete mode 100644 lib/eq.ps1 diff --git a/lib/Voicemeeter.psm1 b/lib/Voicemeeter.psm1 index 271a8e5..d68e388 100644 --- a/lib/Voicemeeter.psm1 +++ b/lib/Voicemeeter.psm1 @@ -4,8 +4,7 @@ . $PSScriptRoot\kinds.ps1 . $PSScriptRoot\iremote.ps1 . $PSScriptRoot\arraymember.ps1 -. $PSScriptRoot\device.ps1 -. $PSScriptRoot\eq.ps1 +. $PSScriptRoot\io.ps1 . $PSScriptRoot\strip.ps1 . $PSScriptRoot\bus.ps1 . $PSScriptRoot\macrobuttons.ps1 diff --git a/lib/bus.ps1 b/lib/bus.ps1 index 3145574..85ece7d 100644 --- a/lib/bus.ps1 +++ b/lib/bus.ps1 @@ -1,13 +1,12 @@ -class Bus : IRemote { +class Bus : IOControl { [Object]$mode [Object]$eq [Object]$levels Bus ([int]$index, [Object]$remote) : base ($index, $remote) { - AddBoolMembers -PARAMS @('mute', 'sel', 'monitor') + AddBoolMembers -PARAMS @('sel', 'monitor') AddIntMembers -PARAMS @('mono') - AddStringMembers -PARAMS @('label') - AddFloatMembers -PARAMS @('gain', 'returnreverb', 'returndelay', 'returnfx1', 'returnfx2') + AddFloatMembers -PARAMS @('returnreverb', 'returndelay', 'returnfx1', 'returnfx2') $this.mode = [BusMode]::new($index, $remote) $this.eq = [BusEq]::new($index, $remote) @@ -17,17 +16,9 @@ class Bus : IRemote { [string] identifier () { return 'Bus[' + $this.index + ']' } - - [void] FadeTo ([single]$target, [int]$time) { - $this.Setter('FadeTo', "($target, $time)") - } - - [void] FadeBy ([single]$target, [int]$time) { - $this.Setter('FadeBy', "($target, $time)") - } } -class BusLevels : IRemote { +class BusLevels : IOLevels { [int]$init [int]$offset @@ -36,23 +27,6 @@ class BusLevels : IRemote { $this.offset = 8 } - hidden [single] Convert([single]$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) } @@ -93,7 +67,7 @@ class BusMode : IRemote { } } -class BusEq : Eq { +class BusEq : IOEq { BusEq ([int]$index, [Object]$remote) : base ($index, $remote, 'Bus') { } @@ -122,7 +96,7 @@ class VirtualBus : Bus { } } -class BusDevice : Device { +class BusDevice : IODevice { BusDevice ([int]$index, [Object]$remote) : base ($index, $remote) { if ($this.index -eq 0) { $this.AddASIO() diff --git a/lib/device.ps1 b/lib/device.ps1 deleted file mode 100644 index d6c3718..0000000 --- a/lib/device.ps1 +++ /dev/null @@ -1,52 +0,0 @@ -class Device : IRemote { - Device ([int]$index, [Object]$remote) : base ($index, $remote) { - } - - hidden $_name = $($this | Add-Member ScriptProperty 'name' ` - { - $this.Getter_String('name') - } ` - { - return Write-Warning ("ERROR: $($this.identifier()).name is read only") - } - ) - - hidden $_sr = $($this | Add-Member ScriptProperty 'sr' ` - { - [int]$this.Getter('sr') - } ` - { - return Write-Warning ("ERROR: $($this.identifier()).sr is read only") - } - ) - - hidden $_wdm = $($this | Add-Member ScriptProperty 'wdm' ` - { - return Write-Warning ("ERROR: $($this.identifier()).wdm is write only") - } ` - { - param([string]$arg) - return $this.Setter('wdm', $arg) - } - ) - - hidden $_ks = $($this | Add-Member ScriptProperty 'ks' ` - { - return Write-Warning ("ERROR: $($this.identifier()).ks is write only") - } ` - { - param([string]$arg) - return $this.Setter('ks', $arg) - } - ) - - hidden $_mme = $($this | Add-Member ScriptProperty 'mme' ` - { - return Write-Warning ("ERROR: $($this.identifier()).mme is write only") - } ` - { - param([string]$arg) - return $this.Setter('mme', $arg) - } - ) -} \ No newline at end of file diff --git a/lib/eq.ps1 b/lib/eq.ps1 deleted file mode 100644 index 048ebe3..0000000 --- a/lib/eq.ps1 +++ /dev/null @@ -1,60 +0,0 @@ -class Eq : IRemote { - [System.Collections.ArrayList]$channel - [string]$kindOfEq - - Eq ([int]$index, [Object]$remote, [string]$kindOfEq) : base ($index, $remote) { - $this.kindOfEq = $kindOfEq - - AddBoolMembers -PARAMS @('on', 'ab') - - $this.channel = @() - for ($ch = 0; $ch -lt $remote.kind.eq_ch[$this.kindOfEq]; $ch++) { - $this.channel.Add([EqChannel]::new($ch, $remote, $this.identifier())) - } - } - - [void] Load ([string]$filename) { - $param = 'Command.Load{0}Eq[{1}]' -f $this.kindOfEq, $this.index - $this.remote.Setter($param, $filename) - } - - [void] Save ([string]$filename) { - $param = 'Command.Save{0}Eq[{1}]' -f $this.kindOfEq, $this.index - $this.remote.Setter($param, $filename) - } -} - -class EqChannel : IRemote { - [System.Collections.ArrayList]$cell - [string]$eqId - - EqChannel ([int]$index, [Object]$remote, [string]$eqId) : base ($index, $remote) { - $this.eqId = $eqId - - $this.cell = @() - $cellCount = $this.remote.kind.cells - for ($c = 0; $c -lt $cellCount; $c++) { - $this.cell.Add([EqCell]::new($c, $remote, $this.identifier())) - } - } - - [string] identifier () { - return '{0}.Channel[{1}]' -f $this.eqId, $this.index - } -} - -class EqCell : IRemote { - [string]$channelId - - EqCell ([int]$index, [Object]$remote, [string]$channelId) : base ($index, $remote) { - $this.channelId = $channelId - - AddBoolMembers -PARAMS @('on') - AddIntMembers -PARAMS @('type') - AddFloatMembers -PARAMS @('f', 'gain', 'q') - } - - [string] identifier () { - return '{0}.Cell[{1}]' -f $this.channelId, $this.index - } -} \ No newline at end of file diff --git a/lib/strip.ps1 b/lib/strip.ps1 index 6595322..cbbedef 100644 --- a/lib/strip.ps1 +++ b/lib/strip.ps1 @@ -1,11 +1,10 @@ -class Strip : IRemote { +class Strip : IOControl { [System.Collections.ArrayList]$gainlayer [Object]$levels Strip ([int]$index, [Object]$remote) : base ($index, $remote) { - AddBoolMembers -PARAMS @('solo', 'mute') - AddFloatMembers -PARAMS @('gain', 'limit', 'pan_x', 'pan_y') - AddStringMembers -PARAMS @('label') + AddBoolMembers -PARAMS @('solo') + AddFloatMembers -PARAMS @('limit', 'pan_x', 'pan_y') AddChannelMembers @@ -20,17 +19,9 @@ class Strip : IRemote { [string] identifier () { return 'Strip[' + $this.index + ']' } - - [void] FadeTo ([single]$target, [int]$time) { - $this.Setter('FadeTo', "($target, $time)") - } - - [void] FadeBy ([single]$target, [int]$time) { - $this.Setter('FadeBy', "($target, $time)") - } } -class StripLevels : IRemote { +class StripLevels : IOLevels { [int]$init [int]$offset @@ -46,23 +37,6 @@ class StripLevels : IRemote { } } - hidden [single] Convert([single]$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) } @@ -196,7 +170,7 @@ class StripAudibility : IRemote { ) } -class StripEq : Eq { +class StripEq : IOEq { StripEq ([int]$index, [Object]$remote) : base ($index, $remote, 'Strip') { } @@ -205,7 +179,7 @@ class StripEq : Eq { } } -class StripDevice : Device { +class StripDevice : IODevice { StripDevice ([int]$index, [Object]$remote) : base ($index, $remote) { } From ea780f6595a868c6fd2d8cd89dba7dec61d6ecad Mon Sep 17 00:00:00 2001 From: pblivingston <71585805+pblivingston@users.noreply.github.com> Date: Tue, 9 Dec 2025 12:10:14 -0500 Subject: [PATCH 3/5] stripknob centralizes threshold, knob - stripcomp - stripgate - stripdenoiser prelim pester tests for potato pass --- lib/strip.ps1 | 57 +++++++++++++++++++-------------------------------- 1 file changed, 21 insertions(+), 36 deletions(-) diff --git a/lib/strip.ps1 b/lib/strip.ps1 index cbbedef..9893fc5 100644 --- a/lib/strip.ps1 +++ b/lib/strip.ps1 @@ -75,65 +75,50 @@ class PhysicalStrip : Strip { } } -class StripComp : IRemote { +class StripKnob : IRemote { + StripKnob ([int]$index, [Object]$remote) : base ($index, $remote) { + AddFloatMembers -PARAMS @('threshold') + } + + hidden $_knob = $($this | Add-Member ScriptProperty 'knob' ` + { + [math]::Round($this.Getter(''), 2) + } ` + { + param([single]$arg) + return $this.Setter('', $arg) + } + ) +} + +class StripComp : StripKnob { StripComp ([int]$index, [Object]$remote) : base ($index, $remote) { - AddFloatMembers -PARAMS @('gainin', 'ratio', 'threshold', 'attack', 'release', 'knee', 'gainout') + AddFloatMembers -PARAMS @('gainin', 'ratio', 'attack', 'release', 'knee', 'gainout') AddBoolMembers -PARAMS @('makeup') } [string] identifier () { return 'Strip[' + $this.index + '].Comp' } - - hidden $_knob = $($this | Add-Member ScriptProperty 'knob' ` - { - [math]::Round($this.Getter(''), 2) - } ` - { - param([single]$arg) - return $this.Setter('', $arg) - } - ) } -class StripGate : IRemote { +class StripGate : StripKnob { StripGate ([int]$index, [Object]$remote) : base ($index, $remote) { - AddFloatMembers -PARAMS @('threshold', 'damping', 'bpsidechain', 'attack', 'hold', 'release') + AddFloatMembers -PARAMS @('damping', 'bpsidechain', 'attack', 'hold', 'release') } [string] identifier () { return 'Strip[' + $this.index + '].Gate' } - - hidden $_knob = $($this | Add-Member ScriptProperty 'knob' ` - { - [math]::Round($this.Getter(''), 2) - } ` - { - param([single]$arg) - return $this.Setter('', $arg) - } - ) } -class StripDenoiser : IRemote { +class StripDenoiser : StripKnob { StripDenoiser ([int]$index, [Object]$remote) : base ($index, $remote) { - AddFloatMembers -PARAMS @('threshold') } [string] identifier () { return 'Strip[' + $this.index + '].Denoiser' } - - hidden $_knob = $($this | Add-Member ScriptProperty 'knob' ` - { - [math]::Round($this.Getter(''), 2) - } ` - { - param([single]$arg) - return $this.Setter('', $arg) - } - ) } class StripPitch : IRemote { From ea6192ba5ffa55557e9d4c13ce8ffbb5e8c3acd6 Mon Sep 17 00:00:00 2001 From: pblivingston <71585805+pblivingston@users.noreply.github.com> Date: Tue, 9 Dec 2025 13:49:25 -0500 Subject: [PATCH 4/5] io classes, stripknob to CHANGELOG pester tests pass for all kinds --- CHANGELOG.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e160e56..4d6a640 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,8 +26,11 @@ Strip Gainlayers are now FloatArrayMember objects, see README for details - ArrayMember classes for array-like properties - Patch class - Option class -- Device class -- EQ class +- IO classes to centralize controls common to both Strip and Bus + - IOControl + - IOLevels + - IOEq + - IODevice - FX class - AddAliasMembers meta function takes a hashtable `-MAP` of `alias = property` @@ -55,6 +58,7 @@ Strip Gainlayers are now FloatArrayMember objects, see README for details - Strip.Karaoke alias for Strip.K - Strip.EQGain1|EQGain2|EQGain3 with bass/low, mid/med, treble/high aliases, respectively - StripAudibility class with Strip.Audibility.Knob +- StripKnob base class for banana/potato audibility knobs with `knob` and `threshold` - Strip.Denoiser.Threshold - Strip.VAIO - Strip.Pitch, StripPitch class @@ -81,12 +85,9 @@ Strip Gainlayers are now FloatArrayMember objects, see README for details - Recorder.Armstrip|Armbus -> BoolArrayMember: now have .Get() - Cast Recorder getters to types for consistency -- Bus.Levels.Convert hidden and return type [float] -> [single] for naming consistency - - Strip.Mono is now an alias for Strip.MC on virtual strips - Strip.AppMute|AppGain can now take an app index; see README for details - Strip Knob setters: explicit $arg types for consistency -- Strip.Levels.Convert hidden and return type [float] -> [single] for naming consistency ### Fixed From 9d3f58f6f2b58990b135109c649bfbcb2fc78ea0 Mon Sep 17 00:00:00 2001 From: pblivingston <71585805+pblivingston@users.noreply.github.com> Date: Sat, 13 Dec 2025 11:42:23 -0500 Subject: [PATCH 5/5] knob threshold, audibility move threshold back to comp/gate/denoiser so audibility can be derived from StripKnob pester tests for safety pass --- CHANGELOG.md | 2 +- lib/strip.ps1 | 18 ++++-------------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d6a640..a862c7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,7 +58,7 @@ Strip Gainlayers are now FloatArrayMember objects, see README for details - Strip.Karaoke alias for Strip.K - Strip.EQGain1|EQGain2|EQGain3 with bass/low, mid/med, treble/high aliases, respectively - StripAudibility class with Strip.Audibility.Knob -- StripKnob base class for banana/potato audibility knobs with `knob` and `threshold` +- StripKnob base class for audibility knobs with `knob` - Strip.Denoiser.Threshold - Strip.VAIO - Strip.Pitch, StripPitch class diff --git a/lib/strip.ps1 b/lib/strip.ps1 index 9893fc5..1ac1528 100644 --- a/lib/strip.ps1 +++ b/lib/strip.ps1 @@ -77,7 +77,6 @@ class PhysicalStrip : Strip { class StripKnob : IRemote { StripKnob ([int]$index, [Object]$remote) : base ($index, $remote) { - AddFloatMembers -PARAMS @('threshold') } hidden $_knob = $($this | Add-Member ScriptProperty 'knob' ` @@ -93,7 +92,7 @@ class StripKnob : IRemote { class StripComp : StripKnob { StripComp ([int]$index, [Object]$remote) : base ($index, $remote) { - AddFloatMembers -PARAMS @('gainin', 'ratio', 'attack', 'release', 'knee', 'gainout') + AddFloatMembers -PARAMS @('gainin', 'ratio', 'threshold', 'attack', 'release', 'knee', 'gainout') AddBoolMembers -PARAMS @('makeup') } @@ -104,7 +103,7 @@ class StripComp : StripKnob { class StripGate : StripKnob { StripGate ([int]$index, [Object]$remote) : base ($index, $remote) { - AddFloatMembers -PARAMS @('damping', 'bpsidechain', 'attack', 'hold', 'release') + AddFloatMembers -PARAMS @('threshold', 'damping', 'bpsidechain', 'attack', 'hold', 'release') } [string] identifier () { @@ -114,6 +113,7 @@ class StripGate : StripKnob { class StripDenoiser : StripKnob { StripDenoiser ([int]$index, [Object]$remote) : base ($index, $remote) { + AddFloatMembers -PARAMS @('threshold') } [string] identifier () { @@ -136,23 +136,13 @@ class StripPitch : IRemote { } } -class StripAudibility : IRemote { +class StripAudibility : StripKnob { StripAudibility ([int]$index, [Object]$remote) : base ($index, $remote) { } [string] identifier () { return 'Strip[' + $this.index + '].Audibility' } - - hidden $_knob = $($this | Add-Member ScriptProperty 'knob' ` - { - [math]::Round($this.Getter(''), 2) - } ` - { - param([single]$arg) - return $this.Setter('', $arg) - } - ) } class StripEq : IOEq {