57 (fft_size & (fft_size - 1)) == 0;
61 static_assert(std::is_floating_point_v<SampleType>);
75 [[nodiscard]]
bool ok() const noexcept {
84 static_assert(std::is_floating_point_v<SampleType>);
91 std::uint64_t& bytes)
noexcept {
92 if (!config_valid_(config))
94 const auto bins =
static_cast<std::uint64_t
>(config.fft_size / 2 + 1);
95 std::uint64_t fft_bytes = 0;
97 if (!charge.
add<SampleType>(bins) ||
98 !charge.
add<std::complex<SampleType>>(
static_cast<std::uint64_t
>(config.fft_size)) ||
100 target_max_bytes, fft_bytes) ||
103 bytes = charge.
total();
108 const auto status = config_status_(config);
113#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
117 if (!next_fft.
ready())
119 std::vector<SampleType> next_smooth(
static_cast<std::size_t
>(config.fft_size / 2 + 1),
121 std::vector<std::complex<SampleType>> next_cepstrum(
122 static_cast<std::size_t
>(config.fft_size),
123 std::complex<SampleType>{SampleType{0}, SampleType{0}});
125 fft_ = std::move(next_fft);
126 smooth_input_ = std::move(next_smooth);
127 cepstrum_ = std::move(next_cepstrum);
130#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
131 }
catch (
const std::bad_alloc&) {
133 }
catch (
const std::length_error&) {
143 return prepared_ ? config_.fft_size : 0;
146 return prepared_ ? config_.fft_size / 2 + 1 : 0;
148 [[nodiscard]]
int order() const noexcept {
149 return prepared_ ? config_.order : 0;
155 std::span<SampleType> log_envelope)
noexcept {
158 const auto bins =
static_cast<std::size_t
>(
num_bins());
159 if (log_magnitude.size() != bins)
161 if (log_envelope.size() != bins)
163 for (
const auto value : log_magnitude) {
164 if (!std::isfinite(value))
167 if (!input_range_valid_(log_magnitude))
170 smooth_(log_magnitude, log_envelope);
172 for (; iterations < config_.true_envelope_iterations; ++iterations) {
173 for (std::size_t k = 0; k < bins; ++k)
174 smooth_input_[k] = std::max(log_magnitude[k], log_envelope[k]);
175 smooth_(smooth_input_, log_envelope);
176 if (config_.convergence_tolerance > SampleType{0}) {
177 SampleType residual = SampleType{0};
178 for (std::size_t k = 0; k < bins; ++k)
179 residual = std::max(residual, log_magnitude[k] - log_envelope[k]);
180 if (residual <= config_.convergence_tolerance) {
190 static bool config_valid_(
const Config& config)
noexcept {
197 if (config.order < 0 || config.order > config.fft_size / 2)
199 if (config.true_envelope_iterations < 0 ||
202 if (!std::isfinite(config.convergence_tolerance) ||
203 config.convergence_tolerance < SampleType{0})
208 bool input_range_valid_(std::span<const SampleType> log_spectrum)
const noexcept {
209 SampleType
maximum = SampleType{0};
210 for (
const auto value : log_spectrum)
217 const long double size =
static_cast<long double>(config_.fft_size);
218 const long double passes =
static_cast<long double>(config_.true_envelope_iterations + 2);
219 const long double conservative_fft_growth = 4.0L *
size * std::sqrt(size) * passes;
220 const long double limit =
static_cast<long double>(std::numeric_limits<SampleType>::max()) /
221 conservative_fft_growth;
222 return static_cast<long double>(
maximum) <= limit;
225 void smooth_(std::span<const SampleType> log_spectrum,
226 std::span<SampleType> log_envelope)
noexcept {
227 const int n = config_.fft_size;
228 const int bins =
n / 2 + 1;
229 const auto* input = log_spectrum.data();
230 auto* output = log_envelope.data();
231 for (
int k = 0;
k < bins; ++
k)
232 cepstrum_[
static_cast<std::size_t
>(k)] = {input[
k], SampleType{0}};
233 for (
int k = bins;
k <
n; ++
k)
234 cepstrum_[
static_cast<std::size_t
>(k)] = {input[
n -
k], SampleType{0}};
235 fft_.inverse(cepstrum_.data());
236 for (
int q = config_.order + 1; q < n - config_.order; ++q)
237 cepstrum_[
static_cast<std::size_t
>(
q)] = {SampleType{0}, SampleType{0}};
238 fft_.forward(cepstrum_.data());
239 for (
int k = 0;
k < bins; ++
k)
240 output[k] = cepstrum_[
static_cast<std::size_t
>(k)].real();
245 std::vector<SampleType> smooth_input_;
246 std::vector<std::complex<SampleType>> cepstrum_;
247 bool prepared_ =
false;
259 [[nodiscard]]
bool ok() const noexcept {
267template <
typename SampleType>
268[[nodiscard]] AutocorrelationResultT<SampleType>
270 std::span<SampleType> autocorrelation)
noexcept {
271 static_assert(std::is_floating_point_v<SampleType>);
274 if (samples.size() <=
static_cast<std::size_t
>(order))
276 if (autocorrelation.size() !=
static_cast<std::size_t
>(order + 1))
279 SampleType scale = SampleType{0};
280 for (
const auto sample : samples) {
281 if (!std::isfinite(sample))
283 scale = std::max(scale, std::abs(sample));
285 if (!(scale > SampleType{0}))
288 const long double promoted_scale =
static_cast<long double>(scale);
289 const long double divisor =
static_cast<long double>(samples.size());
290 for (
int lag = 0; lag <= order; ++lag) {
291 long double sum = 0.0L;
292 const auto count = samples.size() -
static_cast<std::size_t
>(lag);
293 for (std::size_t
i = 0;
i < count; ++
i) {
294 const long double left =
static_cast<long double>(samples[
i]) / promoted_scale;
295 const long double right =
296 static_cast<long double>(samples[
i +
static_cast<std::size_t
>(lag)]) /
300 autocorrelation[
static_cast<std::size_t
>(lag)] =
static_cast<SampleType
>(sum / divisor);
309 [[nodiscard]]
bool ok() const noexcept {
317template <
typename SampleType>
318[[nodiscard]] LevinsonDurbinResultT<SampleType>
319levinson_durbin(std::span<const SampleType> autocorrelation, std::span<SampleType> coefficients,
320 std::span<SampleType> reflection_coefficients, std::span<SampleType> workspace,
321 SampleType rank_tolerance = std::numeric_limits<SampleType>::epsilon() *
322 SampleType{64})
noexcept {
323 static_assert(std::is_floating_point_v<SampleType>);
324 const auto order = coefficients.size();
325 const auto clear_outputs = [&] {
326 std::fill(coefficients.begin(), coefficients.end(), SampleType{0});
327 std::fill(reflection_coefficients.begin(), reflection_coefficients.end(), SampleType{0});
330 if (order == 0 || order >
static_cast<std::size_t
>(kSourceFilterMaximumLpcOrder) ||
331 autocorrelation.size() != order + 1 || reflection_coefficients.size() != order)
332 return {SourceFilterAnalysisStatus::InvalidOrder, SampleType{0}};
333 if (workspace.size() != order)
334 return {SourceFilterAnalysisStatus::InvalidWorkspaceSize, SampleType{0}};
335 if (!std::isfinite(rank_tolerance) || rank_tolerance <= SampleType{0} ||
336 rank_tolerance >= SampleType{1})
337 return {SourceFilterAnalysisStatus::InvalidTolerance, SampleType{0}};
338 for (
const auto value : autocorrelation) {
339 if (!std::isfinite(value))
340 return {SourceFilterAnalysisStatus::NonFiniteInput, SampleType{0}};
342 if (!(autocorrelation[0] > SampleType{0}))
343 return {SourceFilterAnalysisStatus::DegenerateInput, SampleType{0}};
345 long double error =
static_cast<long double>(autocorrelation[0]);
346 const long double tolerance =
static_cast<long double>(rank_tolerance);
347 const long double minimum_error =
error * tolerance;
348 const long double sample_max =
static_cast<long double>(std::numeric_limits<SampleType>::max());
349 const auto assign_checked = [&](
long double value, SampleType& destination) {
350 if (!std::isfinite(value) || std::abs(value) > sample_max)
352 destination =
static_cast<SampleType
>(
value);
353 return std::isfinite(destination);
355 for (std::size_t stage = 0; stage < order; ++stage) {
356 long double numerator =
static_cast<long double>(autocorrelation[stage + 1]);
357 for (std::size_t j = 0;
j < stage; ++
j)
358 numerator +=
static_cast<long double>(coefficients[j]) *
359 static_cast<long double>(autocorrelation[stage -
j]);
360 const long double reflection_ld = -numerator /
error;
361 if (!std::isfinite(reflection_ld)) {
363 return {SourceFilterAnalysisStatus::RankDeficient, SampleType{0}};
365 if (std::abs(reflection_ld) >= 1.0L - tolerance) {
366 const auto status = std::abs(reflection_ld) > 1.0L + tolerance
367 ? SourceFilterAnalysisStatus::UnstableModel
368 : SourceFilterAnalysisStatus::RankDeficient;
370 return {status, SampleType{0}};
373 std::copy(coefficients.begin(), coefficients.end(), workspace.begin());
374 for (std::size_t j = 0;
j < stage; ++
j) {
375 const long double updated =
376 static_cast<long double>(workspace[
j]) +
377 reflection_ld *
static_cast<long double>(workspace[stage - 1 - j]);
378 if (!assign_checked(updated, coefficients[j])) {
380 return {SourceFilterAnalysisStatus::NumericalOverflow, SampleType{0}};
383 if (!assign_checked(reflection_ld, coefficients[stage]) ||
384 !assign_checked(reflection_ld, reflection_coefficients[stage])) {
386 return {SourceFilterAnalysisStatus::NumericalOverflow, SampleType{0}};
388 error *= 1.0L - reflection_ld * reflection_ld;
389 if (!std::isfinite(error) || error <= minimum_error) {
391 return {SourceFilterAnalysisStatus::RankDeficient, SampleType{0}};
394 if (error > sample_max) {
396 return {SourceFilterAnalysisStatus::NumericalOverflow, SampleType{0}};
398 return {SourceFilterAnalysisStatus::Ok,
static_cast<SampleType
>(
error)};
409 [[nodiscard]]
bool ok() const noexcept {
415 static_assert(std::is_floating_point_v<SampleType>);
421 std::uint64_t& bytes)
noexcept {
425 if (!charge.
add<SampleType>(
static_cast<std::uint64_t
>(
order + 1)) ||
428 bytes = charge.
total();
433 prepare(
int order, SampleType rank_tolerance = std::numeric_limits<SampleType>::epsilon() *
438 if (!std::isfinite(rank_tolerance) || rank_tolerance <= SampleType{0} ||
439 rank_tolerance >= SampleType{1}) {
440 return SourceFilterAnalysisStatus::InvalidTolerance;
443#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
446 std::vector<SampleType> next_autocorrelation(
static_cast<std::size_t
>(order + 1),
448 std::vector<SampleType> next_coefficients(
static_cast<std::size_t
>(order),
450 std::vector<SampleType> next_reflections(
static_cast<std::size_t
>(order),
452 std::vector<SampleType> next_workspace(
static_cast<std::size_t
>(order), SampleType{0});
454 rank_tolerance_ = rank_tolerance;
455 autocorrelation_ = std::move(next_autocorrelation);
456 coefficients_ = std::move(next_coefficients);
457 reflections_ = std::move(next_reflections);
458 workspace_ = std::move(next_workspace);
461 return SourceFilterAnalysisStatus::Ok;
462#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
463 }
catch (
const std::bad_alloc&) {
464 return SourceFilterAnalysisStatus::AllocationFailure;
465 }
catch (
const std::length_error&) {
466 return SourceFilterAnalysisStatus::AllocationFailure;
472 [[nodiscard]]
Result analyze(std::span<const SampleType> samples)
noexcept {
476 if (samples.size() <=
static_cast<std::size_t
>(order_))
479 const auto autocorrelation_result =
481 if (!autocorrelation_result.ok())
482 return result_ = {autocorrelation_result.status};
484 autocorrelation_, coefficients_, reflections_, workspace_, rank_tolerance_);
485 if (!solver_result.ok()) {
487 return result_ = {solver_result.status};
490 const long double scale =
static_cast<long double>(autocorrelation_result.input_scale);
491 const long double prediction_error =
492 static_cast<long double>(solver_result.normalized_prediction_error) * scale * scale;
493 if (!std::isfinite(prediction_error) || prediction_error < 0.0L ||
494 prediction_error >
static_cast<long double>(std::numeric_limits<SampleType>::max())) {
499 solver_result.normalized_prediction_error,
500 static_cast<SampleType
>(prediction_error)};
507 [[nodiscard]]
int order() const noexcept {
508 return prepared_ ? order_ : 0;
513 [[nodiscard]] std::span<const SampleType>
coefficients() const noexcept {
514 return result_.ok() ? std::span<const SampleType>(coefficients_)
515 : std::span<const SampleType>{};
518 return result_.ok() ? std::span<const SampleType>(reflections_)
519 : std::span<const SampleType>{};
523 void clear_result_() noexcept {
524 std::fill(coefficients_.begin(), coefficients_.end(), SampleType{0});
525 std::fill(reflections_.begin(), reflections_.end(), SampleType{0});
530 SampleType rank_tolerance_ = SampleType{0};
531 std::vector<SampleType> autocorrelation_;
532 std::vector<SampleType> coefficients_;
533 std::vector<SampleType> reflections_;
534 std::vector<SampleType> workspace_;
536 bool prepared_ =
false;
546template <
typename SampleType>
548lpc_stability(std::span<const SampleType> coefficients, std::span<SampleType> workspace,
549 SampleType stability_margin = std::numeric_limits<SampleType>::epsilon() *
550 SampleType{64})
noexcept {
551 static_assert(std::is_floating_point_v<SampleType>);
552 const auto order = coefficients.size();
553 if (order == 0 || order >
static_cast<std::size_t
>(kSourceFilterMaximumLpcOrder))
554 return SourceFilterAnalysisStatus::InvalidOrder;
555 if (workspace.size() != order)
556 return SourceFilterAnalysisStatus::InvalidWorkspaceSize;
557 if (!std::isfinite(stability_margin) || stability_margin <= SampleType{0} ||
558 stability_margin >= SampleType{1})
559 return SourceFilterAnalysisStatus::InvalidTolerance;
560 for (
const auto coefficient : coefficients) {
561 if (!std::isfinite(coefficient))
562 return SourceFilterAnalysisStatus::NonFiniteInput;
564 std::copy(coefficients.begin(), coefficients.end(), workspace.begin());
565 for (std::size_t stage = order; stage > 0; --stage) {
566 const long double reflection =
static_cast<long double>(workspace[stage - 1]);
567 const long double margin =
static_cast<long double>(stability_margin);
568 if (!std::isfinite(reflection) || std::abs(reflection) >= 1.0L - margin)
569 return SourceFilterAnalysisStatus::UnstableModel;
570 const long double denominator = 1.0L - reflection * reflection;
571 const long double sample_max =
572 static_cast<long double>(std::numeric_limits<SampleType>::max());
573 const auto assign_checked = [&](
long double value, SampleType& destination) {
574 if (!std::isfinite(value) || std::abs(value) > sample_max)
576 destination =
static_cast<SampleType
>(
value);
577 return std::isfinite(destination);
579 const std::size_t remaining = stage - 1;
580 for (std::size_t i = 0;
i < remaining / 2; ++
i) {
581 const std::size_t
j = remaining - 1 -
i;
582 const long double left =
static_cast<long double>(workspace[
i]);
583 const long double right =
static_cast<long double>(workspace[
j]);
584 if (!assign_checked((left - reflection * right) / denominator, workspace[i]) ||
585 !assign_checked((right - reflection * left) / denominator, workspace[j]))
586 return SourceFilterAnalysisStatus::NumericalOverflow;
588 if ((remaining & 1u) != 0u) {
589 const std::size_t
middle = remaining / 2;
590 if (!assign_checked(
static_cast<long double>(workspace[middle]) / (1.0L + reflection),
592 return SourceFilterAnalysisStatus::NumericalOverflow;
595 return SourceFilterAnalysisStatus::Ok;
601template <
typename SampleType>
603 std::span<const SampleType> coefficients, SampleType gain, SampleType sample_rate,
int fft_size,
604 std::span<SampleType> magnitude, std::span<SampleType> stability_workspace,
605 SampleType stability_margin = std::numeric_limits<SampleType>::epsilon() * SampleType{64},
606 SampleType denominator_floor = std::numeric_limits<SampleType>::epsilon() *
607 SampleType{64})
noexcept {
608 static_assert(std::is_floating_point_v<SampleType>);
609 if (!source_filter_fft_size_valid(fft_size))
610 return SourceFilterAnalysisStatus::InvalidFftSize;
611 if (!std::isfinite(sample_rate) || sample_rate <= SampleType{0})
612 return SourceFilterAnalysisStatus::InvalidSampleRate;
613 if (!std::isfinite(gain) || gain < SampleType{0})
614 return SourceFilterAnalysisStatus::InvalidGain;
615 if (magnitude.size() !=
static_cast<std::size_t
>(fft_size / 2 + 1))
616 return SourceFilterAnalysisStatus::InvalidOutputSize;
617 if (!std::isfinite(denominator_floor) || denominator_floor <= SampleType{0})
618 return SourceFilterAnalysisStatus::InvalidTolerance;
619 const auto stability =
lpc_stability(coefficients, stability_workspace, stability_margin);
620 if (stability != SourceFilterAnalysisStatus::Ok)
623 constexpr long double pi = 3.141592653589793238462643383279502884L;
624 const auto bins =
static_cast<std::size_t
>(fft_size / 2 + 1);
625 const auto response_value = [&](std::size_t bin) {
626 const long double frequency =
static_cast<long double>(bin) *
627 static_cast<long double>(sample_rate) /
628 static_cast<long double>(fft_size);
629 const long double omega = 2.0L *
pi * frequency /
static_cast<long double>(sample_rate);
630 std::complex<long double> denominator{1.0L, 0.0L};
631 for (std::size_t k = 0;
k < coefficients.size(); ++
k)
632 denominator +=
static_cast<long double>(coefficients[k]) *
633 std::polar(1.0L, -omega *
static_cast<long double>(k + 1));
634 const long double absolute = std::abs(denominator);
635 if (!std::isfinite(absolute) || absolute <
static_cast<long double>(denominator_floor))
636 return std::numeric_limits<long double>::infinity();
637 return static_cast<long double>(gain) / absolute;
639 for (std::size_t bin = 0; bin < bins; ++bin) {
640 const long double value = response_value(bin);
641 if (!std::isfinite(value) || value < 0.0L ||
642 value >
static_cast<long double>(std::numeric_limits<SampleType>::max()))
643 return SourceFilterAnalysisStatus::ResponseSingularity;
645 for (std::size_t bin = 0; bin < bins; ++bin)
646 magnitude[bin] =
static_cast<SampleType
>(response_value(bin));
647 return SourceFilterAnalysisStatus::Ok;
Log-magnitude spectrum to liftered log-envelope.
Definition source_filter_analysis.hpp:83
SourceFilterAnalysisStatus prepare(const Config &config)
Definition source_filter_analysis.hpp:107
int num_bins() const noexcept
Definition source_filter_analysis.hpp:145
int order() const noexcept
Definition source_filter_analysis.hpp:148
bool prepared() const noexcept
Definition source_filter_analysis.hpp:139
static bool checked_retained_bytes(const Config &config, std::uint64_t target_max_bytes, std::uint64_t &bytes) noexcept
Definition source_filter_analysis.hpp:90
CepstralEnvelopeResultT< SampleType > Result
Definition source_filter_analysis.hpp:88
int fft_size() const noexcept
Definition source_filter_analysis.hpp:142
CepstralEnvelopeConfigT< SampleType > Config
Definition source_filter_analysis.hpp:87
Result estimate(std::span< const SampleType > log_magnitude, std::span< SampleType > log_envelope) noexcept
Rejected input leaves log_envelope unchanged.
Definition source_filter_analysis.hpp:154
Definition checked_allocation.hpp:57
bool add(std::uint64_t elements) noexcept
Definition checked_allocation.hpp:63
std::uint64_t total() const noexcept
Definition checked_allocation.hpp:83
bool add_retained_bytes(std::uint64_t bytes) noexcept
Definition checked_allocation.hpp:78
bool add_repeated(std::uint64_t elements_per_allocation, std::uint64_t repetitions) noexcept
Definition checked_allocation.hpp:70
bool ready() const noexcept
True when every backend resource required by forward()/inverse() is available.
Definition fft.hpp:296
Definition source_filter_analysis.hpp:414
Result result() const noexcept
Definition source_filter_analysis.hpp:510
LpcAnalysisResultT< SampleType > Result
Definition source_filter_analysis.hpp:418
bool prepared() const noexcept
Definition source_filter_analysis.hpp:504
Result analyze(std::span< const SampleType > samples) noexcept
Failure clears the published coefficient, reflection, and error views.
Definition source_filter_analysis.hpp:472
std::span< const SampleType > reflection_coefficients() const noexcept
Definition source_filter_analysis.hpp:517
int order() const noexcept
Definition source_filter_analysis.hpp:507
static bool checked_retained_bytes(int order, std::uint64_t target_max_bytes, std::uint64_t &bytes) noexcept
Definition source_filter_analysis.hpp:420
std::span< const SampleType > coefficients() const noexcept
Definition source_filter_analysis.hpp:513
SourceFilterAnalysisStatus prepare(int order, SampleType rank_tolerance=std::numeric_limits< SampleType >::epsilon() *SampleType{64})
Definition source_filter_analysis.hpp:433
@ right
Definition canvas.hpp:221
@ left
Definition canvas.hpp:221
@ middle
Definition canvas.hpp:230
@ Config
Set via InspectorConfig / setEditorUrlTemplate.
Definition editor_url.hpp:50
@ size
Definition config.hpp:216
constexpr double pi
Definition fir_design.hpp:164
Definition additive_bank.hpp:218
SourceFilterAnalysisStatus lpc_stability(std::span< const SampleType > coefficients, std::span< SampleType > workspace, SampleType stability_margin=std::numeric_limits< SampleType >::epsilon() *SampleType{64}) noexcept
Explicit Schur step-down stability test for the A(z) coefficient convention used above.
Definition source_filter_analysis.hpp:548
SourceFilterAnalysisStatus
Definition source_filter_analysis.hpp:28
@ InvalidTolerance
Definition source_filter_analysis.hpp:34
@ NonFiniteInput
Definition source_filter_analysis.hpp:39
@ InvalidFftSize
Definition source_filter_analysis.hpp:31
@ InvalidGain
Definition source_filter_analysis.hpp:46
@ InvalidWorkspaceSize
Definition source_filter_analysis.hpp:37
@ NotPrepared
Definition source_filter_analysis.hpp:30
@ InvalidSampleRate
Definition source_filter_analysis.hpp:45
@ InvalidOutputSize
Definition source_filter_analysis.hpp:36
@ DegenerateInput
Definition source_filter_analysis.hpp:41
@ InvalidIterationCount
Definition source_filter_analysis.hpp:33
@ Ok
Definition source_filter_analysis.hpp:29
@ RankDeficient
Definition source_filter_analysis.hpp:42
@ InvalidOrder
Definition source_filter_analysis.hpp:32
@ UnstableModel
Definition source_filter_analysis.hpp:43
@ PredictionErrorOverflow
Definition source_filter_analysis.hpp:44
@ NumericalOverflow
Definition source_filter_analysis.hpp:40
@ AllocationFailure
Definition source_filter_analysis.hpp:38
@ ResponseSingularity
Definition source_filter_analysis.hpp:47
@ InvalidInputSize
Definition source_filter_analysis.hpp:35
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
CepstralEnvelopeAnalyzerT< double > CepstralEnvelopeAnalyzer64
Definition source_filter_analysis.hpp:253
constexpr int kSourceFilterMaximumEnvelopeIterations
Definition source_filter_analysis.hpp:53
SourceFilterAnalysisStatus all_pole_magnitude_response(std::span< const SampleType > coefficients, SampleType gain, SampleType sample_rate, int fft_size, std::span< SampleType > magnitude, std::span< SampleType > stability_workspace, SampleType stability_margin=std::numeric_limits< SampleType >::epsilon() *SampleType{64}, SampleType denominator_floor=std::numeric_limits< SampleType >::epsilon() *SampleType{64}) noexcept
Evaluates gain / |A(e^jw)| at fft_size / 2 + 1 bins from DC through Nyquist.
Definition source_filter_analysis.hpp:602
CepstralEnvelopeAnalyzerT< float > CepstralEnvelopeAnalyzer
Definition source_filter_analysis.hpp:252
constexpr int kSourceFilterMaximumLpcOrder
Definition source_filter_analysis.hpp:52
LpcAnalyzerT< double > LpcAnalyzer64
Definition source_filter_analysis.hpp:540
CepstralEnvelopeConfigT< double > CepstralEnvelopeConfig64
Definition source_filter_analysis.hpp:251
CepstralEnvelopeConfigT< float > CepstralEnvelopeConfig
Definition source_filter_analysis.hpp:250
@ maximum
Definition spectrum_trace.hpp:34
@ i
Definition formant_filter_bank.hpp:20
bool source_filter_fft_size_valid(int fft_size) noexcept
Definition source_filter_analysis.hpp:55
constexpr int kSourceFilterMinimumFftSize
Definition source_filter_analysis.hpp:50
LevinsonDurbinResultT< SampleType > levinson_durbin(std::span< const SampleType > autocorrelation, std::span< SampleType > coefficients, std::span< SampleType > reflection_coefficients, std::span< SampleType > workspace, SampleType rank_tolerance=std::numeric_limits< SampleType >::epsilon() *SampleType{64}) noexcept
Solves A(z) = 1 + sum(a[k] z^-(k+1)).
Definition source_filter_analysis.hpp:319
LpcAnalyzerT< float > LpcAnalyzer
Definition source_filter_analysis.hpp:539
AutocorrelationResultT< SampleType > scaled_autocorrelation(std::span< const SampleType > samples, int order, std::span< SampleType > autocorrelation) noexcept
Biased autocorrelation of a safely normalized signal.
Definition source_filter_analysis.hpp:269
constexpr int kSourceFilterMaximumFftSize
Definition source_filter_analysis.hpp:51
@ value
the widget's primary value (Knob, Fader, RangeSlider, Toggle, ProgressBar)
Definition binding_diagnostics.hpp:19
@ j
Definition input_events.hpp:40
@ q
Definition input_events.hpp:41
@ n
Definition input_events.hpp:40
@ k
Definition input_events.hpp:40
Definition source_filter_analysis.hpp:255
SourceFilterAnalysisStatus status
Definition source_filter_analysis.hpp:256
bool ok() const noexcept
Definition source_filter_analysis.hpp:259
SampleType input_scale
Definition source_filter_analysis.hpp:257
Definition source_filter_analysis.hpp:60
int true_envelope_iterations
Definition source_filter_analysis.hpp:65
int fft_size
Definition source_filter_analysis.hpp:63
float convergence_tolerance
Definition source_filter_analysis.hpp:68
int order
Definition source_filter_analysis.hpp:64
Definition source_filter_analysis.hpp:71
int iterations_performed
Definition source_filter_analysis.hpp:73
bool ok() const noexcept
Definition source_filter_analysis.hpp:75
SourceFilterAnalysisStatus status
Definition source_filter_analysis.hpp:72
Definition source_filter_analysis.hpp:305
SourceFilterAnalysisStatus status
Definition source_filter_analysis.hpp:306
SampleType normalized_prediction_error
Definition source_filter_analysis.hpp:307
bool ok() const noexcept
Definition source_filter_analysis.hpp:309
Definition source_filter_analysis.hpp:401
SampleType normalized_prediction_error
Definition source_filter_analysis.hpp:405
SampleType input_scale
Definition source_filter_analysis.hpp:404
bool ok() const noexcept
Definition source_filter_analysis.hpp:409
SampleType prediction_error
Prediction-error power in the original sample-squared units.
Definition source_filter_analysis.hpp:407
SourceFilterAnalysisStatus status
Definition source_filter_analysis.hpp:402
int order
Definition source_filter_analysis.hpp:403