Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
analysis_frontends.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <pulp/signal/fft.hpp>
4
5#include <algorithm>
6#include <array>
7#include <cmath>
8#include <complex>
9#include <cstddef>
10#include <cstdint>
11#include <limits>
12#include <optional>
13#include <type_traits>
14
15namespace pulp::signal {
16
22
26inline double onset_energy_flux(double previous, double current) noexcept {
27 if (!std::isfinite(previous) || !std::isfinite(current))
28 return std::numeric_limits<double>::quiet_NaN();
29 return std::max(0.0, current - previous);
30}
31
32inline double onset_spectral_bin_flux(OnsetDetectionMethod method, double previous, double current,
33 std::size_t bin) noexcept {
34 if (!std::isfinite(previous) || !std::isfinite(current))
35 return std::numeric_limits<double>::quiet_NaN();
36 const auto positive = std::max(0.0, current - previous);
38 ? positive * static_cast<double>(bin + 1u)
39 : positive;
40}
41
43 double sample_rate = 48000.0;
44 std::size_t channels = 1;
45 std::uint32_t fft_size = 2048;
46 std::uint64_t hop_size = 2048;
47 std::uint64_t max_retained_fft_bytes = 64u * 1024u * 1024u;
48};
49
50namespace detail {
51
52enum class AnalysisWindow : std::uint8_t { rectangular, symmetric_hann };
53
54template <typename SampleType, std::size_t MaxFftSize, std::size_t MaxChannels>
56 static_assert(std::is_floating_point_v<SampleType>);
57 static_assert(MaxFftSize >= 2);
58 static_assert(MaxChannels > 0);
59
60 public:
61 [[nodiscard]] bool prepare(const StreamingAnalysisConfig& config, AnalysisWindow window,
62 bool require_fft = true) {
63 if (!valid_config(config, require_fft))
64 return false;
65
66 std::uint64_t retained_fft_bytes = 0;
67 std::optional<FftT<SampleType>> fft;
68 if (require_fft) {
70 config.fft_size, config.max_retained_fft_bytes, retained_fft_bytes))
71 return false;
72 fft.emplace(static_cast<int>(config.fft_size));
73 if (!fft->ready())
74 return false;
75 }
76 std::array<double, MaxFftSize> coefficients{};
77 for (std::size_t i = 0; i < config.fft_size; ++i) {
78 if (window == AnalysisWindow::symmetric_hann) {
79 constexpr double two_pi = 6.28318530717958647692;
80 const auto phase =
81 two_pi * static_cast<double>(i) / static_cast<double>(config.fft_size - 1u);
82 coefficients[i] = 0.5 - 0.5 * std::cos(phase);
83 } else {
84 coefficients[i] = 1.0;
85 }
86 }
87
88 config_ = config;
89 retained_fft_bytes_ = retained_fft_bytes;
90 fft_ = std::move(fft);
91 window_ = coefficients;
92 prepared_ = true;
93 reset();
94 return true;
95 }
96
97 void reset() noexcept {
98 mono_ring_.fill(SampleType{0});
99 power_ring_.fill(0.0);
100 time_frame_.fill(SampleType{0});
101 spectrum_.fill({});
102 write_ = 0;
103 filled_ = 0;
104 until_next_frame_ = 0;
105 stream_frames_ = 0;
106 }
107
109 mono_ring_.fill(SampleType{0});
110 power_ring_.fill(0.0);
111 time_frame_.fill(SampleType{0});
112 spectrum_.fill({});
113 write_ = 0;
114 filled_ = 0;
115 until_next_frame_ = 0;
116 }
117
118 // A rejected input sample still occupies one position on the absolute
119 // input timeline. It cannot contribute to a window, so restart readiness
120 // from the next finite sample while preserving timestamp monotonicity.
121 void reject_sample() noexcept {
122 ++stream_frames_;
124 }
125
126 [[nodiscard]] bool push(double mono, double channel_power) noexcept {
127 mono_ring_[write_] = mono;
128 power_ring_[write_] = channel_power;
129 write_ = (write_ + 1u) % config_.fft_size;
130 ++stream_frames_;
131
132 if (filled_ < config_.fft_size) {
133 ++filled_;
134 if (filled_ == config_.fft_size) {
135 until_next_frame_ = config_.hop_size;
136 return true;
137 }
138 return false;
139 }
140
141 if (--until_next_frame_ == 0) {
142 until_next_frame_ = config_.hop_size;
143 return true;
144 }
145 return false;
146 }
147
148 [[nodiscard]] bool render_spectrum() noexcept {
149 return render_spectrum(false);
150 }
151
152 [[nodiscard]] bool render_gain_normalized_spectrum() noexcept {
153 return render_spectrum(true);
154 }
155
156 [[nodiscard]] double frame_energy() const noexcept {
157 long double sum = 0.0L;
158 const auto divisor = static_cast<long double>(config_.fft_size);
159 for (std::size_t i = 0; i < config_.fft_size; ++i) {
160 const auto source = (write_ + i) % config_.fft_size;
161 // Divide each admitted finite term before accumulation. This
162 // remains bounded when long double has only double precision.
163 sum += static_cast<long double>(power_ring_[source]) / divisor;
164 }
165 return static_cast<double>(sum);
166 }
167
170 [[nodiscard]] const std::array<std::complex<SampleType>, MaxFftSize>&
171 spectrum() const noexcept {
172 return spectrum_;
173 }
174 [[nodiscard]] const StreamingAnalysisConfig& config() const noexcept {
175 return config_;
176 }
177 [[nodiscard]] std::uint64_t stream_frames() const noexcept {
178 return stream_frames_;
179 }
180 [[nodiscard]] bool prepared() const noexcept {
181 return prepared_;
182 }
183 [[nodiscard]] std::uint64_t retained_fft_bytes() const noexcept {
184 return retained_fft_bytes_;
185 }
186
187 private:
188 [[nodiscard]] bool render_spectrum(bool normalize_gain) noexcept {
189 if (!fft_)
190 return false;
191 double maximum = 0.0;
192 if (normalize_gain) {
193 for (std::size_t i = 0; i < config_.fft_size; ++i) {
194 const auto source = (write_ + i) % config_.fft_size;
195 const auto windowed = mono_ring_[source] * window_[i];
196 if (!std::isfinite(windowed))
197 return false;
198 maximum = std::max(maximum, std::abs(windowed));
199 }
200 }
201 for (std::size_t i = 0; i < config_.fft_size; ++i) {
202 const auto source = (write_ + i) % config_.fft_size;
203 const auto windowed = mono_ring_[source] * window_[i];
204 time_frame_[i] = static_cast<SampleType>(maximum > 0.0 ? windowed / maximum : windowed);
205 if (!std::isfinite(time_frame_[i]))
206 return false;
207 }
208 fft_->forward_real_half(time_frame_.data(), spectrum_.data());
209 for (std::size_t bin = 0; bin <= config_.fft_size / 2u; ++bin) {
210 if (!std::isfinite(spectrum_[bin].real()) || !std::isfinite(spectrum_[bin].imag()))
211 return false;
212 }
213 return true;
214 }
215 static bool valid_config(const StreamingAnalysisConfig& config, bool require_fft) noexcept {
216 return std::isfinite(config.sample_rate) && config.sample_rate > 0.0 &&
217 config.channels > 0 && config.channels <= MaxChannels && config.fft_size >= 2 &&
218 config.fft_size <= MaxFftSize &&
219 (!require_fft || (config.fft_size & (config.fft_size - 1u)) == 0) &&
220 config.hop_size > 0 && (!require_fft || config.max_retained_fft_bytes > 0);
221 }
222
223 StreamingAnalysisConfig config_{};
224 std::optional<FftT<SampleType>> fft_{};
225 std::array<double, MaxFftSize> mono_ring_{};
226 std::array<double, MaxFftSize> power_ring_{};
227 std::array<double, MaxFftSize> window_{};
228 std::array<SampleType, MaxFftSize> time_frame_{};
229 std::array<std::complex<SampleType>, MaxFftSize> spectrum_{};
230 std::size_t write_ = 0;
231 std::size_t filled_ = 0;
232 std::uint64_t until_next_frame_ = 0;
233 std::uint64_t stream_frames_ = 0;
234 std::uint64_t retained_fft_bytes_ = 0;
235 bool prepared_ = false;
236};
237
238template <typename SampleType, std::size_t MaxChannels>
239bool mix_planar_frame(const SampleType* const* channels, std::size_t channel_count,
240 std::size_t frame, bool compute_power, double& mono,
241 double& channel_power) noexcept {
242 if (channels == nullptr || channel_count == 0 || channel_count > MaxChannels)
243 return false;
244 double scale = 0.0;
245 for (std::size_t channel = 0; channel < channel_count; ++channel) {
246 if (channels[channel] == nullptr)
247 return false;
248 const auto sample = static_cast<double>(channels[channel][frame]);
249 if (!std::isfinite(sample))
250 return false;
251 scale = std::max(scale, std::abs(sample));
252 }
253
254 if (scale == 0.0) {
255 mono = 0.0;
256 channel_power = 0.0;
257 return true;
258 }
259
260 double scaled_sum = 0.0;
261 double scaled_power = 0.0;
262 for (std::size_t channel = 0; channel < channel_count; ++channel) {
263 const auto scaled = static_cast<double>(channels[channel][frame]) / scale;
264 scaled_sum += scaled;
265 if (compute_power)
266 scaled_power += scaled * scaled;
267 }
268 const auto divisor = static_cast<double>(channel_count);
269 const auto mixed = scale * (scaled_sum / divisor);
270 if (!std::isfinite(mixed) ||
271 std::abs(mixed) > static_cast<double>(std::numeric_limits<SampleType>::max()))
272 return false;
273 mono = mixed;
274 channel_power = 0.0;
275 if (compute_power) {
276 if (scale > std::sqrt(std::numeric_limits<double>::max()))
277 return false;
278 channel_power = (scale * scale) * (scaled_power / divisor);
279 if (!std::isfinite(channel_power))
280 return false;
281 }
282 return true;
283}
284
285inline int pitch_class_for_frequency(double frequency_hz) noexcept {
286 if (!(frequency_hz > 0.0) || !std::isfinite(frequency_hz))
287 return -1;
288 const auto midi = 69.0 + 12.0 * std::log2(frequency_hz / 440.0);
289 if (!std::isfinite(midi))
290 return -1;
291 auto pitch_class = static_cast<int>(std::lround(midi)) % 12;
292 if (pitch_class < 0)
293 pitch_class += 12;
294 return pitch_class;
295}
296
297} // namespace detail
298
302template <typename SampleType> struct ChromaFrameT {
303 std::array<double, 12> magnitude{};
304 std::array<SampleType, 12> normalized{};
305 std::uint64_t window_start_frame = 0;
306 std::uint64_t window_center_frame = 0;
307 std::uint64_t ready_at_frame = 0;
308 std::uint64_t sequence = 0;
309 bool valid = false;
310};
311
320template <typename SampleType = float, std::size_t MaxFftSize = 4096, std::size_t MaxChannels = 8>
322 static_assert(std::is_floating_point_v<SampleType>);
323 static_assert(MaxFftSize >= 2);
324 static_assert(MaxChannels > 0);
325
326 public:
328
329 [[nodiscard]] bool prepare(const StreamingAnalysisConfig& config) {
330 if (!window_.prepare(config, detail::AnalysisWindow::symmetric_hann))
331 return false;
332 sequence_ = 0;
333 current_ = {};
334 return true;
335 }
336
337 void reset() noexcept {
338 window_.reset();
339 sequence_ = 0;
340 current_ = {};
341 }
342
343 template <typename Sink>
344 [[nodiscard]] bool process(const SampleType* const* channels, std::size_t channel_count,
345 std::size_t frames, Sink&& sink) noexcept {
346 static_assert(std::is_nothrow_invocable_v<Sink&, const Frame&>,
347 "analysis sinks must be noexcept");
348 if (!window_.prepared() || channel_count != window_.config().channels ||
349 channels == nullptr)
350 return false;
351 for (std::size_t channel = 0; channel < channel_count; ++channel) {
352 if (channels[channel] == nullptr)
353 return false;
354 }
355
356 bool finite = true;
357 for (std::size_t frame = 0; frame < frames; ++frame) {
358 double mono{};
359 double power{};
360 if (!detail::mix_planar_frame<SampleType, MaxChannels>(channels, channel_count, frame,
361 false, mono, power)) {
362 window_.reject_sample();
363 finite = false;
364 continue;
365 }
366 if (!window_.push(mono, power))
367 continue;
368 if (!render_frame()) {
369 window_.clear_history_after_fault();
370 finite = false;
371 continue;
372 }
373 sink(current_);
374 }
375 return finite;
376 }
377
378 [[nodiscard]] const Frame& current() const noexcept {
379 return current_;
380 }
381 [[nodiscard]] std::uint32_t algorithmic_latency_samples() const noexcept {
382 return window_.prepared() ? window_.config().fft_size / 2u : 0u;
383 }
384 [[nodiscard]] std::uint32_t startup_samples() const noexcept {
385 return window_.prepared() ? window_.config().fft_size : 0u;
386 }
387 [[nodiscard]] std::uint64_t retained_fft_bytes() const noexcept {
388 return window_.retained_fft_bytes();
389 }
390
391 private:
392 [[nodiscard]] bool render_frame() noexcept {
393 if (!window_.render_spectrum())
394 return false;
395 Frame next{};
396 const auto& config = window_.config();
397 const auto& spectrum = window_.spectrum();
398 for (std::size_t bin = 1; bin < config.fft_size / 2u; ++bin) {
399 const auto magnitude = static_cast<double>(std::abs(spectrum[bin]));
400 const auto left = static_cast<double>(std::abs(spectrum[bin - 1u]));
401 const auto right = static_cast<double>(std::abs(spectrum[bin + 1u]));
402 if (!std::isfinite(magnitude) || !std::isfinite(left) || !std::isfinite(right))
403 return false;
404 if (magnitude < left || magnitude < right)
405 continue;
406 const auto normalized_bin =
407 static_cast<double>(bin) / static_cast<double>(config.fft_size);
408 const auto frequency = config.sample_rate * normalized_bin;
409 if (frequency < 55.0 || frequency > 5000.0)
410 continue;
411 const auto pitch_class = detail::pitch_class_for_frequency(frequency);
412 if (pitch_class >= 0)
413 next.magnitude[static_cast<std::size_t>(pitch_class)] += magnitude;
414 }
415 long double total = 0.0L;
416 for (const auto value : next.magnitude)
417 total += static_cast<long double>(value);
418 if (!std::isfinite(total))
419 return false;
420 if (total > 0.0L) {
421 for (std::size_t pc = 0; pc < 12; ++pc)
422 next.normalized[pc] =
423 static_cast<SampleType>(static_cast<long double>(next.magnitude[pc]) / total);
424 next.valid = true;
425 }
426 next.ready_at_frame = window_.stream_frames() - 1u;
427 next.window_start_frame = window_.stream_frames() - config.fft_size;
428 next.window_center_frame = next.window_start_frame + config.fft_size / 2u;
429 next.sequence = ++sequence_;
430 current_ = next;
431 return true;
432 }
433
434 detail::StreamingAnalysisWindowT<SampleType, MaxFftSize, MaxChannels> window_{};
435 Frame current_{};
436 std::uint64_t sequence_ = 0;
437};
438
442template <typename SampleType> struct OnsetNoveltyFrameT {
443 double novelty = 0.0;
444 std::uint64_t window_start_frame = 0;
445 std::uint64_t window_center_frame = 0;
446 std::uint64_t ready_at_frame = 0;
447 std::uint64_t sequence = 0;
449};
450
454template <typename SampleType = float, std::size_t MaxFftSize = 4096, std::size_t MaxChannels = 8>
456 static_assert(std::is_floating_point_v<SampleType>);
457 static_assert(MaxFftSize >= 2);
458 static_assert(MaxChannels > 0);
459
460 public:
462
463 [[nodiscard]] bool prepare(const StreamingAnalysisConfig& config, OnsetDetectionMethod method) {
464 if (method != OnsetDetectionMethod::EnergyFlux &&
467 return false;
468 const auto require_fft = method != OnsetDetectionMethod::EnergyFlux;
469 if (!window_.prepare(config, detail::AnalysisWindow::rectangular, require_fft))
470 return false;
471 method_ = method;
472 previous_magnitudes_.fill(0.0);
473 previous_energy_ = 0.0;
474 have_previous_ = false;
475 sequence_ = 0;
476 current_ = {};
477 return true;
478 }
479
480 void reset() noexcept {
481 window_.reset();
482 previous_magnitudes_.fill(0.0);
483 previous_energy_ = 0.0;
484 have_previous_ = false;
485 sequence_ = 0;
486 current_ = {};
487 }
488
489 template <typename Sink>
490 [[nodiscard]] bool process(const SampleType* const* channels, std::size_t channel_count,
491 std::size_t frames, Sink&& sink) noexcept {
492 static_assert(std::is_nothrow_invocable_v<Sink&, const Frame&>,
493 "analysis sinks must be noexcept");
494 if (!window_.prepared() || channel_count != window_.config().channels ||
495 channels == nullptr)
496 return false;
497 for (std::size_t channel = 0; channel < channel_count; ++channel) {
498 if (channels[channel] == nullptr)
499 return false;
500 }
501
502 bool finite = true;
503 for (std::size_t frame = 0; frame < frames; ++frame) {
504 double mono{};
505 double power{};
507 channels, channel_count, frame, method_ == OnsetDetectionMethod::EnergyFlux,
508 mono, power)) {
509 reject_sample();
510 finite = false;
511 continue;
512 }
513 if (!window_.push(mono, power))
514 continue;
515 if (!render_frame()) {
516 clear_history_after_fault();
517 finite = false;
518 continue;
519 }
520 sink(current_);
521 }
522 return finite;
523 }
524
525 [[nodiscard]] const Frame& current() const noexcept {
526 return current_;
527 }
528 [[nodiscard]] std::uint32_t readiness_latency_samples() const noexcept {
529 return window_.prepared() ? window_.config().fft_size - 1u : 0u;
530 }
531 [[nodiscard]] std::uint64_t retained_fft_bytes() const noexcept {
532 return window_.retained_fft_bytes();
533 }
534
535 private:
536 void clear_history_after_fault() noexcept {
537 window_.clear_history_after_fault();
538 previous_magnitudes_.fill(0.0);
539 previous_energy_ = 0.0;
540 have_previous_ = false;
541 }
542
543 void reject_sample() noexcept {
544 window_.reject_sample();
545 previous_magnitudes_.fill(0.0);
546 previous_energy_ = 0.0;
547 have_previous_ = false;
548 }
549
550 [[nodiscard]] bool render_frame() noexcept {
551 double novelty = 0.0;
552 if (method_ == OnsetDetectionMethod::EnergyFlux) {
553 const auto energy = window_.frame_energy();
554 if (!std::isfinite(energy))
555 return false;
556 if (have_previous_)
557 novelty = onset_energy_flux(previous_energy_, energy);
558 previous_energy_ = energy;
559 } else {
560 if (!window_.render_spectrum())
561 return false;
562 const auto& spectrum = window_.spectrum();
563 const auto bins = window_.config().fft_size / 2u + 1u;
564 for (std::size_t bin = 0; bin < bins; ++bin) {
565 const auto magnitude = static_cast<double>(std::abs(spectrum[bin]));
566 if (!std::isfinite(magnitude))
567 return false;
568 if (have_previous_) {
569 novelty +=
570 onset_spectral_bin_flux(method_, previous_magnitudes_[bin], magnitude, bin);
571 }
572 previous_magnitudes_[bin] = magnitude;
573 }
574 }
575 if (!std::isfinite(novelty))
576 return false;
577 have_previous_ = true;
578
579 const auto& config = window_.config();
580 Frame next{};
581 next.novelty = novelty;
582 next.ready_at_frame = window_.stream_frames() - 1u;
583 next.window_start_frame = window_.stream_frames() - config.fft_size;
584 next.window_center_frame = next.window_start_frame + config.fft_size / 2u;
585 next.sequence = ++sequence_;
586 next.method = method_;
587 current_ = next;
588 return true;
589 }
590
591 detail::StreamingAnalysisWindowT<SampleType, MaxFftSize, MaxChannels> window_{};
592 std::array<double, MaxFftSize / 2u + 1u> previous_magnitudes_{};
593 double previous_energy_ = 0.0;
594 Frame current_{};
596 std::uint64_t sequence_ = 0;
597 bool have_previous_ = false;
598};
599
604
605} // namespace pulp::signal
Fixed-capacity chroma analysis over caller-owned planar input.
Definition analysis_frontends.hpp:321
std::uint64_t retained_fft_bytes() const noexcept
Definition analysis_frontends.hpp:387
std::uint32_t algorithmic_latency_samples() const noexcept
Definition analysis_frontends.hpp:381
bool prepare(const StreamingAnalysisConfig &config)
Definition analysis_frontends.hpp:329
std::uint32_t startup_samples() const noexcept
Definition analysis_frontends.hpp:384
const Frame & current() const noexcept
Definition analysis_frontends.hpp:378
ChromaFrameT< SampleType > Frame
Definition analysis_frontends.hpp:327
void reset() noexcept
Definition analysis_frontends.hpp:337
bool process(const SampleType *const *channels, std::size_t channel_count, std::size_t frames, Sink &&sink) noexcept
Definition analysis_frontends.hpp:344
Fixed-capacity streaming novelty analysis.
Definition analysis_frontends.hpp:455
std::uint32_t readiness_latency_samples() const noexcept
Definition analysis_frontends.hpp:528
OnsetNoveltyFrameT< SampleType > Frame
Definition analysis_frontends.hpp:461
bool prepare(const StreamingAnalysisConfig &config, OnsetDetectionMethod method)
Definition analysis_frontends.hpp:463
bool process(const SampleType *const *channels, std::size_t channel_count, std::size_t frames, Sink &&sink) noexcept
Definition analysis_frontends.hpp:490
std::uint64_t retained_fft_bytes() const noexcept
Definition analysis_frontends.hpp:531
const Frame & current() const noexcept
Definition analysis_frontends.hpp:525
void reset() noexcept
Definition analysis_frontends.hpp:480
Definition analysis_frontends.hpp:55
double frame_energy() const noexcept
Definition analysis_frontends.hpp:156
void reject_sample() noexcept
Definition analysis_frontends.hpp:121
bool render_spectrum() noexcept
Definition analysis_frontends.hpp:148
void clear_history_after_fault() noexcept
Definition analysis_frontends.hpp:108
void reset() noexcept
Definition analysis_frontends.hpp:97
bool prepared() const noexcept
Definition analysis_frontends.hpp:180
bool render_gain_normalized_spectrum() noexcept
Definition analysis_frontends.hpp:152
std::uint64_t stream_frames() const noexcept
Definition analysis_frontends.hpp:177
bool push(double mono, double channel_power) noexcept
Definition analysis_frontends.hpp:126
const StreamingAnalysisConfig & config() const noexcept
Definition analysis_frontends.hpp:174
const std::array< std::complex< SampleType >, MaxFftSize > & spectrum() const noexcept
Latest rendered spectrum.
Definition analysis_frontends.hpp:171
std::uint64_t retained_fft_bytes() const noexcept
Definition analysis_frontends.hpp:183
bool prepare(const StreamingAnalysisConfig &config, AnalysisWindow window, bool require_fft=true)
Definition analysis_frontends.hpp:61
Definition custom_node_events.hpp:26
@ config
Per-user settings root (an XDG distinction; equals app_data off Linux).
Definition special_dir.hpp:65
Round-2 effect-wave vocabulary.
Definition analysis_frontends.hpp:50
AnalysisWindow
Definition analysis_frontends.hpp:52
@ symmetric_hann
Definition analysis_frontends.hpp:52
@ rectangular
Definition analysis_frontends.hpp:52
bool mix_planar_frame(const SampleType *const *channels, std::size_t channel_count, std::size_t frame, bool compute_power, double &mono, double &channel_power) noexcept
Definition analysis_frontends.hpp:239
int pitch_class_for_frequency(double frequency_hz) noexcept
Definition analysis_frontends.hpp:285
Definition additive_bank.hpp:218
ChromaFrontEndT< double > ChromaFrontEnd64
Definition analysis_frontends.hpp:601
bool checked_fft_retained_bytes(std::uint64_t fft_size, std::uint64_t target_max_bytes, std::uint64_t &bytes) noexcept
Complete retained-storage contract for one prepared FftT.
Definition fft.hpp:133
@ right
Definition multi_channel_meter.hpp:67
@ left
Definition multi_channel_meter.hpp:66
@ energy
sum h^2 = 1 per output ear (default; convolution reverb).
Definition zero_latency_convolver_support.hpp:160
double onset_energy_flux(double previous, double current) noexcept
Pure novelty transitions shared by fixed-capacity streaming analysis and background/offline adapters.
Definition analysis_frontends.hpp:26
@ maximum
Definition spectrum_trace.hpp:34
@ u
Definition formant_filter_bank.hpp:20
@ i
Definition formant_filter_bank.hpp:20
OnsetNoveltyFrontEndT< float > OnsetNoveltyFrontEnd
Definition analysis_frontends.hpp:602
OnsetDetectionMethod
Definition analysis_frontends.hpp:17
@ HighFrequencyContent
Definition analysis_frontends.hpp:20
@ SpectralFlux
Definition analysis_frontends.hpp:19
@ EnergyFlux
Definition analysis_frontends.hpp:18
ChromaFrontEndT< float > ChromaFrontEnd
Definition analysis_frontends.hpp:600
double onset_spectral_bin_flux(OnsetDetectionMethod method, double previous, double current, std::size_t bin) noexcept
Definition analysis_frontends.hpp:32
@ positive
y = dry + wet. Notches at (2k+1)/(2D).
Definition flanger.hpp:148
OnsetNoveltyFrontEndT< double > OnsetNoveltyFrontEnd64
Definition analysis_frontends.hpp:603
@ spectrum
Definition design_ir.hpp:265
One complete chroma analysis window.
Definition analysis_frontends.hpp:302
std::array< double, 12 > magnitude
Definition analysis_frontends.hpp:303
std::uint64_t window_center_frame
Definition analysis_frontends.hpp:306
std::uint64_t ready_at_frame
Definition analysis_frontends.hpp:307
std::uint64_t sequence
Definition analysis_frontends.hpp:308
std::array< SampleType, 12 > normalized
Definition analysis_frontends.hpp:304
std::uint64_t window_start_frame
Definition analysis_frontends.hpp:305
bool valid
Definition analysis_frontends.hpp:309
One complete novelty window.
Definition analysis_frontends.hpp:442
std::uint64_t sequence
Definition analysis_frontends.hpp:447
std::uint64_t window_center_frame
Definition analysis_frontends.hpp:445
double novelty
Definition analysis_frontends.hpp:443
std::uint64_t ready_at_frame
Definition analysis_frontends.hpp:446
std::uint64_t window_start_frame
Definition analysis_frontends.hpp:444
OnsetDetectionMethod method
Definition analysis_frontends.hpp:448
Definition analysis_frontends.hpp:42
double sample_rate
Definition analysis_frontends.hpp:43
std::size_t channels
Definition analysis_frontends.hpp:44
std::uint32_t fft_size
Definition analysis_frontends.hpp:45
std::uint64_t max_retained_fft_bytes
Definition analysis_frontends.hpp:47
std::uint64_t hop_size
Definition analysis_frontends.hpp:46