Alert Volume Controller

This commit is contained in:
James
2025-12-01 12:00:00 -07:00
parent 65c768cff0
commit 4b5c59d32c
3 changed files with 96 additions and 1 deletions
@@ -98,6 +98,14 @@ FrogPilotSoundsPanel::FrogPilotSoundsPanel(FrogPilotSettingsWindow *parent, bool
});
}
for (const QString &key : alertVolumeControlKeys) {
FrogPilotParamValueButtonControl *toggle = static_cast<FrogPilotParamValueButtonControl*>(toggles[key]);
QObject::connect(toggle, &FrogPilotParamValueButtonControl::buttonClicked, [key, toggle, this]() {
toggle->updateParam();
testSound(key);
});
}
QObject::connect(parent, &FrogPilotSettingsWindow::closeSubPanel, [soundsLayout, soundsPanel, this] {
openDescriptions(forceOpenDescriptions, toggles);
soundsLayout->setCurrentWidget(soundsPanel);
@@ -110,6 +118,8 @@ FrogPilotSoundsPanel::FrogPilotSoundsPanel(FrogPilotSettingsWindow *parent, bool
}
}
initializeSoundPlayer();
updateToggles();
}
@@ -117,6 +127,33 @@ void FrogPilotSoundsPanel::showEvent(QShowEvent *event) {
updateToggles();
}
void FrogPilotSoundsPanel::initializeSoundPlayer() {
QString program = R"(
import numpy as np
import sounddevice as sd
import sys
import wave
while True:
try:
line = sys.stdin.readline()
if not line:
break
path, volume = line.strip().split('|')
sound_file = wave.open(path, 'rb')
audio = np.frombuffer(sound_file.readframes(sound_file.getnframes()), dtype=np.int16).astype(np.float32) / 32768.0
sd.play(audio * float(volume), sound_file.getframerate())
sd.wait()
except Exception:
pass
)";
soundPlayerProcess = new QProcess(this);
soundPlayerProcess->start("python3", QStringList{"-u", "-c", program});
}
void FrogPilotSoundsPanel::updateState(const UIState &s) {
if (!isVisible()) {
return;
@@ -162,3 +199,24 @@ void FrogPilotSoundsPanel::updateToggles() {
update();
}
void FrogPilotSoundsPanel::testSound(const QString &key) {
QString baseName = QString(key).remove("Volume");
if (started) {
updateFrogPilotToggles();
util::sleep_for(UI_FREQ);
QString camelCaseAlert = QString(baseName).replace(0, 1, baseName[0].toLower());
params_memory.put("TestAlert", camelCaseAlert.toStdString());
} else {
QString snakeCaseAlert = QString(baseName).replace(QRegularExpression("([A-Z])"), "_\\1").toLower().mid(1);
QString stockPath = "../../selfdrive/assets/sounds/" + snakeCaseAlert + ".wav";
QString themePath = "../../frogpilot/assets/active_theme/sounds/" + snakeCaseAlert + ".wav";
float volume = params.getFloat(key.toStdString()) / 100.0f;
soundPlayerProcess->write(((QFile::exists(themePath) ? themePath : stockPath) + "|" + QString::number(volume) + "\n").toUtf8());
}
}
@@ -15,6 +15,8 @@ protected:
void showEvent(QShowEvent *event) override;
private:
void initializeSoundPlayer();
void testSound(const QString &key);
void updateState(const UIState &s);
void updateToggles();
@@ -32,4 +34,6 @@ private:
Params params;
Params params_memory{"", true};
QProcess *soundPlayerProcess;
};
+34 -1
View File
@@ -85,6 +85,8 @@ class Soundd:
self.frogpilot_toggles = get_frogpilot_toggles()
self.auto_volume = 0
self.update_frogpilot_sounds()
def load_sounds(self):
@@ -135,7 +137,10 @@ class Soundd:
self.current_sound_frame = 0
def get_audible_alert(self, sm):
if sm.updated['selfdriveState']:
if self.params_memory.get("TestAlert"):
self.update_alert(getattr(AudibleAlert, self.params_memory.get("TestAlert")))
self.params_memory.remove("TestAlert")
elif sm.updated['selfdriveState']:
new_alert = sm['selfdriveState'].alertSound.raw
# FrogPilot variables
@@ -182,6 +187,15 @@ class Soundd:
self.spl_filter_weighted.update(sm["soundPressure"].soundPressureWeightedDb)
self.current_volume = self.calculate_volume(float(self.spl_filter_weighted.x))
if self.frogpilot_toggles.alert_volume_controller:
self.auto_volume = self.current_volume
self.current_volume = 0.0
elif self.current_alert in self.volume_map and self.frogpilot_toggles.alert_volume_controller:
self.current_volume = self.volume_map[self.current_alert]
if self.current_volume == 1.01:
self.current_volume = self.auto_volume
self.get_audible_alert(sm)
rk.keep_time()
@@ -196,6 +210,25 @@ class Soundd:
self.update_frogpilot_sounds()
def update_frogpilot_sounds(self):
self.volume_map = {
AudibleAlert.engage: self.frogpilot_toggles.engage_volume / 100.0,
AudibleAlert.disengage: self.frogpilot_toggles.disengage_volume / 100.0,
AudibleAlert.refuse: self.frogpilot_toggles.refuse_volume / 100.0,
AudibleAlert.prompt: self.frogpilot_toggles.prompt_volume / 100.0,
AudibleAlert.promptRepeat: self.frogpilot_toggles.prompt_volume / 100.0,
AudibleAlert.promptDistracted: self.frogpilot_toggles.promptDistracted_volume / 100.0,
AudibleAlert.warningSoft: self.frogpilot_toggles.warningSoft_volume / 100.0,
AudibleAlert.warningImmediate: self.frogpilot_toggles.warningImmediate_volume / 100.0,
FrogPilotAudibleAlert.goat: self.frogpilot_toggles.prompt_volume / 100.0,
FrogPilotAudibleAlert.startup: self.frogpilot_toggles.engage_volume / 100.0
}
for sound in sound_list:
if sound not in self.volume_map:
self.volume_map[sound] = 1.01
def main():