# Spectro Desk > A spectrogram answers two questions with one picture — when did it happen, and > what pitch was it — and the window length is the dial between them. This works > out what your settings can and cannot separate, and whether what you are > asking of the picture has an answer at all. ## The one thing to know ```text df = rate / N the width of one bin, in hertz dt = N / rate the length of one window, in seconds df * dt = 1 always, for every rate and every N ``` You do not get to choose both. That is not a limitation of any tool — it is what a Fourier transform is — and every argument about "the right window" is really an argument about which of the two questions matters here. At 48 kHz with a Hann taper: | Window | One bin | One window | Separates | Semitone floor | | --- | --- | --- | --- | --- | | 512 samples | 93.8 Hz | 10.7 ms | 375 Hz | 6,306 Hz | | 1,024 samples | 46.9 Hz | 21.3 ms | 188 Hz | 3,153 Hz | | 2,048 samples | 23.4 Hz | 42.7 ms | 93.8 Hz | 1,577 Hz | | 4,096 samples | 11.7 Hz | 85.3 ms | 46.9 Hz | 788 Hz | | 8,192 samples | 5.86 Hz | 171 ms | 23.4 Hz | 394 Hz | | 16,384 samples | 2.93 Hz | 341 ms | 11.7 Hz | 197 Hz | | 32,768 samples | 1.46 Hz | 683 ms | 5.86 Hz | 98.5 Hz | Every row's bin width times its window length is exactly 1. ## The taper is not free Nobody analyses with a rectangular window, because its sidelobes are only 13 dB down and a quiet tone beside a loud one disappears under its skirts. Every taper that fixes that widens the main lobe, and the main lobe is what actually decides whether two tones separate: | Shape | Main lobe | First sidelobe | Separates at 2,048 | Semitone floor | | --- | --- | --- | --- | --- | | `rectangular` | 2 bins | -13 dB | 46.9 Hz | 788 Hz | | `hann` | 4 bins | -31 dB | 93.8 Hz | 1,577 Hz | | `hamming` | 4 bins | -43 dB | 93.8 Hz | 1,577 Hz | | `blackman` | 6 bins | -58 dB | 141 Hz | 2,365 Hz | | `blackman-harris` | 8 bins | -92 dB | 188 Hz | 3,153 Hz | | `flattop` | 10 bins | -93 dB | 234 Hz | 3,942 Hz | So "rate over N" is the optimistic answer. With Hann it is off by a factor of four. ## The semitone floor **Music is spaced by RATIO and a spectrogram is spaced by HERTZ.** A semitone at f is `f x 0.059463` hertz — 5.95 Hz at 100 Hz, 59.5 Hz at 1,000 Hz — while the bins stay the same width all the way down. The two cross at exactly one frequency, and that is the lowest note whose semitones the window can separate. With the default 2,048-sample Hann window at 48 kHz, **that floor is 1,577 Hz — above the top of a cello.** Concert A at 440 Hz is nearly two octaves below it. Reading a semitone at the low E of a bass guitar (82.41 Hz, where a semitone is 4.90 Hz) needs **39,181 samples — 816 ms**, which is 816 ms of smear on every event in the take. ## The two things that do not help - **The sample rate.** It is in both halves of the trade and cancels out. At a fixed window *duration* the bins are 23.4 Hz wide at 44.1 kHz, 48, 96 and 192 alike. A higher rate raises the ceiling and adds bins above the audible range. Held at the same N it makes the floor twice as bad, because the window is half as long. - **The hop.** It changes how often the picture is redrawn and nothing about what any one window sees. More frames is the same smear sampled more often. ## What it is A single page at https://spectro-desk.skillsafe.ai. The engine that computes all of this runs entirely in your browser, needs no account and costs nothing. Writing the report calls a model and needs credits. ## The free engine Everything below is computed client-side in `spectro.js` and sent with every run as `prescan`, so the model is never asked to recompute it: - **The grid.** Bin width, window length, their product, the number of bins, the ceiling, the hop in milliseconds, frames a second and the overlap. - **The resolution.** Bin width times the taper's main lobe in bins. - **The semitone floor.** The resolution divided by the semitone ratio. - **Every tone.** The semitone width at its own pitch, whether it is above the ceiling, below the first bin or below the floor, and the window that would be needed to read a semitone there. - **Every adjacent pair.** Their separation in hertz, in semitones and in bins, and whether they are one peak or two. - **Every pair of events.** Their separation against one window length. - **Every demand.** Whether any window at all satisfies both halves, and by what factor it falls short if not. The engine makes no network calls. ## Sheet grammar Four blocks. Blank lines and `#` comments are ignored. ```text ANALYSIS name | the piano and bass take rate | 48000 window | 2048 hop | 512 shape | hann length | 12.5 TONES t1 | 82.41 | the low E of the bass t2 | 87.31 | the F a semitone above it EVENTS e1 | 0.500 | the snare e2 | 0.520 | the hi-hat DEMANDS d1 | 4.9 | 0.020 | read the bass line AND see the hat land separately ``` - A TONES row is `id | hertz | what it is`. - An EVENTS row is `id | seconds | what happens`. - A DEMANDS row is `id | hertz apart | seconds apart | what it is for`, and it is the only block that can be impossible. - `rate` may be written `48000`, `48k` or `48 kHz`. - `window` and `hop` are in **samples**, not milliseconds. - `length` is the material in seconds, and is what makes an event outside it detectable. - Every setting has a default, every default multiplies something, and an assumed one is reported as assumed. ## Lanes | Lane | What it decides | Fields | | --- | --- | --- | | `plan` | The analysis before you render the picture | `brief`, `known` | | `check` | What this window can and cannot show | `sheet`, `symptom` | | `window` | Where the time and frequency trade lands | `sheet`, `priority` | | `pitch` | Which notes this analysis can tell apart | `sheet`, `material` | | `deliver` | What changes: the window, the rate, or the question | `sheet`, `fixed` | `check` is the primary lane. Every lane ships a worked example that costs nothing to read. ## Severity Severity is fixed by the code, not by the model. **Errors are reserved for a picture that cannot answer the question at all** — a demand no window satisfies, a tone that is not in the signal, samples the analysis never looks at, a window longer than the material. A real cost that needs a decision is a warning. A description of the analysis is a note. A semitone floor is not a fault. Every window has one, so it is a note. There are 28 codes. `HOP-EXCEEDS-WINDOW`, `WINDOW-LONGER-THAN-SIGNAL`, `TONE-ABOVE-NYQUIST`, `TONE-BELOW-FIRST-BIN`, `EVENT-OUTSIDE` and `DEMAND-IMPOSSIBLE` are the six errors. ## API ``` POST https://api.skillsafe.ai/v1/app-api/run X-App-Key: Content-Type: application/json {"task": "check", "sheet": "ANALYSIS\nrate | 48000\nwindow | 2048\n...", "symptom": "the bass is one smear"} ``` The run body **is** the input object. There is no `input` wrapper. Every field is a string. Full documentation: https://spectro-desk.skillsafe.ai/api.html ## What this page cannot do - **It has not heard the audio.** Every figure is arithmetic on the settings and on frequencies somebody typed in. - **It does not know what is in the signal.** A tone on a sheet is a claim about the material, not a measurement of it. - **The main-lobe widths are the standard ones**, and a real implementation's taper may differ slightly. They are the right order and not exact. - **Separability is not detectability.** Two tones far enough apart still vanish if one is far louder than the other and the sidelobes are high. - **It says nothing about level, noise or masking.** Only about what can be told apart. ## Source Lanes derived from the `songsee` skill in https://github.com/steipete/clawdis, which renders spectrograms and feature panels from audio. Every spectrogram it draws has made this trade already, whether or not anybody chose it. Not affiliated with or endorsed by that repository's authors.