Report the instrument's automatable parameters to the host under a frozen id table, in signal-flow order, with real units
42 of 44 ids issued: pitch key-track and Trigger length stay reserved pending a live path. Master gain reclassified Live — it never reloaded.
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
// param_units.h — the plain-value layer the host reads a parameter through: the unit category,
|
||||
// the plain range, and the norm <-> plain pair. `toPlain` IS the taper's forward map and
|
||||
// `toNormalized` its inverse, so the host's normalization, the knob's needle angle and the
|
||||
// overlay node's position are the SAME function rather than three that agree today.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/instrument/ui/deck_groups.h" // DeckParam
|
||||
|
||||
namespace reasampler::instrument::param {
|
||||
|
||||
using ui::DeckParam;
|
||||
|
||||
// The eight DISPLAY categories. A category fixes the units string and the digit precision; the
|
||||
// norm <-> plain LAW is per control, because three of the dimensionless controls (the curve
|
||||
// exponents, Q, drive) share a display and share no law.
|
||||
enum class UnitKind {
|
||||
Time, // ms, 0..10000
|
||||
Semitones, // st, -24..+24, always signed
|
||||
PercentUnipolar, // %, 0..100
|
||||
PercentKeyTrack, // %, 0..200
|
||||
PercentBipolar, // %, -100..+100, always signed
|
||||
PercentRate, // %, 50..200, one decimal
|
||||
Decibels, // dB, -60..+24, always signed; norm 0 reads -inf
|
||||
Hertz, // Hz, 20..20000
|
||||
Dimensionless, // no unit, two decimals
|
||||
};
|
||||
|
||||
struct PlainRange {
|
||||
double min = 0.0;
|
||||
double max = 1.0;
|
||||
};
|
||||
|
||||
UnitKind unitKindFor(DeckParam deck);
|
||||
|
||||
// The units string ParameterInfo carries — "" for the dimensionless category. Carried SEPARATELY
|
||||
// from the digits, which is the SDK's own convention (RangeParameter::toString prints the number;
|
||||
// the Parameter constructor takes units as its own argument).
|
||||
const char* unitStringFor(DeckParam deck);
|
||||
|
||||
PlainRange plainRangeFor(DeckParam deck);
|
||||
|
||||
// A straight line drawn in a host automation lane is NOT linear in these plain units, and that is
|
||||
// deliberate: exponential in ms, linear in octaves on cutoff, linear in dB on master gain, a
|
||||
// linear pitch glide on rate, and slow-near-zero on the two centre-expanded semitone throws. It
|
||||
// follows from reporting real units over a musically-shaped taper; the remedy for a user who
|
||||
// wants a literal-units ramp is the host's own curve tools, never a change to the taper.
|
||||
double toPlain(DeckParam deck, double normalized);
|
||||
double toNormalized(DeckParam deck, double plain);
|
||||
|
||||
// The filter's four tone controls STORE their normalized position (payload v9), so their default
|
||||
// normalized value is that stored double verbatim and no taper participates in a host's
|
||||
// reset-to-default. Reporting Hz / Q / drive depth for them means CALLING their frozen laws, not
|
||||
// replacing them.
|
||||
bool storesNormalized(DeckParam deck);
|
||||
|
||||
// The default, read off a default-constructed PlaySeconds — there is no second table of defaults,
|
||||
// and no normalized default is ever written as a literal. defaultNormalized is COMPUTED as
|
||||
// toNormalized(defaultPlain) for every tapered control, which is what makes a host's
|
||||
// reset-to-default and the editor's double-click land on the same value.
|
||||
double defaultPlain(DeckParam deck);
|
||||
double defaultNormalized(DeckParam deck);
|
||||
|
||||
} // namespace reasampler::instrument::param
|
||||
Reference in New Issue
Block a user