Ray Tracing Room Acoustics Simulator — User Guide

Physically accurate ray tracing + diffuse tail: simulates room acoustics using geometric ray tracing for early reflections and a diffuse tail for realistic reverb.

Author: Shai Cohen Affiliation: Department of Music, Bar-Ilan University, Israel Version: 1.0 (2025) License: MIT License Repo: https://github.com/ShaiCohen-ops/Praat-plugin_AudioTools
Contents:

What this does

This script implements Ray Tracing Room Acoustics Simulation — a physically-inspired approach to simulating room reverberation using geometric acoustics. The method traces sound rays from a source, calculates reflections off walls, and captures early reflections near the listener. A diffuse reverb tail is added for realistic decay. The result is a convolution-ready impulse response that can be applied to any sound.

Key Features:

How ray tracing works in acoustics: Sound is modeled as rays emanating from a source in all directions. Each ray travels in straight lines, reflecting off surfaces with energy loss based on wall absorption. When a ray passes near the listener (within capture radius), its contribution is added to the impulse response with appropriate delay and attenuation. Early reflections (first 15-30 ms) are traced geometrically; later reflections are modeled as a diffuse tail. This hybrid approach balances physical accuracy with computational efficiency.

Technical Implementation: (1) Room Setup: Define room dimensions, source/listener positions, absorption coefficients. (2) Ray Generation: Emit rays uniformly in all directions (azimuth). (3) Ray Tracing: For each ray: calculate intersection with walls, update direction via reflection, track path length and energy loss. (4) Listener Capture: When ray passes within listener radius, add contribution to impulse response at delay = path length / speed of sound. (5) Diffuse Tail: Add exponentially decaying Gaussian noise to simulate late reverberation. (6) Convolution: Convolve input sound with generated impulse response. Output: "originalname_raytraced".

Quick start

  1. In Praat, select exactly one Sound object.
  2. Run script…ray_tracing_room_acoustics.praat.
  3. Choose Preset (e.g., "Large Concert Hall", "Recording Studio").
  4. Adjust room dimensions if using Custom preset.
  5. Set ray tracing parameters: number_of_rays, max_reflections, listener_radius.
  6. Set acoustic parameters: wall_absorption, speed_of_sound.
  7. Set reverb parameters: reverb_tail, diffuse_level, early_reflection_level.
  8. Adjust source and listener positions if needed.
  9. Click OK — simulation runs, visual preview shown, output named "originalname_raytraced".
Quick tip: Start with presets to hear different room types immediately. "Small Living Room" for intimate reverb, "Cathedral" for long decay. Increase number_of_rays for smoother, more accurate early reflections (but slower processing). Adjust listener_radius to capture more/less reflections. Lower wall_absorption for longer reverb (more reflective surfaces). Enable visual preview to see ray paths (first 3 reflections for every 5th ray). Output is convolution result — original sound with added room acoustics.
Important: COMPUTATIONAL INTENSITY — More rays = more accurate but slower processing. 100–200 rays recommended for balance. Early reflections only — Late reverb is statistical (diffuse tail), not traced ray-by-ray. 2D approximation — Ray tracing is in 2D (top-down), ignoring ceiling/floor reflections for simplicity. Energy conservation — Each reflection reduces energy by wall_absorption; rays stop when energy < 1%. Listener radius critical — Larger radius captures more reflections but may create unnatural clustering. RT60 estimate — Calculated via Sabine formula; actual reverb may differ due to geometry.

Ray Tracing Theory

Geometric Acoustics Basics

Sound as Rays

Ray assumption: At high frequencies (>~500 Hz), sound propagates like light — straight lines, specular reflections. This is the geometric acoustics approximation.

Ray properties: - Origin: source position (xₛ, yₛ) - Direction: unit vector (dx, dy) - Energy: starts at 1.0, decays per reflection - Path length: cumulative distance traveled Reflection law: angle of incidence = angle of reflection For walls aligned with axes: simply negate x or y component Energy loss per reflection: energy_new = energy_old × (1 - α) where α = wall absorption coefficient (0–1)

Why Ray Tracing for Early Reflections?

Advantages of ray tracing for early reflections:

Limitations:

Listener Capture Mechanism

Capture Radius Method

Instead of checking exact intersection: In real rooms, listener is not a point but has spatial extent. Capture radius simulates this.

