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
| Port | Type | Default |
|---|---|---|
| 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. | int | 0 |
| ValueThe target the spring chases. Any range works; smoothing follows whatever you feed it, and the first frame starts right at that value. | float | 0 |
| 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. | float | 0.5 |
| Rising CurveThe spring character while rising — Snappy and Bouncy overshoot, Smooth settles cleanly, Heavy crawls. Values outside the list fall back to Smooth. | int | 0 |
| Falling DurationThe same timing for when the value drops, so you can snap up and ease down. Never goes below 0.001 seconds. | float | 0.5 |
| Falling CurveThe spring character while falling. Values outside the list fall back to Smooth. | int | 0 |
Outputs
| Port | Type |
|---|---|
| Smoothed Value | float |
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:
| # | Name | Damping Ratio | Character | Description |
|---|---|---|---|---|
| 0 | Smooth | 1.0 | Critically damped | The 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. |
| 1 | Responsive | 0.7 | Slight overshoot | Reaches the target quickly with a small overshoot before settling. Feels quick and reactive. Good for UI responses. |
| 2 | Bouncy | 0.4 | Visible overshoot | Overshoots the target noticeably and oscillates briefly before settling. Creates a playful, elastic feel. |
| 3 | Heavy | 2.0 | Over-damped, sluggish | Approaches the target very slowly without overshoot. Feels weighty and deliberate, like moving through a thick medium. |
| 4 | Snappy | 0.25 | Strong overshoot | Reaches the target very fast with significant overshoot and several oscillations. Creates an energetic, springy feel. |
| 5 | Gentle | 1.5 | Over-damped, soft | Approaches 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 = 0Where:
xis 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.