Linear audio crossfade

Image

This example uses the subpatch from the previous example, so it requires that you download the file mix~.maxpat and save the file, with that same name, somewhere in the Max file search path.

This example demonstrates the use of the line~ object to make a linear control signal, which is used to control the balance between two audio signals. (A “control signal” is a signal that’s not intended to be heard directly, but which will affect some aspect of another signal, or perhaps will control some global parameter of several sounds.) The line~object receives a destination value and a ramp time, and it then interpolates, sample-by-sample, from whatever its current value is, to ramp to the specified destination value in exactly the desired amount of time.

The mix~ object expects a control signal from 0 to 1 in its right inlet to specify the desired balance between the two audio signals in its left and middle inlets. When the control signal is 0, we hear only the first input sound; when the control signal is 1, we hear only the second input sound. Inside mix~, the two sounds are scaled appropriately according to the balance value in the right inlet, added together, and sent out the outlet. So to do a smooth linear crossfade between sound 1 and sound 2, it makes sense to send a linear control signal from 0 to 1 into the right inlet.

The two cycle~ objects provide constant full-amplitude tones (the pitches A and B), so they’re good sound sources to allow us to hear the effect of the crossfade clearly. The toggle is used to initiate a crossfade from one sound to the other; it provides a 1 or a 0 as the destination value for the balance. First we need to supply a ramp time, in milliseconds, in the right inlet of the pack object. When the destination value comes from the toggle, it gets packed together with the ramp time as a two-item list, and passed to the left inlet of line~. Over the course of that specified time, line~ calculates the intermediate value for each sample that’s needed in order to describe a straight linear progression toward the destination value.

The line~ object is thus a control signal generator, and importantly, it’s an object that provides an interface between the Max scheduler (the normal world of Max in which individual messages occur at a specific instant in time) and the MSP signal chain (in which a continuous stream of audio samples are being calculated). A single message to line~ triggers a change in its output signal, a change which could take place over any desired amount of time. You can also think of line~ as a “smoother”, allowing a signal parameter (such as amplitude, frequency, etc.) to change smoothly from one value to another.

A useful subpatch for mixing and balancing two sounds

Image

To mix two sounds together equally, you just add them together. If you know that both sounds will frequently be at or near full amplitude (peak amplitude at or near 1) then you probably want to multiply each sound by 0.5 after you add them together, to avoid clipping. However, if you want to mix two sounds unequally, with one sound having a higher gain than the other, a good way to accomplish that is to give one sound a gain between 0 and 1 and give the other sound a gain that’s equal to 1 minus that amount. Thus, the sum of the two gain factors will always be 1, so the sum of the sounds will not clip. When sound A has a gain of 1, sound B will have a gain of 0, and vice versa. As one gain goes from 0 to 1, the gain of the other sound will go from 1 to 0, so you can use this method to create a smooth crossfade between two sounds.

This example employs that mixing technique and implements it as a patch that can be used as an object inside another patch. It’s handy for easily mixing and/or adjusting the balance of two audio signals. Save the patch as a file with a distinct and memorable name such as “mix~.maxpat” somewhere in the Max file search path. Then you can use it as a subpatch (also often called an “abstraction”) in any other patch just by making an object named “mix~”. The audio signals go into the left and middle inlets and the mix value from 0 to 1 goes into the right inlet. There are three ways to specify the balance: 1) as an argument typed into the object box, 2) as a float in the right inlet, or 3) as a signal in the right inlet. Using a signal to control mixing is the best choice if you intend to change the mix dynamically.

Whatever goes in the inlets of the mix~ object in the main patch comes out the corresponding inlet objects in the mix~ subpatch, and the mixed signal comes out the outlet. The sig~ object provides a constant signal in which every sample has the same value, in this case a constant value of 1. The argument #1 will be replaced by whatever is typed into the mix~ object box as an argument in the parent patch; if nothing is typed in, it will be 0, and if a signal is attached in the main patch then the signal value will be used. This allows the user to type in an argument to specify the initial balance value in one of the *~ objects, and the -~ object provides 1 minus that value to the other *~ object. That initial balance value can be replaced by sending in a float or a signal.