Files
valhallir-deconvolver/README.md
Bastian Bührig 1954312833 Add automatic phase correction with cross-correlation detection and manual override
- Implement cross-correlation-based phase inversion detection
- Add --force-invert-phase flag for manual override and testing
- Add --no-phase-correction flag to disable automatic detection
- Update README with comprehensive documentation
- Improve phase detection sensitivity and add detailed logging
- Ensure consistent IR polarity for easier mixing of multiple IRs
2025-07-11 16:10:01 +02:00

14 KiB

Valhallir Deconvolver

A CLI tool for processing WAV files to generate impulse responses (IR) from sweep and recorded WAV files, designed for guitar speaker IR creation.

Features

  • Fast FFT-based deconvolution for accurate IR extraction
  • Automatic input conversion: Accepts any WAV sample rate, bit depth, or channel count
  • Optional output IR length: Specify output IR length in milliseconds with --length-ms
  • Optional low-cut and high-cut filtering: Apply Butterworth filters to the recorded sweep before IR extraction (--lowcut, --highcut, --cut-slope)
  • Automatic fade-out: Linear fade-out at the end of the IR to avoid clicks (default 5 ms, configurable with --fade-ms)
  • IR Visualization: Generate frequency response and waveform plots with --plot-ir
  • Automatic Phase Correction: Detects and corrects phase-inverted recorded sweeps for consistent IR polarity
  • Manual Phase Inversion: Use --force-invert-phase to explicitly invert the recorded sweep for testing or manual override
  • 96kHz 24-bit WAV file support for high-quality audio processing
  • Multiple output formats with configurable sample rates and bit depths
  • Minimum Phase Transform (MPT) option for reduced latency IRs
  • Automatic silence trimming and normalization
  • Modular design with separate packages for WAV I/O, convolution, and visualization
  • Robust error handling and validation

Installation

# Clone the repository
git clone <repository-url>
cd valhallir-convoluter

# Build the application
go build -o valhallir-deconvolver

Usage

Basic IR Generation

Generate a standard impulse response from sweep and recorded files (any WAV format):

./valhallir-deconvolver --sweep sweep.wav --recorded recorded.wav --output ir.wav

With Minimum Phase Transform

Generate both regular and minimum phase IRs:

./valhallir-deconvolver --sweep sweep.wav --recorded recorded.wav --output ir.wav --mpt

This creates:

  • ir.wav - Standard impulse response
  • ir_mpt.wav - Minimum phase transform version

Limit Output IR Length

Trim or zero-pad the output IR to a specific length (in milliseconds):

./valhallir-deconvolver --sweep sweep.wav --recorded recorded.wav --output ir.wav --length-ms 100

This will ensure the output IR is exactly 100 ms long (trimming or zero-padding as needed).

Fade-Out to Avoid Clicks

By default, a 5 ms linear fade-out is applied to the end of the IR to avoid clicks. You can change the fade duration:

./valhallir-deconvolver --sweep sweep.wav --recorded recorded.wav --output ir.wav --fade-ms 10

This applies a 10 ms fade-out at the end of the IR.

Filtering the Recorded Sweep

You can apply a low-cut (high-pass) and/or high-cut (low-pass) filter to the recorded sweep before IR extraction. This is useful for removing rumble, DC, or high-frequency noise:

./valhallir-deconvolver --sweep sweep.wav --recorded recorded.wav --output ir.wav --lowcut 40 --highcut 18000

This applies a 40 Hz low-cut (high-pass) and 18 kHz high-cut (low-pass) filter to the recorded sweep.

You can control the filter steepness (slope) with --cut-slope (in dB/octave, default 12). For example:

./valhallir-deconvolver --sweep sweep.wav --recorded recorded.wav --output ir.wav --lowcut 40 --highcut 18000 --cut-slope 24

This applies a 40 Hz low-cut and 18 kHz high-cut, both with a 24 dB/octave slope (steeper than the default 12).

Automatic Phase Correction

Valhallir Deconvolver automatically detects and corrects phase-inverted recorded sweeps to ensure consistent IR polarity. This is especially important when mixing multiple IRs later.

By default, the tool:

  • Detects phase inversion by analyzing the correlation between sweep and recorded signals
  • Automatically corrects phase-inverted recorded sweeps
  • Ensures consistent polarity across all generated IRs

If you know your recorded sweep has the correct phase, you can disable automatic correction:

./valhallir-deconvolver --sweep sweep.wav --recorded recorded.wav --output ir.wav --no-phase-correction

Forcing Phase Inversion (Testing/Manual Override)

You can force the recorded sweep to be inverted (regardless of automatic detection) using:

./valhallir-deconvolver --sweep sweep.wav --recorded recorded.wav --output ir.wav --force-invert-phase

