Skip to content

Tags

Tags give the ability to mark specific points in history as being important
  • v0.5.1
    saugns v0.5.1. Add ADSR envelope to sweepable parameters.
    
    Language changes:
     * Parameter envelopes. Implement ADSR envelope, add to every
       sweepable parameter. This uses list heading subparameters,
       under the new `.e` (envelope) subparameter which has a new
       sweepable secondary value (like that for value range `.r`,
       but for an envelope as a stage applied after, similarly).
       The envelope secondary value also accepts modulators in
       the list as does the long-form value range secondary value.
       - Add `a`, `d`, `s`, `r` subparameters within `.e[...]` --
         these can be used alongside the sweep subparameters.
         Also add `e` for further envelope-specific settings.
       - Add line selection `.l` sub-subparameter for each timed
         subparameter (`a`, `d`, and `r`), as well as `e` for
         setting all of them (overridden by the others if used
         at the same time) as in `e.lcos`.
       - Add 4 modes which can be toggled under `e`, default `ec`:
         `0` (off), `c` (clamp stage times to fit note duration,
         shortening stage trajectories without cutting them off),
         `l` (loop envelope instead of triggering when time set),
         `t` (truncate envelope trajectory if times are too long).
     * Remove long-deprecated sweep subparameter `r` (now `l`).
     * Phase distortion synthesis. Make the secondary parameter
       values default to the do-nothing values if not zero. Makes
       PD envelopes and value range modulation simpler to use.
    
    Support an ADSR envelope for each of the parameters allowing
    value ranges and sweeps (most). It triggers and runs anew with
    each new time duration set to the main `t` parameter for the
    generator the parameter belongs to. Each `;` for the generator
    implicitly sets `t` and thus triggers the envelope.
    
    For modulators, if time is implicit/indefinite (default `ti`)
    then the envelopes for parameters trigger with the closest
    carrier having its time set. Thus a single `;` for a carrier
    can trigger envelopes for a nested structure of oscillators.
    
    Prune example scripts, tweak some old ones adding envelopes.
    
    Performance tweaks to phaseshaping code, replace floorf().
  • v0.5.0c
    saugns v0.5.0c. Fix for builds with the clang 19 compiler.
    
    This is for an issue known to have affected x86-64.
    
    No difference for gcc nor for clang 18 and older.
    With clang 19, to keep -ffast-math builds from having
    broken FM and PM, never use lrint()/lrintf(), always
    use llrint()/llrintf() even when C type `long` is 64-bit.
    (Otherwise the former turn into 32-bit result instructions
    that clip values in some places.)
  • v0.5.0b
    saugns v0.5.0b. Fixes for PD parameter handling.
    
    Fix sweeps for PD parameters. These were meant to
    work, but were broken by v0.5.0 refactoring; time
    flags lacked initialization.
    
    Correct polarity of PD `.p` phase offset for `R`,
    was flipped relative to `W`.
    
    Fix mis-scaling of the `.p` phase offset for `.c`
    and `.d`, when using `R mh`, and for `R` whenever
    the `.f` multiplier is used.
    
    Refactor, unify "phasor" (phase signal generator,
    including PD) for `W` & `R`.
  • v0.5.0
    saugns v0.5.0. Add a set of PD synthesis & PS options.
    
    Language changes:
     * Signal generator types. Add `W` mode toggle. (See below.)
     * Accept phase `p` values directly after `W` and `R` (a
       phase number requires e.g. parentheses around to set it
       apart from a wave or line type). This is mostly a shortcut
       to using phase subparameters (`W.a1/2`) and/or PM (`W[W]`).
     * Accept amplitude `a` values directly after `N` (not only
       after `A` as before); an amplitude number requries e.g.
       parentheses around to set it apart from the noise type.
       This is more for consistency and as a shortcut for AM.
     * Implement phase distortion synthesis, and some forms of
       pulsar synthesis as well. Add a set of phase `p`
       subparameters for this; each is for a distortion function,
       with main and subvalues which can be set, swept, and
       modulated. Used with constant numbers, they derive new wave
       types, e.g. `W.c2` is a sine alternating between on and off
       every other cycle with preserved base frequency.
     * Accept phase `p` subparameters for PD and for self-PM as
       `p[]` list heading subparameters. The main `p` parameter
       doesn't support value sweeps etc., so there was nothing
       else being parsed in such a way. This combines with the
       new support for `p` values right after `R` or `W`.
    
    Implement `R` and `W` PD options, each such subparameter
    (including its 2 subparameters) having full value ranges
    support.
     * Each PD option under `p` subparameters has in turn:
       - Subfrequency `.f`.
       - Phase offset `.p`.
     * The new duty cycle parameter `p.d` defaults to 1; a
       zoom phase distortion which is the inverse of `p.c`
       and corresponds to "PulWM", implemented through PD.
       Full zoom-out at 0.
     * The new cycle length parameter `p.c` defaults to 1.
       Values closer to 0 "zoom in" -- sawtooth-like edges
       may form. Values larger than 1 "zoom out", with the
       new area filled with a "blank" (the cycle beginning
       and end amplitude).
     * The new hold phase distortion with parameter `p.h`,
       a way to overwrite a portion of a wave cycle. Using
       a positive value draws a horizontal line up to that
       phase position, e.g. 1/4 for the first 1/4; using a
       negative value the line is drawn backward (for -1/4
       over the last 1/4).
     * The new `p.x` and `p.y` parameters allow a PWM-like
       phase distortion, which changes the size proportion
       of the 1st and 2nd halves of a cycle. Use `p.x` for
       "PWM" generalized to any wave type. Meanwhile `p.y`
       is the inverse, a rate-of-change distortion for how
       much phase moves in each half, making one "slower",
       the other "faster".
     * Tweak the `W` oscillator's LFO behavior for ADAA to
       remove overshoots, also fix PD glitches. For 0 Hz a
       prior value was (re-)used instead of a new, causing
       some LF noise with the new zoom-out PD. Instead, in
       case of phase difference at most 1 LUT value large,
       produce a naive sample instead. More glitches fixed
       for extreme PD where one sample pops up or down but
       some issues remain.
    
    Allow use of `W` as a naive oscillator using a new mode `m`
    switch. (The `W m` option is similar to `R m`, but simpler,
    having only 2 letters for modes as yet.) The default is `a`
    (ADAA, antiderivative anti-aliasing) preserving the current
    behavior. Using `n` switches to the naive implementation in
    the codebase that gives results like pre-v0.3.9 saugns, but
    with the current wave types -- not rounded like v0.3.3 had.
    
    Fix default line type for `p.a[]` -- now `lin`, was `cos`.
    
    Major refactoring, mainly of the generator module.
  • v0.4.8c
    saugns v0.4.8c. Fix minor bug, refactoring.
    
    Fix v0.4.8b bug which gave junk results when a
    0 Hz oscillator has an `f` modulator with `r`
    frequency ratio. (Normally useless, but valid
    in scripts.) Was due to use of uninitialized
    data for that specific case only.
    
    This script made noise with the buggy v0.4.8b,
    is correctly silent now:
    
    `W f0[W r10 a1000] t10`
  • v0.4.8b
    saugns v0.4.8b. Value range modulation for more parameters.
    
    For consistency, allow "Modulation with value ranges" for
    every parameter which accepts value sweeps. That's all with
    modulators, except the main phase & PM parameter `p` and its
    frequency-scaled PM subparameter `p.f`, where range-mapping
    doesn't make sense. This means it's now supported for `c`
    (channel mixing) and for self-PM `p.a` as well.
  • v0.4.8
    saugns v0.4.8. Add long-form value range modulation syntax.
    
    Modulation with value range. Add a new variation on
    the syntax with greater flexibility, for both `a`
    (amplitude) and `f`/`r` (frequency) parameters.
    
    Below `X` and `Y` denote optionally included range
    endpoint values, while `A` and `B` are the newly
    introduced modulator lists whose outputs are added
    for the endpoints only. The `C` and `D` modulator
    lists work as before. The old syntaxes remain as
    short forms unchanged:
     - `X[A]..Y[B].r[C].a[D]`
     - `X[D].rY[C]`
     - `X[D]`
    
    The use of the '..' changes the meaning of the first
    modulator list prior if included, so that it plays
    the part of `A` rather than of `D`. (If no `C` list
    is used for the generator the results of `A` and `D`
    modulators are identical, but the lists are built
    and cleared separately.)
  • v0.4.7c
    saugns v0.4.7c. Bugfixes for "r" rel. freq handling.
    
    Fix bugs for `r...` relative frequency parameters in
    AM modulators when placed inside `A` or `N`. (Latter
    types don't have frequency parameters, so use of `r`
    inside can't apply to them as the carriers outside.)
    When possible, make `r1` be better than `f1`.
     * A script `N a0[W]` now has a default frequency of
       `f440` for the inner `W`, not `r1` (which is like
       `f1` here, as there's no carrier frequency). But,
       in `W a0.r1[N[W]]` it's `r1`, effectively `f440`.
     * A separate bug affected e.g. `W a0.r1[A0[W r1]]`,
       where the `r1` acted like `f1` instead of passing
       the nearest outer frequency from the other `W`. A
       pointer wasn't passed along, a typo made it NULL.
     * Don't allow `r` for a modulator with all carriers
       being of types lacking a frequency parameter. Now
       such modulators are more like 1st level carriers.
    
    Clarify `r` behavior fully in the `README.SAU` file.
  • v0.4.7b
    saugns v0.4.7b. Bugfix for "$?variable" checks.
    
    Fix error resulting in silence rather than no script
    when script rejected by "$?variable" check. This bug
    was added in v0.4.4b.
    
    Also a little update for example scripts.
  • v0.4.7
    saugns v0.4.7. Improved named note frequencies.
    
    Language changes:
     * Add generator type `A` (Amplitude generator), for
       sweepable amplitude offsets i.e. DC offsets, plus
       adding and/or multiplying its AM modulators.
     * Frequencies as notes.
       - Support MIDI note number constants (`M0` to `M127`
         where `M69` by default corresponds to 440 Hz). All
         tuning systems are supported, but for just intoned
         notes, numbers which don't map to any natural note
         get the average of the two surrounding ones. Other
         options include flats and sharps (which for a just
         note are never exactly between two notes) like for
         C-D-E-F-G-A-B notes.
       - For just intoned tuning modes, rotate scale ratios
         with key selection, so that the note for a key has
         the first ratio. Makes tuning good for non-C keys.
    
    Generator `A` is yet of limited use, but will take a
    greater role when distortion options etc. are added.
  • v0.4.6
    saugns v0.4.6. Added `R` flag `p` for 1D Perlin noise modes.
    
    Language changes:
     * Signal generator types. `R` mode `m` flags:
       - Add `p` (Perlin noise mode) to reshape the waveform for
         1D Perlin noise, combinable with all noise functions and
         other flags.
       - Change updating of flags when adjusting mode; now every
         flag set is kept until setting a function, which clears
         old flags. Before, any change to mode cleared old flags.
         (Makes especially the use of parameter `.a` less clunky.)
         Also fix `m.a... ma`, now handled like `ma.a...`.
     * Line types.
        - Add `smo` (Smoothstep degree 5),
          a sinuous curve traditionally used for Perlin noise.
     * Seed parameter. Make `s` recognize the same numerical
       constants as `p` (phase), currently `G`.
  • v0.4.5
    saugns v0.4.5. Added self-PM/"feedback FM". New 'R' mode 'a'.
    
    Language changes:
     * Add `p.a` amplitude feedback parameter for phase,
       for phase self-modulation. Accepts both sweep and
       modulators within `[]`. Default value is 0.0.
     * Signal generator types. `R` mode `m` noise functions:
       - Add `a` (additive recurrence, low-discrepancy a.k.a.
         quasirandom sequence) by default based on the golden
         ratio. Add mode subparameter `m.a` for changing the
         multiplier used to the fractional part of a number.
       - Rename `r` (uniform random, default) to `u`.
       - Seeds for all modes not using the `h` flag now differ.
         Keep the highest bit from the internal 32-bit seed,
         sacrifice the lowest bit (odd vs. even line segment)
         as phase extends a bit to take over its role instead.
     * Numerical expressions. Changes to mathematical functions:
       - Add `arbf(x)`, additive recurrence base frequency.
         Returns a multiplier for how much the pitch will
         change for an `R` instance when `x` is set to `R ma.a`.
         The value may be negative, corresponding to direction
         in a sawtooth-like wave which rises rather than falls.
       - Add `arhf(x)`, additive recurrence higher frequency.
         Like `arbf(x)`, but for the closest new frequency above
         the unshifted base frequency, instead of below it.
       - Add `sgn(x)`, which returns the sign of `x` as +/- 1
         or 0. (The sign bit is also preserved for 0.)
       - Remove deprecated `seed(x)` function replaced by `$seed`.
     * Seedable common parameters. Add `s` common to `N` and `R`,
       for overriding the default seed (assigned to new instances
       based on the `$seed` variable and a random sequence
       derived from it). `s` takes a value modulo 1.0 as the
       percentage of the state space, so `s0` means beginning, 0.
    
    This self-PM support requries, to preserve the performance
    when not using the feature, twice as much code for both the
    `W` and `R` implementations. Self-modulation typically takes
    at least 3 times more CPU time, sometimes more than 4 times.
    (Self-modulation precludes use of vectorizing optimations.)
    
    The parameter range uses the simplest scaling possible, like
    multiplying the value by pi. This maps 1.0 to Yamaha feedback
    level 6 in their chips. To avoid excessive ringing at that
    level, stronger filtering than Yamaha used is used: 1-zero
    (their choice) combined with 1-pole (itself a little better
    at dampening self-oscillations than a 1-zero filter alone).
  • v0.4.4d
    saugns v0.4.4d. Another minor parsing bugfix. Refactoring.
    
    Fix parsing bugs for (still undocumented) `{}` grouping.
    Refactor scope handling in parser, extend arrtype module.
    
    "Random segments oscillator" has been renamed to
    "Rumble oscillator, a.k.a. random line segments oscillator"
    in the documentation.
  • v0.4.4c
    saugns v0.4.4c. Minor parsing bugfix. Refactoring.
    
    Language changes:
     * Nesting syntax.
        - Fix parsing of num. expr. namespace for "Y" in `[X][Y]`;
          for any "X" object params, "Y" sweep namespace was lost.
        - Change undocumented generic `<...>` nesting, to `{...}`.
     * Sweep syntax. Remove deprecated support for params in `{}`.
    
    Rebased down modulator list `-` and concat, and sweep and list
    unification, to v0.2.x (modified sgensys versions pre-saugns).
    Logs kept while scripts in branch have one less syntax change.
    
    Changes in naming and code style built up, working through the
    versions. The new code is tidied similar to old rebasing work.
    Outside the parser, refactoring and more cover some more code.
  • v0.4.4b
    saugns v0.4.4b. Turn PRNG seed into cli-settable variable.
    
    Language changes:
     * Numerical expressions. Replace `seed(x)` with `$seed` magic
       variable, which composes with the non-overriding assignment
       feature for simple cli setting and script handling of seed.
       [Add backward-compatibility deprecated `seed(x)` function.]
    
    Improve usage warnings on failed `$?name`, `$?name=...` check.
    
    Old scripts can usually be updated with one of the below regex
    options -- the 2nd will use `?=` assignment to allow override.
    
    `perl -pi -e "s/\\/seed/\\\$seed=/g;" paths...`
    `perl -pi -e "s/\\/seed/\\\$seed\\?=/g;" paths...`
  • v0.4.4
    saugns v0.4.4. Cli and variable feature expansion.
    
    Command-line options:
     * Add "variable=value" option, to set variables and pass them
       to scripts. Each variable is passed as `$variable`, and the
       name must be valid for use as a SAU variable. Each value is
       restricted to only a number which may have a decimal point.
     * Make `-e` apply only to scripts after, not to every script.
    
    Language changes:
     * Variable syntax.
        - Change numerical variable assignment syntax to use a `$`
          as leading character: `$name=...`, unlike object labels.
          [Add backward-compatibility deprecated alias, `'name=`.]
        - Labels (`'name `, `@name`) and variables (`$name`) won't
          conflict if they have the same name any longer. Now they
          are separate rather than one dynamically typed variable.
        - Add `?=` non-overriding numerical assignment; only takes
          effect for a variable that doesn't hold a number. Has no
          side effects when skipping evaluation of the expression.
        - Add `$?name` construct warning when a numerical variable
          isn't already set to a number. Can be used by itself, or
          combined with assignment (`$?name=...`) to also do `?=`.
          If used by itself, the script won't run on failed check.
    
    The new cli option and SAU `?=` syntax work together, to allow
    passing named, numerical arguments to a script. A script makes
    predefining a value optional by using `?=` to set its default.
    Using `$?name` requires that `name` be passed, used by itself.
    
    Old scripts can be updated to use the newer assignment syntax,
    without any manual adjustment, using regex search-and-replace:
    
    `perl -pi -e "s/'([A-Za-z0-9_]+\\s*)=/\\$\\1=/g;" paths...`
  • v0.4.3
    saugns v0.4.3. Add 'N' noise generator. Small redesign steps.
    
    Language changes:
     * Add generator type `N` (Noise generator), a plain
       noise generator without any frequency parameters.
       It has the underlying noise types of `R` and red.
     * Variable syntax. Relax rules for use of numerical
       variable `=`, allow whitespace after `=`, and not
       only before it. This behavior is less surprising.
     * Allow `[]` list unconnected to any parameter. Its
       objects are held unused. More language constructs
       are needed to use the free list, or its contents.
     * Amplitude handling. Add `S a.m`, script-wide gain
       mix control in outermost scope. Replaces the role
       of `S a` in disabling auto-downscaling by voices.
    
    Parser redesign:
     * Turn lists into a main type, for two with the old
       audio "operator". Create objects, do type checks.
     * Make parseconv a utility header the parser simply
       uses. Simplify memory handling & code structures.
    
    Fix some parser warnings wrongly numbering position.
  • v0.4.2d
    saugns v0.4.2d. Various fixes. Beginning of new redesign.
    
    Language changes:
     * Channel mixing. Fix combination of `c[]` modulation
       and non-swept non-center values; e.g. `cL[...]` now
       is at left compared to `cC[...]`, before it wasn't.
    
    Fix minor bugs in parser timing code:
     * Make time `td` default time work properly
       for modulators; it (from v0.3.11c) always
       used to change to implicit time for them.
     * Fix bug causing default times to end up
       too short in a few situations; cleanup.
    
    Parser redesign:
     * Make postparse code in parser run once
       per durgroup just after it, not at end
       of script. Adjust, simplify time code.
       Preparation for further time redesign.
     * Move voice number allocation to parser
       from parseconv. Don't fix a number for
       each carrier, allow their renumbering.
       This made voices number optimally low.
    
    Add `CHANGELOG.md` based on tag messages and the website,
    with a few additions for clarity on parts of the history.
    
    A few scripts may now count as having fewer voices and
    consequently play louder, if auto-scaling of amplitude
    is used. One example being, `'a W cL| 'b W cR| @a t1`.
  • v0.4.2c
    saugns v0.4.2c. Add quartertone pitch names, add JI systems.
    
    Language changes:
     * Frequencies as notes.
        - Add flat 'b' alias ('f' still supported).
        - Add half-flat 'd' and half-sharp 'z'.
        - Add flat-and-a-half 'v' and sharp-and-a-half 'k'.
        - Add double-flat 'w' and double-sharp 'x'.
        - Add "S f.s" tuning systems 'c' (classic
          5-limit JI) and 'p' (Pythagorean 3-limit JI).
    
    Revise and extend frequency as note further.
    Extend default 12TET-based options to 24TET;
    use the 7-factor quartertone for JI tunings.
    
    (JI is short for just intonation.)
    
    Add a classic 5-limit JI 'c' mode with sharp
    and flat always the same size unlike in 'j'.
    Also add Pythagorean tuning system mode 'p'.
  • v0.4.2b
    saugns v0.4.2b. Allow "[X][Y]" to "[X Y]" concat.
    
    Language changes:
     * Modulator list syntax. Writing two or more lists in
       direct succession now concatenates their contents.
    
    Minor feature addition which is backward-compatible.
    
    Other than that, this is a clean-up release, removing
    obsolete and misleading looping in generator.c, and
    trimming obsolete code in parser.c.