Basic Volume Controls

This commit is contained in:
unknown 2024-08-03 21:43:04 -04:00
parent 9bb1b526ed
commit 78d9577a5f
9 changed files with 201 additions and 112 deletions

7
.gitignore vendored
View File

@ -1,2 +1,5 @@
*.bak
*.ini
MidiToMacro.ini
/SOURCE
/.vs
games_list.ini
config.ini

View File

@ -110,6 +110,11 @@ Return
; MIDI Rules dispatcher
LoadModules:
; Include the ModuleLoader script
#Include ModuleLoader.ahk
Return
MidiRules:
if (statusbyte >= 128 and statusbyte <= 159) { ; Note off/on
isNoteOn := (statusbyte >= 144 and byte2 > 0)

View File

@ -1,4 +1,3 @@
;*************************************************
;* RULES - MIDI FILTERS
;*************************************************
@ -13,36 +12,94 @@ ProcessNote(device, channel, note, velocity, isNoteOn) {
}
ProcessCC(device, channel, cc, value) {
if (cc = 21 or cc = 29) {
scaled_value := ConvertCCValueToScale(value, 0, 127)
vol := scaled_value * 100
SoundSet, vol
;*************************************************
;* Rotary Knob 1 (Master Volume Control) *
;*************************************************
if (cc = 21) {
scaled_value := ConvertCCValueToScale(value, 7, 120)
vol := Round(scaled_value * 100) ; Scale to percentage
SoundSet, vol, MASTER
; Minimizing feedback to optimize speed
DisplayOutput("Volume", vol)
} else if (cc = 51) {
Send {Volume_Mute}
DisplayOutput("Volume", "Mute")
} else if (cc = 52 and value != 0) {
Send {Volume_Down}
DisplayOutput("Volume", "Down")
} else if (cc = 53 and value != 0) {
Send {Volume_Up}
DisplayOutput("Volume", "Up")
} else if (cc = 54 and value != 0) {
Send {Media_Play_Pause}
DisplayOutput("Media", "Play/Pause")
} else if (cc = 55 and value != 0) {
Send {Media_Stop}
DisplayOutput("Media", "Stop")
} else if (cc = 56 and value != 0) {
Send {Media_Prev}
DisplayOutput("Media", "Previous")
} else if (cc = 57 and value != 0) {
Send {Media_Next}
DisplayOutput("Media", "Next")
} else if (cc = 58 and value != 0) {
; Place a cue marker in Sound Forge 9
ControlSend, , {Alt down}m{Alt up}, ahk_class #32770
DisplayOutput("Sound Forge", "Place Cue Marker")
}
if (cc = 0 and value = 1) {
SoundSet, 1, MASTER, MUTE ; Unmute
DisplayOutput("Volume Unmuted", "")
} else if (cc = 0 and value = 0) {
SoundSet, 0, MASTER, MUTE ; Mute
DisplayOutput("Volume Muted", "")
}
;*************************************************
;* Rotary Knob 2 (Mozilla Firefox Volume Control)*
;*************************************************
if (cc = 22) {
scaled_value := ConvertCCValueToScale(value, 7, 120)
vol := Round(scaled_value, 2) ; Scale to the range used by nircmd
; Adjust Firefox volume using nircmd
Run, nircmd setappvolume firefox.exe %vol%
; Minimizing feedback to optimize speed
scaled_value := ConvertCCValueToScale(vol, 0, 127)
percentage := Round(vol * 100) ; Scale to percentage
DisplayOutput("Firefox Volume", percentage)
}
if (cc = 1 and value = 1) {
; Mute Mozilla Firefox
Run, nircmd muteappvolume firefox.exe 1
DisplayOutput("Firefox Muted", "")
} else if (cc = 1 and value = 0) {
; Unmute Mozilla Firefox
Run, nircmd muteappvolume firefox.exe 0
DisplayOutput("Firefox Unmuted", "")
}
;*************************************************
;* Rotary Knob 3 (Games Volume Control) *
;*************************************************
if (cc = 23) {
scaled_value := ConvertCCValueToScale(value, 7, 120)
vol := Round(scaled_value, 2) ; Scale to the range used by nircmd
; Read the list of game executables from the file
FileRead, gameList, game_exe_list.txt
Loop, Parse, gameList, `n, `r
{
if (A_LoopField != "") {
; Adjust game volume using nircmd
Run, nircmd setappvolume %A_LoopField% %vol%
}
}
; Minimizing feedback to optimize speed
scaled_value := ConvertCCValueToScale(vol, 0, 127)
percentage := Round(vol * 100) ; Scale to percentage
DisplayOutput("Games Volume", percentage)
}
if (cc = 2 and value = 1) {
; Mute all games
FileRead, gameList, game_exe_list.txt
Loop, Parse, gameList, `n, `r
{
if (A_LoopField != "") {
Run, nircmd muteappvolume %A_LoopField% 1
}
}
DisplayOutput("Games Muted", "")
} else if (cc = 2 and value = 0) {
; Unmute all games
FileRead, gameList, game_exe_list.txt
Loop, Parse, gameList, `n, `r
{
if (A_LoopField != "") {
Run, nircmd muteappvolume %A_LoopField% 0
}
}
DisplayOutput("Games Unmuted", "")
}
}
@ -52,5 +109,4 @@ ProcessPC(device, channel, note, velocity) {
ProcessPitchBend(device, channel, value) {
}
}

BIN
NirCmd.chm Normal file

Binary file not shown.

89
Original_README.md Normal file
View File

@ -0,0 +1,89 @@
# MidiToMacro
This is an AutoHotKey script for Windows, to map MIDI input values to hotkeys or macros.
You can use this script to bind CC messages to media keys (play/pause/next), volume sliders, or unusual keyboard combinations (ctrl+shift+alt+F13) which you can assign in programs like StreamLabs OBS.
It's cobbled together from scripts found on the AHK forums. It originally supported mapping MIDI inputs to a virtual joystick using vJoy, and to MIDI outputs; this functionality has been removed. All credit goes to the original authors.
## Running
Double click on `MidiToMacro.ahk`.
To launch the program when Windows starts, you can add a shortcut to the file in your Start Menu\Startup folder.
The first time you launch the script, you will be prompted to choose a MIDI input device. If you need to change it later, you can right click on the system tray icon and click `MidiSet`. Or, you can open the `MidiMon`, and change the input in the "Midi Input" dropdown menu; the script will automatically reload.
To see a log of recent MIDI input messages and any output events, right click on the system tray icon and click `MidiMon`. You can close this window, and the script will keep running in the background.
## Adding rules
You can add rules to the file `MidiRules.ahk`.
There are four handler functions you can modify:
- `ProcessNote`: handles note on/off events
- `ProcessCC`: handles CC (Control Change, or Continuous Control) events
- `ProcessPC`: handles patch change events
- `ProcessPitchBend`: handle pitch bend events
Within each function, you can have a series of `if/else` blocks.
```
if (cc = 21) {
; ...
} else if (cc = 51) {
; ...
} else if (cc = 52 and value != 0) {
; ...
}
```
A rule to toggle the mute button when receiving CC 51 might look like this:
```
if (cc = 51) {
Send {Volume_Mute}
DisplayOutput("Volume", "Mute")
}
```
`Send {Volume_Mute}` simulates pressing the "mute" button on your keyboard. `DisplayOutput("Volume", "Mute")` logs a message to the MidiMon GUI.
A rule to press the play/pause button might look like this:
```
if (cc = 54 and value != 0) {
Send {Media_Play_Pause}
DisplayOutput("Media", "Play/Pause")
}
```
`value != 0` lets us detect button presses, and ignores button releases, on our MIDI controller. (Without this clause, we'd send the keyboard macro twice; once for the button press, and agin for the button release.)
Here's a rule to map a continuous control from a slider to the main Windows mixer volume:
```
if (cc = 21 or cc = 29) {
scaled_value := ConvertCCValueToScale(value, 0, 127)
vol := scaled_value * 100
SoundSet, vol
DisplayOutput("Volume", vol)
}
```
`ConvertCCValueToScale` is a utility function from `CommonFunctions.ahk`. It converts a value within a give range into a floating point number between 0 and 1.
Here's a rule to trigger a keyboard shortcut in a specific application; in this example, Sound Forge 9:
```
if (cc = 58 and value != 0) {
; Place a cue marker in Sound Forge 9
ControlSend, , {Alt down}m{Alt up}, ahk_class #32770
DisplayOutput("Sound Forge", "Place Cue Marker")
}
```
You can use AutoHotKey's "WindowSpy" script to identify windows, or controls within an application, for use with `ahk_class`.
You can find [a list of standard CC messages online](https://www.midi.org/specifications-old/item/table-3-control-change-messages-data-bytes-2). You could use any control number without a specified control function, including numbers between 20-31, 52-63, and 102-119. But, any control number should work fine.

View File

@ -1,89 +1,23 @@
# MidiToMacro
# MidiToMacro - LaunchKey Mini [Mk3] Fork
This is an AutoHotKey script for Windows, to map MIDI input values to hotkeys or macros.
I made this fork to use my Launchkey Mini [Mk3] as a Stream Deck.
You can use this script to bind CC messages to media keys (play/pause/next), volume sliders, or unusual keyboard combinations (ctrl+shift+alt+F13) which you can assign in programs like StreamLabs OBS.
It is a fork of [laurence-myers/midi-to-macro](https://github.com/laurence-myers/midi-to-macro). It uses Modules to easily enable or disable different controls and is designed to be easily modified via the Config.ini file.
It's cobbled together from scripts found on the AHK forums. It originally supported mapping MIDI inputs to a virtual joystick using vJoy, and to MIDI outputs; this functionality has been removed. All credit goes to the original authors.
## TODO
## Running
Planned Features
Double click on `MidiToMacro.ahk`.
- Modules
To launch the program when Windows starts, you can add a shortcut to the file in your Start Menu\Startup folder.
- Laravel WebUI for modification of Inputs / Outputs
The first time you launch the script, you will be prompted to choose a MIDI input device. If you need to change it later, you can right click on the system tray icon and click `MidiSet`. Or, you can open the `MidiMon`, and change the input in the "Midi Input" dropdown menu; the script will automatically reload.
## Functionality
To see a log of recent MIDI input messages and any output events, right click on the system tray icon and click `MidiMon`. You can close this window, and the script will keep running in the background.
For more info on the functionality, please see the [Original_README](Original_README.md) file.
## Adding rules
### Dependencies
You can add rules to the file `MidiRules.ahk`.
- NirCmd has been added to the project as a dependency. It is included so you will not need to download it.
There are four handler functions you can modify:
- `ProcessNote`: handles note on/off events
- `ProcessCC`: handles CC (Control Change, or Continuous Control) events
- `ProcessPC`: handles patch change events
- `ProcessPitchBend`: handle pitch bend events
Within each function, you can have a series of `if/else` blocks.
```
if (cc = 21) {
; ...
} else if (cc = 51) {
; ...
} else if (cc = 52 and value != 0) {
; ...
}
```
A rule to toggle the mute button when receiving CC 51 might look like this:
```
if (cc = 51) {
Send {Volume_Mute}
DisplayOutput("Volume", "Mute")
}
```
`Send {Volume_Mute}` simulates pressing the "mute" button on your keyboard. `DisplayOutput("Volume", "Mute")` logs a message to the MidiMon GUI.
A rule to press the play/pause button might look like this:
```
if (cc = 54 and value != 0) {
Send {Media_Play_Pause}
DisplayOutput("Media", "Play/Pause")
}
```
`value != 0` lets us detect button presses, and ignores button releases, on our MIDI controller. (Without this clause, we'd send the keyboard macro twice; once for the button press, and agin for the button release.)
Here's a rule to map a continuous control from a slider to the main Windows mixer volume:
```
if (cc = 21 or cc = 29) {
scaled_value := ConvertCCValueToScale(value, 0, 127)
vol := scaled_value * 100
SoundSet, vol
DisplayOutput("Volume", vol)
}
```
`ConvertCCValueToScale` is a utility function from `CommonFunctions.ahk`. It converts a value within a give range into a floating point number between 0 and 1.
Here's a rule to trigger a keyboard shortcut in a specific application; in this example, Sound Forge 9:
```
if (cc = 58 and value != 0) {
; Place a cue marker in Sound Forge 9
ControlSend, , {Alt down}m{Alt up}, ahk_class #32770
DisplayOutput("Sound Forge", "Place Cue Marker")
}
```
You can use AutoHotKey's "WindowSpy" script to identify windows, or controls within an application, for use with `ahk_class`.
You can find [a list of standard CC messages online](https://www.midi.org/specifications-old/item/table-3-control-change-messages-data-bytes-2). You could use any control number without a specified control function, including numbers between 20-31, 52-63, and 102-119. But, any control number should work fine.
- Git Bash is what I used to run .sh files on Windows. I have not tested it with cmd or powershell or any other bash clients.

2
game_exe_list.txt Normal file
View File

@ -0,0 +1,2 @@
# This file is looped through and works best with 3 or 4 games in the list or it starts to lag. This comment is also read, so delete it if you want to speed it up by 1 line.
MTGA.exe

BIN
nircmd.exe Normal file

Binary file not shown.

BIN
nircmdc.exe Normal file

Binary file not shown.