Spectral Mirror — User Guide
A two-character spectral reflection processor: the original phase-crushed legacy texture and a measured-correct frequency-domain mirror, both rendered as a stereo wet field around a mono source.
What this does
Spectral Mirror reflects frequency-domain content around a controllable axis and adds the reflected image to the retained source spectrum. The processor first derives a mono source, builds different left and right mirror geometries, then returns a stereo result.
The script intentionally offers two different engines. legacy texture preserves the original phase-crushed, chunk-breathing behaviour because that sound became part of the instrument's identity. clean mirror implements the intended frequency reflection in measured frequency coordinates and uses 50% Hann overlap-add normalization.
What is spectral mirroring?
For the clean engine, a source frequency f is reflected around an axis using:
Reflection therefore works like a geometric mirror on the frequency axis. If the axis is 6.8 kHz, 6.0 kHz reflects to 7.6 kHz and 10.0 kHz reflects to 3.6 kHz. The script keeps the identity component and adds the reflected image only where its destination lies below the channel's cutoff.
Quick start
- Select exactly one Sound.
- Run
Basic_Mirror.praat. - Choose a preset and a Character.
- Set Dry_wet_mix and Stereo_spread.
- Use Edit_details only when you need a custom divisor, stereo reflection offset or output peak.
- Run the script and compare the visualization with what you hear.
Presets
The preset changes the base cutoff divisor. Stereo spread is applied afterwards, so the final left and right receiving cutoffs can differ from the nominal base value.
| Preset | Base cutoff before stereo spread |
|---|---|
| Mild | Nyquist / 4 |
| Moderate | Nyquist / 2 |
| Strong | Nyquist / 8 |
| Extreme | Nyquist / 16 |
| Custom | Nyquist / Custom cutoff divisor; divisor must be greater than 1 |
Two characters
| Character | What it does | Level / overlap behaviour |
|---|---|---|
| legacy texture | Preserves the original implementation: numeric frequency controls are used as FFT-bin indices, the real spectrum row is duplicated into both rows, and the nearly non-overlapping Hann chunks create the characteristic phase-crushed breathing texture. | Hop = chunk duration − 20 ms. Wet L/R are peak-scaled independently to 0.95 before mixing. |
| clean mirror | Reads from a frozen complex spectrum, reflects by measured bin width, realigns partial-frame mirror images and retains the untouched identity component. | 50% Hann hop with overlap-sum normalization. Wet L/R use one joint scale to 0.95, preserving their relative balance. |
Controls
| Control | Default | Meaning |
|---|---|---|
| Preset | Moderate | Sets the base receiving-band cutoff. |
| Character | legacy texture | Selects the original or corrected spectral engine. |
| Dry_wet_mix | 0.7 | Linear wet proportion, 0…1. |
| Stereo_spread | 0.25 | Moves left/right receiving cutoffs apart. Valid range 0…0.9. |
| Edit_details | Off | Opens the secondary controls. |
| Custom cutoff divisor | 2 | Used only by Custom; must be >1. |
| Stereo reflection-sum offset | 0.15 | Separates the L/R reflection axes; valid range 0…0.9. |
| Output peak | 0.9 | Final target peak for the complete stereo mix. |
| Draw_visualization | On | Draws the process-oriented four-panel figure. |
| Play_result | On | Plays the final Sound. |
Processing pipeline
- Convert the selected source to mono.
- Keep a full-rate dry copy.
- Process the wet path at min(source sample rate, 32 kHz).
- Split the signal into 32,768-sample Hann chunks.
- Transform each chunk to the spectrum, apply the selected mirror character independently for L/R geometry, and transform back to sound.
- Overlap-add the chunks using the character-specific normalization.
- Resample the wet channels back to the original sample rate when required.
- Scale the wet field, mix the same mono dry source into L/R, combine to stereo, then target-normalize the final output.
Channels, bandwidth and level
- Input: any channel count accepted, but all multichannel input is converted to mono for processing.
- Output: always stereo.
- Duration: preserved.
- Sample rate: restored to the original rate.
- Wet bandwidth: when the source rate exceeds 32 kHz, the wet path is processed at 32 kHz and therefore carries no content above 16 kHz. The dry path remains full-rate.
- Final level: every non-silent result is target-normalized to
Output peak. Consequently, Dry_wet_mix = 0 is not an amplitude-identical bypass; it produces dual-mono dry content inside a stereo file and then applies final peak scaling.
Output name: <source>_mirror_<preset>.
Visualization
- A — Chunk geometry: three Hann frames and their overlap sum, making the clean COLA behaviour versus legacy breathing directly visible.
- B — Frequency reflection map: one shared frequency axis, receiving bands, reflection axes and example source→destination folds.
- C — Measured spectrum: dry source against the pure wet L/R spectra, including measured strongest-component locations.
- D — Final output: measured left/right waveforms on one amplitude scale.
Compositional context
Spectral mirroring treats the frequency distribution itself as compositional material. Rather than transposing a melody or shifting every partial by one ratio, the processor reorganizes spectral locations around a fixed axis. This can turn harmonic material into inharmonic structures, move low components upward while sending high components downward, and create time-reversed spectral pre-images on attacks.
The two-character design is also part of the instrument's compositional identity: the legacy engine preserves a historically accidental but musically distinctive phase/chunk texture, while the clean engine exposes the intended reflection law. They should therefore be heard as two related instruments, not as "wrong" and "right" versions of the same sound.