Two capture scenarios: 1. Reflection point near listener: - Ray reflects at wall point P - Distance from P to listener L: d = |P - L| - If d < listener_radius: capture reflection - Path length = distance from source to P + d 2. Ray segment passes near listener: - Ray travels from A to B - Closest point C on segment AB to listener L - Distance from C to L: d = |C - L| - If d < listener_radius: capture segment - Path length = distance from source to C + d Amplitude calculation: amplitude = energy × early_reflection_level × distance_attenuation distance_attenuation = 1 / (1 + d/3.0) (inverse distance law approximation)

Why Capture Radius?

Physical rationale:

📐 Visual Example

Small radius (0.5m):

Only very close reflections captured → sparse early reflection pattern, drier sound

Large radius (2.0m):

Many reflections captured → dense early reflections, richer but potentially clustered

Typical: 1.0–1.5m for natural balance

RT60 Calculation

Sabine Formula

Reverberation time estimation:

Sabine's formula: RT60 = 0.161 × V / (α × S) Where: V = room volume (m³) = width × height × depth S = total surface area (m²) = 2×(w×h + w×d + h×d) α = average absorption coefficient (wall_absorption) Example: 8×6×5m room, α=0.15 V = 240 m³ S = 2×(48 + 40 + 30) = 236 m² RT60 = 0.161×240 / (0.15×236) ≈ 1.09 seconds Limitations: - Assumes diffuse sound field (valid for late reverb) - Uniform absorption (all walls same) - No furniture/people Still useful for setting reverb tail length

Diffuse Tail Generation

Statistical late reverb: After ~80 ms, reflections become dense and statistically random.

Diffuse tail formula: tail(t) = diffuse_level × N(0,1) × exp(-6.9 × t / RT60) Where: t = time from impulse start N(0,1) = Gaussian white noise (mean 0, variance 1) exp(-6.9 × t / RT60) = exponential decay (6.9 = ln(1000) for 60dB decay) diffuse_level = overall tail loudness (0.0–1.0) Implementation: For each sample in impulse response: value = existing_value + diffuse_level * randomGauss(0,1) * exp(-6.9 * time / RT60) Physical basis: - Gaussian noise: statistical independence of late reflections - Exponential decay: energy decay proportional to current energy - RT60 controls decay rate

Complete Processing Pipeline

SETUP: Select Sound object Choose preset or custom parameters Parse room dimensions, positions, acoustic parameters VISUALIZATION: Draw room (top view) Mark source (red) and listener (blue) Draw listener capture circle (Optional: draw first 3 reflections for sample of rays) RAY TRACING: FOR each ray (1 to number_of_rays): angle = uniform 0–360° pos = source_position dir = (cos(angle), sin(angle)) energy = 1.0 path_length = 0 FOR reflection (1 to max_reflections): Find wall intersection (nearest among 4 walls) Update path_length energy = energy × (1 - wall_absorption) Check if reflection point OR ray segment is within listener_radius of listener IF within radius AND energy > 0.01: Calculate total acoustic path delay = path_length / speed_of_sound amplitude = energy × early_reflection_level × distance_atten Add to impulse response at delay time Reflect direction (negate x or y component) Update position to wall point IF energy < 0.01: BREAK END FOR reflections END FOR rays DIFFUSE TAIL: Add: IR = IR + diffuse_level × N(0,1) × exp(-6.9×t/RT60) NORMALIZATION: Scale peak to 0.99 CONVOLUTION: Convolve original sound with impulse response Rename: "originalname_raytraced" Scale peak: 0.95 OUTPUT: New Sound object with room acoustics applied Info window with simulation statistics

Room Presets

Built-in Room Types

🏠 Small Living Room

Dimensions: 5×3×4m (W×H×D)

Characteristics: Intimate, short reverb (RT60 ~0.6s), moderate reflections

Use: Dialogue, intimate music, home theater simulation

🎻 Large Concert Hall

Dimensions: 40×15×20m

Characteristics: Long reverb (RT60 ~3.0s), many reflections, diffuse

Use: Classical music, orchestral, large ensemble

🚽 Bathroom (Bright)

Dimensions: 2.5×2.2×2.0m

Characteristics: Very reflective (α=0.05), bright reverb, flutter echoes

Use: Vocal effects, percussive sounds, special effects

🎙️ Recording Studio (Dead)

Dimensions: 6×4×5m

Characteristics: High absorption (α=0.70), very short reverb (RT60 ~0.3s)

Use: Dry recordings, voice-over, close-mic simulation

⛪ Cathedral (Very Long)

Dimensions: 60×25×40m

