As with the offline granulator that we’ve discussed in the previous post, finding resources for real-time granular synthesis on PD was for me even harder. As far as I could figure out, the simple approach that is presented here has not been previously discussed, but I think that this approach is the most efficient, lightweight and intuitive. So please have a look at this post and the example patch and I’ll be very happy to receive any comments, suggestions, questions etc…
Goal: we want to have a look at the intuition behind making a patch that allows basic granular synthesis in real-time on the mic-in signal, using some tools that Pure Data offers. Basic granular synthesis in the context of this post includes the following parameters:
- Grain starting time: how far back in the mic input will the grains be collected.
Grain length: how long the grains will be.
Playback speed: how quickly will the grain be played, affecting the pitch of the grain as well.
The example patch given in this tutorial is a bit more “dirty” than the patch parts that are shown in the text illustrations because there are some complicated relations that need to be taken care of; those relations are beyond the intuitive purposes of this tutorial, so the interested reader is referred to the example patch, which automatically adjusts the aforementioned plus some additional parameters, e.g. grain panning, volume, option for octave-locking and grain firing rate. By abstracting this patch, bigger patches can be made that allow more impressive results on real-time granular synthesis.
Real-time? Circular buffer!
A circular buffer or a ring buffer, can be imagined as a round tape that has a recording head, say on top, and while it is turning, new audio is recorded over old audio. How far back will audio start being recorded over is a matter of the tape length. The circular buffer that comes built in with PD is the [delwrite~ ] object. Figure 1 shows a graphical example of a circular buffer and the PD implementation, considering that the tape has a length of 5 seconds.
Play something on this circular buffer.
To make some sound out of this circular buffer, we need to place a play head, implemented with the [vd~ ] object in PD, at some position of this buffer. The delay time (given as a signal in the [vd~ ] object) defines the how far back we need to take sound from – later on this will be the grain starting time. Figure 2 shows the illustration and the PD implementation of a 300ms delay time.
Isolate a (short) part.
Until now we are able to go back in time in the mic input and start playing continuously what we has been played a while ago (300ms in our example). Figure 3 shows how we can actually trigger an amplitude curve that allows only a short part of what was going on 300ms ago to be heard. The volume envelope comprises a cosine function driven by a [line~ ] object and the time of the line object defines how long the audible segment will be – in this example the time segment is 100ms. Shorter segments are probably more usual in granular synthesis, but let’s consider 100ms for this tutorial.
Pitch up (faster) / pitch down (slower).
If we start moving the playhead on the tape, then the pitch of the recorded material will be affected.
- If we move it closer to the recording head, then the playhead plays the tape’s content faster and therefore we have pitch-up.
If we move it away from the recording head, then the playhead plays the tape’s content slower and therefore we have pitch-down.
The illustration on the right in Figure 4 shows both directions, but the PD patch part on the left shows only the slower case. For playing the tape’s content slower we need to gradually move the playhead away from the recording head (increase the delay time in the [vd~ ] object). This is done by the [line~ ] object that substituted the [sig~ ] object on top of the [vd~ ] object. In this example, during the 100ms that the audible segment “survives”, the playhead moves from 300ms (direct initialisation of the [line~ ] object) to 400ms.
That’s a grain!
As Figure 5 indicates, this patch part is what we need to control the three aforementioned parameters (grain starting time, length and playback speed); thus we have a basic implementation of a grain.
- Grain starting time is controlled by the parameter value in the green box.
Grain length is controlled by the parameter value in the red boxes.
Grain pitch is controlled by the parameter value in the bleu box (greater value than the one in green box causes pitch down and the vice versa).
A simple patch built by a online single grain from mic-in and randomness
The example patch given allows monophonic granular synthesis on mic input with setting some random parameters. This patch implements the ideas of granular synthesis discussed until Figure 5, along with some additional parameters, includes controls for setting the minimum and the range of random variation for the following parameters:
- Firing rate (how often new grains are fired).
Grain starting time.
Grain starting volume.
Initially, maximum grain length and maximum delay time are set and almost all horizontal sliders are giving relative percentages based on those maximum values. There are many interrelations between the different parameters in order to avoid glitches and other things that can go wrong. E.g. it is not possible to have the play head 50ms away from the rec head and request (for pitch-up purposes) to move the playhead 100ms towards the rec head since this way the playhead will have to go 50ms in the… future!
I’m also preparing a bigger patch that includes combined abstractions of single grains based on this tutorial patch. I’ll make a new post about bigger patches for both file-based and mic-in-based granulators. Stay tuned!