Discontinuities in granulators are commonly handled using windowing functions, though they sometimes create a recognisable sound and I was looking for alternative techniques.
Zero-crossing (ZC) detection can be deployed to avoid discontinuities between grains.
In Pure Data, I had already done some experiments last year with this technique using audio samples and static buffers. The sounds were nice and crisp though a proper implementation wasn’t possible because of some limitations in PD.
I am now implementing my new systems in Faust and the image shows the Faust diagram of the main unit in the granulator.
For this implementation, I’m using Faust’s read-write tables as circular buffers for the read and write indexes can be piloted through signals and there are no issues with synchronisation among several buffers.
This algorithm uses three circular buffers. One buffer is used to store the processed signal; the other two buffers are used to store the index position at which a ZC has been detected in ascending or descending signals.
“Frame“ linearly cycles through integers starting from 0 to read the samples in the buffer. At each new cycle, a new ZC position is sampled and used as a starting position for the grain. The position is then fed back into “frame“ to calculate the end position for that grain, which is the ZC position closest to the desired length of the grains. To keep consistency for ascending and descending signals, the output of the granulator is tracked down with a differentiator to calculate the slopeness that is sent back into the main module, in the “sel_zc“ object, so that the next position is sampled from the right set of ZCs.
Quite happy of how it sounds and the next step might be to implement the algorithm with variable delay lines to make grain transposition possible, although synchronisation might not be as easy.