Phantom Bass Enhancer + Haas Stereo Widener — User Guide

Psychoacoustic bass enhancement through harmonic generation combined with spatial widening using Haas effect and mid-side processing.

Type: Psychoacoustic Audio Enhancement Methods: Waveshaping + Haas + M/S Processing Input: Mono or Stereo Sound Mono Compatibility: Optional safety mode
Contents:

What this does

This script implements psychoacoustic bass enhancement combined with stereo spatial widening. It creates the perception of deep bass on systems with limited low-frequency response (small speakers, headphones) by generating harmonic overtones that trick the ear into "hearing" missing fundamentals. Simultaneously, it applies stereo enhancement using both the Haas (precedence) effect and mid-side processing to create a wider, more immersive soundstage.

Key Features:

Psychoacoustic Bass Enhancement: The human auditory system has a phenomenon called "the missing fundamental" where if harmonics of a fundamental frequency are present, we perceive the fundamental even if it's physically absent. This script:
  1. Extracts bass frequencies (30-120 Hz typical)
  2. Generates harmonics via waveshaping distortion (tanh function)
  3. Filters original audio to remove deep bass
  4. Mixes harmonics back in, creating perception of strong bass

Result: Audio appears to have more powerful bass without actually boosting low frequencies that small speakers can't reproduce.

Technical Implementation: (1) Stereo preparation: Converts mono to stereo if needed. (2) Bass extraction: Bandpass filters each channel for low frequencies. (3) Harmonic generation: Applies tanh(x·drive) waveshaping to create harmonics, then bandpass filters to desired brightness range. (4) Original filtering: High-passes original to remove conflicting bass. (5) Mixing: Combines filtered original with harmonics at controlled mix level. (6) Haas effect: Delays one channel slightly (±15ms typical). (7) Mid-side widening: Extracts mid/side components, boosts side signal. (8) Safety features: Multiple peak detection passes, mono compatibility controls. (9) Preset system: 6 carefully tuned starting points.

Quick start

  1. In Praat, select exactly one Sound object (mono or stereo).
  2. Run script…phantom_bass_haas_widener.praat.
  3. Choose preset (6 options):
    • Custom (use manual settings)
    • Subtle Enhancement (gentle)
    • Moderate Effect (balanced)
    • Aggressive MaxxBass Style (strong)
    • Mono-Safe Widening (broadcast safe)
    • Wide Stereo (not mono-safe)
  4. Adjust Phantom Bass parameters if using Custom preset:
    • bass_low_freq, bass_high_freq: Bass extraction range
    • drive: Harmonic generation intensity (0.1-10)
    • harmonic_mix: Dry/wet blend (0-1)
    • highpass_freq: Original bass removal cutoff
    • harmonic_lowpass: Harmonic brightness control
  5. Set Haas Effect options (enable/disable, delay, mix, level difference).
  6. Set Mid-Side Widening options (enable/disable, stereo width).
  7. Enable preserve_mono_compatibility for broadcast/safe use.
  8. Enable play_result to auto-play output.
  9. Click OK — processing applied, output named "originalname_phantom_haas".
Quick tip: Start with Moderate Effect preset to hear balanced enhancement. For headphones/small speakers: Try Aggressive MaxxBass Style. For broadcast/streaming: Use Mono-Safe Widening. Always test in mono (collapse to mono in your DAW or sum L+R) to check for phase cancellation. The script includes multiple peak protection passes, but extreme settings can still cause clipping — listen for distortion. For speech/content: Use Subtle Enhancement or disable bass enhancement entirely (set harmonic_mix=0). The Haas effect works best at 10-30ms delays — longer delays create distinct echoes.
Critical: Always test in mono! The Haas effect and mid-side widening can cause severe phase cancellation when collapsed to mono. Enable preserve_mono_compatibility for broadcast, streaming, or club systems. Without this protection, your audio may disappear or become thin in mono playback. The script warns but cannot prevent all issues — your ears are the final test. Haas delays >25ms become audible as distinct echoes. High drive values (>5) create strong distortion — use judiciously. Removing too much original bass (highpass_freq >150 Hz) can make audio sound thin — balance with harmonic mix.

Psychoacoustic Theory

The Missing Fundamental Phenomenon

👂 How We "Hear" Phantom Bass

Scientific basis: When a complex tone contains harmonics at frequencies f, 2f, 3f, 4f... the auditory system often perceives a fundamental frequency f even if it's physically absent.

Example: Small speaker playing 100 Hz tone
Physical limitation: Speaker can't reproduce 100 Hz effectively
Perceptual trick: Generate harmonics at 200 Hz, 300 Hz, 400 Hz...
Brain interprets: "There must be a 100 Hz fundamental"
Result: Perception of deep bass without actual low frequencies

Practical application: Extract bass frequencies (30-120 Hz) → Generate harmonics (120-800 Hz) → Remove original bass → Brain fills in the "missing" low end.

Waveshaping function: tanh(drive × x) Where: x = extracted bass signal (normalized) drive = distortion amount (higher = more harmonics) tanh = hyperbolic tangent (soft clipping) Harmonic series generated: For fundamental f, tanh distortion creates: f, 2f, 3f, 4f, 5f... (odd and even harmonics) Advantages over simple distortion: - Soft clipping (no harsh edges) - Natural harmonic decay - Controllable via drive parameter

Haas (Precedence) Effect

🎧 Creating Spatial Width with Time Differences

Discovery: Helmut Haas (1949) found that when two identical sounds arrive within 1-30ms of each other, we perceive a single sound located at the first arriving source.

Haas implementation: L(t) = original_left(t) R(t) = (1 - mix) × original_right(t) + mix × original_right(t - Δt) Where: Δt = delay time (10-30ms typical) mix = wet/dry balance (0-1) Perceptual effects: Δt < 10ms: Image widens without localization shift Δt = 10-30ms: Clear spatial separation Δt > 40ms: Distinct echo perceived

Mono compatibility issue: When L and R are summed to mono:

Mono sum = L(t) + R(t) = original_left(t) + (1-mix)×original_right(t) + mix×original_right(t-Δt) If original_left ≈ original_right (stereo pair): Comb filtering occurs due to time difference Frequency-dependent cancellation Can cause "phasiness" or complete cancellation

Mid-Side Processing

🎚️ Stereo Width Control

Concept: Any stereo signal can be represented as Mid (mono-compatible) and Side (stereo-difference) components:

Encoding: M = (L + R) / 2 (Mid = center/mono content) S = (L - R) / 2 (Side = stereo difference) Decoding: L = M + S R = M - S Width control: L' = M + S × width R' = M - S × width Where width = 0.5-1.5: width < 1.0: Narrower than original width = 1.0: Same as original width > 1.0: Wider than original

Mono compatibility: When collapsed to mono:

Mono = (L' + R') / 2 = (M+S×width + M-S×width) / 2 = (2M) / 2 = M Perfect mono compatibility: Side signal completely cancels But: If S contains low frequencies with phase issues → partial cancellation Solution: High-pass side signal (200Hz cutoff in safety mode)

Phantom Bass Enhancement

Stage 1: Bass Extraction

🔊 Isolating Low Frequencies

Bandpass filtering: Extract only the frequency range that will generate harmonics

ParameterTypical RangeEffectRecommendation
bass_low_freq20-60 HzLowest frequency extracted30 Hz for most music, 40 Hz for speech
bass_high_freq80-150 HzHighest frequency extracted120 Hz balances harmonic generation
Process per channel: bass_L = Filter (pass Hann band): bass_low_freq, bass_high_freq, 100 bass_R = Filter (pass Hann band): bass_low_freq, bass_high_freq, 100 Filter characteristics: Hann window: Smooth frequency response Bandwidth: 100 Hz transition bands Purpose: Clean extraction without excessive ringing

Design rationale: Extract only frequencies that benefit from harmonic generation. Too low (<30Hz) may not generate audible harmonics. Too high (>150Hz) may conflict with existing midrange.

