12#ifndef SBL_DSP_PM_BOW_SET_HPP_
13#define SBL_DSP_PM_BOW_SET_HPP_
37 apply_select(select_su_);
40 uint8_t
count()
const {
return count_; }
46 apply_select(select_su_);
56 if (count_ == 0)
return 0.0f;
57 float force = a_.
process(dv_free);
59 const float other = b_.
process(dv_free);
60 force += blend_ * (other - force);
79 p.
add(
"table B", other.
in);
85 static constexpr float HALF_BLEND = 0.5f;
86 static constexpr uint8_t NO_TABLE = 0xFF;
88 void apply_select(
float select_su) {
89 if (tables_ ==
nullptr || count_ == 0)
return;
91 const float pos = select_su *
static_cast<float>(count_ - 1);
92 uint8_t a =
static_cast<uint8_t
>(pos);
93 if (count_ > 1 && a >= count_ - 1) a =
static_cast<uint8_t
>(count_ - 2);
94 blend_ = count_ > 1 ? pos -
static_cast<float>(a) : 0.0f;
103 const uint8_t b = count_ > 1 ?
static_cast<uint8_t
>(a + 1) : a;
113 const BowTable* tables_ =
nullptr;
115 uint8_t a_index_ = NO_TABLE;
116 uint8_t b_index_ = NO_TABLE;
117 float select_su_ = 0.0f;
121static_assert(is_friction_law_v<TableSet>,
"TableSet is a friction law (physical-modeling.md §4.5)");
156static_assert(is_exciter_v<BowSet>,
"BowSet is an Exciter (physical-modeling.md §4.2)");
A bow: a speed, a weight, and a friction law at a string's junction (Physical modeling — composition)
Clamping (Cross-cutting — Math)
A bow over a set of tables: velocity, pressure and select, all smoothed.
static constexpr float DEFAULT_SELECT_SU
void set_tables(const BowTable *tables, uint8_t count)
The tables this bow can be played with (TableSet::set_tables).
void set_select_su(float su)
Which table: crossfades across the set. Smoothed.
static constexpr float SMOOTH_MS
void advance(uint16_t n)
A block's worth of port movement.
TableSet & law()
The law, for its own parameters (a table, a rosin).
float process(float dv_free)
One sample: relative velocity in, injection force out.
float limit() const
Static-friction limit at the current bow force — where the string releases.
void set_bow(const float *family, const float *limits, uint8_t slices, uint16_t size, uint16_t stride, float dv_max=1.0f)
Install a bow: a lute-solved family and its per-slice limits.
bool sticking() const
True while the string travels with the bow.
void set_force_su(float su)
Bow force across the family [0, 1]; crossfades adjacent slices.
diagram::Ports describe(diagram::Graph &g, uint8_t group, const char *name="bow friction") const
One Junction node: the friction nonlinearity. Never called from audio code (AP-037).
bool sticking() const
The table you hear — the one with the larger crossfade weight — holds the string.
void set_tables(const BowTable *tables, uint8_t count)
The tables, in the order the select sweeps them. The array must outlive the set.
void set_select_su(float su)
Which table: 0 the first, 1 the last, a crossfade between neighbours. Applied at once.
float process(float dv_free)
One sample: relative velocity in, the crossfaded force out (wave units).
const BowTable * tables() const
static constexpr uint8_t MAX_TABLES
void set_force_su(float su)
diagram::Ports describe(diagram::Graph &g, uint8_t group, const char *name="friction") const
One junction per running table. in/out is the first; the second is the named port "table B".
void set(float target)
The port's setter stores here; nothing moves until advance().
void set_time_ms(float ms, float rate_hz)
Settling time, at the rate the smoother is advanced at (per sample here).
void reset()
Snap to the target: what reset() does, so ports start where they were set.
float advance(uint16_t n)
Advance by a block: the smoothed value to apply for this block.
What a load, an exciter, a termination and a friction law provide (Physical modeling — cross-cutting)
A model's wiring, as data (AP-037)
constexpr float clamp01(float x)
x held to [0, 1]; NaN → 0.
Physical modeling: laws, bows, junctions, loads, resonators, strings (docs/conventions/physical-model...
The ports a component exposes after describing itself, so an owner can wire them.
void add(const char *name, uint8_t node)
Add a named port; a ninth is refused and find() answers NO_NODE for it.
uint8_t in
where a wave enters (the junction, the load)
One bow: a lute-solved family and the shape of its arrays.
A bow: friction solved against the string (Physical modeling — primitive)