Files
templates/c/set-protocol/docs/GUI_SPECTRUM.md

54 lines
2.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Shared GUI spectrum
`include/set_spectrum.h` / `src/set_spectrum.c` implement the same numerical
pipeline for desktop and Android. CMake, `tools/build_host.py`, and the Android
NDK build include it. The wire protocol is unchanged. The host-only analyzer
allocates at most two FFT arrays (2×N doubles), releasing them before return.
The last N samples are used: the largest power of two within available data and
`max_size`, 16…16384. Timestamps are seconds; inputs are immutable. Fs is measured
from the selected endpoints. Non-monotonic/duplicate times and interval deviations
over 50% of the mean are rejected. Lesser jitter is linearly interpolated onto an
even grid (this can affect high-frequency amplitude; inspect returned jitter).
Processing order: interpolation, optional mean subtraction, filter, periodic
window, forward FFT, one-sided peak amplitude. Windows: rectangular, Hann,
Hamming, Blackman, Flat Top. Amplitudes are divided by window sum, doubled except
DC and Nyquist. Output is not RMS/PSD/dB. Coherent gain correction is exact for
bin-centered tones away from DC/Nyquist; off-bin tones still have scalloping.
Filters run before the window, on the unmodified sample copy. LP/HP are second
order Butterworth; band pass cascades HP and LP; notch uses Q=30.
Coefficients: [W3C Audio EQ Cookbook](https://www.w3.org/TR/audio-eq-cookbook/).
Initial state is the first sample's steady state, not a carried streaming state;
block-start transients may occur. Cutoffs must be strictly within (0, Fs/2).
## Python
```python
from protocan.spectrum import NativeSpectrum, Window, Filter
# lib = an existing ctypes.CDLL from protocan.native.NativeProtocol
spectrum = NativeSpectrum(lib).analyze(times_seconds, values,
window=Window.HANN, filter=Filter.LOW_PASS, high_hz=100,
max_size=4096, remove_mean=True)
plot(spectrum.frequencies, spectrum.amplitudes)
```
Adapter errors are ValueError, not empty/misleading arrays. No NumPy/Qt dependency.
## Android
`SpectrumAnalyzer.analyze(List<TrendPoint>, SpectrumOptions)` calls JNI using
relative seconds from millisecond timestamps. `TrendSpectrum` contains N, Fs,
maximum relative jitter, amplitudes or a displayable error. Call on a worker
dispatcher. `PlotViewport` provides axis-independent zoom/pan, focus anchoring,
128× limit and bounds clamping without any Compose dependency.
## Checks
Build CMake with tests and run CTest in Debug (assertions enabled). Python
`tests/test_spectrum.py` runs against an explicitly supplied `SETPROTOCOL_LIBRARY`:
independent direct DFT, amplitude correction, DC/Nyquist, off-bin leakage, filter
bands, timing rejection/interpolation, bounded tail selection and immutable inputs.