Stage 2: Harmonic Generation via Waveshaping

Harmonic generation formula: harmonics = tanh(drive × bass_signal) Where: tanh(x) = (e^x - e^{-x}) / (e^x + e^{-x}) (hyperbolic tangent) drive = intensity control (0.1-10) Mathematical properties: tanh(x) ≈ x for small x (low drive = minimal distortion) tanh(x) → ±1 as x → ±∞ (soft clipping) Generates both odd and even harmonics Frequency domain effect: Input: pure sine at frequency f Output: f + 2f + 3f + 4f + ... (harmonic series) Amplitude decreases with harmonic number

Stage 3: Harmonic Filtering

Controlling harmonic brightness: Raw waveshaping generates harmonics far beyond the audible range. A lowpass filter controls how "bright" or "warm" the harmonics sound.
ParameterTypical RangeSonic Character
harmonic_lowpass = 400 Hz400-600 HzWarm, subtle harmonics
harmonic_lowpass = 800 Hz700-900 HzBalanced, natural
harmonic_lowpass = 1200 Hz1000-1500 HzBright, pronounced
harmonic_lowpass = 2000 Hz1500-2500 HzAggressive, distorted

Filter implementation:

harmonics_filtered = Filter (pass Hann band): bass_high_freq, harmonic_lowpass, 100 Why bandpass, not just lowpass? - Removes any residual fundamental below bass_high_freq - Clean transition from original to harmonics - Prevents low-frequency "mud"

Stage 4: Original High-Pass Filtering

Critical step: Remove conflicting bass frequencies from original signal
  • Purpose: Prevent original bass from masking generated harmonics
  • Without this: Bass becomes boomy/muddy, harmonics less effective
  • Parameter: highpass_freq typically 80-120 Hz
  • Rule: Should be near or slightly below bass_high_freq
original_highpassed = Filter (stop Hann band): 0, highpass_freq, 100 Filter type: High-pass (stop band 0 to highpass_freq) Transition: 100 Hz Hann window (smooth rolloff) Result: Original with bass removed, mids/highs intact

Common mistake: Setting highpass_freq too high (>150Hz) removes too much body from audio, making it sound thin.

Stage 5: Harmonic Mixing

Final mix per channel: result = original_highpassed + harmonics_filtered × harmonic_mix Where: harmonic_mix = 0.0-1.0 (dry/wet balance) Typical values: 0.0-0.3: Very subtle enhancement 0.4-0.6: Balanced, natural effect (default) 0.7-0.9: Strong, obvious enhancement 1.0: Full wet (rarely used) Perceptual effect: Low mix: Bass feels "fuller" but not distorted High mix: Obvious harmonic enhancement, "MaxxBass" style

Parameter Interactions

Parameter synergy examples:

Warm, subtle bass: bass_low_freq=40, bass_high_freq=100 drive=2.0, harmonic_mix=0.4 highpass_freq=90, harmonic_lowpass=500 Result: Gentle fullness

Aggressive modern bass: bass_low_freq=30, bass_high_freq=120 drive=5.0, harmonic_mix=0.8 highpass_freq=120, harmonic_lowpass=1000 Result: Pronounced "hyperreal" bass

Speech/clarity focused: bass_low_freq=60, bass_high_freq=150 drive=1.5, harmonic_mix=0.3 highpass_freq=120, harmonic_lowpass=400 Result: Vocal presence without boominess

Haas Effect Implementation

Basic Haas Algorithm

⏱️ Channel Delay Technique

Standard implementation: Delay one channel slightly relative to the other

Right channel processing (typical): delayed_right[n] = right[n - D] × level_factor Where: D = delay_samples = round(haas_delay_ms / 1000 × sampleRate) level_factor = 10^(level_difference_db / 20) Mix with original: right_result = (1 - haas_mix) × right + haas_mix × delayed_right left_result = left (unchanged)

