diff --git a/src/auracast/auracast_config.py b/src/auracast/auracast_config.py index 757e862..41114ee 100644 --- a/src/auracast/auracast_config.py +++ b/src/auracast/auracast_config.py @@ -111,3 +111,4 @@ class AuracastConfigGroup(AuracastGlobalConfig): bigs: List[AuracastBigConfig] = [ AuracastBigConfigDeu(), ] + analog_gain: int = 50 # ADC gain level for analog mode (10-60%) diff --git a/src/auracast/server/multicast_frontend.py b/src/auracast/server/multicast_frontend.py index 2e58d41..3b64134 100644 --- a/src/auracast/server/multicast_frontend.py +++ b/src/auracast/server/multicast_frontend.py @@ -196,6 +196,20 @@ if audio_mode == "Demo": else: start_stream, stop_stream = render_stream_controls(is_streaming, "Start Auracast", "Stop Auracast", running_mode, secondary_is_streaming) +# Analog gain control (only for Analog mode, placed below start button) +analog_gain_value = 50 # default +if audio_mode == "Analog": + saved_analog_gain = saved_settings.get('analog_gain', 50) + analog_gain_value = st.slider( + "Analog Input Gain", + min_value=10, + max_value=60, + value=min(saved_analog_gain, 60), + step=5, + disabled=is_streaming, + help="ADC gain level for both analog inputs (10-60%). Default is 50%." + ) + # Placeholder for validation errors (will be filled in later) validation_error_placeholder = st.empty() @@ -602,6 +616,7 @@ else: 'immediate_rendering': immediate_rendering2, 'presentation_delay_ms': presentation_delay_ms2, 'qos_preset': qos_preset2, + 'analog_gain': analog_gain_value, } radio1_cfg = { @@ -616,7 +631,8 @@ else: 'immediate_rendering': immediate_rendering1, 'presentation_delay_ms': presentation_delay_ms1, 'qos_preset': qos_preset1, - 'stereo_mode': stereo_enabled, # Add stereo mode setting + 'stereo_mode': stereo_enabled, + 'analog_gain': analog_gain_value, } if audio_mode == "Network - Dante": @@ -1499,6 +1515,7 @@ if start_stream: immediate_rendering=bool(cfg['immediate_rendering']), presentation_delay_us=int(cfg['presentation_delay_ms'] * 1000), qos_config=QOS_PRESET_MAP[cfg['qos_preset']], + analog_gain=cfg.get('analog_gain', 50), bigs=[ auracast_config.AuracastBigConfig( id=cfg.get('id', 123456), diff --git a/src/auracast/server/multicast_server.py b/src/auracast/server/multicast_server.py index a62be3c..f3bac0f 100644 --- a/src/auracast/server/multicast_server.py +++ b/src/auracast/server/multicast_server.py @@ -238,12 +238,16 @@ async def _init_i2c_on_startup() -> None: log.warning("Exception running i2cget (%s): %s", " ".join(read_cmd), e, exc_info=True) -async def _set_adc_level_on_startup() -> None: - """Ensure ADC mixer level is set at startup. +async def _set_adc_level(gain_percent: int = 50) -> None: + """Set ADC mixer level. - Runs: amixer -c 2 set 'ADC' x% + Runs: amixer -c 1 set 'ADC' x% + + Args: + gain_percent: Gain level 10-60, default 50 (above 60% causes clipping/silence) """ - cmd = ["amixer", "-c", "2", "set", "ADC", "80%"] + gain_percent = max(10, min(60, gain_percent)) + cmd = ["amixer", "-c", "1", "set", "ADC", f"{gain_percent}%"] try: proc = await asyncio.create_subprocess_exec( *cmd, @@ -338,6 +342,9 @@ async def init_radio(transport: str, conf: auracast_config.AuracastConfigGroup, if input_device_name in ('ch1', 'ch2'): audio_mode_persist = 'Analog' + # Set ADC gain level for analog mode + analog_gain = getattr(conf, 'analog_gain', 50) + await _set_adc_level(analog_gain) elif input_device_name in dante_channels: audio_mode_persist = 'Network - Dante' else: @@ -485,6 +492,7 @@ async def init_radio(transport: str, conf: auracast_config.AuracastConfigGroup, 'immediate_rendering': getattr(conf, 'immediate_rendering', False), 'assisted_listening_stream': getattr(conf, 'assisted_listening_stream', False), 'analog_stereo_mode': getattr(conf.bigs[0], 'analog_stereo_mode', False) if conf.bigs else False, + 'analog_gain': getattr(conf, 'analog_gain', 50), 'stream_password': (conf.bigs[0].code if conf.bigs and getattr(conf.bigs[0], 'code', None) else None), 'big_ids': [getattr(big, 'id', DEFAULT_BIG_ID) for big in conf.bigs], 'big_random_addresses': [getattr(big, 'random_address', DEFAULT_RANDOM_ADDRESS) for big in conf.bigs], @@ -737,6 +745,7 @@ async def _autostart_from_settings(): immediate_rendering=immediate_rendering, assisted_listening_stream=assisted_listening_stream, presentation_delay_us=pres_delay if pres_delay is not None else 40000, + analog_gain=settings.get('analog_gain', 50), bigs=bigs, ) # Set num_bis for stereo mode if needed @@ -890,6 +899,7 @@ async def _autostart_from_settings(): immediate_rendering=immediate_rendering, assisted_listening_stream=assisted_listening_stream, presentation_delay_us=pres_delay if pres_delay is not None else 40000, + analog_gain=settings.get('analog_gain', 50), bigs=bigs, ) conf.qos_config = QOS_PRESET_MAP.get(saved_qos_preset, QOS_PRESET_MAP["Fast"]) @@ -926,8 +936,8 @@ async def _startup_autostart_event(): # Hydrate settings cache once to avoid disk I/O during /status _init_settings_cache_from_disk() await _init_i2c_on_startup() - # Ensure ADC mixer level is set at startup - await _set_adc_level_on_startup() + # Ensure ADC mixer level is set at startup (default 50%) + await _set_adc_level(50) refresh_pw_cache() log.info("[STARTUP] Scheduling autostart task") asyncio.create_task(_autostart_from_settings())