Vehicle Noise Synthesizer

ATG Simulator Developer Reference v1.9f

Overview

Vehicle Noise Synthesizer (VNS) is the audio engine used by ATG Simulator to simulate vehicle sounds based on engine RPM and load. It blends real audio clips recorded at different RPM values using a constant-power crossfade, running on Unity's Burst Job System for maximum performance.

The core algorithm picks the two neighbouring clips that bracket the current RPM and crossfades them with a constant-power cosine/sine pan law (cos² + sin² = 1). A hysteresis-buffered pair selector with cylinder-aware hold timing prevents rapid switching. On non-WebGL platforms every instance is batched inside a Burst-compiled job.

Key Features

  • RPM-Ratio Pitch Model: Each clip's base pitch is engineRPM / clipRPM × global pitch curve, producing physically accurate playback speed that scales correctly at all RPM levels (v1.9).
  • Burst-Accelerated: Multi-threaded audio calculations via Unity's Job System (non-WebGL).
  • Constant-Power Crossfade: Smooth, equal-loudness transitions between RPM clips.
  • Active-Pair Visualization: The inspector graph highlights only the two clips currently blending.
  • NWH Vehicle Physics 2 Integration: Direct feed from engine.OutputRPM and engine.Load with gear-change pitch oscillation.
  • Three-Tier Pitch Control: Tune pitch globally (pitch curve), per-bank (trim), or per-clip (Lo/Hi multipliers).
  • Throttle Body & DCT Shift (event-driven): Intake roar, throttle flutter, and DCT shift burble are now triggered by public methods (OnThrottleTipIn, OnThrottleTipOut, OnGearShift) called from the integration script — not by internal load-delta thresholds. The old threshold fields are deprecated.
  • Exhaust Burble & Engine Lugging: Configurable overrun pops and low-RPM strain effects.

What's New in v1.9f NEW

Pitch Model Rewrite — RPM-Ratio Based

  • New formula: Each clip's base pitch is now engineRPM / clipRPM × globalPitchCurve. This is physically accurate: a clip recorded at 2000 RPM plays at 2× speed when the engine reaches 4000 RPM, before any per-clip multipliers.
  • Per-clip fields renamed: minPitch/maxPitch (absolute clamps, default 0.5–2.5) are now loPitch/hiPitchmultipliers on top of the RPM-ratio pitch, defaulting to 1.0 (neutral, no effect).
  • rpmPitchTracking removed — the new ratio model makes per-clip tracking strength redundant.
  • targetedShiftPitch removed — global pitch shaping is now done exclusively through the pitchCurve (Tier 1).
  • idlePitch removed — the ratio model naturally produces correct pitch at all RPM including idle.
  • pitchCurve default is now a flat constant 1.0 (was 0.97→1.03).

New Audio Features

  • Throttle Body Effects (event-driven): Intake roar and throttle flutter are now triggered by public methods (OnThrottleTipIn / OnThrottleTipOut) called from the integration script when the player's throttle input jumps 0→1 or 1→0. The old deltaLoad threshold fields (intakeRoarLoadDeltaThreshold, throttleFlutterLoadDeltaThreshold) are deprecated and no longer read.
  • DCT Shift Burble (event-driven): The DCT exhaust overlay is now fired exclusively by OnGearShift() on gear change, instead of the old deltaLoad-based trigger. The dctShiftBurbleFiredThisDecrease flag is removed. A 30ms grace period prevents transmission-engagement noise from cutting off the burble; load increase still stops it immediately after the grace window.
  • Exhaust Redline Effect: Repeating one-shot crackle/pressure-wave clips while RPM stays within a configurable redline window. Delay and pitch are randomised.
  • Burble window: Single burbleLoadThreshold replaced by burbleLoadLowThreshold + burbleLoadHighThreshold — burble now fires within a configurable load window instead of only below a threshold.

