In the last article, I discussed the beginnings of granular synthesis, the basic theory, and some of the applications of this synthesis technique. In this post, we will walk through a basic implementation of granular synthesis that focuses on independent pitch shifting and time stretching of an audio file. You won’t need more than a rudimentary knowledge of Max/MSP to follow along, and most of the techniques we will discuss can be easily ported to other computer music platforms.
You can find the finished project HERE. I am assuming a small knowledge of Max/MSP jargon, and I won’t stop to describe objects in particular, unless they are fundamental in understanding the concepts. If you ever have a question about one of the objects, the reference system and documentation in Max/MSP is great, and I encourage you to use it to clarify anything that you may not understand. Most of the heavy lifting is done inside a poly~ object that holds instances of the eb.Granulator abstraction. Most of the article will be focused on that object, and I will leave most of the UI stuff out of this discussion. The project folder contains all the external files and dependencies you’ll need, so you should be good to go!
I have automatically loaded one of everyone’s favorite Max samples, anton.aif, into the patch, but you can drop any sample you like from your hard drive to experiment with other sounds (if for some reason you don’t have anton.aif in your max search path, you’ll have to load your own sound into the patch before you’ll hear anything). You can start by turning ON the grains, and hitting the PLAY button. This will play through the audio file in a mostly naturally sounding way. Then play the sample back after adjusting the transposition to hear some pitch shifting, and then try adjusting the play back rate to hear some time-stretching. You’ll definitely hear the characteristic sound of granular based time and pitch effects, and some of that can be quite cool. Try pushing the playback rate really slowly, or transposing the sample in extreme ratios (you can use the number box below the dial to get crazy).
There are also some controls for scrubbing through the sample, and defining just a range for playback. You can play back just a small repeating section, or you can have the grains jump around the sample. You can play everything back in reverse, which can give quite interesting results depending on the source material.
Now that we know how it sounds, let’s take a look at some of the inner workings of the patch. Open up the eb.Granular patch from the Max/MSP project. I’ve tried to do my best to annotate this, so there is some direction once you’re in the device. At the top of the device we receive a MIDI note. We convert each note into a bang that tells our granular engine how to playback the sample. When you turn On the granular engine, a MIDI note is sent into the device at an interval defined by the Grain Frequency setting. The rate of grains has a huge impact on the sound.
You can follow the trigger objects bang out from right to left to see the order of operation. First we send a bang to manage the voice of this poly (turning them off when not in use saves CPU!), then we fetch the transposition. This affects the pitch of each grain. Then we get the panning and the length of each grain (make sure that this is longer than the grain frequency!). Finally we calculate where in the sample we should start playing, where in the sample we will end, and the length of time it will take to get there.
With each bang, the parameters that we have defined are used to play back the sample from the buffer in a particular way. If you were to expand this engine to include randomness on every parameter, each bang would generate new values and would give an organic and unpredictable feel to the sound (which is awesome). In this basic implementation the only parameter that is randomized is the position in the sample where playback will begin, but there are subpatchers (the rchoose patch) that can easily introduce some defined randomness.
So we’ve talked about granular synthesis, and we made our own simple engine in Max/MSP. You can extend this in a variety of ways, and in the next article we’ll explore some of the options.