Wednesday, January 2, 2008

Send Equalized Sound to Airport speakers on the cheap

Ok, here’s how I’ve setup my MacBook to stream audio through AU Lab for processing (EQ) and then out to my Airport Express –like airtunes, but for all sound, not just iTunes content (Airfoil works better for this, but It’s not as much fun, and it costs money)

BTW aside from the AU Lab EQ, I found all of this how-to info using Google. It seemed that most people describing this were in the Bearded Unix Guru catagory and kept describing it as "easy" whereas I was finding it "$%@# confusing" so once I figured out a system for doing what I wanted I thought I'd try to spell it out for other muddlers like myself. If my descriptions seem too long winded, I'm not writing that part for you, I'm writing it for your mother. If my *nix skills seem weak...that's 'cause I'm no good at unix... etc. etc. If you find/know of a better way, please let me know. Pieces of my email address are found at the bottom of the post.

Ok, let's get started...

First of all you’ll need these programs:
  • Soundflower - http://www.cycling74.com/products/soundflower
  • AU Lab – found at /Developer/Applications/Audio/ after you’ve installed "Developer Tools" from your Mac OS X Install disc
  • Enlightened Sound Daemon - http://www.tux.org/~ricdude/overview.html
  • JustePort - http://nanocr.eu/software/justeport/
  • Mono - http://www.mono-project.com/Downloads - used to run JustPort on your mac
A bit about structure… the idea here is to pipe sound from any program (probably not iTunes as it can do this natively) to AU Lab, run it through whatever filters in AU Lab (a graphic EQ for me) and then pipe it from there out to an airport express connected to external speakers of some kind. The sound will follow this path:
OUTPUT -> Soundflower 16ch -> AU Lab -> soundflower 2ch -> esdrec -> JustePort -> Airport Express
Note: Soundflower 2ch and 16ch will be bundled into one Aggregate Device

To start, install all those programs listed previously. Install Mono before trying to compile JustePort ‘cause it’s a C# program being compiled and later run by Mono (I think there may be a way to compile JustePort so that it runs natively on mac os, but I couldn’t figure it out so in my example we’ll be running JustePort like this:
> mono /path/to/JustePort.exe
Much of what the kind of stuff we’re going to do with soundflower and Audio MIDI Setup is explained in more detail in the previous post here so read through that for a more detailed explanation. I’m going to go a little fast with that stuff…

Blatant plagiarism of my last post:
We’re going to need an input of sound into AU Lab and an output for our modified sound (after the equalizer). Strangely, as far as I can tell, AU Lab can only work with what it sees as one device at a time, luckily Audio MIDI Setup has a method of bundling devices together to create “Aggregate Devices”. This is the only step for which you need to be Admin, so for this step, change to your Admin account and open “Audio MIDI Setup”. Now Choose “Open Aggregate Device Editor” from the “Audio menu.

We need to provide a pipe into AU Lab and a pipe from there to esdrec so we’ll check “use” for “Soundflower (2ch)” and “Soundflower (16ch)”, name this device anything you like (or leave it as the default “Aggregate Device” – this is what I’ll call it for the rest of this post). When you’ve done this, click done, and make sure your “Aggregate Device” now appears in the dropdowns Audio MIDI Setup – don’t select it now, just make sure it appears (if you select it and forget you’ll wonder why your sound is broke in your admin account). If your new Agg. Device exists and your Outputs are set to Built-in, it’s time to exit this program, log out Admin and return to your normal account.

You now have all the pieces needed to implement this system. Now let’s do it. Eventually we’ll discuss using an applescript to automate the steps. For instance, I can run an applescript and all my sound will be routed to my stereo, and run a different one, and all sound will be returned to my built-in speakers. But first we’ll do the steps manually in order to understand them better.

Start some music playing at a moderate volume and leave that running in the background.

In Audio MIDI Setup select Soundflower (2ch) as the default input and the default output. Your music will now go quiet although the program is still running, any normal sound played by any program on your mac is going into Soundflower (2ch) and any program which can take in sound (to record it for instance) will get that same sound piped right in. Now open a terminal window and type
/path/to/esdrec | path/to/mono /path/to/JustePort.exe - 10.0.1.1 -30

(i.e. /usr/local/bin/esdrec | /usr/bin/mono /usr/local/bin/JustePort.exe - 10.0.1.1 -30)

you should get output like this:

opening socket, format = 0x00002021 at 44100 Hz
using device Soundflower (2ch) for output:
with sample rate 44100.000000, 2 channels and 32-bit sample
using device Soundflower (2ch) for input:
with sample rate 44100.000000, 2 channels and 32-bit sample
JackStatus: connected
JackType: analog

And your computers sound should now be coming out of your speakers attached to your Airport Express.

To understand the above command, let’s look at the parts:
  • esdrec – outputs from the sound device's current input.
  • “ | “ – a pipe sending the output from esdrec to JustePort
  • mono – allows us to run the C# windows executable JustePort
  • JustePort – The program sending the data over the wifi to your airport
  • - 10.0.1.1 – an argument to JustePort – this is hopefully the ip of your airport (it tells JustePort where to stream your sound)
  • - 30 – this is the optional volume setting for JustePort which is unnecessary as -30 db is the default volume, but you can change the sent volume by changing this: -0 is loudest -144 is the quietest

ok…done deal, unless you want to control the volume and add a graphic EQ in which case we’ll use AU Lab similarly to the EQ instructions in the last post.

Now, with your system still how we left it (sending sound to your airport) go into Audio MIDI Setup, and change the default output to Soundflower (16ch). Your sound should go quiet because so far nothing is using sound from SF(16ch).

more self plagiarism follows…