Editor UX & Workflow

  • RPM field is now a plain integer text box (no more Range slider).
  • Pitch Lo/Hi sliders show numeric readouts with "0" and "4" endpoint labels on the blue range bar.
  • Active-pair highlighting: The volume envelope graph highlights only the two active neighbour clips; inactive clips dim to 13%.
  • No more auto-sort: Editor clip order is preserved; sorting happens locally at runtime inside BuildRpmTables and BuildBankLayers.
  • Debug RPM markers follow debugrpm in both edit and play modes.

Carried Forward from v1.8f2

  • Combustion Timing: Cylinder-aware pair-hold turns the blend into a granular, looped system.
  • Constant-power crossfade (cos² + sin² = 1), hysteresis fixes, rev-limiter cutoff, engine lugging system.

The 3-Tier Pitch Guide

Pitch is the single most common thing you will tune. VNS gives you three levels of control, from the broadest brush to the finest. Always reach for the broadest tier that solves your problem.

Tier 1 - Global Curve

Everything, both banks

If every clip (acceleration and deceleration alike) sounds too high or too low, shape the global pitchCurve. The default is a flat constant 1.0.

Field: pitchCurve (AnimationCurve)
Section: Global Curves
Tier 2 - Per-Bank

All accel OR all decel

If the whole acceleration bank, or the whole deceleration bank, is off relative to the other, trim that one bank.

Fields: acPitchTrim / dcPitchTrim
Section: Tuning
Tier 3 - Per-Clip

One clip at a time

If a single clip is higher or lower than its neighbours, adjust its own loPitch/hiPitch multipliers with the blue Lo/Hi bar under its clip row.

Fields: loPitch (Lo) / hiPitch (Hi)
Section: Acceleration / Deceleration Bank

How the per-clip Lo / Hi window works

Each clip has two pitch multiplier fields shown on the blue bar beneath its audio-clip field:

  • Lo (loPitch) is the multiplier applied to the RPM-ratio pitch at the lowest RPM of this clip's active range (just after it fades in). Default 1.0 = neutral.
  • Hi (hiPitch) is the multiplier applied to the RPM-ratio pitch at the highest RPM of its range (just before the next clip takes over). Default 1.0 = neutral.

The final pitch formula for each clip at runtime is:

pitch = (engineRPM / clipRPM) × globalPitchCurve × Lerp(loPitch, hiPitch, progress) + bankPitchTrim + pitchOffset

Lo and Hi interpolate smoothly as RPM climbs through that clip's window. The blue bar visualizes where that window sits on the full 0.01 to 4.0 scale, so you can see at a glance how wide and how high each clip reaches.

Lo and Hi default to 1.0 = fully automatic. When both are 1.0, the RPM-ratio pitch model (engineRPM / clipRPM) runs unmodified — the engine sounds physically correct with zero per-clip tuning, provided your audio clips are well-recorded and rpmValue is accurate. Lo/Hi are artistic fine-tuning controls only: reach for them when a single clip sounds slightly too high or too low relative to its neighbours, not as a substitute for correct rpmValue assignment.

Recommended Quick-Start Recipe

This neutralizes every pitch tier first, then lets your ears do the work. It produces surprisingly realistic results fast.

  1. Set the pitchCurve (Global Curves) to a flat constant 1.0 (the default).
  2. Set every clip's Lo and Hi values to 1.0 (neutral). With correct rpmValue and well-recorded clips, the RPM-ratio model produces realistic pitch automatically. Only adjust Lo/Hi later if a specific clip sounds out of place relative to its neighbours — these are artistic fine-tuning controls, not required tuning.
  3. Set acPitchTrim and dcPitchTrim (Tuning) to 0.
  4. Before anything else, assign the correct rpmValue to every clip in the banks. This is the single most important data point — the entire RPM-ratio model depends on it.
  5. Enable debug, then sweep debugrpm across the range and listen. Adjust by ear, starting from the broadest tier that helps.
Your audio clips and their RPM values directly shape the end result. No parameter can rescue badly recorded or badly spaced clips, so invest in good, seamless loops first.

Setup & Usage

