With the latest release you can type in “GrainUtils” in the helpbrowser and get an overview over all the guides and helpfiles. Thanks @nufets for the contribution.
I have added DualPulsarOS. A sub-sample accurate, bandlimited and oversampled pulsar oscillator with cross modulation between mod and osc and phase increment distortion which warps the phases of the osc and mod oscillators via a cubic easing function to redistribute the single cycles for pitch slides per grain.
Check it out here:
If somebody ever wondered about my motivation for creating GrainUtils or want to have a better understanding about sub-sample accurate event scheduling and dynamic voice allocation, i have put together a pdf file which encapsulates all of that, with some nice mathlib plots ![]()
GrainUtils.pdf (2.0 MB)
With the latest update you get MorphSVF which can continuously interpolate between LPF, BPF and HPF shapes through linear interpolation of the filter mix coefficients.
(
{
var sig, fltFreqMod, fltFreq;
fltFreqMod = SinOsc.ar(\fltFreqMF.kr(2));
fltFreq = \fltFreq.kr(2000) * (2 ** (fltFreqMod * \fltFreqMD.kr(0)));
sig = Saw.ar(55);
sig = MorphSVF.ar(
input: sig,
freq: fltFreq,
resonance: 0.85,
shape: SinOsc.ar(0.3).linlin(-1, 1, 0, 1) // 0: lpf, 0.5: bpf, 1: hpf
);
sig!2 * 0.1;
}.play;
)
s.freqscope
With the latest update you get a refactor of the RampDivider Ugen, which now has three different modes for ramp division. Release v1.3.14 · dietcv/GrainUtils · GitHub
- simple (mode 0) - No automatic sync.
- grid (mode 1) - On significant ratio change, the follower snaps to the nearest grid position at the next wrap of the input ramp. Causes a mid-cycle phase discontinuity.
- offset (mode 2) - On ratio change, the follower completes its current cycle at the previous slope and transitions at its own next wrap. No mid-cycle discontinuity; the follower may be temporarily offset from the grid during the transition.
(
{
var phase = Phasor.ar(DC.ar(0), 20 * SampleDur.ir);
var ratio = EnvGen.ar(Env([3, 3, 2], [0.2, 0]));
var modeA = RampDivider.ar(phase, ratio, mode: 0);
var modeB = RampDivider.ar(phase, ratio, mode: 1);
var modeC = RampDivider.ar(phase, ratio, mode: 2);
[phase, modeA, modeB, modeC, ratio * 0.1];
}.plot(1);
)
several internal improvements in here: Release v1.3.17 · dietcv/GrainUtils · GitHub
Now single binary build with some adjustments towards buffer handling and oversampling, thanks to @Spacechild1.
A few more refinements to make until the release of SchedulerBank, with voice spread and kuramoto-sakaguchi global phase coupling to enter the matrix of n schedulers x m voice allocators.
Which pill will you take?
SchedulerBank is ready ![]()
listen to some random presets here:


