# The frozen id table and the derived exposed set. Links deck_groups alone: the exposed set IS
# deckParamCommit's answer, and identity needs nothing else.
reasampler_pure_library(param_id SOURCES param_id.cpp LINK PUBLIC deck_groups)
reasampler_test(param_id LINK param_id)

# The norm <-> plain layer. deck_values carries the tapers' full scales and the two field
# resolvers the defaults are read through; filter_params and master_gain are the frozen laws the
# filter's four and the gain report through, CALLED rather than restated. filter_params rather
# than the whole `filter` target: this is the parameter surface, and a link edge from it onto the
# per-voice filter KERNEL would put the voice DSP in reach of any future extension-side consumer
# of param_format — which root CLAUDE.md's bake invariant forbids.
reasampler_pure_library(param_units
    SOURCES param_units.cpp
    LINK PUBLIC deck_values param_taper curve_law master_gain filter_params)
# sample_map for the test alone: the host-vs-editor default agreement reads the two instance
# scalars where they LIVE, and one of them is a field of InstrumentParams.
reasampler_test(param_units LINK param_units param_id sample_map)

reasampler_pure_library(param_format SOURCES param_format.cpp LINK PUBLIC param_units)
# param_id and sample_map are linked for the test only: the one-formatter-two-consumers assertion
# sweeps the exposed set (identity's answer, not this module's) and reads pitch key-track where it
# lives, on InstrumentParams.
reasampler_test(param_format LINK param_format param_id sample_map)

# The host write, both sides of the model/audio split: the live block patched in place and the
# stored parameter set written, through one value map (param_units'). No engine — the block is a
# value, not a thing the voice owns.
reasampler_pure_library(param_live
    SOURCES param_live.cpp
    LINK PUBLIC deck_values live_params param_units)
# sample_map for the test alone: the equivalence assertion drives the MODEL path
# (writeHostParam -> resolvePlay -> foldLive) as its reference.
reasampler_test(param_live LINK param_live param_id sample_map)

# The block-boundary merge decision — the automation hold's authority lifetime, with no atomic
# and no host type in it.
reasampler_pure_library(param_merge SOURCES param_merge.cpp LINK PUBLIC param_live)
reasampler_test(param_merge LINK param_merge param_id param_units sample_map)