ATG Simulator note: The project already includes NWH Vehicle Physics 2. The bridge script AudioGranulatorNWHVehiclePhysics2.cs automatically feeds NWH engine data into VNS, so no manual wiring is required.

Requirements

  • Unity 2021.3 or newer.
  • Unity.Mathematics and Unity.Burst packages (install via Package Manager).
  • NWH Vehicle Physics 2 (included in the ATG Simulator project).

Adding VNS to a Vehicle

  1. Add the VehicleNoiseSynthesizer component to your vehicle's audio root GameObject (menu: "ATG Audio / Vehicle Noise Synthesizer").
  2. Assign an AudioSource to audioSourceTemplate. The pooling system copies its 3D settings for every generated source.
  3. Populate acceleratingSounds with your clips. For each, set the AudioClip and the rpmValue it was recorded at. The rpmValue field is a plain integer text box in v1.9f — type exact values.
  4. Set each clip's loPitch and hiPitch multipliers (default 1.0 = neutral). Watch the active-pair volume graph confirm your blends.
  5. Add the matching bridge from Scripts/Inputs/NWH-Physics_IntegrationSample.

Debugging with the Simple UI

The sample scene plus AudioGranulatorSimpleUI gives sliders and keyboard controls (Up/Down for RPM, Left/Right for Load) to audition sounds without a full vehicle. It supports both the New Input System and the Legacy Input Manager.

Live Inspector Simulator

A faithful, fully interactive recreation of the VehicleNoiseSynthesizer inspector. Every section opens with a plain-language explainer of what it does, and hovering (or tapping ) any field reveals its documentation tooltip with type, range, and a practical tip. Drag the master Debug RPM scrubber to watch the blend graphs and the active-clip pair update live.

How to read it: Coloured dots mark pitch tiers — ● Global, ● Per-Bank, ● Per-Clip. Hit Expand all, then sweep Debug RPM to see exactly which two clips blend at any moment.

Vehicle Noise Synthesizer (Script)
v1.9f • github.com/ImDanOush/VehicleNoiseSynthesizer

Full Parameter Reference

Every parameter on the component, grouped by its inspector section. Pitch-related fields are tagged with their tier. All defaults and ranges match the v1.9 source code exactly.

Debug Controls

  • debug (bool, default false):

    Manually override RPM/load for testing so the NWH Vehicle Controller does not dictate them. debugrpm and debugload then drive the audio. Markers follow debugrpm in both edit and play modes.

  • debugrpm (float, 100–9000, default 800):

    Test RPM value used while debug is on.

  • debugload (float, 0–1, default 1):

    Test engine load value used while debug is on.

  • enableDiagnosticLogger (bool, default false):

    Prints per-clip volume/pitch state to the console once per second.

  • enableBurbleDiagnostics (bool, default false):

    Logs burble gate decisions to the console.

Core

  • audioSourceTemplate (AudioSource):

    Template the pooling system clones for every generated voice. Its 3D settings (spatial blend, rolloff) are copied to all sources.

  • mixer (AudioMixerGroup):

    Optional mixer group for routing.

  • mixerType (enum):

    Role label: Intake, Engine, Exhaust, Transmission, or Differential.

  • masterVolume (float, 0.007–1.00, default 1):

    Master volume for all engine sounds.

  • autoBlip (bool, default true):

    Forces the acceleration bank blend to 1.0 on a sharp RPM jump.

  • rpmdeviation (int, default 1000):

    Fallback RPM spacing used when neighbouring clips are missing.

  • shiftPitchOsc (float, HideInInspector):

    Gear-change pitch oscillation value written by the NWH bridge (AudioGranulatorNWHVehiclePhysics2). Not shown in the inspector; driven automatically.

Global Curves

  • pitchCurve (AnimationCurve) Pitch Tier 1:

    Global pitch contour vs normalized RPM. Default is a flat constant 1.0. Keep flat while tuning, then add character later. The curve value is multiplied into every clip's RPM-ratio pitch.

  • volumeCurve (AnimationCurve):

    Bank loudness vs normalized RPM. Default rises from 0.5 to 1.0.

  • loadEffectivenessOnPitch (float, default 0.05):

    How much engine load bends the global pitch contour.

