Archive for the ‘music’ Category

Updated Studio Computer to Snow Leopard

Monday, September 7th, 2009

last night. The glitches I encountered were

1) PACE license code needed updating
2) MIDI and Firewire Audio drivers needed updating
3) MOTU Ethno component needed to be removed from MAS folder
4) Virtual String Machine’s font got clobbered and had to be downloaded (found it through support FAQ)

Otherwise it all went great.

NAMM Dinner Friday Night

Thursday, January 15th, 2009

This week is the North American Music Manufacturers annual trade show. There’s going to be a dinner with users and employees of DP, a program I use to record music. I’m hoping to show off Jambalaya. What would be the coolest is if some established company would take over marketing Jambalaya and hired me to do future development. That would be my dream gig more or less.

OK, its not likely to happen, but I can dream. Although if things don’t pick up next month, marketing that is likely to move to the forefront as I’ll have nothing else going on.

JambaLaya development at WWDC

Friday, June 13th, 2008

So far WWDC has been very useful. I came with a checklist of about 10 items I wanted to add to JambaLaya but was having trouble with and I got them all more or less knocked out. Among those:

Custom font bundling – there’s some black art here and it took two days to find the guy who knows how that works. It is possible that people downloading JambaLaya have been getting it rendered with really ugly fonts. If you’ve downloaded it and it doesn’t look like the picture, I’d like know because I think I’ve been getting fooled by system installed fonts. Fixed.

JambaLaya Screen

Key indicator highlighting on key range mapping. I couldn’t get this to draw reliably due to threading issues. Fixed. Makes it much easier to see where your keys are because hitting a key on the keyboard animates it in the mapper.

Adding side chain routing to audio unit views – since these are often carbon views (ICK) adding UI is kind of nasty – but someone suggested I stick a drawer on the bottom – cool. It was kind of tricky to get working with carbon window but we made it work in the end. Expect side chaining and other custom add-ons to appear in audio unit views.

Clock and Tempo. For working with things like Stylus RMX adding ways to communicate song tempo and beat clock. JambaLaya will also get the ability to both supply timing or sync to external timing and will get transport controls.

Some other goodies I’m not talking about yet. :-)

Expect 1.1.0 early with all the bugs fixed by next week. New features as I get time.

In other WWDC news, iPhone app development is HOT HOT HOT. I confess to developing iPhone envy looking at how much use people get.

Mike Arrington, Software Pirate

Monday, March 24th, 2008

The ever clueless and abrasive Mike Arrington says something even more ridiculous than usual. I can see both sides of the Bebo thing and frankly, social networking makes me yawn. I have no patience or interest in it. Seems like a phenomenal waste of bits to me. Musicians uploaded their music without expectation of compensation. So sure, they’re probably not ‘entitled’ to a payout. OTOH, Bragg’s point is well taken – the musicians made them successful and it would be a nice gesture to give back. But I wouldn’t hold my breath on that. They’re internet entrepreneurs. Thus greedy bastards by definition.

OTOH, the thing that really ticks me off is this little comment by Arrington.

…it costs exactly the same to produce one copy of the song (the first one) as 10 million copies. Simple economics takes over. Free.

Which, if true, implies that Microsoft ought to be giving away Vista, Office, and everything else. Because Music is Software. It costs as much to develop as software, it takes every bit as much time, talent, and skill.

Just because you can make a second copy for a buck, doesn’t mean that’s all it is worth. If it costs $30k to record a song (which is kind of typical these days), and we are expecting to sell 100 copies, then this song needs to make $300 per copy to break even. If its 10 copies, then its $3000 a copy. The same economics apply as software. Just like there is free software, shareware, and commercial software, there are many business models around music. No single model is right all of the time.

Arrington should stick to his little blog about the shiny things – he obviously knows fuck all about the economics of creation.

JambaLaya site updated with documentation

Thursday, March 20th, 2008

mainscreen.png

Today I uploaded a whole bunch of shots and comments – primarily to serve as a proxy for a user’s manual. It is such a straight forward simple app, I can’t imagine it needs much of a manual. Basically live music performance oriented MIDI and audio processing.

Anyhow, check it out. http://www.audiofreakshow.com

About the only thing preventing a full on launch is the back end stuff to take payments and issue serial numbers, and finishing up the serial number handling in the application. It doesn’t adequately cripple things if there is no serial yet. Few more bottlenecks to install checks into. Also, one little bug with lyric editing. Minor, but a little annoying.

JambaLaya approaching final candidate

Wednesday, March 19th, 2008

I’ve been working on it like crazy, stomping bugs and adding polish. It is pretty close to RC. Still need to add registration and complete the website infrastructure to automate dispensing of serials. I’m sure it will be huge because I just added the killer must-have feature.

Behold – Murph and the MagicTones Mode!

murphaboutbox.png

JambaLaya covered in “Thick Red Shag!” No other Audio Units host has that! Take that MainStage!

JambaLaya Website Updated

Monday, March 17th, 2008

I finally got the JambaLaya website looking decent – installed Drupal’s forum module, did a lot of work on a theme. It needs more marketing stuff – more recent screen shots and better feature exposition – but as a start its not bad.

If you’ve downloaded JambaLaya and tried it – the place to report bugs is definitely in the forums.

JambaLaya Updated

Monday, March 17th, 2008

New beta released

Download it.

Release Notes

Lots of new goodies including integration with external synthesizers, full audio IO capabilities, note doubling (stacking octaves and 5ths), and it is much leaner on resources.

The Audio IO bit arrived just in time as I joined a group purchase of AmpliTube 2, AmpliTube Jimi Hendrix Edition, and some other goodies. This let me route my guitar into one of the inputs on my MOTU UltraLight, set up the AmpliTube as an effect, and get some really sweet guitar sounds. No more lugging a guitar amp around!

Addressing HAL Devices with Apple’s Core Audio in JambaLaya

Sunday, March 16th, 2008

I play guitar and keyboards in a rock band for fun. I’m basically a guitarist, but I have this knack for programming things, like computers and, as it turns out, synthesizers. Thus, I always end up doing some keyboard work in any band I play with. I have a lot of classic hardware synthesizers from the 80’s. But these days a lot of software emulations for hardware have come out and I use these as much as possible.

Occasionally, however, there is no replacement for an external synthesizer. It would be great if JambaLaya could present and allow routing to the hardware instruments in the same way as it does software instruments. While I’m at it, I might as well add support for audio routing. Currently JambaLaya just uses the default audio device and plays to its default outputs.

An AudioUnit MusicDevice takes in MIDI control information and outputs audio signals. A hardware synth does the same, but to get its audio, I have to map it to an audio input in my audio interface and then sort of pretend that the audio is generated from the device. The idea being a hardware synth is a midi endpoint, channel, and audio input set. While I’m at it, I might as well provide HAL support and allow any kind of audio routing the user wants. My live audio interface is a MOTU UltraLite. It has 12 audio inputs and 14 audio outputs. It also acts as my MIDI interface. The goal is to make a hardware synthesizer look and act just like an AudioUnit MusicDevice.

AUGraph Channels vs Busses

AUGraph connections connect BUSSES. A buss can contain many channels. How many is determined by setting the AudioStreamBasicDescription on the kAudioUnitProperty_StreamFormat for the buss. Each node in an AUGraph has a number of input and output busses. For some AudioUnits, the number of busses are fixed. Most MusicDevices just have one output buss. Others, like the MatrixMixer can be configured with any number of busses.

Connecting Busses

To connect busses, you make node connections using

AUGraphConnectNodeInput(graph, sourceNode,sourceBussNumber, destinationNode,destinationBussNumber)

Before you can do this though, you have to configure the busses on both sides by setting kAudioUnitProperty_StreamFormat using an AudioStreamBasicDescription on both sides to make sure the signal formats and number of channels is compatible. If you don’t do this, things don’t work the way you expect. This is especially true when connecting a mixer because the number of channels in the stream format determines the number of channels in mixer. The total number of input channels in the mixer is the sum of the number of channels of each of its input busses. Same for the outputs. This is why configuring stream formats is so important. Furthermore, you cannot change the stream format after making the connection – you’ll get an error. So, always configure both stream formats prior to connecting nodes.

Mapping Audio IO in HAL Devices

HAL devices present their IO channels all in one buss. All the audio inputs (in jacks) are presented on a single output buss for the device. All of the audio outputs are presented on a single input buss. Confused? THE TERMINOLOGY OF INPUT vs OUTPUT in a HAL DEVICE is VERY CONFUSING. This took me many days of experimentation to figure out and is the primary motivator for writing this article.

To begin with, all HAL devices are referred to as Output Devices, regardless of whether they do input, output, or both. In the case of the MOTU UltraLite, one device does both jobs, but you could use different devices for input and output. HAL devices are not at all configurable with respect to what audio appears where – so to do any kind of routing, you want to stick a matrix mixer in front of it, then work with that to do signal routing. Thus, your application will most likely have a matrix mixer representing the audio inputs, and a matrix mixer representing the audio outputs.

AudioIO2

Creating the Output Device

First you need to add a node to your AUGraph to represent your HAL device.

AUGraph graph;
OSStatus status=NewAUGraph(&graph);

// Description for HAL Output Device
ComponentDescription halAudioOutputDescription={
kAudioUnitType_Output,
kAudioUnitSubType_HALOutput,
kAudioUnitManufacturer_Apple};

// Create a node to represent the IO device
AUNode outputDeviceNode;
status=AUGraphNewNode(graph, &halAudioOuputDescription, 0, 0, &outputDeviceNode);

