Class Control
- Namespace
- Sigil.Sound
- Assembly
- Sigil.Sound.dll
A value the game or UI sets while sound is playing, such as engine RPM or how tense the music is. The audio thread
follows it smoothly, so a jump in Sigil.Sound.Control.Value (a game frame is 16 ms, a block is 5 ms) glides over
slewSeconds instead of clicking. Setting it from any thread is safe and takes no lock.
public sealed class ControlInheritance
Inherited Members
Examples
// A control is a value the game changes while the sound plays. Here an engine note follows an RPM control.
var rpm = new Control(800, min: 600, max: 7000, slewSeconds: 0.03);
var engine = Saw(rpm / 30).LowPass(rpm.Map(200, 4000, ControlCurve.Exponential));
rpm.Value = 3500; // set from the game loop, every frame
engine * 0.3
Remarks
A control converts to a Sigil.Sound.Param and to a Sigil.Sound.Sound, so it goes anywhere a modulating value does. One control can drive any number of sounds and voices; each reads it once per block. A graph compiled later starts at the current value, with no glide from the default.
Constructors
Control(double, double, double, double, string?)
public Control(double value = 0, double min = 0, double max = 1, double slewSeconds = 0.02, string? name = null)Parameters
valuedouble-
The starting value.
mindouble-
The lowest value; Sigil.Sound.Control.Value is clamped to it.
maxdouble-
The highest value; Sigil.Sound.Control.Value is clamped to it.
slewSecondsdouble-
The glide time: after this long the sound has covered about 63% of a jump. 0 follows at once, which can click on gain, pitch and cutoff.
namestring?-
A label for debugging and for showing the control in a UI.
Properties
Max
The highest value.
public float Max { get; }Property Value
Min
The lowest value.
public float Min { get; }Property Value
Name
The label given at creation, or null.
public string? Name { get; }Property Value
Options
The names of the choices when the control is a selector (see Sigil.Sound.Control.Choice(System.String,System.Collections.Generic.IReadOnlyList{System.String},System.Int32)); null otherwise. The value is the index of the chosen option and only takes whole numbers.
public IReadOnlyList<string>? Options { get; }Property Value
Polarity
What a signal sent to Sigil.Sound.Control.SetFromSignal(System.Double) spans. Defaults to Sigil.Sound.ControlPolarity.Unipolar.
public ControlPolarity Polarity { get; init; }Property Value
SlewSeconds
The glide time in seconds.
public float SlewSeconds { get; }Property Value
Style
The widget a host UI is advised to show. Defaults to Sigil.Sound.ControlStyle.Knob.
public ControlStyle Style { get; init; }Property Value
Taper
How a UI's travel maps onto the value; Sigil.Sound.Control.Travel applies it. A hint for a host UI: the sound does not care.
Set it when creating the control: new Control(1200, 40, 18000) { Taper = ControlTaper.Log }.
public ControlTaper Taper { get; init; }Property Value
Exceptions
- ArgumentOutOfRangeException
-
Sigil.Sound.ControlTaper.Log with a minimum that is not above zero, or an unknown taper.
Travel
The value as a position from 0 (the minimum) to 1 (the maximum), through Sigil.Sound.Control.Taper. A UI reads it to place a knob and sets it as the knob turns, so the UI never needs to know the taper. Setting it is thread-safe like Sigil.Sound.Control.Value, and the sound still glides over Sigil.Sound.Control.SlewSeconds. A selector's travel is the choice's place along its options.
public double Travel { get; set; }Property Value
Examples
// A knob reports its position from 0 to 1 and the control applies the taper: half way is the geometric middle, 1000 Hz.
var cutoff = new Control(100, min: 100, max: 10000) { Taper = ControlTaper.Log };
cutoff.Travel = 0.5;
Saw(110).LowPass(cutoff) * 0.4
Exceptions
- ArgumentOutOfRangeException
-
Set to NaN or infinity.
Value
The value the sound is heading for. Set it from any thread; out-of-range values are clamped to Sigil.Sound.Control.Min and Sigil.Sound.Control.Max.
public double Value { get; set; }Property Value
Exceptions
- ArgumentOutOfRangeException
-
The value is NaN or infinite.
Methods
Choice(string, IReadOnlyList<string>, int)
Creates a selector: a control that picks one of a few named options. The value is the index of the chosen option, it changes at once with no glide, and its style is Sigil.Sound.ControlStyle.Selector.
public static Control Choice(string name, IReadOnlyList<string> options, int selected = 0)Parameters
namestring-
A label for the UI.
optionsIReadOnlyList<string>-
The names of the choices, at least two.
selectedint-
The index of the starting choice.
Returns
Examples
// A selector holds the index of the picked option. Here option 1 ("Saw") opens the filter further than option 0.
var wave = Control.Choice("Wave", ["Sine", "Saw", "Square"], selected: 1);
Saw(110).LowPass(wave * 600 + 400) * 0.4
Map(double, double, ControlCurve)
The control mapped from its own range onto outMin to outMax. The glide happens
before the mapping, so an exponential cutoff sweep stays smooth.
public Param Map(double outMin, double outMax, ControlCurve curve = ControlCurve.Linear)Parameters
outMindouble-
The output when the control is at Sigil.Sound.Control.Min.
outMaxdouble-
The output when the control is at Sigil.Sound.Control.Max.
curveControlCurve-
Use Sigil.Sound.ControlCurve.Exponential for frequencies.
Returns
Map(double, double, double, double, ControlCurve)
The control mapped from inMin to inMax onto the output range; values outside the input range extend the line.
public Param Map(double inMin, double inMax, double outMin, double outMax, ControlCurve curve = ControlCurve.Linear)Parameters
inMindouble-
The input value that maps to
outMin. inMaxdouble-
The input value that maps to
outMax. outMindouble-
The output at
inMin. outMaxdouble-
The output at
inMax. curveControlCurve-
Use Sigil.Sound.ControlCurve.Exponential for frequencies.
Returns
SetFromSignal(double)
Sets the control from a signal that arrives from outside, such as a modulator the host wired in. The signal is read through Sigil.Sound.Control.Polarity (0 to 1, or -1 to 1) and then Sigil.Sound.Control.Taper; a signal beyond the span stops at the ends.
public void SetFromSignal(double signal)Parameters
signaldouble-
The incoming value.
Exceptions
- ArgumentOutOfRangeException
-
The signal is NaN or infinite.
ToString()
A short description of the control, such as its current value.
public override string ToString()Returns
Operators
operator +(Control, double)
The control plus a constant, as a signal.
public static Sound operator +(Control control, double offset)Parameters
Returns
operator /(Control, double)
The control divided by a constant, as a signal.
public static Sound operator /(Control control, double divisor)Parameters
Returns
implicit operator Param(Control)
Uses the control as a parameter; the value is read live, once per block.
public static implicit operator Param(Control control)Parameters
controlControl
Returns
implicit operator Sound(Control)
Uses the control as a sound, so it can be added to, scaled and fed to other sounds.
public static implicit operator Sound(Control control)Parameters
controlControl
Returns
operator *(Control, double)
The control times a constant, as a signal.
public static Sound operator *(Control control, double gain)Parameters
Returns
operator *(double, Control)
The control times a constant, as a signal.
public static Sound operator *(double gain, Control control)Parameters
Returns
operator -(Control, double)
The control minus a constant, as a signal.
public static Sound operator -(Control control, double offset)