Why usually delay right channel? Convention, not requirement. Can swap L/R for different spatial effects.

Haas Parameters

ParameterRangeEffectMono-Safe Limits
haas_delay_ms1-50 msDelay time; longer = wider but risk echo≤12 ms
haas_mix0.0-1.0Wet/dry balance; higher = stronger effect≤0.25
level_difference_db-6 to +6 dBDelayed channel level relative to original-3 to 0 dB

Mono Compatibility Issues

⚠️ Phase Cancellation Problem

What happens in mono? Left and right channels sum:

Mono_sum = left + [(1-mix)×right + mix×right_delayed] = left + right + mix×(right_delayed - right) If left ≈ right (typical stereo material): Mono_sum ≈ 2×right + mix×(right_delayed - right) Frequency cancellation: For frequency f with period T: right_delayed(t) = right(t - Δt) Difference creates comb filtering with notches at: f = k / Δt (k = 1, 2, 3...) Example: Δt = 15ms → notches at 67Hz, 133Hz, 200Hz...

Safety mode implementation:

if preserve_mono_compatibility = 1: haas_delay_actual = min(haas_delay_ms, 12) haas_mix_actual = min(haas_mix, 0.25) Rationale: - Shorter delays (<12ms) push cancellation notches higher - Lower mix (<25%) reduces cancellation depth - Combined: Minimizes audible phasing in mono

Practical Haas Guidelines

Recommended settings by application:
  • Headphones only: 15-30ms delay, 0.4-0.7 mix
  • Stereo speakers: 10-20ms delay, 0.3-0.5 mix
  • Broadcast/streaming: 5-12ms delay, 0.1-0.25 mix (with safety mode)
  • Club/PA systems: Avoid or use ≤5ms with safety mode
  • Music production: 10-20ms delay, automate mix for effect

When to avoid Haas:

  • Material that will definitely be played in mono
  • Vocals or center-panned elements (can cause "phasiness")
  • Already wide stereo mixes (can become exaggerated)
  • Material with strong transients (can blur timing)

Mid-Side Widening

M/S Encoding/Decoding

🎛️ Stereo Representation

Mid (M) and Side (S) components:

Encoding (L,R → M,S): M = (L + R) / 2 S = (L - R) / 2 Decoding (M,S → L,R): L = M + S R = M - S Properties: - M contains all mono-compatible information - S contains all stereo difference information - In mono: L+R = 2M (S cancels completely)

Width control: Amplify or attenuate the side component:

Width adjustment: L' = M + S × width R' = M - S × width Where: width = 0.0: mono (S completely removed) width = 0.5: narrower than original width = 1.0: original width width = 1.5: 50% wider width = 2.0: stereo extremes

Implementation Details

Script implementation: # Calculate mid mid = (left_mixed + right_mixed) / 2 # Calculate side with width control side = (left_mixed - right_mixed) / 2 × stereo_width # Mono safety: high-pass side signal if preserve_mono_compatibility = 1: side_filtered = Filter (stop Hann band): 0, 200, 100 # Removes low-frequency phase issues # Reconstruct left_result = mid + side_filtered right_result = mid - side_filtered

Why High-Pass the Side Signal?

Low-frequency phase issues: In real-world recordings, low frequencies (<200Hz) often have random phase relationships between channels due to:
  • Room acoustics (standing waves, reflections)
  • Microphone placement differences
  • Bass management in mixing
  • Proximity effect variations

Problem: These random phase differences create unpredictable cancellation when:

Mono_sum = L' + R' = 2M + (S - S) = 2M (theoretically) But with phase differences at low frequencies: S_low ≠ (L_low - R_low)/2 in phase-coherent way Result: Partial cancellation, thin bass in mono

Solution: High-pass side signal at 200Hz removes problematic low-frequency phase issues while preserving stereo width at mid/high frequencies where phase coherence is better.

Width Parameter Guidelines

