- 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
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-phaseto 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 responseir_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 fileir.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-msis 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
--lowcutand/or--highcutto specify cutoff frequencies in Hz - Use
--cut-slopeto control the filter steepness (12 dB/octave = gentle, 24+ = steeper)
Deconvolution Process
- FFT-based deconvolution of recorded signal by sweep signal
- Regularization to prevent division by zero
- Silence trimming to remove leading/trailing silence
- 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-correctionif 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
- urfave/cli - CLI framework
- go-audio/wav - WAV file I/O
- go-dsp/fft - FFT implementation
- gonum - Numerical computing
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
- Install the Dagger Go SDK and dependencies:
go install dagger.io/dagger@latest go get github.com/joho/godotenv go mod tidy - Build for all platforms:
go run ci/dagger.go - (Optional) Upload binaries to a Gitea release:
- Create a
.envfile 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.
- Create a
Troubleshooting Dagger
- If you see
could not import dagger.io/dagger, make sure you have installed the Dagger Go SDK and rungo mod tidy. - The pipeline requires Docker or a compatible container runtime.
- For Gitea upload, ensure your
.envfile 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-rateflag value
"Invalid bit depth" error (output)
- Use only supported output bit depths: 16, 24, 32
- Check the
--bit-depthflag value
Dagger pipeline errors
- If you see
could not import dagger.io/dagger, install the Dagger Go SDK and rungo 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