Volume Configuration

  • idleVolume (float, 0.05–1.00, default 0.1):

    Default volume when the engine is at idle.

  • maxVolumeAcc (float, 0–2, default 0.4):

    Volume cap for acceleration sounds (0 = no limit). Values above 1.0 boost the bank.

  • maxVolumeDcc (float, 0–2, default 0.1):

    Volume cap for deceleration sounds (0 = no limit).

Blend Behaviour

  • keepBankClipsPlaying (bool, default true):

    Keep silent clips looping at zero volume to avoid playback-start latency.

  • clipVolumeResponseTime (float, 0.005–0.50, default 0.05):

    Per-layer volume smoothing time in seconds.

  • clipPitchResponseTime (float, 0.005–0.50, default 0.04):

    Per-layer pitch smoothing time in seconds.

  • rpmResponseTime (float, 0.005–0.50, default 0.035):

    Input RPM smoothing time in seconds.

  • loadResponseTime (float, 0.005–0.50, default 0.04):

    Input load smoothing time in seconds.

  • pairHysteresisRpm (float, 0–500, default 120):

    Extra RPM margin required before the active clip pair is allowed to switch.

  • pairHoldCycles (float, 0–20, default 0.5):

    Minimum hold after a pair switch, measured in combustion-event cycles. The combustion-derived duration is rounded up to whole physics ticks (Time.fixedDeltaTime) before it is applied, because the pair selector is evaluated inside a WaitForFixedUpdate loop and a sub-tick hold would expire before it could ever block a switch. A value of 0 disables the hold (the pairHysteresisRpm margin still limits switching). Raise it for longer, more audible stability.

Acc/Dec Crossfade

  • loadCrossoverPoint (float, 0–0.5, default 0.18):

    Load value where acceleration and deceleration banks blend 50/50.

  • loadBlendWidth (float, 0.01–0.4, default 0.10):

    Width of the blend zone around the crossover point.

  • loadVolumeAccChangerFactor (float, 0–1, default 1):

    Depth of load-based volume modulation for the accel bank.

  • loadVolumeDccChangerFactor (float, 0–1, default 1):

    Depth of load-based volume modulation for the decel bank.

  • loadVolumeChangerMinValue (float, 0–0.99, default 0.1):

    Gain floor at the weakest load state.

Combustion Timing

  • cylinderCount (int, 1–16, default 4):

    Cylinder count used to estimate firing frequency. This is the v1.8 "magic" that makes the blend a granular, looped system, repeating clips per the engine's cylinder spec for realism.

  • combustionCycleMode (enum, default FourStroke):

    FourStroke uses cylinderCount/2 firing events per revolution; TwoStroke uses cylinderCount.

Acceleration / Deceleration Banks

You can use one clip for both directions, or a series of clips per bank. Each clip is an EngineAudioClipData:

  • audioClip (AudioClip):

    The recorded engine sound.

  • rpmValue (int, 0–10000, default 1000):

    RPM the clip was recorded at. Plain integer field in v1.9f (no slider). This is the foundation of the RPM-ratio pitch model.

  • description (string):

    Optional description for this audio clip.

  • loPitch (float, 0.01–10, default 1) Pitch Tier 3:

    Multiplier applied to the RPM-ratio pitch at the lowest RPM of this clip's window. Default 1.0 = neutral (no scaling — the RPM-ratio model runs automatically). This is an artistic fine-tuning control; with correct rpmValue and well-recorded clips, leave at 1.0. Formerly minPitch in v1.8.

  • hiPitch (float, 0.01–10, default 1) Pitch Tier 3:

    Multiplier applied to the RPM-ratio pitch at the highest RPM of this clip's window. Default 1.0 = neutral (no scaling — the RPM-ratio model runs automatically). This is an artistic fine-tuning control; with correct rpmValue and well-recorded clips, leave at 1.0. Formerly maxPitch in v1.8.

  • volumeOffset (float, -1 to 1, default 0):

    Per-clip volume trim.

  • pitchOffset (float, -0.5 to 0.5, default 0):

    Per-clip pitch trim added to the final computed pitch.

