# 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 ```sh # Clone the repository git clone 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): ```sh ./valhallir-deconvolver --sweep sweep.wav --recorded recorded.wav --output ir.wav ``` ### With Minimum Phase Transform Generate both regular and minimum phase IRs: ```sh ./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): ```sh ./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: ```sh ./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: ```sh ./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: ```sh ./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: ```sh ./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: ```sh ./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: ```sh ./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: ```sh # 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 ```sh ./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 - [urfave/cli](https://github.com/urfave/cli) - CLI framework - [go-audio/wav](https://github.com/go-audio/wav) - WAV file I/O - [go-dsp/fft](https://github.com/mjibson/go-dsp) - FFT implementation - [gonum](https://gonum.org/) - Numerical computing ## Examples ### Guitar Cabinet IR (CD Quality) ```sh # 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) ```sh # 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) ```sh # 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`](./ci/dagger.go). It outputs binaries named `valhallir-deconvolver--` in the `dist/` directory. ### Usage 1. Install the Dagger Go SDK and dependencies: ```sh go install dagger.io/dagger@latest go get github.com/joho/godotenv go mod tidy ``` 2. Build for all platforms: ```sh 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: ```sh 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](./CHANGELOG.md) for version history and details. Current version: v1.0.0