This is useful for testing or if you know your recorded sweep is out of phase and want to override the automatic detection.

IR Visualization

Generate frequency response and waveform plots of your IRs:

./valhallir-deconvolver --sweep sweep.wav --recorded recorded.wav --output ir.wav --plot-ir

This creates:

  • ir.wav - The impulse response file
  • ir.png - A professional plot showing frequency response and waveform

The plot includes:

  • Frequency Response: dB vs Hz with log frequency scale (20Hz-20kHz)
  • Waveform: Time-domain view of the first 10ms of the IR
  • Valhallir Branding: Logo and filename information
  • Professional Layout: Clean, publication-ready visualization

Different Output Formats

Generate IRs in different sample rates and bit depths:

# 44kHz 16-bit (CD quality)
./valhallir-deconvolver \
  --sweep sweep.wav \
  --recorded recorded.wav \
  --output ir_cd.wav \
  --sample-rate 44100 \
  --bit-depth 16

# 48kHz 32-bit (studio quality)
./valhallir-deconvolver \
  --sweep sweep.wav \
  --recorded recorded.wav \
  --output ir_studio.wav \
  --sample-rate 48000 \
  --bit-depth 32 \
  --mpt

# 96kHz 24-bit (high resolution)
./valhallir-deconvolver \
  --sweep sweep.wav \
  --recorded recorded.wav \
  --output ir_hires.wav \
  --sample-rate 96000 \
  --bit-depth 24

Advanced Options

./valhallir-deconvolver \
  --sweep sweep.wav \
  --recorded recorded.wav \
  --output ir.wav \
  --mpt \
  --sample-rate 48000 \
  --bit-depth 24 \
  --normalize 0.95 \
  --trim-threshold 0.001 \
  --length-ms 50

Command Line Options

Flag Description Default Required
--sweep Path to sweep WAV file (any format) - Yes
--recorded Path to recorded WAV file (any format) - Yes
--output Path to output IR WAV file - Yes
--mpt Generate minimum phase transform IR false No
--sample-rate Output sample rate (44, 48, 88, 96 kHz) 96000 No
--bit-depth Output bit depth (16, 24, 32 bit) 24 No
--normalize Normalize output to peak value (0.0-1.0) 0.95 No
--trim-threshold Silence threshold for trimming (0.0-1.0) 0.001 No
--length-ms Output IR length in milliseconds (trim or zero-pad) - No
--fade-ms Fade-out duration in milliseconds at end of IR (default 5) 5 No
--lowcut Low-cut filter (high-pass) cutoff frequency in Hz (recorded sweep) - No
--highcut High-cut filter (low-pass) cutoff frequency in Hz (recorded sweep) - No
--cut-slope Filter slope in dB/octave (12, 24, 36, ...; default 12) 12 No
--plot-ir Generate frequency response and waveform plot false No
--no-phase-correction Disable automatic phase correction false No
--force-invert-phase Force inversion of the recorded sweep (manual override) false No

File Requirements

Input Files

  • Format: Any uncompressed WAV file
  • Sample Rate: Any (will be automatically resampled to 96kHz for processing)
  • Bit Depth: Any (16, 24, 32-bit supported; will be converted to float64 internally)
  • Channels: Any (mono, stereo, or multi-channel; will be converted to mono by averaging channels)

Output Files

  • Format: WAV files
  • Sample Rate: 44kHz, 48kHz, 88kHz, or 96kHz (set by --sample-rate)
  • Bit Depth: 16-bit, 24-bit, or 32-bit (set by --bit-depth)
  • Channels: Mono (1 channel)

Technical Details

Input Conversion

  • All input files are automatically converted to mono, 96kHz, float64 for processing
  • Stereo or multi-channel files are averaged to mono
  • Sample rates are resampled to 96kHz using linear interpolation
  • Bit depths are normalized to float64

Output IR Length

  • If --length-ms is set, the output IR (and MPT IR) will be trimmed or zero-padded to the specified length in milliseconds
  • If not set, the full IR is used

Fade-Out

  • By default, a 5 ms linear fade-out is applied to the end of the IR (and MPT IR) to avoid clicks
  • You can change the fade duration with --fade-ms

Filtering

  • You can apply a Butterworth low-cut (high-pass) and/or high-cut (low-pass) filter to the recorded sweep before IR extraction
  • Use --lowcut and/or --highcut to specify cutoff frequencies in Hz
  • Use --cut-slope to control the filter steepness (12 dB/octave = gentle, 24+ = steeper)

Deconvolution Process

  1. FFT-based deconvolution of recorded signal by sweep signal
  2. Regularization to prevent division by zero
  3. Silence trimming to remove leading/trailing silence
  4. Normalization to prevent clipping

