# CLIENT-SIDE EXECUTION FLOW (SF3 + SPESSASYNTH + INDEXEDDB)

This document describes the step-by-step processing chain that takes place inside the Client Browser, from launching the Web DAW application, downloading and buffering `.sf3` instrument files, and setting up MIDI channels, to outputting real-time audio.

---

## 1. SEQUENCE DIAGRAM

```text
[ USER / UI ]        [ APP / CLIENT ]        [ INDEXEDDB ]        [ SERVER API ]      [ SPESSASYNTH ENGINE ]
      |                     |                      |                    |                       |
1. Open Web Page ---------> | Initial AudioCtx     |                    |                       |
      |                     | Init SpessaSynth -----------------------------------------------> | Connect Destination
      |                     | Fetch Catalog --------------------------->| Get /catalog          |
      |                     |                      |                    |                       |
2. Select Instrument -----> | Read (sf_id, bank, prog)                  |                       |
   (e.g., Pipa)             | Query SF3 Buffer --->| Check Key (sf_id)  |                       |
      |                     |                      | -- (Miss) -------->| Fetch /download/sf_id |
      |                     |                      |                    | Return .sf3 (~4MB)    |
      |                     | <--------------------| Save ArrayBuffer --|                       |
      |                     | Load SF3 Memory ------------------------------------------------> | addSoundFont(buffer)
      |                     |                      |                    |                       |
3. Channel Router --------> | Switch Bank/Program -------------------------------------------> | controllerChange(ch, 0, bank)
      |                     |                      |                    |                       | programChange(ch, prog)
      |                     |                      |                    |                       |
4. Trigger MIDI Key ------> | Raw MIDI Event       |                    |                       |
   (or Timeline Play)       | (noteOn: pitch, vel) -------------------------------------------> | noteOn(ch, pitch, vel)
      |                     |                      |                    |                       | AudioWorklet Synthesis
      |                     | <------------------------------------------------------------------ | Audio Out (User Speakers)

```

---

## 2. DETAILED PROCESSING PHASES

### PHASE 1: BOOTSTRAPPING & ENGINE INIT

* **Web Audio Context Initialization:** Upon the user's first interaction with the web page (Mouse Click/Keypress), the application initializes the `AudioContext`.
* **SpessaSynth Synthesizer Initialization:** The `soundfontPlayer.js` module instantiates `SpessaSynthClass` and connects its output directly to `audioCtx.destination`:
```javascript
this.synthInstance = new window.SpessaSynthClass(this.audioCtx.destination);

```


* **Instrument Catalog Load (Catalog Context):** The Frontend dispatches a `GET /api/v1/plugins/soundfonts/catalog` request to load the `condensed_catalog`, which contains lookup tables for `sf_id`, `bank`, and `program`.

---

### PHASE 2: `.SF3` ASSET LOADING & CACHING

Triggered when a user selects an instrument via the Synth UI button (or when the AI Copilot spawns a new Track with a designated instrument, e.g., `dsk_asian_dreamz`):

* **Query Browser Cache (IndexedDB):** The Client calls `sfStorage.getBuffer(sfId)` to search for the `.sf3` file's `ArrayBuffer` inside the `DAW_SoundFont_Cache` database.
* **Handling Cache Hit vs Cache Miss:**
* **Cache Hit ($0\text{ms}$):** Retrieves the `ArrayBuffer` directly from the browser's RAM/Storage.
* **Cache Miss:**
1. Sends a `GET /api/v1/plugins/soundfonts/download/{sf_id}` request to the Server.
2. Downloads the compressed, optimized `.sf3` asset (ultra-lightweight size $\sim 3.5 - 5.5\text{ MB}$).
3. Invokes `sfStorage.saveBuffer(sfId, arrayBuffer)` to store it inside IndexedDB for subsequent visits.




* **Load Data into SpessaSynth Wasm/JS Memory:** Passes the `ArrayBuffer` to SpessaSynth Engine's `SoundFontManager`:
```javascript
await this.synthInstance.soundFontManager.addSoundFont(buffer);

```



---

### PHASE 3: BANK/PROGRAM ROUTING & MIDI CHANNEL SETUP

This is the most critical phase to resolve `No preset found for 0:0:0` errors.

* **MIDI Channel Assignment:**
* **Melodic Instruments (Piano, Pipa, Strings, Brass, etc.):** Allocated to Channels 0 through 8.
* **Percussion / Drum Kits (Bank 128):** Mandatory allocation to Channel 9 (GM Standard Channel 10).


* **Dispatch Bank Select & Program Change to SpessaSynth Engine:** Prior to scheduling any note events, the Client triggers two simultaneous control events:
```javascript
// 1. Select Bank (Control Change 0)
this.synthInstance.controllerChange(channel, 0, bank);

// 2. Select Program (Program Change)
this.synthInstance.programChange(channel, program);

```


*Example for Pipa (`dsk_asian_dreamz`):* Calls `controllerChange(0, 0, 0)` and `programChange(0, 0)`. SpessaSynth switches Channel 0's state to the Pipa instrument patch.

---

### PHASE 4: REALTIME SYNTHESIS & AUDIO OUTPUT

Triggered when receiving note-control signals (from a Hardware MIDI Keyboard or Timeline Transport Playback):

* **Scenario A: User plays a Hardware MIDI Keyboard (e.g., Nektar SE49)**
1. The browser receives a Raw MIDI Event: Web MIDI API captures message `[144, 65, 78]` (`NoteOn`, `Pitch 65`, `Velocity 78`).
2. **Latency Compensation:** Calculates real-time offsets and issues `NoteOn` to SpessaSynth:
```javascript
const midiPitch = pitch;
const midiVelocity = Math.floor(velocity * 127);
this.synthInstance.noteOn(channel, midiPitch, midiVelocity);

```


3. **Key Release:** Triggers a `NoteOff` event:
```javascript
this.synthInstance.noteOff(channel, midiPitch);

```




* **Scenario B: User triggers Play on Timeline / Piano Roll**
1. **Transport Controller & Scheduler (`PrecisionAudioScheduler`):** Scans for MIDI notes located within the moving Playhead window.
2. **Note Scheduling:**
* Converts beat positions to precise audio timing based on BPM tempo (`exactAudioTime`).
* Dispatches `noteOn(channel, pitch, velocity)` at the exact timestamp $T_{\text{start}}$.
* Dispatches `noteOff(channel, pitch)` at timestamp $T_{\text{start}} + T_{\text{duration}}$.




* **Audio Worklet Audio Rendering:** SpessaSynth Engine reads Ogg/WAV sample data inside the `.sf3` asset, applies Envelopes (ADSR), Modulators, and Gain Control parameters on the designated Channel, and pushes PCM audio data directly to user speakers with $0\text{ms}$ latency.

---

## 3. 100% RELIABILITY VERIFICATION CHECKLIST

* [ ] `.sf3` files loaded into the browser open without triggering `Corrupted File` errors.
* [ ] The `sfStorage.getBuffer` function successfully stores and retrieves `ArrayBuffer` data from IndexedDB.
* [ ] Both `controllerChange(channel, 0, bank)` and `programChange(channel, program)` are invoked immediately upon changing instruments on the UI.
* [ ] Percussion/Drum instruments are persistently allocated to Channel 9.
* [ ] Console logs confirm: `[SonicSF] Switched Channel X -> Bank: B, Program: P`.