Library Comparisons
This page summarizes implementation-level differences between TorchRIR and related libraries within this comparison scope:
torchrirgpuRIRrir-generatorpyroomacoustics
Feature Comparison
| Feature | torchrir |
gpuRIR |
pyroomacoustics |
rir-generator |
|---|---|---|---|---|
| 🎯 Dynamic Sources | ✅ | 🟡 Single moving source | 🟡 Manual loop | ❌ |
| 🎤 Dynamic Microphones | ✅ | ❌ | 🟡 Manual loop | ❌ |
| 🖥️ CPU | ✅ | ❌ | ✅ | ✅ |
| 🧮 CUDA | ✅ | ✅ | ❌ | ❌ |
| 🍎 MPS | ✅ | ❌ | ❌ | ❌ |
| 📊 Scene Plot | ✅ | ❌ | ✅ | ❌ |
| 🎞️ Dynamic Scene GIF | ✅ | ❌ | 🟡 Manual animation script | ❌ |
| 🗂️ Dataset Build | ✅ | ❌ | ✅ | ❌ |
| 🎛️ Signal Processing | ❌ Scope out | ❌ | ✅ | ❌ |
| 🧱 Non-shoebox Geometry | 🚧 Candidate | ❌ | ✅ | ❌ |
| 🌐 Geometric Acoustics | 🚧 Candidate | ❌ | ✅ | ❌ |
Legend:
✅native support🟡manual setup🚧candidate (not yet implemented)❌unavailable
Notes:
Signal Processingincludes beamforming, DOA, BSS, adaptive filtering, STFT, and denoising.- For
torchrir, this row is included for comparison only and is marked as scope out.
Visualization, Dynamic GIF, and Dataset Build (Source-Level)
Scoring criteria in this section:
- Mark as
✅when the functionality is provided as a library API/submodule (not only in examples). - Mark as
🟡when possible only via manual composition without a dedicated library feature surface. - Mark as
❌when no corresponding library functionality exists.
Visualization
torchrir(✅):- Dedicated visualization submodule and public functions are provided.
- Source lines:
src/torchrir/viz/__init__.py#L6-L17,src/torchrir/viz/scene.py#L14-L23,src/torchrir/viz/scene.py#L51-L63,src/torchrir/viz/io.py#L22-L36,src/torchrir/viz/io.py#L93-L107,src/torchrir/viz/io.py#L127-L141
gpuRIR(❌):- Package exports simulation/control functions only; plotting appears in example scripts.
- Source lines:
gpuRIR/__init__.py#L11,examples/example.py#L8-L9,examples/example.py#L35-L36,examples/polar_plots.py#L3,examples/polar_plots.py#L9-L10,examples/polar_plots.py#L66-L75
pyroomacoustics(✅):- Library-level plotting APIs exist (
Room.plot,Room.plot_rir), with optional plotting helpers in other submodules. - Source lines:
pyroomacoustics/room.py#L1535-L1547,pyroomacoustics/room.py#L1827-L1843,pyroomacoustics/__init__.py#L123-L134
- Library-level plotting APIs exist (
rir-generator(❌):- The package API is focused on RIR generation (
generate) and does not include plotting APIs. - Source lines:
src/rir_generator/__init__.py#L36-L50
- The package API is focused on RIR generation (
Dynamic Scene GIF
torchrir(✅):- Dedicated GIF APIs are provided for dynamic trajectories.
- Source lines:
src/torchrir/viz/__init__.py#L3-L17,src/torchrir/viz/animation.py#L13-L29,src/torchrir/viz/io.py#L127-L141
gpuRIR(❌):- No GIF/animation API is exposed in the package interface.
- Source lines:
gpuRIR/__init__.py#L11
pyroomacoustics(🟡):- Plotting APIs are provided, but no dedicated dynamic-scene GIF API; animation must be manually composed by users.
- Source lines:
pyroomacoustics/room.py#L1535-L1547,pyroomacoustics/room.py#L1827-L1843,pyroomacoustics/__init__.py#L123-L134
rir-generator(❌):- No GIF/animation API is provided.
- Source lines:
src/rir_generator/__init__.py#L36-L50
Dataset Build
torchrir(✅):- Dataset utilities are provided as library modules (
torchrir.datasets) including dataset wrappers and source-loading utilities used by dataset generation workflows. - Source lines:
src/torchrir/datasets/__init__.py#L1-L7,src/torchrir/datasets/__init__.py#L19-L42,src/torchrir/datasets/utils.py#L30-L37
- Dataset utilities are provided as library modules (
gpuRIR(❌):- No dataset submodule or dataset-building API is exposed.
- Source lines:
gpuRIR/__init__.py#L11
pyroomacoustics(✅):- Dataset functionality is provided in-library via
pyroomacoustics.datasetswith corpus classes andbuild_corpusmethods. - Source lines:
pyroomacoustics/__init__.py#L98-L99,pyroomacoustics/__init__.py#L123,pyroomacoustics/datasets/__init__.py#L1-L4,pyroomacoustics/datasets/cmu_arctic.py#L114-L117,pyroomacoustics/datasets/cmu_arctic.py#L196-L202,pyroomacoustics/datasets/google_speech_commands.py#L72-L73,pyroomacoustics/datasets/google_speech_commands.py#L99-L105
- Dataset functionality is provided in-library via
rir-generator(❌):- No dataset module or dataset-building API is present.
- Source lines:
src/rir_generator/__init__.py#L36-L50
ISM High-Pass Filter (HPF) Implementations
This section focuses on libraries (in this comparison scope) that implement a built-in HPF for ISM-generated RIRs: torchrir, rir-generator, and pyroomacoustics.
torchrir: parameterization and equations
Defaults:
rir_hpf_enable=Truerir_hpf_fc=10.0(Hz)rir_hpf_kwargs={"n": 2, "rp": 5.0, "rs": 60.0, "type": "butter"}
For sampling frequency f_s and cutoff f_c, the normalized digital cutoff is:
Second-order sections are designed as:
For each generated RIR tensor x, TorchRIR applies:
along the time axis (last dimension), i.e. static (n_src, n_mic, nsample) and dynamic (T, n_src, n_mic, nsample) outputs are filtered in-place along nsample.
rir-generator: parameterization and equations
Default: hp_filter=True.
The filter coefficients are derived from sampling frequency f_s:
With input sample x[n], internal state v[n], and output y[n]:
State is initialized to zero (v[-1] = v[-2] = 0).
pyroomacoustics: parameterization and equations
Defaults:
rir_hpf_enable=Truerir_hpf_fc=10.0(Hz)rir_hpf_kwargs={"n": 2, "rp": 5.0, "rs": 60.0, "type": "butter"}
For sampling frequency f_s and cutoff f_c, the normalized digital cutoff is:
Second-order sections are designed as:
For each generated RIR x, the library applies:
This is forward-backward filtering (zero-phase response).
ISM Image-Source Amplitude Scaling
In ISM implementations, a common per-image gain form is:
where g_i aggregates reflection/directivity terms and d_i is propagation distance.
Some libraries additionally include free-field normalization by 4\pi:
Quick comparison
| Library | Typical distance scaling | Notes |
|---|---|---|
torchrir |
1/r |
Reflection/directivity gains are multiplied, then divided by distance. |
gpuRIR |
1/(4πr) |
CUDA core uses explicit 4π factor in image-source amplitude. |
rir-generator |
1/(4πr) |
Core C++ implementation uses 4π free-field normalization. |
pyroomacoustics |
Usually 1/r in room ISM path |
build_rir_matrix uses 1/(4πr), so scale depends on API path. |
Practical implication for cross-library tests
Even with matched geometry, beta, image limits, and interpolation settings, direct waveform-level comparisons can show an almost constant gain ratio near 4π between 1/r and 1/(4πr) conventions. Normalize this global factor before enforcing strict amplitude-matching thresholds.
Known Differences
In addition to the 4π scaling gap, the following implementation differences affect cross-library RIR waveform comparisons.
Line references below were checked against:
torchrir(this repository, current branch)gpuRIR(mastersnapshot used for this comparison)pyroomacoustics0.9.0rir-generator0.3.0
1) Image-source enumeration rules (max_order / nb_img)
torchrir: withmax_order, it truncates by L1 norm (diamond); withnb_img, it enumerates a rectangular index range.rir-generator: loops over a rectangular range, then filters by an order condition.gpuRIR: mapsnb_imgdirectly to CUDA-side index expansion, so the enumeration path differs.
Practical note:
- Even when parameters look identical, the included image-source set may not match exactly.
Source lines:
torchrir:src/torchrir/sim/ism/images.py#L21-L32rir-generator:src/rir_generator/_cffi/rir_generator_core.cpp#L177-L207gpuRIR:src/gpuRIR_cuda.cu#L337-L341,src/gpuRIR_cuda.cu#L804-L806,src/gpuRIR_cuda.cu#L839
2) Fractional-delay interpolation kernel
torchrir: Hann-windowed sinc (default tap length 81), with selectable LUT on/off.gpuRIR:Tw-based implementation with separate LUT and mixed-precision controls.rir-generator: a different LP interpolation implementation (with differentTwdefinition).
Practical note:
- Local waveform shape around sample positions can differ, causing mismatches in peak amplitude and fine temporal detail.
Source lines:
torchrir:src/torchrir/config.py#L26-L30,src/torchrir/sim/ism/accumulate.py#L212-L229gpuRIR:src/gpuRIR_cuda.cu#L629-L637,src/gpuRIR_cuda.cu#L644,src/gpuRIR_cuda.cu#L676-L696,gpuRIR/__init__.py#L223-L243rir-generator:src/rir_generator/_cffi/rir_generator_core.cpp#L144-L145,src/rir_generator/_cffi/rir_generator_core.cpp#L214-L218
3) HPF implementation and defaults
torchrir: IIR HPF (enabled by default).pyroomacoustics: also has HPF-enabled paths.rir-generator: uses an Allen-Berkley style HPF.gpuRIR: does not assume an equivalent built-in HPF path, and project discussion indicates the low-frequency attenuation behavior is an intentional design choice (not just a missing toggle).
Practical note:
- HPF presence and coefficient differences change waveform and energy, especially in low-frequency bands.
- In this repository, disabling HPF in
torchrirforgpuRIRparity tests is only a comparison tactic. It does not imply that HPF should be disabled for normal ISM usage.
Source lines:
torchrir:src/torchrir/config.py#L33-L37,src/torchrir/sim/ism/hpf.py#L23-L37,src/torchrir/sim/ism/hpf.py#L40-L56pyroomacoustics:pyroomacoustics/parameters.py#L192-L194,pyroomacoustics/room.py#L2292-L2295,pyroomacoustics/room.py#L2356-L2357rir-generator:src/rir_generator/_cffi/rir_generator_core.cpp#L135-L139,src/rir_generator/_cffi/rir_generator_core.cpp#L232-L243gpuRIR:gpuRIR/__init__.py#L95-L117(no HPF parameter in the publicsimulateRIRAPI)gpuRIRdiscussion: Issue #15
4) Late-reverb / diffuse-tail modeling
torchrir: can add a diffuse tail conditionally.gpuRIR: also separates early reflections and diffuse components, but not with the same method.
Practical note:
- If
tmaxor tail-related settings are not aligned, late-part waveform error can grow significantly.
Source lines:
torchrir:src/torchrir/sim/ism/api.py#L130-L132,src/torchrir/sim/ism/diffuse.py#L15-L49gpuRIR:gpuRIR/__init__.py#L95-L117,gpuRIR/__init__.py#L166,src/gpuRIR_cuda.cu#L831-L835,src/gpuRIR_cuda.cu#L852-L865,src/gpuRIR_cuda.cu#L872-L883,src/gpuRIR_cuda.cu#L445-L461
5) Dynamic API assumptions
torchrir: explicitly models trajectories viasimulate_dynamic_rir(src_traj, mic_traj, ...).gpuRIR: designed around static RIR generation plus trajectory convolution; for fair comparison, fixed mic + single moving source is the cleanest setup.rir-generator: no dynamic trajectory API (static-oriented).
Practical note:
- Without matching scene constraints, a dynamic comparison may reflect API assumptions rather than core algorithm differences.
Source lines:
torchrir:src/torchrir/sim/ism/api.py#L136-L150gpuRIR:gpuRIR/__init__.py#L95-L175,gpuRIR/__init__.py#L177-L220,examples/simulate_trajectory.py#L18-L33rir-generator:src/rir_generator/__init__.py#L36-L50(staticgenerate(...)API)
6) API-path differences inside pyroomacoustics
- The main room ISM path typically uses
1/r. - The
build_rir_matrixpath uses1/(4πr).
Practical note:
- Even within one library, amplitude convention can vary by API path, so fix the call path during comparisons.
Source lines:
pyroomacousticsroom ISM path (1/r):pyroomacoustics/room.py#L2317-L2328->pyroomacoustics/simulation/ism.py#L187pyroomacousticsbuild_rir_matrixpath (1/(4πr)):pyroomacoustics/soundsource.py#L326-L328