Tuning

  • acPitchTrim (float, -1 to 1, default 0) Pitch Tier 2:

    Pitch trim for the entire acceleration bank.

  • dcPitchTrim (float, -1 to 1, default 0) Pitch Tier 2:

    Pitch trim for the entire deceleration bank.

  • maximumTheoricalRPM (float, 1000–20000, default 10000):

    Maximum theoretical RPM used for normalization and graph scaling.

  • lowPassStrength (float, 0–1, default 0):

    Low-pass muffling boost.

  • highPassStrength (float, 0–1, default 0):

    High-pass rasp strength.

  • resonanceStrength (float, 0–1, default 0):

    Resonance strength.

  • distortionStrength (float, 0–1, default 0):

    Distortion boost multiplier.

  • chorusStrength (float, 0–1, default 0):

    Chorus strength.

  • reverbStrength (float, 0–1, default 0):

    Reverb strength.

  • useSharedMixerReverb (bool, default true):

    When true, per-layer AudioReverbFilter components are NOT created; reverb is routed through the mixer instead.

  • reverbMixerParamName (string, default "ReverbAmount"):

    Name of the exposed float parameter on the mixer that controls reverb send/wet level. Only used when useSharedMixerReverb is true.

FX Curves & Sound Character

Optional artistic effects driven by RPM and load. All use Unity's native audio filters.

  • distortionCurve (AnimationCurve):

    Controls distortion amount based on RPM and load.

  • distortionIntensity (float, 0–1, default 0.5):

    Overall intensity of the distortion effect.

  • mufflingIntensity (float, 0–1, default 0.5):

    Intensity of the muffling effect when engine load decreases.

  • lowPassCurve (AnimationCurve):

    Controls low-pass frequency cutoff based on engine load. Default 800 Hz at load 0, 22000 Hz at load 1.

  • lowPassIntensity (float, 0–1, default 0.5):

    Overall intensity of the low pass filter effect.

Throttle Body Configuration v1.9

  • enableThrottleBody (bool, default true):

    Enable throttle body sounds: intake roar on tip-in, flutter on tip-out.

  • intakeRoarSounds (AudioClip[]):

    Audio clips played as a one-shot when the throttle snaps open (tip-in / intake roar).

  • throttleFlutterSounds (AudioClip[]):

    Audio clips played as a one-shot when the throttle snaps shut at high RPM (tip-out / flutter).

  • intakeRoarVolume (float, 0–1, default 0.6):

    Master volume for intake roar clips. Final volume is scaled linearly by normalised RPM.

  • throttleFlutterVolume (float, 0–1, default 0.5):

    Master volume for throttle flutter clips. Final volume is scaled linearly by normalised RPM.

  • throttleBodyPitchVariation (float, 0–0.3, default 0.05):

    Random ±pitch variation applied to each throttle body one-shot.

  • intakeRoarLoadDeltaThreshold (float, 0.005–0.5, default 0.05) DEPRECATED:

    No longer used. Intake roar is now triggered via OnThrottleTipIn() called from the integration script. This field is kept for serialization compatibility but is not read by any logic.

  • throttleFlutterLoadDeltaThreshold (float, 0.005–0.5, default 0.05) DEPRECATED:

    No longer used. Throttle flutter is now triggered via OnThrottleTipOut() called from the integration script. This field is kept for serialization compatibility but is not read by any logic.

  • throttleBodyCooldown (float, 0.01–1, default 0.08):

    Minimum seconds between successive throttle body triggers (prevents spamming).

