#saugns v0.5.7 adds the "a.l" ladder effect distortion at last, 2 years after I experimented with it.

There were many things that seemed silly not to have, while adding the le, so I did all those other things first. Including frequency filter for audio generators in general, instead of placing a filter only inside the distortion.

Now a line like this at the top of a SAU script sets a Sega MD-like sound:
"S a.lC a.f2840 c.pf"

#LadderEffect #YM2612 #SAUlang

#saugns v0.5.6 is out. The never-heard-of command-line synthesizer that makes audio a text/script file format.

Added 1-pole frequency filter options, for each audio generator, as well as a script-wide mix filters option. Ignore them for no filtering. (More filter options are planned for later... This adds some tone control, but not yet proper support for subtractive synthesis.)

(I haven't announced versions consistently here, but anyway...)

I've added MIDI note number constants for frequency in #saugns v0.4.7. (It also fixes just intonation so changing key rotates scale ratios.)

So now `W fM57` beeps at 220 Hz for example. And the note suffixes for flat and sharp, including quartertone (1/2 a MIDI number), can be used here as well.

Phase self-modulation a.k.a. "feedback FM" now added to #saugns / #SAUlang as "p.a" parameter for both wave and random line segment oscillators.

I use stronger filtering than Yamaha did, trivial 1-pole + 1-zero filters both, allowing roughly twice the feedback without too much noise.

Self-PM sawtooth-ifies all smooth noise types nicely. I made the level of self-PM sweepable and modulatable in turn.

Straightforward implementation for random line oscillator, but ~4x slower than no self-PM code.

Finally getting to adding a #saugns cli feature to pre-set and pass variables to numbers. Not difficult at all to implement, I just wonder about how details should look.

This seems a keeper, non-overriding numerical assignment syntax:
'name?=value

But what if scripts are written to take an argument? There's no print feature in the SAU language. Rather than no warning or some auto-warning, I added this optional syntax for use near the top of a script:
!$name

Warns if it doesn't hold a number.

#saugns v0.4.3 was released earlier this week, adding the N generator -- previously found (with less features) in an older development branch. "Ngw t10" for example now makes 10 seconds of plain Gaussian noise.

It's low-hanging fruit, another thing for generating simple signals with my program. All the bigger goals for new features remain, with several old incomplete development branches, but with some steps toward redesign taken since the previous version.

In #saugns, for the time only in the `ladderesque` git branch, I've toyed with adding a distortion based on the Sega MD I "ladder effect" (iconic DAC hardware bug, crossover distortion).

I based it on Aly James's old description:

https://alyjameslab.blogspot.com/2013/06/ym2612-ladder-effect-suite.html #alyjames

But I made the dist signal level a freely set parameter (default 0.01 matches Aly's 0.02).

Sounds bad for some sounds, blends in softly with some, and makes a few sound nicer. `Rlin` noise sounds rich, fresh with a level of 0.025.

YM2612 "LADDER EFFECT" Suite

Last infos on Aly James Latest Creations & Development: Music, Audio Softwares, Synthesis & Signal Processing, Electronics, DIY, Dev updates...

I've created some Codeberg issues for planned #saugns features and design changes. No feedback on such yet from anyone, but may as well write it down...

Only today did it become clear to me: In theory, reducing the number of script processing passes *and* doing as much as possible at the parser end of the program is not a mistake, it'll be best in the end if only I think my way towards solving each problem that comes up. I just need to think better than a decade ago.

https://codeberg.org/sau/saugns/issues/6

Towards fewer script processing passes

Work after v0.4.2c is in progress to reduce the number of processing passes from the parsing end to the audio rendering end. It matters little for present features (actually it's been easier to make things work with more passes, requiring new insights to have fewer and make it still fully work). But a longer-term goal *could* be to adapt this system for live coding, and then multiple passes going through a script won't work as a design. Reducing passes to two also seems optimal for a design without live coding (given no compelling reason for more passes), and that seems good to do before adding more complexity. Some reductions in passes are smaller design adjustments that simply increase efficiency. A smaller change (in the stable branch) is that there's no longer any full postparse loop going through nodes in the parser, as all that is now done per durgroup rather than per script. Beyond that, it's now also in reach to remove a main layer between the parser and the generator/interpreter. Voice allocation doesn't need a separate pass (and is moved to parser per durgroup in the stable branch). This means the parseconv module can be done away with. But some questions remain as to where to place things, how exactly to divide things up between the two remaining ends, or main parts of the program. In the defunct experimental redesign branches that added features on top of something close to a 2011 "mgensys" version of the program, there were likewise only two layers (it was based on the program *before* the middle layer had came about). Some other "sgensys" and saugns features were missing making the task simpler, and I simply made a layer like parseconv + generator at the generator end. In a new, main, more incremental redesign to keep, it may be better to place more at the parser end -- meaning a leaner and meaner generator/interpreter end -- but how much? Remaining in the parseconv middle is: 1) Creating and assigning arrays of node IDs, used for traversal later. 2) "Voice traversal" code only needed for the `-p` printouts (audio rendering does it differently), which depends on the former. It's difficult to tell whether future features will require a different kind of node ID than presently used. The object IDs simply increase without ever being recycled. In the generator/interpreter, it may eventually be best to use a second kind of ID (separate op IDs), allocated to minimize how high they go. Such op IDs are more involved to allocate optimally than voice numbers, it's not yet been attempted in my program. It may become trickier with future features, too, which add more in the way of control flow. However, I think in theory it should always be possible to calculate ahead how a non-Turing complete interpreter will handle timing, etc., pre-running that part to the extent needed, if needed in the future -- though a restriction on number of script processing passes may limit features. So while a little more challenging, I lean towards doing as much as possible in the parsing end of the program; I think it'll be worth it in the end. (It will also mean a smaller design gap between such a design and some future one-pass design, should such become needed for an attempt at live coding.)

Codeberg.org

This sweep and modulator list syntax unification is in #saugns v0.4.2, released today.

The idea for this change was simple, but it took years before it popped into mind. It's done and that's great, but sometimes I wish I found somewhere to discuss such language ideas, it could lead to more sooner. Usually no one has had anything at all to say beyond either indifference or simply finding my program a bit interesting to play with.

I've experimented with making further kinds of simple musical scripts for my #saugns program, mainly one-liners shorter than 80 characters.

It's easy to make algorithmic music that may fit 90s-style video games. Here's a one-liner background #music track, remarkably complex for having one voice and 3 ops only, using randomness for both timbre and "note" variation.

/seed(2) Rlin f2 t60*4 p[Wmto r8.r64[Ruwh f1] a2]