diff --git a/docs/architecture.md b/docs/architecture.md index cd3b561..e6d9354 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -144,6 +144,12 @@ ported to LVGL. The `STATES` table in the sim defines the contract: | `rage` | — | — | 34 fast streams | 3-frame kaomoji loop through the eyes slot: `(°□°) ┬─┬` → `(╯°□°)╯︵ ┻━┻` → `┬─┬ ノ( º_º ノ)` — flips the table, then composes itself and puts it back | | `error` | `x x` | `-` | none (rain dies) | face dims to 45% | +**Sound signature**: the cathedral gong (`play_boot_gong` in firmware — 220 Hz +inharmonic partial stack, feedback-comb reflections, ~-7 dBFS) is the approved house +sound: "audible and butler-non-intrusive." Plays at boot; planned as the +wake-from-`dormant` sound. Tune by adjective: tail = `tau`s, cathedral size = echo +delays, depth = fundamental, presence = `GONG_PEAK`/`GONG_VOLUME`. + **Wait cues are a hard requirement** (user-stated): Tatlock turns take 10–25 s, so `effort` must always show *alive-and-working* signals — the orbiting bezel arc, the elapsed-seconds counter, and max rain. Never a bare static face during a wait, and no diff --git a/firmware/main/desklock_main.c b/firmware/main/desklock_main.c index 5cd10a5..441a388 100644 --- a/firmware/main/desklock_main.c +++ b/firmware/main/desklock_main.c @@ -23,15 +23,15 @@ static const char *TAG = "desklock"; #define GONG_RATE 16000 #define GONG_SECONDS 5 #define GONG_SAMPLES (GONG_RATE * GONG_SECONDS) -#define GONG_VOLUME 58 /* codec volume: discreet, not loud */ -#define GONG_PEAK 8000.0f /* ~-12 dBFS headroom */ +#define GONG_VOLUME 75 /* codec volume: discreet, not loud */ +#define GONG_PEAK 14000.0f /* ~-7 dBFS headroom */ /* A distant temple gong in a stone space. * * Inharmonic partials with per-partial decay (lows ring for seconds, highs * die fast), a detuned fundamental pair for slow shimmer, a soft 45 ms * attack so the strike reads as far away, and three early reflections that - * stand in for cathedral walls. Fundamental sits at 165 Hz — low enough to + * stand in for cathedral walls. Fundamental sits at 220 Hz — low enough to * feel voluminous, high enough for the bare 2 W speaker to reproduce. */ static const struct { @@ -39,11 +39,11 @@ static const struct { float amp; float tau; /* seconds to 1/e */ } gong_partials[] = { - { 1.000f, 0.34f, 2.6f }, + { 1.000f, 0.30f, 2.6f }, { 1.004f, 0.22f, 2.2f }, /* beating partner -> shimmer */ - { 1.590f, 0.16f, 1.4f }, - { 2.140f, 0.11f, 0.9f }, - { 2.760f, 0.08f, 0.55f }, + { 1.590f, 0.22f, 1.4f }, + { 2.140f, 0.16f, 0.9f }, + { 2.760f, 0.10f, 0.55f }, { 3.570f, 0.05f, 0.35f }, { 4.800f, 0.03f, 0.22f }, }; @@ -76,7 +76,7 @@ static void play_boot_gong(void) } for (size_t p = 0; p < sizeof(gong_partials) / sizeof(gong_partials[0]); p++) { - float step = 2.0f * (float)M_PI * 165.0f * gong_partials[p].ratio / GONG_RATE; + float step = 2.0f * (float)M_PI * 220.0f * gong_partials[p].ratio / GONG_RATE; float decay = expf(-1.0f / (gong_partials[p].tau * GONG_RATE)); float env = gong_partials[p].amp; float phase = 0.0f;