Skip to content

Commit

Permalink
FAST: audio interface refinements
Browse files Browse the repository at this point in the history
  • Loading branch information
toomanybrians committed Oct 17, 2023
1 parent fd5af89 commit 29dd102
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 34 deletions.
8 changes: 3 additions & 5 deletions mpf/config_spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -666,12 +666,10 @@ fast_aud:
console_log: single|enum(none,basic,full)|none
file_log: single|enum(none,basic,full)|basic
lcd_pulse_time: single|ms|100
friendly_volume_steps: single|int|20
friendly_max_volume: single|int|20
friendly_headphones_steps: single|int|20
friendly_max_headphones: single|int|20
default_volume: single|int|20
default_headphones_volume: single|int|20
friendly_max_headphone_volume: single|int|20
default_volume: single|int|10
default_headphones_volume: single|int|10
max_volume_main: single|int|63
max_volume_sub: single|int|63
max_volume_headphones: single|int|63
Expand Down
4 changes: 2 additions & 2 deletions mpf/platforms/fast/communicators/aud.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ def update_config(self, send_now=True):
if self.amps['sub']['enabled']:
byte = Util.set_bit(byte, 1)
if self.amps['headphones']['enabled']:
if not self.phones_level: # line level
if not self.phones_level: # line level
byte = Util.set_bit(byte, 2)
byte = Util.set_bit(byte, 3)
else: # phones level
else: # phones level
if self.phones_mute:
byte = Util.set_bit(byte, 3)
else:
Expand Down
101 changes: 76 additions & 25 deletions mpf/platforms/fast/fast_audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ class FASTAudioInterface(LogMixin):

"""Hardware sound system using the FAST Audio board."""

# __slots__ = []
__slots__ = ["platform", "communicator", "current_volume", "current_headphones_volume", "temp_ducked_volume_steps",
"friendly_max_volume", "friendly_max_headphone_volume", "volume_map", "headphones_map",
"link_phones_to_main"]

def __init__(self, platform, communicator):
self.platform = platform
Expand All @@ -16,6 +18,7 @@ def __init__(self, platform, communicator):
self.current_headphones_volume = 0
self.temp_ducked_volume_steps = 0
self.friendly_max_volume = communicator.config['friendly_max_volume']
self.friendly_max_headphone_volume = communicator.config['friendly_max_headphone_volume']
self.volume_map = list()
self.headphones_map = list()

Expand Down Expand Up @@ -43,10 +46,14 @@ def __init__(self, platform, communicator):

self.volume_map = communicator.config['volume_map']
if not self.volume_map:
self.create_volume_map()
self._create_volume_map()
else:
self.friendly_max_volume = len(self.volume_map) - 1

if not self.headphones_map:
self.create_headphones_map()
self._create_headphones_map()
else:
self.friendly_max_headphone_volume = len(self.headphones_map) - 1

communicator.set_phones_behavior(phones, send_now=False)

Expand All @@ -62,13 +69,24 @@ def __init__(self, platform, communicator):
self.communicator.set_volume('sub', self.volume_map[self.current_volume][1], send_now=False)
self.communicator.set_volume('headphones', self.headphones_map[self.current_headphones_volume], send_now=False)

def create_volume_map(self):
steps = self.communicator.config['friendly_volume_steps']
def _create_volume_map(self):
# volume_map is a list of tuples, each tuple is (main_volume, sub_volume)
# the list index is the friendly volume level, e.g. 0-20
# volume_map[0] will always be (0,0)
# the highest will always be (max_volume_main, max_volume_sub)
# valid values in the map are 0-63. These are the technical hardware
# volume levels. Users will see the friendly volume levels, e.g. 0-20
steps = self.communicator.config['friendly_max_volume']
max_volume_main = self.communicator.config['max_volume_main']
max_volume_sub = self.communicator.config['max_volume_sub']
sub_percent_of_main = max_volume_sub / max_volume_main
step_percent = 1 / steps

if max_volume_main > 63:
raise AssertionError(f"Invalid max_volume_main: {max_volume_main}")
if max_volume_sub > 63:
raise AssertionError(f"Invalid max_volume_sub: {max_volume_sub}")

# calculate the sub and main volume for each step
for i in range(steps):
main_volume = ceil(max_volume_main * (1 - (i * step_percent)))
Expand All @@ -81,11 +99,14 @@ def create_volume_map(self):
self.volume_map.append((0, 0))
self.volume_map.reverse()

def create_headphones_map(self):
steps = self.communicator.config['friendly_headphones_steps']
def _create_headphones_map(self):
steps = self.communicator.config['friendly_max_headphone_volume']
max_volume = self.communicator.config['max_volume_headphones']
step_percent = 1 / steps

if max_volume > 63:
raise AssertionError(f"Invalid max_volume_headphones: {max_volume}")

for i in range(steps):
volume = ceil(max_volume * (1 - (i * step_percent)))
self.headphones_map.append(volume)
Expand All @@ -100,38 +121,68 @@ def send_volume_to_hw(self):
def send_headphones_volume_to_hw(self):
self.communicator.set_volume('headphones', self.headphones_map[self.current_headphones_volume])

def increase_volume(self, steps=1):
self.set_volume(self.current_volume + steps)
def increase_volume(self, steps=1, **kwargs):
"""Increase the volume by the specified number of steps."""
self.set_volume(self.current_volume + int(steps))

def decrease_volume(self, steps=1):
self.set_volume(self.current_volume - steps)
def decrease_volume(self, steps=1, **kwargs):
"""Decrease the volume by the specified number of steps."""
self.set_volume(self.current_volume - int(steps))

def set_volume(self, volume=0, **kwargs):
"""Set the main/sub volume to the specified level, using the volume map"""
volume = int(volume)

if volume > self.friendly_max_volume:
volume = self.friendly_max_volume
elif volume < 0:
volume = 0

def set_volume(self, volume=0):
self.current_volume = volume
self.send_volume_to_hw()

if self.link_phones_to_main:
self.current_headphones_volume = volume
self.send_headphones_volume_to_hw()
self.set_headphones_volume(volume)

def increase_headphones_volume(self, steps=1):
self.set_headphones_volume(self.current_headphones_volume + steps)
def increase_headphones_volume(self, steps=1, **kwargs):
"""Increase the headphones volume by the specified number of steps."""
self.set_headphones_volume(self.current_headphones_volume + int(steps))

def decrease_headphones_volume(self, steps=1):
self.set_headphones_volume(self.current_headphones_volume - steps)
def decrease_headphones_volume(self, steps=1, **kwargs):
"""Decrease the headphones volume by the specified number of steps."""
self.set_headphones_volume(self.current_headphones_volume - int(steps))

def set_headphones_volume(self, volume=0, **kwargs):
"""Set the headphones volume to the specified level using the
headphones map"""

if self.link_phones_to_main:
return False # use set_volume() instead

volume = int(volume)

if volume > self.friendly_max_headphone_volume:
volume = self.friendly_max_headphone_volume
elif volume < 0:
volume = 0

def set_headphones_volume(self, volume=0):
self.current_headphones_volume = volume
self.send_headphones_volume_to_hw()

def temp_duck_volume(self, steps=1):
"""Temporarily duck the volume by the specified number of steps."""
return True

def temp_duck_volume(self, steps=1, **kwargs):
"""Temporarily duck the volume by the specified number of steps.
The original value will be saved and can be restored with
restore_volume().
"""
steps = int(steps)
self.temp_ducked_volume_steps = steps
self.set_volume(self.current_volume - steps)

def restore_volume(self):
"""Restore the main/sub blended volume to the saved value."""
def restore_volume(self, **kwargs):
"""Restore the volume to the value it was before the last"""
self.set_volume(self.current_volume + self.temp_ducked_volume_steps)

def pulse_lcd_pin(self, pin, ms=100):
def pulse_lcd_pin(self, pin, ms=100, **kwargs):
"""Pulse the specified LCD pin for the specified number of milliseconds."""
self.communicator.pulse_lcd_pin(pin, ms)
5 changes: 3 additions & 2 deletions mpf/tests/machine_files/fast/config/audio.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ fast:
port: com9
baud: 230400
lcd_pulse_time: 100ms
friendly_volume_steps: 20
friendly_max_volume: 100
friendly_max_volume: 20
friendly_max_headphone_volume: 20
max_volume_main: 63
max_volume_sub: 40
max_volume_headphones: 63
Expand All @@ -19,3 +19,4 @@ fast:
headphones_amp_enabled: True
headphones_level: headphones # headphones or line
mute_speakers_with_headphones: True
link_phones_to_main: False

0 comments on commit 29dd102

Please sign in to comment.