Tags give the ability to mark specific points in history as being important
-
v0.5.8b
851cf934 · ·saugns v0.5.8b. ADSR envelope edge case fixes. Fix ADSR envelope behavior when earlier stages take up the whole note time and there's more than one stage left; now, ensure advancing past every stage when note time runs out. The exception is in loop mode (`el`), which disregards the note duration. Also, fix edge cases for declick mode `ed`.
-
v0.5.8
b49235d6 · ·saugns v0.5.8. Support ternary smooth violet noise, etc. Language changes: * Signal generator types. `R` mode `m` noise functions: - Modify ternary `t` so that changing the shaping level does not mix it with uniform random; instead, make it only impact every other value, keeping it a form of "zero-stuffed" violet noise (which is what makes it sound "smoother" especially when used as modulator). - Implement violet `v` version of `t`. Less bassy, and yet more smooth-sounding for intense use as modulation carrier or modulator. This is a zero-stuffed version of the binary violet noise. - Add `m.z` override for zero-stuffing amplitude used by `t` modes; can e.g. be set to -1 to ensure every other half-cycle hits the bottom amplitude (making it bottom heavy). * Noise types for `N`: add `tv` ternary violet noise, i.e. zero-stuffed version of `bv` (binary violet noise). -
v0.5.7c
a5110990 · ·saugns v0.5.7c. Ladder effect distortion panning and tweak. Language changes: * Channel mixing. Add new pan law `a` additive mix panning (`c.pa`), which is a complement to `f` full-volume mode. Only increases channel panned to (the other unaffected). Used as part of implementing more accurate ladder effect panning. * Ladder effect distortion: - Add `a.l[p]` pan ratio control; multiplier for channel mixing `c` parameter, used specifically for the ladder effect pulse. If 0, mixes the pulse in mono as before. The new behavior, for more accurate emulation uses `C` (-1/7) as the default. Behavior depends on pan law. - Deprecate `a.l.t` in favor of renamed `a.l[t]` option. Tweak ladder effect distortion `a.l` behavior; the behavior to limit DC offset on silence was bad especially for LFO as it could halve the pulse level for half the cycle. It could _somewhat_ reduce pulse amplitude in more cases too. Fixed. Previously, the pulse (always up for an input amplitude not below minus the `a.l[t]` threshold value) would if up decay to 0 if it remained up. Now it only decays when input isn't also above plus the `a.l[t]` threshold value. It's reset to full amplitude when not decaying. This does cause a new quirk, mainly noticeable for a larger `a.l[t]` value and/or larger `a.l` pulse amplitude. When up the pulse may distort, decay beginning, only to be followed by a jump up in level if the input amplitude rises. This is mainly visible in the waveform but not audible. -
v0.5.7b
db5f31fb · ·saugns v0.5.7b. ';' timing fix. Add ADSR 's.t' min sustain. Language changes: * Parameter envelopes. - Add minimum sustain time `s.t` envelope parameter. Can be used to ensure the sustain stage runs for a time if the envelope continues. When time is insufficient, and sustain is normally missing, the release is displaced. In loop mode `el`, a sustain stage is added. - Rename envelope mode `c` (clip envelope shape) back to `t` (truncated envelope). Fix voice allocation for `;` syntax with no time `t` after; an old bug could make such a voice expire prematurely. This fix is needed for a new `examples/drums-and-eh.sau` script. -
v0.5.7
e81d4adf · ·saugns v0.5.7. Added "ladder effect" distortion. And more. Language changes: * Amplitude handling. Add "ladder effect" distortion `a.l` (by default off). The constant `C` (7/512, as in `a.lC`) matches the YM2612 chip level for the pulse added by the distortion. This is Sega Mega Drive/Genesis model 1 type distortion, a.k.a. the hardware bug part of the "sound". - The mixing scales the original signal, plus the added pulse, so that 1.0 plus pulse is brought down to 1.0. - The pulse is added in mono regardless of panning. The actual chip only allowed switching channels (left and right) on and off and added the pulse in all 4 cases. For more accurate behavior, use full-level panning as in `c.pf`; only the mute + pulse behavior is missing. - A threshold control `a.l.t` generalizes the behavior. The pulse shape is controlled by the threshold; where the size of negative input amplitudes exceeds the set threshold, the pulse is down, otherwise up (including whenever the amplitude is positive). The default `C`, here 2^-13, makes it match the chip behavior. For any levels from zero to minus the threshold, a completely different distortion (not matching the chip) is added by silencing that portion of the waveform. If raising the threshold, this becomes audible; it combines with the added pulse such that when the pulse fades out, a half-wave rectified signal remains which is "colored" similarly to a milder version of the pulse. * Frequency filters. The generator `a.f` options now apply to the final result for a generator. Previously, the `c` (channel mixing) options were handled afterward; panning wasn't filtered, but rather after filtering, unlike now. * Fix, that is apply `S c.p`; didn't actually work before. * Parameter sweeps. For a frequency sweep from `f` to `r`, or `r` to `f`, no longer convert its `v` to match `g` -- do not make the `v` value a ratio or non-ratio to match. Instead let the line type interpolate between behaviors. * Deprecate use of PD and self-PM subparameters after `p.` in favor of the `p[]` syntax. This also means e.g. `W[]` and `R[]` instead of `W.` and `R.` for shorthand syntax. * Deprecate use of filter options `a.f.l` and `a.f.h`; the `a.f[l h]` options are favored. From now on each subparameter option will be available only through one of, after a `.` or within `[]`, never both. New options may use this to have the same name, but a different meaning. -
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`.