Math node

Smooth

Real-time spring-based value smoothing using damped harmonic oscillator physics. The Smooth node takes a rapidly changing or noisy input value and produces a smoothed version that transitions gracefully toward the target, with independent control over the rising (increasing) and falling (decreasing) behavior.

Inputs

PortTypeDefault
Time SourceWhere the clock comes from — Parent uses the app's running time, External adds a Time port you drive yourself. Values outside the list fall back to Parent.int0
ValueThe target the spring chases. Any range works; smoothing follows whatever you feed it, and the first frame starts right at that value.float0
Rising DurationHow long the spring takes to catch up while the value is climbing, in seconds. Never goes below 0.001; about 0.05 feels instant, 1 or more is a slow glide.float0.5
Rising CurveThe spring character while rising — Snappy and Bouncy overshoot, Smooth settles cleanly, Heavy crawls. Values outside the list fall back to Smooth.int0
Falling DurationThe same timing for when the value drops, so you can snap up and ease down. Never goes below 0.001 seconds.float0.5
Falling CurveThe spring character while falling. Values outside the list fall back to Smooth.int0

Outputs

PortType
Smoothed Valuefloat

Overview

The Smooth node implements the same spring physics model used by Apple's SwiftUI .spring(response:dampingFraction:) animation system. Instead of simple linear interpolation or exponential moving averages, it uses a full second-order damped harmonic oscillator. This produces natural-feeling motion with physically accurate momentum, overshoot, and settling behavior.

The node provides separate control over the rising and falling phases of the smoothed value. Each phase has its own Duration (how long the transition takes to settle) and Curve (the character of the spring, from critically damped to bouncy). This asymmetry is key for many real-time applications: for example, you may want a fast, snappy response when a value increases but a slow, gentle decay when it decreases.

The smoothing is frame-rate independent. It uses the exact analytical solution of the spring differential equation rather than numerical integration, which means the result is stable regardless of frame rate and will not exhibit the drift or instability that simpler smoothing methods can show at variable frame rates.

On the first frame after creation (or after a reset), the node initializes its internal state to match the current input value, avoiding an unwanted ramp-up from zero.

Curves

The curve selector controls the damping ratio of the spring, which determines how the value approaches its target. Six presets are available:

#NameDamping RatioCharacterDescription
0Smooth1.0Critically dampedThe fastest approach to the target without any overshoot. This is the default and matches the standard critically damped spring used throughout macOS and iOS system animations.
1Responsive0.7Slight overshootReaches the target quickly with a small overshoot before settling. Feels quick and reactive. Good for UI responses.
2Bouncy0.4Visible overshootOvershoots the target noticeably and oscillates briefly before settling. Creates a playful, elastic feel.
3Heavy2.0Over-damped, sluggishApproaches the target very slowly without overshoot. Feels weighty and deliberate, like moving through a thick medium.
4Snappy0.25Strong overshootReaches the target very fast with significant overshoot and several oscillations. Creates an energetic, springy feel.
5Gentle1.5Over-damped, softApproaches the target slowly without overshoot, but faster than Heavy. A soft, gradual arrival.

Understanding Damping Ratio

The damping ratio (zeta) is the key parameter of the spring physics:

  • zeta < 1 (under-damped): The spring overshoots the target and oscillates before settling. Lower values produce more overshoot and more oscillations. Responsive (0.7), Bouncy (0.4), and Snappy (0.25) are under-damped.
  • zeta = 1 (critically damped): The fastest possible approach to the target without any overshoot. This is the Smooth preset.
  • zeta > 1 (over-damped): The spring approaches the target without overshoot, but more slowly than critical damping. Higher values are slower. Heavy (2.0) and Gentle (1.5) are over-damped.

Time Sources

Parent (Default)

Uses GrafitState.shared.elapsedTime, which is the global time reference that Grafit maintains. This is synchronized with the application's frame clock and is the correct choice for most scenarios.

External

Reveals an additional Time input port. You provide your own time value in seconds. The node computes delta time by subtracting the previous frame's time from the current one. This is useful when:

  • You want to control the speed of smoothing by feeding a scaled time value.
  • You are working with a data source that has its own time reference.
  • You want to pause or reverse the smoothing by holding or decrementing the time value.

How It Works

Spring Physics

The node solves the damped harmonic oscillator equation analytically:

x'' + 2 * zeta * omega * x' + omega^2 * x = 0

Where:

  • x is the displacement from the target value.
  • x' is the velocity.
  • omega (natural frequency) = 2 * pi / Duration.
  • zeta (damping ratio) is determined by the selected Curve.

The analytical solution is computed exactly for the given time step, which means:

  • No numerical integration artifacts or energy drift.
  • Unconditionally stable for any frame rate or time step.
  • Identical behavior at 30fps, 60fps, 120fps, or any other rate.

Rising vs. Falling Selection

Each frame, the node checks whether the target (input Value) is above or below the current smoothed position. If the target is above, the Rising Duration and Rising Curve are used. If the target is below, the Falling Duration and Falling Curve are used. This check happens per-frame, so if the target oscillates, the node naturally alternates between rising and falling dynamics.

State Management

The node maintains per-instance state (current position, velocity, last time, initialization flag) keyed by the node's UUID. This state persists between frames to provide continuous smooth tracking. When a node is deleted, its state is cleaned up automatically.

Use Cases

  • Sensor data smoothing: Apply smooth filtering to noisy sensor inputs (EEG, accelerometer, temperature) while preserving the general trend. Use a short duration for fast-changing signals or a longer one for slow ambient measurements.
  • UI animation: Smooth parameter changes to create fluid animations. Use asymmetric rising/falling to make a light quickly brighten but slowly fade.
  • Audio-reactive visuals: Smooth the output of an FFT Peak Amplitude to create visuals that react to audio beats with a fast attack (short Rising Duration with Snappy curve) and slow decay (longer Falling Duration with Smooth curve).
  • Jitter reduction for MIDI/OSC: Smooth incoming MIDI CC or OSC float values to remove jitter from physical hardware controllers.
  • Camera motion: Smooth mouse or controller input to create smooth camera movements in a 3D scene. Use the Responsive or Bouncy curve for a cinematic feel.
  • Envelope follower: Create an amplitude envelope from an audio signal by smoothing the absolute value of the signal with fast attack (short Rising) and slow release (long Falling).

Practical Tips

  • Start with the default Smooth curve (critically damped, no overshoot) and a Duration of 0.5 seconds. Adjust from there based on how the smoothed value feels.
  • If the smoothed value seems to lag too far behind the input, reduce the Duration. If it is too jittery, increase it.
  • For responsive UI interactions, try Responsive (0.7 damping) with a Duration of 0.15-0.3 seconds. This gives a quick, natural feel with just a hint of spring.
  • The Bouncy and Snappy curves produce overshoot, which means the smoothed value will temporarily exceed the target before settling. This can be desirable for animation but problematic for parameters with strict bounds. Consider adding a Range node after the Smooth to clamp the output if needed.
  • Duration values below 0.001 seconds are clamped to 0.001 to prevent division by zero. Setting very small durations effectively disables smoothing (the output closely follows the input).
  • If the smoothed output ever becomes NaN or Infinity (due to extreme input values), the node automatically resets to the current input value and zeroes the velocity, preventing error propagation.
  • The Heavy curve (zeta = 2.0) is useful for values that should change very slowly and deliberately, like a slowly shifting background color or ambient lighting level.

Open Smooth in the interactive catalog →

Smooth is one of 381 nodes in Grafit Pro.

Free download. Every feature for 7 days, no card. Then €99.99 once — or keep playing your projects as a Player.

More Math nodes