Simulate double-tracked electric guitar for stereo L+R panning — no second take needed.
Double tracking is the studio technique of recording the same part twice and panning each take to opposite sides of the stereo field. The slight natural differences between the two takes create a wide, thick guitar sound.
waver simulates that second take from a single recording using three perceptually important tools:
| Technique | Default | Why it works |
|---|---|---|
| Base timing offset | 22 ms | Simulates the tiny human timing difference between takes |
| Random-walk drift | ±1.8 ms RMS | Organic drift — avoids the "chorus" artefact of periodic LFO |
| Micro pitch shift | +8 cents | Simulates slightly different intonation on each take |
| Level mismatch | −1.5 dB | Real second takes are never exactly the same volume |
| High-shelf EQ tilt | −2.5 dB @ 4 kHz | Simulates slightly different mic placement / amp tone |
The original take → left channel. The processed simulation → right channel.
- Python ≥ 3.10
librosa,soundfile,numpy,scipy
pip install -r requirements.txtpython waver.py input.wav output_stereo.wavFull options:
usage: waver [-h] [--delay-ms MS] [--drift-ms MS] [--pitch-cents CENTS]
[--level-db DB] [--no-eq] [--eq-gain-db DB] [--eq-freq-hz HZ]
[--swap] [--seed N] [--headroom-db DB] [--subtype FMT]
input output
positional arguments:
input Input audio file (WAV, FLAC, AIFF, …)
output Output stereo WAV file
Double-tracking parameters:
--delay-ms MS Base timing offset of the simulated take (ms) [22.0]
--drift-ms MS RMS depth of slow random timing drift (ms) [1.8]
--pitch-cents CENTS Pitch offset in cents (positive = slightly sharp) [8.0]
--level-db DB Level offset of the simulated take (dB) [-1.5]
--no-eq Disable high-shelf EQ tilt on the simulated take
--eq-gain-db DB High-shelf gain (dB, negative = cut) [-2.5]
--eq-freq-hz HZ High-shelf frequency (Hz) [4000.0]
--swap Swap L/R channels
--seed N Random seed for timing drift — change for variety [42]
--headroom-db DB Output peak level after normalisation (dB) [-0.3]
--subtype FMT WAV bit-depth: PCM_16, PCM_24, PCM_32, FLOAT [PCM_24]
Record dry. A clean DI (direct input) or lightly processed signal gives waver the best material to work with. Heavy reverb and delay on the input can smear the simulated take.
Try different seeds. --seed 7 gives a completely different timing drift curve. Audition a few and pick the one that sits best in the mix.
Dial in the pitch. For tighter, more controlled parts (palm mutes, single-note riffs) try --pitch-cents 5. For chords and bigger sounds try --pitch-cents 12.
Mono compatibility. The Haas-effect delay means the stereo mix will comb-filter somewhat when summed to mono. Keep --delay-ms ≤ 30 ms to stay in the safe zone.
Lower the delay for tighter sounds. --delay-ms 12 creates a tighter, more aggressive double-track. --delay-ms 30 feels more like two separate mic positions.
waver/
├── waver.py # CLI entry point
├── requirements.txt
└── core/
├── loader.py # Audio I/O (preserves native sample rate)
├── processor.py # DSP: pitch shift, variable delay, EQ tilt
└── exporter.py # Stereo assembly, shared normalisation, WAV export