Minimum Phase Transform

  • Uses real cepstrum method for accurate minimum phase conversion
  • Reduces latency by minimizing pre-ringing
  • Maintains frequency response while optimizing phase characteristics
  • Suitable for real-time applications like guitar amp modeling

IR Visualization

  • Frequency Response Plot: Shows magnitude response in dB vs Hz with log frequency scale
  • Waveform Plot: Displays the first 10ms of the IR in the time domain
  • Professional Layout: Clean, publication-ready plots with Valhallir branding
  • Automatic File Naming: Plots are saved with the same base name as the IR file
  • High-Quality Output: PNG format suitable for documentation and sharing

Phase Correction

  • Automatic Detection: Analyzes correlation between sweep and recorded signals to detect phase inversion
  • Smart Correction: Uses the first 100ms of signals for reliable phase analysis
  • Consistent Polarity: Ensures all IRs have the same phase polarity for easy mixing
  • Optional Disable: Use --no-phase-correction if you know the phase is correct

Output Format Options

  • Sample Rates: 44.1kHz (CD), 48kHz (studio), 88.2kHz, 96kHz (high-res)
  • Bit Depths: 16-bit (CD), 24-bit (studio), 32-bit (high-res)
  • File Sizes: 16-bit ≈ 50% smaller, 32-bit ≈ 33% larger than 24-bit

Dependencies

Examples

Guitar Cabinet IR (CD Quality)

# Generate IR from guitar cab sweep and recording (any WAV format), 50ms length
./valhallir-deconvolver \
  --sweep guitar_cab_sweep.wav \
  --recorded guitar_cab_recorded.wav \
  --output cab_ir_cd.wav \
  --sample-rate 44100 \
  --bit-depth 16 \
  --length-ms 50 \
  --mpt

Room Acoustics IR (Studio Quality)

# Generate room impulse response
./valhallir-deconvolver \
  --sweep room_sweep.wav \
  --recorded room_recorded.wav \
  --output room_ir_studio.wav \
  --sample-rate 48000 \
  --bit-depth 24

High-Resolution IR (Mastering)

# Generate high-resolution IR for mastering
./valhallir-deconvolver \
  --sweep mastering_sweep.wav \
  --recorded mastering_recorded.wav \
  --output mastering_ir.wav \
  --sample-rate 96000 \
  --bit-depth 32 \
  --length-ms 100 \
  --mpt

CI/CD & Multi-Platform Builds

This project includes a Dagger pipeline for building binaries for multiple platforms:

  • macOS ARM64 (darwin/arm64)
  • macOS AMD64 (darwin/amd64)
  • Windows AMD64 (windows/amd64)
  • Linux AMD64 (linux/amd64)

The pipeline is defined in ci/dagger.go. It outputs binaries named valhallir-deconvolver-<os>-<arch> in the dist/ directory.

Usage

  1. Install the Dagger Go SDK and dependencies:
    go install dagger.io/dagger@latest
    go get github.com/joho/godotenv
    go mod tidy
    
  2. Build for all platforms:
    go run ci/dagger.go
    
  3. (Optional) Upload binaries to a Gitea release:
    • Create a .env file in the project root with:
      GITEA_TOKEN=your_token
      GITEA_URL=https://your.gitea.server
      GITEA_OWNER=youruser
      GITEA_REPO=yourrepo
      
    • Run:
      go run ci/dagger.go --release v1.0.0
      
    • This will create (if needed) and upload all binaries to the specified release tag on your Gitea instance.
    • The pipeline will also create and push a local git tag for the release if it does not already exist.

Troubleshooting Dagger

  • If you see could not import dagger.io/dagger, make sure you have installed the Dagger Go SDK and run go mod tidy.
  • The pipeline requires Docker or a compatible container runtime.
  • For Gitea upload, ensure your .env file is present and correct.

Troubleshooting

Common Issues

Input file errors

  • Input files must be uncompressed WAV format. MP3, FLAC, or other compressed formats are not supported.
  • Input sample rate, bit depth, and channel count are automatically converted (no need to preprocess).

"Invalid sample rate" error (output)

  • Use only supported output sample rates: 44100, 48000, 88200, 96000
  • Check the --sample-rate flag value

"Invalid bit depth" error (output)

  • Use only supported output bit depths: 16, 24, 32
  • Check the --bit-depth flag value

Dagger pipeline errors

  • If you see could not import dagger.io/dagger, install the Dagger Go SDK and run go mod tidy.
  • Make sure Docker or a compatible container runtime is running.

Performance

  • Processing time depends on file length
  • FFT-based deconvolution is much faster than time-domain methods
  • Large files (>1GB) may take several minutes
  • Higher bit depths require more memory but don't significantly affect processing time

License

[Add your license information here]

Contributing

[Add contribution guidelines here]

Changelog

See CHANGELOG.md for version history and details. Current version: v1.0.0