Skip to content

notifications: play a sound when a notification arrives - #1906

Open
Coral-coder wants to merge 12 commits into
coredevices:mainfrom
Coral-coder:up/notification-sounds
Open

Coral-coder wants to merge 12 commits into
coredevices:mainfrom
Coral-coder:up/notification-sounds

Conversation

@Coral-coder

Copy link
Copy Markdown
Contributor

Because someone on Reddit wanted it, and I kinda did too… 🤷🏼‍♀️

Adds an optional notification sound for speaker-equipped watches, rendered through the existing note-sequence synth — no PCM assets, a few hundred bytes of note tables. Off by default; picker lives in Settings → Sounds & Haptics and previews each choice on select.
The four tones (Ping, Doorbell, Trill, Ascent) are deliberately quite basic — single-voice chirps meant to prove out the plumbing rather than be the final sound design. Happy to take direction on better melodies; each is ~5 lines of note table.
Behavior: DND follows the vibe mask, the vibe holdoff is shared so a notification storm doesn’t chirp continuously (both gates evaluated before either fires, so a notification’s own vibe can’t suppress its own sound), and speaker mute/volume are enforced by the speaker service. Unlike vibes, sounds still play on the charger, where a docked watch can usefully chirp.
The last commit (third_party/hal_sifli: -Wno-maybe-uninitialized) only matters for building with stock GCC 13 outside the docker image — drop it if unwanted.
Tested on Pebble Time 2 (obelix@pvt); full test suite passes.

@gmarull

gmarull commented Sep 17, 2026

Copy link
Copy Markdown
Member

@ericmigi

@ericmigi

Copy link
Copy Markdown
Collaborator

probably should be in settings -> notifications

Four short chirps (Ping, Doorbell, Trill, Ascent) rendered through the
speaker service's note sequences, a persisted preference defaulting to
off, and an alerts-service gate mirroring the vibe rules. DND follows
the vibe mask, and the vibe holdoff is reused so a notification storm
does not chirp continuously; unlike vibes, sounds still play on the
charger where a vibe would go unnoticed. Speaker mute and volume are
enforced downstream by the speaker service.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Coral Coder <noreply@anthropic.com>
Plays the selected chirp when a notification arrives, following the
same delay-until-peek-settles choice as the vibe so sound and haptics
land together. Both alert gates are evaluated before firing either:
the vibe stamps the shared holdoff timestamp when it runs, which would
otherwise suppress the same notification's sound. The sound path
stamps the holdoff too, so sound-only setups still get storm
throttling.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Coral Coder <noreply@anthropic.com>
Select cycles through the sounds and previews the new choice at the
volume notifications will use.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Coral Coder <noreply@anthropic.com>
bt_rf_fulcal.c trips GCC 13's flow analysis (p0/capcode0/idac0 in the
RF-cal routines) and the warning is promoted to an error, breaking
builds outside the project docker image. Silence it for this vendored
SDK only.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Coral Coder <noreply@anthropic.com>
The note-sequence chirps are square/sine beeps; a real bell needs
inharmonic partials the synth can't voice. Render one offline
(additive synthesis: six partials with per-partial exponential decay
and a detuned hum pair for shimmer) into a 6.7 KB 16 kHz signed 8-bit
one-shot, played through the track player's pitched-sample path.

Sounds now play through one notification_sounds_play() entry point
that routes sampled sounds to the track player and synthesized ones
to the note-sequence source, so callers no longer care which kind
they picked.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Coral Coder <noreply@anthropic.com>
Glass is a brighter, purer, shorter strike (three inharmonic partials
on B6) that supersedes Bell in the same picker slot, so stored
preferences carry over. Pop is a 45 ms rising chirp landing on a
bright G6 ding. Both are offline-rendered 16 kHz signed 8-bit
one-shots through the track player's sampled path.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Coral Coder <noreply@anthropic.com>
Seven new offline-rendered one-shots through the track player's
sampled path: Kalimba (plucked A5/E6 pair), Coin (chiptune square
pickup), Sonar (deep ping with echo), Bounce (accelerating tick
drops), Chirp (songbird double-chirp), Bloom (soft chord swell), and
Sparkle (descending glass run). ~54 KB of 16 kHz signed 8-bit PCM.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Coral Coder <noreply@anthropic.com>
Review feedback on the upstream PR asked for the sound picker to live
in Settings->Notifications rather than Sounds & Haptics. The row keeps
its cycle-and-preview behavior and sits next to Vibe Timing; the
preview volume still matches the real notification volume.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CNRhmmV8Cg7o6U4BBXkkx7
Signed-off-by: Coral Coder <noreply@anthropic.com>
The ~55 KB sampled sound pack overflowed the 1 MB code flash on the
nRF52 boards: asterix release bundling fails with firmware 16 KB over
the slot limit. CONFIG_NOTIFICATION_SOUND_SAMPLES (default y) compiles
the PCM tables; asterix and getafix opt out and keep the synthesized
chirps, with the picker skipping absent entries and stored preferences
for absent sounds falling back to Ping.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Coral Coder <noreply@anthropic.com>
Upstream renamed the WEAK attribute macro to PBL_WEAK; adapt the
alerts stub added by the sound feature.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CNRhmmV8Cg7o6U4BBXkkx7
Signed-off-by: Coral Coder <noreply@anthropic.com>
hal_timer.c trips GCC 13's flow analysis when building outside the
docker image, same false positive already silenced for hal_sifli.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CNRhmmV8Cg7o6U4BBXkkx7
Signed-off-by: Coral Coder <noreply@anthropic.com>
The compliance job's clang-format 22 flags brace and comment spacing
in the sound bank; reformat to match.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CNRhmmV8Cg7o6U4BBXkkx7
Signed-off-by: Coral Coder <noreply@anthropic.com>
@Coral-coder
Coral-coder force-pushed the up/notification-sounds branch from 583afa2 to 639bf0c Compare September 17, 2026 23:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants