# Four places — implementation notes

## Behavior

- Four supplied MP3 files, independent on/off buttons and 0–100% level sliders.
- Output starts at 35%; each sound starts at 45%. These are gain settings, not a loudness measurement or guarantee.
- File duration is read using local audio metadata before that sound's on/off button enables. Nothing plays while metadata is read.
- Web Audio is created and resumed only from an on-button click. The first start fetches and decodes the selected recording; decoded buffers are then cached in memory.
- A looping AudioBufferSourceNode plays each sound. Repeated loops use the decoded buffer's full duration and the audio clock, with no JavaScript restart timer.
- Turning off or stopping all resets a sound. Its next start begins at zero. Slider positions are retained.
- Stop all also cancels sounds that are still loading. Repeated starts create fresh source nodes rather than attempting to restart a stopped node.
- Gain changes, starts and stops use short ramps. Stop takes about 35 ms.
- The interface (`app.js`, `styles.css`, `index.html`) is separate from the reusable engine (`audio-engine.js`).

## Run

Open through the existing local server at `http://127.0.0.1:4191/apps/01-loops/`. No build step, package or internet service is used. ES modules and audio fetching require an HTTP local server; opening index.html directly through a file URL is not supported.

## Verification and limitations

- JavaScript syntax checks and a mocked Web Audio engine check are run locally; see `engine.test.mjs` for what the engine check covers.
- Mock checks cover concurrent playback, output/track gain, stop, restart, whole-buffer loop configuration, and cancellation while loading. They do not replace listening in a browser.
- Browser interaction and audible loop boundaries have not been checked by this implementation agent; the parent owns browser verification.
- The engine adds no gap between decoded buffer repeats. An audible boundary can still exist in the supplied recording itself; there is no crossfade or edit of the source audio.
- Starts are independent and unsynchronized. No microphone, recording, export, persistence or normalization is added.
- Background playback depends on browser and operating-system policies. No assumption is made about a tab continuing indefinitely in the background.
- Metadata errors leave the relevant track disabled and display an explanation. Decode/playback errors allow a fresh on-button attempt.

The first complete version is preserved in `attempts/001/` and made read-only. Any later revisions belong in the working files, not that snapshot.
