91 if (
empty())
return 1.0f;
93 const std::size_t base =
static_cast<std::size_t
>(mode) *
96 if (last == 0)
return weights[base];
97 const float x = std::clamp(position, 0.0f, 1.0f) *
static_cast<float>(last);
98 const int i0 = std::min(
static_cast<int>(x), last - 1);
99 const float frac = x -
static_cast<float>(i0);
100 const float w0 =
weights[base +
static_cast<std::size_t
>(i0)];
101 const float w1 =
weights[base +
static_cast<std::size_t
>(i0) + 1];
102 return w0 + (w1 - w0) * frac;
149 const double n =
excitation.contact_s * sample_rate;
150 return n <= 0.0 ? 0 :
static_cast<int>(n + 0.5);
162 float pickup_position, std::vector<ModalMode>& out) {
163 out.resize(spec.
modes.size());
164 for (std::size_t m = 0; m < spec.
modes.size(); ++m) {
166 const int mi =
static_cast<int>(m);
175 float strike_position = 0.5f,
176 float pickup_position = 0.5f) {
177 std::vector<ModalMode> out;
187template <
typename SampleType>
189 std::vector<ModalMode>& scratch,
float strike_position = 0.5f,
190 float pickup_position = 0.5f) {
191 resolve_modes(spec, strike_position, pickup_position, scratch);
197template <
typename SampleType>
199 double sample_rate,
float strike_position = 0.5f,
200 float pickup_position = 0.5f) {
201 bank.
prepare(sample_rate,
static_cast<int>(spec.
modes.size()));
202 std::vector<ModalMode> scratch;
203 load_modes(spec, bank, scratch, strike_position, pickup_position);
Bank of two-pole modal resonators, stored structure-of-arrays in lane groups so the per-sample state ...
Definition modal_bank.hpp:154
void set_modes(std::span< const ModalMode > modes)
Load a mode set (up to the prepared max; excess modes are ignored).
Definition modal_bank.hpp:193
void prepare(double sample_rate, int max_modes, int max_pickups=1)
Allocate storage for up to max_modes modes and max_pickups listening positions at sample_rate.
Definition modal_bank.hpp:170
Definition additive_bank.hpp:218
bool validate_modal_spec(const ModalSpec &spec, std::string &error)
Check a spec's internal consistency.
bool operator!=(const ModalSpec &a, const ModalSpec &b)
Definition modal_spec.hpp:261
std::string to_json(const ModalSpec &spec, bool pretty=true)
Serialize a spec to JSON.
constexpr int kModalSpecSchemaVersion
Schema version this build writes and is the highest it can read.
Definition modal_spec.hpp:62
std::optional< ModalSpec > parse_modal_spec(std::string_view json, ModalSpecDiagnostics *diagnostics=nullptr)
Parse a ModalSpec from JSON.
void load_modes(const ModalSpec &spec, ModalBankT< SampleType > &bank, std::vector< ModalMode > &scratch, float strike_position=0.5f, float pickup_position=0.5f)
Resolve the spec at a strike/pickup position and load the result into an already-prepared bank.
Definition modal_spec.hpp:188
@ a
Definition formant_filter_bank.hpp:20
bool operator==(const ModalSpec &a, const ModalSpec &b)
Exact equality over every known field.
void resolve_modes(const ModalSpec &spec, float strike_position, float pickup_position, std::vector< ModalMode > &out)
Resolve the spec's modes at a strike/pickup position into out.
Definition modal_spec.hpp:161
void prepare_and_load(const ModalSpec &spec, ModalBankT< SampleType > &bank, double sample_rate, float strike_position=0.5f, float pickup_position=0.5f)
Prepare bank to hold this spec's modes at sample_rate and load them.
Definition modal_spec.hpp:198
One resonant mode of a vibrating object: frequency, decay time, and impulse-response amplitude.
Definition modal_bank.hpp:16
float gain
amplitude of this mode in the impulse response
Definition modal_bank.hpp:19
A mode shape sampled on a uniform grid across the object's normalized extent [0, 1],...
Definition modal_spec.hpp:80
std::vector< float > weights
grid_points weights per mode, laid out [mode * grid_points + g].
Definition modal_spec.hpp:84
int grid_points
Samples per mode across [0, 1]. Zero means "no map".
Definition modal_spec.hpp:82
bool empty() const
Definition modal_spec.hpp:86
float weight_at(int mode, float position) const
Linearly interpolated weight of mode at normalized position.
Definition modal_spec.hpp:90
What a parse found beyond the spec itself. Always populated; read it.
Definition modal_spec.hpp:213
std::vector< std::string > unknown_fields
Dotted paths of fields that were present, unrecognized, and ignored (see the unknown-field policy on ...
Definition modal_spec.hpp:220
std::string error
Empty iff the parse succeeded.
Definition modal_spec.hpp:216
How the resonator is struck.
Definition modal_spec.hpp:67
double velocity
peak of the contact pulse
Definition modal_spec.hpp:69
double contact_s
contact duration; 0 means a unit impulse
Definition modal_spec.hpp:68
The PASS criteria a render of this spec must meet.
Definition modal_spec.hpp:120
double freq_cents
Frequency error budget per mode, in cents.
Definition modal_spec.hpp:122
double verify_seconds
Impulse response length a verifier should render to check the above.
Definition modal_spec.hpp:130
double gain_rel
Amplitude error budget per mode, relative to the resolved gain.
Definition modal_spec.hpp:126
double t60_rel
T60 error budget per mode, relative (0.08 = 8%).
Definition modal_spec.hpp:124
A modal instrument, complete.
Definition modal_spec.hpp:134
std::vector< ModalMode > modes
Definition modal_spec.hpp:138
ModalSpecTolerances tolerances
Definition modal_spec.hpp:143
int schema_version
Definition modal_spec.hpp:135
ModalShapeMap strike_map
Optional. When present, must hold grid_points weights per mode.
Definition modal_spec.hpp:141
std::string name
Definition modal_spec.hpp:136
int contact_samples(double sample_rate) const
Contact duration in samples at sample_rate, for fill_strike_pulse.
Definition modal_spec.hpp:148
ModalShapeMap pickup_map
Definition modal_spec.hpp:142
ModalSpecExcitation excitation
Definition modal_spec.hpp:139
std::string description
Definition modal_spec.hpp:137