Exhaust Redline Configuration v1.9

  • enableRedlineEffect (bool, default true):

    Enable the exhaust crackle/pressure-wave sound that repeats while the engine is held near redline.

  • redlineSounds (AudioClip[]):

    Audio clips played in a repeating loop while RPM stays within the redline range.

  • redlineVolume (float, 0–1, default 0.6):

    Master volume for redline exhaust clips.

  • redlineMinRPM (float, default 7000):

    RPM at which the redline effect begins to trigger.

  • redlineMaxRPM (float, default 0):

    RPM ceiling for the redline effect (0 = no upper limit, uses maxRpm).

  • redlineMinDelay (float, 0.01–1, default 0.05):

    Minimum delay (seconds) between successive redline one-shot clips.

  • redlineMaxDelay (float, 0.01–2, default 0.2):

    Maximum delay (seconds) between successive redline one-shot clips.

  • redlineBasePitch (float, 0.5–2, default 1):

    Base pitch for redline clips.

  • redlinePitchVariation (float, 0–0.3, default 0.05):

    Random ±pitch variation per redline clip.

Burble & Lugging

  • enableExhaustBurble (bool, default true) + burbleSounds, burbleVolume (0–1, default 0.7), burbleMinRPM (default 3500), burbleLoadLowThreshold (0–1, default 0.0), burbleLoadHighThreshold (0–1, default 0.3), burbleRPMDropThreshold (0–3000, default 500), burbleProbability (0–1, default 0.7), minBurbleDelay (0.01–0.5, default 0.05), maxBurbleDelay (0.05–1, default 0.2), burbleRandomPitchVariation (0–0.2, default 0.08), burbleFadeRate (4–100, default 40):

    Overrun pops and crackle. Burble fires when load is within the window [burbleLoadLowThreshold, burbleLoadHighThreshold) — the low threshold prevents burble during full coasting, the high threshold suppresses it under power.

  • enableEngineLugging (bool, default true) + luggingSounds, luggingVolume (0–1, default 0.8), luggingMinRPMThreshold (default 800), luggingMaxRPMThreshold (default 2000), luggingMinLoadThreshold (0–1, default 0.7), luggingFadeInSpeed (0.1–20, default 5), luggingFadeOutSpeed (0.1–20, default 3), luggingBasePitch (0.5–1.5, default 0.9), luggingRandomPitchVariation (0–0.2, default 0.05):

    Low-RPM, high-load strain sound.

  • enableDctShiftBurble (bool, default true) + dctShiftBurbleSound (AudioClip), dctShiftBurbleVolume (0–1, default 0.7), dctShiftBurbleRpmVolumeInfluence (0–1, default 0.5), dctShiftBurbleMinRPM (default 2000), dctShiftBurbleMaxDuration (0.01–1, default 0.12), dctShiftBurbleBasePitch (0.5–2, default 1), dctShiftBurblePitchVariation (0–0.3, default 0.05):

    DCT Shift Burble (event-driven). A looping exhaust overlay fired on gear change via OnGearShift(). Plays for up to dctShiftBurbleMaxDuration but cuts off immediately if engine load increases (after a 30ms grace period to ignore transmission-engagement noise). Volume is scaled by RPM via dctShiftBurbleRpmVolumeInfluence.

Internal / Hidden Fields

  • launchMode (bool, HideInInspector, default false):

    Forces full acceleration blend. Used programmatically for launch control sequences.

  • nonDecelerateAudiosMode (private bool):

    Automatically set to true when the deceleration bank is empty. Causes the accel bank to be reused for both directions through the load crossover.

Public Event API v1.9f+

Integration scripts must call these three methods at the appropriate moments. The old deltaLoad-based auto-detection in UpdateThrottleBodyEffects and UpdateDctShiftBurble has been removed — these effects will not play unless an integration script calls the corresponding method.

OnThrottleTipIn(float throttleValue, float rpm, float engineLoad)

Call when the player's throttle input jumps from near-zero to near-full (0→1 tip-in). Plays a one-shot intake roar clip.

  • Guards: enableThrottleBody must be true; _isOn must be true (engine running); cooldown must be elapsed.
  • Volume: intakeRoarVolume × throttleValue × engineLoad — if the engine is off (load=0), volume is zero.
  • Pitch: slight upward scaling with normalised RPM.

