///|
priv enum BenchExternalGraphKind {
MonoExternalGraph
StereoExternalGraph
}
///|
/// Generated fixture for external-authoring benchmarks.
///
/// Fields keep the graph snapshot, stable IDs, and declared control keys
/// together so each benchmark isolates one boundary step without rebuilding
/// unrelated authoring metadata in the timed closure.
priv struct BenchExternalAuthoringFixture {
name : String
graph_kind : BenchExternalGraphKind
nodes : Array[DspNode]
ids : Array[@identity.GraphNodeId]
control_keys : Array[String]
control_ids : Array[@identity.GraphNodeId]
control_indices : Array[Int]
control_slots : Array[GraphParamSlot]
shape_rewire_target_id : @identity.GraphNodeId
shape_rewire_slot : GraphTopologyInputSlot
shape_rewire_source_id : @identity.GraphNodeId
shape_rewire_restore_id : @identity.GraphNodeId
}
///|
fn bench_external_graph_id(index : Int) -> @identity.GraphNodeId {
try @identity.GraphNodeId::from_string("bench:node:\{index}") catch {
_ => abort("expected valid generated graph id")
} noraise {
id => id
}
}
///|
fn bench_external_inserted_id(suffix : String) -> @identity.GraphNodeId {
try @identity.GraphNodeId::from_string("bench:inserted:\{suffix}") catch {
_ => abort("expected valid inserted graph id")
} noraise {
id => id
}
}
///|
priv struct BenchExternalFixtureBuilder {
nodes : Array[DspNode]
ids : Array[@identity.GraphNodeId]
control_keys : Array[String]
control_ids : Array[@identity.GraphNodeId]
control_indices : Array[Int]
control_slots : Array[GraphParamSlot]
}
///|
fn BenchExternalFixtureBuilder::BenchExternalFixtureBuilder(
node_capacity~ : Int,
control_capacity~ : Int,
) -> BenchExternalFixtureBuilder {
let nodes : Array[DspNode] = []
nodes.reserve_capacity(node_capacity)
let ids : Array[@identity.GraphNodeId] = []
ids.reserve_capacity(node_capacity)
let control_keys : Array[String] = []
control_keys.reserve_capacity(control_capacity)
let control_ids : Array[@identity.GraphNodeId] = []
control_ids.reserve_capacity(control_capacity)
let control_indices : Array[Int] = []
control_indices.reserve_capacity(control_capacity)
let control_slots : Array[GraphParamSlot] = []
control_slots.reserve_capacity(control_capacity)
{ nodes, ids, control_keys, control_ids, control_indices, control_slots, }
}
///|
fn BenchExternalFixtureBuilder::push_node(
self : BenchExternalFixtureBuilder,
node : DspNode,
) -> Int {
let index = self.nodes.length()
self.nodes.push(node)
self.ids.push(bench_external_graph_id(index))
index
}
///|
fn BenchExternalFixtureBuilder::push_value0_control(
self : BenchExternalFixtureBuilder,
key : String,
index : Int,
) -> Unit {
if index < 0 || index >= self.ids.length() {
abort("expected generated control index to resolve")
}
self.control_keys.push(key)
self.control_ids.push(self.ids[index])
self.control_indices.push(index)
self.control_slots.push(GraphParamSlot::Value0)
}
///|
fn BenchExternalFixtureBuilder::finish(
self : BenchExternalFixtureBuilder,
name : String,
graph_kind : BenchExternalGraphKind,
shape_rewire_target_index : Int,
shape_rewire_slot : GraphTopologyInputSlot,
shape_rewire_source_index : Int,
shape_rewire_restore_index : Int,
) -> BenchExternalAuthoringFixture {
if shape_rewire_target_index < 0 ||
shape_rewire_target_index >= self.ids.length() ||
shape_rewire_source_index < 0 ||
shape_rewire_source_index >= self.ids.length() ||
shape_rewire_restore_index < 0 ||
shape_rewire_restore_index >= self.ids.length() {
abort("expected valid shape-edit rewire indices")
}
{
name,
graph_kind,
nodes: self.nodes,
ids: self.ids,
control_keys: self.control_keys,
control_ids: self.control_ids,
control_indices: self.control_indices,
control_slots: self.control_slots,
shape_rewire_target_id: self.ids[shape_rewire_target_index],
shape_rewire_slot,
shape_rewire_source_id: self.ids[shape_rewire_source_index],
shape_rewire_restore_id: self.ids[shape_rewire_restore_index],
}
}
///|
fn build_bench_external_authoring_fixture(
name : String,
stage_count : Int,
) -> BenchExternalAuthoringFixture {
let builder = BenchExternalFixtureBuilder(
node_capacity=stage_count + 2,
control_capacity=stage_count,
)
let mut previous = builder.push_node(
DspNode::oscillator(Waveform::Saw, 220.0),
)
for stage in 0.. DspNode::gain(previous, 0.7)
1 =>
DspNode::biquad(
input=previous,
mode=BiquadMode::LowPass,
cutoff_hz=900.0 + Double::from_int(stage),
q=0.707,
)
_ => DspNode::clip(previous, 0.9)
}
let node_index = builder.push_node(node)
builder.push_value0_control("p:\{stage}", node_index)
previous = node_index
}
let output_index = builder.push_node(DspNode::output(previous))
builder.finish(
name,
BenchExternalGraphKind::MonoExternalGraph,
output_index,
GraphTopologyInputSlot::Input0,
0,
previous,
)
}
///|
fn bench_external_authoring_fixtures() -> Array[BenchExternalAuthoringFixture] {
[
build_bench_external_authoring_fixture("small_10_nodes", 8),
build_bench_external_authoring_fixture("medium_34_nodes", 32),
build_bench_external_authoring_fixture("large_130_nodes", 128),
]
}
///|
fn build_bench_external_branch_fanout_fixture() -> BenchExternalAuthoringFixture {
let builder = BenchExternalFixtureBuilder(
node_capacity=11,
control_capacity=6,
)
let osc = builder.push_node(DspNode::oscillator(Waveform::Saw, 220.0))
let pre_gain = builder.push_node(DspNode::gain(osc, 0.72))
builder.push_value0_control("branch:pre_gain", pre_gain)
let branch_filter = builder.push_node(
DspNode::biquad(
input=pre_gain,
mode=BiquadMode::LowPass,
cutoff_hz=1400.0,
q=0.707,
),
)
builder.push_value0_control("branch:filter_cutoff", branch_filter)
let filter_gain = builder.push_node(DspNode::gain(branch_filter, 0.55))
builder.push_value0_control("branch:filter_gain", filter_gain)
let branch_delay = builder.push_node(
DspNode::delay(
input=pre_gain,
max_delay_samples=4800,
delay_samples=900,
feedback=0.22,
),
)
builder.push_value0_control("branch:delay_feedback", branch_delay)
let delayed_clip = builder.push_node(DspNode::clip(branch_delay, 0.85))
builder.push_value0_control("branch:delay_clip", delayed_clip)
let noise = builder.push_node(DspNode::noise(91U))
let noise_gain = builder.push_node(DspNode::gain(noise, 0.16))
builder.push_value0_control("branch:noise_gain", noise_gain)
let wet_mix = builder.push_node(DspNode::mix(filter_gain, delayed_clip))
let final_mix = builder.push_node(DspNode::mix(wet_mix, noise_gain))
ignore(builder.push_node(DspNode::output(final_mix)))
builder.finish(
"branch_fanout_11_nodes",
BenchExternalGraphKind::MonoExternalGraph,
branch_filter,
GraphTopologyInputSlot::Input0,
osc,
pre_gain,
)
}
///|
fn build_bench_external_mix_bus_fixture() -> BenchExternalAuthoringFixture {
let builder = BenchExternalFixtureBuilder(
node_capacity=17,
control_capacity=8,
)
let osc_a = builder.push_node(DspNode::oscillator(Waveform::Saw, 110.0))
let gain_a = builder.push_node(DspNode::gain(osc_a, 0.45))
builder.push_value0_control("mix:a_gain", gain_a)
let osc_b = builder.push_node(DspNode::oscillator(Waveform::Square, 220.0))
let gain_b = builder.push_node(DspNode::gain(osc_b, 0.32))
builder.push_value0_control("mix:b_gain", gain_b)
let noise = builder.push_node(DspNode::noise(123U))
let noise_filter = builder.push_node(
DspNode::biquad(
input=noise,
mode=BiquadMode::HighPass,
cutoff_hz=1800.0,
q=0.8,
),
)
builder.push_value0_control("mix:noise_filter", noise_filter)
let noise_gain = builder.push_node(DspNode::gain(noise_filter, 0.18))
builder.push_value0_control("mix:noise_gain", noise_gain)
let osc_c = builder.push_node(DspNode::oscillator(Waveform::Triangle, 330.0))
let clipped_c = builder.push_node(DspNode::clip(osc_c, 0.7))
builder.push_value0_control("mix:c_clip", clipped_c)
let mix_ab = builder.push_node(DspNode::mix(gain_a, gain_b))
let mix_noise_c = builder.push_node(DspNode::mix(noise_gain, clipped_c))
let bus_mix = builder.push_node(DspNode::mix(mix_ab, mix_noise_c))
let bus_filter = builder.push_node(
DspNode::biquad(
input=bus_mix,
mode=BiquadMode::LowPass,
cutoff_hz=2400.0,
q=0.707,
),
)
builder.push_value0_control("mix:bus_filter", bus_filter)
let bus_delay = builder.push_node(
DspNode::delay(
input=bus_filter,
max_delay_samples=7200,
delay_samples=1800,
feedback=0.18,
),
)
builder.push_value0_control("mix:bus_delay", bus_delay)
let wet_bus = builder.push_node(DspNode::mix(bus_mix, bus_delay))
let limited = builder.push_node(DspNode::clip(wet_bus, 0.92))
builder.push_value0_control("mix:limiter", limited)
ignore(builder.push_node(DspNode::output(limited)))
builder.finish(
"mix_bus_17_nodes",
BenchExternalGraphKind::MonoExternalGraph,
bus_filter,
GraphTopologyInputSlot::Input0,
mix_ab,
bus_mix,
)
}
///|
fn build_bench_external_terminal_stereo_fixture() -> BenchExternalAuthoringFixture {
let builder = BenchExternalFixtureBuilder(
node_capacity=15,
control_capacity=9,
)
let osc = builder.push_node(DspNode::oscillator(Waveform::Saw, 196.0))
let filter = builder.push_node(
DspNode::biquad(
input=osc,
mode=BiquadMode::LowPass,
cutoff_hz=1600.0,
q=0.707,
),
)
builder.push_value0_control("stereo:filter", filter)
let voice_gain = builder.push_node(DspNode::gain(filter, 0.6))
builder.push_value0_control("stereo:voice_gain", voice_gain)
let noise = builder.push_node(DspNode::noise(321U))
let noise_gain = builder.push_node(DspNode::gain(noise, 0.08))
builder.push_value0_control("stereo:noise_gain", noise_gain)
let dry_mix = builder.push_node(DspNode::mix(voice_gain, noise_gain))
let mono_delay = builder.push_node(
DspNode::delay(
input=dry_mix,
max_delay_samples=4800,
delay_samples=1200,
feedback=0.15,
),
)
builder.push_value0_control("stereo:mono_delay", mono_delay)
let wet_mix = builder.push_node(DspNode::mix(dry_mix, mono_delay))
let clipped = builder.push_node(DspNode::clip(wet_mix, 0.88))
builder.push_value0_control("stereo:mono_clip", clipped)
let pan = builder.push_node(DspNode::pan(clipped, -0.2))
builder.push_value0_control("stereo:pan", pan)
let stereo_filter = builder.push_node(
DspNode::stereo_biquad(
input=pan,
mode=BiquadMode::LowPass,
cutoff_hz=2600.0,
q=0.707,
),
)
builder.push_value0_control("stereo:stereo_filter", stereo_filter)
let stereo_delay = builder.push_node(
DspNode::stereo_delay(
input=stereo_filter,
max_delay_samples=9600,
delay_samples=2400,
feedback=0.2,
),
)
builder.push_value0_control("stereo:stereo_delay", stereo_delay)
let stereo_gain = builder.push_node(
DspNode::stereo_gain(input=stereo_delay, amount=0.8),
)
builder.push_value0_control("stereo:stereo_gain", stereo_gain)
let stereo_clip = builder.push_node(
DspNode::stereo_clip(input=stereo_gain, threshold=0.92),
)
let stereo_output = builder.push_node(DspNode::stereo_output(stereo_clip))
builder.finish(
"terminal_stereo_15_nodes",
BenchExternalGraphKind::StereoExternalGraph,
stereo_output,
GraphTopologyInputSlot::Input0,
stereo_gain,
stereo_clip,
)
}
///|
/// Feedback fixture with no dead authoring nodes.
///
/// WHY no unused frequency constant: topology-controller benchmarks compile raw
/// authoring arrays to preserve control indices, so dead nodes would be rejected
/// instead of optimized away. The forward `mix(filter, gain)` input still gives
/// the compiler a safe feedback edge to route.
fn build_bench_external_feedback_loop_fixture() -> BenchExternalAuthoringFixture {
let builder = BenchExternalFixtureBuilder(node_capacity=6, control_capacity=3)
let osc = builder.push_node(DspNode::oscillator(Waveform::Saw, 440.0))
let filter = builder.push_node(
DspNode::biquad(
input=osc,
mode=BiquadMode::LowPass,
cutoff_hz=1000.0,
q=0.707,
),
)
builder.push_value0_control("feedback:filter", filter)
let loop_mix = builder.push_node(DspNode::mix(filter, 4))
let delay = builder.push_node(
DspNode::delay(
input=loop_mix,
max_delay_samples=4800,
delay_samples=2400,
feedback=0.0,
),
)
builder.push_value0_control("feedback:delay_feedback", delay)
let gain = builder.push_node(DspNode::gain(delay, 0.5))
builder.push_value0_control("feedback:return_gain", gain)
let output = builder.push_node(DspNode::output(gain))
builder.finish(
"feedback_loop_6_nodes",
BenchExternalGraphKind::MonoExternalGraph,
output,
GraphTopologyInputSlot::Input0,
delay,
gain,
)
}
///|
fn bench_external_realistic_authoring_fixtures() -> Array[
BenchExternalAuthoringFixture,
] {
[
build_bench_external_branch_fanout_fixture(),
build_bench_external_mix_bus_fixture(),
build_bench_external_terminal_stereo_fixture(),
build_bench_external_feedback_loop_fixture(),
]
}
///|
fn bench_external_doc(
fixture : BenchExternalAuthoringFixture,
) -> GraphTemplateDoc {
try GraphTemplateDoc::from_nodes(ids=fixture.ids, nodes=fixture.nodes) catch {
error => abort("expected generated graph doc, got \{error}")
} noraise {
doc => doc
}
}
///|
fn build_bench_external_binding_builder(
index_map : GraphIndexMap,
fixture : BenchExternalAuthoringFixture,
) -> ControlBindingBuilder {
let mut builder = ControlBindingBuilder::new()
for i in 0.. builder = next
None => abort("expected generated control id to resolve")
}
}
builder
}
///|
fn bench_external_binding_map(
fixture : BenchExternalAuthoringFixture,
) -> ControlBindingMap {
let doc = bench_external_doc(fixture)
let template = doc.analyze()
build_bench_external_binding_builder(doc.index_map(), fixture)
.build(template)
.unwrap()
}
///|
fn bench_external_control_values(
fixture : BenchExternalAuthoringFixture,
offset : Double,
) -> Map[String, Double] {
let controls : Map[String, Double] = Map([])
for i in 0.. Array[GraphControl] {
let controls : Array[GraphControl] = []
controls.reserve_capacity(fixture.control_ids.length())
for i in 0.. GraphTemplateDoc {
let target_id = fixture.ids[1]
let replaced = try doc.replace_node(target_id, DspNode::gain(0, 0.55)) catch {
error => abort("expected replace edit to apply, got \{error}")
} noraise {
next => next
}
try replaced.replace_node(target_id, fixture.nodes[1]) catch {
error => abort("expected replace roundtrip to apply, got \{error}")
} noraise {
next => next
}
}
///|
fn bench_external_add_roundtrip(
doc : GraphTemplateDoc,
fixture : BenchExternalAuthoringFixture,
) -> GraphTemplateDoc {
let output_id = fixture.ids[fixture.nodes.length() - 1]
let inserted_id = bench_external_inserted_id("add")
let inserted = try
doc.insert_node(
inserted_id,
output_id,
GraphTopologyInputSlot::Input0,
DspNode::gain(-1, 0.8),
)
catch {
error => abort("expected insert edit to apply, got \{error}")
} noraise {
next => next
}
try
inserted.delete_node(
inserted_id,
output_id,
GraphTopologyInputSlot::Input0,
inserted_id,
)
catch {
error => abort("expected add roundtrip to apply, got \{error}")
} noraise {
next => next
}
}
///|
fn bench_external_remove_roundtrip(
doc : GraphTemplateDoc,
fixture : BenchExternalAuthoringFixture,
) -> GraphTemplateDoc {
let output_id = fixture.ids[fixture.nodes.length() - 1]
let delete_index = fixture.nodes.length() - 2
let delete_id = fixture.ids[delete_index]
let removed = try
doc.delete_node(
delete_id,
output_id,
GraphTopologyInputSlot::Input0,
delete_id,
)
catch {
error => abort("expected delete edit to apply, got \{error}")
} noraise {
next => next
}
try
removed.insert_node(
bench_external_inserted_id("restore"),
output_id,
GraphTopologyInputSlot::Input0,
fixture.nodes[delete_index],
)
catch {
error => abort("expected remove roundtrip to apply, got \{error}")
} noraise {
next => next
}
}
///|
fn bench_external_rewire_roundtrip(
doc : GraphTemplateDoc,
fixture : BenchExternalAuthoringFixture,
) -> GraphTemplateDoc {
let target_index = fixture.nodes.length() - 2
let target_id = fixture.ids[target_index]
let replacement_source_id = fixture.ids[0]
let original_source_id = fixture.ids[target_index - 1]
let rewired = try
doc.rewire_input(
target_id,
GraphTopologyInputSlot::Input0,
replacement_source_id,
)
catch {
error => abort("expected rewire edit to apply, got \{error}")
} noraise {
next => next
}
try
rewired.rewire_input(
target_id,
GraphTopologyInputSlot::Input0,
original_source_id,
)
catch {
error => abort("expected rewire roundtrip to apply, got \{error}")
} noraise {
next => next
}
}
///|
fn bench_external_shape_rewire_doc(
doc : GraphTemplateDoc,
fixture : BenchExternalAuthoringFixture,
) -> GraphTemplateDoc {
try
doc.rewire_input(
fixture.shape_rewire_target_id,
fixture.shape_rewire_slot,
fixture.shape_rewire_source_id,
)
catch {
error => abort("expected realistic shape rewire, got \{error}")
} noraise {
next => next
}
}
///|
fn bench_external_shape_rewire_roundtrip(
doc : GraphTemplateDoc,
fixture : BenchExternalAuthoringFixture,
) -> GraphTemplateDoc {
let rewired = bench_external_shape_rewire_doc(doc, fixture)
try
rewired.rewire_input(
fixture.shape_rewire_target_id,
fixture.shape_rewire_slot,
fixture.shape_rewire_restore_id,
)
catch {
error => abort("expected realistic shape rewire roundtrip, got \{error}")
} noraise {
next => next
}
}
///|
fn bench_external_template_analyze_group(
b : @bench.T,
fixtures : Array[BenchExternalAuthoringFixture],
) -> Unit {
for fixture in fixtures {
let nodes = fixture.nodes
b.bench(name=fixture.name, fn() {
let template = CompiledTemplate::analyze(nodes)
b.keep(template)
})
}
}
///|
fn bench_external_control_binding_generation_group(
b : @bench.T,
fixtures : Array[BenchExternalAuthoringFixture],
) -> Unit {
for fixture in fixtures {
let doc = bench_external_doc(fixture)
let index_map = doc.index_map()
b.bench(name=fixture.name, fn() {
let builder = build_bench_external_binding_builder(index_map, fixture)
b.keep(builder)
})
}
}
///|
fn bench_external_control_binding_validation_group(
b : @bench.T,
fixtures : Array[BenchExternalAuthoringFixture],
) -> Unit {
for fixture in fixtures {
let doc = bench_external_doc(fixture)
let template = doc.analyze()
let builder = build_bench_external_binding_builder(doc.index_map(), fixture)
b.bench(name=fixture.name, fn() {
let bindings = builder.build(template)
b.keep(bindings)
})
}
}
///|
fn bench_external_string_control_resolution_group(
b : @bench.T,
fixtures : Array[BenchExternalAuthoringFixture],
) -> Unit {
for fixture in fixtures {
let bindings = bench_external_binding_map(fixture)
let controls_a = bench_external_control_values(fixture, 0.01)
let controls_b = bench_external_control_values(fixture, 0.02)
let use_b = @ref.new(false)
b.bench(name=fixture.name, fn() {
let controls = if use_b.val { controls_b } else { controls_a }
use_b.val = !use_b.val
let batch = bindings.resolve_controls(controls)
b.keep(batch)
})
}
}
///|
fn[T, E] bench_expect_err(result : Result[T, E], label : String) -> E {
match result {
Err(error) => error
Ok(_) => abort("expected \{label} to reject")
}
}
///|
fn bench_external_control_binding_rejection(
b : @bench.T,
make_builder : (GraphIndexMap, BenchExternalAuthoringFixture) -> ControlBindingBuilder,
label : String,
) -> Unit {
for fixture in bench_external_authoring_fixtures() {
let doc = bench_external_doc(fixture)
let template = doc.analyze()
let builder = make_builder(doc.index_map(), fixture)
b.bench(name=fixture.name, fn() {
let error = bench_expect_err(builder.build(template), label)
b.keep(error)
})
}
}
///|
fn bench_external_compile_result_rejection(
b : @bench.T,
make_template : (BenchExternalAuthoringFixture) -> CompiledTemplate,
label : String,
) -> Unit {
let ctx = DspContext::new(sample_rate=BENCH_SAMPLE_RATE, block_size=128)
for fixture in bench_external_authoring_fixtures() {
let template = make_template(fixture)
b.bench(name=fixture.name, fn() {
let error = bench_expect_err(
CompiledDsp::compile_result(template, ctx),
label,
)
b.keep(error)
})
}
}
///|
fn bench_external_invalid_index_binding_builder(
index_map : GraphIndexMap,
fixture : BenchExternalAuthoringFixture,
) -> ControlBindingBuilder {
let builder = build_bench_external_binding_builder(index_map, fixture)
builder.bind(
key="diagnostic:invalid-index",
node_index=fixture.nodes.length() + 7,
slot=GraphParamSlot::Value0,
)
}
///|
fn bench_external_invalid_slot_binding_builder(
index_map : GraphIndexMap,
fixture : BenchExternalAuthoringFixture,
) -> ControlBindingBuilder {
let builder = build_bench_external_binding_builder(index_map, fixture)
builder.bind(
key="diagnostic:invalid-slot",
node_index=1,
slot=GraphParamSlot::Value1,
)
}
///|
fn bench_external_duplicate_key_binding_builder(
index_map : GraphIndexMap,
fixture : BenchExternalAuthoringFixture,
) -> ControlBindingBuilder {
let builder = build_bench_external_binding_builder(index_map, fixture)
builder.bind(
key=fixture.control_keys[0],
node_index=1,
slot=GraphParamSlot::Value0,
)
}
///|
fn bench_external_invalid_param_batch(
fixture : BenchExternalAuthoringFixture,
offset : Double,
) -> Array[GraphControl] {
let controls = bench_external_control_batch(fixture, offset)
// Node 3 is the first generated Clip stage in all benchmark fixtures.
controls.push(GraphControl::set_param(3, GraphParamSlot::Value0, -1.0))
controls
}
///|
fn bench_external_invalid_topology_edit() -> GraphTopologyEdit {
GraphTopologyEdit::rewire_input(0, GraphTopologyInputSlot::Input0, 1)
}
///|
fn bench_external_valid_replace_edit(amount : Double) -> GraphTopologyEdit {
GraphTopologyEdit::replace_node(1, DspNode::gain(0, amount))
}
///|
fn bench_external_invalid_topology_edit_batch() -> Array[GraphTopologyEdit] {
[
bench_external_valid_replace_edit(0.55),
bench_external_invalid_topology_edit(),
]
}
///|
fn bench_external_recompile_rejected_topology_edit(
fixture : BenchExternalAuthoringFixture,
) -> GraphTopologyEdit {
let output_index = fixture.nodes.length() - 1
GraphTopologyEdit::replace_node(
output_index,
DspNode::gain(output_index - 1, 0.5),
)
}
///|
fn bench_external_invalid_doc_rewire(
doc : GraphTemplateDoc,
fixture : BenchExternalAuthoringFixture,
) -> GraphTemplateDocError {
try
doc.rewire_input(
fixture.ids[0],
GraphTopologyInputSlot::Input0,
fixture.ids[1],
)
catch {
error => error
} noraise {
_ => abort("expected invalid topology document rewire")
}
}
///|
fn bench_external_missing_output_template(
fixture : BenchExternalAuthoringFixture,
) -> CompiledTemplate {
let nodes = fixture.nodes.copy()
ignore(nodes.pop())
CompiledTemplate::analyze(nodes)
}
///|
fn bench_external_multiple_outputs_template(
fixture : BenchExternalAuthoringFixture,
) -> CompiledTemplate {
let nodes = fixture.nodes.copy()
nodes.push(DspNode::output(fixture.nodes.length() - 2))
CompiledTemplate::analyze(nodes)
}
///|
fn bench_external_invalid_input_template(
fixture : BenchExternalAuthoringFixture,
) -> CompiledTemplate {
let nodes = fixture.nodes.copy()
let output_index = nodes.length() - 1
nodes[output_index] = DspNode::output(nodes.length() + 17)
CompiledTemplate::analyze(nodes)
}
///|
fn bench_external_invalid_param_template(
fixture : BenchExternalAuthoringFixture,
) -> CompiledTemplate {
let nodes = fixture.nodes.copy()
nodes[1] = DspNode::gain(0, 0.0 / 0.0)
CompiledTemplate::analyze(nodes)
}
///|
test "bench graph: external authoring fixtures compile, bind, and edit" {
let ctx = DspContext::new(sample_rate=BENCH_SAMPLE_RATE, block_size=128)
for fixture in bench_external_authoring_fixtures() {
let doc = bench_external_doc(fixture)
assert_true(doc.length() == fixture.nodes.length())
let template = doc.analyze()
let bindings = build_bench_external_binding_builder(
doc.index_map(),
fixture,
)
.build(template)
.unwrap()
assert_true(bindings.length() == fixture.control_keys.length())
let compiled = CompiledDsp::compile(doc.analyze(), ctx).unwrap()
compiled
.apply_controls(bench_external_control_batch(fixture, 0.01))
.unwrap()
assert_true(
bench_external_replace_roundtrip(doc, fixture).length() ==
fixture.nodes.length(),
)
assert_true(
bench_external_add_roundtrip(doc, fixture).length() ==
fixture.nodes.length(),
)
assert_true(
bench_external_remove_roundtrip(doc, fixture).length() ==
fixture.nodes.length(),
)
assert_true(
bench_external_rewire_roundtrip(doc, fixture).length() ==
fixture.nodes.length(),
)
}
}
///|
test "bench graph: external authoring diagnostic fixtures reject safely" {
let ctx = DspContext::new(sample_rate=BENCH_SAMPLE_RATE, block_size=128)
for fixture in bench_external_authoring_fixtures() {
let doc = bench_external_doc(fixture)
let index_map = doc.index_map()
let template = doc.analyze()
assert_true(
bench_external_invalid_index_binding_builder(index_map, fixture).build(
template,
)
is Err(_),
)
assert_true(
bench_external_invalid_slot_binding_builder(index_map, fixture).build(
template,
)
is Err(_),
)
assert_true(
bench_external_duplicate_key_binding_builder(index_map, fixture).build(
template,
)
is Err(_),
)
ignore(bench_external_invalid_doc_rewire(doc, fixture))
assert_true(doc.length() == fixture.nodes.length())
assert_true(
CompiledDsp::compile_result(
bench_external_missing_output_template(fixture),
ctx,
)
is Err(_),
)
assert_true(
CompiledDsp::compile_result(
bench_external_multiple_outputs_template(fixture),
ctx,
)
is Err(_),
)
assert_true(
CompiledDsp::compile_result(
bench_external_invalid_input_template(fixture),
ctx,
)
is Err(_),
)
assert_true(
CompiledDsp::compile_result(
bench_external_invalid_param_template(fixture),
ctx,
)
is Err(_),
)
let compiled = CompiledDsp::compile(template, ctx).unwrap()
assert_true(
compiled.apply_controls(bench_external_invalid_param_batch(fixture, 0.01))
is Err(_),
)
assert_true(
compiled.apply_controls(bench_external_control_batch(fixture, 0.02))
is Ok(_),
)
let controller = CompiledDspTopologyController::from_nodes(
fixture.nodes,
ctx,
crossfade_samples=128,
).unwrap()
assert_true(
controller.apply_controls(
bench_external_invalid_param_batch(fixture, 0.03),
)
is Err(_),
)
assert_true(
controller.apply_controls(bench_external_control_batch(fixture, 0.04))
is Ok(_),
)
assert_true(
controller.queue_topology_edit(bench_external_invalid_topology_edit())
is Err(_),
)
assert_true(
controller.queue_topology_edit(bench_external_valid_replace_edit(0.55))
is Ok(_),
)
let recompile_controller = CompiledDspTopologyController::from_nodes(
fixture.nodes,
ctx,
crossfade_samples=128,
).unwrap()
assert_true(
recompile_controller.queue_topology_edit(
bench_external_recompile_rejected_topology_edit(fixture),
)
is Err(_),
)
assert_true(
recompile_controller.queue_topology_edit(
bench_external_valid_replace_edit(0.56),
)
is Ok(_),
)
}
}
///|
test "bench graph: realistic external authoring fixtures compile, bind, and edit" {
let ctx = DspContext::new(sample_rate=BENCH_SAMPLE_RATE, block_size=128)
for fixture in bench_external_realistic_authoring_fixtures() {
let doc = bench_external_doc(fixture)
assert_true(doc.length() == fixture.nodes.length())
let template = doc.analyze()
let bindings = build_bench_external_binding_builder(
doc.index_map(),
fixture,
)
.build(template)
.unwrap()
assert_true(bindings.length() == fixture.control_keys.length())
let controls = bench_external_control_batch(fixture, 0.01)
let edited_doc = bench_external_shape_rewire_doc(doc, fixture)
let edited_template = edited_doc.analyze()
let edited_bindings = build_bench_external_binding_builder(
edited_doc.index_map(),
fixture,
)
.build(edited_template)
.unwrap()
assert_true(edited_bindings.length() == fixture.control_keys.length())
match fixture.graph_kind {
MonoExternalGraph => {
let compiled = CompiledDsp::compile(doc.analyze(), ctx).unwrap()
compiled.apply_controls(controls).unwrap()
let edited_compiled = CompiledDsp::compile(edited_doc.analyze(), ctx).unwrap()
edited_compiled.apply_controls(controls).unwrap()
}
StereoExternalGraph => {
let compiled = CompiledStereoDsp::compile(doc.analyze(), ctx).unwrap()
compiled.apply_controls(controls).unwrap()
let edited_compiled = CompiledStereoDsp::compile(
edited_doc.analyze(),
ctx,
).unwrap()
edited_compiled.apply_controls(controls).unwrap()
}
}
assert_true(
bench_external_shape_rewire_roundtrip(doc, fixture).length() ==
fixture.nodes.length(),
)
}
}
// ---- External authoring/control benchmarks ----
// WHY separate from process(): these measure editor/control-thread work from
// the Mini/graph authoring boundary, not audio block processing. Parser,
// lowering, template analysis, binding validation, compile, and hot-swap setup
// may allocate; only precompiled process/apply at block boundaries belongs on
// the audio callback.
///|
test "bench/external_authoring/template_analyze" (b : @bench.T) {
bench_external_template_analyze_group(b, bench_external_authoring_fixtures())
}
///|
test "bench/external_authoring/control_binding_generation" (b : @bench.T) {
bench_external_control_binding_generation_group(
b,
bench_external_authoring_fixtures(),
)
}
///|
test "bench/external_authoring/control_binding_validation" (b : @bench.T) {
bench_external_control_binding_validation_group(
b,
bench_external_authoring_fixtures(),
)
}
///|
test "bench/external_authoring/string_control_resolution" (b : @bench.T) {
bench_external_string_control_resolution_group(
b,
bench_external_authoring_fixtures(),
)
}
///|
test "bench/external_control/apply_param_batch_compiled" (b : @bench.T) {
let ctx = DspContext::new(sample_rate=BENCH_SAMPLE_RATE, block_size=128)
for fixture in bench_external_authoring_fixtures() {
let compiled = CompiledDsp::compile(
CompiledTemplate::analyze(fixture.nodes),
ctx,
).unwrap()
let controls_a = bench_external_control_batch(fixture, 0.01)
let controls_b = bench_external_control_batch(fixture, 0.02)
let use_b = @ref.new(false)
b.bench(name=fixture.name, fn() {
let controls = if use_b.val { controls_b } else { controls_a }
use_b.val = !use_b.val
compiled.apply_controls(controls).unwrap()
b.keep(compiled)
})
}
}
///|
test "bench/external_control/apply_param_batch_topology_controller" (
b : @bench.T,
) {
let ctx = DspContext::new(sample_rate=BENCH_SAMPLE_RATE, block_size=128)
for fixture in bench_external_authoring_fixtures() {
let controller = CompiledDspTopologyController::from_nodes(
fixture.nodes,
ctx,
crossfade_samples=128,
).unwrap()
let controls_a = bench_external_control_batch(fixture, 0.01)
let controls_b = bench_external_control_batch(fixture, 0.02)
let use_b = @ref.new(false)
b.bench(name=fixture.name, fn() {
let controls = if use_b.val { controls_b } else { controls_a }
use_b.val = !use_b.val
controller.apply_controls(controls).unwrap()
b.keep(controller)
})
}
}
///|
test "bench/external_authoring/topology_doc_roundtrips" (b : @bench.T) {
for fixture in bench_external_authoring_fixtures() {
let doc = bench_external_doc(fixture)
let fixture_name = fixture.name
b.bench(name="replace_node/\{fixture_name}", fn() {
let edited = bench_external_replace_roundtrip(doc, fixture)
b.keep(edited)
})
b.bench(name="add_node/\{fixture_name}", fn() {
let edited = bench_external_add_roundtrip(doc, fixture)
b.keep(edited)
})
b.bench(name="remove_node/\{fixture_name}", fn() {
let edited = bench_external_remove_roundtrip(doc, fixture)
b.keep(edited)
})
b.bench(name="reconnect_edge/\{fixture_name}", fn() {
let edited = bench_external_rewire_roundtrip(doc, fixture)
b.keep(edited)
})
}
}
///|
test "bench/external_authoring/compile_prepared_template_change" (b : @bench.T) {
let ctx = DspContext::new(sample_rate=BENCH_SAMPLE_RATE, block_size=128)
for fixture in bench_external_authoring_fixtures() {
let doc = bench_external_doc(fixture)
let edited_doc = try
doc.replace_node(fixture.ids[1], DspNode::gain(0, 0.55))
catch {
error => abort("expected prepared template edit, got \{error}")
} noraise {
next => next
}
let template_a = doc.analyze()
let template_b = edited_doc.analyze()
let use_b = @ref.new(false)
b.bench(name=fixture.name, fn() {
let template = if use_b.val { template_b } else { template_a }
use_b.val = !use_b.val
let compiled = CompiledDsp::compile_result(template, ctx)
b.keep(compiled)
})
}
}
///|
test "bench/external_authoring/queue_prepared_hotswap_setup" (b : @bench.T) {
let ctx = DspContext::new(sample_rate=BENCH_SAMPLE_RATE, block_size=128)
for fixture in bench_external_authoring_fixtures() {
let doc = bench_external_doc(fixture)
let edited_doc = try
doc.replace_node(fixture.ids[1], DspNode::gain(0, 0.55))
catch {
error => abort("expected prepared hotswap edit, got \{error}")
} noraise {
next => next
}
let compiled_a = CompiledDsp::compile(doc.analyze(), ctx).unwrap()
let compiled_b = CompiledDsp::compile(edited_doc.analyze(), ctx).unwrap()
let use_b = @ref.new(false)
b.bench(name=fixture.name, fn() {
let active = if use_b.val { compiled_b } else { compiled_a }
let next = if use_b.val { compiled_a } else { compiled_b }
use_b.val = !use_b.val
let hs = CompiledDspHotSwap::from_graph(active, crossfade_samples=128)
hs.queue_swap(next).unwrap()
b.keep(hs)
})
}
}
// ---- External diagnostic/failure benchmarks ----
// These isolate editor/control-thread rejection paths. Invalid candidates are
// prepared outside audio processing; rejected work must leave the current
// compiled/template state usable.
///|
test "bench/external_authoring_diagnostics/control_binding_invalid_index" (
b : @bench.T,
) {
bench_external_control_binding_rejection(
b, bench_external_invalid_index_binding_builder, "invalid-index control binding",
)
}
///|
test "bench/external_authoring_diagnostics/control_binding_invalid_slot" (
b : @bench.T,
) {
bench_external_control_binding_rejection(
b, bench_external_invalid_slot_binding_builder, "invalid-slot control binding",
)
}
///|
test "bench/external_authoring_diagnostics/control_binding_duplicate_key" (
b : @bench.T,
) {
bench_external_control_binding_rejection(
b, bench_external_duplicate_key_binding_builder, "duplicate-key control binding",
)
}
///|
test "bench/external_control_diagnostics/apply_invalid_param_batch_compiled" (
b : @bench.T,
) {
let ctx = DspContext::new(sample_rate=BENCH_SAMPLE_RATE, block_size=128)
for fixture in bench_external_authoring_fixtures() {
let compiled = CompiledDsp::compile(
CompiledTemplate::analyze(fixture.nodes),
ctx,
).unwrap()
let controls_a = bench_external_invalid_param_batch(fixture, 0.01)
let controls_b = bench_external_invalid_param_batch(fixture, 0.02)
let use_b = @ref.new(false)
b.bench(name=fixture.name, fn() {
let controls = if use_b.val { controls_b } else { controls_a }
use_b.val = !use_b.val
let error = bench_expect_err(
compiled.apply_controls(controls),
"compiled invalid param batch",
)
b.keep(error)
})
}
}
///|
test "bench/external_control_diagnostics/apply_invalid_param_batch_topology_controller" (
b : @bench.T,
) {
let ctx = DspContext::new(sample_rate=BENCH_SAMPLE_RATE, block_size=128)
for fixture in bench_external_authoring_fixtures() {
let controller = CompiledDspTopologyController::from_nodes(
fixture.nodes,
ctx,
crossfade_samples=128,
).unwrap()
let controls_a = bench_external_invalid_param_batch(fixture, 0.01)
let controls_b = bench_external_invalid_param_batch(fixture, 0.02)
let use_b = @ref.new(false)
b.bench(name=fixture.name, fn() {
let controls = if use_b.val { controls_b } else { controls_a }
use_b.val = !use_b.val
let error = bench_expect_err(
controller.apply_controls(controls),
"topology-controller invalid param batch",
)
b.keep(error)
})
}
}
///|
test "bench/external_authoring_diagnostics/topology_doc_invalid_rewire" (
b : @bench.T,
) {
for fixture in bench_external_authoring_fixtures() {
let doc = bench_external_doc(fixture)
b.bench(name=fixture.name, fn() {
let error = bench_external_invalid_doc_rewire(doc, fixture)
b.keep(error)
})
}
}
///|
test "bench/external_authoring_diagnostics/queue_invalid_topology_edit" (
b : @bench.T,
) {
let ctx = DspContext::new(sample_rate=BENCH_SAMPLE_RATE, block_size=128)
for fixture in bench_external_authoring_fixtures() {
let controller = CompiledDspTopologyController::from_nodes(
fixture.nodes,
ctx,
crossfade_samples=128,
).unwrap()
let edit = bench_external_invalid_topology_edit()
b.bench(name=fixture.name, fn() {
let error = bench_expect_err(
controller.queue_topology_edit(edit),
"invalid topology edit",
)
b.keep(error)
})
}
}
///|
test "bench/external_authoring_diagnostics/queue_invalid_topology_edit_batch" (
b : @bench.T,
) {
let ctx = DspContext::new(sample_rate=BENCH_SAMPLE_RATE, block_size=128)
for fixture in bench_external_authoring_fixtures() {
let controller = CompiledDspTopologyController::from_nodes(
fixture.nodes,
ctx,
crossfade_samples=128,
).unwrap()
let edits = bench_external_invalid_topology_edit_batch()
b.bench(name=fixture.name, fn() {
let error = bench_expect_err(
controller.queue_topology_edits(edits),
"invalid topology edit batch",
)
b.keep(error)
})
}
}
///|
test "bench/external_authoring_diagnostics/queue_topology_recompile_rejected" (
b : @bench.T,
) {
let ctx = DspContext::new(sample_rate=BENCH_SAMPLE_RATE, block_size=128)
for fixture in bench_external_authoring_fixtures() {
let controller = CompiledDspTopologyController::from_nodes(
fixture.nodes,
ctx,
crossfade_samples=128,
).unwrap()
let edit = bench_external_recompile_rejected_topology_edit(fixture)
b.bench(name=fixture.name, fn() {
let error = bench_expect_err(
controller.queue_topology_edit(edit),
"topology recompile rejection",
)
b.keep(error)
})
}
}
///|
test "bench/external_authoring_diagnostics/queue_topology_pending_rejection" (
b : @bench.T,
) {
let ctx = DspContext::new(sample_rate=BENCH_SAMPLE_RATE, block_size=128)
for fixture in bench_external_authoring_fixtures() {
let controller = CompiledDspTopologyController::from_nodes(
fixture.nodes,
ctx,
crossfade_samples=128,
).unwrap()
controller
.queue_topology_edit(bench_external_valid_replace_edit(0.55))
.unwrap()
b.bench(name=fixture.name, fn() {
let error = bench_expect_err(
controller.queue_topology_edit(bench_external_valid_replace_edit(0.56)),
"pending topology queue",
)
b.keep(error)
})
}
}
///|
test "bench/external_authoring_diagnostics/compile_result_missing_output" (
b : @bench.T,
) {
bench_external_compile_result_rejection(
b, bench_external_missing_output_template, "compile missing output",
)
}
///|
test "bench/external_authoring_diagnostics/compile_result_multiple_outputs" (
b : @bench.T,
) {
bench_external_compile_result_rejection(
b, bench_external_multiple_outputs_template, "compile multiple outputs",
)
}
///|
test "bench/external_authoring_diagnostics/compile_result_invalid_input" (
b : @bench.T,
) {
bench_external_compile_result_rejection(
b, bench_external_invalid_input_template, "compile invalid input",
)
}
///|
test "bench/external_authoring_diagnostics/compile_result_invalid_param" (
b : @bench.T,
) {
bench_external_compile_result_rejection(
b, bench_external_invalid_param_template, "compile invalid param",
)
}
// ---- Realistic external authoring/control shape benchmarks ----
// WHY separate from the linear fixtures: these keep the same boundary
// decomposition while exercising fan-out, mix-heavy fan-in, terminal stereo,
// and feedback-capable authoring snapshots.
///|
test "bench/external_authoring/realistic_template_analyze" (b : @bench.T) {
bench_external_template_analyze_group(
b,
bench_external_realistic_authoring_fixtures(),
)
}
///|
test "bench/external_authoring/realistic_control_binding_generation" (
b : @bench.T,
) {
bench_external_control_binding_generation_group(
b,
bench_external_realistic_authoring_fixtures(),
)
}
///|
test "bench/external_authoring/realistic_control_binding_validation" (
b : @bench.T,
) {
bench_external_control_binding_validation_group(
b,
bench_external_realistic_authoring_fixtures(),
)
}
///|
test "bench/external_authoring/realistic_string_control_resolution" (
b : @bench.T,
) {
bench_external_string_control_resolution_group(
b,
bench_external_realistic_authoring_fixtures(),
)
}
///|
test "bench/external_control/realistic_apply_param_batch_compiled" (
b : @bench.T,
) {
let ctx = DspContext::new(sample_rate=BENCH_SAMPLE_RATE, block_size=128)
for fixture in bench_external_realistic_authoring_fixtures() {
let controls_a = bench_external_control_batch(fixture, 0.01)
let controls_b = bench_external_control_batch(fixture, 0.02)
let use_b = @ref.new(false)
match fixture.graph_kind {
MonoExternalGraph => {
let compiled = CompiledDsp::compile(
CompiledTemplate::analyze(fixture.nodes),
ctx,
).unwrap()
b.bench(name=fixture.name, fn() {
let controls = if use_b.val { controls_b } else { controls_a }
use_b.val = !use_b.val
compiled.apply_controls(controls).unwrap()
b.keep(compiled)
})
}
StereoExternalGraph => {
let compiled = CompiledStereoDsp::compile(
CompiledTemplate::analyze(fixture.nodes),
ctx,
).unwrap()
b.bench(name=fixture.name, fn() {
let controls = if use_b.val { controls_b } else { controls_a }
use_b.val = !use_b.val
compiled.apply_controls(controls).unwrap()
b.keep(compiled)
})
}
}
}
}
///|
test "bench/external_control/realistic_apply_param_batch_topology_controller" (
b : @bench.T,
) {
let ctx = DspContext::new(sample_rate=BENCH_SAMPLE_RATE, block_size=128)
for fixture in bench_external_realistic_authoring_fixtures() {
let controls_a = bench_external_control_batch(fixture, 0.01)
let controls_b = bench_external_control_batch(fixture, 0.02)
let use_b = @ref.new(false)
match fixture.graph_kind {
MonoExternalGraph => {
let controller = match
CompiledDspTopologyController::from_nodes(
fixture.nodes,
ctx,
crossfade_samples=128,
) {
Some(controller) => controller
None => abort("expected mono topology controller for \{fixture.name}")
}
b.bench(name=fixture.name, fn() {
let controls = if use_b.val { controls_b } else { controls_a }
use_b.val = !use_b.val
match controller.apply_controls(controls) {
Ok(_) => ()
Err(error) =>
abort(
"expected mono topology controls for \{fixture.name}, got \{error}",
)
}
b.keep(controller)
})
}
StereoExternalGraph => {
let controller = match
CompiledStereoDspTopologyController::from_nodes(
fixture.nodes,
ctx,
crossfade_samples=128,
) {
Some(controller) => controller
None =>
abort("expected stereo topology controller for \{fixture.name}")
}
b.bench(name=fixture.name, fn() {
let controls = if use_b.val { controls_b } else { controls_a }
use_b.val = !use_b.val
match controller.apply_controls(controls) {
Ok(_) => ()
Err(error) =>
abort(
"expected stereo topology controls for \{fixture.name}, got \{error}",
)
}
b.keep(controller)
})
}
}
}
}
///|
test "bench/external_authoring/realistic_shape_rewire_roundtrip" (b : @bench.T) {
for fixture in bench_external_realistic_authoring_fixtures() {
let doc = bench_external_doc(fixture)
b.bench(name=fixture.name, fn() {
let edited = bench_external_shape_rewire_roundtrip(doc, fixture)
b.keep(edited)
})
}
}
///|
test "bench/external_authoring/realistic_compile_prepared_shape_change" (
b : @bench.T,
) {
let ctx = DspContext::new(sample_rate=BENCH_SAMPLE_RATE, block_size=128)
for fixture in bench_external_realistic_authoring_fixtures() {
let doc = bench_external_doc(fixture)
let edited_doc = bench_external_shape_rewire_doc(doc, fixture)
let template_a = doc.analyze()
let template_b = edited_doc.analyze()
let use_b = @ref.new(false)
match fixture.graph_kind {
MonoExternalGraph =>
b.bench(name=fixture.name, fn() {
let template = if use_b.val { template_b } else { template_a }
use_b.val = !use_b.val
let compiled = CompiledDsp::compile_result(template, ctx)
b.keep(compiled)
})
StereoExternalGraph =>
b.bench(name=fixture.name, fn() {
let template = if use_b.val { template_b } else { template_a }
use_b.val = !use_b.val
let compiled = CompiledStereoDsp::compile_result(template, ctx)
b.keep(compiled)
})
}
}
}
///|
test "bench/external_authoring/realistic_queue_prepared_hotswap_setup" (
b : @bench.T,
) {
let ctx = DspContext::new(sample_rate=BENCH_SAMPLE_RATE, block_size=128)
for fixture in bench_external_realistic_authoring_fixtures() {
let doc = bench_external_doc(fixture)
let edited_doc = bench_external_shape_rewire_doc(doc, fixture)
let use_b = @ref.new(false)
match fixture.graph_kind {
MonoExternalGraph => {
let compiled_a = CompiledDsp::compile(doc.analyze(), ctx).unwrap()
let compiled_b = CompiledDsp::compile(edited_doc.analyze(), ctx).unwrap()
b.bench(name=fixture.name, fn() {
let active = if use_b.val { compiled_b } else { compiled_a }
let next = if use_b.val { compiled_a } else { compiled_b }
use_b.val = !use_b.val
let hs = CompiledDspHotSwap::from_graph(active, crossfade_samples=128)
hs.queue_swap(next).unwrap()
b.keep(hs)
})
}
StereoExternalGraph => {
let compiled_a = CompiledStereoDsp::compile(doc.analyze(), ctx).unwrap()
let compiled_b = CompiledStereoDsp::compile(edited_doc.analyze(), ctx).unwrap()
b.bench(name=fixture.name, fn() {
let active = if use_b.val { compiled_b } else { compiled_a }
let next = if use_b.val { compiled_a } else { compiled_b }
use_b.val = !use_b.val
let hs = CompiledStereoDspHotSwap::from_graph(
active,
crossfade_samples=128,
)
hs.queue_swap(next).unwrap()
b.keep(hs)
})
}
}
}
}