stereo_widthPerceived EffectRecommended UseMono Safety
0.0-0.3Narrower than originalFocusing center, reducing widthSafe
0.4-0.6Moderate wideningGeneral enhancement, most musicSafe with HPF
0.7-0.9Significant wideningElectronic music, creative effectsRisky, test in mono
1.0-1.3Extreme wideningSpecial effects, sound designNot safe
1.4+Hyper-wide, possibly invertedExperimental onlyDefinitely not safe

Parameters & Presets

Preset System

Preset 1: Custom
Manual parameter control only

Preset 2: Subtle Enhancement
drive=2.0, harmonic_mix=0.4, highpass_freq=90, harmonic_lowpass=600
haas: 10ms delay, 30% mix
MS width: 0.3, mono-safe: ON
Use: Gentle enhancement for natural material

Preset 3: Moderate Effect (Default)
drive=3.0, harmonic_mix=0.6, highpass_freq=100, harmonic_lowpass=800
haas: 15ms delay, 50% mix
MS width: 0.5, mono-safe: ON
Use: Balanced enhancement for most music

Preset 4: Aggressive MaxxBass Style
drive=5.0, harmonic_mix=0.8, highpass_freq=120, harmonic_lowpass=1000
haas: 20ms delay, 60% mix
MS width: 0.7, mono-safe: OFF
Use: Strong effect for EDM, hip-hop, headphones

Preset 5: Mono-Safe Widening
drive=2.5, harmonic_mix=0.5, highpass_freq=100, harmonic_lowpass=700
haas: 8ms delay, 20% mix
MS width: 0.4, mono-safe: ON
Use: Broadcast, streaming, club systems

Preset 6: Wide Stereo (not mono-safe)
drive=3.5, harmonic_mix=0.65, highpass_freq=100, harmonic_lowpass=900
haas: 25ms delay, 70% mix
MS width: 0.8, mono-safe: OFF
Use: Headphones, stereo-only playback, immersive effects

Phantom Bass Parameters

ParameterTypeDefaultRangeDescription
bass_low_freqpositive3020-100 HzLowest frequency for harmonic generation
bass_high_freqpositive12060-200 HzHighest frequency for harmonic generation
drivepositive3.00.1-10.0Harmonic generation intensity
harmonic_mixreal0.60.0-1.0Dry/wet mix of harmonics
highpass_freqpositive10050-200 HzOriginal bass removal cutoff
harmonic_lowpasspositive800400-2000 HzHarmonic brightness control

Haas Effect Parameters

ParameterTypeDefaultRangeDescription
apply_haasboolean10/1Enable/disable Haas effect
haas_delay_mspositive151-50 msDelay time for one channel
haas_mixreal0.50.0-1.0Wet/dry balance for Haas
level_difference_dbreal-3-6 to +6 dBDelayed channel level relative to original

Mid-Side Parameters

ParameterTypeDefaultRangeDescription
apply_ms_wideningboolean10/1Enable/disable M/S widening
stereo_widthreal0.50.0-2.0Stereo width multiplier

Safety Parameters

ParameterTypeDefaultDescription
preserve_mono_compatibilityboolean1Enable safety features for mono playback
play_resultboolean1Auto-play processed sound

Processing Stages

Complete Processing Pipeline

1. INPUT PREPARATION Store original sound Convert mono to stereo if needed Extract left/right channels 2. PHANTOM BASS PROCESSING (per channel) Bass extraction: bandpass(bass_low_freq, bass_high_freq) Harmonic generation: tanh(drive × bass) Harmonic filtering: bandpass(bass_high_freq, harmonic_lowpass) Original high-pass: highpass(highpass_freq) Mix: original_highpassed + harmonics × harmonic_mix 3. PEAK SAFETY PASS 1 Check max peak after harmonic mix Scale if >0.95 to prevent clipping 4. HAAS EFFECT (if enabled) Create delayed version of right channel Mix: right_result = (1-mix)×right + mix×right_delayed Apply mono safety limits if preserve_mono_compatibility=1 5. PEAK SAFETY PASS 2 Check max peak after Haas Scale if >0.95 6. MID-SIDE WIDENING (if enabled) Calculate: mid = (L+R)/2, side = (L-R)/2 × width If mono-safe: high-pass side at 200Hz Reconstruct: L' = mid + side, R' = mid - side 7. PEAK SAFETY PASS 3 Check max peak after M/S Scale if >0.95 8. FINAL ASSEMBLY Combine L'/R' to stereo sound Scale peak to 0.99 Rename: originalname_phantom_haas Play if requested Print processing summary