OnThrottleTipOut(float rpm, float engineLoad)

Call when the player's throttle input drops from near-full to near-zero (1→0 tip-out). Plays a one-shot throttle flutter clip.

  • Guards: enableThrottleBody must be true; _isOn must be true; cooldown must be elapsed.
  • Volume: throttleFlutterVolume (constant — flutter is a release sound).
  • Pitch: slight upward scaling with normalised RPM.

OnGearShift()

Call when the transmission changes gear. Fires the DCT shift burble (looping exhaust overlay).

  • Guards: enableDctShiftBurble must be true; dctShiftBurbleSound must be assigned.
  • Duration: plays for up to dctShiftBurbleMaxDuration (default 0.12s).
  • Cut-off: stops immediately if engine load increases (driver floors it), but only after a 30ms grace period to ignore transmission-engagement noise.

NWH Vehicle Physics 2 Integration

ATG Simulator uses NWH Vehicle Physics 2. The bridge script feeds engine data straight into VNS.

AudioGranulatorNWHVehiclePhysics2

  • Hooks the engine's onStart/onStop events to call TurnOn()/TurnOff().
  • Each FixedUpdate passes engine.OutputRPM to rpm and engine.Load to load.
  • Throttle tracking: Tracks vp.input.Throttle across ticks. When throttle jumps 0→1 (below 0.2 to above 0.8), calls OnThrottleTipIn(throttle, rpm, engineLoad). When it drops 1→0, calls OnThrottleTipOut(rpm, engineLoad). The 0.2/0.8 hysteresis bands prevent noise at transition boundaries.
  • Detects gear changes, drives the EnginePitchOscillator (writing to shiftPitchOsc), and calls OnGearShift() to fire the DCT shift burble.

⚠️ If using a custom input script: You must call OnThrottleTipIn, OnThrottleTipOut, and OnGearShift at the appropriate moments, or the throttle body and DCT shift burble effects will never play.

EnginePitchOscillator

  • oscillationSpeed / oscillationDepth:

    Base speed and maximum amount of the pitch wobble.

  • rpmIncreaseThreshold / rpmDecreaseThreshold / revLimiterThreshold:

    RPM deltas that trigger the effect.

  • dampingFactor / loadInfluence / effectDelay:

    Fade-out rate, load sensitivity, and onset delay.

  • harmonicFrequency / harmonicAmplitude / gearChangeIntensityMultiplier:

    Secondary oscillation and gear-shift boost.

AudioGranulatorSimpleUI (Test Harness)

Standalone tester with sliders, keyboard control, and a configurable rev-limiter fuel-cut stutter. Works with both the New Input System and the Legacy Input Manager.

Common Pitfalls & Tuning Guide

When NOT to use the Deceleration Bank

The deceleration bank is optional. If you leave it empty, VNS automatically sets nonDecelerateAudiosMode = true and reuses the acceleration bank for both directions through the load crossover. Fill it only when you have genuine off-throttle recordings that sound distinctly different from the acceleration clips. Do not fill it with the same clips — that wastes audio sources and blurs the accel/decel distinction unnecessarily.

pairHysteresisRpm Tuning

This is the most frequently misconfigured field in the blend system. It creates a dead zone around each clip-pair boundary.

  • Too low (0–50): Clips flicker back and forth audibly near boundaries, especially at steady RPM.
  • Too high (>300): The blend lags behind the actual RPM, making the engine sound disconnected from throttle input.
  • Good starting point: Half the gap between adjacent clip rpmValues (e.g. 500 for 1000-RPM-spaced clips).

loadCrossoverPoint — What Value to Use

The default 0.18 works for most vehicles. It means the accel and decel banks blend 50/50 when engine load is 0.18.

  • Lower (0.05–0.12): Deceleration clips are used more aggressively. The engine switches to decel sounds even under light throttle. Suits vehicles with pronounced engine braking.
  • Higher (0.22–0.35): Acceleration clips dominate more of the load range. Only heavy off-throttle triggers decel sounds. Suits vehicles where decel is barely audible.

