Phase 1 completion: every official package now has a synthesized spec with screens/flow, rules/scoring/AI, controls, content inventory, implementation plan and an Assembly!Type.Method citation log. 62 specs / ~9,000 lines; documentation-first gate is closed. Notable corpus findings recorded in the specs: - color-spill is blocked upstream: its marketplace package shares a GUID with Reversi, so the archive payload is Reversi.exe (register notes + spec gap). - W2 AI tiers, W3 score/simulation constants, W6 30 Hz deterministic simulation and content inventories are now pinned for implementation. No Microsoft content is committed; analysis only.
8.5 KiB
Piano
- Official package:
Piano.exe(piano) - Corpus:
Zune HD Apps (Decompiled)/piano(external, untracked) - Wave: W1 · Category: music
- Status:
native· Complexity: TBD - Dorado-HD id: piano
Synthesized from the decompiled reference. No Microsoft code, strings, or assets are copied; behavior is re-derived and all content is re-authored.
1. Device behavior (mined)
Piano.exe is a 38-type / 119-method XNA application (2,934 lines) that runs
landscape-only at 480×272. It is a multi-touch electric piano: a 52-white-key
scrollable keyboard with correctly offset black keys, per-octave colour
themes, note-name notation, three volume levels, and latching sustain/dampen
pads. Samples are a full chromatic set of recorded piano notes (A−1…C7),
transposed upward when the exact key has no sample.
| Assembly | Types | Methods | Source lines |
|---|---|---|---|
Piano.exe |
38 | 119 | 2934 |
Microsoft.Xna.Zune.dll |
110 | 825 | 15652 |
Core types: Piano!PianoKeyboard (key layout, scroll interpolation,
multi-touch routing), Piano!PianoKey (per-key voice, glow, sustain/dampen,
release fade), Piano!PianoKeySoundBank (sample lookup + voice cap),
Piano!PianoKeyPitch (note arithmetic), Piano!NotePitchExtensions
(white/black classification), Piano!TopButtonBar/OctaveBar (controls),
Piano!Device (accelerometer orientation lock) and Piano!Settings
(PianoSettings/Settings.xml with ShowNotations and VolumeLevel).
2. Screens & navigation
Game1 owns the whole scene: a shared sprite sheet is parsed from
SpriteSheet.txt and a LoadingScreen (startup-notated / startup-normal
plus loading-bar frames) covers startup. After load there is a single
landscape screen with three zones:
- Top control bar (
TopButtonBar.Load): two 52 px key groups at x=322 and x=375 with an arrow at x=428 that flips between them, plus a 104×56 About text button. State 0 shows notation toggle + volume (three steps); state 1 shows dampen + sustain pulse pads.ArrowButton.Clickedstarts a 0.2 s cross-fade between the two states. - Keyboard: 52 white keys drawn at 60 px pitch and 221 px height, with
black keys 40×127 inset 20 px into each white key's right edge; the whole
keyboard is translated by
WhiteKeyOffset(in white-key units). - Octave bar (
OctaveBar.Load): a 7-notch overview strip at the left, drawn with theoctave_select_off/octave_select_keynotesstates and theoctave_selectormarker.
AboutScreen is a modal overlay dismissed by a tap. Device forces portrait
first, then tracks orientation, and TouchManager transforms touch points into
the landscape coordinate space.
3. Rules, scoring & progression
There is no score. The play/audio model is the interesting part:
- Voice allocation (
PianoKeySoundBank.PlayNote): look up the exact pitch; if missing, walk outward up to 12 semitones (AdjustPitchByKeyCount) and play the found sample transposed withSoundEffectInstance.Pitch. At most 14 live instances are kept — older ones are disposed first — andInstancePlayLimitExceptionis swallowed so fast glissandi never crash. - Press/release (
PianoKey.Press/Release): pressing starts a voice and sets the glow (0.7 with dampen, 1.0 otherwise), pushing the previous voice onto anoldNoteslist. Releasing while sustain is on leaves the note ringing; otherwise it enters a 1 s cool-down that fades the instance at double rate and then disposes it.Unsustainstops all ringing non-pressed keys;Dampendrops volume to 0.7 andUndampenrestores 1.0.KillSound,ReleaseAllKeysandDampenAllKeys/UndampenAllKeys/UnsustainAllKeysare the bulk operations used by the top bar and input loss. - Glow decays per frame: 0.4/s while sustain is latched, 2/s otherwise.
- Octave navigation: dragging the octave bar scrubs continuously
(
OctaveBar.HandleInput), tapping a notch snaps to one of seven octaves; on release the keyboard interpolates (WhiteKeyStart/WhiteKeyTarget, speed 8–10/s) and the octave marker follows for scrub moves. - Settings:
Settings.Load/Saveread/write a storage-containerPianoSettings/Settings.xmlwith a notation flag and 0–2 volume that maps to master volume 0.3/0.6/1.0.Game1.Initializere-applies the level. - Startup art and per-key colours are octave-themed: nine ebony/ivory/edge
hues indexed by octave (
PianoKeyboard.GetColorOctave), and the keyboard draws note letters when notation display is on.
4. Controls
Fully multi-touch. Game1.HandleInput routes every touch point:
OctaveBar.HandleInput first claims touches on the strip; a new touch on the
top bar runs TopButtonBar.TestInput; touches below y=56 hit the keyboard.
When a finger moves more than 10 px in a frame the path is interpolated in
10 px steps so dragging produces a glissando rather than a gap. Notes are
released when the finger lifts (ReleaseKeysNotPressedThisFrame after
ResetKeysForNextFrame). The Damper/Sustain pads are latching pulse buttons
whose outline pulses whenever a key is played. About is a tap-to-dismiss
overlay. Accelerometer is used only to keep the device locked to landscape —
there is no tilt instrument.
5. Content inventory (must be re-authored)
35 files: 30 audio XNBs (a chromatic sample set: A_-1…A_6, C_0…C_7,
DSharp_0…DSharp_6, FSharp_0…FSharp_6), one 284 KB sprite sheet, its
SpriteSheet.txt rectangle table, Text/Fonts.xml, and Language/en|es|fr
strings. The samples are recorded piano audio (Microsoft content) and the
sprite sheet is Zune UI chrome.
Re-authoring: no sample may ship. Build a PianoVoice synth in MiniSynth:
per-note frequency (equal temperament from A4 = 440), a fast attack and long
exponential decay with a few harmonic partials and a velocity/volume envelope
per the 0–2 volume setting; black keys derive from the same table. Keys,
octave bar and top-bar states are drawn with Compose canvas + tokens (zero
radius); SpriteSheet is not used.
6. Implementation plan
- Engine: new
ui/apps/piano/PianoEngine.kt—object PianoEngine+ immutabledata class PianoState(scrollWhiteKeys, volume, notation, sustain, dampen, activeKeys); pure helpers for the 52-key layout (white/black bounds, black-key offset),noteFor(whiteIndex, black),frequencyFor(midi), octave-bar snap/scrub maths, and voice allocation (cap 14, oldest-first eviction). - Audio:
ui/apps/piano/PianoVoice.ktonMiniSynth— synth-only, no samples; a short attack, long decay, two-three partials, and a dampen/sustain gate that matches the device envelope times (1 s release fade, 0.7 dampen gain). Note names in notation mode useSelawik. - UI: rewrite
PianoApp()(PianoDrum.kt:31) asui/apps/piano/PianoApp.kt: landscape canvas keyboard scrolled byWhiteKeyOffset, multi-touch down/move/up tracking per pointer id, interpolated glissando, top bar with arrow-flipped notation/volume and dampen/sustain pads, octave strip on the left.DetailScaffoldprovides the back affordance; everything token-coloured, zero radius. - Fidelity gaps vs current code: only 14 fixed white keys, tap-only play, no scroll/octave bar, no sustain/dampen/volume/notation, no glissando and no voice cap.
- Persistence:
showNotationsandvolumeingraph.appState.put("piano", …). - Tests:
app/src/test/java/com/heretek/dorado_hd/PianoEngineTest.kt— note layout (52 whites, 36 blacks), black-key placement set, frequency table, octave snap points, voice-cap eviction, sustain/dampen gating and release fade, glissando path sampling. - Edge cases: 10-finger chords on a small screen, pointer cancel/re-entry, scrolling while notes are held, sample-free range above C7 (clamp or octave-fold), and About overlay swallowing touch-up.
7. Citation log
Piano!PianoKey.Press, Piano!PianoKey.Release, Piano!PianoKey.Dampen,
Piano!PianoKey.Undampen, Piano!PianoKey.Unsustain,
Piano!PianoKey.KillSound, Piano!PianoKey.Update,
Piano!PianoKeyboard.Load, Piano!PianoKeyboard.HandleInput,
Piano!PianoKeyboard.GenerateWhiteKey,
Piano!PianoKeyboard.ReleaseKeysNotPressedThisFrame,
Piano!PianoKeyboard.GetColorOctave,
Piano!PianoKeyPitch.AdjustPitchByKeyCount,
Piano!PianoKeySoundBank.PopulateSoundBankForInstrument,
Piano!PianoKeySoundBank.PlayNote, Piano!TopButtonBar.Load,
Piano!TopButtonBar.pianoKeyboard_KeyPlayed, Piano!ArrowButton.Clicked,
Piano!OctaveBar.HandleInput, Piano!OctaveBar.Load,
Piano!Settings.Load, Piano!Settings.Save, Piano!AboutScreen.Show,
Piano!Game1.HandleInput, Piano!TouchManager.Update, Piano!Device.Update.