This commit is contained in:
royjr
2026-09-07 02:59:10 -04:00
parent f3cc96b0a7
commit 2f3f1d76a5
3 changed files with 14 additions and 20 deletions
@@ -11,7 +11,8 @@ AUDIO_DIR = Path("/data/media/0/custom_audio")
SAMPLE_RATE = 48000
MAX_SECONDS = 300
GEAR_TIMEOUT = 0.5
RESUME_FRAMES = int(0.15 * SAMPLE_RATE)
DUCK_FRAMES = int(0.05 * SAMPLE_RATE)
RESTORE_FRAMES = int(0.15 * SAMPLE_RATE)
class GearTransition:
@@ -54,7 +55,6 @@ class AudioPlayer:
self.samples = np.empty(0, dtype=np.float32)
self.position = 0
self.gain = 1.0
self.paused = False
def render(self, frames, alert_active):
command = self.command
@@ -63,23 +63,15 @@ class AudioPlayer:
self.samples = command if command is not None else np.empty(0, dtype=np.float32)
self.position = 0
self.gain = 1.0
self.paused = False
out = np.zeros(frames, dtype=np.float32)
if self.position == len(self.samples):
return out
if alert_active:
self.paused = True
self.gain = 0.0
return out
if self.paused:
self.paused = False
self.gain = 0.0
n = min(frames, len(self.samples) - self.position)
gains = np.minimum(1, self.gain + np.arange(n) / RESUME_FRAMES)
step = -0.5 / DUCK_FRAMES if alert_active else 0.5 / RESTORE_FRAMES
gains = np.clip(self.gain + np.arange(n) * step, 0.5, 1.0)
out[:n] = self.samples[self.position:self.position + n] * gains
self.position += n
if n:
self.gain = float(gains[-1])
self.gain = float(np.clip(self.gain + n * step, 0.5, 1.0))
return out
@@ -7,7 +7,8 @@ Each gear change plays `<gear>.wav`: `park.wav`, `drive.wav`, `sport.wav`, `reve
- Entering a gear starts its audio from the beginning at full volume, with no fade-in.
- Changing gears cuts the previous audio without a fade-out. If the new file is missing or invalid, playback stays silent.
- Returning to a previous gear restarts its audio from the beginning. Staying in the same gear does not replay it.
- Safety alerts pause custom audio immediately. After the alert, it resumes from its saved position with a **150 ms fade-in**. Audio triggered during an alert waits, then fades in.
- While any alert sounds, custom audio keeps playing and fades to **50% volume over 50 ms**. Afterward it fades back to full volume over **150 ms**.
- Alert volume is unchanged. Custom audio may be reduced further to prevent clipping when both sounds are loud.
- Startup and recovery from unknown/invalid gear data or data gaps establish a silent baseline.
No settings or dismiss control. Replace or remove files to change future playback.
+7 -6
View File
@@ -1,7 +1,7 @@
import numpy as np
from openpilot.cereal import messaging
from openpilot.selfdrive.ui.soundd import AudibleAlert, Soundd
from openpilot.selfdrive.ui.soundd import Soundd
from openpilot.sunnypilot.selfdrive.ui.custom_audio import CustomAudio
@@ -12,12 +12,13 @@ class SounddSP(Soundd):
self.gear_sock = messaging.sub_sock("carState", conflate=False)
def callback(self, data_out: np.ndarray, frames: int, time, status) -> None:
alert_active = self.current_alert != AudibleAlert.none
super().callback(data_out, frames, time, status)
alert_active = alert_active or self.current_alert != AudibleAlert.none or bool(np.any(data_out[:frames, 0]))
custom_data = self.custom_audio.player.render(frames, alert_active)
if not alert_active:
data_out[:frames, 0] = custom_data
alert_data = data_out[:frames, 0]
alert_peak = float(np.max(np.abs(alert_data)))
custom_data = self.custom_audio.player.render(frames, alert_peak > 0)
custom_peak = float(np.max(np.abs(custom_data)))
gain = min(1.0, max(0.0, 1.0 - alert_peak) / max(custom_peak, 1e-9))
alert_data += custom_data * gain
def get_audible_alert(self, sm):
super().get_audible_alert(sm)