Tags give the ability to mark specific points in history as being important
-
v0.5.6c
3bc41d8d · ·saugns v0.5.6c. Ratio carrier selection for modulators. Fix. Language changes: * Frequency. Ratio carrier selection for modulators. Every modulator now has the `r.c` option; it allows overriding which carrier's frequency is multiplied by the `r` value (by default going up one level, `r.c-1`). Changing it to 0 or a positive value will go inward, from the root/top. Values out of range are clamped to the range, from root, to the level just above the modulator being set. Fix v0.5.6 edge case bug for frequency parameter sweeps; if using ratio for goal but not for state or vice-versa (mixed rather than consistent selection), the newer handling could mess up the signal. Scripts like the below are now fixed. "W f[W f10 a440] t10 p[R f440 r[g1]]"
-
v0.5.6b
6b60e3e7 · ·saugns v0.5.6b. Add pan law switches. Remove time '|' quirk. Language changes: * Channel mixing. Add `c.p` pan law switch to each generator, and a `S c.p` default setting. The modes are: - `l` (linear, center -6 dB, default). The old behavior, allows a mono downmix to undo panning cleanly. - `f` (full, center -0 dB). Makes positions `L`, `R` and `C` behave like traditional channel switcher settings. `2*L` or `2*R` cause a phase-inverted "fake surround". Modulation produces stereo-spread distortion (mono mix simplifies the sound while it remains impure). * Timing. For `|` time separator, correct an inconsistency (and the documentation). Using `|` never decreases delay to add now. Previously, it did so only when no generator was active in scope (like before any is added or after a prior `|`). -
v0.5.6
6c5ec477 · ·saugns v0.5.6. Add 1-pole filter options. Redesign rendering. Language changes: * Frequency filters. - Add filter option `a.f` for all audio generators, and 1-pole lowpass and highpass filters. Options `a.f.l`, `a.f.h` (alternatively `a.f[l h]`) will set a cut-off frequency to use if given a positive number; if given 0, the filter is disabled. As shorthand, `a.f` can be given a number if only lowpass or highpass (not both) is to be used; a positive number is used for lowpass, while a negative number is negated, and then used for highpass; if 0 is set, both filters are disabled. - Add global mix filters under `S a.f`, the same syntax and use as those for individual audio generators. The use of these filters is recommended to filter a whole audio file. * Parameter sweeps. Change sweep time interpretation, from being dynamic (much like time for a modulator), to being static or parse-time (much like timing offset syntax). A sweep is no longer paused or delayed if the generator it belongs to is paused or unused. Change `-p` printouts to only include script/"program" info beyond statistics if verbose `-v` is also passed. Tweak the format as well both for statistics and for verbose display. Redesign audio generation code; the traversal of the linked generators and deciding what to run now happens in new code in parser/semantics.h. The generator.c code now only runs a set of instructions (sauRIns), provided/set once per event. The aim is to move complexity out from the audio rendering. -
v0.5.5b
043ceb20 · ·saugns v0.5.5b. Another edge case fix for internal ID reuse. Fix remaining object ID allocation/reuse bug. A script like the following misbehaved (in this case making the `N` silent the last second): "W[R t2 ; a0] t1 /1 W[N t4] t2" Further ID reuse correctness changes, and final improvements for reuse (see `saugns -p` output) with this approach.
-
v0.5.5
45106d14 · ·saugns v0.5.5. Make numerical variables lexically scoped. Language changes: * Numerical expressions. Fix parsing bug causing `num-[]` (where `-[]` is a later expression clearing and setting a modulator list) to fail to read number `num`. * Numerical variables. Make them lexically scoped, add an option for accessing globals. - Make `$var=` always assign to a variable at the current block/list level. - Make `$var` in a numerical expression return a value from the lexically closest variable with a value, if any. Thus `$var=$var` may create a new local variable given the value of a variable from an outer scope. - Add `$~var` which can be used to read and/or write to a global variable from any lexical scope. For any syntax that began with `$var`, `$~var` is available. - Restrict `$?var` to being used at the global scope. Non-overriding assignmnent `$var?=` can still be used at any scope; it checks for the existence of `$var` at any scope, does nothing if it exists, defines a local variable if it does not exist. * Time values. Rename constant `D` to `T`. -
v0.5.4
80bb2f48 · ·saugns v0.5.4. Envelope mode changes, add 'S e' option. Language changes: * Script options. Add envelope setting `S e` to allow setting values for several envelopes at once. The values accepted are the same as those for any `.e` envelope subparameter, except for a lack of sweep and modulator values within `S e[]`. To apply the setting to envelopes in some generator after in the same scope, "touch" an envelope setting by writing its name, for example `a.e` mentions the amplitude envelope and the setting is then applied to it. * Parameter envelopes. Adjust ADSR envelope modes, changing the default to the new declick mode `d`. - Rename modes `t` (truncate envelope trajectory) to `c` (clip envelope shape), and the old `c` (clamp stage times) to `s` (shrink stage times). - Add `d` (declicked envelope shape), which when time runs out before completion keeps the last value and starts the next attack from it. Otherwise like `c`. Fix v0.5.2 bug which caused `S a` behavior when an affected generator uses AM lists to go wrong (scaling was wrongly applied to `.r[]` too, and not to `.e[]` which it should be). Simplify parser semantics, merge generator and object IDs. The object ID reuse is slightly better than in v0.5.3e (which improved it compared to v0.5.3d), but less "perfect" than v0.5.3e generator ID reuse (in return re-simplifying the generator pass code). -
v0.5.3e
0571b48a · ·saugns v0.5.3e. Fix several parsing bugs. Fix v0.5.3 use-after-free when cloning into modulator lists, as triggered by scripts such as: `'a W[R] | N[A :a N :a :a]` Fix time placement of `@name` inside modulator list assigned for a `;` compound step. This never worked correctly before; it used to be placed before the `;` in time from v0.3.12, in older versions being placed an extra time after `;` instead. Also fix behavior of the undocumented `{}` grouping feature, specifically it mixed with the `;` compound step, `{; ...}`. -
v0.5.3d
8bf41c50 · ·saugns v0.5.3d. Fix elusive bug in semantics code. Fix v0.5.3 bug not caught by test scripts, which may prevent correct generator ID reuse in scripts which use more voices.
-
v0.5.3c
04dea7e4 · ·saugns v0.5.3c. Fix crash on failed script file open. Fix v0.5.3 bug causing crash (occasionally hang) when saugns fails to open a file to parse (for example, bogus filename).
-
v0.5.3b
8486b7dd · ·saugns v0.5.3b. Fix edge case for cloned modulators. In v0.5.3 object IDs alongside generator IDs were made to be reused. Object ID reuse code missed an edge case (to treat cloned modulators as labeled/non-reusable if the main/carrier generator cloned is freshly labeled). A crash could happen for scripts triggering the error.
-
v0.5.3
18cd2822 · ·saugns v0.5.3. Generator cloning with ':name'. Language changes: * Time values. Replace non-number literal `d` for the main time `t` parameter with a constant `D` usable for every time length parameter. * Label syntax. - Add `:name` expression, for copying the object pointed to by "name". A generator copy will be inserted where the reference is placed, unlike with an `@name` reference which merely touches the original object. A copy has separate time. All modulators are also cloned, once per copy. - Remove the deprecated syntax for num. variable assignment, `'name=`. Simplify parsing code and semantics before audio generation. One less set of data structures, don't copy and "convert". The code formerly called "parseconv" is now parser/semantics. Write generator number allocation code in parser semantics to reuse generators when their durations expire in scripts. The printouts from `saugns -p` reflect the new scheduling, the audio output is (of course) identical. -
v0.5.2
27c5993a · ·saugns v0.5.2. Give 'A' and 'N' wrappers 'f' control. Language changes: * Signal generator types. Allow frequency `f` (and ratio `r`) for all generators, not only oscillators. This allows using `A0[...]` (or `N[...]`) as a wrapper generator and giving it timed pitch changes, to control nested oscillators inside (which can use `r`). Useful for FM and additive sound design, with several carriers per voice. * Line types. More exp/log types with steepness not 6. - Add `exp11`, `log11`, `xpe11`, `lge11`. Steepness 11. * Modulation with value ranges. Tweak semantics, and add envelope options `.e` to long-form, for completeness. Don't switch list behavior for the very first list when the `..` long-form syntax is written just after, instead do it when short-form `.r` or `.e` are written after. After `..`, the options `.r`, `.e`, and/or `.a` can be used -- concatenated in the order listed, with any left out. For example, just one of them, or `.r.e`. * Fix `S a` when placed in additive AM list. (A typo in the code prevented multiplication by outer level setting from working, muting sound for generators after in scope instead.) * Frequencies as notes. Slightly tweak JI quartertones used. -
v0.5.1
4c321ec4 · ·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
ee70b648 · ·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
ab21657e · ·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
4615bf3d · ·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
3e343b0d · ·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
960161e7 · ·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
e8d8adb0 · ·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
761cec29 · ·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.