# Implementation notes

Built from `prompt.txt` only. The app is a single local HTML file with inline CSS and JavaScript. It uses no external libraries, assets or services.

## Choices

- A generated eight-second stereo C major 9 chord gives an immediate source. Imported audio decodes locally, becomes the selected source and loops. Importing alone does not start playback.
- Clean, subtly worn and clearly degraded presets change all three treatments. Each treatment also has its own bypass and control. Custom control changes clear the preset selection.
- Saturation uses a soft `tanh` curve with drive compensation. Bit reduction quantizes amplitude independently. Sample resolution uses a sample-and-hold clock at the selected effective rate. It intentionally allows aliasing rather than acting as a playback-speed control.
- Signal order is saturation, bit reduction, then sample hold. The hold-clean button temporarily bypasses all three without resetting settings. Pointer, touch and keyboard release restore the edited version.
- Master volume starts at -18 dB and is limited to -6 dB. The chord peaks at 0.68. Loud imported files receive a uniform reduction to at most the same peak; quiet files are not raised. A compressor after the master provides an additional ceiling. Presets are not precisely matched for perceived loudness.
- AudioWorklet handles sample processing when available. A native ScriptProcessor fallback supports browsers or local-file contexts that reject the Blob worklet module. A shared DSP function keeps both implementations consistent.
- Stop fades the master. Escape and moving the page into the background stop playback. Source and preset changes do not intentionally reset the comparison source position, except switching between the chord and imported file restarts the selected source.
- Layout adapts to a single column on small screens. Inputs have visible focus states, text labels and separate accessible bypass names.

## Checks performed

- Parsed the full inline JavaScript with Node.
- Ran the actual shared DSP body against synthetic arrays. Confirmed exact clean pass-through, independent saturation, 5-bit quantization steps, a 4 kHz sample hold at a 48 kHz processing rate, and the temporary clean override.
- Checked for duplicate HTML IDs.
- No browser, server, rendered-layout check or listening test was run by this implementation agent. Browser testing belongs to the parent task.

## Limits

- This is a texture comparison, not a hardware emulation or calibrated hearing test. Comfortable output still depends on the device and headphone volume.
- Source switching and hard effect changes can produce a short transition. Imported loop boundaries are not crossfaded.
- Supported import formats depend on the browser decoder. Very long files are held in memory. There is no export or recording feature because the prompt asks for listening comparison.
- The ScriptProcessor compatibility path uses the main thread and may be less stable under heavy page load. The main path uses the audio rendering thread.

The first complete implementation is preserved in `attempts/001/index.html` with these notes.

## Student follow-up 002

The menu had a malformed closing tag, `</option value="import" disabled>`, where a closing tag followed by a new opening option belonged. As a result, browsers received only one real source choice. Corrected the markup so Generated chord and Imported audio are separate options. Imported audio remains disabled until a successful file import, then the existing import handler enables and selects it. Added a stable ID for that option and replaced positional lookups with that ID. The decoded imported buffer stays in memory when switching to the chord and back. The treatment controls, generated chord and DSP are unchanged. The QA observer script reference remains in place.

Checks for this follow-up: JavaScript parse check, HTML parser check that the menu contains two separate options, and a local mocked-DOM/audio test of import and switching between both retained buffers. No browser or listening check was run by this agent.