// get the component instance so we can initialize the device -
// nothing works until the device is initialized
ComponentInstance instance = 0;
status=AUGraphGetNodeInfo(graph, outputDeviceNode, 0, 0, 0, &instance);

// initialize the device
status=AudioUnitInitialize(instance);

//Get the identifiers of the default audio input and output devices

AudioDeviceID outputDeviceID;
AudioDeviceID inputDeviceID;
UInt32 size=sizeof(AudioDeviceID);

status=AudioHardwareGetProperty ( kAudioHardwarePropertyDefaultOutputDevice, &size, &outputDeviceID );
status=AudioHardwareGetProperty ( kAudioHardwarePropertyDefaultInputDevice, &size, &inputDeviceID );

//Now you must enable the device for audio output.

UInt32 value = 1;
status=AudioUnitSetProperty(instance, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &value, sizeof(value));

If we are using the same device for input, enable it for input too. IMPORTANT! The hardware’s OUTPUT channels appear on BUSS 0. But the INPUT channels are on BUSS 1! Why? What’s the significance? I DON’T KNOW! But keep this in mind as it will come back to bite you when connecting the input mixer.

if(inputDeviceID == outputDeviceID)
{
inputDeviceNode=outputDeviceNode;
status=AudioUnitSetProperty(instance, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &value, sizeof(value));
}
else // signal an error - you can only have one output device in the graph

// Set the AudioDeviceID on the HAL device to map it to the right piece of hardware
status=AudioUnitSetProperty(instance, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &outputDeviceID, sizeof(outputDeviceID));

Creating the Output Mixer

If you were just interested in mapping hardware inputs to outputs, you could get by with a single matrix mixer and set matrix channel volumes to route audio. But it seems more natural to connect nodes to make connections – especially when mixing in Audio Unit Music Devices (virtual instruments). So I create a mixer for each interface, then connect various busses between them like a patch bay. You create the mixer pretty much the same way as the HAL device.

// Description for the matrix mixer
ComponentDescription matrixMixerDescription={kAudioUnitType_Mixer, kAudioUnitSubType_MatrixMixer,kAudioUnitManufacturer_Apple};

// Create a node to represent the mixer
AUNode outputMixerNode;
status=AUGraphNewNode(graph, &matrixMixerDescription, 0, 0, &outputMixerNode);

// get the component instance so we can initialize the device - nothing works until the device is initialized
ComponentInstance instance = 0;
status=AUGraphGetNodeInfo(graph, outputMixerNode, 0, 0, 0, &instance);

// initialize the mixer
status=AudioUnitInitialize(instance);

The output device node’s audio is fed into INPUT BUSS 0 which has one channel in it for each OUTPUT jack on the device. So you only need a single OUTPUT BUSS on the mixer, which you will connect to the INPUT BUSS 0 of the OUTPUT DEVICE. Refer to the picture if you’re getting confused.

UInt32 busCount = 1;
status=AudioUnitSetProperty(instance, kAudioUnitProperty_BusCount, kAudioUnitScope_Output, 0, &busCount, sizeof(busCount));

Prior to connecting the nodes, you want to make sure the number of channels and sample rates match. THIS IS CONFUSING! The stream description for the INPUT bus of the OUTPUT device for the device’s OUTPUTS is gotten by asking for the stream format for the OUTPUT device’s OUTPUT stream format for BUSS 0. Read that a couple times. Because you have to copy that stream description to the INPUT BUSS 0 of the output device and the OUTPUT BUSS 0 of the output device prior to connecting the busses. Here we go.

// get the node instance for the output device
status=AUGraphGetNodeInfo(graph, outputDeviceNode, 0, 0, 0, &instance);

// get the OUTPUT stream description for the OUTPUT device to set on the DEVICE's INPUT BUS 0 and MIXER's OUTPUT BUS 0
AudioStreamBasicDescription streamDescription;
UInt32 size=sizeof(AudioStreamBasicDescription);
status=AudioUnitGetProperty(instance, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &streamDescription, &size);

// set the format on the INPUT BUS 0 of the OUTPUT DEVICE
status=AudioUnitSetProperty(instance, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescription, sizeof(streamDescription));

// get the node instance for the output mixer
status=AUGraphGetNodeInfo(graph, outputMixerNode, 0, 0, 0, &instance);

// set the format on the OUTPUT BUS 0 of the MIXER
status=AudioUnitSetProperty(instance, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &streamDescription, sizeof(streamDescription));

// connect the busses - OUTPUT BUS 0 of the MIXER to INPUT BUS 0 of the OUTPUT Device - hard to keep straight I think
status=AUGraphConnectNodeInput(graph, outputMixerNode,0,outputDeviceNode,0);