clipVolumeResponseTime — Smooth vs Snappy

0.05 is the recommended default. Values below 0.02 make crossfades sound granular and choppy. Values above 0.15 make the engine feel sluggish and unresponsive to throttle changes. This interacts with rpmResponseTime: if the engine feels "slow," check both values — a slow RPM response can mask a fast clip response and vice versa.

rpmdeviation and Edge Clips

rpmdeviation defines the fallback spacing when a clip has only one neighbour (the lowest-RPM and highest-RPM clips in each bank). Set it to roughly the average gap between your clips' rpmValues. If it is too small, the outermost clips blend abruptly (sharp edges). If it is too large, the blend zone extends far beyond where the clip was recorded, producing a washed-out, blurry sound at the extremes.

keepBankClipsPlaying — CPU vs Latency Tradeoff

When enabled (default), every clip loops continuously at zero volume when not active. This eliminates the ~10-50 ms latency of starting an AudioSource from cold, ensuring seamless transitions. The CPU cost is minimal (silent looping costs almost nothing). Disable only if you have 50+ vehicle instances and are seeing genuine audio-thread bottlenecks in the Profiler.

masterVolume vs maxVolumeAcc / maxVolumeDcc

These serve different purposes:

  • masterVolume: Scales everything — both banks, all clips, equally. Use this when the entire vehicle is too loud or too quiet.
  • maxVolumeAcc / maxVolumeDcc: Cap individual banks. If acceleration clips are overpowering but deceleration sounds fine, lower only maxVolumeAcc. Set to 0 for no cap. Values above 1.0 (up to 2.0) can boost a bank that was recorded too quietly.

autoBlip — When to Disable

The autoBlip system detects sharp RPM jumps (typically from downshifts) and momentarily forces the acceleration bank to full blend, creating a realistic throttle-blip sound. Disable it if:

  • You hear unexpected volume spikes during gear changes.
  • Your vehicle uses a CVT or electric drivetrain (no discrete gear changes).
  • You want a smoother, more subdued shift character without the sporty blip.

Cylinder Count and Blend Granularity

Higher cylinder counts produce more firing events per revolution, which shortens the raw pairHoldCycles hold time automatically. A V12 at 6000 RPM fires 600 events/second (a raw ~0.8 ms/cycle); an inline-4 at the same RPM fires only 200 events/second (a raw ~2.5 ms/cycle). Because the selector runs on the fixed-update tick, these raw durations are rounded up to whole Time.fixedDeltaTime ticks before being applied — so at the default pairHoldCycles the effective hold is one tick for every cylinder count, and the cylinder-dependent grading only becomes audible once pairHoldCycles is raised high enough that the raw duration spans multiple ticks (e.g. a low-RPM I4 reaching several ticks while a V12 still rounds to one). Match cylinderCount accurately to the simulated engine, and raise pairHoldCycles until the grain is audible.

Per-Clip Pitch Workflow: Start Broad, Then Narrow

The quick-start recipe (flat pitch curve, all clips near 1.0) neutralizes every tier first. Once the basic blend sounds right:

  1. Broad strokes: Edit the pitchCurve if everything is off (Tier 1).
  2. Bank-level: Use acPitchTrim / dcPitchTrim if one whole bank is off (Tier 2).
  3. Clip-level: Tweak individual loPitch/hiPitch values only as a last resort for that one clip that sounds out of place among its neighbours (Tier 3).

This prevents the common mistake of chasing clip-level pitch values in circles when the real problem is a global offset.

rpmValue Accuracy — The Foundation of the Pitch Model

The v1.9 RPM-ratio pitch formula uses engineRPM / clipRPM as its base. If your rpmValue is wrong by even 10%, the pitch will be off by 10% at that clip. Always set rpmValue to the exact RPM the clip was recorded at before tuning anything else.

Tools & Resources

Creating Seamless Looping Clips

Clean loops are essential for good results: