2023-07-14 17:08:23 +01:00
[![License: MIT ](https://img.shields.io/badge/License-MIT-yellow.svg )][license]
2023-07-14 21:08:05 +01:00
[![Ruby Code Style ](https://img.shields.io/badge/code_style-standard-violet.svg )](https://github.com/standardrb/standard)
2023-07-14 12:32:12 +01:00
# Ruby Wrapper for Voicemeeter API
This gem offers a Ruby interface for the Voicemeeter Remote C API.
For an outline of past/future changes refer to: [CHANGELOG ](CHANGELOG.md )
## Tested against
- Basic 1.0.8.8
- Banana 2.0.6.8
- Potato 3.0.2.8
## Requirements
- [Voicemeeter ](https://voicemeeter.com/ )
- Ruby 3.2 or greater
## Installation
### Bundler
```
2023-07-27 15:14:57 +01:00
bundle add voicemeeter
2023-07-14 12:32:12 +01:00
bundle install
```
## `Use`
Simplest use case, request a Remote class of a kind, then pass a block to run.
Login and logout are handled for you in this scenario.
#### `main.rb`
```ruby
require "voicemeeter"
2023-07-21 09:34:26 +01:00
class Main
def run
Voicemeeter::Remote
.new(:banana)
.run do |vm|
vm.strip[0].label = "podmic"
vm.strip[0].mute = true
puts "strip 0 #{vm.strip[0].label} mute was set to #{vm.strip[0].mute}"
vm.bus[3].gain = -6.3
vm.bus[4].eq.on = true
info = [
"bus 3 gain has been set to #{vm.bus[3].gain}",
"bus 4 eq has been set to #{vm.bus[4].eq.on}"
]
puts info
end
2023-07-14 17:08:23 +01:00
end
2023-07-21 09:34:26 +01:00
end
Main.new.run if $PROGRAM_NAME == __FILE__
2023-07-14 12:32:12 +01:00
```
Otherwise you must remember to call `vm.login` `vm.logout` at the start/end of your code.
2023-07-14 17:08:23 +01:00
## `KIND_ID`
2023-07-14 12:32:12 +01:00
2023-07-14 17:08:23 +01:00
Pass the kind of Voicemeeter as an argument. KIND_ID may be:
2023-07-14 12:32:12 +01:00
- `:basic`
- `:banana`
- `:potato`
## `Available commands`
### Strip
2023-07-18 10:34:51 +01:00
The following attributes are available.
2023-07-14 12:32:12 +01:00
- `mono` : boolean
- `solo` : boolean
- `mute` : boolean
- `gain` : float, from -60.0 to 12.0
- `audibility` : float, from 0.0 to 10.0
- `limit` : int, from -40 to 12
- `A1 - A5` , `B1 - B3` : boolean
- `label` : string
- `mc` : boolean
2023-07-18 08:19:17 +01:00
- `karaoke` : int, from 0 to 4
2023-07-14 12:32:12 +01:00
- `bass` : float, from -12.0 to 12.0
- `mid` : float, from -12.0 to 12.0
- `treble` : float, from -12.0 to 12.0
- `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
example:
```ruby
vm.strip[3].gain = 3.7
puts vm.strip[0].label
```
The following methods are available.
- `appgain(name, value)` : string, float, from 0.0 to 1.0
Set the gain in db by value for the app matching name.
- `appmute(name, value)` : string, bool
Set mute state as value for the app matching name.
example:
```ruby
vm.strip[5].appgain("Spotify", 0.5)
vm.strip[5].appmute("Spotify", true)
```
2023-07-18 08:19:17 +01:00
#### Comp
2023-07-18 10:34:51 +01:00
The following attributes are available.
2023-07-18 08:19:17 +01:00
- `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, from 0.0 to 1.0
- `gainout` : float, from -24.0 to 24.0
- `makeup` : boolean
example:
```ruby
puts vm.strip[4].comp.knob
```
Strip Comp parameters are defined for PhysicalStrips.
`knob` defined for all versions, all other parameters potato only.
#### Gate
2023-07-18 10:34:51 +01:00
The following attributes are available.
2023-07-18 08:19:17 +01:00
- `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
example:
```ruby
vm.strip[2].gate.attack = 300.8
```
Strip Gate parameters are defined for PhysicalStrips.
`knob` defined for all versions, all other parameters potato only.
#### Denoiser
2023-07-18 10:34:51 +01:00
The following attributes are available.
2023-07-18 08:19:17 +01:00
- `knob` : float, from 0.0 to 10.0
example:
```ruby
vm.strip[0].denoiser.knob = 0.5
```
Strip Denoiser parameters are defined for PhysicalStrips, potato version only.
#### EQ
2023-07-18 10:34:51 +01:00
The following attributes are available.
2023-07-18 08:19:17 +01:00
- `on` : boolean
- `ab` : boolean
example:
```ruby
vm.strip[0].eq.ab = True
```
Strip EQ parameters are defined for PhysicalStrips, potato version only.
2023-07-14 12:32:12 +01:00
##### Gainlayers
- `gain` : float, from -60.0 to 12.0
example:
```ruby
vm.strip[3].gainlayer[3].gain = 3.7
```
Gainlayers are defined for potato version only.
##### Levels
2023-07-18 10:34:51 +01:00
The following attributes are available.
2023-07-14 12:32:12 +01:00
- `prefader`
- `postfader`
- `postmute`
example:
```ruby
puts vm.strip[3].levels.prefader
```
Level properties will return -200.0 if no audio detected.
### Bus
2023-07-18 10:34:51 +01:00
The following attributes are available.
2023-07-14 12:32:12 +01:00
- `mono` : boolean
- `mute` : boolean
- `sel` : boolean
- `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
- `monitor` : boolean
example:
```ruby
vm.bus[3].gain = 3.7
puts vm.bus[0].label
vm.bus[4].mono = true
```
2023-07-18 08:19:17 +01:00
##### EQ
2023-07-18 10:34:51 +01:00
The following attributes are available.
2023-07-18 08:19:17 +01:00
2023-07-18 10:34:51 +01:00
- `on` : boolean
2023-07-18 08:19:17 +01:00
- `ab` : boolean
example:
```ruby
vm.bus[4].eq.on = true
```
2023-07-14 12:32:12 +01:00
##### Modes
2023-07-18 10:34:51 +01:00
The following attributes are available.
2023-07-14 12:32:12 +01:00
- `normal` : boolean
- `amix` : boolean
- `bmix` : boolean
- `composite` : boolean
- `tvmix` : boolean
- `upmix21` : boolean
- `upmix41` : boolean
- `upmix61` : boolean
- `centeronly` : boolean
- `lfeonly` : boolean
- `rearonly` : boolean
2023-07-18 10:34:51 +01:00
The following methods are available.
- `get`
2023-07-14 12:32:12 +01:00
example:
```ruby
vm.bus[4].mode.amix = true
2023-07-18 10:34:51 +01:00
puts vm.bus[3].mode.get
2023-07-14 12:32:12 +01:00
```
##### Levels
2023-07-18 10:34:51 +01:00
The following attributes are available.
2023-07-14 12:32:12 +01:00
- `all`
example:
```ruby
puts vm.bus[0].levels.all
```
`levels.all` will return -200.0 if no audio detected.
### Strip | Bus
The following methods are available
- `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.
example:
```ruby
vm.strip[0].fadeto(-10.3, 1000)
vm.bus[3].fadeby(-5.6, 500)
```
#### Strip.Device | Bus.Device
2023-07-18 10:34:51 +01:00
The following attributes are available
2023-07-14 12:32:12 +01:00
- `name` : str
- `sr` : int
- `wdm` : str
- `ks` : str
- `mme` : str
- `asio` : str
example:
```ruby
puts vm.strip[0].device.name
vm.bus[0].device.asio = "Audient USB Audio ASIO Driver"
```
strip|bus device parameters are defined for physical channels only.
name, sr are read only. wdm, ks, mme, asio are write only.
### Macrobuttons
Three modes defined: state, stateonly and trigger.
- `state` : boolean
- `stateonly` : boolean
- `trigger` : boolean
example:
```ruby
vm.button[37].state = true
vm.button[55].trigger = false
```
### Recorder
2023-07-18 10:34:51 +01:00
The following attributes accept boolean values.
2023-07-14 12:32:12 +01:00
- `loop` : boolean
- `A1 - A5` : boolean
- `B1 - A3` : boolean
The following methods are available
- `play`
- `stop`
- `pause`
- `record`
- `ff`
- `rew`
- `load(filepath)` : string
example:
```ruby
vm.recorder.play
vm.recorder.stop
# Enable loop play
vm.recorder.loop = true
# Disable recorder out channel B2
vm.recorder.B2 = false
# filepath as string
vm.recorder.load('C:\music\mytune.mp3')
```
### VBAN
2023-07-18 10:34:51 +01:00
- `vm.vban.enable` | `vm.vban.disable` Turn VBAN on or off
2023-07-14 12:32:12 +01:00
##### Instream | Outstream
2023-07-18 10:34:51 +01:00
The following attributes are available.
2023-07-14 12:32:12 +01:00
- `on` : boolean
- `name` : string
- `ip` : string
- `port` : int, range from 1024 to 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.
example:
```ruby
# turn VBAN on
vm.vban.enable
# turn on vban instream 0
vm.vban.instream[0].on = true
# set bit property for outstream 3 to 24
vm.vban.outstream[3].bit = 24
```
### Command
Certain 'special' commands are defined by the API as performing actions rather than setting values. The following methods are available:
- `show` : Bring Voiceemeter GUI to the front
2023-07-18 10:34:51 +01:00
- `hide` : Hide Voicemeeter GUI
2023-07-14 12:32:12 +01:00
- `shutdown` : Shuts down the GUI
- `restart` : Restart the audio engine
2023-07-18 10:34:51 +01:00
The following attributes are write only and accept boolean values.
2023-07-14 12:32:12 +01:00
- `showvbanchat` : boolean
- `lock` : boolean
example:
```ruby
vm.command.restart
vm.command.showvbanchat = true
```
### Device
- `ins` `outs` : Returns the number of input/output devices
- `input(i)` `output(i)` : Returns a hash of device properties for device[i]
example:
```ruby
2023-07-27 22:34:26 +01:00
vm.run { (0...vm.device.ins).each { puts vm.device.input(_1) } }
2023-07-14 12:32:12 +01:00
```
2023-07-27 22:34:26 +01:00
### FX
### Fx.Reverb | Fx.Delay
2023-07-27 22:38:29 +01:00
The following attributes are available:
2023-07-27 22:34:26 +01:00
- `on` : boolean
- `ab` : boolean
example:
```ruby
vm.fx.reverb.on = true
vm.fx.delay.ab = true
```
### Patch
2023-07-27 22:38:29 +01:00
The following attributes are available:
2023-07-27 22:34:26 +01:00
- `postfadercomposite` : boolean
- `postfxinsert` : boolean
example:
```ruby
vm.patch.postfxinsert = false
```
##### asio[i]
- `get()` : int
- `set(patch_in)` : int, valid range determined by connected device.
example:
```ruby
vm.patch.asio[3].set(4)
```
i, from 0 to 10
##### A2[i] - A5[i]
- `get()` : int
- `set(patch_out)` : int, valid range determined by connected device.
example:
```ruby
vm.patch.A3[5].set(3)
```
i, from 0 to 8.
##### composite[i]
- `get()` : int
- `set(channel)` : int, from 0 up to number of channels depending on version.
example:
```ruby
vm.patch.composite[7].set(4)
```
i, from 0 to 8.
##### insert[i]
- `on` : boolean
example:
```ruby
vm.patch.insert[18].on = true
```
i, from 0 up to number of channels depending on version.
### Option
2023-07-27 22:38:29 +01:00
The following attributes are available:
2023-07-27 22:34:26 +01:00
- `sr` : int
- `asiosr` : boolean
- `monitoronsel` : boolean
- `slidermode` : boolean
example:
```ruby
vm.option.sr = 48_000
```
#### Option.buffer
2023-07-27 22:38:29 +01:00
The following attributes are available:
2023-07-27 22:34:26 +01:00
- `mme` : int
- `wdm` : int
- `ks` : int
- `asio` : int
example:
```ruby
vm.option.buffer.wdm = 512
```
##### delay[i]
- `get()` : int
- `set(delay)` : int, from 0 to 500
example:
```ruby
vm.option.delay[4].set(30)
```
i, from 0 up to 4.
2023-07-14 12:32:12 +01:00
### Midi
2023-07-18 10:34:51 +01:00
The following attributes are available:
2023-07-14 12:32:12 +01:00
- `channel` : int, returns the midi channel
- `current` : int, returns the current (or most recently pressed) key
The following methods are available:
- `get(key)` : int, returns most recent velocity value for a key
example:
```ruby
puts vm.midi.get(12)
```
get may return nil if no value for requested key in midi cache
### Multiple parameters
- `apply`
Set many strip/bus/macrobutton/vban parameters at once, for example:
```ruby
vm.apply(
{
2023-07-17 20:00:25 +01:00
"strip-0" => {
2023-07-14 12:32:12 +01:00
mute: true,
gain: 3.2,
A1: true
},
2023-07-17 20:00:25 +01:00
"bus-3" => {
2023-07-14 12:32:12 +01:00
gain: -3.2,
2023-07-18 08:19:17 +01:00
eq: {
on: true
}
2023-07-14 12:32:12 +01:00
},
2023-07-17 20:00:25 +01:00
"button-39" => {
2023-07-14 12:32:12 +01:00
stateonly: true
},
2023-07-17 20:00:25 +01:00
"vban-outstream-3" => {
2023-07-14 12:32:12 +01:00
on: true,
bit: 24
}
}
)
```
Or for each class you may do:
```ruby
vm.strip[0].apply(mute: true, gain: 3.2, A1: true)
vm.vban.outstream[0].apply(on: true, name: "streamname", bit: 24)
```
## Config Files
`vm.apply_config(<configname>)`
You may load config files in TOML format.
Three example configs have been included with the package. Remember to save
current settings before loading a config. To set one you may do:
```ruby
require "voicemeeter"
2023-07-18 10:34:51 +01:00
Voicemeeter::Remote.new(:banana).run { |vm| vm.apply_config(:example) }
2023-07-14 12:32:12 +01:00
```
will load a config file at mydir/configs/banana/example.toml for Voicemeeter Banana.
## Events
By default, NO events listened for.
Use keyword args `pdirty` , `mdirty` , `midi` , `ldirty` to initialize event updates.
example:
```ruby
require 'voicemeeter'
# Set updates to occur every 50ms
# Listen for level updates
2023-07-18 10:34:51 +01:00
Voicemeeter::Remote.new(:banana, ratelimit: 0.05, ldirty: true).run do
...
2023-07-14 12:32:12 +01:00
```
#### `vm.register`|`vm.deregister`
Use the register/deregister methods to register/deregister callbacks and event observers.
example:
```ruby
2023-07-18 08:19:17 +01:00
# register a callback to receive updates
2023-07-14 12:32:12 +01:00
class App():
def initialize(vm)
@vm = vm
2023-07-28 18:51:15 +01:00
@vm .register(method(:on_pdirty))
2023-07-14 12:32:12 +01:00
...
def on_pdirty
...
```
#### `vm.event`
Use the event class to toggle updates as necessary.
2023-07-18 10:34:51 +01:00
The following attributes are available:
2023-07-14 12:32:12 +01:00
- `pdirty` : boolean
- `mdirty` : boolean
- `midi` : boolean
- `ldirty` : boolean
example:
```ruby
vm.event.ldirty = true
vm.event.pdirty = false
```
Or add, remove an array of events.
The following methods are available:
- `add(events)`
- `remove(events)`
- `get`
example:
```ruby
vm.event.add(%w[pdirty mdirty midi ldirty])
vm.event.remove(%w[pdirty mdirty midi ldirty])
# get a list of currently subscribed
p vm.event.get
```
## `Voicemeeter Module`
### Remote class
2023-07-27 21:54:53 +01:00
#### Voicemeeter::Remote
2023-07-14 12:32:12 +01:00
You may pass the following optional keyword arguments:
- `sync` : boolean=false, force the getters to wait for dirty parameters to clear. For most cases leave this as false.
- `ratelimit` : float=0.033, how often to check for updates in ms.
- `pdirty` : boolean=true, parameter updates
- `mdirty` : boolean=true, macrobutton updates
- `midi` : boolean=true, midi updates
- `ldirty` : boolean=false, level updates
Access to lower level Getters and Setters are provided with these functions:
- `vm.get(param, string=false)` : For getting the value of any parameter. Set string to true if getting a property value expected to return a string.
- `vm.set(param, value)` : For setting the value of any parameter.
Access to lower level polling functions are provided with these functions:
- `vm.pdirty?` : Returns true iff a parameter has been updated.
- `vm.mdirty?` : Returns true iff a macrobutton has been updated.
example:
```ruby
vm.get("Strip[2].Mute")
vm.set("Strip[4].Label", "stripname")
vm.set("Strip[0].Gain", -3.6)
```
2023-07-17 14:15:04 +01:00
### Errors
2023-07-14 12:32:12 +01:00
2023-07-17 14:15:04 +01:00
- `Errors::VMError` : Error raised when general errors occur.
- `Errors::VMCAPIError` : Error raised when the C-API returns error values.
- Error codes are stored in {Error Class}.code. For a full list of error codes [check the VoicemeeterRemote header file][voicemeeter remote header].
2023-07-14 12:32:12 +01:00
2023-07-17 14:15:04 +01:00
### Logging
2023-07-27 15:14:57 +01:00
To enable logs set an environmental variable `VM_LOG_LEVEL` to the appropriate level.
2023-07-17 14:15:04 +01:00
example in powershell:
```powershell
2023-07-18 08:19:17 +01:00
$env:VM_LOG_LEVEL="DEBUG"
2023-07-14 12:32:12 +01:00
```
2023-07-18 08:19:17 +01:00
### Tests
2023-07-17 14:15:04 +01:00
To run all tests:
2023-07-14 12:32:12 +01:00
```
2023-07-17 14:15:04 +01:00
Bundle exec rake
2023-07-14 12:32:12 +01:00
```
### Official Documentation
2023-07-17 14:15:04 +01:00
- [Voicemeeter Remote C API ](https://github.com/onyx-and-iris/Voicemeeter-SDK/blob/update-docs/VoicemeeterRemoteAPI.pdf )
2023-07-14 17:08:23 +01:00
[license]: https://github.com/onyx-and-iris/voicemeeter-rb/blob/dev/LICENSE
2023-07-17 14:15:04 +01:00
[voicemeeter remote header]: https://github.com/onyx-and-iris/Voicemeeter-SDK/blob/update-docs/VoicemeeterRemote.h