Now you can configure the input side of this mixer anyway you like. For instance, you could create a bunch of stereo pairs and then attach Audio Unit Music Device’s to them. Or some stereo pairs and a few mono inputs. Think of it as one side of your patch bay.

Creating the Input Mixer

This code is very similar – only for reasons that I don’t understand, all of the action on the INPUT side of an OUTPUT device occurs on OUTPUT BUSS 1. First we create the mixer as before.

// Create a node to represent the mixer
AUNode inputMixerNode;
status=AUGraphNewNode(graph, &matrixMixerDescription, 0, 0, &inputMixerNode);

// get the component instance so we can initialize the device - nothing works until the device is initialized
ComponentInstance instance=0;
status=AUGraphGetNodeInfo(graph, inputMixerNode, 0, 0, 0, &instance);

// initialize the mixer
status=AudioUnitInitialize(instance);

The output device used for INPUT has an OUTPUT BUSS 1 buss with one channel in it for each INPUT jack on the device. So you only need a single INPUT BUSS on the mixer, which you will connect to the OUTPUT BUSS 1 of the output device used for input. Refer to the picture if you’re getting confused.

UInt32 busCount = 1;
status=AudioUnitSetProperty(instance, kAudioUnitProperty_BusCount, kAudioUnitScope_Input, 0, &busCount, sizeof(busCount));

Now we need to setup the stream formats for the OUTPUT BUSS 1 of the DEVICE and INPUT BUSS 0 of the MIXER. You get the correct stream format for the OUTPUT BUSS by getting it from the DEVICE INPUT BUSS 1. THIS IS VERY CONFUSING!

// get the INPUT stream description for the OUTPUT device used for INPUT to set on the DEVICE's OUTPUT BUSS 1 and MIXER's INPUT BUSS 0
// REMEMBER that the INPUT description is found on ELEMENT 1

// get the device instance
status=AUGraphGetNodeInfo(graph, inputDeviceNode, 0, 0, 0, &instance);

AudioStreamBasicDescription streamDescription;
UInt32 size=sizeof(AudioStreamBasicDescription);
status=AudioUnitGetProperty(instance, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &streamDescription, &size);

// set the format on the OUTPUT BUS 1 of the DEVICE used for INPUT
status=AudioUnitSetProperty(instance, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &streamDescription, sizeof(streamDescription));

// get the node instance for the input mixer
status=AUGraphGetNodeInfo(graph, inputMixerNode, 0, 0, 0, &instance);

// set the format on the INPUT BUS 0 of the MIXER
status=AudioUnitSetProperty(instance,kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input,0,&streamDescription,sizeof(streamDescription));

// connect the busses - OUTPUT BUS 1 of the DEVICE to INPUT BUS 0 of the MIXER - THINK HARD!
status=AUGraphConnectNodeInput(graph,inputDeviceNode,1,inputMixerNode,0);

Now you can configure the outputs of the input mixer into any combination of busses and channels you like. To make a connection, just connect an output buss from the input mixer to an input buss on the output mixer.

Hopefully this will help someone else because it took me days to figure this out as CoreAudio’s documentation is really sketchy.

MIDI Performance Software

Friday, January 11th, 2008

jambalaya1.png

Last spring and summer, I decided to stop dragging a bunch of hardware synthesizers back and forth to band practice and start using a laptop as an all-in-one solution. This is more or less possible thanks to the availability of a variety of virtual instruments in Audio Units format that rival (and in some cases faithfully reproduce) the hardware synths of olde.

Seems simple. I need a MIDI controller keyboard – I chose an 88 key model and figured I’d map various instruments to different ranges of keys. So I started looking for an Audio Units host oriented towards live performance.

I came up empty. Nearly all of them are oriented towards sequencing and multi-track recording. They could kind of do what I wanted, but the user interface wasn’t oriented towards what I needed. There was one product – an independent program called RAX – that seemed right – only its author had just withdrawn it from the market. I managed to get an evaluation license from the developer but I disqualified it because it had a problem handling sustain pedal events and its future was uncertain.

So I set out to build my own and I’ve succeeded. It works well enough, is pretty bare bones, but allows the user to do complex splits and layers very quickly. I call it JambaLaya and I use it all the time. It isn’t quite production quality and there are missing feature I’d like to add. But it is a great feeling to control your own destiny and not have to worry about a critical piece of software disappearing from the market.

Now I’m trying to decide what to do with it. I could polish it up and offer it for sale, but since I wrote it two things have happened. RAX was acquired by a new publisher who is once again selling and supporting it and Apple has released a Logic 8 update with a program called Mainstage that is also oriented towards live performance. In both cases, I prefer the way the JambaLaya works, the UI is much more feature dense and it works the way I expect (little wonder, since I wrote it). I think in the short term, the best thing is to start a community website for it and give it away. So I think that’s the plan unless somebody has a better idea. I just need more time to configure the Drupal site and get that going.