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
contracts.hpp
Go to the documentation of this file.
1// sbl/dsp/pm/contracts.hpp — What a load, an exciter, a termination and a friction law provide (Physical modeling — cross-cutting)
2//
3// The contracts the physical-modeling components compose against, as
4// compile-time checks (docs/conventions/physical-modeling.md §4). A consumer
5// asserts the contract on its template parameter the way hw/validation/
6// checks a driver, so a type that is missing a member fails at the assert
7// with the contract's name rather than deep inside a call.
8//
9// static_assert(pm::is_load_v<Load>, "LoadJunction needs a Load");
10//
11// Load admittance(), history(), commit(force), energy(), reset()
12// Exciter excite(const JunctionState&), advance(n), energy(), reset()
13// Termination reflect(arriving), energy(), reset()
14// FrictionLaw set_force_su(su), process(dv_free), sticking(), limit(), reset()
15// Described describe(graph, group[, name]) — the diagram obligation, checked
16// beside the physics contracts rather than inside them (RPT-036)
17//
18// The junction state is what a guide reports at an excitation point: the
19// velocity arriving there, the point's displacement, and the guide's wave
20// impedance. Every exciter is handed all three, whatever law it runs, so
21// energy can pass both ways at the point (Michael, 2026-09-17: bidirectional
22// junction-point energy transfer). The exciter returns a force; the guide
23// converts it to a wave with its impedance.
24//
25// Friction laws speak in wave units: the force they return is F / 2Z, the
26// velocity a string of impedance Z would take from it. A junction that knows
27// Z converts. A law solved offline (a lute table) is solved against a string's
28// line and is only valid there; a Coulomb law (the thermal one) exposes its
29// limit and can be solved against any line (AP-041 Phase 6).
30
31#ifndef SBL_DSP_PM_CONTRACTS_HPP_
32#define SBL_DSP_PM_CONTRACTS_HPP_
33
34#include <cstdint>
35#include <type_traits>
36#include <utility>
37
39
40namespace sbl::dsp::pm {
41
42/// What the guide reports at an excitation point, each sample.
44 float velocity; ///< the velocity arriving at the point, before this sample's injection
45 float displacement; ///< the point's displacement, integrated from its velocity (wave units × samples)
46 float impedance; ///< the guide's wave impedance Z
47};
48
49namespace detail {
50
51template<typename T>
52using returns_float = std::is_same<std::decay_t<T>, float>;
53
54template<typename T, typename = void>
55struct has_energy_reset : std::false_type {};
56template<typename T>
57struct has_energy_reset<T, std::void_t<
58 std::enable_if_t<returns_float<decltype(std::declval<const T&>().energy())>::value>,
59 decltype(std::declval<T&>().reset())>> : std::true_type {};
60
61} // namespace detail
62
63// ─── Load ────────────────────────────────────────────────────────────
64
65template<typename T, typename = void>
66struct is_load : std::false_type {};
67template<typename T>
68struct is_load<T, std::void_t<
69 std::enable_if_t<detail::returns_float<decltype(std::declval<const T&>().admittance())>::value>,
70 std::enable_if_t<detail::returns_float<decltype(std::declval<const T&>().history())>::value>,
71 std::enable_if_t<detail::returns_float<decltype(std::declval<T&>().commit(0.0f))>::value>,
72 std::enable_if_t<detail::has_energy_reset<T>::value>>> : std::true_type {};
73template<typename T>
74inline constexpr bool is_load_v = is_load<T>::value;
75
76// ─── Exciter ─────────────────────────────────────────────────────────
77
78template<typename T, typename = void>
79struct is_exciter : std::false_type {};
80template<typename T>
81struct is_exciter<T, std::void_t<
82 std::enable_if_t<detail::returns_float<decltype(std::declval<T&>().excite(std::declval<const JunctionState&>()))>::value>,
83 decltype(std::declval<T&>().advance(uint16_t{})),
84 std::enable_if_t<detail::has_energy_reset<T>::value>>> : std::true_type {};
85template<typename T>
86inline constexpr bool is_exciter_v = is_exciter<T>::value;
87
88// ─── Termination ─────────────────────────────────────────────────────
89
90template<typename T, typename = void>
91struct is_termination : std::false_type {};
92template<typename T>
93struct is_termination<T, std::void_t<
94 std::enable_if_t<detail::returns_float<decltype(std::declval<T&>().reflect(0.0f))>::value>,
95 std::enable_if_t<detail::has_energy_reset<T>::value>>> : std::true_type {};
96template<typename T>
98
99// ─── Friction law ────────────────────────────────────────────────────
100
101template<typename T, typename = void>
102struct is_friction_law : std::false_type {};
103template<typename T>
104struct is_friction_law<T, std::void_t<
105 decltype(std::declval<T&>().set_force_su(0.0f)),
106 std::enable_if_t<detail::returns_float<decltype(std::declval<T&>().process(0.0f))>::value>,
107 std::enable_if_t<std::is_same<decltype(std::declval<const T&>().sticking()), bool>::value>,
108 std::enable_if_t<detail::returns_float<decltype(std::declval<const T&>().limit())>::value>,
109 decltype(std::declval<T&>().reset())>> : std::true_type {};
110template<typename T>
112
113// ─── Described ───────────────────────────────────────────────────────
114
115template<typename T, typename = void>
116struct is_described : std::false_type {};
117template<typename T>
118struct is_described<T, std::void_t<
119 std::enable_if_t<std::is_same<
120 decltype(std::declval<const T&>().describe(std::declval<diagram::Graph&>(), uint8_t{})),
121 diagram::Ports>::value>>> : std::true_type {};
122template<typename T>
124
125// ─── Waveguide callables ─────────────────────────────────────────────
126
127template<typename F>
128inline constexpr bool is_wave_callable_v = std::is_invocable_r_v<float, F, float>;
129
130} // namespace sbl::dsp::pm
131
132#endif // SBL_DSP_PM_CONTRACTS_HPP_
A model's wiring, as data (AP-037)
std::is_same< std::decay_t< T >, float > returns_float
Definition contracts.hpp:52
Physical modeling: laws, bows, junctions, loads, resonators, strings (docs/conventions/physical-model...
Definition bow.hpp:31
constexpr bool is_termination_v
Definition contracts.hpp:97
constexpr bool is_load_v
Definition contracts.hpp:74
constexpr bool is_described_v
constexpr bool is_exciter_v
Definition contracts.hpp:86
constexpr bool is_wave_callable_v
constexpr bool is_friction_law_v
What the guide reports at an excitation point, each sample.
Definition contracts.hpp:43
float displacement
the point's displacement, integrated from its velocity (wave units × samples)
Definition contracts.hpp:45
float impedance
the guide's wave impedance Z
Definition contracts.hpp:46
float velocity
the velocity arriving at the point, before this sample's injection
Definition contracts.hpp:44