Then play the actual instrument.
The hero above is the real signal — click it. An OscillatorNode runs through a WaveShaper into an AnalyserNode; getByteFrequencyData feeds the bars, getByteTimeDomainData feeds the curve. Below is the same idea wired into a controllable instrument with the same ring-buffer plumbing the signal page uses.
Mouse X controls frequency. The spectrum responds in real time. Bars rise from the bottom. Waveform floats above. Particles burst on peaks. One signal, visualized.
Sits between the AudioWorklet and the speakers. Performs FFT on every audio frame — decomposing the waveform into 128 frequency bins. getByteFrequencyData() returns magnitude in dB. getByteTimeDomainData() returns the raw waveform. Both feed the canvas every frame.
The signal-processor.js AudioWorklet is identical to the one on the signal page. Same SPSC ring buffer. Same frequency input. Same sine oscillator output. The only addition is the AnalyserNode between worklet and destination. Different view. Same instrument.