diff --git a/openpilot/starpilot/audio/sound_pack.py b/openpilot/starpilot/audio/sound_pack.py index 9a1619b524..95799f43a0 100644 --- a/openpilot/starpilot/audio/sound_pack.py +++ b/openpilot/starpilot/audio/sound_pack.py @@ -246,6 +246,19 @@ def tici_speaker_samples(samples: np.ndarray) -> np.ndarray: filtered_peak = float(np.max(np.abs(result))) if filtered_peak > original_peak: result *= original_peak / filtered_peak + result = result.astype(np.float32).astype(np.float64) + prior_peak = float(np.max(np.abs(result))) + taps = np.arange(2049, dtype=np.float64) - 1024 + window = np.hamming(len(taps)) + band = (2 * 540 / 48000 * np.sinc(2 * 540 / 48000 * taps) - # codespell:ignore sinc + 2 * 310 / 48000 * np.sinc(2 * 310 / 48000 * taps)) * window # codespell:ignore sinc + result -= 0.85 * np.convolve(result, band, mode="full")[1024:1024 + len(result)] + if fade_frames: + result[:fade_frames] *= fade + result[-fade_frames:] *= fade[::-1] + peak = float(np.max(np.abs(result))) + if peak > prior_peak: + result *= prior_peak / peak output = result.astype(np.float32) output.flags.writeable = False return output diff --git a/openpilot/starpilot/audio/tests/test_sound_pack.py b/openpilot/starpilot/audio/tests/test_sound_pack.py index 738864acd5..466675ec2f 100644 --- a/openpilot/starpilot/audio/tests/test_sound_pack.py +++ b/openpilot/starpilot/audio/tests/test_sound_pack.py @@ -175,7 +175,7 @@ class SoundPackTests(unittest.TestCase): class TiciSpeakerTests(unittest.TestCase): def test_bass_reduction_preserves_presence_and_never_boosts(self): t = np.arange(48000) / 48000 - for frequency, bounds in ((100, (.23, .27)), (400, (.23, .28)), (1500, (.98, 1.01)), (4000, (.98, 1.01))): + for frequency, bounds in ((100, (.23, .27)), (400, (.03, .05)), (1500, (.98, 1.01)), (4000, (.98, 1.01))): with self.subTest(frequency=frequency): samples = (.25 * np.sin(2 * np.pi * frequency * t)).astype(np.float32) original = samples.copy() @@ -250,3 +250,20 @@ class TiciSpeakerTests(unittest.TestCase): daemon.callback(output, len(output), None, None) np.testing.assert_array_equal(output[:, 0], samples) self.assertEqual(daemon.current_sound_frame, len(samples)) + + +def test_tici_speaker_targets_reported_resonance_without_cutting_chimes(): + from openpilot.starpilot.audio.sound_pack import tici_speaker_samples + time = np.arange(48000) / 48000 + amplitudes = {} + for frequency in (370, 420, 470, 880, 1200, 1570): + samples = (0.5 * np.sin(2 * np.pi * frequency * time)).astype(np.float32) + output = tici_speaker_samples(samples) + amplitudes[frequency] = np.sqrt(np.mean(output[4096:-4096] ** 2) / np.mean(samples[4096:-4096] ** 2)) + assert len(output) == len(samples) and output.dtype == np.float32 + assert not output.flags.writeable and np.isfinite(output).all() + assert np.max(np.abs(output)) <= np.max(np.abs(samples)) + 1e-7 + for frequency in (370, 420, 470): + assert amplitudes[frequency] < 0.05 + for frequency in (880, 1200, 1570): + assert 0.95 < amplitudes[frequency] <= 1.001 diff --git a/prebuilt.json b/prebuilt.json index aa25fc88f9..154d41dbfc 100644 --- a/prebuilt.json +++ b/prebuilt.json @@ -1 +1 @@ -{"protected_inventory_sha256": "7ac070bc4f4929e1b96bee176089d2011d98d5c95199c4524b9d266a699133c6", "schema_version": 1} +{"protected_inventory_sha256": "4a20e038be7af8a6565c1660ce1addc80e4fe792e13623e55aab24abcb7a77d0", "schema_version": 1}