Skip to content

AmbientSynth 1.12.1

Choose a tag to compare

@reneweller-coding reneweller-coding released this 10 Sep 14:21
· 59 commits to master since this release

The grain loop, four times faster — and two things it was getting wrong.

A third of the instrument's work was in one loop. Measured with VTune over a preset with four
texture slots, SourceSlot::renderTexture was 3.11 s of 9.87 s — the largest single cost in the
synthesizer, and 59 % of it with the density knobs up. It is now 0.80 s, and the whole render went
from 9.87 s to 6.82 s of CPU.

Two steps got it there. The test that ends a grain (age >= len || pos >= len - 2) sat inside the
sample loop and belongs in front of it: when a grain runs out of window or off the end of the clip
follows from its rate, and can be worked out once a block. Then the loop was vectorised across the
SAMPLES of one grain rather than across grains — across grains they all add into the same output
sample, so every step ends in a horizontal reduction, and their lanes are never all alive at once.
Across samples the accumulation is a plain vector add and the lifetime stays scalar. AVX2 on x86-64
with a gather for the interpolation; NEON beside it for the Quest. Measured against the scalar path,
the difference is 114 dB below the signal.

Silence at the top of the keyboard. A grain reads Grain length × rate samples of its clip, and
when that was more than the clip held, no grain spawned at all — not a shorter one, silence. A
one-second clip with 300 ms grains went quiet two octaves up. The grain is now shortened to what the
clip can give. (The shipped library did not reach this below MIDI 85; a short clip of your own does.)

Grains that were cut off and lost. Grains is a ceiling on how many may be started, but the
render loop stopped there too: turning the knob down left every grain above the new value cut off
mid-waveform — a click — never finished, and still marked as in use, so its place was gone for good.
The live grains are now packed densely, so the ceiling costs nothing when it is high and means what
it says when it is low.

Grain clouds lost a comb. New grains began at sample 0 of the audio block regardless of when they
were actually due, so a dense cloud started every grain on one of 750 instants a second. They now
begin where the spawn clock says.

Checked: self test, host test, race test, pluginval at strictness 10, the thread sanitizer and the
address sanitizer — the last three on exactly this code.

The sample library -- eight archives, 10.55 GB: the samples, wavetables and impulse responses
the presets name -- is attached here. The installer offers to download it during setup.