Before we can sequence any samples, we need to know how to make Max play them. There are a few different ways to play audio files in Max. One option is sfplay~, which reads and plays audio files directly from disk. This is useful to minimize RAM usage when playing long audio files, but it adds some overhead every time we play a file. Samples for a sequencer tend to be relatively short and need to be played over and over (potentially with the same file's audio overlapping itself), so it makes sense to load them into RAM and play them from memory. play~ and groove~ are the standard options for playing audio from audio buffers in memory. For this project I'll be using play~.
buffer~ controls loading a file into memory and names the audio buffer so it can be used by other objects like play~. We create a buffer with the name stepler-buffer by providing the name as an argument: buffer~ stepler-buffer. Then we can create a play~ object to use that buffer by providing it with the same name: play~ stepler-buffer
loading an audio file into a buffer~ for use with play~
We can then load an audio file by sending the message buffer~. This will open a dialog window to select a file. If you need an audio file, look under examples/sounds in your Max installation. I loaded drumLoop.aifto the
Another way to load audio files is to open the File Browser window (under the menu: buffer~. Very convenient!). Then you can search for any audio file on Max's search path, and drag and drop it onto the
sending the output of play~ to your speakers via gain~ and ezdac~
To hear anything we need to connect play~ to Max's audio output. ezdac~ provides audio output and a UI for turning the audio on and off. We can control the volume by putting a gain~ before the output.
To keep things simple, I'm going to assume all our audio samples are monophonic (single channel). So we'll send the output of gain~ to both the left and right channels of ezdac~ in order to get stereo output.
Now if we tell play~ to play our buffer and we should be able to hear it. Typically, a line~ is used to play the buffer by sending a message to line~. start is the starting position of the buffer, end is the ending position of the buffer, and duration is the amount of time it takes to get from start to end. All values are in ms (milliseconds).
In the patch stepler-1a, we'll send the message which will play the first 1000 ms (1 second) of audio in the buffer.
As noted in the patch's comments, before we can hear anything we need to:
The order doesn't actually matter. Once those steps steps are done, each time you click on the button or message above line~, you should hear the first second of audio from the file you loaded. If you don't hear anything, make sure the audio file isn't silence for the 1000 ms, double check your audio settings are correct at under the menu, and make sure your speakers are turned on.
One problem with the stepler-1a patch is we need to specify the end position for our buffer. It would be a major pain to check the length of every audio file we load. Let's fix the patch so it will always play the entire audio file.
determining a buffer's length with info~ and storing it in pv for easy access
info~ can tell us lots of useful information about an audio buffer. Like play~, it needs to know the buffer name: info~ stepler-buffer. When we bang info~, the 7th outlet reports the total length of the buffer in ms (the ending position of the buffer). Conveniently, buffer~ sends a bang out its 2nd outlet whenever it loads a file, so by connecting this to info~ we'll get the buffer length whenever the audio file changes.
Let's store the buffer length somewhere so we can easily get the value whenever we need it. The pv object is one way to do this. Send the output of info~ to an object pv buffer-length. This stores the value in a variable named buffer-length. Then we can create additional pv buffer-length objects anywhere in this patch or its subpatches and bang those objects to get the buffer length.
So now that we know the buffer length, how do we adjust our line~ message? Remember the format is . We want to start at 0 and end at the buffer-length. For now we'll play the audio file at normal speed, so the duration should also be the buffer-length (normal speed means to play X ms worth of samples in X ms). With the message the special $1 symbol will be replaced by whatever value we send to the message object. In this case, we'll send the value stored in pv buffer-length.
Now the patch will always play the audio file in its entirety.
This patch doesn't do much yet, but it laid the foundation for this project. The next tutorial covers using poly~ to play multiple audio files at the same time by running multiple copies of this patch.