Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
sample_heritage_schema.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <array>
5#include <cmath>
6#include <cstddef>
7#include <cstdint>
8#include <iterator>
9#include <string>
10#include <string_view>
11#include <type_traits>
12#include <utility>
13#include <variant>
14#include <vector>
15
16namespace pulp::audio {
17
18inline constexpr std::uint32_t kSampleHeritageProfileSchemaVersion = 3;
19inline constexpr std::uint32_t kSampleHeritageProfileDigestVersion = 5;
20inline constexpr std::uint32_t kSampleHeritageSpectralTiltLawVersion = 1;
21inline constexpr double kSampleHeritageMaximumLadderCutoffRatio = 0.49;
22inline constexpr float kSampleHeritageMaximumLadderResonance = 0.3f;
23inline constexpr std::size_t kSampleHeritageMaximumStages = 7;
24inline constexpr std::size_t kSampleHeritageMaximumVoiceBlocks = 8;
25inline constexpr std::size_t kSampleHeritageMaximumBusBlocks = 2;
26inline constexpr std::size_t kSampleHeritageMaximumRecordCommitBlocks = 4;
27inline constexpr std::size_t kSampleHeritageMaximumChannels = 8;
28inline constexpr std::size_t kSampleHeritageMaximumProfileIdBytes = 63;
29
34
35enum class SampleHeritageBlockDomain : std::uint8_t { Voice, Bus, RecordCommit };
41enum class SampleHeritageConverterFamily : std::uint8_t {
45};
46enum class SampleHeritageHoldMode : std::uint8_t { ZeroOrder };
47enum class SampleHeritageCutoffLaw : std::uint8_t { FixedHz, MachineRateRatio };
48enum class SampleHeritageNoiseGate : std::uint8_t { AlwaysOn, VoiceActive };
61enum class SampleHeritageAnalogFilterFamily : std::uint8_t { None, Ladder4Pole };
62enum class SampleHeritageLivePitchMode : std::uint8_t { Preserve, RateLinked };
63
65struct SampleHeritageVoiceClockBlock { double ratio = 1.0; };
115
125
132
134 float noise_amplitude = 0.0f;
135 float idle_amplitude = 0.0f;
136 float tilt_db_per_octave = 0.0f;
138 std::uint64_t seed = 0;
141 // Tilt law version 1 is a deterministic cascade of unit-slope RBJ high
142 // shelves. The lowest shelf starts at tilt_floor_hz. Successive shelves
143 // span one octave, or the last partial octave through Nyquist, with a
144 // geometric-mean center and tilt_db_per_octave times the octave width.
145 // The cascade is normalized to 0 dB at tilt_reference_hz. The requested
146 // slope is a target, not an exact power law. Below the floor, response
147 // approaches the low-frequency asymptote rather than being hard-clamped.
148 // Compatibility compares the prepared response; the ideal slope has no
149 // normative error tolerance.
150 double tilt_reference_hz = 1000.0;
151 double tilt_floor_hz = 20.0;
152};
154 float drive = 1.0f;
155 float ceiling = 1.0f;
156};
165
167 float drive = 1.0f;
168 float clip_level = 1.0f;
169};
190 double factor = 1.0;
191 std::uint32_t cycle_samples = 1;
192 std::uint32_t crossfade_samples = 0;
193 std::uint64_t zone_start_frame = 0;
194 std::uint64_t zone_end_frame = 0;
195};
197 double factor = 1.0;
198 std::uint32_t decision_hop_samples = 1;
199 std::uint32_t search_radius_samples = 0;
200 std::uint32_t search_stride_samples = 1;
201 std::uint32_t crossfade_samples = 0;
202 std::uint64_t zone_start_frame = 0;
203 std::uint64_t zone_end_frame = 0;
204 bool stereo_link = true;
205 std::uint8_t quality = 99;
206 std::uint8_t width = 99;
207};
208
211 return static_cast<std::uint32_t>(
212 (static_cast<std::uint64_t>(block.search_radius_samples) * block.quality + 49u) / 99u);
213}
214
217 return static_cast<std::uint32_t>(
218 (static_cast<std::uint64_t>(block.crossfade_samples) * block.width + 49u) / 99u);
219}
231
235
243
245 double ratio = 1.0;
246};
247
249 std::uint32_t hold_samples = 1;
250};
251
255
262
264 float gain = 1.0f;
265};
266
275
280
285 std::string profile_id;
286 double host_sample_rate = 0.0;
287 std::vector<SampleHeritageVoiceBlockSpec> voice;
288 std::vector<SampleHeritageBusBlockSpec> bus;
289 std::vector<SampleHeritageRecordCommitBlockSpec> record_commit;
290
291 // Flat stages are an in-memory engine representation and never cross the
292 // profile JSON boundary.
293 std::vector<SampleHeritageStageSpec> stages;
294};
295
297 std::uint32_t schema_version = 0;
298 std::array<char, kSampleHeritageMaximumProfileIdBytes + 1> profile_id{};
299 double host_sample_rate = 0.0;
300 std::array<SampleHeritageVoiceBlockSpec, kSampleHeritageMaximumVoiceBlocks>
302 std::size_t voice_count = 0;
303 std::array<SampleHeritageBusBlockSpec, kSampleHeritageMaximumBusBlocks> bus{};
304 std::size_t bus_count = 0;
307 std::size_t record_commit_count = 0;
308 // The post-mix engine consumes flat stages; profile JSON does not.
309 std::array<SampleHeritageStageSpec, kSampleHeritageMaximumStages> stages{};
310 std::size_t stage_count = 0;
311 std::array<std::uint8_t, 32> profile_digest{};
312
313 std::string_view id() const noexcept {
314 const auto end = std::find(profile_id.begin(), profile_id.end(), '\0');
315 return {profile_id.data(),
316 static_cast<std::size_t>(std::distance(profile_id.begin(), end))};
317 }
318};
319
336
346
347namespace detail {
348
349inline bool valid_neutral_profile_id(std::string_view id) noexcept {
350 constexpr std::string_view prefix = "neutral.";
351 if (!id.starts_with(prefix) || id.size() <= prefix.size() ||
353 return false;
354 }
355 bool previous_separator = true;
356 for (std::size_t index = prefix.size(); index < id.size(); ++index) {
357 const char character = id[index];
358 const bool alpha = character >= 'a' && character <= 'z';
359 const bool digit = character >= '0' && character <= '9';
360 const bool separator = character == '.' || character == '-';
361 if (!alpha && !digit && !separator) return false;
362 if (separator && previous_separator) return false;
363 previous_separator = separator;
364 }
365 return !previous_separator;
366}
367
368template <typename Stage>
369inline constexpr std::size_t stage_type_index = [] {
370 if constexpr (std::is_same_v<Stage, SampleHeritageMachineDomainStage>) return 0u;
371 if constexpr (std::is_same_v<Stage, SampleHeritageQuantizationStage>) return 1u;
372 if constexpr (std::is_same_v<Stage, SampleHeritageClockPitchStage>) return 2u;
373 if constexpr (std::is_same_v<Stage, SampleHeritageDacHoldStage>) return 3u;
374 if constexpr (std::is_same_v<Stage, SampleHeritageReconstructionFilterStage>) return 4u;
375 if constexpr (std::is_same_v<Stage, SampleHeritageNoiseStage>) return 5u;
376 return 6u;
377}();
378
379} // namespace detail
380
384std::array<std::uint8_t, 32> sample_heritage_profile_digest(const SampleHeritageProfile& profile);
385
389 if (source.schema_version != kSampleHeritageProfileSchemaVersion) {
391 return result;
392 }
393 if (!detail::valid_neutral_profile_id(source.profile_id)) {
395 return result;
396 }
397 if (!(source.host_sample_rate >= 8000.0 && source.host_sample_rate <= 384000.0) ||
398 !std::isfinite(source.host_sample_rate)) {
400 return result;
401 }
402 const bool has_typed_blocks = !source.voice.empty() || !source.bus.empty() ||
403 !source.record_commit.empty();
404 if (has_typed_blocks && !source.stages.empty()) {
406 return result;
407 }
408 if (source.stages.size() > kSampleHeritageMaximumStages) {
410 return result;
411 }
412 if (source.voice.size() > kSampleHeritageMaximumVoiceBlocks ||
413 source.bus.size() > kSampleHeritageMaximumBusBlocks ||
414 source.record_commit.size() > kSampleHeritageMaximumRecordCommitBlocks) {
416 return result;
417 }
418
419 if (has_typed_blocks) {
420 const auto finite_range = [](auto value, auto minimum, auto maximum) {
421 return std::isfinite(value) && value >= minimum && value <= maximum;
422 };
423 const auto valid_seed_policy = [](SampleHeritageSeedPolicy policy) {
426 };
427 const auto validate_seed = [&](float amount, std::uint64_t seed,
429 return valid_seed_policy(policy) &&
430 !((amount > 0.0f ||
432 seed == 0);
433 };
434 double voice_machine_rate = source.host_sample_rate;
435 for (const auto& spec : source.voice) {
436 if (spec.bypass) continue;
437 if (const auto* machine =
438 std::get_if<SampleHeritageVoiceMachineDomainBlock>(&spec.parameters))
439 voice_machine_rate = machine->sample_rate;
440 }
441 const auto validate_cutoff = [&](SampleHeritageCutoffLaw law,
442 double value,
443 double sample_rate) {
445 return std::isfinite(value) && value > 0.0 && value < 0.5;
446 return law == SampleHeritageCutoffLaw::FixedHz &&
447 std::isfinite(value) && value >= 1.0 &&
448 std::isfinite(sample_rate) && value < sample_rate * 0.5;
449 };
450 const auto resolved_voice_cutoff = [&](SampleHeritageCutoffLaw law,
451 double value) {
453 ? value * voice_machine_rate
454 : value;
455 };
456 const auto validate_ordered = [&](const auto& blocks,
458 auto validate_block) {
459 std::array<bool, std::variant_size_v<std::decay_t<decltype(blocks.front().parameters)>>> seen{};
460 std::size_t previous = 0;
461 bool have_previous = false;
462 for (std::size_t index = 0; index < blocks.size(); ++index) {
463 result.stage_index = index;
464 result.block_domain = domain;
465 if (blocks[index].domain != domain)
467 const auto type = blocks[index].parameters.index();
468 if (std::exchange(seen[type], true))
470 if (have_previous && type < previous)
472 previous = type;
473 have_previous = true;
474 if (!validate_block(blocks[index].parameters))
476 }
478 };
479
480 auto status = validate_ordered(
482 [&](const SampleHeritageVoiceBlockParameters& parameters) {
483 return std::visit(
484 [&](const auto& block) {
485 using Block = std::decay_t<decltype(block)>;
486 if constexpr (std::is_same_v<Block,
487 SampleHeritageVoiceMachineDomainBlock>)
488 return finite_range(block.sample_rate, 8000.0, 384000.0);
489 else if constexpr (std::is_same_v<Block,
490 SampleHeritageVoiceClockBlock>)
491 return finite_range(block.ratio, 0.015625, 64.0);
492 else if constexpr (std::is_same_v<Block,
493 SampleHeritageVoicePitchBlock>)
494 return (block.family == SampleHeritagePitchFamily::VariableClock ||
495 block.family == SampleHeritagePitchFamily::DropRepeat ||
496 block.family == SampleHeritagePitchFamily::EarlyLinear) &&
497 finite_range(block.max_transpose_semitones, 0.0, 96.0);
498 else if constexpr (std::is_same_v<Block,
499 SampleHeritageVoiceConverterBlock>)
500 return (block.family == SampleHeritageConverterFamily::LinearPcm ||
501 block.family == SampleHeritageConverterFamily::MuLaw ||
502 block.family == SampleHeritageConverterFamily::ALaw) &&
503 finite_range(block.bit_depth, 4.0f, 16.0f) &&
504 finite_range(block.dac_nonlinearity, 0.0f, 1.0f) &&
505 finite_range(block.dither_lsb, 0.0f, 2.0f) &&
506 validate_seed(block.dither_lsb, block.seed,
507 block.seed_policy);
508 else if constexpr (std::is_same_v<Block,
509 SampleHeritageVoiceHoldDroopBlock>)
510 return block.mode == SampleHeritageHoldMode::ZeroOrder &&
511 block.hold_samples >= 1 && block.hold_samples <= 65536 &&
512 finite_range(block.droop, 0.0f, 1.0f);
513 else if constexpr (std::is_same_v<Block,
514 SampleHeritageVoiceReconstructionBlock>)
515 return validate_cutoff(block.cutoff_law, block.cutoff_value,
516 voice_machine_rate) &&
517 resolved_voice_cutoff(block.cutoff_law,
518 block.cutoff_value) <
519 source.host_sample_rate * 0.5 &&
520 ((block.family ==
521 SampleHeritageReconstructionFamily::OnePole &&
522 block.order == 1 && block.ripple_db == 0.0f &&
523 block.stopband_attenuation_db == 0.0f) ||
524 (block.family ==
525 SampleHeritageReconstructionFamily::Butterworth &&
526 block.order >= 2 && block.order <= 16 &&
527 (block.order & 1u) == 0 &&
528 block.ripple_db == 0.0f &&
529 block.stopband_attenuation_db == 0.0f) ||
530 (block.family ==
531 SampleHeritageReconstructionFamily::Chebyshev &&
532 block.order >= 2 && block.order <= 16 &&
533 (block.order & 1u) == 0 &&
534 finite_range(block.ripple_db, 0.0f, 12.0f) &&
535 block.ripple_db > 0.0f &&
536 block.stopband_attenuation_db == 0.0f) ||
537 (block.family ==
538 SampleHeritageReconstructionFamily::Elliptic &&
539 block.order >= 2 && block.order <= 16 &&
540 (block.order & 1u) == 0 &&
541 finite_range(block.ripple_db, 0.0f, 12.0f) &&
542 block.ripple_db > 0.0f &&
543 finite_range(block.stopband_attenuation_db,
544 block.ripple_db, 180.0f) &&
545 block.stopband_attenuation_db > block.ripple_db));
546 else if constexpr (std::is_same_v<Block,
547 SampleHeritageVoiceAnalogColorBlock>)
548 return finite_range(block.drive, 0.0f, 16.0f) &&
549 finite_range(block.asymmetry, -1.0f, 1.0f) &&
550 finite_range(block.mix, 0.0f, 1.0f) &&
551 ((block.filter_family ==
552 SampleHeritageAnalogFilterFamily::None &&
553 block.cutoff_law ==
554 SampleHeritageCutoffLaw::FixedHz &&
555 block.cutoff_value == 0.0 &&
556 block.resonance == 0.0f) ||
557 (block.filter_family ==
558 SampleHeritageAnalogFilterFamily::Ladder4Pole &&
559 ((block.cutoff_law ==
560 SampleHeritageCutoffLaw::MachineRateRatio &&
561 std::isfinite(block.cutoff_value) &&
562 block.cutoff_value * voice_machine_rate >= 1.0 &&
563 block.cutoff_value <=
564 kSampleHeritageMaximumLadderCutoffRatio) ||
565 (block.cutoff_law ==
566 SampleHeritageCutoffLaw::FixedHz &&
567 std::isfinite(block.cutoff_value) &&
568 block.cutoff_value >= 1.0 &&
569 block.cutoff_value <=
570 voice_machine_rate *
571 kSampleHeritageMaximumLadderCutoffRatio)) &&
572 resolved_voice_cutoff(block.cutoff_law,
573 block.cutoff_value) <=
574 source.host_sample_rate *
575 kSampleHeritageMaximumLadderCutoffRatio &&
576 finite_range(
577 block.resonance, 0.0f,
578 kSampleHeritageMaximumLadderResonance)));
579 else
580 return finite_range(block.factor, 0.25, 20.0) &&
581 std::isfinite(block.cycle_ms) && block.cycle_ms > 0.0 &&
582 block.cycle_ms * voice_machine_rate * 0.001 <=
583 1048576.0 &&
584 finite_range(block.splice_ms, 0.0, 20.0) &&
585 block.splice_ms <= block.cycle_ms * 0.5 &&
586 (block.shuffle_divisions == 0 ||
587 (block.shuffle_divisions >= 2 &&
588 block.shuffle_divisions <= 64)) &&
589 (block.pitch_mode == SampleHeritageLivePitchMode::Preserve ||
590 block.pitch_mode == SampleHeritageLivePitchMode::RateLinked) &&
591 valid_seed_policy(block.seed_policy) &&
592 !((block.shuffle_divisions != 0 ||
593 block.seed_policy ==
594 SampleHeritageSeedPolicy::ContinueSerializedState) &&
595 block.seed == 0);
596 }, parameters);
597 });
599 status = validate_ordered(
601 [&](const SampleHeritageBusBlockParameters& parameters) {
602 return std::visit(
603 [&](const auto& block) {
604 using Block = std::decay_t<decltype(block)>;
605 if constexpr (std::is_same_v<Block,
606 SampleHeritageBusNoiseIdleBlock>)
607 return finite_range(block.noise_amplitude, 0.0f, 1.0f) &&
608 finite_range(block.idle_amplitude, 0.0f, 1.0f) &&
609 finite_range(block.tilt_db_per_octave, -24.0f,
610 24.0f) &&
611 std::isfinite(block.tilt_floor_hz) &&
612 block.tilt_floor_hz >= 1.0 &&
613 std::isfinite(block.tilt_reference_hz) &&
614 block.tilt_reference_hz >= block.tilt_floor_hz &&
615 block.tilt_reference_hz <
616 source.host_sample_rate * 0.5 &&
617 (block.gate == SampleHeritageNoiseGate::AlwaysOn ||
618 block.gate ==
619 SampleHeritageNoiseGate::VoiceActive) &&
620 validate_seed(
621 std::max(block.noise_amplitude,
622 block.idle_amplitude),
623 block.seed, block.seed_policy);
624 else
625 return finite_range(block.drive, 0.0f, 16.0f) &&
626 finite_range(block.ceiling, 0.001f, 4.0f);
627 }, parameters);
628 });
629 double record_processing_rate = source.host_sample_rate;
631 status = validate_ordered(
632 source.record_commit, SampleHeritageBlockDomain::RecordCommit,
633 [&](const SampleHeritageRecordCommitBlockParameters& parameters) {
634 return std::visit(
635 [&](const auto& block) {
636 using Block = std::decay_t<decltype(block)>;
637 if constexpr (std::is_same_v<Block,
638 SampleHeritageRecordInputDriveClipBlock>)
639 return finite_range(block.drive, 0.0f, 16.0f) &&
640 finite_range(block.clip_level, 0.001f, 4.0f);
641 else if constexpr (std::is_same_v<Block,
642 SampleHeritageRecordRateBlock>) {
643 const auto valid =
644 finite_range(block.sample_rate, 8000.0,
645 384000.0) &&
646 validate_cutoff(block.cutoff_law,
647 block.cutoff_value,
648 record_processing_rate) &&
649 ((block.filter_family ==
650 SampleHeritageRecordFilterFamily::OnePole &&
651 block.order == 1 && block.ripple_db == 0.0f &&
652 block.stopband_attenuation_db == 0.0f) ||
653 (block.filter_family ==
654 SampleHeritageRecordFilterFamily::Butterworth &&
655 block.order >= 2 && block.order <= 16 &&
656 (block.order & 1u) == 0 &&
657 block.ripple_db == 0.0f &&
658 block.stopband_attenuation_db == 0.0f) ||
659 (block.filter_family ==
660 SampleHeritageRecordFilterFamily::Chebyshev &&
661 block.order >= 2 && block.order <= 16 &&
662 (block.order & 1u) == 0 &&
663 finite_range(block.ripple_db, 0.0f, 12.0f) &&
664 block.ripple_db > 0.0f &&
665 block.stopband_attenuation_db == 0.0f) ||
666 (block.filter_family ==
667 SampleHeritageRecordFilterFamily::Elliptic &&
668 block.order >= 2 && block.order <= 16 &&
669 (block.order & 1u) == 0 &&
670 finite_range(block.ripple_db, 0.0f, 12.0f) &&
671 block.ripple_db > 0.0f &&
672 finite_range(block.stopband_attenuation_db,
673 block.ripple_db, 180.0f) &&
674 block.stopband_attenuation_db >
675 block.ripple_db));
676 if (valid &&
677 !source.record_commit[result.stage_index].bypass)
678 record_processing_rate = block.sample_rate;
679 return valid;
680 }
681 else if constexpr (std::is_same_v<Block,
682 SampleHeritageRecordConverterBlock>)
683 return (block.family == SampleHeritageConverterFamily::LinearPcm ||
684 block.family == SampleHeritageConverterFamily::MuLaw ||
685 block.family == SampleHeritageConverterFamily::ALaw) &&
686 finite_range(block.bit_depth, 4.0f, 16.0f) &&
687 finite_range(block.dac_nonlinearity, 0.0f, 1.0f) &&
688 finite_range(block.dither_lsb, 0.0f, 2.0f) &&
689 validate_seed(block.dither_lsb, block.seed,
690 block.seed_policy);
691 else if constexpr (std::is_same_v<
692 Block,
693 SampleHeritageRecordCommitCyclicStretchBlock>)
694 return
695 finite_range(block.factor, 0.25, 20.0) &&
696 block.cycle_samples >= 1 &&
697 block.cycle_samples <= 1048576 &&
698 block.crossfade_samples <= block.cycle_samples / 2 &&
699 ((block.zone_start_frame == 0 &&
700 block.zone_end_frame == 0) ||
701 block.zone_start_frame < block.zone_end_frame);
702 else
703 return finite_range(block.factor, 0.25, 20.0) &&
704 block.decision_hop_samples >= 1 &&
705 block.decision_hop_samples <= 1048576 &&
706 block.search_radius_samples <= 1048576 &&
707 block.search_stride_samples >= 1 &&
708 block.search_stride_samples <= 1048576 &&
709 block.crossfade_samples <= 524288 &&
710 block.crossfade_samples <= block.decision_hop_samples &&
711 block.quality <= 99 && block.width <= 99 &&
712 ((block.zone_start_frame == 0 &&
713 block.zone_end_frame == 0) ||
714 block.zone_start_frame < block.zone_end_frame);
715 }, parameters);
716 });
717 if (status != SampleHeritageProfileStatus::Ok) {
718 result.status = status;
719 return result;
720 }
721
722 result.profile.schema_version = source.schema_version;
723 std::copy(source.profile_id.begin(), source.profile_id.end(),
724 result.profile.profile_id.begin());
725 result.profile.host_sample_rate =
726 source.host_sample_rate == 0.0 ? 0.0 : source.host_sample_rate;
727 result.profile.voice_count = source.voice.size();
728 result.profile.bus_count = source.bus.size();
729 result.profile.record_commit_count = source.record_commit.size();
730 std::copy(source.voice.begin(), source.voice.end(), result.profile.voice.begin());
731 std::copy(source.bus.begin(), source.bus.end(), result.profile.bus.begin());
732 std::copy(source.record_commit.begin(), source.record_commit.end(),
733 result.profile.record_commit.begin());
734 try {
735 result.profile.profile_digest = sample_heritage_profile_digest(source);
736 } catch (...) {
737 result.status = SampleHeritageProfileStatus::DigestUnavailable;
738 return result;
739 }
740 result.status = SampleHeritageProfileStatus::Ok;
741 result.stage_index = source.record_commit.size();
742 return result;
743 }
744
745 double machine_sample_rate = source.host_sample_rate;
746 double clock_ratio = 1.0;
747 for (const auto& spec : source.stages) {
748 if (spec.bypass) continue;
749 if (const auto* machine =
750 std::get_if<SampleHeritageMachineDomainStage>(&spec.parameters)) {
751 machine_sample_rate = machine->sample_rate;
752 } else if (const auto* clock =
753 std::get_if<SampleHeritageClockPitchStage>(&spec.parameters)) {
754 clock_ratio = clock->ratio;
755 }
756 }
757 const auto clocked_sample_rate = machine_sample_rate * clock_ratio;
758
759 std::array<bool, kSampleHeritageMaximumStages> seen{};
760 for (std::size_t index = 0; index < source.stages.size(); ++index) {
761 const auto type = std::visit(
762 [](const auto& stage) noexcept {
763 using Stage = std::decay_t<decltype(stage)>;
764 return detail::stage_type_index<Stage>;
765 },
766 source.stages[index].parameters);
767 if (std::exchange(seen[type], true)) {
768 result.status = SampleHeritageProfileStatus::DuplicateStage;
769 result.stage_index = index;
770 return result;
771 }
772 }
773
774 std::size_t previous_type = 0;
775 bool have_previous_type = false;
776 for (std::size_t index = 0; index < source.stages.size(); ++index) {
777 result.stage_index = index;
778 const auto status = std::visit(
779 [&](const auto& stage) noexcept {
780 using Stage = std::decay_t<decltype(stage)>;
781 constexpr auto type = detail::stage_type_index<Stage>;
782 if (have_previous_type && type < previous_type)
783 return SampleHeritageProfileStatus::InvalidStageOrder;
784 previous_type = type;
785 have_previous_type = true;
786 if constexpr (std::is_same_v<Stage, SampleHeritageMachineDomainStage>) {
787 if (!(stage.sample_rate >= 8000.0 && stage.sample_rate <= 384000.0) ||
788 !std::isfinite(stage.sample_rate))
789 return SampleHeritageProfileStatus::InvalidStageParameter;
790 } else if constexpr (std::is_same_v<Stage,
791 SampleHeritageQuantizationStage>) {
792 if (stage.bit_depth < 2 || stage.bit_depth > 24 ||
793 !(stage.dither_lsb >= 0.0f && stage.dither_lsb <= 2.0f) ||
794 !std::isfinite(stage.dither_lsb) ||
795 (stage.seed_policy !=
796 SampleHeritageSeedPolicy::RestartFromProfileSeed &&
797 stage.seed_policy !=
798 SampleHeritageSeedPolicy::ContinueSerializedState) ||
799 ((stage.dither_lsb > 0.0f ||
800 stage.seed_policy ==
801 SampleHeritageSeedPolicy::ContinueSerializedState) &&
802 stage.seed == 0))
803 return SampleHeritageProfileStatus::InvalidStageParameter;
804 } else if constexpr (std::is_same_v<Stage, SampleHeritageClockPitchStage>) {
805 if (!(stage.ratio > 0.0) || !std::isfinite(stage.ratio))
806 return SampleHeritageProfileStatus::InvalidStageParameter;
807 } else if constexpr (std::is_same_v<Stage, SampleHeritageDacHoldStage>) {
808 if (stage.hold_samples == 0 || stage.hold_samples > 65536)
809 return SampleHeritageProfileStatus::InvalidStageParameter;
810 } else if constexpr (std::is_same_v<Stage,
811 SampleHeritageReconstructionFilterStage>) {
812 if (!(stage.cutoff_hz > 0.0 &&
813 stage.cutoff_hz < clocked_sample_rate * 0.5) ||
814 !std::isfinite(stage.cutoff_hz))
815 return SampleHeritageProfileStatus::InvalidStageParameter;
816 } else if constexpr (std::is_same_v<Stage, SampleHeritageNoiseStage>) {
817 if (!(stage.amplitude >= 0.0f && stage.amplitude <= 1.0f) ||
818 !std::isfinite(stage.amplitude) ||
819 (stage.seed_policy !=
820 SampleHeritageSeedPolicy::RestartFromProfileSeed &&
821 stage.seed_policy !=
822 SampleHeritageSeedPolicy::ContinueSerializedState) ||
823 ((stage.amplitude > 0.0f ||
824 stage.seed_policy ==
825 SampleHeritageSeedPolicy::ContinueSerializedState) &&
826 stage.seed == 0))
827 return SampleHeritageProfileStatus::InvalidStageParameter;
828 } else if constexpr (std::is_same_v<Stage, SampleHeritageOutputStage>) {
829 if (!(stage.gain >= 0.0f && stage.gain <= 16.0f) ||
830 !std::isfinite(stage.gain))
831 return SampleHeritageProfileStatus::InvalidStageParameter;
832 }
833 return SampleHeritageProfileStatus::Ok;
834 },
835 source.stages[index].parameters);
836 if (status != SampleHeritageProfileStatus::Ok) {
837 result.status = status;
838 return result;
839 }
840 }
841
842 const auto host_to_machine = source.host_sample_rate / machine_sample_rate;
843 const auto clocked_to_host = clocked_sample_rate / source.host_sample_rate;
844 if (!(host_to_machine > 0.0 && host_to_machine <= 128.0) ||
845 !(clocked_to_host > 0.0 && clocked_to_host <= 128.0) ||
846 !std::isfinite(host_to_machine) || !std::isfinite(clocked_to_host)) {
847 result.status = SampleHeritageProfileStatus::UnsupportedRateConversion;
848 result.stage_index = source.stages.size();
849 return result;
850 }
851
852 result.profile.schema_version = source.schema_version;
853 std::copy(source.profile_id.begin(), source.profile_id.end(),
854 result.profile.profile_id.begin());
855 const auto canonical_zero = []<typename Number>(Number value) noexcept {
856 return value == Number{0} ? Number{0} : value;
857 };
858 result.profile.host_sample_rate = canonical_zero(source.host_sample_rate);
859 result.profile.stage_count = source.stages.size();
860 std::copy(source.stages.begin(), source.stages.end(), result.profile.stages.begin());
861 for (std::size_t index = 0; index < result.profile.stage_count; ++index) {
862 std::visit(
863 [&](auto& stage) noexcept {
864 using Stage = std::decay_t<decltype(stage)>;
865 if constexpr (std::is_same_v<Stage, SampleHeritageMachineDomainStage>)
866 stage.sample_rate = canonical_zero(stage.sample_rate);
867 else if constexpr (std::is_same_v<Stage, SampleHeritageQuantizationStage>)
868 stage.dither_lsb = canonical_zero(stage.dither_lsb);
869 else if constexpr (std::is_same_v<Stage, SampleHeritageClockPitchStage>)
870 stage.ratio = canonical_zero(stage.ratio);
871 else if constexpr (std::is_same_v<Stage,
872 SampleHeritageReconstructionFilterStage>)
873 stage.cutoff_hz = canonical_zero(stage.cutoff_hz);
874 else if constexpr (std::is_same_v<Stage, SampleHeritageNoiseStage>)
875 stage.amplitude = canonical_zero(stage.amplitude);
876 else if constexpr (std::is_same_v<Stage, SampleHeritageOutputStage>)
877 stage.gain = canonical_zero(stage.gain);
878 }, result.profile.stages[index].parameters);
879 }
880 try {
881 result.profile.profile_digest = sample_heritage_profile_digest(source);
882 } catch (...) {
883 result.status = SampleHeritageProfileStatus::DigestUnavailable;
884 return result;
885 }
886 result.status = SampleHeritageProfileStatus::Ok;
887 result.stage_index = source.stages.size();
888 return result;
889}
890
891} // namespace pulp::audio
constexpr std::size_t stage_type_index
Definition sample_heritage_schema.hpp:369
bool valid_neutral_profile_id(std::string_view id) noexcept
Definition sample_heritage_schema.hpp:349
Definition analyzer_provider.hpp:12
SampleHeritagePitchFamily
Definition sample_heritage_schema.hpp:36
@ EarlyLinear
Definition sample_heritage_schema.hpp:39
@ DropRepeat
Definition sample_heritage_schema.hpp:38
@ VariableClock
Definition sample_heritage_schema.hpp:37
SampleHeritageCutoffLaw
Definition sample_heritage_schema.hpp:47
@ MachineRateRatio
Definition sample_heritage_schema.hpp:47
@ FixedHz
Definition sample_heritage_schema.hpp:47
SampleHeritageProfileStatus
Definition sample_heritage_schema.hpp:320
@ NonCanonicalProfileRepresentation
Definition sample_heritage_schema.hpp:329
@ MixedLegacyAndTypedBlocks
Definition sample_heritage_schema.hpp:328
@ WrongBlockDomain
Definition sample_heritage_schema.hpp:327
@ InvalidHostSampleRate
Definition sample_heritage_schema.hpp:324
@ InvalidStageOrder
Definition sample_heritage_schema.hpp:331
@ InvalidStageParameter
Definition sample_heritage_schema.hpp:332
@ InvalidProfileId
Definition sample_heritage_schema.hpp:323
@ DigestUnavailable
Definition sample_heritage_schema.hpp:334
@ DuplicateStage
Definition sample_heritage_schema.hpp:330
@ Ok
Definition sample_heritage_schema.hpp:321
@ UnsupportedSchemaVersion
Definition sample_heritage_schema.hpp:322
@ TooManyStages
Definition sample_heritage_schema.hpp:325
@ TooManyBlocks
Definition sample_heritage_schema.hpp:326
std::variant< SampleHeritageVoiceMachineDomainBlock, SampleHeritageVoiceClockBlock, SampleHeritageVoicePitchBlock, SampleHeritageVoiceConverterBlock, SampleHeritageVoiceLiveCyclicStretchBlock, SampleHeritageVoiceHoldDroopBlock, SampleHeritageVoiceReconstructionBlock, SampleHeritageVoiceAnalogColorBlock > SampleHeritageVoiceBlockParameters
Definition sample_heritage_schema.hpp:116
constexpr std::size_t kSampleHeritageMaximumBusBlocks
Definition sample_heritage_schema.hpp:25
constexpr std::size_t kSampleHeritageMaximumVoiceBlocks
Definition sample_heritage_schema.hpp:24
SampleHeritageHoldMode
Definition sample_heritage_schema.hpp:46
@ ZeroOrder
Definition sample_heritage_schema.hpp:46
std::array< std::uint8_t, 32 > sample_heritage_profile_digest(const SampleHeritageProfile &profile)
SHA-256 over a versioned, domain-separated, little-endian canonical byte encoding of the authoring pr...
std::variant< SampleHeritageRecordInputDriveClipBlock, SampleHeritageRecordRateBlock, SampleHeritageRecordConverterBlock, SampleHeritageRecordCommitCyclicStretchBlock, SampleHeritageRecordCommitAdaptiveStretchBlock > SampleHeritageRecordCommitBlockParameters
Definition sample_heritage_schema.hpp:220
SampleHeritageLivePitchMode
Definition sample_heritage_schema.hpp:62
@ RateLinked
Definition sample_heritage_schema.hpp:62
@ Preserve
Definition sample_heritage_schema.hpp:62
@ InvalidHostSampleRate
Definition sample_heritage_runtime_state.hpp:103
@ UnsupportedSchemaVersion
Definition sample_heritage_runtime_state.hpp:98
std::variant< SampleHeritageBusNoiseIdleBlock, SampleHeritageBusOutputDriveBlock > SampleHeritageBusBlockParameters
Definition sample_heritage_schema.hpp:157
@ None
Definition finite_time_stretch.hpp:26
constexpr std::size_t kSampleHeritageMaximumStages
Definition sample_heritage_schema.hpp:23
constexpr std::uint32_t kSampleHeritageSpectralTiltLawVersion
Definition sample_heritage_schema.hpp:20
constexpr std::uint32_t sample_heritage_adaptive_effective_search_radius(const SampleHeritageRecordCommitAdaptiveStretchBlock &block) noexcept
Definition sample_heritage_schema.hpp:209
SampleHeritageProfileValidation validate_sample_heritage_profile(const SampleHeritageProfile &source) noexcept
Definition sample_heritage_schema.hpp:387
std::variant< SampleHeritageMachineDomainStage, SampleHeritageQuantizationStage, SampleHeritageClockPitchStage, SampleHeritageDacHoldStage, SampleHeritageReconstructionFilterStage, SampleHeritageNoiseStage, SampleHeritageOutputStage > SampleHeritageStageParameters
Definition sample_heritage_schema.hpp:267
@ UnsupportedRateConversion
Definition sample_heritage_engine.hpp:43
SampleHeritageRecordFilterFamily
Definition sample_heritage_schema.hpp:55
@ OnePole
Definition sample_heritage_schema.hpp:56
@ Ok
Definition loop_types.hpp:34
SampleHeritageSeedPolicy
Definition sample_heritage_schema.hpp:30
@ RestartFromProfileSeed
Definition sample_heritage_schema.hpp:31
@ ContinueSerializedState
Definition sample_heritage_schema.hpp:32
constexpr std::uint32_t sample_heritage_adaptive_effective_crossfade_samples(const SampleHeritageRecordCommitAdaptiveStretchBlock &block) noexcept
Definition sample_heritage_schema.hpp:215
constexpr std::size_t kSampleHeritageMaximumRecordCommitBlocks
Definition sample_heritage_schema.hpp:26
constexpr std::size_t kSampleHeritageMaximumProfileIdBytes
Definition sample_heritage_schema.hpp:28
constexpr std::uint32_t kSampleHeritageProfileSchemaVersion
Definition sample_heritage_schema.hpp:18
constexpr std::uint32_t kSampleHeritageProfileDigestVersion
Definition sample_heritage_schema.hpp:19
SampleHeritageAnalogFilterFamily
Definition sample_heritage_schema.hpp:61
@ Ladder4Pole
Definition sample_heritage_schema.hpp:61
@ None
Definition sample_heritage_schema.hpp:61
SampleHeritageConverterFamily
Definition sample_heritage_schema.hpp:41
@ MuLaw
Definition sample_heritage_schema.hpp:43
@ LinearPcm
Definition sample_heritage_schema.hpp:42
@ ALaw
Definition sample_heritage_schema.hpp:44
SampleHeritageReconstructionFamily
Definition sample_heritage_schema.hpp:49
@ OnePole
Definition sample_heritage_schema.hpp:50
@ Chebyshev
Definition sample_heritage_schema.hpp:52
@ Butterworth
Definition sample_heritage_schema.hpp:51
@ Elliptic
Definition sample_heritage_schema.hpp:53
SampleHeritageBlockDomain
Definition sample_heritage_schema.hpp:35
@ RecordCommit
Definition sample_heritage_schema.hpp:35
@ Bus
Definition sample_heritage_schema.hpp:35
@ Voice
Definition sample_heritage_schema.hpp:35
SampleHeritageNoiseGate
Definition sample_heritage_schema.hpp:48
@ AlwaysOn
Definition sample_heritage_schema.hpp:48
@ VoiceActive
Definition sample_heritage_schema.hpp:48
constexpr double kSampleHeritageMaximumLadderCutoffRatio
Definition sample_heritage_schema.hpp:21
constexpr std::size_t kSampleHeritageMaximumChannels
Definition sample_heritage_schema.hpp:27
constexpr float kSampleHeritageMaximumLadderResonance
Definition sample_heritage_schema.hpp:22
@ index
Definition gpu_pass.hpp:140
Stage
Ordered semantic stage described by one EvidenceEvent.
Definition health_result.hpp:133
@ type
Built-in / common type name (e.g. int, Number).
Definition code_editor_tokenizer.hpp:39
@ value
the widget's primary value (Knob, Fader, RangeSlider, Toggle, ProgressBar)
Definition binding_diagnostics.hpp:19
Definition sample_heritage_schema.hpp:160
SampleHeritageBusBlockParameters parameters
Definition sample_heritage_schema.hpp:163
SampleHeritageBlockDomain domain
Definition sample_heritage_schema.hpp:161
bool bypass
Definition sample_heritage_schema.hpp:162
Definition sample_heritage_schema.hpp:133
double tilt_reference_hz
Definition sample_heritage_schema.hpp:150
double tilt_floor_hz
Definition sample_heritage_schema.hpp:151
SampleHeritageSeedPolicy seed_policy
Definition sample_heritage_schema.hpp:139
float tilt_db_per_octave
Definition sample_heritage_schema.hpp:136
SampleHeritageNoiseGate gate
Definition sample_heritage_schema.hpp:137
std::uint64_t seed
Definition sample_heritage_schema.hpp:138
float idle_amplitude
Definition sample_heritage_schema.hpp:135
float noise_amplitude
Definition sample_heritage_schema.hpp:134
Definition sample_heritage_schema.hpp:153
float drive
Definition sample_heritage_schema.hpp:154
float ceiling
Definition sample_heritage_schema.hpp:155
Definition sample_heritage_schema.hpp:244
double ratio
Definition sample_heritage_schema.hpp:245
Definition sample_heritage_schema.hpp:248
std::uint32_t hold_samples
Definition sample_heritage_schema.hpp:249
Definition sample_heritage_schema.hpp:232
double sample_rate
Definition sample_heritage_schema.hpp:233
Definition sample_heritage_schema.hpp:256
float amplitude
Definition sample_heritage_schema.hpp:257
SampleHeritageSeedPolicy seed_policy
Definition sample_heritage_schema.hpp:259
std::uint64_t seed
Definition sample_heritage_schema.hpp:258
Definition sample_heritage_schema.hpp:263
float gain
Definition sample_heritage_schema.hpp:264
Definition sample_heritage_schema.hpp:296
std::size_t bus_count
Definition sample_heritage_schema.hpp:304
std::array< SampleHeritageRecordCommitBlockSpec, kSampleHeritageMaximumRecordCommitBlocks > record_commit
Definition sample_heritage_schema.hpp:306
double host_sample_rate
Definition sample_heritage_schema.hpp:299
std::array< SampleHeritageStageSpec, kSampleHeritageMaximumStages > stages
Definition sample_heritage_schema.hpp:309
std::size_t record_commit_count
Definition sample_heritage_schema.hpp:307
std::size_t stage_count
Definition sample_heritage_schema.hpp:310
std::size_t voice_count
Definition sample_heritage_schema.hpp:302
std::string_view id() const noexcept
Definition sample_heritage_schema.hpp:313
std::array< char, kSampleHeritageMaximumProfileIdBytes+1 > profile_id
Definition sample_heritage_schema.hpp:298
std::array< SampleHeritageVoiceBlockSpec, kSampleHeritageMaximumVoiceBlocks > voice
Definition sample_heritage_schema.hpp:301
std::uint32_t schema_version
Definition sample_heritage_schema.hpp:297
std::array< std::uint8_t, 32 > profile_digest
Definition sample_heritage_schema.hpp:311
std::array< SampleHeritageBusBlockSpec, kSampleHeritageMaximumBusBlocks > bus
Definition sample_heritage_schema.hpp:303
Definition sample_heritage_schema.hpp:337
std::size_t stage_index
Definition sample_heritage_schema.hpp:340
SampleHeritageBlockDomain block_domain
Definition sample_heritage_schema.hpp:341
bool valid() const noexcept
Definition sample_heritage_schema.hpp:344
SampleHeritagePreparedProfile profile
Definition sample_heritage_schema.hpp:342
SampleHeritageProfileStatus status
Definition sample_heritage_schema.hpp:338
Authoring/serialization schema.
Definition sample_heritage_schema.hpp:283
std::string profile_id
Definition sample_heritage_schema.hpp:285
double host_sample_rate
Definition sample_heritage_schema.hpp:286
std::vector< SampleHeritageStageSpec > stages
Definition sample_heritage_schema.hpp:293
std::uint32_t schema_version
Definition sample_heritage_schema.hpp:284
std::vector< SampleHeritageRecordCommitBlockSpec > record_commit
Definition sample_heritage_schema.hpp:289
std::vector< SampleHeritageVoiceBlockSpec > voice
Definition sample_heritage_schema.hpp:287
std::vector< SampleHeritageBusBlockSpec > bus
Definition sample_heritage_schema.hpp:288
Definition sample_heritage_schema.hpp:236
SampleHeritageSeedPolicy seed_policy
Definition sample_heritage_schema.hpp:240
std::uint8_t bit_depth
Definition sample_heritage_schema.hpp:237
float dither_lsb
Definition sample_heritage_schema.hpp:238
std::uint64_t seed
Definition sample_heritage_schema.hpp:239
Definition sample_heritage_schema.hpp:252
double cutoff_hz
Definition sample_heritage_schema.hpp:253
Definition sample_heritage_schema.hpp:196
bool stereo_link
Definition sample_heritage_schema.hpp:204
std::uint32_t crossfade_samples
Definition sample_heritage_schema.hpp:201
std::uint32_t decision_hop_samples
Definition sample_heritage_schema.hpp:198
double factor
Definition sample_heritage_schema.hpp:197
std::uint8_t width
Definition sample_heritage_schema.hpp:206
std::uint32_t search_radius_samples
Definition sample_heritage_schema.hpp:199
std::uint64_t zone_start_frame
Definition sample_heritage_schema.hpp:202
std::uint8_t quality
Definition sample_heritage_schema.hpp:205
std::uint32_t search_stride_samples
Definition sample_heritage_schema.hpp:200
std::uint64_t zone_end_frame
Definition sample_heritage_schema.hpp:203
Definition sample_heritage_schema.hpp:225
bool bypass
Definition sample_heritage_schema.hpp:227
SampleHeritageBlockDomain domain
Definition sample_heritage_schema.hpp:226
SampleHeritageRecordCommitBlockParameters parameters
Definition sample_heritage_schema.hpp:228
Definition sample_heritage_schema.hpp:189
std::uint32_t cycle_samples
Definition sample_heritage_schema.hpp:191
double factor
Definition sample_heritage_schema.hpp:190
std::uint64_t zone_end_frame
Definition sample_heritage_schema.hpp:194
std::uint32_t crossfade_samples
Definition sample_heritage_schema.hpp:192
std::uint64_t zone_start_frame
Definition sample_heritage_schema.hpp:193
Definition sample_heritage_schema.hpp:180
SampleHeritageSeedPolicy seed_policy
Definition sample_heritage_schema.hpp:186
float bit_depth
Definition sample_heritage_schema.hpp:182
float dac_nonlinearity
Definition sample_heritage_schema.hpp:183
SampleHeritageConverterFamily family
Definition sample_heritage_schema.hpp:181
float dither_lsb
Definition sample_heritage_schema.hpp:184
std::uint64_t seed
Definition sample_heritage_schema.hpp:185
Definition sample_heritage_schema.hpp:166
float drive
Definition sample_heritage_schema.hpp:167
float clip_level
Definition sample_heritage_schema.hpp:168
Definition sample_heritage_schema.hpp:170
SampleHeritageCutoffLaw cutoff_law
Definition sample_heritage_schema.hpp:174
double sample_rate
Definition sample_heritage_schema.hpp:173
float stopband_attenuation_db
Definition sample_heritage_schema.hpp:178
SampleHeritageRecordFilterFamily filter_family
Definition sample_heritage_schema.hpp:171
std::uint8_t order
Definition sample_heritage_schema.hpp:176
double cutoff_value
Definition sample_heritage_schema.hpp:175
float ripple_db
Definition sample_heritage_schema.hpp:177
Definition sample_heritage_schema.hpp:276
bool bypass
Definition sample_heritage_schema.hpp:277
SampleHeritageStageParameters parameters
Definition sample_heritage_schema.hpp:278
Definition sample_heritage_schema.hpp:93
float asymmetry
Definition sample_heritage_schema.hpp:95
float mix
Definition sample_heritage_schema.hpp:96
SampleHeritageAnalogFilterFamily filter_family
Definition sample_heritage_schema.hpp:97
double cutoff_value
Definition sample_heritage_schema.hpp:100
float resonance
Definition sample_heritage_schema.hpp:101
SampleHeritageCutoffLaw cutoff_law
Definition sample_heritage_schema.hpp:99
float drive
Definition sample_heritage_schema.hpp:94
Definition sample_heritage_schema.hpp:126
SampleHeritageBlockDomain domain
Definition sample_heritage_schema.hpp:127
bool bypass
Definition sample_heritage_schema.hpp:128
SampleHeritageVoiceBlockParameters parameters
Definition sample_heritage_schema.hpp:129
Definition sample_heritage_schema.hpp:65
double ratio
Definition sample_heritage_schema.hpp:65
Definition sample_heritage_schema.hpp:70
float bit_depth
Definition sample_heritage_schema.hpp:72
float dither_lsb
Definition sample_heritage_schema.hpp:74
SampleHeritageConverterFamily family
Definition sample_heritage_schema.hpp:71
std::uint64_t seed
Definition sample_heritage_schema.hpp:75
SampleHeritageSeedPolicy seed_policy
Definition sample_heritage_schema.hpp:76
float dac_nonlinearity
Definition sample_heritage_schema.hpp:73
Definition sample_heritage_schema.hpp:79
std::uint32_t hold_samples
Definition sample_heritage_schema.hpp:81
SampleHeritageHoldMode mode
Definition sample_heritage_schema.hpp:80
float droop
Definition sample_heritage_schema.hpp:82
Definition sample_heritage_schema.hpp:103
bool tempo_lock
Definition sample_heritage_schema.hpp:113
SampleHeritageLivePitchMode pitch_mode
Definition sample_heritage_schema.hpp:112
double cycle_ms
Definition sample_heritage_schema.hpp:105
std::uint16_t shuffle_divisions
Definition sample_heritage_schema.hpp:108
SampleHeritageSeedPolicy seed_policy
Definition sample_heritage_schema.hpp:110
bool stereo_link
Definition sample_heritage_schema.hpp:107
double splice_ms
Definition sample_heritage_schema.hpp:106
double factor
Definition sample_heritage_schema.hpp:104
std::uint64_t seed
Definition sample_heritage_schema.hpp:109
Definition sample_heritage_schema.hpp:64
double sample_rate
Definition sample_heritage_schema.hpp:64
Definition sample_heritage_schema.hpp:66
SampleHeritagePitchFamily family
Definition sample_heritage_schema.hpp:67
double max_transpose_semitones
Definition sample_heritage_schema.hpp:68
Definition sample_heritage_schema.hpp:84
float ripple_db
Definition sample_heritage_schema.hpp:90
double cutoff_value
Definition sample_heritage_schema.hpp:88
SampleHeritageCutoffLaw cutoff_law
Definition sample_heritage_schema.hpp:87
float stopband_attenuation_db
Definition sample_heritage_schema.hpp:91
std::uint8_t order
Definition sample_heritage_schema.hpp:89
SampleHeritageReconstructionFamily family
Definition sample_heritage_schema.hpp:85