In this chapter we demonstrate a design for playing pre-recorded samples from a MIDI keyboard. This design implements some of the main features of a basic sampler keyboard: assigning samples to regions of the keyboard, specifying a base (untransposed) key location for each sample, playing samples back with the proper transposition depending on which key is played, and making polyphonic voice assignments. For the sake of simplicity, this patch does not implement control from the pitchbend wheel or mod wheel, but the method for doing so would not be much different from that demonstrated in the previous two chapters.
In this patch we use the groove~
object to play samples back at various speeds, in some cases using looped samples. As was noted in Tutorial 19
, if we want a polyphonic instrument we need as many sound-generating objects as we want separate simultaneous notes. In this tutorial patch, we use four copies of a subpatch called to supply four-voice polyphony. As in Tutorial 19
— we use a poly
object to assign a voice number to each MIDI note, and we use route
to send the note information to the correct subpatch.
poly assigns a voice number to each MIDI note, to send information to the correct subpatch
Before we examine the workings of the
subpatch, it will help to review what information is needed to play a sample correctly.
• 1. The sound samples must be read into memory (in buffer~
objects), and a list of the memory locations (buffer~
names) must be kept.
• 2. Each sample must be assigned to a region of the keyboard, and a list of the key assignments must be kept.
• 3. A list of the base key for each region -- the key at which the sample should play back untransposed -- must be kept.
• 4. A list of the loop points for each sample (and whether looping should be on or off) must be kept.
• 5. When a MIDI note message is received, and is routed to a groove~
object in that subpatch must first be told which buffer~
to read (based on the key region being played), how fast to play the sample (based on the ratio between the frequency being played and the base key frequency for that region), what loop points to use for that sample, whether looping is on or off, and what amplitude scaling factor to use based on the note- on velocity.
In this patch, the samples are all read into memory when the patch is first loaded.
• Double-click on the p
subpatch to open its Patcher window.
You can see that six samples have been loaded into buffer~
objects named , , etc. If, in a performance situation, you need to have access to more samples than you can store at once in RAM, you can use messages with filename arguments to load new samples into buffer~
objects as needed.
• Close the subpatch window. Click on the message
box marked ‘keyboard sample assignments’.
This stores a set of numbered key regions in the funbuff
object. (This information could have been embedded in the funbuff
and saved with the patch, but we left it in the message
box here so that you can see the contents of the funbuff
.) MIDI key numbers 0 to 40 are key region 1, keys 41 to 47 are key region 2, etc. When a note-on message is received, the key number goes into funbuff
, and funbuff
reports the key region number for that key. The key region number is used to look up other vital information in the coll
Note-on key number finds region number in funbuff, which looks up sample info in coll
• Double-click on the coll
object to see its contents.
coll contains sample information for each key region
The key region number is used to index the information in coll
. For example, whenever a key from 48 to 52 is pressed, funbuff
sends out the number , and the information for key region 3 is recalled and sent to the appropriate subpatch. The data for each key region is: base key, buffer~
name, loop start time, loop end time, and loop on/off flag.
The voice number from poly
opens the correct outlet of gate
so that the information from coll
goes to the right subpatch.
• Close the coll
window, and double-click on one of the subpatch objects to open its Patcher window.
The samplervoice~ subpatch
You can see that the information from coll
is unpacked in the subpatch and is sent to the proper places to prepare the groove~
object for the note that is about to be played. This tells groove~
to read, what loop times to use, and whether looping should be on or off. Then, when the note information comes in the left inlet, the velocity is used to send an amplitude value to the *~
object, and the note-on key number is used (along with the base key number received from the right inlet) to calculate the proper playback speed for groove~
and to trigger groove~
to begin playback from time .
• Close the subpatch window.
You're almost ready to begin playing samples, but there is one more detail to attend to first. To save storage space, the samples used in this patch are mono AIFF files with a sample rate of 22,050 Hz. To hear them play properly you should set the sample rate of MSP to that rate.
• Double-click on the dac~
object to open the DSP Status window. Set the Sampling Rate to , then close the DSP Status window.
• Note: Resetting the sampling rate may not be possible, depending on your hardware.
The difference between the sample rate of an audio file and the sample rate being used in MSP is a potential problem when playing samples. This method of resolving the difference suffices in this situation because the audio files are all at the same sample rate and because these samples are the only sounds we will be playing in MSP. In other situations, however, you're likely to want to play samples (perhaps with different sampling rates) combined with other sounds in MSP, and you'll want to use the optimum sampling rate.
For such situations, you would be best advised to use the ratio between the audio file sample rate and the MSP sample rate as an additional factor in determining the correct playback speed for groove~
. For example, if the sample rate of the audio file is half the sample rate being used by MSP, then groove~
should play the sample half as fast.
You can use the objects info~
to find out the sampling rate of the sample and of MSP respectively, as demonstrated in the following example.
Calculate playback speed based on the sampling rates of the audio file and of MSP
The note-on key number is used first to recall the information for the sample to be played. The name of a buffer~
is sent to groove~
. Next, a is sent to dspstate~
. Upon receiving a , dspstate~
reports the sampling rate of MSP and info~
reports the sampling rate of the AIFF file stored in the buffer~
. In the lower left part of the example, you can see how this sampling rate information is used as a factor in determining the correct playback speed for groove~
• Turn audio on and set the ‘Output Level’ number box
to a comfortable listening level. Play a slow chromatic scale on the MIDI keyboard to hear the different samples and their arrangement on the keyboard.
To arrange a unified single instrument sound across the whole keyboard, each key region should contain a sample of a note from the same source. In this case, though, the samples are arranged on the keyboard in such a way as to make available a full ‘band’ consisting of drums, bass, and keyboard. This sort of multi-timbral keyboard layout is useful for simple keyboard splits (such as bass in the left hand and piano in the right hand) or, as in this case, for accessing several different sounds on a single MIDI channel with a sequencer.
• For an example of how a multi-timbral sample layout can be used by a sequencer, click on the toggle
marked ‘Play Sequence’. Click on it again when you want to stop the sequence. Turn audio off. Double-click on the p
object to open the Patcher window of the subpatch.
The p sequence subpatch
object contains a pre-recorded MIDI file. The midiparse
object sends the MIDI key number and velocity to poly
in the main patch. Each time the sequence finishes playing, a is sent out the right outlet of seq
; the is used to restart the seq
immediately, to play the sequence as a continuous loop. When the sequence is stopped by the user, a is sent to midiflush
to turn off any notes currently being played.
• When you have finished with this patch, don't forget to open the DSP Status window and restore the Sampling Rate to its original setting.
To play samples from the MIDI keyboard, load each sample into a buffer~
and play the samples with groove~
. For polyphonic sample playback, you will need one groove~
object per voice of polyphony. You can route MIDI notes to different groove~
objects using voice assignments from the poly
To assign each sample to a region of the MIDI keyboard, you will need to keep a list of key regions, and for each key region you will need to keep information about which buffer~
to use, what transposition to use, what loop points to use, etc. A funbuff
object is good for storing keyboard region assignments. The various items of information about each sample can be best stored together as lists in a coll
, indexed by the key region number. When a note is played, the key region is looked up in the funbuff
, and that number is used to look up the sample information in coll
The proper transposition for each note can be calculated by dividing the played frequency (obtained with the mtof
object) by the base frequency of the sample. The result is used as the playback speed for groove~
. If the sampling rate of the recorded samples differs from the sampling rate being used in MSP, that fact must be accounted for when playing the samples with groove~
. Dividing the audio file sampling rate by the MSP sampling rate provides the correct factor by which to multiply the playback speed of groove~
. The sampling rate of MSP can be obtained with the dspstate~
object. The sampling rate of the AIFF file in a buffer~
can be obtained with info~
(Remember -- resetting the sampling rate may not be possible on your hardware).
Note-on velocity can be used to control the amplitude of the samples. An exponential mapping of velocity to amplitude is usually best. Multi-timbral sample layouts on the keyboard can be useful for playing many different sounds, especially from a sequencer. The end-of-file seq
can be used to restart the seq
to play it in a continuous loop. If the MIDI data goes through a midiflush
object, any notes that are on when the seq
is stopped can be turned off by sending a to midiflush
from the right outlet of
Store audio samples
Report current DSP settings
Variable-rate looping sample playback
Polyphony/DSP manager for patchers