Compare commits

...

5 Commits

Author SHA1 Message Date
Onyx and Iris
3158ed87c7 fix iris_mic index 2026-01-02 09:37:44 +00:00
Onyx and Iris
426cd1be9f add intro banner 2026-01-02 06:31:44 +00:00
Onyx and Iris
5134c752ff upd reset bind 2026-01-02 06:15:57 +00:00
Onyx and Iris
30f06bb535 upd Bus7 label 2026-01-02 05:54:34 +00:00
Onyx and Iris
9cfba017ea make greater use of Enums to improve readability 2026-01-02 05:54:14 +00:00
5 changed files with 94 additions and 56 deletions

View File

@ -194,7 +194,7 @@ gain = 0.0
mode = "normal"
[bus-7]
label = "Both Mics"
label = "Stream Mics"
mono = false
eq.on = false
mute = false

View File

@ -4,7 +4,7 @@ import time
import vban_cmd
from . import configuration
from .enums import Buttons, Strips
from .enums import Buttons, VBANChannels, VMBuses, VMStrips, XAirBuses, XAirStrips
from .layer import ILayer
from .states import AudioState
from .util import ensure_mixer_fadeout
@ -42,44 +42,42 @@ class Audio(ILayer):
def mute_mics(self):
self.state.mute_mics = not self.state.mute_mics
if self.state.mute_mics:
self.vm.strip[0].mute = True
self.vm.strip[1].mute = True
self.vm.strip[4].mute = True
self.vm.strip[VMStrips.onyx_mic].mute = True
self.vm.strip[VMStrips.iris_mic].mute = True
self.logger.info('Mics Muted')
else:
self.vm.strip[0].mute = False
self.vm.strip[1].mute = False
self.vm.strip[4].mute = False
self.vm.strip[VMStrips.onyx_mic].mute = False
self.vm.strip[VMStrips.iris_mic].mute = False
self.logger.info('Mics Unmuted')
self.vm.button[Buttons.mute_mics].stateonly = self.state.mute_mics
def only_discord(self):
self.state.only_discord = not self.state.only_discord
if self.state.only_discord:
self.mixer.dca[0].on = False
self.vm.strip[4].mute = True
self.vm.bus[VMBuses.both_mics].mute = True
self.mixer.strip[XAirStrips.comms].send[XAirBuses.stream_mix].level = -90
self.logger.info('Only Discord Enabled')
else:
self.vm.strip[4].mute = False
self.mixer.dca[0].on = True
self.mixer.strip[XAirStrips.comms].send[XAirBuses.stream_mix].level = -24
self.vm.bus[VMBuses.both_mics].mute = False
self.logger.info('Only Discord Disabled')
self.vm.button[Buttons.only_discord].stateonly = self.state.only_discord
def only_stream(self):
self.state.only_stream = not self.state.only_stream
if self.state.only_stream:
self.vm.bus[5].mute = True
self.vm.bus[6].mute = True
self.vm.strip[2].gain = -3
self.vm.strip[3].gain = -3
self.vm.strip[6].gain = -3
self.vm.bus[VMBuses.onyx_mic].mute = True
self.vm.bus[VMBuses.iris_mic].mute = True
self.vm.strip[VMStrips.onyx_pc].gain = -3
self.vm.strip[VMStrips.iris_pc].gain = -3
self.vm.strip[VMStrips.pretzel].gain = -3
self.logger.info('Only Stream Enabled')
else:
self.vm.strip[2].gain = 0
self.vm.strip[3].gain = 0
self.vm.strip[6].gain = 0
self.vm.bus[5].mute = False
self.vm.bus[6].mute = False
self.vm.strip[VMStrips.onyx_pc].gain = 0
self.vm.strip[VMStrips.iris_pc].gain = 0
self.vm.strip[VMStrips.pretzel].gain = 0
self.vm.bus[VMBuses.onyx_mic].mute = False
self.vm.bus[VMBuses.iris_mic].mute = False
self.logger.info('Only Stream Disabled')
self.vm.button[Buttons.only_stream].stateonly = self.state.only_stream
@ -113,54 +111,54 @@ class Audio(ILayer):
self.state.sound_test = not self.state.sound_test
if self.state.sound_test:
self.vm.strip[Strips.onyx_mic].apply({'A1': True, 'B1': False, 'B3': False, 'mute': False})
self.vm.strip[Strips.iris_mic].apply({'A1': True, 'B2': False, 'B3': False, 'mute': False})
self.vm.vban.outstream[0].on = True
self.vm.vban.outstream[1].on = True
self.vm.vban.outstream[0].route = 0
self.vm.vban.outstream[1].route = 0
self.vm.strip[VMStrips.onyx_mic].apply({'A1': True, 'B1': False, 'B3': False, 'mute': False})
self.vm.strip[VMStrips.iris_mic].apply({'A1': True, 'B2': False, 'B3': False, 'mute': False})
self.vm.vban.outstream[VBANChannels.onyx_mic].on = True
self.vm.vban.outstream[VBANChannels.iris_mic].on = True
self.vm.vban.outstream[VBANChannels.onyx_mic].route = 0
self.vm.vban.outstream[VBANChannels.iris_mic].route = 0
toggle_soundtest(ENABLE_SOUNDTEST)
self.logger.info('Sound Test Enabled')
else:
toggle_soundtest(DISABLE_SOUNDTEST)
self.vm.vban.outstream[0].route = 5
self.vm.vban.outstream[1].route = 6
self.vm.strip[Strips.onyx_mic].apply({'A1': False, 'B1': True, 'B3': True, 'mute': True})
self.vm.strip[Strips.iris_mic].apply({'A1': False, 'B2': True, 'B3': True, 'mute': True})
self.vm.vban.outstream[VBANChannels.onyx_mic].route = 5
self.vm.vban.outstream[VBANChannels.iris_mic].route = 6
self.vm.strip[VMStrips.onyx_mic].apply({'A1': False, 'B1': True, 'B3': True, 'mute': True})
self.vm.strip[VMStrips.iris_mic].apply({'A1': False, 'B2': True, 'B3': True, 'mute': True})
self.logger.info('Sound Test Disabled')
@ensure_mixer_fadeout
def stage_onyx_mic(self):
"""Gain stage SE Electronics DCM8 with phantom power"""
self.mixer.headamp[10].phantom = True
self.mixer.headamp[XAirStrips.onyx_mic].phantom = True
for i in range(21):
self.mixer.headamp[10].gain = i
self.mixer.headamp[XAirStrips.onyx_mic].gain = i
time.sleep(0.1)
self.logger.info('Onyx Mic Staged with Phantom Power')
@ensure_mixer_fadeout
def stage_iris_mic(self):
"""Gain stage TLM102 with phantom power"""
self.mixer.headamp[11].phantom = True
self.mixer.headamp[XAirStrips.iris_mic].phantom = True
for i in range(31):
self.mixer.headamp[11].gain = i
self.mixer.headamp[XAirStrips.iris_mic].gain = i
time.sleep(0.1)
self.logger.info('Iris Mic Staged with Phantom Power')
def unstage_onyx_mic(self):
"""Unstage SE Electronics DCM8 and disable phantom power"""
for i in reversed(range(21)):
self.mixer.headamp[10].gain = i
self.mixer.headamp[XAirStrips.onyx_mic].gain = i
time.sleep(0.1)
self.mixer.headamp[10].phantom = False
self.mixer.headamp[XAirStrips.onyx_mic].phantom = False
self.logger.info('Onyx Mic Unstaged and Phantom Power Disabled')
def unstage_iris_mic(self):
"""Unstage TLM102 and disable phantom power"""
for i in reversed(range(31)):
self.mixer.headamp[11].gain = i
self.mixer.headamp[XAirStrips.iris_mic].gain = i
time.sleep(0.1)
self.mixer.headamp[11].phantom = False
self.mixer.headamp[XAirStrips.iris_mic].phantom = False
self.logger.info('Iris Mic Unstaged and Phantom Power Disabled')
def solo_onyx(self):
@ -169,6 +167,8 @@ class Audio(ILayer):
def solo_iris(self):
"""placeholder method"""
### Workstation and TV Audio Routing via VBAN ###
def _fade_mixer(self, target_fader, fade_in=True):
"""Fade the mixer's fader to the target level."""
current_fader = self.mixer.lr.mix.fader

