This is a tutorial on making a simple audio loop in Max/MSP.
The accompanying patches can be found here:
Let us begin!
Let us begin with almost the simplest patch that will allow one to loop a piece of audio. This patch can then be expanded upon.
This simple patch allows the user to control four aspects of the loop:
• which file is being looped
• what the ratio of playback should be (this changes the speed and pitch accordingly)
• where the loop begins in relation to the audio in the file
• how long the loop is
The patch revolves around the groove~ object. The groove~ object controls the playback of a sample through its inlets and outlets. The groove~ object is associated with a buffer~ object by sharing the same name in their first argument. The groove~ object has the word "loop" as its first argument. The buffer~ object also has the word "loop" as its first argument. The word "loop" in this context acts as a name that binds the groove~ object to the buffer~ object.
The buffer~ is an allocated space in memory in which the sample that is played back via the groove~ is stored. The number after the name of the buffer~ (in this case the word "loop") is how long the sound file that is loaded into the buffer~ (and played back by the groove~) can be. This sets the maximum length of the file in ms.
In this patch, the maximum length of the buffer~ is 60000 ms or or one minute exactly. For example, if a wave file is loaded into the buffer~ that is two minutes long, only the first 60000 ms will be available to the groove~ object to play back. However, if a wave file is loaded into the buffer~ that is only forty seconds long, the entire 40 seconds will playback (even though 60 seconds was set as the seconds argument for the buffer~). In order to read a file into the buffer~ so that it can be played back by the groove~ object, the message "read" must be sent to the buffer~'s only inlet.
The groove~ object has three inlets and two outlets. The left-most inlet is used for control-type messages as well as changing the ratio of the sample that is being played. The middle inlet sets the start point of the loop in ms (where 0 is the beginning of the buffer~). The right inlet sets the end point of the loop in ms (where 0 is the beginning of the buffer~) .
Because the groove~ object does not loop by default, the message "loop 1, loopinterp 1" is sent upon opening the patch. This is done by first connecting a loadbang object to the message "loop 1, loopinterp 1" to the left inlet of the groove~ object. "loop 1" tells the groove~ object that it must loop. "interp 1" tells the groove~ object that it must interpolate samples when it repeated the looping section of the audio buffer~.
The three number boxes at the top of the patch control the three remaining parameters. The first box on the left controls the playback ratio of the groove~ object. The middle number box controls the loop starting point in ms. The right number box controls the loop length in ms.
The playback ratio control is connected to the left inlet of the groove~ object via a sig~object. The sig~ object transforms a number (such as what comes out of the number box) to a Max/MSP audio signal (which is what is used to control the ratio). However, we do not hear this audio signal directly - it is used to continuously change the playback ratio of the sample as the number box is changed. A ratio of 1.0 will play the looping sample at its original speed and pitch. A ratio of 0.5 will play the looping sample at half its original speed and an octave lower. A ratio of 2.0 will play the looping sample at twice its original speed and an octave higher. A negative ratio will play the sample in reverse.
Finally, it is a matter of setting the loop start and end times. The start time is simply a number box connected directly to the middle inlet of the groove~ object. The end time is a little more complex. The aim is to set the loop length in ms. However, the right inlet of the groove~ object sets the end point of the loop, not the loop length. In other words, we are dealing with a absolute value (in reference to the buffer~ length in milliseconds) instead of a delta value in comparison to our loop starting point.
The easiest way to work around this problem is to take the loop starting point and simply add a value (in ms) to it and then send the result to the right inlet of the groove~ object. This is why the loop start number box and the loop length number box go to the left and right inlets of a + object. This object performs the addition of both of these numbers.
The nature of the + means that a bang trigger is needed. This is because any changes in value to the left inlet will trigger the calculation, but the changes in the right inlet will not trigger the calculation directly. As a result, changes to the loop start point will update the groove~ start and finish loop points (because the loop start point is connected to the left inlet of the +). However, changes in the loop length will only be updated when the loop starting point has been changed.
The bang re-triggers the addition calculation every time the loop length changes by triggering the left inlet of the + object. Note the right-to-left order; the number from the loop length number box is sent to the right inlet of the + before the calculation is re-triggered. If the bang was to the right of the right inlet of the +, then the calculation would be triggered before the new value for the loop length had been sent.
Please note that in order to hear anything, the DSP Engine must be set to on (in Options > DSP Status > Audio).
Adding LFO Modulation
This simple extension adds the following features to the patch described above.
• LFO Sinewave modulation of the start point of the loop, resulting in a more complex sound and a wider variety of sounds.
• Control over modulation depth (in ms) and speed (in Hz).
The other features are retained.
The patch itself has not changed that much. The main structure from the first version is still almost completely intact. The only change in the original structure of the patch is that a + object has been added in between the loop start point number box and the rest of the patch. The loop start point number box is connected to the right inlet of the new + object.
Connected to the new + object is a sinewave generator (the cycle~ object) whose signal is routed through a signal monitor (which looks similar to a number box) and a scale object. The cycle~ object generates an audio waveform in shape of a sinewave. The frequency of this sinewave in Hz is determined by the number that is sent to its left inlet, which is connected to the mod speed number box.
The output of the sinewave is connected to the signal monitor, which is able to convert a signal into a number which is output to its left outlet. In the case of the sinewave, the numbers are in between -1.0 and 1.0. This stream of numbers is used as a starting point with which to modulation the loop start and end points with.
The numbers from the signal monitor object are sent to the scale object. The scale object takes four main arguments - low input, high input, low output and high output. The object takes a number and scales it as described by the four arguments. For example, if the scale object's four arguments are 0.0 1.0 0.0 10.0 and the value 0.5 was sent to the left inlet, then the scale object would return 5.0, because this value is to 0.0 and 10.0 what 0.5 is to 0.0 and 1.0.
Because we know that our source signal is a sinewave oscillator, we also know that the minimum data range that is generated by the sinewave is -1.0 and the maximum is 1.0. Hence, the first two arguments (the low input and the high input). The high output value is set by the mod depth number box as it is connected to the second-most-right inlet of the scale object.
This stream of numbers, as determined by the speed of the sinewave and the high output value of the scale object is then simply added to the user-determined starting point. This is how the modulation signal is integrated into the original structure of the patch.