Tag Archives: transport
Bass drum player with swing
Image
This patch uses the transport object to control an algorithmic performer of kick drum patterns. When the transport is turned on, the metro also turns on because its active attribute is set on. The metro sends a bang on every 16th note. Those bangs are first used to trigger information from the transport itself, and then to look up in a table of patterns to see whether or not to play a bass drum note. Along the way, the bangs from the metro pass through a subpatch that applies a certain amount of delay–equal to some proportion of a 16th note–to every other 16th note, giving a variable amount of “swing” feel to the drum patterns.
For each bang of the metro, we get information from the transport: the bar number, the beat number, and the number of units (ticks) within the beat. On the right part of the patch, you can see that we use the change object to filter out repetitions of bar number, so we will only pass on the bar number when it changes, which is to say, on the downbeat of each bar. We use that downbeat indicator to choose a random number from 0 to 7, and multiply that by 16 so that we get the numbers 0, 16, 32, … 112. That result gets stored in a +object. We’ll see what it’s used for in just a minute.
For now, let’s ignore the patcher swinger object. We’ll come back to that. Let’s imagine that the bang from the metro is just going directly to the patcher which16th. The metro sends a bang on every 16th note, and the patcher which16th subpatch will tell us which 16th note of the measure is occurring, using numbers 0 to 15. (Side note: you could also use a counter 0 15 object to generate that information, but if the transport time were to be changed in some other patch, the counter could get out of sync with the downbeat, and would be providing incorrect information.) Double-click on the patcher which16th object to see its contents. Since there are 480 divisions per quarter note by default, and the metro is quantized to occur only on 16th notes, the units coming in the right inlet will always be 0, 120, 240 or 360. So we divide by 120 to get which 16th note of the beat it is — 0, 1, 2, or 3. The beats coming in the middle inlet are numbered 1 to 4, so we subtract 1 and multiply by 4 to convert that to a number of 16th notes, add it to the 16th note offset from the units, and store the result in the right inlet of an i object. That’s the 16th note index within the measure, numbered from 0 to 15. Then, when the bang from the metro comes in an instant later, it will send out the correct 16th note index.
We use that 16th note index to look up information in the table object. But before it gets to the table, it passes through the + object where we previously — on the downbeat of each measure — stored some offset 0, 16, 32, …112. That means that for each measure, we will be looking up some different range of sixteen values in the table: 0-15, 16-31, 32-47, etc. up to 112-127. Double-click on the table object to see its contents. It stores 128 values ranging from 0 to 3. A table of 0s and 1s is useful for storing patterns of on/off information; in this case I decided to use numbers 0 to 3 so that the table could store four gradations: off, soft, medium, and hard. Every group of 16 values in the table is a unique composed rhythmic pattern of notes suitable as a kick drum rhythm in 4/4 time. Using the information derived from the transport, we read through a group of 16 articulation values to get one of 8 possible rhythmic patterns. The output of the table will always be numbers 0 to 3, which we use to trigger velocity values: 80, 104, 127, or no action (for 0). Those velocity values are passed to a noteout object that’s set to transmit on MIDI channel 10 — the channel designated for drums in the General MIDI specification — and then a pitch value of 36 — designated to mean kick drum in the GM specs — is sent to noteout to trigger the note.
Now let’s take a look at the patcher swinger subpatch. As you know, in various styles of jazz and popular music, 16th notes are played unevenly, with the duration of the first of each pair of 16ths being slightly longer than the second. You might just as well say that the onset time of the second of each pair of 16th notes is delayed slightly. This practice is known as “swing”. Scientific musicologists who have studied the performance of music that involves swing have found that the amount of swing varies from one style of music to another, and is also dependent on the tempo of the music. So, rather than try to quantify swing as some particular rhythmic unit, such as a triplet 8th note, it may make more sense in computer music to quantify swing as some percentage of a beat, or of a half beat. That’s how we do it in this patch. If you figure that normally an unswung 16th note is 50% of an 8th note (120 ticks for a 16th, and 240 for an 8th), then a swung 16th note might range from 50% (no swing) to 75% (extreme swing equal to a dotted 16th note) of an 8th note. So to specify how much swing we want, I provide the user with a live.dial object that has a range from 50 to 75 and its units displayed with a % sign. Regardless of the range of the live.dial or how its units are displayed, however, its right outlet will always send a float value from 0 to 1 based on the dial position. Now double-click on the patcher swinger object to see its contents.
Inside the patcher swinger subpatch, the 0-to-1 value from the live.dial gets multiplied by 60 to produce some number from 0 to 60. The “ticks” value from the transport, which will always be 0, 120, 240, or 360 in this case, gets divided by 120 to convert those numbers to 0, 1, 2, or 3. We then use a bitwise operator & 1 to look just at the least significant bit of that number (the 1s place of its binary representation) to see if the number is odd or not. If the number is odd, the & 1 object will send out a 1; if not, it will send out a 0. That gets multiplied by the number from 0 to 60 we got from the right inlet, gets packed together with the word “ticks”, and is stored in the right inlet of the delay object as a tempo-relative time value. It’s the number of ticks we want to delay each 16th note: 0 delay for even numbered 16ths and some amount of delay for the odd numbered 16ths. (Remember, we’re indexing the 16th notes of the measure starting from 0.) 0 ticks is no delay, and 60 ticks is a 32nd note’s worth of delay. So each bang that comes in the left inlet gets delayed by some amount, depending on whether it’s the first or second of a pair of 16ths, and based on the amount (percentage) of swing specified in the main patch.
I worked with only the kick drum in this example, so that the patch would not become too complicated, but one could duplicate this procedure for all of the other instruments of the drum kit, with unique patterns appropriate to each instrument, to get a full constantly-varying automated drum performance.
Note that this patch requires virtually no modification to work as a MIDI plug-in in Ableton Live. One can copy and paste this patch into Max for Live, add the “Swing” live.dial to the Presentation, move it to the visible area of the Presentation (the upper left corner), and set the patcher to “Open in Presentation” in the Patcher Inspector. The control messages to the transport object would become superfluous because the Live transport would be in charge, but the bang messages to the transport object from the metro will still report the correct time so that the patch will work as it should. The swing function will have the same effect, and will be independent of any “Groove” setting the Live track might have.
Convert between musical time and clock time
Image
The translate object performs conversions from one kind of time unit to any other, and is particularly useful when you need to convert from a tempo-relative time unit to a clock time unit (e.g., convert note values to milliseconds) or vice versa. In this example, try changing the bpm tempo of the transport, and you’ll see that the translate object sends out updated information whenever the tempo changes.
Rhythmic delays in time with a musical tempo
Image
The tempo-relative timing capabilities in Max can be used to synchronize MSP processing in time with a musical beat. In this example, timings of delays are specified in tempo-relative time units so that they remain rhythmically correct for any tempo.
Click on the button above the click~ and you will hear a click followed by four rhythmically delayed versions of the click (with diminishing amplitudes). The timings of the delays have been set to a dotted eighth note, a dotted quarter note, a double-dotted quarter note, and a half-note-plus-a-sixteenth. The tapout~ object does not interpret tempo-relative time syntax on its own, so we use the translate object to convert time musical units such as 8nd or bars.beats.units such as 0.1.360 into milliseconds.
Now try changing the tempo of the transport to some other tempo such as 96 bpm, and then trigger the click again. Notice how the rate of the rhythm has changed commensurate with the change in the global tempo. Finally, start the transport, which will also start the metro, which will begin playing a different sound every quarter note. Since the delays are all set to happen on sixteenth note pulses somewhere between the quarter notes, you will hear a composite rhythm that is more complex than is actually being played by the metro. If you change the tempo, the delays will stay in the same rhythmic relationship to the quarter-note beat.
Transport-controlled phasor~
Image
A phasor~ object, like other MSP objects such as cycle~ that use a rate for their timing, can have its repetition rate specified as a transport-related tempo-relative time value (note values, ticks, etc.). So if you want a phasor~ to work at a rate that is related to the transport’s tempo, you can type in a tempo-relative time as an argument to specify its period of repetition instead of typing in a frequency. The existence of that time syntax argument will tell the object to use the transport’s tempo as its basis of timing. MSP objects that are using transport-based timing will work — and will respond to changes in the transport’s tempo — even when the transport is not turned on. By setting the object’s ‘lock’ attribute to 1, you can cause the object to sync precisely to the quantized note value of the moving transport. When the lock attribute is on, the object will only work when the transport is on.
In this example we have a phasor~ with a typed-in argument of 16n and a lock attribute setting of 1. This means that it will only move forward when the transport is running, and its period of repetition will be synchronized with the 16th notes of the transport.
Read some sound into the buffer~. This will cause the length of the sound file to go to the right inlet of the *~ object. The noise~ object generates random sample values in the range -1 to 1. We use the sample-and-hold trick that was explained in Example 25 to get individual random numbers at a time that’s perfectly synchronized with the start of each phasor~ cycle, we take the absolute value of that (to force the number to be positive) scale it to be a useful time value within the buffer~, and use that as a starting point for play~ each time the phasor~ starts a new ramp. By translating the 16th-note note value into milliseconds, we can scale the phasor~ ramp to traverse one 16th note’s worth of time in the play~ object, offset by the starting point we got from sah~. The same phasor~ is used to make a trapezoidal amplitude envelope for each 16-note chunk of audio we play. The result is randomly-chosen 16th-note soundbites played continuously and in synchrony with the transport (and click-free) from the buffer~.
Tempo-relative timing with the transport object
Image
This patch doesn’t do anything musical in its own right, but it shows some features of the transport object for tempo-relative control of timing in Max. For several other examples online of how to implement tempo-relative timing in Max, see Examples 42 through 48 from the 2010 IAP class.
The transport object controls a global beat-based clock running at a specific metronomic tempo expressed in beats per minute (bpm). Other timing objects such as metro, delay, pipe, makenote, etc. can be synchronized to the global clock by specifying their timing interval in some tempo-relative format such as note values, ticks (parts per quarter note, usually 1/480 of a quarter note by default), or bars.beats.ticks.
At the top of this patch is a transport object for turning the global clock on and off. You can think of it like the tape-recorder-like controller that appears in most music sequencing software such as Pro Tools, Logic, Garage Band, Cubase, etc. You can set the global bpm tempo via the transport object’s ‘tempo’ attribute, either with a typed-in attribute argument or by sending it a ‘tempo’ message. You can cause it to jump to a particular location in time by sending a point in time, expressed in ticks, in the right inlet. (So, for example, ‘0’ causes it to rewind to the beginning of time.) Whenever it’s running, other timing objects that have their timing units expressed in one of the tempo-relative timing formats will be controlled by the transport. So, when the transport is not running, those objects will be frozen in time.
The metro object just above that transport is there solely to bang the transport at regular intervals of time, causing the transport to send out a report of its current time status (meter, tempo, current location, etc.). Notice two important typed-in attributes in the metro. One is the ‘active’ attribute, which is set to ‘on’ (1), meaning that the metro will be active (on) whenever the transport is on. The other is ‘quantize’ meaning that the metro will snap all of its bangs to the nearest 16th note (or whatever time unit is specified) of the transport’s beat-based clock. The ‘quantize’ attribute is useful for making sure that events occur right on a particular time unit such as on the beat, on the downbeat, etc.
The timepoint object schedules a bang to occur at a specific moment in time. (You can send it a new time if you want to schedule a different event, but each timepoint object can hold only one scheduled bang at a time.) You can use those bangs to cause particular things to occur, turn other processes on or off, etc. In this example, timepoint schedules a bang to occur on the downbeat of measure 9 of the global clock. At that moment it turns on a toggle, which in turn does three things. It resets the time of another (named) transport object, it turns on that other transport, and it turns on a metro that’s associated with that transport.
If you give a transport object a name (by setting its ‘name’ attribute to some word), that transport will be completely independent of the global transport, and can have its own meter and tempo, can be started and stopped independently, and can thus be at different place in “time”. (In short, the ability to name transports means that there can be two or more independent time universes.) In this example we named the transport ‘slowtempo’ and we assigned it a slow tempo of 48 bpm.
As shown, time intervals can be expressed as rhythmic values (or dotted values, or triplet values) or ticks (useful for less usual rhythmic values like quintuplets) or bars.beats.ticks (in this example we use ‘0.0.120’ just to show that it’s one possible way to express a 16th note; it’s equivalent to ‘120 ticks’ or ’16n’).
At the bottom of the patch we show the use of the timer object. It measures the time between a bang received in its left inlet and a bang received in its right inlet, so it’s the best object for measuring the elapsed time between any two events (i.e., between any two Max messages). You can use timer to measure absolute time in ms even without the use of the transport. But you can also ask it to send out its time measurement as a tempo-relative time, by specifying a time format for its right outlet. In this example we use two timer objects, one associated with the global transport and the other associated with the ‘slowtempo’ transport, to measure the time between bangs from the ‘slowtempo’ metro. Notice that they both give the same millisecond measurement out their left outlets, but they give a different number of ticks, one based on the beat rate (tempo) of the global transport and the other based on the ‘slowtempo’ beat rate of 48 bpm.