Peak Protection System

Three-stage peak monitoring: The script checks and normalizes peaks at three critical points:
  1. After harmonic mixing: Harmonic addition can increase peaks
  2. After Haas processing: Delay-and-mix can create constructive interference
  3. After M/S widening: Side signal boosting can increase levels

Algorithm:

For each safety pass: max_left = Get maximum of left channel min_left = Get minimum of left channel max_right = Get maximum of right channel min_right = Get minimum of right channel max_peak = max(abs(max_left), abs(min_left), abs(max_right), abs(min_right)) if max_peak > 0.95: scale_factor = 0.95 / max_peak left = left × scale_factor right = right × scale_factor

Final normalization: After all processing, scale peak to 0.99 (leaves 0.01 headroom for downstream processing).

Practical Applications

🎧 Headphone Listening Enhancement

Goal: Create immersive, bass-rich experience for headphones

Preset: Aggressive MaxxBass Style or Wide Stereo

Rationale: Headphones have no room acoustics/crossfeed, benefit from strong spatial enhancement and bass harmonics.

📻 Podcast/Voice Enhancement

Goal: Warm, present voice without boominess

Settings:

  • bass_low_freq=80, bass_high_freq=200 (voice fundamentals)
  • drive=1.5, harmonic_mix=0.3 (subtle)
  • Haas: 5ms delay, 15% mix (minimal)
  • MS width: 0.2 (slight widening)
  • mono-safe: ON (broadcast essential)

🎵 Music Mastering for Streaming

Goal: Consistent impact across all playback systems

Preset: Mono-Safe Widening (modified)

Additional steps: Always A/B with reference tracks, test on phone speakers, car systems, and collapsed to mono.

Troubleshooting

Problem: Thin/weak bass in mono
Cause: Phase cancellation from Haas or M/S processing
Solution: Enable preserve_mono_compatibility, reduce Haas delay/mix, test in mono
Problem: Distorted/unpleasant harmonics
Cause: Drive too high, harmonic_lowpass too high
Solution: Reduce drive to 2.0-3.0, lower harmonic_lowpass to 600-800Hz
Problem: Echo/comb filtering artifacts
Cause: Haas delay too long (>30ms)
Solution: Reduce haas_delay_ms to 10-20ms, lower haas_mix
Problem: Audio sounds "hollow" or phasey
Cause: Too much side signal, especially at low frequencies
Solution: Reduce stereo_width to 0.3-0.5, ensure mono-safe mode enabled
Problem: Clipping despite peak protection
Cause: Extreme settings, inter-sample peaks
Solution: Reduce all levels, use more conservative settings, add external limiter

Best Practices

Workflow recommendations:
  1. Start with presets: Use Moderate Effect as baseline
  2. A/B constantly: Compare processed vs original
  3. Test in mono: Collapse to mono after processing
  4. Test on different systems: Headphones, laptop speakers, car
  5. Use reference material: Compare with professionally processed tracks
  6. Less is more: Subtle enhancement often works better than extreme
  7. Consider downstream processing: Leave headroom for further mastering
When to use (and when to avoid):

Good candidates:

  • Mixes lacking low-end impact
  • Material for headphone listening
  • Audio for small speaker playback
  • Stereo enhancement for narrow mixes
  • Broadcast audio needing consistent bass

Avoid or use cautiously:

  • Already bass-heavy material (can become muddy)
  • Acoustic recordings needing naturalness
  • Material with strong stereo effects already
  • Audio destined primarily for mono playback
  • Mastering for vinyl (phase issues critical)