Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
modal_extraction.hpp
Go to the documentation of this file.
1#pragma once
2
87
88#include <cstddef>
89#include <span>
90#include <string>
91#include <vector>
92
94
95namespace pulp::test::audio {
96
97// ── Modes ─────────────────────────────────────────────────────────────────
98
101 double freq_hz = 0.0;
102 double t60_s = 0.0;
103 double amplitude = 0.0;
111 double confidence = 0.0;
116 double prominence_db = 0.0;
118 int fit_points = 0;
121 std::string note;
122};
123
131 int fft_length = 32768;
133 double search_low_hz = 20.0;
134 double search_high_hz = 20000.0;
136 double peak_floor_db = -60.0;
138 double min_separation_hz = 8.0;
140 int max_modes = 64;
141
145 double refine_span_cents = 60.0;
146 double refine_step_cents = 2.0;
150 int refine_window = 8192;
151
156 double fit_start_db = -3.0;
157 double fit_end_db = -30.0;
160 double fit_offset_s = 0.005;
162 int envelope_window = 2048;
163 int envelope_hop = 512;
169 int channel = 0;
170};
171
174 std::vector<MeasuredMode> modes;
175 double sample_rate = 0.0;
176 double bin_hz = 0.0;
181 bool ok = false;
182 std::string message;
183};
184
193ModeAnalysis analyze_modes(std::span<const float> ir, double sample_rate,
194 const ModeAnalysisOptions& options = {});
195
200MeasuredMode measure_mode(std::span<const float> ir, double sample_rate,
201 double guess_hz,
202 const ModeAnalysisOptions& options = {});
203
205std::string summarize(const ModeAnalysis& analysis);
206std::string summarize(const MeasuredMode& mode);
207
208// ── Partials and inharmonicity ────────────────────────────────────────────
209
212 int index = 0;
213 double freq_hz = 0.0;
214 double harmonic_hz = 0.0;
215 double deviation_cents = 0.0;
216 double amplitude = 0.0;
217 bool found = false;
218};
219
232
243 double f0_hz = 0.0;
244 double b_coefficient = 0.0;
245 double rms_deviation_cents = 0.0;
250 std::vector<MeasuredPartial> partials;
252 bool ok = false;
253 std::string message;
254};
255
262 double sample_rate, double f0_guess,
263 const InharmonicityOptions& options = {});
264
265std::string summarize(const InharmonicityResult& result);
266
267// ── Time-resolved f0(t), sigma(t), Q(t) ───────────────────────────────────
268
275 double time_s = 0.0;
276 double freq_hz = 0.0;
277 double envelope = 0.0;
278 double sigma_np_s = 0.0;
279 double q = 0.0;
283 bool sigma_valid = false;
292 bool directional_only = false;
293};
294
298 double onset_threshold = 1.0e-3;
301 double start_offset_s = 0.021;
303 double tail_floor_ratio = 3.0e-4;
309 int min_cycles = 4;
310};
311
314 std::vector<CycleObservation> cycles;
315 double onset_s = 0.0;
316 double sample_rate = 0.0;
323 bool ok = false;
324 std::string message;
325
328 double mean_f0(double from_s, double to_s) const;
329 double mean_sigma(double from_s, double to_s) const;
330 double mean_q(double from_s, double to_s) const;
333 double sigma_span_percent(double from_s, double to_s) const;
334 double f0_span_percent(double from_s, double to_s) const;
337 double f0_q_correlation(double from_s, double to_s) const;
338};
339
352CycleTrack track_cycles(std::span<const float> signal, double sample_rate,
353 const CycleTrackOptions& options = {});
354
357 double time_s = 0.0;
358 double freq_hz = 0.0;
359 double sigma_np_s = 0.0;
360 double q = 0.0;
364 double residual_ratio = 0.0;
365};
366
369 double window_s = 0.080;
370 double hop_s = 0.020;
371 double onset_threshold = 1.0e-3;
372 double start_offset_s = 0.021;
374 double silence_threshold = 1.0e-7;
375};
376
385struct Ar2Track {
386 std::vector<Ar2Observation> windows;
387 bool ok = false;
388 std::string message;
389};
390
391Ar2Track track_ar2(std::span<const float> signal, double sample_rate,
392 const Ar2TrackOptions& options = {});
393
394std::string summarize(const CycleTrack& track);
395std::string summarize(const Ar2Track& track);
396
397// ── Primitives ────────────────────────────────────────────────────────────
398
404double windowed_magnitude(std::span<const float> x, std::size_t start,
405 std::size_t length, double freq_hz,
406 double sample_rate);
407
408// ── Shipped offline compiler ─────────────────────────────────────────────
409
420
425 int max_input_samples = 1 << 20;
426 int max_modes = 64;
431 double min_separation_cents = 25.0;
432 double confidence_floor = 0.70;
433 double snr_floor_db = -60.0;
434 std::string recipe = "modal-extraction-v1";
435};
436
439 double confidence = 0.0;
440 double prominence_db = 0.0;
441 double ranking_score = 0.0;
442 bool merged = false;
443 bool kept = false;
444};
445
448 bool ok = false;
449 std::string message;
450 std::string recipe;
452 std::vector<ModalExtractionCandidate> candidates;
453};
454
461 std::span<const float> impulse, double sample_rate,
462 const ModalExtractionOptions& options = {});
463
464} // namespace pulp::test::audio
ModalSpec — a modal instrument as a data file rather than a C++ class.
Definition additive_bank.hpp:218
Definition audio_artifacts.hpp:20
ModalExtractionResult compile_modal_spec(std::span< const float > impulse, double sample_rate, const ModalExtractionOptions &options={})
Compile a bounded, mono impulse response into the existing ModalSpec data model.
Ar2Track track_ar2(std::span< const float > signal, double sample_rate, const Ar2TrackOptions &options={})
InharmonicityResult measure_inharmonicity(std::span< const float > signal, double sample_rate, double f0_guess, const InharmonicityOptions &options={})
Track the partials of signal starting from f0_guess and measure the inharmonicity.
@ none
Not watched.
Definition latency_evidence.hpp:74
std::string summarize(const BufferMetrics &metrics, const FrequencyEstimate &frequency={})
Compact, agent-readable signal summary.
ModeAnalysis analyze_modes(std::span< const float > ir, double sample_rate, const ModeAnalysisOptions &options={})
Recover the modes present in ir, a rendered impulse response (mono).
CycleTrack track_cycles(std::span< const float > signal, double sample_rate, const CycleTrackOptions &options={})
Track f0(t), sigma(t) and Q(t) of a decaying quasi-sinusoidal note, cycle by cycle.
double windowed_magnitude(std::span< const float > x, std::size_t start, std::size_t length, double freq_hz, double sample_rate)
Hann-windowed DFT magnitude of x[start .
MeasuredMode measure_mode(std::span< const float > ir, double sample_rate, double guess_hz, const ModeAnalysisOptions &options={})
Measure one mode whose frequency is already known approximately.
ModalExtractionError
Definition modal_extraction.hpp:410
@ silent_input
Definition modal_extraction.hpp:414
@ none
Definition modal_extraction.hpp:411
@ invalid_options
Definition modal_extraction.hpp:417
@ invalid_sample_rate
Definition modal_extraction.hpp:416
@ non_finite_input
Definition modal_extraction.hpp:415
@ no_modes
Definition modal_extraction.hpp:418
@ input_too_short
Definition modal_extraction.hpp:413
@ empty_input
Definition modal_extraction.hpp:412
One resonant mode of a vibrating object: frequency, decay time, and impulse-response amplitude.
Definition modal_bank.hpp:16
A modal instrument, complete.
Definition modal_spec.hpp:134
One short-window AR(2) pole fit.
Definition modal_extraction.hpp:356
double residual_ratio
Residual energy over signal energy in the window, in [0, 1].
Definition modal_extraction.hpp:364
double time_s
Centre of the window.
Definition modal_extraction.hpp:357
double sigma_np_s
From the pole radius, -ln(r) * fs.
Definition modal_extraction.hpp:359
double q
pi * freq_hz / sigma_np_s.
Definition modal_extraction.hpp:360
double freq_hz
From the pole angle.
Definition modal_extraction.hpp:358
Options for track_ar2.
Definition modal_extraction.hpp:368
double onset_threshold
Definition modal_extraction.hpp:371
double silence_threshold
Windows whose peak |x| is below this are dropped (end of the tail).
Definition modal_extraction.hpp:374
double window_s
Definition modal_extraction.hpp:369
double start_offset_s
Definition modal_extraction.hpp:372
double hop_s
Definition modal_extraction.hpp:370
AR(2) pole track — an independent cross-check on track_cycles.
Definition modal_extraction.hpp:385
std::vector< Ar2Observation > windows
Definition modal_extraction.hpp:386
std::string message
Definition modal_extraction.hpp:388
bool ok
Definition modal_extraction.hpp:387
One cycle of a decaying quasi-sinusoid.
Definition modal_extraction.hpp:274
double freq_hz
1 / (period between zero crossings).
Definition modal_extraction.hpp:276
double time_s
Centre of the cycle.
Definition modal_extraction.hpp:275
double sigma_np_s
Local decay rate, Np/s. Valid iff sigma_valid.
Definition modal_extraction.hpp:278
double envelope
Peak |x| within the cycle.
Definition modal_extraction.hpp:277
bool directional_only
True for the first tracked cycle — the attack cycle, whose freq_hz is a mixture of the attack-mode re...
Definition modal_extraction.hpp:292
double q
pi * freq_hz / sigma_np_s.
Definition modal_extraction.hpp:279
bool sigma_valid
False for cycles within half_window of either end of the track, where the sliding log-envelope fit ha...
Definition modal_extraction.hpp:283
Options for track_cycles.
Definition modal_extraction.hpp:296
int sigma_half_window
Half-width, in cycles, of the sliding log-envelope fit that yields sigma.
Definition modal_extraction.hpp:307
double onset_threshold
|x| above this counts as the onset.
Definition modal_extraction.hpp:298
double tail_floor_ratio
Stop tracking once |x| stays below max(|x|) * this ratio.
Definition modal_extraction.hpp:303
int min_cycles
A track with fewer usable cycles than this is reported ok = false.
Definition modal_extraction.hpp:309
double start_offset_s
Start tracking this long after the detected onset, to clear the excitation transient.
Definition modal_extraction.hpp:301
Time-resolved track of one note.
Definition modal_extraction.hpp:313
bool ok
Definition modal_extraction.hpp:323
double onset_s
Definition modal_extraction.hpp:315
double monocomponent_confidence
Fraction of cycle periods within 20% of the median period, in [0, 1].
Definition modal_extraction.hpp:322
double sigma_span_percent(double from_s, double to_s) const
Peak-to-peak spread of sigma over valid cycles in the window, as a percentage of its mean.
double mean_f0(double from_s, double to_s) const
Mean over cycles with sigma_valid, in [from_s, to_s).
double mean_q(double from_s, double to_s) const
double mean_sigma(double from_s, double to_s) const
double f0_span_percent(double from_s, double to_s) const
double f0_q_correlation(double from_s, double to_s) const
Pearson correlation of f0 and Q over valid cycles in the window.
std::string message
Definition modal_extraction.hpp:324
std::vector< CycleObservation > cycles
Definition modal_extraction.hpp:314
double sample_rate
Definition modal_extraction.hpp:316
Options for measure_inharmonicity.
Definition modal_extraction.hpp:221
double search_span_cents
How far around each predicted partial to search, in cents.
Definition modal_extraction.hpp:226
int num_partials
Definition modal_extraction.hpp:222
ModeAnalysisOptions mode_options
Definition modal_extraction.hpp:230
double partial_floor_db
Amplitude floor, relative to the loudest partial, below which a partial is reported found = false rat...
Definition modal_extraction.hpp:229
Inharmonicity of a (quasi-)harmonic tone.
Definition modal_extraction.hpp:242
int found_partials
Definition modal_extraction.hpp:251
std::vector< MeasuredPartial > partials
Definition modal_extraction.hpp:250
bool ok
Definition modal_extraction.hpp:252
double rms_deviation_cents
Residual of the stiff-string fit.
Definition modal_extraction.hpp:245
double b_coefficient
Stiff-string B (least squares).
Definition modal_extraction.hpp:244
double f0_hz
Refined fundamental.
Definition modal_extraction.hpp:243
double rms_harmonic_deviation_cents
RMS deviation from the pure harmonic series (B = 0).
Definition modal_extraction.hpp:249
std::string message
Definition modal_extraction.hpp:253
One resonant mode recovered from a rendered impulse response.
Definition modal_extraction.hpp:100
double amplitude
Linear amplitude of this mode at t = 0.
Definition modal_extraction.hpp:103
double confidence
Fit quality in [0, 1]: the R^2 of the log-envelope slope fit, and zero when no fit was possible at al...
Definition modal_extraction.hpp:111
std::string note
Empty when the mode fit cleanly; otherwise says what went wrong (fit window ran past the buffer,...
Definition modal_extraction.hpp:121
int fit_points
Number of envelope points the T60 slope fit consumed.
Definition modal_extraction.hpp:118
double prominence_db
Peak height in dB relative to the strongest peak in the discovery spectrum.
Definition modal_extraction.hpp:116
double t60_s
Time to decay 60 dB, from the fitted slope.
Definition modal_extraction.hpp:102
double freq_hz
Refined mode frequency.
Definition modal_extraction.hpp:101
One tracked partial of a (quasi-)harmonic sound.
Definition modal_extraction.hpp:211
double deviation_cents
Measured vs harmonic_hz, in cents.
Definition modal_extraction.hpp:215
int index
Harmonic number, 1 = fundamental.
Definition modal_extraction.hpp:212
bool found
False when no peak was located.
Definition modal_extraction.hpp:217
double harmonic_hz
index * f0, the ideal-string prediction.
Definition modal_extraction.hpp:214
double amplitude
Linear amplitude at t = 0.
Definition modal_extraction.hpp:216
double freq_hz
Measured frequency.
Definition modal_extraction.hpp:213
Definition modal_extraction.hpp:437
double ranking_score
Definition modal_extraction.hpp:441
double confidence
Definition modal_extraction.hpp:439
bool merged
Definition modal_extraction.hpp:442
bool kept
Definition modal_extraction.hpp:443
double prominence_db
Definition modal_extraction.hpp:440
pulp::signal::ModalMode mode
Definition modal_extraction.hpp:438
Definition modal_extraction.hpp:421
ModeAnalysisOptions analysis
Definition modal_extraction.hpp:422
int max_input_samples
Requested input bound.
Definition modal_extraction.hpp:425
double min_separation_cents
Qualified candidates closer than this are one mode.
Definition modal_extraction.hpp:431
double confidence_floor
Definition modal_extraction.hpp:432
std::string recipe
Definition modal_extraction.hpp:434
int max_modes
Definition modal_extraction.hpp:426
double snr_floor_db
Definition modal_extraction.hpp:433
Definition modal_extraction.hpp:446
std::vector< ModalExtractionCandidate > candidates
Definition modal_extraction.hpp:452
std::string message
Definition modal_extraction.hpp:449
std::string recipe
Definition modal_extraction.hpp:450
pulp::signal::ModalSpec spec
Definition modal_extraction.hpp:451
bool ok
Definition modal_extraction.hpp:448
ModalExtractionError error
Definition modal_extraction.hpp:447
Options for analyze_modes.
Definition modal_extraction.hpp:127
double peak_floor_db
Reject peaks quieter than this (dB below the strongest peak).
Definition modal_extraction.hpp:136
int min_fit_points
A slope fit needs at least this many envelope points to be reported with non-zero confidence.
Definition modal_extraction.hpp:166
double min_separation_hz
Two peaks closer than this are treated as one mode; the louder wins.
Definition modal_extraction.hpp:138
double refine_step_cents
Definition modal_extraction.hpp:146
int refine_window
Window (samples) used by the refinement DFT probe.
Definition modal_extraction.hpp:150
int max_modes
Cap on reported modes (strongest first during discovery).
Definition modal_extraction.hpp:140
int channel
Channel index when a multi-channel view is reduced (unused by the span overloads; present so callers ...
Definition modal_extraction.hpp:169
double search_high_hz
Definition modal_extraction.hpp:134
double search_low_hz
Discovery search band. Peaks outside it are ignored.
Definition modal_extraction.hpp:133
double fit_end_db
Definition modal_extraction.hpp:157
double fit_offset_s
Skip this much of the head before fitting, so an excitation pulse or a processor's pre-ring is outsid...
Definition modal_extraction.hpp:160
int envelope_hop
Definition modal_extraction.hpp:163
int envelope_window
Envelope tracking window/hop for the decay fit, in samples.
Definition modal_extraction.hpp:162
int fft_length
Discovery FFT length (power of two).
Definition modal_extraction.hpp:131
double refine_span_cents
Half-width of the cents grid scanned around each discovery peak when refining its frequency,...
Definition modal_extraction.hpp:145
double fit_start_db
dB window, relative to the mode's own level at fit_offset_s, over which the log-envelope slope is fit...
Definition modal_extraction.hpp:156
Modes recovered from an impulse response, strongest first.
Definition modal_extraction.hpp:173
std::vector< MeasuredMode > modes
Definition modal_extraction.hpp:174
std::string message
Always populated; read it.
Definition modal_extraction.hpp:182
double bin_hz
Discovery resolution, sample_rate/fft_length.
Definition modal_extraction.hpp:176
double sample_rate
Definition modal_extraction.hpp:175
bool ok
False when the buffer was unusable.
Definition modal_extraction.hpp:181
int discovered_peaks
Candidates before the mode cap was applied.
Definition modal_extraction.hpp:180
double resolution_limit_hz
Frequencies closer than roughly this cannot be separated by the discovery window at all (Hann main lo...
Definition modal_extraction.hpp:179