store/send mic audio with toggle

pull/35595/head
Quantizr (Jimmy) 4 weeks ago
parent c1e0b87059
commit ea0faea457
  1. 7
      cereal/log.capnp
  2. 2
      cereal/services.py
  3. 1
      common/params_keys.h
  4. 7
      selfdrive/ui/layouts/settings/toggles.py
  5. 7
      selfdrive/ui/qt/offroad/settings.cc
  6. 15
      system/micd.py

@ -2479,6 +2479,11 @@ struct Microphone {
filteredSoundPressureWeightedDb @2 :Float32; filteredSoundPressureWeightedDb @2 :Float32;
} }
struct AudioData {
sampleRate @0 :UInt32;
data @1 :Data;
}
struct Touch { struct Touch {
sec @0 :Int64; sec @0 :Int64;
usec @1 :Int64; usec @1 :Int64;
@ -2557,6 +2562,8 @@ struct Event {
# microphone data # microphone data
microphone @103 :Microphone; microphone @103 :Microphone;
audioData @147 :AudioData;
audioDataNoLog @148 :AudioData;
# systems stuff # systems stuff
androidLog @20 :AndroidLogEntry; androidLog @20 :AndroidLogEntry;

@ -74,6 +74,8 @@ _services: dict[str, tuple] = {
"qRoadEncodeIdx": (False, 20.), "qRoadEncodeIdx": (False, 20.),
"userFlag": (True, 0., 1), "userFlag": (True, 0., 1),
"microphone": (True, 10., 10), "microphone": (True, 10., 10),
"audioData": (True, 20.),
"audioDataNoLog": (False, 20.),
# debug # debug
"uiDebug": (True, 0., 1), "uiDebug": (True, 0., 1),

@ -99,6 +99,7 @@ inline static std::unordered_map<std::string, uint32_t> keys = {
{"PandaSomResetTriggered", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION}, {"PandaSomResetTriggered", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION},
{"PandaSignatures", CLEAR_ON_MANAGER_START}, {"PandaSignatures", CLEAR_ON_MANAGER_START},
{"PrimeType", PERSISTENT}, {"PrimeType", PERSISTENT},
{"RecordAudio", PERSISTENT},
{"RecordFront", PERSISTENT}, {"RecordFront", PERSISTENT},
{"RecordFrontLock", PERSISTENT}, // for the internal fleet {"RecordFrontLock", PERSISTENT}, // for the internal fleet
{"SecOCKey", PERSISTENT | DONT_LOG}, {"SecOCKey", PERSISTENT | DONT_LOG},

@ -21,6 +21,7 @@ DESCRIPTIONS = {
"AlwaysOnDM": "Enable driver monitoring even when openpilot is not engaged.", "AlwaysOnDM": "Enable driver monitoring even when openpilot is not engaged.",
'RecordFront': "Upload data from the driver facing camera and help improve the driver monitoring algorithm.", 'RecordFront': "Upload data from the driver facing camera and help improve the driver monitoring algorithm.",
"IsMetric": "Display speed in km/h instead of mph.", "IsMetric": "Display speed in km/h instead of mph.",
"RecordAudio": "Records microphone audio.",
} }
@ -76,6 +77,12 @@ class TogglesLayout(Widget):
toggle_item( toggle_item(
"Use Metric System", DESCRIPTIONS["IsMetric"], self._params.get_bool("IsMetric"), icon="monitoring.png" "Use Metric System", DESCRIPTIONS["IsMetric"], self._params.get_bool("IsMetric"), icon="monitoring.png"
), ),
toggle_item(
"Record Microphone Audio",
DESCRIPTIONS["RecordAudio"],
self._params.get_bool("RecordAudio"),
icon="monitoring.png",
),
] ]
self._list_widget = ListView(items) self._list_widget = ListView(items)

@ -68,6 +68,13 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) {
"../assets/icons/metric.png", "../assets/icons/metric.png",
false, false,
}, },
{
"RecordAudio",
tr("Record Microphone Audio"),
tr("Records microphone audio."),
"../assets/icons/monitoring.png",
true,
},
}; };

@ -7,12 +7,13 @@ from cereal import messaging
from openpilot.common.realtime import Ratekeeper from openpilot.common.realtime import Ratekeeper
from openpilot.common.retry import retry from openpilot.common.retry import retry
from openpilot.common.swaglog import cloudlog from openpilot.common.swaglog import cloudlog
from openpilot.common.params import Params
RATE = 10 RATE = 10
FFT_SAMPLES = 4096 FFT_SAMPLES = 4096
REFERENCE_SPL = 2e-5 # newtons/m^2 REFERENCE_SPL = 2e-5 # newtons/m^2
SAMPLE_RATE = 44100 SAMPLE_RATE = 16000
SAMPLE_BUFFER = 4096 # approx 100ms SAMPLE_BUFFER = 800 # 50ms
@cache @cache
@ -45,7 +46,7 @@ def apply_a_weighting(measurements: np.ndarray) -> np.ndarray:
class Mic: class Mic:
def __init__(self): def __init__(self):
self.rk = Ratekeeper(RATE) self.rk = Ratekeeper(RATE)
self.pm = messaging.PubMaster(['microphone']) self.pm = messaging.PubMaster(['microphone', 'audioData', 'audioDataNoLog'])
self.measurements = np.empty(0) self.measurements = np.empty(0)
@ -88,6 +89,14 @@ class Mic:
self.measurements = self.measurements[FFT_SAMPLES:] self.measurements = self.measurements[FFT_SAMPLES:]
audio_data_service = 'audioData' if Params().get_bool("RecordAudio") else 'audioDataNoLog'
msg = messaging.new_message(audio_data_service, valid=True)
audio_field = getattr(msg, audio_data_service)
audio_field.sampleRate = SAMPLE_RATE
audio_data_int_16 = (indata[:, 0] * 32767).astype(np.int16)
audio_field.data = audio_data_int_16.tobytes()
self.pm.send(audio_data_service, msg)
@retry(attempts=7, delay=3) @retry(attempts=7, delay=3)
def get_stream(self, sd): def get_stream(self, sd):
# reload sounddevice to reinitialize portaudio # reload sounddevice to reinitialize portaudio

Loading…
Cancel
Save