View File

@ -2,5 +2,25 @@ from enum import IntEnum
Buttons = IntEnum('Buttons', 'mute_mics only_discord only_stream', start=0)
Strips = IntEnum('Strips', 'onyx_mic iris_mic onyx_pc iris_pc', start=0)
Buses = IntEnum('Buses', 'MR18 ASIO[1,2] ASIO[3,4] ASIO[5,6] ASIO[7,8] onyx_mic iris_mic both_mics', start=5)
# Voicemeeter Channels
VMStrips = IntEnum('Strips', 'onyx_mic iris_mic onyx_pc iris_pc st_input_5 system comms pretzel', start=0)
VMBuses = IntEnum('Buses', 'onyx_mic iris_mic both_mics', start=5)
# VBAN Channels
VBANChannels = IntEnum('VBANChannels', 'onyx_mic iris_mic comms workstation', start=0)
# XAir Channels
class XAirStrips(IntEnum):
system = 0
comms = 2
pretzel = 4
game_pcs = 6
onyx_mic = 10
iris_mic = 11
class XAirBuses(IntEnum):
onyx_mix = 0
iris_mix = 2
stream_mix = 4

View File

@ -9,6 +9,8 @@ from duckypad_twitch import configuration
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def register_hotkeys(duckypad):
def audio_hotkeys():
@ -40,7 +42,7 @@ def register_hotkeys(duckypad):
keyboard.add_hotkey('ctrl+alt+F14', duckypad.obsws.stop_stream)
def duckypad_hotkeys():
keyboard.add_hotkey('ctrl+F21', duckypad.reset)
keyboard.add_hotkey('ctrl+F24', duckypad.reset)
for step in (
audio_hotkeys,
@ -63,5 +65,21 @@ def run():
register_hotkeys(duckypad)
banner_width = 80
logger.info(
'\n'.join(
(
'\n' + '#' * banner_width,
'Duckypad Twitch is running. ',
'Run sound test and gain stage mics to verify audio setup.',
'Then start the stream.',
"Don't forget Voicemeeter starts in Only Stream mode!",
'So first unmute mics, then give stream introduction, then disable Only Stream mode.',
'Now you are live with mics unmuted!',
'#' * banner_width,
)
)
)
print('press ctrl+shift+F24 to quit')
keyboard.wait('ctrl+shift+F24')

View File

@ -1,6 +1,6 @@
import logging
from .enums import Strips
from .enums import VMStrips
from .layer import ILayer
from .states import SceneState
@ -33,8 +33,8 @@ class Scene(ILayer):
self._state = SceneState()
def start(self):
self.vm.strip[Strips.onyx_pc].mute = True
self.vm.strip[Strips.iris_pc].mute = True
self.vm.strip[VMStrips.onyx_pc].mute = True
self.vm.strip[VMStrips.iris_pc].mute = True
self.obsws.switch_to_scene('START')
def dual_stream(self):
@ -43,26 +43,26 @@ class Scene(ILayer):
'A5': True,
'gain': 0,
}
self.vm.strip[Strips.onyx_pc].apply(ENABLE_PC)
self.vm.strip[Strips.iris_pc].apply(ENABLE_PC)
self.vm.strip[VMStrips.onyx_pc].apply(ENABLE_PC)
self.vm.strip[VMStrips.iris_pc].apply(ENABLE_PC)
self.obsws.switch_to_scene('DUAL STREAM')
def brb(self):
self.vm.strip[Strips.onyx_pc].mute = True
self.vm.strip[Strips.iris_pc].mute = True
self.vm.strip[VMStrips.onyx_pc].mute = True
self.vm.strip[VMStrips.iris_pc].mute = True
self.obsws.switch_to_scene('BRB')
def end(self):
self.vm.strip[Strips.onyx_pc].mute = True
self.vm.strip[Strips.iris_pc].mute = True
self.vm.strip[VMStrips.onyx_pc].mute = True
self.vm.strip[VMStrips.iris_pc].mute = True
self.obsws.switch_to_scene('END')
def onyx_solo(self):
self.vm.strip[Strips.onyx_pc].mute = False
self.vm.strip[Strips.iris_pc].mute = True
self.vm.strip[VMStrips.onyx_pc].mute = False
self.vm.strip[VMStrips.iris_pc].mute = True
self.obsws.switch_to_scene('ONYX SOLO')
def iris_solo(self):
self.vm.strip[Strips.onyx_pc].mute = True
self.vm.strip[Strips.iris_pc].mute = False
self.vm.strip[VMStrips.onyx_pc].mute = True
self.vm.strip[VMStrips.iris_pc].mute = False
self.obsws.switch_to_scene('IRIS SOLO')