Frontend: Album 1 BGM player + full SFX wiring to sound-effects/*.wav #68
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:open_issues
agents
agent:security_audit
agent:verify
area
timecurve
arena
arena-v2
audit
block:feature_review
block:security
bug
contracts
design
devops
docs
documentation
enhancement
epic
feature
frontend
indexer
low priority
megaeth
operations
ops
performance
QA
qa checklist
referrals
removal
security
smart-contracts
tech-debt
testing
time-arena
timecurve
visual-qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
code/yieldomega#68
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Ship a layered audio experience in the frontend: background music (Album 1) via a small in-app player, plus one-shot and sparse-loop SFX from
frontend/public/sound-effects/{name}.wav, with SFX mixed above the music. Authoritative product guidance lives indocs/frontend/sound-effects-recommendations.md; this issue turns that into concrete implementation + acceptance work.Architecture (recommended)
bgmGain(album) andsfxGain(SFX), both feeding master with user mute and per-bus volume (see accessibility below).*.wavwith decode once,AudioBufferSourceper play (or pool); avoid reusing one HTMLAudioElement for overlapping hits.play()on load. It starts (or is armed) on the first user gesture on the page (click / key / touch) — e.g. same handler used to unlock BGM, then continue in-order playback.sound-effects-recommendations.md§6); avoid spamming the same*.wavon every TanStack refetch.Album 1 — music player (deliverable 1)
Asset root:
frontend/public/music/album_1/(order below).01-hills-dawn.mp302-coin-path.mp303-rainbow-switchback.mp304-moss-and-brass.mp305-jig-generator.mp306-starline-overworld.mp307-lucky-run.mp308-kumbaya-campfire.mp3Player behavior
Plays sequentially from track 1 → 8, then may loop the album or stop at end (pick one, document; looping is a better default for ambient sessions).
Default BGM level:
bgmGain0.25 of nominal (i.e. 25% perceived starting volume vs max slider) when the user has not changed the slider; persist preference inlocalStorage(or existing settings pattern).Controls (must exist in the UI and be wired):
constplaylist).Autoplay / unlock: on first user interaction with the document (within the app shell), if BGM is enabled and not yet started, call
play(); show player state (playing / current title).SFX over music: SFX bus gain independent of BGM; default mix so SFX are clear without clipping; optional light ducking of BGM on SFX (nice-to-have, not required for acceptance).
SFX — current
frontend/public/sound-effects/*.wav(deliverable 2)ui_button_click.wav<button>/ CTA.coin_hit_shallow.wavcharmed_confirmon confirm; not for every poller tick.charmed_confirm.wavbuy/buyFor/ relevant write confirmations (TimeCurve, treasury flows where UX signals “you’re in”); wallet connect success; generic tx confirmed (where not an error).peer_buy_distant.wavtimer_heartbeat_calm.wavtimerHardReset/ hero timer UX). Sparse (interval in tens of seconds), never every second.timer_heartbeat_urgent.wavwarbow_twang.wavkumbaya_whoosh.wavquoterefetch — pair with in-flight state (swapQuoteLoadinginuseTimeCurveSaleSession/ issue 56).Gaps (tracked but may ship after v1, or re-map existing file temporarily)
Many moments in
sound-effects-recommendations.md(modal open/close, 13m/15m hard reset, error/revert, sale end, redeem pour, PvP steal/guard/revenge) do not yet have a dedicated*.wav. For full coverage, either: (a) add newscripts/sound-effectspresets + regenerate, or (b) temporarily map the closest file (e.g.kumbaya_whooshfor “route”,ui_button_clickfor “disabled”) and document the mapping. This issue’s acceptance criteria require every user-facing control and major activity in the app to have an intentional SFX (including “silent on purpose” for e.g. hover), with no silent gaps for primary CTAs and core TimeCurve + wallet flows.Where to integrate (wiring map — non-exhaustive file hints)
frontend/src/pages/TimeCurveSimplePage.tsx,useTimeCurveSaleSession, timer / phase hooks (useTimecurveHeroTimer,timeCurveSimplePhase), buy CTA, CHARM / spend controls, Kumbaya quote flow.Accessibility & settings
prefers-reduced-motionper doc.Acceptance criteria
album_1; BGM autoplays only after first user interaction with the page; state is clear in the UI.sound-effects/{x}.wavor an explicit no SFX (and why) — no accidental silence on primary actions.*.wavabove are used where the table says; throttling and no spam on Kumbaya quote / cooldown are verified.docs/frontend/) links playlist order, SFX file names, and wiring pattern for future assets.Related doc:
docs/frontend/sound-effects-recommendations.md· Regen SFX:cd scripts/sound-effects && python generate.py --out ../../frontend/public/sound-effectsOut of scope (optional follow-ups)
mentioned in commit
54ba8cd736mentioned in commit
5b087686a9Issue #68 — implementation merged to
main(54ba8cd)Implemented the Web Audio layered stack from the issue: Album 1 (tracks 1–8) via
bgmGain+HTMLAudioElement/MediaElementSourceNode, SFX via decoded buffers onsfxGain, master + per-bus mutes and localStorage (yieldomega:audio:v1:).Behavior
AudioContextand prefetches core WAVs; BGM does not auto-start — user presses Play in the header bar (avoids double-toggle with the same click).coin_hit_shallowafterbuytx submit;charmed_confirmon receipt and onredeemCharmsreceipt;kumbaya_whooshon CL8Y/ETH/USDM pay-mode change; peer buys (indexer head, not self) + timer heartbeats (≤13m calm / ≤2m urgent, throttled); timer SFX off whenprefers-reduced-motion.charmed_confirmon connect false→true (no sound on cold load when already connected).ui_button_clickon primary buttons/nav links; softer gain on disabled buttons; inputs/ranges excluded.Docs / crosslinks
docs/frontend/sound-effects-recommendations.md§8,docs/frontend/timecurve-views.md(Simple audio),docs/testing/invariants-and-business-logic.md(table row + subsection),skills/README.md,.cursor/skills/yieldomega-guardrails/SKILL.mditem 17.Tests run:
cd frontend && npm run typecheck && npm test(Vitest all green). Playwright navigation was not completed in this environment (hung waiting on browser); recommend a quick CI / local UI smoke.@brouie please verify when you have a moment. Checklist:
Issue left open for your sign-off.
mentioned in issue #71
mentioned in issue #103
mentioned in issue #108
Source-level pre-walkthrough on
54ba8cd(carried into243e2a0) surfaced a concrete gap.Confirmed at source level
frontend/public/sound-effects/:charmed_confirm,coin_hit_shallow,kumbaya_whoosh,peer_buy_distant,timer_heartbeat_calm,timer_heartbeat_urgent,ui_button_click,warbow_twang.src/audio/sfxUrls.ts.yieldomega:audio:v1:consistent acrossaudioPreferences.tsandaudioPlaybackState.ts.Finding — filed as #108
Acceptance criterion 4 ("The eight
*.wavabove are used where the table says") is currently regressed: 3 of the 8 registered SFX have zero call sites in the codebase:coin_hit_shallowbuytx submit" — not wired)kumbaya_whooshwarbow_twangprefetchCommonSfxlist)Full inventory + repro + suggested fix in #108.
cc @PlasticDigits
Kumbaya whoosh is for future, other 2 need wiring
mentioned in commit
ae72b9d016Update — @brouie please re-verify (#68 maintainer guidance + inventory #108)
Shipped
coin_hit_shallowon TimeCurvebuy/ single-txbuyViaKumbayasubmit (tx hash returned, before receipt) viaplayGameSfxCoinHitBuySubmitinuseTimeCurveSaleSession,useTimeCurveArenaModel, andlib/timeCurveKumbayaSingleTx.ts.warbow_twangis wired for indexed ladder podium cues only (shouldPlayWarbowRankStingerinfrontend/src/audio/warbowRankSfxPolicy.ts+ throttle ~18s inWebAudioMixer;useArenaWarbowRankSfxin Arena view). Mid-pack rank drift (e.g. 10→4) stays silent by design — tests inwarbowRankSfxPolicy.test.ts.kumbaya_whooshremains off prefetch / UX until explicit pay-route wiring (per PlasticDigits).Invariant / docs:
INV-AUDIO-68-WIREindocs/testing/invariants-and-business-logic.md, sound-effects §8, timecurve-views (Simple/Arena audio), manual QA #manual-qa-sfx-coin-warbow-108. Cross-links from.cursor/skills/yieldomega-guardrails/SKILL.md,skills/README.md,skills/play-timecurve-warbow/SKILL.md,skills/contributor-mobile-album-dock/SKILL.md.Automated verification:
cd frontend && npm ci && npm run typecheck && npm run test -- --run(Vitest green).Issue left open for your sign-off.
Checklist for @brouie
warbow_twang, excludes whoosh.#manual-qa-sfx-coin-warbow-108.all 4 checklist items pass — source + audible.
source-side wiring:
playGameSfxCoinHitBuySubmitdefined ataudio/playGameSfx.ts:19-20(gainMul 0.9), called from 3 modules per your note —useTimeCurveSaleSession.ts:1051(Simple),useTimeCurveArenaModel.tsx:2293(Arena),lib/timeCurveKumbayaSingleTx.ts:111(single-tx Kumbaya)writeContractAsyncresolve, beforewaitForTransactionReceiptwarbow_twangwired viaWebAudioMixer.ts:341throttle +useArenaWarbowRankSfx.tsconsumerwarbowRankSfxPolicy.test.ts5/5 vitest pass (covers 10→4 mid-pack silence + top-3 entry/movement triggers)AudioEngineProvider.tsx:71-81includes warbow_twang, correctly excludes kumbaya_whooshINV-AUDIO-68-WIREat invariants-and-business-logic.md:416 +manual-qa-sfx-coin-warbow-108at manual-qa-checklists.md:469 resolveaudible walk on /timecurve/arena:
all 4 items in your checklist pass.