FANCO16 v8 — filtered noise and a shared-source mixer =================================================== v8 uses the v7 instruction set and C/WASM CPU, graphics and sound core. The simulated guest CPU runs at 60 MHz (1250 guest cycles per 48 kHz sample). App images carry version 8. v7 builds do not include these extensions. The v7 register map remains in place. The v8 additions occupy 03F8–03FA and 0480–05FF; ordinary guest RAM and custom-envelope DMA source addresses start at 0600. Capture DMA cannot write below 0600. Noise recipes and envelope keyframes are guest content: they occupy and count against the 64 KB guest address space. The chip contains no instrument recipes, note tables or instrument handlers. 0480–04FF: 16 shared-source mixer slots, 8 bytes each +0 bit 7 enable; bits 0–4 source ID +1 signed pan, -127 left, 0 center, 127 right (-128 treated as -127) +2 little-endian gain, 0–65535 maps to 0–1 +4 route: 1–3 shared filters, otherwise stereo dry bus +5 delay send, 0–255 maps to 0–1 (dry route only) +6 gain response +7 pan response Source IDs: 0–15 existing operators; 16–23 filtered noise generators. 24–31 are reserved and return zero. Each slot may select either generator kind. Existing 0300–0327 mixer slots remain available for operators. A mixer slot scales the source by gain / 3, then the existing master stage scales by 0.5 at full volume. Pan is linear with unity at center per channel. Additive operator sources preserve their partial stereo image on dry routes. 0500–057F: 8 noise generators, 16 bytes each +0 little-endian high-pass cutoff in Hz; 0 bypasses the high-pass +2 little-endian low-pass cutoff in Hz; 0 or >=24000 bypasses it +4 little-endian U4.12 amplitude gain (4096 = 1) +6 high-pass cutoff response +7 low-pass cutoff response +8 gain response +9 bit 0 enable; bit 7 reset strobe (cleared after the control tick) +10 bits 0–1 high-pass stages - 1; bits 2–3 low-pass stages - 1 +11–15 reserved 0580–05FF: reserved for expansion; writes stored, no audio effect. Each noise generator has its own deterministic xorshift32 stream, uniform in [-1,1), followed by a second-order Butterworth high-pass and low-pass. The filters use trapezoidal state-variable integration at 48 kHz, Q=1/sqrt(2). Each filter may cascade 1–4 identical sections at the same cutoff: 12, 24, 36 or 48 dB per octave (the cutoff point sits 3 dB down per section). Active cutoff is clamped to 5–21600 Hz. Cutoffs are independent: an inverted band attenuates both sides rather than silently swapping them. A reset clears filter history and restores that generator's seed. Disable outputs zero and freezes its noise/filter state; parameter responses continue advancing. Noise capture IDs are 10–17 hexadecimal. Existing capture IDs are unchanged. Response bytes use the existing additive-weight response encoding: 00 immediate top two bits 00 damped spring, 01 linear, 10 S-curve, 11 exponential lower six bits q: response time = 2^(q/5) / 600 seconds The all-zero byte is immediate rather than a spring. Exponential response reduces remaining error to 10% in that time. Spring damping ratio is 0.69. Targets latch at the chip control rate, fixed at 600 Hz; responses advance per audio sample. Cutoff response is linear in Hz, gain in amplitude, pan in signed linear position. Spring overshoot is allowed; pan is clamped on output. All new register values and running states reset to zero except stream seeds. Control rate and output stage ----------------------------- The chip latches all register targets every 80 samples (600 Hz). 03F4–03F5 are fixed at 600; writes have no effect. 03F8 output mode: bit 0 limiter off, bit 1 soft clip on 03F9 ceiling, n/256 of full scale; 0 = 243 (95%) 03FA limiter release, n × 10 ms; 0 = 100 ms Mode 0 (reset): look-ahead limiter. It sees 96 samples (2 ms) ahead and lowers the gain before a peak arrives, so the output stays at or below the ceiling and the waveform keeps its shape. Signals below the ceiling pass unchanged. Mode 1: raw path; the signal is only clamped to ±1. Mode 2: limiter, then soft clip. Mode 3: soft clip only: above the ceiling, y = c + (1 - c)·t/(1 + t) with t = (|x| - c)/(1 - c), approaching full scale. Every mode ends in a ±1 clamp and delays the output by 95 samples, so mode changes do not shift time. Structural transitions — implementation candidate, not deployed --------------------------------------------------------------- An operator produces a stream of sound samples. A filter changes which frequencies pass through. Some settings can move gradually: for example, cutoff frequency can move from 200 Hz to 2000 Hz using its response control. Keep these existing parameter responses; they are not replaced by this design. Other settings change the structure of the sound. Switching a sawtooth to a sine changes the waveform. Changing a noise filter from one stage to three means sending sound through three filters in a row instead of one. Making such a change in one sample can cause a sharp jump heard as a click. For structural changes, run the old and new versions together briefly: old configuration + running state -> old sound -- fade out --+ +-> mixer new configuration + running state -> new sound -- fade in ----+ The transition lasts exactly one control tick: 80 samples at 48 kHz, or 1/600 second. A fixed, precomputed S-curve table supplies the blend amount w, starting at exactly 0 and ending at exactly 1: output = (1 - w) * old sound + w * new sound The S-curve starts and ends gently. Both versions keep running during the transition; this is not a fade from a frozen sample. After sample 80, discard the old version. The next control tick can start another transition without building up extra copies. The new sound starts during this tick, not after a one-tick wait. Mixers, effects and the final limiter receive the blended sound. Structural smoothing is enabled by default, with a per-operator and per-noise-generator opt-out for programs that deliberately want hard switches. There is no global switch or adjustable transition duration in this design. Operator +0E bit 5 disables structural smoothing. Classic waveform selection (+04 bits 4–7, +07 bits 0–1) and combination mode (+07 bits 6–7) trigger it. Both paths share the running phase, pitch, envelope and modulation controls; these are not retriggered by a shape change. Each path retains its waveform configuration and separate colored-noise history. The blended output drives self-feedback and downstream modulation. Entering or leaving additive mode is not covered; additive-bank changes retain their existing behavior. Noise +9 bit 6 disables structural smoothing. A change to +10 bits 0–3 (stage counts) triggers it when the generator was and remains enabled. The outgoing path retains its filter history and existing parameter responses. The incoming path copies that history, clears newly added stages, and accepts the new cutoff/gain targets through their existing response controls. Both paths start with the same random-stream state and advance independently. Reset (+9 bit 7) takes priority and remains a hard reset. Enable/disable and cutoff bypass changes retain their existing behavior, without this crossfade. The first control tick initializes directly; there is no startup crossfade. Sharing modulation signals ~~~~~~~~~~~~~~~~~~~~~~~~~~ One operator can control another. For example, operator A can make operator B's pitch rise and fall. A is then B's modulation source: a moving control signal. If B changes shape, both old B and new B read the same signal from A: +-> old B --+ A -> one control signal | +-> blended B output +-> new B --+ Do not make a separate copy of A for each version of B. If another operator controls A, copying the whole chain again could multiply the work needlessly. Each source produces one shared output signal per sample. A source undergoing its own transition supplies its blended output. Preserve the chip's defined operator evaluation order; do not recursively evaluate upstream operators. Work budget and verification ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Assume a guest changes every eligible generator on every 600 Hz tick. Then both versions run continuously. Budget and measure that worst case on the user's real device while sustaining the promised virtual CPU rate; occasional changes are not an adequate performance test. At most two versions of each unit may run. Additional running state is chip working memory, not guest instrument content. Exact real-device cost has not yet been measured. Verify waveform switches, filter-stage switches, successive-tick changes, opt-out behavior and interactions with parameter responses. Reproduce the OP10 noise bursts separately: the player used immediate cutoff changes with slower gain ramps. Structural smoothing does not excuse mismatched continuous parameter responses. Remove the guest's temporary noise-reuse waiting queue only after the chip and guest configuration handle those transitions correctly. Build: sh v8/wasm/build.sh Live audition: /v8/piano/noise/ The audition's host compiles numeric recipes into guest keyframes; the guest CPU schedules every gain write. AudioWorklet runs the actual C/WASM CPU and chip in 128-sample slices. No synthesized WAV is used for the live VM button. The reference button plays a selected original Steinway recording clip. Spectrograms use offline captures of the same guest program and C/WASM chip.