Open AU Lab – at the create new document dialog:
choose “Aggregate Device” from the Audio Device dropdown menu. Under the output tab grab the red box and make sure it’s on the channels 1&2 (which shoud be the group of 2 channels -- you should also see an adjacent group of 16 channels) now click the “Inputs” tab, and then click Add Input – a red box should appear – drag this red box until it’s on channels 3&4 which are the first 2 channels of the 16 channel portion, now you can click OK to create the document

At this point you should have an Untitled window with some controls and your music and sound should come back on (as long as you left it playing and left JustePort running in your terminal. At this point save the current document so you don’t have to configure it again (it will be saved with the extension ".trak" and doubleclicking this file in the future will open it in AU Lab - very handy). In the left column you’ll see the heading “Effects” and three dropdown menus – These can be used to apply all sorts of effects, but the basic need is an equalizer, so choose AUGraphicEQ and play around. I recommend opening up the iTunes equalizer and copying presets from there onto the 10-band EQ - be sure to save any EQ settings you like.

Alright. Hopefully this works for you so far. To quit sending sound to the Airport and return it to your machine:
  • in Audio MIDI Setup set Default Output and Input menus to "Built-in"
  • in the Terminal window which is still piping esdrec into JustePort type ctrl-c to halt this process. Alternatively you can just close the terminal window or quit terminal
that's it.

Now that the system's been setup, the steps to send sound back to your airport are
  • in Audio MIDI Setup set Default Output to "Soundflower (2ch)" and Default Input to "Aggregate Device"
  • in Terminal enter
    /path/to/esdrec | path/to/mono /path/to/JustePort.exe - 10.0.1.1 -30
  • open your saved AU Lab file ( mySavedFile.trak or whatever you named it) - this will launch AU Lab
  • in Audio MIDI Setup set Default Output to Soundflower (16ch)
Note: The in Audio MIDI Setup, Default Input must be set to "Aggregate Device" and Default Output must be set to "Soundflower (2ch) at the time that esdrec is called -- otherwise, esdrec will choose the wrong input and your sound will never get to JustePort. After this has been set and the esdrec | mono... call has been made then you can change the default output to Soundflower (16ch) and open your saved AU Lab configuration.

Not too bad to save $25 (remember airfoil) but it's even easier if you automate it with an AppleScript.

For this applescript to work you'll need to go to System Preferences -> Universal Access and check "Enable access for assistive devices" which allows applescript to do "GUI scripting"

Open the AppleScript editor and paste the following into it. Next, modify any file paths needed to conform to your machine (i.e. esd may be found at /usr/bin/esd or /usr/local/bin/esd or wherever you put it when you compiled it. Likewise for esdrec, yourFile.trak, mono, and JustePort.) Then save the applescript with whatever name you'd like (I named mine sound2Airport and sound2Normal)-- In the applescript save dialog choose "Application" from the File Format dropdown so that you can just double click on the applescript to run it.
--------begin applescript

-- Note: on MIDI setup page "Properties For" must be left set to "Built-in Output" or
-- "Soundflower (2ch)" for script to execute properly

-- we use this function to set the popup wndows
-- I don't remember who I plagiarized this function from
-- but credit goes to them...

on setPopUp(x, y)
tell application "System Events"
tell process "Audio MIDI Setup"
tell window "Audio MIDI Setup"
tell tab group 1
tell pop up button x
click
tell menu item y of menu 1 to click
end tell
end tell
end tell
end tell
end tell
end setPopUp

--first we tell AMS to set necessary output and input
tell application "Audio MIDI Setup" to activate
setPopUp(6, "Soundflower (2ch)") -- Default Output to start esd
delay 0.3
setPopUp(7, "Aggregate Device
") -- Default Input
delay 0.3

-- now we start the Enlightened Sound Daemon while the Input and Output are set correct
--this way esdrec will use the correct channels later
do shell script "/usr/bin/esd &> /dev/null & " --esd must be started with SF_2ch selected and

-- now we set Output to SF16
tell application "Audio MIDI Setup" to activate
setPopUp(6, "Soundflower (16ch)") -- Default Output for Playing through AU Lab
tell application "Audio MIDI Setup" to quit

-- now we open our saved AU Lab track and then pipe the sound out through JustePort
do shell script "open Users/josh/Scripting/Sound/sound2Airport/ControlSound2Airport.trak" -- AU Lab for EQ and volume
do shell script "/usr/bin/esdrec | mono /usr/bin/JustePort.exe - 10.0.1.1 -20 &" -- pipe the sound to airport

---------------end applescript

the AppleScript to return settings to normal is much more simple... save this one as an application also...

------------- begin applescript
-- Note: on MIDI setup page "Properties For" must be set to "Built-in Output" or
-- "Soundflower (2ch)" for script to execute properly - dunno why
on setPopUp(x, y)
tell application "System Events"
tell process "Audio MIDI Setup"
tell window "Audio MIDI Setup"
tell tab group 1
tell pop up button x
click
tell menu item y of menu 1 to click
end tell
end tell
end tell
end tell
end tell
end setPopUp



tell application "Audio MIDI Setup" to activate
delay 0.3
setPopUp(6, "Built-in Output")
delay 0.3
setPopUp(5, "Built-in Output")
delay 0.3
setPopUp(7, "Built-in Input")
delay 0.1
tell application "Audio MIDI Setup"
quit
end tell



do shell script "killall mono"
do shell script "killall esd"


tell application "AU Lab" to quit

-------------- end applescript


A Note on these applescripts: I'm no bloody good at writing applescripts so if YOU are good at writing the them and you see a better way to do something please let me know so I can modify the posted code. Actually that goes for pretty much all of the above... I don't really know what I'm doing so y'all let me know if you know a better way.

I can be reached at
jp.
random
@GOOGLESEMAILSERVICE.com <- hopefully the spambots can't figure it out...and you can.

No comments: