Skip to content

Step Sequencer

Tier: Core | ComponentType: 21 | Params: 4

16-step discrete modulation source with direction control, glide smoothing, and 15 pattern presets.

Overview

StepSequencer is a patterned modulation source that cycles through a 16-step pattern of semitone values at a configurable rate. Each step holds a float value (typically a semitone offset), and the sequencer advances through the pattern at a rate determined by the Step Length parameter. The output is the current step's value, optionally smoothed by a Glide parameter that creates portamento-like transitions between steps.

Four Direction modes control traversal: Forward steps through the pattern sequentially, Reverse walks backward, PingPong bounces at the boundaries, and Random selects steps uniformly via xorshift32 PRNG. The step count can be reduced from the full 16 to create shorter loops.

15 pattern presets cover common musical use cases:

  • Pitch presets (semitone values): OctaveUp, OctaveDown, FifthUp, Triad, PowerChord, Chromatic4, Pentatonic, WholeSteps, ThermaeClassic
  • Gate presets (0/1 values): Gate4, Gate3, Euclidean5_8
  • Contour presets: Accelerando (ramp), RandomEach (per-step random), RandomHold (held random blocks)

Custom patterns are loaded via setPattern(values, count). In chain mode, the sequencer modulates the input signal like ChaosAttractor — it is a modulation source, not an audio effect.

File Locations

Path
Header Sources/FolioDSP/include/FolioDSP/Core/StepSequencer.h
Implementation Sources/FolioDSP/src/Core/StepSequencer.cpp
Tests Tests/FolioDSPTests/StepSequencerTests.swift
Bridge Sources/FolioDSPBridge/src/FolioDSPBridge.mm (StepSequencerBridge)

Parameters

Index Name Description Min Max Default Min Default Max Default Unit
0 Steps Number of active steps 1.0 16.0 1.0 16.0 8.0
1 Step Length Duration of each step 1.0 44100.0 50.0 2000.0 200.0 ms
2 Glide Smoothing between steps (0% = instant, 100% = full step length) 0.0 100.0 0.0 100.0 0.0 %
3 Direction Step direction (0=Forward, 1=Reverse, 2=PingPong, 3=Random) 0.0 3.0 0.0 3.0 0.0

Processing Algorithm

The process() function executes once per sample. It has no audio input — it generates a modulation signal.

1. Step Duration

The step length in milliseconds is converted to samples:

\[S = \frac{\text{stepLength}_{\text{ms}}}{1000} \times f_s\]

2. Step Advance

A per-sample counter increments. When it reaches the step duration, the sequencer advances:

\[\text{counter} \leftarrow \text{counter} + 1\]
\[\text{if } \text{counter} \geq S: \text{advance step, reset counter}\]

3. Direction Logic

The step index advances according to the selected direction mode:

Forward:

\[\text{step} = (\text{step} + 1) \bmod N\]

Reverse:

\[\text{step} = (\text{step} - 1 + N) \bmod N\]

PingPong:

\[\text{step} \leftarrow \text{step} + \text{dir}, \quad \text{dir} \in \{-1, +1\}\]
\[\text{if step} \geq N-1: \text{dir} = -1; \quad \text{if step} \leq 0: \text{dir} = +1\]

Random:

\[\text{step} = \text{xorshift32}() \bmod N\]

4. Target Value

The target value is read from the current position in the pattern array:

\[\text{target} = \text{pattern}[\text{step} \bmod N]\]

5. Glide Smoothing

When glide is non-zero, a one-pole lowpass filter smooths the transition between step values. The glide time is a percentage of the step length:

\[T_{\text{glide}} = \frac{\text{glide\%}}{100} \times S\]
\[\alpha = \frac{1}{T_{\text{glide}}}\]
\[y[n] = y[n-1] + \alpha \cdot (\text{target} - y[n-1])\]

When glide is zero, the output snaps instantly to the target value.

6. Output

The smoothed (or unsmoothed) value is returned as the modulation output.

Core Equations

\[S = \text{stepLength}_{\text{ms}} \times f_s / 1000\]
\[\text{target} = \text{pattern}[\text{step}]\]
\[y[n] = y[n-1] + \frac{1}{T_{\text{glide}}} \cdot (\text{target} - y[n-1])\]

Snapshot Fields

Field Type Range Unit Description
Current Step Float 0–15 Index of the currently active step
Value Float -24–24 st Current output value (smoothed)
Step Length Float 1–44100 ms Current step duration
Glide Float 0–100 % Current glide amount
Step Progress Float 0–1 Progress through the current step (counter/S)
Direction Uint8 0–3 Current direction mode
Num Steps Float 1–16 Number of active steps
Pattern Float[16] -24–24 st Full 16-step pattern values

Implementation Notes

  • Step counter uses floating-point accumulation (stepCounter_ += 1.0f) and subtracts samplesPerStep on advance, preserving fractional timing for accurate long-term phase.
  • Pattern values are stored in a plain C array (float pattern_[16]), not atomic. Patterns should be set from the main thread only — the audio thread reads directly. This is safe because pattern updates are infrequent and atomic consistency per-element is not required.
  • xorshift32 PRNG for random direction provides fast, deterministic pseudo-random step selection without system calls.
  • Preset patterns are constructed in stack-local arrays inside setPresetPattern() and then copied via setPattern(). The random presets (RandomEach, RandomHold) use fixed seeds for reproducibility.
  • Semitone values in pitch presets use standard semitone intervals: 7 = perfect fifth, 12 = octave, 4 = major third. The ThermaeClassic preset references the Chase Bliss Thermae pitch-shifting delay pedal pattern.
  • All parameters use std::atomic<float> (or std::atomic<int>) for lock-free thread safety.
  • Snapshot emission is decimated to ~60 fps (every 735 samples at 44.1 kHz).

Equation Summary

y = pattern[step] + glide smooth