Bees & Bombs
Rebuilding a gif from Bees & Bombs
I built a loading view for a 28-iPad installation I’ve been working on over at Logic&Form. The majority of code focuses on the setup and styling of shapes, so it is straightforward. The outcome is a dynamic radial visualization of sound that uses timers, audio samples and metering.
Here’s what we’ll be building:
Let’s get to it.
Visually, there are 5 elements: an image and four polygons. Behind the scenes, there are an additional 3 elements: a timer, an audio player and an audio sample. The four lines represents the peak and average power readings for each of the two channels in our audio sample.
The audio sample we’re using in this tutorial is a short version of Black Velvet a song by WOULG… and definitely NOT Alannah Myles. You should definitely check out interview Homegrown: Woulg, by Freq Magazine. I like how it starts:
“A psychonaut can be described as a person taking a trip into the depths of ideas.”
We know we need a few things to start, so let’s just add them in now.
In your project’s WorkSpace
add the following variables:
These should all be placed before your setup()
and for the most part should be self-explanatory. However, there are a few things to note:
paths
and shapes
because it’s the paths we’re going to continuously add points to these, then update the visible shapes with them!
for the audio player only for simplicitymaxPeak
and avgPeak
values from the audio sample we’re using.Check this link for the code that I used to generate the max / avg values: Max Avg
To make the main setup()
cleaner, we’ll break down all the necessary steps into discreet functions.
We’ve already initialized our paths as class-level tuples, so we can use them to create and setup our shapes.
First, we’re going to be styling our shapes consistently, so add this simple method to your WorkSpace
:
Then, add the following method:
A key thing to note is that there are 4 shapes, three of which we rotate. We do this so that their starting positions don’t overlap.
First, grab the audio sample for this tutorial and drag it into your project: BlackVelvet.m4a
Next, create the audio player by adding this method:
We want to extract the meters from each of the channels in our audio sample. So, before starting playback we need to set meteringEnabled = true
. This makes sure that when we request the average or peak values for a channel that we get actual numbers.
First, grab, unzip and add the 3 logo images to the Images.xcassets folder in your project. Here’s the zip: LFLogo.zip
Here’s what your project should look like:
Now, add this method to your WorkSpace
:
To check that everything works nicely, you need to edit your main setup
to look like this:
Hit play in Xcode. You should hear the sample play, and see this:
The next main thing we need to do is create the infrastructure for reading the audio meters and updating the shapes. To do this we’ll create a few methods for extracting values, updating paths, and run everything using a timer.
Every time our timer fires, we’re going to want to grab the current meters. From there, we’re going to convert the values to points via some polar coordinate math.
Add the following method to your WorkSpace
:
This takes a value and converts it to a Point()
, using the current angle (Θ
).
Before we generate Points, we’re going to extract the audio values. These come in from our audio player in a pretty raw format (often ranging well below 0).
We’ll use the following method to convert our values to something we can use. Add this to your WorkSpace
:
This takes a negative value and converts it to positive. Then, it normalizes the incoming value based on the current max
parameter, giving a range between 0...1
. Finally, we map the normalized value to the following range: 100...200
.
This mapped value will be the radius we use to generate a point.
For each path we will extract the current channel value, convert it to a point, and then add it to the given path. Add the following to your WorkSpace
:
After extracting, converting and adding all the points to our paths, this method also increments our current angle (Θ
) and will also reset the paths for each 360 degree revolution.
In C4 you can conveniently update the path of a Shape
. For simple paths this process is extremely fast, so even if the shape is complex the device will still be able to update and redraw the shape.
Add the following method to your WorkSpace
:
Updating the path won’t keep it in the same position. So, all we need to do is recenter the shape after each update. (Also fast).
The final step for this tutorial is to set up a timer that will fire at 60fps
. Add the following method to your WorkSpace
:
In sequence, and 60 times per second, this timer will udpate the player’s meters, then generate points, then udpate the visible shapes.
Simple, right?
Now, call this method at the end of your main setup()
and run the project.
You can grab a copy of the code for this tutorial from here:
And, here are the media links for the logo and audio files:
Finito.