Transfer vocal tone from a reference recording to a target recording, or remove high-frequency electrical whine from WAV and MP4 audio.
This tool is useful when recordings are technically usable, but do not sound consistent enough for delivery. A typical case is a studio or office video production where one take was recorded with a cleaner mic chain, better placement, or a more controlled room, while another take sounds thinner, duller, harsher, or slightly off because of a different camera mic, lav setup, gain staging, or speaker position.
Instead of rebuilding the sound by hand every time, spectrumtransfer can derive a static tonal correction from a good reference and apply it to the weaker recording. That makes it practical for interview shoots, talking-head videos, podcast video sessions, training content, social snippets, and other post-production workflows where multiple recordings should feel like they came from the same setup.
It also helps in the common case where the voice is basically fine, but the recording contains a narrow high-frequency electrical whine from studio gear, screens, power supplies, lighting, or camera electronics. In that situation you can use the dedicated whine-only mode to clean the noise without changing the rest of the signal more than necessary.
Core idea:
EQ delta = desired_spectrum_dB - target_spectrum_dB
- Spectrum/EQ transfer (
match) from desired WAV to target WAV - Curve-only workflow from Audacity spectrum
.txtfiles (curve) - Apply saved curve to WAV (
apply) - Audio fix workflow (
fix) for whine reduction, auto-level, and optional de-esser without EQ transfer - Whine-only cleanup with upper-band cut plus optional notch filters (
whine) - Optional de-esser
- Optional Voice Clarity presence/air enhancement
- Optional Second Step EQ for additional tested speech clarity shaping
- Optional auto-level + compressor + limiter
- MP4 audio extraction/remux workflows via the master command
- Single user-facing launcher:
spectrumtransfer.command
spectrumtransfer.commandis a macOS launcher (Terminal.commandfile).spectrumtransfer.pyis platform-independent Python and can run on macOS, Linux, and Windows (with dependencies installed).
- Python 3.9+
ffmpegin PATH (for MP4 workflows)- Python packages:
numpy,scipy
Install Python deps:
python3 -m pip install numpy scipyUse only this launcher:
./spectrumtransfer.commandThe launcher validates python3 and requires version >= 3.9 before creating .venv or installing dependencies.
Menu:
Audio Pipeline (file/folder)Fast Pipeline (standard settings, file/folder)MP4 -> WAV (file/folder)Exit
The pipeline asks for a target .wav/.mp4 file or a folder first, then offers these optional steps in order:
- Auto level
- Spectrum Master (
.wav,.csv, or.mp4audio/curve reference;.txtspectrum references remain curve-only) - De-Esser
- Voice Clarity for gentle presence/air enhancement
- Optional Second Step EQ curve based on the tested Audacity Graphic EQ shape
- Peak normalizer to
-6 dBFS - Peak ceiling at
-6 dBFS - Whine reduction
Folder processing is non-recursive and skips generated output files from previous runs.
If a folder batch has failed files, the launcher prints the affected file paths at the end and asks whether only those failed files should be retried.
Batch MP4 processing runs ffmpeg with stdin disabled so ffmpeg cannot consume the internal file list while a folder is being processed.
Each successful Audio Pipeline or Fast Pipeline export also writes a *_settings_<timestamp>.txt file next to the result with the timestamp, source/output paths, selected settings, and command arguments.
Fast Pipeline uses these defaults without asking for every processing choice: auto-level vocal fast, Spectrum Master off, de-esser gentle, Voice Clarity gentle, Second Step EQ off, peak normalizer -6 dBFS, peak ceiling -6 dBFS, and whine reduction gentle.
python3 spectrumtransfer.py match \
--desired-wav desired_reference.wav \
--target-wav vocal_to_fix.wav \
--out-wav vocal_matched.wav \
--curve-csv eq_curve.csv \
--audacity-preset audacity_filter_curve.txtUseful flags:
--whine-high-cut/--whine-notch-hz--de-ess(+--de-ess-*params)--auto-level(+ dynamics params)
python3 spectrumtransfer.py pipeline \
--target-wav vocal_to_fix.wav \
--out-wav vocal_processed.wav \
--auto-level \
--spectrum-reference-wav desired_reference.wav \
--de-ess \
--voice-clarity gentle \
--second-step-eq \
--peak-normalize \
--peak-ceiling \
--whine-high-cutpython3 spectrumtransfer.py curve \
--desired-spectrum desired_spectrum.txt \
--target-spectrum target_spectrum.txt \
--curve-csv eq_curve.csv \
--audacity-preset audacity_filter_curve.txtpython3 spectrumtransfer.py apply \
--curve-csv eq_curve.csv \
--target-wav vocal_to_fix.wav \
--out-wav vocal_matched.wavpython3 spectrumtransfer.py whine \
--target-wav vocal_to_fix.wav \
--out-wav vocal_whine_reduced.wav \
--whine-high-cut \
--whine-high-cut-freq-hz 17400 \
--whine-high-cut-gain-db -30 \
--whine-high-cut-q 1.2 \
--whine-notch-hz 15600 16800 18100python3 spectrumtransfer.py fix \
--target-wav vocal_to_fix.wav \
--out-wav vocal_fixed.wav \
--whine-high-cut \
--whine-notch-hz 15600 16800 18100 \
--auto-level \
--de-ess- This is static spectrum matching (tonal balance), not adaptive dynamic EQ.
- For problematic WAV headers, the process may warn but still continue.
See CHANGELOG.md.