In the early 1980s, I had the pleasure of conceiving and designing a true classic, the Lexicon PCM42 digital delay. At that time, I was interested in using looping delays that could be beat-synchronized with drum machines and arpeggiators, and I incorporated some of my ideas into the '42. With the resources of Lexicon, I was also able to build a great-sounding delay for general use. The original '42 became nearly a studio standard; a used PCM42 fetches a higher price today than it did when it was new.
I've always taken pride in having created the PCM42. I felt, and still feel, that there's a special richness and immediacy in creating music with long delay loops with feedback, and I'm pleased to claim my little bit of history in this area.
Recently, I've been thinking about what I would do if I were to redesign the PCM42. Among the things the PCM42 would need most is the ability to dial in delay times as beats per minute and note values. There would be other changes, as well:
- My updated PCM42 would be entirely software, built with a “construction kit” such as Cycling '74's Max/MSP.
- It would be a live-performance environment, with analog inputs and outputs.
- Delay loops would be beat-synchronized, with options for master or slave operation.
- It would be semimodular, with multiple units that could be connected in series or in parallel in any combination.
- The device would offer multispeaker surround outputs as an option.
I found that I can do all of this within the Max/MSP environment, and I'm pleased with the musical results I'm getting. In this article, I'll give you a full working multichannel real-time looping device with sophisticated features, and I'll show you exactly how to build it. You can build the system from scratch or just download the completed program from the EM Web site for instant fun.
THE MAX/MSP ENVIRONMENT
Max/MSP, published by Cycling '74, is a visual programming language for both music and audio. Originally developed by Miller Puckette, Max has been available since 1991. Max offers something that I've never found elsewhere: a complete software “construction set” of basic I/O, control, and processing routines that can be connected to create any function imaginable. It is truly the visual programming language of MIDI.
A couple of years ago, Max took a huge step forward with the introduction of MSP (Max Signal Processing). An integral part of the Max 4.0 package, MSP extends the concept of Max into native audio processing, a tremendously exciting development that makes it possible to create arbitrarily complex effects processors and signal generators at will.
One of the nice things that Max has always offered is its free run-time engine. With it, any Max program (called a Patcher) can be loaded and run by anyone. Controls in the user interface are fully active, but no changes can be made to the Patcher itself. Thanks to this policy, Max/MSP developers can distribute their work freely.
HARDWARE AND SOFTWARE
Max/MSP runs exclusively on the Macintosh, although a PC version is under development. OS 8.6 or higher is required (I run OS 9.1), but OS X is not yet supported.
The device we'll build is a real-time audio processor designed to work with live audio inputs, so a stereo or (preferably) multichannel audio interface is needed. Max/MSP supports ASIO and Apple Sound Manager drivers. I've used the program successfully with an Emagic EMI 2/6 and a Mark of the Unicorn 828.
Because it is based on long delay loops, the Patcher we're going to create is memory hungry. It doesn't require much for essential operation, but the more delays you use and the longer they are, the more memory you will need. As a benchmark, if you run at a 44.1 kHz sampling rate, eight seconds of delay memory (equivalent to four bars at 120 bpm) consumes about 5.6 MB.
To run the Patcher, you need some form of Max/MSP. Readers who already own Max/MSP can jump right in, of course, but if you don't yet have the program, you can download the free Max run-time engine or the complete Max package from Cycling '74's Web site (www.cycling74.com).
Running the virtual delay unit is fun and (I hope) musical, but what I really want to do in this article is show you how to modify and customize the program to meet your own needs, as well as to create your own processing and synthesis programs from scratch. This is the excitement of Max/MSP, and you should definitely give it a try.
Luckily, Cycling '74 allows you to download the complete program for a free 30-day trial. That's easily enough time for you to work through this example and some of the excellent tutorial material that is included with the download. Within your 30 days, you can do anything you want; after that the program will refuse to operate until you get an authorization code from the manufacturer. It's a good and fair system. I offer one caution, though. If you're running the trial version, do not try to change your system date and time. That will cause the program to immediately time out.
The Max/MSP Patchers shown in this article are available for download as a single archive from the EM Web site. To help in coordination, Patchers are identified according to the figure in which they appear. To get the most from this article, get Max/MSP (demo or full version) and build these Patchers yourself in addition to studying the downloadable versions. If you like, however, you can also download the Max/MSP run-time environment and use any or all of these Patchers as they are.
FIG. 1: Max/MSP''s Audio Through Patcher accepts a stereo signal from the audio interface and passes it directly to the audio output. To understand Max and the operation of these example Patchers, pay special attention to the comments.
MAX/MSP AUDIO PROGRAMMING
In an article such as this, there's no way to describe the complete ins and outs of programming with Max and MSP. For that, the best source is the excellent documentation, tutorials, and Help system that come with the package (also see the review of Max 4.0/MSP 2.0 in the April 2002 issue). But let's take a look at the basic principles of operation.
In Max, low-level functional blocks, which are called Objects, are connected together in Patchers. Fig. 1 shows a simple Patcher that passes stereo audio from input to output. Notice the descriptive text that appears alongside the Patcher itself. Comments such as those can be instructive to someone attempting to use your Patchers or to you to remind you how a Patcher works. You can download and run this Patcher, but the best way to learn is to build it from scratch in Max/MSP.
There are three kinds of Objects used here. The “adc~” Object gets input from the audio interface, “stereo by default.” Audio data is transferred from the outputs of adc~ to the inputs of the “dac~” Object by virtual patch cords. The dac~ Object outputs stereo audio to the audio interface.
The remaining Object in this Patcher is a message box that contains the word start. A start message is required to initiate processing of audio. To make the Patcher operate, click on the start message. A separate stop message can be used to halt processing.
There's an important distinction in Max/MSP between Objects that handle audio data and those that deal with control and MIDI information. Max Objects for control and MIDI process data only when stimulated by the user interface or incoming messages. MSP audio Objects, on the other hand, process audio data continuously.
FIG. 2: The Through with Gain Control Patcher adds stereo gain control to the simple Audio Through. The initial gain is 0.5, but the gain can be controlled by click dragging on the number box.
MSP audio-processing Objects are distinguished by a tilde (“~”) sign after their names. In many cases, Objects of the same name are available in control and audio form. For example, the Object “*” will multiply two numbers, whereas the Object “*~” multiplies numbers in a continuous stream of audio data for gain control and modulation, as shown in Fig. 2.
Note that Max supports the Apple Sound Manager and ASIO drivers. To use your ASIO interface, put the driver into the ASIO Drivers folder in the Max application folder. Then, open the DSP Status window by double-clicking on an adc~ or dac~ Object in any Patcher (or by selecting DSP Status in the Options menu) and make the appropriate selections for your interface.
FIG. 3: When a Max/MSP Patcher is unlocked, the Object toolbar appears at the top of the window. Although there are a large number of different Max/MSP Objects available, the seven leftmost items in the toolbar are the ones that are essential to nearly any project.
To build and modify Patchers in Max, you unlock the Patcher window by clicking on the lock icon next to the Close box. If you're running the Patchers with the free Max run-time application, that icon doesn't appear. Try creating a new, empty Patcher. With the Patcher window unlocked, you will find that it is easy to get started by dragging Objects from the upper toolbar and then connecting their outlets (which are found along the bottom of each Object) to the inlets of other Objects. When you drag from the Object tool, which is leftmost in the toolbar, into the main Patcher window, a handy index of the available Objects pops up, and it is sorted into functional groups (see Fig. 3).
FIG. 4: The Help window for any Max or MSP Object is a completely commentated working Patcher that illustrates the full function and options for that Object.
Max/MSP uses a Help system that I really like. When a Patcher window is unlocked, you can pick any Object and then go to the Help menu and get a Help screen specific to that Object. The Object Help window is itself an active Max Patcher that illustrates the full function and options for that Object, complete with comments. You can run the Help Patcher Object as is, or you can unlock it and modify it to see how the Object behaves. Fig. 4 shows the Max Help window for the adc~ Object.
BASIC AUDIO DELAY
Now we can have some fun. In Max/MSP an audio delay line requires two separate Objects, which are “tapin~” and “tapout~.” Tapin~ creates the delay unit and uses a numeric argument that defines the maximum delay in milliseconds. You then connect the output of the tapin~ to tapout~'s input. Tapout~ has a numeric argument that defines the actual audio delay; that can be changed by sending a number to the Object's input.
FIG. 5: This Patcher is a simple audio delay line with variable delay time. Left and right audio inputs are mixed together, delayed, and then distributed to both audio outputs.
In the Patcher shown in Fig. 5, the left and right audio inputs are connected to the input of tapin~. In Max/MSP, audio sources connected to the same input are summed together at unity gain, which makes audio mixing easy.
FIG. 6: This version of the delay line adds controls for feedback gain as well as level controls for direct and delayed audio. The decimal points in the arguments for the audio multiply (*~) Objects and in the number boxes that set the gains are necessary to make those Objects work in fractional values, in this case zero to unity gain.
If you run the Basic Audio Delay Patcher, you'll find that it does in fact delay audio. However, audio delay is not much fun unless you have a way to mix it with the direct signal and to feed the delayed signal back to the input with some attenuation. Fig. 6 shows an audio delay that provides those functions.
At this point, a couple of notes about numbers in Max/MSP are in order. There are two kinds of numbers available: integer numbers (0, 1, 2, and so on) and floating-point numbers (floats) that can have noninteger values (0.5, for example). By default, Max uses integers. Audio gains, though, are usually fractional (in a range of 0 to 1.0, typically), so it's important to use Object types that are compatible.
Arithmetic Objects such as the *~ Object are made compatible with floating-point numbers by entering an initial argument with a decimal point. Similarly, number boxes such as those we're using to vary the gain values come in two types. These are represented separately in Max's toolbar and are denoted by a decimal point in the floating-point number box.
FIG. 7: The Number Inspector (select the number box and hit Command + I on keyboard) defines important properties of the integer or floating point number box, including the number range. Defining the range of each box appropriately will help to make your audio patches behave as you intended.
It's also important to limit audio gains to appropriate values, usually unity. To limit the range of values in a number box, unlock the Patcher, select the number box in question, and hit Command + I on the Mac keyboard. This opens a dialog that controls the numeric range, as well as other properties of the number box (see Fig. 7).
By the way, if your audio interface provides a direct-monitoring path, you can delete the portion of the Patcher that feeds the direct signal to the output. That is a better way to monitor the direct sound, because routing audio through the computer always entails at least a few milliseconds of latency.
FIG. 8: This figure shows the audio delay line function encapsulated in a Max Patcher Object. Double clicking on the Object labeled “patcher delayline” will open the second window, revealing the contents of that Patcher Object. Inlet and outlet Objects are used to designate inputs and outputs to appear on the completed Patcher Object.
KEEP IT CLEAN
I will now reveal to you the secret of making useful programs with Max/MSP: make sure you keep your Patchers neat. That's the difference between a hacked-up Patcher that falls apart and a complete, usable, and maintainable program. Keep your Patchers organized, and you can do anything you want.
Max provides excellent facilities to build complex functions with good organization, visual sense, and flexible design of the user interface. To start with, you can encapsulate an entire Patcher in a single Object. When you make a new Patcher Object, a subwindow automatically opens where you can construct an entire function and link it into a larger Patcher.
Fig. 8 shows our delay module with the core delay function incorporated into such a subpatch. Inputs and outputs are defined in the subpatch by using “inlet” and “outlet” Objects, which appear like the inputs and outputs of a native Max Object. When configuring a subpatch in this way, it's a very good idea to add labels for the inlets and outlets. Number boxes inside the Subpatcher are handy for debugging, as well.
I also cleaned up our patches by using right-angle lines for patch cords instead of diagonals. To do that, select the item Segmented Patch Cords in the Options menu. When connecting Objects, you can create breaks by clicking on the cords with the mouse. I use segmented patch cords in all of my work with Max, restricting use of diagonal cords to short runs where segmented cords would be awkward.
It also helps to organize Objects that connect to each other into vertical columns or horizontal rows using the Align Objects command. Simply select all of the Objects to be aligned and use the keyboard shortcut (Command + Y) to snap the selected Objects into line.
FIG. 9: The knob Object can be used to set gains instead of number boxes. Knob Objects in Max output numbers ranging from 0 to 127. To use these to set gain at a maximum value of unity, it is necessary to divide the raw output by 127, using a floating point divide, as indicated by the decimal point in each divide Object.
Number boxes are also not the ideal way to control audio gain. Max provides slider and knob Objects for more conventional audio control. Fig. 9 shows our patch with knobs instead of number boxes for the gain parameters. The knob Object outputs numbers from 0 to 127, but the gain-control multiplier needs to see a range of 0 to 1.0. To convert, divide the knob output by a fixed value of 127 using a floating-point divide so decimal values between 0 and 1.0 will be output.
FIG. 10: The Hide on Lock command in the Object menu is a powerful means of maintaining Patchers so that they look clean and neat to the end user, with wiring and Objects that the user doesn''t need to see hidden from view.
Another way to help maintain visual organization is to hide connections and Objects that the end user doesn't need to see. To do that in Max, unlock the Patcher, select the item or items you wish to conceal, and then select the command Hide on Lock from the Object menu. When you relock the Patcher, all of the Objects that were selected will be concealed, as shown on the right of Fig. 10. All patch cords and Objects that the user doesn't need to see are now hidden from view.
I elected to leave the delayline Patcher Object visible for two reasons. The first is that in order to edit a Patcher Object, you have to double-click on it while the main Patcher is locked. If the Patcher Object is hidden, you can't do that. Second, it is also helpful to embed the main function of a Patcher in a single Patcher Object and then keep that Object visible. For one thing, it helps to remind me of what that particular Patcher does for a living.
Making your Patchers orderly is an art, and you should adopt the practice from the start of your work with Max. Spaghetti Patchers get out of hand very quickly.
FIG. 11: The loadbang Object triggers specific actions when the Patcher is opened, ensuring that the Patcher always comes up in a known, useful state.
MAKE IT NICE
It's a good idea for you to include some initialization so that your Patchers come up running in a known state. An Object called “loadbang” can help make your Patchers initialize properly. Fig. 11 shows the previous version of the delayline Patcher with initialization added to load a known set of values and to start audio processing automatically.
In the Patcher shown in Fig. 11, I've unhidden some of the Objects and cords and added notes to make clear what's happening there. Whenever the Patcher is opened, loadbang sends out a trigger pulse called a bang. In this case, the bang goes to two separate places.
The first is to a Max preset Object. This is one of Max's magic functions, storing a preset for an entire Patcher window. In this illustration, a preset has been loaded into “memory 1.” Loadbang triggers the message box, sending the number “1” and loading that setup.
At the same time, loadbang triggers the “delay 500” Object. After a half second, this Object sends the start message to begin audio processing. That ensures that the whole Patcher is up and running before processing begins.
FIG. 12: This Patcher fragment converts a bpm value into a delay value corresponding to a 16th note at the designated tempo. The send Object allows this value to be conveniently routed to any number of destinations.
ADDING BEAT SYNC
So far we've managed to create a fairly well-behaved audio delay line with an uncluttered user interface. You're probably thinking that there must be more to life than this.
There is. The good news is that because we've built up our delay line from scratch, we understand it well, and we are in a position to customize it however we like. To fulfill my original wish list, the next thing we are going to add is a way to synchronize delays with a defined tempo. The simplest way to do that is to provide a means for entering a tempo value in beats per minute (bpm) and then change the entry of delay time so that delays are expressed as a number of defined units, such as 16th notes.
Entering a tempo value is easy; it's just a number box. The trick is to convert the bpm number to a value in milliseconds per unit of time (we will use the 16th note for this). This value is then fed to the delay line, which next multiplies it by the defined number of delay units to get the actual delay value in milliseconds, as required by the tapout~ Object.
Fig. 12 shows a Patcher fragment that lets the user enter a tempo in bpm and converts it into a delay value corresponding to a 16th note in 4/4 time. This fragment will be incorporated into our delayline Patcher to provide simple beat synchronization. Take a moment to look over the diagram and read the notes in this example, as some things happening there may not be completely obvious.
To calculate the value in milliseconds, first divide the number of milliseconds in a minute (60 times 1,000, or 60,000) by the bpm value entered by the user. To get the 16th-note value, divide the quarter-note result by four. We can achieve the same thing in fewer steps by using 15,000 (60,000 divided by 4) as the dividend.
In this case, the Max divide (“/”) Object doesn't quite work as we'd like it to, so we have to do a little bit of extra work. In the Max / Object, the left input accepts the dividend value, which in this case is fixed at 15,000. To make sure this value gets loaded on startup, a loadbang Object is connected to a message box containing the value 15,000, and this is connected to the / Object's left input.
FIG. 13: The delayline Patcher Object must be modified to calculate a final delay value from the 16th note value generated by the bpm master calculation and a multiple of that pulse entered by the user.
The bpm value entered by the user becomes the divisor and is sent to the right-hand input of the / Object. However, in Max the computation of a value is triggered by the receipt of a number or a bang at the left input. We can enter values all day at the right input, but no new values for the output will be generated until we send a message to the left input. This is the function of the “button” Object, which is connected to the bpm entry box. When this Object receives any message, it generates a bang in response. The bang output is connected to the left input of the / Object, and that causes it to generate a new value whenever the user enters a new value for bpm.
If you've built this Patcher fragment from scratch, you may also have noticed that it doesn't work right away. That is because the value “15,000” is not actually transmitted until the Patcher is saved, closed, and reopened. You can get around that by locking the Patcher and clicking on the message box, which triggers it to send its message to the / Object. After that all entries of bpm will generate a new value in the number box connected to the output of the / Object.
The final output of this fragment is provided by the “send” Object. Send and “receive” Objects are among Max's great gifts to help keep your complex Patchers legible and maintainable. Send and receive Objects always have a name. Any message sent to the input of a send Object will be routed automatically to any receive Object that has the same name. That makes it easy to send a single message to multiple destinations. Because we plan to create multiple delay lines tied to the same tempo, it's appropriate to use the send and receive Objects.
FIG. 14: This is the complete delay line with beat sync calculation. All Objects and patch cords have been unhidden to help in tracing, and a single loadbang Object is used.
Now that we've derived a time value corresponding to a 16th-note pulse, we need to modify our delayline Patcher to receive this value and calculate delay times as a multiple of it. Fig. 13 shows the Max code that does that, first as a fragment and then incorporated into our delayline Patcher Object. Fig. 14 shows the complete Patcher that includes the bpm delay setting as well as specification of delays as a number of 16th-note units.
FIG. 15: This version of the delay has been further simplified by incorporating I/O and control scaling into the delayline Patcher Object. This makes it easy to create additional delay sections by copying and pasting.
Although this seems like a lot of work just to get an audio delay line, now the real fun can begin. Thanks to the wonders of software, we can turn our single delay loop into any number of delays, all synchronized to a common tempo.
Before doing that, we need to simplify our Patcher a little more by moving some of the functions that remain outside the delayline Patcher Object inside, as shown in Fig. 15. By moving the audio I/O and scaling for the controls into the Patcher Object, we've made our main delay section compact and self-contained.
FIG. 16: To duplicate delay lines, unlock the Patcher, select all the Objects to be copied, and hit Command + D on the keyboard. It is usually necessary to do some initialization of parameters after duplication.
It now becomes quite easy for us to duplicate the delay section using standard Duplicate or Copy-and-Paste commands (see Fig. 16). All you have to do is unlock the Patcher, select all the items in the Delay 1 unit, and hit Command + D. The selected items are duplicated, and you can move them as a group and change the label as needed.
When you duplicate a group of Objects, they come up without any parameter values set, so it's necessary to go to the controls and set them to something useful. You also need to reenter the bpm value so that it gets transmitted to the new, duplicate module. After doing those things, Shift-click on the first button in the preset Object we added earlier to create a valid setup that will be loaded the next time the modified Patcher is opened.
FIG. 17: The selector~ Object provides an easy way to select an audio input by a numeric value. Combined with the umenu Object, it becomes easy to control audio signal routing in a multidelay Patcher.
INPUT SIGNAL ROUTING
Hopefully, you're now enjoying playing your instruments through your new dual-synchronized audio-loop delay. You may be thinking that it's kind of lame, though, because both delays get the same input, and the delays come back from both speakers equally.
There are any number of ways to control signal routing in Max, including drawing patch cords from point to point. For Patchers such as the one we created, I prefer to use pop-up menus to choose an input for each delay section. Fig. 17 shows our first delay unit modified to let the user choose from a list of inputs, along with a fragment that shows the changes needed with the delayline Patcher Object to accommodate menu selection. (Patcher Objects appear in brackets in the title bar of the edit window to indicate that you're editing a Subpatcher within a larger patch rather than a standalone Patcher.)
FIG. 18: The umenu Inspector allows you to enter a text list, delimited with commas, for the pop up menu. When an Object is selected, umenu outputs a number corresponding to that item''s position in the list, starting with 0.
The user menu (“umenu”) Object provides a pop-up list that is defined in the Object's Inspector dialog (accessed by selecting the Object and then pressing Command + I), as shown in Fig. 18. Items in the list are delimited by commas. When the user clicks on the umenu Object, this list of items pops up. When an item is selected, umenu outputs a number corresponding to the item's position in the list, starting with 0.
Within the delayline Object, an audio “selector~” Object controls the actual audio source routed to tapin~. The selector~ provides some number of inputs, defined by the number that follows the name, and one input for control. The number routed from the user menu goes to the left-hand input of the selector~. Selector~ routes one signal at a time to its output, depending on the number sent to the left-hand control input. An input of 0 switches all signals off.
Up to this point, we've used the adc~ Object in its default Stereo mode. But this Object can accommodate any number of inputs from a physical interface; simply list the inputs in the Object's name. To illustrate, adc~ is set up in Fig. 18 to accommodate four inputs. It could just as easily be 8 or 16 ins.
You can also route the output of one delay unit to another's input by using send~ and receive~ Objects, which are the audio equivalents of the send-receive pair that we used for the master tempo. Space precludes detailing that in this article.
FIG. 19: You can create as many delay sections as you wish, all synced to the same bpm value. In this example, each section is fed by a different analog input, but you can also have a single source going to multiple delay sections.
Now that you have a way to set different inputs for each delay unit, you might want to create even more iterations of the core delay, as shown in Fig. 19. Go ahead and have some fun with it.
PANNING AND MIXING
FIG. 20: A simple left right pan can be built using a knob control and simple arithmetic to create complementary control signals for each channel.
The last step we're going to take with our multisynced delay Patcher is to add output panning, first in stereo and then (for those with the means and inclination) in quad. For simplicity's sake, we'll stick with straight linear panning. Cycling '74 provides some excellent examples of equal-power panners and other variations in the user documents, and these are well worth studying and implementing. For the purpose of this exercise, though, we'll keep it simple.
Fig. 20 shows our main delay section with a stereo pan pot added, along with the portions of the delayline Patcher Object that are changed to accommodate it. The key here is the creation of two gain control signals from the single pan-pot output, accomplished by subtracting the maximum control range (127) and then multiplying by -1 to invert. After that both signals are scaled and sent to a pair of audio multipliers that implement the actual pan.
FIG. 21: Four channel panning is a little more complex because left right and front back controls must be created separately.
Our last trick will be to do the same in quad. Max provides a convenient x-y control that makes doing that easy. To make the actual panning work, we first have to create the left and right pan outputs and then use four additional audio multiplies to implement front-rear panning separately for left and right (see Fig. 21).
Fig. 22 shows the final result (well, a final result) of our efforts: a group of four long audio delays that are coordinated precisely with a common tempo. Try this Patcher out with slow-attacking guitar, synths, vocals, and so forth. You are guaranteed a spacious experience, especially if you can listen in quad! Of course, there's no reason to limit yourself to four modules. You can add as many as you like, until processing power or memory runs out.
FIG. 22: With the full version of the multidelay Patcher, you can route and control as many delays as you like, with full 4 channel panning and common tempo sync.
MAKING IT YOUR OWN
We've come a fair distance with our quad multibeat-synced delay lines, but the real purpose of this article has been to get you comfortable with creating and modifying audio-processing Patchers in Max/MSP. You should now be able to build your own creative signal-processing tools. Even starting with the Patcher presented here, you have ample room for expansion. Here are a few ideas if you want to continue exploring on your own.
- Add a function to accept a tapped tempo to define bpm.
- Add a MIDI-clock output to drive external sequencers, drum machines, and the like at the designated tempo.
- Add a MIDI-clock input. (Take note: this is actually harder than it sounds!)
- Modify the signal routing so one delay unit can feed into another.
- Add MIDI-control inputs so all parameters can be changed with a MIDI control surface.
- Add audio recording so you can grab your jams on the fly.
- Add time-based automation so all control moves can be recorded.
All of this is possible within Max and MSP, although some tricks are more difficult than others. The real excitement will be in generating and implementing your own concepts. With Max/MSP there's simply no need to be limited by what's available in current fixed-function products, because you can build anything you like, on the spot, and totally from scratch if need be!
Gary S. Hallconsults, writes, and composes from his home base in Alameda, California, and from custom remote facilities in Bahia and the Utah outback.