Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
pulp::signal::CartesianWalkT< SampleType > Class Template Reference

The 2-D (Cartesian) sequencer. More...

#include <cartesian_walk.hpp>

Classes

struct  Frame

Public Member Functions

void prepare (double sample_rate)
void set_size (int w, int h)
int width () const
int height () const
void set_value (int x, int y, SampleType volts)
SampleType value (int x, int y) const
void set_access (CartesianAccess mode)
CartesianAccess access () const
void set_offsets (int x_cv, int y_cv)
 Integer CV offsets added to each axis counter.
void apply_reset_edge ()
 Verb 2: both counters home, gate low, output CV held.
void reset ()
int x () const
int y () const
int cell_x () const
int cell_y () const
bool gate () const
SampleType cv () const
Frame process (bool run_high, bool reset_edge, bool x_clock_edge, bool y_clock_edge)

Static Public Member Functions

static constexpr int latency_samples ()

Static Public Attributes

static constexpr int kMaxDim = 8
 Grid cap.
static constexpr int kDefaultDim = 4
static constexpr int kMaxOffset = 1000000
 Bound on an axis offset.

Detailed Description

template<typename SampleType = float>
class pulp::signal::CartesianWalkT< SampleType >

The 2-D (Cartesian) sequencer.

(lineage — informative) Make Noise René (2009) is documented as "the world's first Cartesian sequencer for music synthesizers": sixteen locations in a 4×4 grid with the X and Y axes clocked independently, plus CV offset inputs added to each axis counter — "a control signal at the X-CV input… is added to the number generated by the X-Axis counter to create the X coordinate" [Make Noise, René Manual]. Cited for concept and topology only; the 8×8 cap is ours.

Two independent clocks over a grid is a genuinely different topology from a linear sequencer, and the reason is arithmetic: clock only X on a 4×4 and you loop four values; add a Y clock at four times the period and the sequence is sixteen; make the two periods coprime and the walk visits cells in an order with a super-cycle of lcm of the two — long sequences out of two cheap dividers and no memory.

The gate is a one-sample trigger, not a level, and fires on any clock edge that changes the output coordinate (a simultaneous X and Y edge is one gate). This block has no gate modes to give a gate a length, so inventing one would be inventing a tempo; a caller who wants a gate of a stated length puts a GateGenT (kit) downstream, which is also where a gate length belongs.

USE. Evolving pads — slow Y, fast X: the melody re-colours row by row. Two-hand performance — drive X-clock and Y-clock from two ClockDividerT (kit) taps at different divisions for hands-free polyrhythm. Chord tables — a chord's notes across each row: walk X for arpeggios, tap Y to change chord, with a QuantizeScaleT downstream to keep arbitrary grid values in key.

RT contract: as the header.

Member Function Documentation

◆ access()

template<typename SampleType = float>
CartesianAccess pulp::signal::CartesianWalkT< SampleType >::access ( ) const
inline

◆ apply_reset_edge()

template<typename SampleType = float>
void pulp::signal::CartesianWalkT< SampleType >::apply_reset_edge ( )
inline

Verb 2: both counters home, gate low, output CV held.

The next clock lands on the home cell rather than one past it, so "reset then run" plays from the top on both sequencers in this header.

◆ cell_x()

template<typename SampleType = float>
int pulp::signal::CartesianWalkT< SampleType >::cell_x ( ) const
inline

◆ cell_y()

template<typename SampleType = float>
int pulp::signal::CartesianWalkT< SampleType >::cell_y ( ) const
inline

◆ cv()

template<typename SampleType = float>
SampleType pulp::signal::CartesianWalkT< SampleType >::cv ( ) const
inline

◆ gate()

template<typename SampleType = float>
bool pulp::signal::CartesianWalkT< SampleType >::gate ( ) const
inline

◆ height()

template<typename SampleType = float>
int pulp::signal::CartesianWalkT< SampleType >::height ( ) const
inline

◆ latency_samples()

template<typename SampleType = float>
constexpr int pulp::signal::CartesianWalkT< SampleType >::latency_samples ( )
inlinestaticconstexpr

◆ prepare()

template<typename SampleType = float>
void pulp::signal::CartesianWalkT< SampleType >::prepare ( double sample_rate)
inline

◆ process()

template<typename SampleType = float>
Frame pulp::signal::CartesianWalkT< SampleType >::process ( bool run_high,
bool reset_edge,
bool x_clock_edge,
bool y_clock_edge )
inline

◆ reset()

template<typename SampleType = float>
void pulp::signal::CartesianWalkT< SampleType >::reset ( )
inline

◆ set_access()

template<typename SampleType = float>
void pulp::signal::CartesianWalkT< SampleType >::set_access ( CartesianAccess mode)
inline

◆ set_offsets()

template<typename SampleType = float>
void pulp::signal::CartesianWalkT< SampleType >::set_offsets ( int x_cv,
int y_cv )
inline

Integer CV offsets added to each axis counter.

Read at clock time only, never continuously — a continuously-read offset would zipper the output between cells whenever the offset crossed an integer.

◆ set_size()

template<typename SampleType = float>
void pulp::signal::CartesianWalkT< SampleType >::set_size ( int w,
int h )
inline

◆ set_value()

template<typename SampleType = float>
void pulp::signal::CartesianWalkT< SampleType >::set_value ( int x,
int y,
SampleType volts )
inline

◆ value()

template<typename SampleType = float>
SampleType pulp::signal::CartesianWalkT< SampleType >::value ( int x,
int y ) const
inline

◆ width()

template<typename SampleType = float>
int pulp::signal::CartesianWalkT< SampleType >::width ( ) const
inline

◆ x()

template<typename SampleType = float>
int pulp::signal::CartesianWalkT< SampleType >::x ( ) const
inline

◆ y()

template<typename SampleType = float>
int pulp::signal::CartesianWalkT< SampleType >::y ( ) const
inline

Member Data Documentation

◆ kDefaultDim

template<typename SampleType = float>
int pulp::signal::CartesianWalkT< SampleType >::kDefaultDim = 4
staticconstexpr

◆ kMaxDim

template<typename SampleType = float>
int pulp::signal::CartesianWalkT< SampleType >::kMaxDim = 8
staticconstexpr

Grid cap.

4×4 is the cited hardware; 8×8 is ours. [design parameter] default 4×4, range 1×1 .. 8×8.

◆ kMaxOffset

template<typename SampleType = float>
int pulp::signal::CartesianWalkT< SampleType >::kMaxOffset = 1000000
staticconstexpr

Bound on an axis offset.

Any offset is equivalent to itself modulo the axis length, so a bound loses nothing musically; it exists so counter + offset cannot overflow on a runaway CV. [design parameter] default ±1,000,000, range ±(kMaxDim) .. ±2^24.


The documentation for this class was generated from the following file: