A Max/MSP external object for multi-channel, multi-voice, multi-transposition granular synthesis

Michael Edwards

object arguments
left inlet
other inlets
change log


This Max/MSP object performs time granulation of sampled sound in real-time.

Input in the form of a fixed, pre-recorded sample buffer or an incoming signal of user-specified length is used to randomly select segments of sound (grains) whose durations (grain length) may be modified on-the-fly. The grains are (amplitude-) enveloped and reconfigured each time a precursor comes to an end.

The granulation is performed in a user-specified number of streams (also known as (aka) voices or layers): the more streams, the denser and thicker but also the smoother the effect. An increase in streams also implies an increase in processing time and is the main factor affecting real-time performance.

The streams may be subject to transposition whereby either a single transposition offset is given and/or a list of semitone values sent to the object forms the set from which a randomly-chosen value is selected for each grain of sound output by the object.

Finally, each grain is routed to a randomly-chosen outlet (the number of which is also user specified) allowing mapping onto an arbitrary number of output channels.

N.B. Most data passed to the object only has an effect when the DSP is on. If you're getting strange behaviour/crashes, make sure the DSP is on before you start interacting with the object.

mdeGranular~ object usage

object arguments

The object takes the following arguments:

  1. The number of simultaneous streams (aka voices, layers) of grains ; this is limited only by your computer's CPU power.
  2. The number of output channels; this will determine the number of signal outlets the object has, i.e. there will be one for each channel you request.

object inlets

left inlet

As with most Max/MSP objects, various data can be sent to the left-most inlet:

other inlets

The rest of the inlets, numbered from left to right, are as follows. The messages which can be sent to the leftmost inlet to accomplish the same thing are in square brackets and are case sensitive.

  1. Transposition offset in semitones (default none): This may be fractional; it is added to the list of transpositions sent to the left inlet (see above), or simply transposes all the grains if no transposition list is given.
  2. Grain length in milliseconds (default 50).
  3. Grain length deviation (as a percentage) of the grain length (plus or minus, default 10%); i.e. if anything other than 0, the grain length is randomised by an amount between plus or minus the deviation percentage.
  4. The minimum start point in the input buffer (fixed or live) in milliseconds (default 0). The actual start point is a function of the grain length, and the start and end points (see below) and is randomly chosen to fit anywhere within these points.
  5. The maximum end point in the buffer in millisecs (the default is the end of the buffer). N.B if end < start then the buffer will be granulated backwards. If the difference between these two is too small for the ramp up and ramp down to be accomplished, no grains will be output.
  6. The "density" of the grains (as a percentage). 100% means a grain will start immediately every time the previous one ends, 50% means one in two grains (determined randomly) will produce no output. (Default 100%).
    [ Density]
  7. Grain amplitude (>=0 and <= 100, default 0.5). This is a straight amplitude scaler for each grain, i.e. no account is taken of how many voices there are. N.B. when using MIDI faders, the 7-bit step between values is often large enough to create a slight but audible click in output. This is corrected in mdeGranular~ by interpolating from the last to the new amplitude. The side-effect is that new amplitudes will not be accepted for an "audio tick's worth" of samples.


mdeGranular~ 1.1 (external and help file) for Max API 6.1.3 and above. 64 bit and more stable than the Universal Binary version below.

Old mdeGranular~ archive (external and help file) for Max/MSP pre Max 6.1.3 on OS X (Universal Binary)
N.B. On older systems this ZIP file needs to be unzipped with /System/Library/CoreServices/BOMArchiveHelper in order for resource forks to be preserved. If you get the error "mdeGranular~: no such object" when you open the help file in Max/MSP, unzip the downloaded archive again using the above application.

mdeGranular~ external for Windows Max/MSP (thanks and kudos to Giacomo Lepri for compilation services)
mdeGranular~ help file

change log

19/9/13: 1.1
    * Updated to Max API 6.1.3: fairly hefty changes to make the object work in
    the now 64 bit float (double) MSP environment.  The object should also
    behave itself better when the dac~ is turned on and off and/or receive
    messages that normally would need the dac~ to be on before being processed
    correctly.  Most changes however reflect the new buffer accessing
    framework.  The MSP buffer~ is still 32 bit (for backward compatibility) so
    if granulating a static buffer~, its samples are first copied over and
    promoted to 64 bit.  This will mean that if you change the contents of the
    buffer~ there will be no difference to the granulator's output until you
    reuse the set message again, thus triggering the samples copy.
    * 3/10/11: added BufferGrainRamp message/method
    * 19/5/11: fixed bug that caused crash on reinitialisation of object

14/9/10: 1.06:
    * made some changes to allow resumption of previous state (without crashes)
      when the DSP is turned off and back on again 
    * migrated project to latest SDK (5.1.1)

    * fixed a bug that caused a crash when quickly changing ramp lengths from
      very long to short;
    * added the Portion, PortionWidth, and PortionPosition messages to more
      easily control buffer granulation points; 
    * made the ms prefix to setting live buffer sizes no longer necessary by
      introducing the setms message e.g.  'setms 2000' instead of 'set ms2000'
      (but ms prefix still works);
    * handled the post bug that in Max5 refuses to add new lines (thus screwing
      up warning/error messages); 
    * fixed bug in grain start/end setting that added current live index even
      when we were processing a static buffer;  
    * separated out the maxmsp and pd interface parts into separate c files
      and created a common header.

    * added Warnings message to turn on/off printing to max window (for Kim
      Cascone ;)  

1/5/08: 1.03: 
    * added OctaveSize and OctaveDivisions messages for non-standard tunings 

17/4/08: 1.02: 
    * fixed bug that stopped grain amplitude from reaching 0 

3/4/08: 1.01: 
    * added OSX USB support 
    * fixed RAND_MAX bug in between function

Michael Edwards
Last modified: Friday, 08-Mar-2019 15:18:11 CET