Sound Byte Libs 0.5.1-121-g3358a44
C++ firmware library for audio applications on 32-bit ARM Cortex-M processors
Loading...
Searching...
No Matches
hybrid_friction.hpp
Go to the documentation of this file.
1// sbl/dsp/pm/hybrid_friction.hpp — The table's curve, its force scaled by the rosin's warmth (Physical modeling — primitive)
2//
3// Woodhouse 2003 §5: a friction curve whose whole force–velocity relation,
4// limit included, scales with μ(T). The TableFriction finds the force at the
5// weight warm rosin leaves it; the ThermalFriction keeps the temperature from
6// that force and the sliding speed. The scaling is applied when the weight is
7// set — once a block, by the bow that owns this — not every sample
8// (physical-modeling.md §5.5). Parked since the first calibration (AP-040:
9// permanent stick at C4 bare), kept as the third law so the choice stays a
10// type, not a branch.
11
12#ifndef SBL_DSP_PM_HYBRID_FRICTION_HPP_
13#define SBL_DSP_PM_HYBRID_FRICTION_HPP_
14
15#include <cmath>
16#include <cstdint>
17
22
23namespace sbl::dsp::pm {
24
26public:
27 /// @note All public methods are ISR-safe — bounded computation, no I/O.
28
29 /// The table read, and the cold limits the rosin warms.
30 void set_bow(const BowTable& bow) {
31 table_.set_bow(bow);
32 rosin_.set_limits(bow.limits, bow.slices);
33 }
34
35 /// Bow force across the family [0, 1]; the table sees it scaled by the
36 /// rosin's warmth as of now. Set once a block.
37 void set_force_su(float su) {
38 force_su_ = su < 0.0f ? 0.0f : (su > 1.0f ? 1.0f : su);
39 rosin_.set_force_su(force_su_);
40 table_.set_force_su(force_su_ * rosin_.mu_rel());
41 }
42
43 /// The rosin, for its parameters (ThermalFriction::set_rosin, set_fast_cooling).
44 ThermalFriction& rosin() { return rosin_; }
45 const ThermalFriction& rosin() const { return rosin_; }
46
47 /// One sample: relative velocity in, force out (wave units).
48 float process(float dv_free) {
49 const float force = table_.process(dv_free);
50 const float a = std::fabs(dv_free);
51 const float fa = std::fabs(force);
52 rosin_.advance(force, table_.sticking() ? 0.0f : a - fa);
53 return force;
54 }
55
56 bool sticking() const { return table_.sticking(); }
57 float limit() const { return table_.limit(); }
58 float temperature() const { return rosin_.temperature(); }
59
60 void reset() {
61 table_.reset();
62 rosin_.reset();
63 }
64
65 diagram::Ports describe(diagram::Graph& g, uint8_t group, const char* name = "friction (hybrid)") const {
66 return table_.describe(g, group, name);
67 }
68
69private:
70 TableFriction table_;
71 ThermalFriction rosin_;
72 float force_su_ = 1.0f;
73};
74
75static_assert(is_friction_law_v<HybridFriction>, "HybridFriction is a friction law (physical-modeling.md §4.5)");
76
77} // namespace sbl::dsp::pm
78
79#endif // SBL_DSP_PM_HYBRID_FRICTION_HPP_
const ThermalFriction & rosin() const
ThermalFriction & rosin()
The rosin, for its parameters (ThermalFriction::set_rosin, set_fast_cooling).
diagram::Ports describe(diagram::Graph &g, uint8_t group, const char *name="friction (hybrid)") const
void set_bow(const BowTable &bow)
The table read, and the cold limits the rosin warms.
float process(float dv_free)
One sample: relative velocity in, force out (wave units).
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).
float temperature() const
Contact temperature as a fraction of the range over which the rosin softens.
float mu_rel() const
Friction relative to cold, from the temperature: 1 cold down to mu_ratio hot.
void set_limits(const float *limits, uint8_t slices)
The cold static limit per force slice — the friction-curve bow's limits
void set_force_su(float su)
Bow force across the slices [0, 1]; the cold limit interpolates between them.
void advance(float force, float v_slip)
Advance the contact one sample from a force and sliding speed found elsewhere.
What a load, an exciter, a termination and a friction law provide (Physical modeling — cross-cutting)
A model's wiring, as data (AP-037)
Physical modeling: laws, bows, junctions, loads, resonators, strings (docs/conventions/physical-model...
Definition bow.hpp:31
The ports a component exposes after describing itself, so an owner can wire them.
Definition graph.hpp:130
One bow: a lute-solved family and the shape of its arrays.
const float * limits
static-friction limit per slice
A bow: friction solved against the string (Physical modeling — primitive)
A bow whose friction remembers: the thermal model (Physical modeling — primitive)