Characteristics: Extremely long reverb (RT60 ~5.0s), massive space

Use: Religious music, atmospheric pads, epic sound design

Preset Parameters Table

PresetDimensions (W×H×D)RaysMax ReflectionsAbsorption (α)RT60 (s)Listener Radius
Small Living Room5×3×4m80100.400.61.0m
Large Concert Hall40×15×20m150250.153.02.5m
Bathroom (Bright)2.5×2.2×2.0m100200.051.00.8m
Recording Studio (Dead)6×4×5m5050.700.31.0m
Cathedral (Very Long)60×25×40m200300.085.03.0m
Small Club12×4×10m100120.251.01.5m
Outdoor (Minimal)100×50×100m3030.950.22.0m
Bright Chamber8×6×7m120150.121.51.2m

Parameters & Settings

Room Geometry

ParameterTypeDefaultDescription
room_widthpositive8Room width (meters)
room_heightpositive6Room height (meters)
room_depthpositive5Room depth (meters)
source_xpositive2Source X position (meters from left wall)
source_ypositive3Source Y position (meters from bottom wall)
listener_xpositive6Listener X position
listener_ypositive3Listener Y position

Ray Tracing Parameters

ParameterTypeDefaultDescription
number_of_rayspositive100Number of rays emitted (more = accurate but slower)
max_reflectionspositive15Maximum reflections per ray (higher = longer tail)
listener_radiuspositive1.5Capture radius around listener (meters)

Acoustic Parameters

ParameterTypeDefaultDescription
wall_absorptionpositive0.15Wall absorption coefficient (0=perfect reflector, 1=perfect absorber)
speed_of_soundpositive343Speed of sound in m/s (343 at 20°C)

Reverb Parameters

ParameterTypeDefaultDescription
reverb_tailpositive1.5Additional seconds after RT60 for impulse response
diffuse_levelpositive0.15Amplitude of diffuse tail (0–1)
early_reflection_levelpositive0.6Loudness of traced reflections (0–1)

Applications

Room Simulation for Production

Use case: Add realistic room acoustics to dry recordings

Technique: Match preset to intended space (studio, hall, etc.)

Example: Dry vocal → "Small Club" preset for live feel

Acoustic Design Testing

Use case: Test acoustic treatment options virtually

Technique: Adjust wall_absorption to simulate different materials

Workflow:

Sound Design for Film/Games

Use case: Create realistic environmental sounds

Technique: Use extreme presets for effect

Examples:

Educational Tool

Use case: Teach acoustics and reverberation principles

Technique: Visualize rays, adjust parameters, hear results

Learning outcomes:

Virtual Room Micing

Use case: Simulate different microphone placements

Technique: Adjust source-listener distance and positions

Examples:

Practical Workflow Examples

🎙️ Vocal Room Addition

Goal: Add natural room sound to dry vocal recording

Settings:

  • Preset: Bright Chamber
  • number_of_rays: 120
  • wall_absorption: 0.12
  • early_reflection_level: 0.7
  • diffuse_level: 0.18

Result: Natural reverb with clear early reflections, not overwhelming

🎹 Piano Hall Simulation

Goal: Create concert hall reverb for dry piano recording

Settings:

  • Preset: Large Concert Hall
  • number_of_rays: 150
  • max_reflections: 25
  • reverb_tail: 3.0
  • listener_radius: 2.5m

Result: Rich, long reverb with dense early reflections

🔬 Acoustic Research

Goal: Study effect of room proportions on reverb

Method:

  • Fix volume (e.g., 1000m³)
  • Vary width:height:depth ratios
  • Keep same absorption
  • Compare RT60 and reflection patterns

Insight: Cube-shaped rooms vs. long halls produce different reverb characteristics

Advanced Techniques

Ray count optimization:
  • 50 rays: Fast, sparse reflections (good for quick previews)
  • 100–150 rays: Balance of accuracy and speed (recommended)
  • 200+ rays: Very smooth, accurate but slow (final renders)
  • Note: Each ray traces up to max_reflections bounces

More rays better capture directional distribution of reflections

Positioning strategies:
  • Source near wall: Strong early reflections from that wall
  • Listener in room center: Most symmetric reflection pattern
  • Source and listener close: Strong direct sound, less reverb
  • Listener near corner: Reflections from multiple walls simultaneously

Visual preview helps understand reflection patterns

Troubleshooting Common Issues

Problem: Output too dry/not enough reverb
Causes: wall_absorption too high, listener_radius too small, early_reflection_level too low
Solutions: Decrease absorption, increase radius/level, choose more reflective preset
Problem: Output too washy/muddy
Causes: wall_absorption too low, RT60 too long, diffuse_level too high
Solutions: Increase absorption, choose drier preset, decrease diffuse_level
Problem: Processing too slow
Causes: Too many rays, too many reflections, large room
Solutions: Reduce number_of_rays, reduce max_reflections, use faster computer
Problem: Clipping/distortion
Causes: early_reflection_level or diffuse_level too high, insufficient normalization
Solutions: Reduce levels, ensure scale peak applied after convolution
Problem: Unnatural "clustering" of reflections
Causes: listener_radius too large, capturing too many similar-path reflections
Solutions: Reduce radius, increase number_of_rays for smoother distribution

Technical Deep Dive

Ray-Wall Intersection Mathematics

Exact Intersection Calculation

For axis-aligned walls:

Room boundaries: x = 0 (left wall), x = room_width (right wall) y = 0 (bottom wall), y = room_height (top wall) Ray equation: x(t) = pos_x + dir_x × t y(t) = pos_y + dir_y × t Intersection with right wall (x = room_width): t_right = (room_width - pos_x) / dir_x (if dir_x > 0) Intersection with left wall (x = 0): t_left = -pos_x / dir_x (if dir_x < 0) Intersection with top wall (y = room_height): t_top = (room_height - pos_y) / dir_y (if dir_y > 0) Intersection with bottom wall (y = 0): t_bottom = -pos_y / dir_y (if dir_y < 0) Choose smallest positive t: t_wall = min(positive t_right, t_left, t_top, t_bottom) Intersection point: wall_x = pos_x + dir_x × t_wall wall_y = pos_y + dir_y × t_wall

Energy Decay Modeling

Exponential decay with distance and absorption:

Physical model: Sound pressure decays with distance: p ∝ 1/r Energy (power) decays: I ∝ 1/r² Our simplification: distance_attenuation = 1 / (1 + distance/3.0) This approximates 1/r for small distances, avoids singularity at r=0 Per-reflection absorption: energy_after = energy_before × (1 - α) where α = wall_absorption coefficient Total amplitude for reflection at distance d after n reflections: amplitude = (1 - α)^n × early_reflection_level × 1/(1 + d/3.0) Ray stopping criterion: Stop when energy < 0.01 (99% absorbed) Corresponds to n > log(0.01)/log(1-α) reflections

Diffuse Tail Physics

Statistical Room Acoustics

Late reverb as Gaussian process:

Schroeder's late reverb model: - After sufficient time, sound field becomes diffuse - Reflections arrive from all directions with equal probability - Amplitude distribution becomes Gaussian (Central Limit Theorem) - Energy decays exponentially: E(t) = E₀ × exp(-13.8 × t / RT60) Our implementation: tail_sample = diffuse_level × N(0,1) × exp(-6.9 × t / RT60) Where 6.9 = ln(1000)/2 (for pressure, not power) Rationale: - N(0,1): Gaussian noise representing random phase/amplitude - exp(-6.9t/RT60): Exponential decay (60dB in RT60 seconds) - diffuse_level: Overall gain control Note: This is pressure decay, not energy decay Energy would decay twice as fast: exp(-13.8t/RT60)

Limitations and Extensions

Current Limitations

1. 2D approximation: - Only horizontal reflections (x-y plane) - No ceiling/floor reflections - Could extend to 3D with 6 walls 2. Specular reflections only: - No diffuse scattering - Real walls scatter sound at high frequencies 3. Frequency-independent absorption: - Real materials have frequency-dependent α(ω) - Could implement via frequency-dependent convolution 4. No diffraction/edge effects: - Sound bends around obstacles/corners - Important for low frequencies 5. Point source assumption: - Real sources have directivity - Could implement directional ray emission

Potential Extensions

1. 3D ray tracing: - Add z-coordinate, ceiling/floor - 6 walls instead of 4 - More realistic but 3× slower 2. Frequency-dependent absorption: - Multiple impulse responses for bands - Convolve each frequency band separately 3. Image source method for early reflections: - Analytically calculate early reflection paths - More accurate than ray tracing for early part 4. Hybrid ray tracing/image source: - Image source for first 3–5 reflections - Ray tracing for later reflections - Best accuracy/efficiency balance 5. Air absorption: - High frequencies absorb in air over distance - Add frequency-dependent distance attenuation