Overview
Vehicle Noise Synthesizer (VNS) is a Unity granulator-style engine
audio component (package menu:
ATG Audio / Vehicle Noise Synthesizer). It blends real
recorded clips at known RPM values using a constant-power
neighbour-pair crossfade, driven by rpm and
load each physics fixed step.
The active pair is selected with RPM hysteresis and combustion-cycle
hold (tick-quantized). Per-clip pitch uses an RPM-ratio model with
optional stretch soft-clamp. Non-WebGL builds batch every active
instance in a Burst IJobParallelFor once per
Time.fixedTimeAsDouble step and complete the same tick.
WebGL runs the same algorithm on the main thread in
ProcessAudioFrame.
Key Features (v1.9)
-
RPM-ratio pitch:
(pitchRpm / clip.referenceRpm) × finalPitch, thenloPitch/hiPitchmultipliers, bank trim, and clip pitch offset. Final pitch is clamped to0.01…3(Unity clip pitch limit). - maxPitchRatioBeyondPair (default 1.2): soft-clamps the RPM used for pitch and can escape a pair hold when live RPM leaves the pair window far enough.
- Burst batch path (non-WebGL) and WebGL main-thread path with matching pair/pitch logic.
-
Immediate spectral load via raw
filterLoadfor LPF/HPF/distortion (and reverb load term). Bank volume and acc/dec blend still usesmoothedLoad. -
Constant-power crossfade between the two active
neighbour clips (
cos² + sin² = 1). -
Three-tier pitch control:
pitchCurve, bankacPitchTrim/dcPitchTrim, per-cliploPitch/hiPitch. -
Event-driven one-shots:
OnThrottleTipIn,OnThrottleTipOut,OnGearShift(throttle body + DCT shift burble). - Exhaust burble (load window + optional RPM-drop path) and redline one-shot loop. Engine lugging is not present in this package.
- Editor Simple / Advanced inspector mode (EditorPrefs only; does not change runtime).
-
NWH VP2 sample:
AudioGranulatorNWHVehiclePhysics2with optionaldisableNwhEngineRunningAudioandEnginePitchOscillatorwritingshiftPitchOsc.
What's New through v1.9 v1.9
This page documents the current public package behavior.
Pitch & neighbour pairs
-
Per-clip pitch uses
loPitch/hiPitchmultipliers (default 1.0, range 0.01-3), not absolute 0.5-2.5 clamps. -
Final layer pitch is clamped to
0.01f…3f(matches UnityAudioSource.pitchfor clips). -
maxPitchRatioBeyondPair(default 1.2, range 1-2): soft-clamps the RPM used for pitch into the active pair window ±stretch, and can escape pair hold when RPM leaves that window. -
Pair hold (
pairHoldCycles, default 0.5) is quantized up to wholefixedDeltaTimeticks. Switch jumps to the ideal neighbour pair when hysteresis or stretch-escape allows (no one-step crawl in this package). -
Removed / absent APIs from older docs:
rpmPitchTracking, absolute min/max pitch fields as clamps, commented-outidlePitch, engine lugging (not present).
Burst / WebGL & GC
-
Non-WebGL: one Burst batch per fixed step via
fixedTimeAsDouble, same-tick complete, rebuild fallthrough, dispose on last unregister, dirty curve uploads. - WebGL:
ProcessAudioFrameon the main thread. -
Nested
Mathf.Maxon hot RPM paths (avoids 3-argparamsalloc). CachedWaitForFixedUpdate.
Load → spectrum (v1.9)
-
Raw
filterLoaddrives LPF curve, HPF load scale, distortion load term, and reverb load term. -
LPF/HPF cutoffs and Q (and distortion level) are applied
immediately each fixed tick (legacy
filterLPFSlewHz/filterHPFSlewHzdo not slew bank cutoffs). -
Bank volume, acc/dec blend, and pitch load trim still use
smoothedLoad/loadResponseTime.
Events, one-shots, editor, NWH sample
-
OnThrottleTipIn/OnThrottleTipOut/OnGearShiftare the only triggers for throttle-body and DCT shift effects (no internal load-delta auto-detect). -
Burble uses
burbleLoadLowThreshold+burbleLoadHighThreshold(load window) and optional RPM-drop path. -
Redline one-shot loop while RPM stays in
redlineMinRPM…redlineMaxRPM(0 max = usemaxRpm). -
Editor toolbar Simple | Advanced (
EditorPrefskeyVNS_InspectorAdvancedMode). -
NWH sample:
disableNwhEngineRunningAudio(default true); oscillator usesfixedDeltaTime, seeds baseline RPM, caps gear intensity at 1.0 (norevLimiterThresholdmultiplier in current sample).
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.
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.
pitchCurve (AnimationCurve)Section: Global Curves
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.
acPitchTrim / dcPitchTrimSection: Tuning
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.
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.
Runtime pitch (from source) for an active layer, simplified:
-
finalPitch = max(0.01, pitchCurve(normRpm) + loadEffectivenessOnPitch × smoothedLoad + shiftPitchOsc) -
pitchRpmis live RPM soft-clamped into the active pair window usingmaxPitchRatioBeyondPair. -
ratioPitch = (pitchRpm / max(1, clip.referenceRpm)) × finalPitch -
progress = Clamp01((pitchRpm - idleRpm) / max(1, maxRpm - idleRpm)) -
pitch = Clamp(ratioPitch × Lerp(loPitch, hiPitch, progress) + bankPitchTrim + pitchOffset, 0.01, 3)
Lo and Hi interpolate as RPM progresses through idle…max. The inspector Lo/Hi bar uses the real clip pitch scale 0.01…3 (not 0…4).
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.
-
Set the
pitchCurve(Global Curves) to a flat constant 1.0 (the default). -
Set every clip's Lo and
Hi values to 1.0 (neutral).
With correct
rpmValueand 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. -
Set
acPitchTrimanddcPitchTrim(Tuning) to 0. -
Before anything else, assign the correct
rpmValueto every clip in the banks. This is the single most important data point - the entire RPM-ratio model depends on it. -
Enable
debug, then sweepdebugrpmacross the range and listen. Adjust by ear, starting from the broadest tier that helps.
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.MathematicsandUnity.Burstpackages (install via Package Manager). - NWH Vehicle Physics 2 (included in the ATG Simulator project).
Adding VNS to a Vehicle
-
Add the
VehicleNoiseSynthesizercomponent to your vehicle's audio root GameObject (menu: "ATG Audio / Vehicle Noise Synthesizer"). -
Assign an
AudioSourcetoaudioSourceTemplate. The pooling system copies its 3D settings for every generated source. -
Populate
acceleratingSoundswith your clips. For each, set theAudioClipand therpmValueit was recorded at. TherpmValuefield is a plain integer text box in v1.9f - type exact values. -
Set each clip's
loPitchandhiPitchmultipliers (default 1.0 = neutral). Watch the active-pair volume graph confirm your blends. -
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.
Full Parameter Reference
Every public field on VehicleNoiseSynthesizer, grouped
as in the inspector. Defaults and ranges match
VehicleNoiseSynthesizer.cs (v1.9 source).
Debug Controls
-
debug(bool, default false):Enable to manually control RPM and load values for testing. When true, the fixed-step loop uses
debugrpm/debugloadinstead of_rpm/_load. -
enablePairSelectorDiagnostics(bool, default false):Pair-selector diagnostic logger (hold duration, hysteresis, switches once per second).
-
debugrpm(float, 100-9000, default 800):Test RPM value when debug mode is enabled.
-
debugload(float, 0-1, default 1):Test engine load when debug is enabled. Also becomes the raw
filterLoadused by LPF/HPF/distortion. -
enableDiagnosticLogger(bool, default false):Enable the 1-second diagnostic logger.
-
enableBurbleDiagnostics(bool, default false):Enable burble gate diagnostics in 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, in combustion-event cycles. Raw duration is rounded up to whole
fixedDeltaTimeticks.0disables the hold (pairHysteresisRpmstill applies). High values can cause pitch stretch if RPM races ahead of the held pair. -
maxPitchRatioBeyondPair(float, 1-2, default 1.2):How far live RPM may go past the active pair outer reference before pitch is soft-clamped and hold can escape (1.2 = ±20%). Prevents chipmunk pitch during pair catch-up.
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
-
acceleratingSounds(List<EngineAudioClipData>:List of audio clips for engine acceleration.
-
deceleratingSoundsList<EngineAudioClipData>:Optional list of audio clips for engine deceleration. If empty or null after strip, runtime sets
nonDecelerateAudiosModeand reuses the acceleration bank for both directions.
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-3, default 1) Pitch Tier 3:Low-end pitch multiplier at minimum RPM (1 = neutral).
[Range(0.01f, 3f)]matches runtime pitch clamp. -
hiPitch(float, 0.01-3, default 1) Pitch Tier 3:High-end pitch multiplier at maximum RPM (1 = neutral).
[Range(0.01f, 3f)]. -
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
useSharedMixerReverbis 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. Target uses
filterLoad; level is assigned immediately each fixed tick. -
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. Cutoff snaps with filterLoad each fixed tick.
-
filterLPFSlewHz(float, 100-5000, default 800):Legacy. LPF cutoff snaps with load each tick; not used for bank cutoff.
-
filterHPFSlewHz(float, 10-500, default 180):Legacy. HPF cutoff snaps with load each tick; not used for bank cutoff.
-
filterReverbSlewDbS(float, 500-5000, default 2500):Max dB/s the reverb level may move.
-
filterParamSlewRate(float, 0.1-5, default 1):Slew multiplier for MoveTowards on chorus. LPF/HPF/distortion are snapped.
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. Runtime:
intakeRoarVolume × throttleValue × Max(0.5, engineLoad). -
throttleFlutterVolume(float, 0-1, default 0.5):Master volume for throttle flutter clips.
-
throttleBodyPitchVariation(float, 0-0.3, default 0.05):Random ±pitch variation applied to each throttle body one-shot.
-
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.
Exhaust Burble & DCT Shift Burble
-
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. Eligible when RPM ≥ min and load is in [
burbleLoadLowThreshold,burbleLoadHighThreshold) or RPM drop ≥burbleRPMDropThreshold(if > 0). UsessmoothedLoadfor the load gate. -
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):Looping exhaust overlay fired only via
OnGearShift(). Pitch clamped to 0.01-3. After a short grace period, a raw-load tip-in can start fade-out.
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:
enableThrottleBodymust be true;_isOnmust be true (engine running); cooldown must be elapsed. -
Volume:
intakeRoarVolume × throttleValue × Max(0.5, engineLoad)(fromOnThrottleTipInsource). Engine must be on (isOn). - 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:
enableThrottleBodymust be true;_isOnmust 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:
enableDctShiftBurblemust be true;dctShiftBurbleSoundmust 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/onStopevents to callTurnOn()/TurnOff(). -
Each
FixedUpdatepassesengine.OutputRPMtorpmandengine.Loadtoload. -
Throttle tracking: Tracks
vp.input.Throttleacross ticks. When throttle jumps 0→1 (below 0.2 to above 0.8), callsOnThrottleTipIn(throttle, rpm, engineLoad). When it drops 1→0, callsOnThrottleTipOut(rpm, engineLoad). The 0.2/0.8 hysteresis bands prevent noise at transition boundaries. -
Detects gear changes, drives the
EnginePitchOscillator (writing to
shiftPitchOsc), and callsOnGearShift()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 (sample defaults)
-
oscillationSpeed(8) /oscillationDepth(0.15) -
rpmIncreaseThreshold(150) /rpmDecreaseThreshold(80) - norevLimiterThresholdin current sample -
dampingFactor(5) /loadInfluence(0.3) /effectDelay(0.05) -
harmonicFrequency(2) /harmonicAmplitude(0.3) /gearChangeIntensityMultiplier(1.0, range 0-1, capped) -
ProcessPitchseeds the first RPM sample (no false burst from 0→current), uses the passeddeltaTime(sample usesfixedDeltaTime).
Optional disableNwhEngineRunningAudio (default
true) disables NWH
engineRunningComponent so it does not double with VNS
continuous banks.
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.
filterLoad vs smoothedLoad
Raw load (debug ? debugload : _load, packed as
filterLoad) drives LPF/HPF/distortion targets and is
applied the same fixed tick. smoothedLoad (via
loadResponseTime) still drives bank volumes, acc/dec
blend, pitch load trim, and burble load gates. Do not expect bank
volume to snap with the same immediacy as LPF open/close.
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 onlymaxVolumeAcc. 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:
-
Broad strokes: Edit the
pitchCurveif everything is off (Tier 1). -
Bank-level: Use
acPitchTrim/dcPitchTrimif one whole bank is off (Tier 2). -
Clip-level: Tweak individual
loPitch/hiPitchvalues 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:
- Audacity (free): Create Looping Sound Effects for Free
- Audacity (advanced): Seamlessly Loop Any Audio
- Online looper: Drumbot Online Audio Looper
- Pitch correction (paid): Pitch Correcting Engine Noises