Creating level meters in Quartz Composer

Previously I wrote about Quartz Composer and the creation of LatheMachine, a visualizer module included in AudioCodex. In that case, I did what a lot of people do when learning Quartz Composer. I found a qtz file which was interesting or in some way relevant to my goal, opened it up and tweaked it to my liking.

One great thing about Quartz Compositions is that there is no way to compile the file into an opaque, uneditable format. All qtz files are open source. This means that you can learn from examining other people's compositions, or by building a new composition based on someone else's graph.

Today, I'm going to talk about my very first "from scratch" Quartz Composition. I have been fooling around with Quartz Composer for a few years, but so far I've never had a compelling reason to create a new composition from scratch. In this post I'll discuss the design process I went through to produce the LevelMeters composition.

On the top level

One thing that AudioCodex lacks, and for which we have had a few requests, is some kind of multi spectral level meters. There is a good explanation for this gap: as yet, AudioCodex has no internal module to provide the spectral data required. This feature has been on our wish list since the beginning, however the code is tough, and other things have so far taken precedence. Our current target for this module is version 2.0.

In the meantime, it occurred to me based on something Mark mentioned, that whilst we don't have this code, Quartz Composer does! And, coincidentally, our app is a qtz host! In the event it proved to be quite simple to cook up a qtz multi spectral level meter. I didn't even bother looking to see if there are already similar qtz files available, I just rolled up my sleeves and dove in to Quartz Composer, with a New Blank file.

The first thing this composition needs is a background, so I added a Clear patch with the default black colour.

This composition needs to react to audio input (through the system input, usually the microphone), so next I added an Audio Input patch. Lastly I added a Cube patch. This cube will be made to dance to the beat coming in from the Audio Input patch. These latter two building blocks are the engine of the level meter. Let's wire them up and see the basic principle which I'll elaborate upon later.

Connect the Volume peak of the Audio input patch to the Height of the Cube patch as shown below.

This simple arrangement will form the basis of the level meter. The first obvious change is to make the cube thinner. I set the cube's Input Parameters (Cmd-1) as follows:

  • Width: 0.045
  • Depth: 0

All other values are fine as default.

You should now see our nice thin cube in the Viewer jumping in response to audio input. If you don't, try playing a track in iTunes or AudioCodex and turn up the volume. The movement is a bit weak, so let's add a Math patch to amplify the signal.

The Amplifier Math patch is configured as follows:

  • Initial value: [From Volume peak]
  • Operation #1: Multiply
  • Operand #1: 10

Next we need to constrain the cube's movement in one axis, or rather from one end. You'll notice in the Input Parameters inspector that the Height field is greyed out, and shows the constantly shifting value from the audio input. To constrain the cube we need to find half this value at any moment, and then subtract that from the Y (up down) Position. This calls for another Math patch, or indeed two.

The Divider Math patch is configured as follows:

  • Initial value: [From Amplifier Resulting Value]
  • Operation #1: Divide
  • Operand #1: 2

The Y Positioner Math patch is configured as follows:

  • Initial value: 0
  • Operation #1: Subtract
  • Operand #1: [From Divider Resulting Value]

Hook the Resulting Value of the Y Positioner to the Y Position of the Cube. You'll notice that now the top of the cube stays anchored as the cube grows downwards.

Nested patches

So far, so simple. For the next stages, which will complexify the composition, let's encapsulate the meter we have created so far within a Macro Patch. Select the three Math patches and the Cube renderer patch, then click on the Create Macro button in the toolbar. Your selected patches will be replaced by a new Macro Patch. Rename it "Meter". If you double click it, you will be able to see our math and cube patches hidden inside it.

I tried a few different approaches to creating the visual effect of a column of LEDs, and I eventually settled on creating an image of the LEDs and using the meter to mask or reveal them. There are, no doubt, other ways to achieve this same effect. But to do it this way, the meter needs to have a height of 1 when audio input is 0, and reduce in height towards max Y until audio reaches its peak, when height should be 0, revealing all the LEDs.

The current behaviour is the opposite of this, so we need yet another Math patch to invert the value.

The Inverter Math patch is configured as follows:

  • Initial value: 1
  • Operation #1: Subtract
  • Operand #1: [From Amplifier Resulting Value]

The Y Positioner Math patch now needs to be reconfigured as follows:

  • Initial value: 1
  • Operation #1: Add
  • Operand #1: [From Divider Resulting Value]

Hook the Resulting Value of the Inverter to the Height of the Cube. Your graph should look something like this:

You should now see the meter as a white bar that shrinks towards its top as the level increases.

Next we will create the LED column image. Drag a Sprite patch to the Editor window somewhere to the side of the Cube and Math patches. Configure its Input parameters as follows:

  • Width: 0.045

All other values are fine as default.

Background sprite

It took me a while to figure out how to set the layer level in Quartz Composer. The answer is to click on the little number in the corner of the patch. Set the Sprite to Layer 1. This puts it behind (below) the Cube.

Next, drag a Linear Gradient patch next to the Sprite, and configure it as follows:

  • Point 1 (X): 0
  • Point 1 (Y): 100
  • Point 2 (X): 0
  • Point 2 (Y): 200
  • Color 1: Green
  • Color 2: Red

Gradients need to be cropped before they can be used, so drag an Image Crop patch to the Editor. Connect the Image output of the Linear Gradient to the Image input of the Image Crop.

To create the effect of individual LED units, grab a Line Screen patch and add it to the Editor as well. Set it up as follows:

  • Center (X): 0
  • Center (Y): 10
  • Angle: 90
  • Width: 4
  • Sharpness: 1

Now connect the Cropped Image output of the Image Crop to the Image input of the Sprite. Connect the Cropped Image output of the Image Crop to the Image input of the Line Screen. Connect the Image output of the Line Screen to the Mask Image input of the Sprite.

Finally, set the Front Color of the Cube to be black.

Click Edit Parent in the toolbar to return to the top level (Root) patch.

You should now be seeing a single level meter jumping up and down to the beat. In the next installment, I'll show you how to create a set of 24 meters, with each one reacting to a particular slice of the audio spectrum.

Download

Download the sample project: SimpleLevelMeter.qtz.zip (4KB).

Requires Mac OS X 10.4+ and Quartz Composer.

Article continues

Read on to part 2.

Great tutorial, but...

Thanks for posting this, this is a great tutorial for someone looking to get into Quartz Composer. I went through the entire tutorial and noticed that there may be a step missing.

When you get to the Image Crop patch you didn't express that you have to set all values to 100 in your writeup. If you don't set these values your gradient - line patch effect doesnt show properly. I had to download your source code and examine the values of each patch to come to this conclusion.

Also, another error in the tutorial is that the Y Positioner initial value should be set to 0 not 1 - this puts the level in the middle of the viewing area just as your example shows.

Complex Numbers?

As a beginner Mac developer, projects like this are very welcome.

However I think you mean complicate not complexify - see http://en.wikipedia.org/wiki/Complexification
for what that means! (In short it means- "Let V be a real vector space. The complexification of V is defined by taking the tensor product of V with the complex numbers (thought of as a two-dimensional vector space over the reals):").

But otherwise, great work!

Post new comment

The content of this field is kept private and will not be shown publicly.
CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
9 + 5 =
Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.

Navigation

User login

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
2 + 14 =
Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.

Recent