Digital Media • 54:19
Mac OS X delivers system-level support for a comprehensive set of professional-grade audio and MIDI services. This session provides an overview of the APIs and services in Core Audio and MIDI in Mac OS X. Topics include AUGraph and Sequencing services, as well as AudioUnits and the AudioConverter services.
Speakers: Jeff Moore, Chris Rogers, Bill Stewart
Unlisted on Apple Developer site
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Welcome to the Core Audio Technologies session. I'm Craig Keithley. I'm Apple's USB and FireWire evangelist. My role in evangelism is to help, primarily, developers bring products to the Mac, and audio is a special favorite of mine, so I'm pleased to help introduce the audio folks here today. One of the things -- of all the things we're going to talk about today, I think you'll find the 3D audio stuff that we've been working on pretty exciting. We'll also go into the MIDI aspects of Core Audio and the multichannel reverb. So with that, let me bring up Jeff. Thank you very much.
Good afternoon. My name is Jeff Moore. I'm an engineer with the Core Audio Group. And today I'm going to tell you a little bit about how to use the AudioConverter API in the Core Audio -- in the Audio Toolbox. So the AudioConvertor API is for transforming audio data in one format into another format. We provide converters for doing rate conversion, integer to floating point, floating point to integer, interleaving and deinterleaving of multichannel data, and of course, encoding and decoding nonlinear PCM data.
So the, first I want to get into a little bit of how audio formats are described. The way we describe formats is common throughout all of the Core Audio APIs, so having a good grounding here will help you when you get into the more advanced APIs. The basic structure for encapsulating format information is the AudioStream Basic Description.
It has fields for describing the sample rate, the 4-care code, format ID, some flags to identify to specialize the format, and a bunch of other information that's important to know: how big the data is, what its channelization is like, and other information about how to process the data. In Core Audio, we use 32-bit floating-point numbers as the canonical linear PCM format.
In general, what you'll find is that everything goes to 32-bit float and then from there back into some other format. And like I said, both interleaved and non-interleaved multichannel data is fully supported. So you can take a buffer full of interleaved stereo and split it into two monobuffers or put them back together, whatever your needs are.
So new in the AudioConverter and Jaguar is support for encoded audio formats. And what I mean by encoded formats are formats that are not linear PCM. Examples of this are MP3 data, AAC data, AU, IMA, all sorts of stuff that is grouped together in -- that can't be separated apart. Encoded formats are typically dealt with in terms of packets of data instead of in terms of frames, like linear PCM data is. This means that you will be getting chunks of data that contain a certain number of frames of audio data in them.
[Transcript missing]
and David And then when you start talking about the MPEG-4 formats, you're going to start seeing that even more external description in terms of how the packets are broken up is also required to fully describe the data. And all the APIs that we've added to the AudioConverter and Jaguar fully support these mechanisms.
So, first thing you want to need to know is how to create and configure an AudioConverter to do what it is you want to do. So, here you see the way you do it. You basically just fill out the input format, you fill out the output format, and then you call AudioConverter new. And if there is a translation that can be built from your input format to your output format, the converter will create it for you and configure it and be ready to go to a certain extent.
Next, once you have the converter created, some formats of data, particularly encoded formats of data, require some external configuration information. In the API, we've turned this the magic cookie because the data is wholly private to the format and should under no circumstances be looked at by the application. You won't understand it anyway.
So, and the way you tell the converter about the magic cookie for the format you're encoding or decoding is quite simple. You just call AudioConverterSetProperty with the CodecParameters property. And it'll just get handed off to the appropriate encoder or decoder depending on the task you have at hand.
So there are other configuration parameters that you can change about your AudioConverter while you're doing it. One of the most common ones that you want to play with is changing the algorithm for rate conversion. Now, you want to do this for a variety of reasons. You want to trade quality for performance in a lot of cases, like in a game or something. And then you -- or in some cases, you may want the best quality possible. So here we see an example of setting the Converter Rate Converter algorithm to the polyphase, which is the highest quality rate converter algorithm we support.
Again, it shows up in the API as a property. You just call -- and it's suitably named AudioConverter Sample Rate Converter Algorithm. In the header file, you'll see an enumeration of the currently supported algorithm types. They include linear interpolation and a few others in addition to polyphase that have different tradeoffs in terms of performance for quality.
Then, once you have created and configured your converter, you're going to want to feed some data into it and get some data out of it to do the transformation that you're looking for. So, the AudioConverter actually provides three separate mechanisms for doing this. And the reason why is that not every mechanism is suited for your circumstance. So, you will want to pick and choose the most appropriate mechanism for what you're trying to do.
The first mechanism that we have is for simple data formats that have very simple data flow requirements. This is only really available for transformation where the ratio between the input buffer and the output buffer is both constant and an integer. What this comes down to, meaning, is that when you provide an input buffer, it has to be completely consumed to produce exactly the output buffer. Any other combination, you'll get an error from AudioConverter. from audio converter to convert buffer.
Here we see a simple loop that kind of illustrates the calling sequence. It's a very simplistic example, but it kind of gets across the flow. So basically the flow is while you have input data, you get a new output buffer, and then you call AudioConvert or ConvertBuffer with those buffers.
And previously, by setting up the conversion, you've already specified everything the converter needs to know to evaluate whether or not this call will succeed. You'll find these calls the most useful in the cases of doing linear PCM to linear PCM translations. A good example would be going from, say, 16-bit integer to 32-bit float.
So the next most common application is when you have simple data, but you have a much more complex data flow to deal with. In your application, you might have a thread, a producer thread that is reading data off a disk and putting it in a queue, or reading it from the network or whatever, and it's not necessarily going to be in a position where you're going to be able to say, here's the input buffer, here's the output buffer. You're going to need more logic involved with that. So the AudioConvertor fill buffer routine allows for this by providing an input data callback. So that will get called whenever the converter wants more input data to process.
Here's an example of calling AudioConvertor fill buffer. In this case, the input data is completely encapsulated inside the input data proc. There's no actual buffer handling about the input that goes into making this call. Once you define your input data proc, you just pass it in and then it will be called when the converter wants data from you. Then you'll give it to it and the conversion will happen, up to so that it fills up the entire buffer that you're asking for in your call to convert fill buffer.
Then in Jaguar, we have a new API that we've added to support more complex data formats like MPEG-4 AAC, among others. This was the most general of the calls in the AudioConverter. It's there for data formats that are much more complex than, say, linear PCM, or that require external packetization. This is also the API you need to use for interleaving and deinterleaving data. The API call itself is called AudioConverter Fill Complex Buffer.
Here's a simple example of how to call it. It looks very similar to the regular AudioConverter fill buffer call. The key thing to notice about this is that AudioConverter fill complex buffer operates in terms of packets of data. As you recall, I mentioned that encoded formats are almost always dealt with in terms of packets.
This is why the API is structured like this. What this implies is that you can only do I/O in terms of this API in increments of full packets. That's very important to consider, especially for encoded VBR formats where that's really the only way to do timing on the data.
So we've also wrapped up the AudioConverter into an AudioUnit in Jaguar. The AudioConverter, the AUConverter AudioUnit is basically something you can stick in your graph of AudioUnits and you can feed it data so that it can be converted and doled out to the rest of the graph in kind of a very unified way. It makes integrating data into the graph and getting it back out very easy.
I would be surprised if there aren't most of your graphs that you end up constructing include a converter unit of one kind or another. The most common example of a converter unit is actually the output AudioUnits, which are actually a subclass of AUConverter AudioUnit and provide that mechanism right at the output stage for the easiest way to get audio out of the system. Jeff Moore, Chris Rogers, Bill Stewart Also new in Jaguar, the AudioConvertor now will support a plug-in mechanism.
I will be speaking more tomorrow in session 508 about AudioCodec components and how they're written, how they're used, and what they do. But in the meantime, the SDK will be available. It's available now where now means sometime real soon. and it will include the Codec APIs and a set of C++ base classes for implementing audio codec components. In the seed of Jaguar that you have right now, this stuff is not currently supported, so you won't find it on the seed of Jaguar that you have now.
So that's pretty much it for the AudioConvertor. It's kind of an introductory to how it works. You'll encounter it mostly in terms of the AudioUnit Converter AudioUnit, but it's there for separate use as well. So next up, I'd like to bring up Chris Rogers, and he's going to talk a little bit about audio spatialization.
Hi. As Jeff Moore said, my name is Chris Rogers, and I'm a member of the Core Audio team also. I'm going to talk a bit about 3D audio technology, some of the stuff we've been working on at Apple here. I'm going to start off giving kind of a conceptual overview of 3D principles in general, psychoacoustic principles and that kind of stuff. And then in the second part, I'm going to go over our 3D mixer and our reverb audio unit, some more practical applications, and show some demonstrations of that.
So here I just wanted to show kind of where this top fits into the larger scheme of Core Audio here. And you can see in the AudioUnits section there the 3D mixer and the reverb. And we'll also be seeing a little bit of the AudioUnit views that are off to the right there.
So this diagram is... I kind of want to make an anchor point for the whole talk, so I'm going to spend a little bit of time trying to go over what I mean by this. This isn't the only way to break down...
[Transcript missing]
I'm making a distinction between more environmental type of sounds where you want to actually capture a spatial quality through a microphone recording technique, and then the guitar down there. It represents a type of a sound source which doesn't have any spatial information inherent in the sound signal, and where maybe further processing is applied to create a spatial aspect.
I think the reproduction...
[Transcript missing]
I'm going to go over a couple of principles, really basic principles of psychoacoustics, how human beings interpret spatial position of sounds. I don't have time to really go into enough detail to really cover this thoroughly, but I'm going to just cover some basic stuff.
Two of the really fundamental ways that human beings can tell the direction of a sound source is through interaural time difference and interaural intensity difference. A very simple spatialization model can be created called spherical head model based off that. More advanced models can be created that are called HRTF, head-related transfer function. Thank you. After that, I'm going to talk about how human beings interpret distance.
So, interaural time difference. What is that? Imagine a sound that's off to your right. Your right ear is going to hear the sound before your left ear does, simply because the sound wave arrives at the right ear sooner. The brain is able to use that slight delay to make a judgment on what direction the sound is coming from. This works only for sounds that are below about 1,000 Hz.
So sounds coming straight ahead hit both ears at the same time. Also, sounds coming from straight above do and from straight behind. So the brain knows that the sound is in the median plane. But for sounds that are extremely on one side or the other, the delay is quite pronounced, and we can tell the direction.
Another method that we use is called interaural intensity difference, and that's a frequency-dependent intensity difference between the two ears. So, for example, if once again we have a sound coming from the right-hand side, it will appear louder to the right ear than it does to the left ear.
And not only is it louder, but the left ear might hear somewhat of a more muffled sound because the head is blocking the high frequencies more than it blocks the low frequencies. and for sounds that are above around 1,000 Hz, the brain is able to use that information to determine the direction of a sound.
Don't worry about the details of this, but this is just showing that through simple rules of geometry, it's possible to construct a basic model using a sphere as a model for the head. The delay time between the two ears, depending on the direction that the sound hits the ears, and also using some basic
[Transcript missing]
HRTF, or Head-Related Transfer Functions, it's kind of related to what I was talking about with interaural intensity difference.
You remember when I was talking about having one sound off to the right, how the close ear is going to hear a louder sound, the left ear is going to hear maybe a more muffled, quieter sound. It's quite a bit more complicated than that, actually. And the outer ear, the fine structure of the outer ear, the complex folds of skin and so on, act as a highly directional filter.
So depending on the direction that the sound is coming from, how it hits the ear, the ear will filter that sound in a different way through various reflections in the skin and other things that are going on there to create a very unique signature of resonances and notches in the frequency response. And here in this diagram, this is just an example. I don't know what direction the sound was coming from, but you see a very deep notch there.
And it's possible under very highly controlled laboratory conditions to take probe microphones, place them in the ear canals, and make measurements playing sound through a speaker at various positions in the room, various angles relative to the ears. The microphones pick up the sound and the frequency response can be measured at these various positions, stored in a computer and a database. Later, these filters can be used to filter synthetic sound sources to create the illusion that sounds are coming from a particular position in space.
In fact, it's a combination of a filter for the right ear and the left ear. It's the combination of that that creates the effect. The playback generally has to be done on headphones for the best effect, but it can also be done on stereo. area speakers with certain compensation.
So how do human beings judge how far away a sound is? There are a couple different ways. If you're inside, maybe inside a large church or a hall, one of those methods is the ratio of direct to reverberant sound. So if a dog is in the very back of the hall, very far away from you and is barking, you're going to hear this really kind of reverberant barking sound.
If the dog is in the same hall but very close to you, you're going to hear more of a direct barking sound. You'll still hear the reverb, but that'll be less in the mix. Doppler shift is in effect when we're hearing moving sources. So if you've ever been walking down a sidewalk noticing the sound of cars rushing by you, as the car is approaching, the pitch of the whooshing sound of the car increases. And then as it passes by you and goes away from you, the pitch goes down, it drops. And so that's a very important cue for judging moving sources. And in our demonstration, A little bit later we'll hopefully hear that effect.
Another way that we use to judge distance is high-frequency drop-off due to air absorption. It's also just intensity drop-off. Generally, the farther away a sound source is, the quieter it's going to sound. and David Koehn. I'm going to talk about the different types of audio services that are available in Mac OS X. I'm going to talk about the different types of audio services that are available in Mac OS X.
I'm going to talk about the different types of audio services that are available in Mac OS X. I'm going to talk about the different types of audio services that are available in Mac OS X. The source will span a large angle as it's moving and
[Transcript missing]
and Diffusion is another effect, very, very, very far away sounds, maybe kind of diffused, kind of reverberant in a way.
So if we think back to that original diagram that I had up where we had the sound sources, the encoding, the reproduction, and the perception, on the left we had the sources. And there were two types of sources. I talked about maybe ambient environmental sources, the waterfall. And I'm going to call these intrinsic sources and use microphones to record these types of sounds. And there are various microphone recording techniques.
And in order to hear the spatial effect, there's little or no further processing necessary. You can just play it back on the speakers, essentially. And then the second type of source I'm going to talk about is I'm going to call synthetic or mono or dry recorded source. In order to create a spatial quality, we need to do some kind of synthetic processing, some kind of digital signal processing, in order to locate it in space or make it sound like it's in some kind of acoustic space.
So for these intrinsic sources, these environmental ambient sources, there are a couple different recording techniques. One of these is called binaural recording. Another is using a sound field microphone. And then there are many other ways that are commonly used with distantly spaced omnidirectional microphones or crossed directional microphones. I'm not going to talk much about those common methods, but I'm going to talk a little bit now about the first two. Thank you.
In binaural recording, we make use of the principle of the HRTF, the head-related transfer function that we talked about before. The way that this recording works is take a dummy head, a mannequin's head, with actual ears that are molded after human ears, and tiny little microphones inside of the ears. Somebody takes this head, believe it or not, into an environment where there are some interesting sounds with spatial qualities, and makes a recording, just a stereo recording, and then plays back this recording on headphones in order to recreate the original space, spatial effect.
Some people go so far as to have molds taken of their own ears, because the effect is actually better if you make a recording with your own ears compared with somebody else's, because there are actually large differences in the size and the shape of people's ears. This effect is highly sensitive on that.
Another interesting way of recording spatial information is using what's known as a sound field microphone. That records into Ambisonics B format. I'll talk a bit more about Ambisonics in the next slide. It attempts to capture the complete 3D pressure sound field, and it uses four microphone elements that are very tightly spaced into one capsule. It's a very finely jeweled piece of equipment. It's quite expensive, but it can make some really nice recordings.
So the Sound Field Microphone records into ambisonics format. Ambisonics is both a recording technique using the Sound Field Microphone and other techniques and a panning technique to synthetically spatialize sounds. And it aims to recreate the original sound field using all of the available playback speakers, whether that be two speakers, four, five in a surround system, or more speakers.
It has a nice quality in that it doesn't really require a sweet spot for listening as other spatialization reproduction systems do. And as sound is being panned around, the sound does not collapse into a single speaker. That's another nice principle. Other techniques like vector-based panning suffer from this problem, from moving sources.
The ambisonics encoding is a four-channel encoding, four mono-channels. Those channels are W, which is an omnidirectional component. It comes from the omnidirectional microphone. X is a front-back component. Y is left-right. Z is an up-down. So you capture the three dimensions plus an omni-component. It's possible to generate these W, X, Y, Z coordinates given a coordinate in spherical coordinates to synthesize the location of a synthetic source. We're going to show that in a demo in a little while.
Now we get on to the practical matters. I'm going to talk about the 3D Mixer Audio Unit. It's an audio unit that will ship in Jaguar. You should come to this session tomorrow where we talk in quite a lot of detail about AudioUnits. The Mixer is just another AudioUnit and it adheres to the same APIs and everything. I'm not going to really talk about the APIs today. The Mixer takes in mono inputs. It can take stereo inputs, but in my demo these are all mono inputs. It localizes each of these inputs in three-dimensional space.
There's one output bus. The stream format of the output bus depends on what type of speaker configuration you're applying to, whether that's stereo, headphones, 5.1, or whatever. There's an optional reverb that's in the 3D Mixer so that we can actually have more of a wet mix for distant sources, as we talked about in distance effects.
Each of the inputs can be parametrically controlled. The first three parameters are azimuth angle, elevation, and distance are part of a spherical coordinate system. Azimuth is, say, if I'm pointing straight ahead, as I trace my arm out to the right, I'm spanning positive angle in azimuth from 0 degrees all the way to minus 180 degrees.
And as I go to the left, it's negative. So, say, negative 10 degrees, negative 90, minus 180. Elevation is just going up and down. So straight ahead is zero degrees, all the way down to minus 90 degrees. And straight up is 90 degrees. Distance is measured in meters. It's pretty simple. There's also an additional parameter that's gain. It's measured in decibels.
As most AudioUnits, the 3D Mixer AudioUnit is configurable through properties. I talked about the parameters. The playback configuration needs to be configured through a property. The default is stereo, so if you know you're playing back through stereo, you don't have to worry about it. There's also a setting for the rendering algorithm. I talked about a couple of those, but in the next slide or two we'll see the list of them. Optionally, you can configure the source to have a Doppler shift. The playback configurations are listed here, and I think I've talked about them before.
and the rendering algorithms are listed here. For stereo playback, there are three different methods. The first is equal power panning. And this is the traditional type of panning that you see on a lot of mixing boards, where you just have a control that moves from left to right and it moves the sound from the left speaker to the right speaker. When it's in the middle, the sound comes from the center, between the two speakers.
The algorithm using the spherical head model is a little bit more sophisticated than that. It incorporates the interaural time difference and the interaural intensity difference using a very simple model of the sphere, as we saw in the picture, to attempt to position sound. It can work pretty well for certain types of sources. The third way is the most expensive in terms of the CPU. That's HRTF, to actually apply these measured filters, measured in the laboratory, to sources to position sound over stereo speakers or headphones, where it works the best, actually.
For more complicated speaker configurations like 5.1 Surround, we have two different methods: ambisonics method, which is what we're going to see in the demo, and also vector-based panning, which is an alternate method. So I'm going to move over to the other machine now and see if we can get some sounds going.
The interface is very, very simple here. You developers can imagine your own much more interesting looking interface, but I think it's fine for illustrating the principle. All of these sources, once again, are mono sources, so any kind of spatial quality is created by the mixer itself. You should be able to hear, in certain cases, the Doppler shift and also distant sources getting more muffled. Just general spatialization type of stuff I've been talking about.
[Transcript missing]
It can be configured as just an ordinary stereo reverb. That's the default configuration, in fact. Or a 5.1 surround reverb. And it has various parameters: room size, density, brightness, etc. We'll see in a minute some of those parameters. So there are a couple different ways you can use this in addition to just an ordinary stereo reverb as people have used in the studio forever.
There are a couple of different ways that producers today use surround reverb. One way is to actually have the reverb in all of the speakers with a separate reverberant stream in each of the five speakers. That's what we'll be seeing. Another way that producers sometimes like to use surround is to take an ordinary stereo reverb and put the stereo in the rear two speakers.
This could be used for this application, too, but we're not going to see that in a demo. Another thing that you can do is take a mono put it through a reverb,
[Transcript missing]
The surround reverb is an AudioUnit, and its output format can be configured either to five channels or two channels. and, as I said, if it's in surround mode, each of the five speakers will have a separate reverberant stream. So five independent reverb streams. So let's have a listen. So this is the dry sound right here. This is the wet sound.
and David I'm going to go over that too much because I think that Bill's going to have some fun with that a little bit later. I think that might be it. I think that's the end of my talk. So I'd like to introduce Bill Stewart. He'll play around a little bit more with this 3D stuff and also talk about some other interesting stuff that we've got going.
[Transcript missing]
Excuse me. I'm going to basically do a couple more slides then we'll get to a demo. What we decided to do with this demo is to show you how to assemble a processing graph of audio units. The source of the audio that you're going to be hearing is coming from the DLS synth, which is an audio unit in itself.
It's a special type of audio unit called a music device. It has some additional component selectors to get a MIDI message or MIDI raw data. We also have an extended protocol for turning notes on and off and controlling them. It gives you a much greater flexibility than MIDI does for scheduling note events in the synth.
In this graph we're going to take the reverb send from the DLS device rather than doing a reverb interpretation. Speaker 1: I'm going to show you a little bit of the DLS synth. I'm going to show you the DLS synth. I'm going to show you a little bit of the DLS synth. I'm going to show you a little bit of the DLS synth.
I'm going to show you a little bit of the DLS synth. I'm going to show you a little bit of the DLS synth. I'm going to show you a little bit of the DLS synth. I'm internal to the DLS. We're going to actually put it through a multi-channel reverb as Chris showed in his previous demo.
We'll take a dry, then we'll mix those two, and then we'll pass it through an output unit. We'll have five channels of out. Typically with a 5.1 system, as many of you know, a lot of 5.1 content won't have much content at all in the .1 channel. A lot of systems will have what they call a base management that will do a filter of the signal and push frequencies, typically at 80 Hz or below to the sub, and then take the rest of the feeds to the speakers. You could also have a low frequency effect in the system. That's a choice you make.
[Transcript missing]
This is the flow of the graph that we have, just to give you some idea of what we're doing. The DLS synth is outputting two buses, and on each bus it's a stereo bus. It's the bus that you would normally take through the reverb and the bus that you wouldn't.
So we put that through the reverb, and we've configured the reverb to give us five channels of output. And then what we want to do is to create a mix between the dry send of the reverb and the wet send that's been passed through the reverb. So we de-interleave the reverb stream.
And the three channels on that side, my right, your left, I guess, they're actually three mono channels in the demo we've got now. And then the one on this side is a two-channel. So the de-interleave is actually doing a stereo de-interleave and then three mono channels. Both of those go into the stereo mixer. We can adjust the volumes of those two.
That creates a stereo mix stream, which then gets interleaved back into the five channels that goes to the output. So with that, I'll get Doug to come up. And if we could have the demo machine just on this one. Thank you. So this is Doug White, in case you don't know. Round of applause for Doug. He's going to play some keyboard for us. So I'm going to probably make some horrible sounds at the moment just to give you... Oh, this is dry.
Have you... It's very wet. So if I turn this to zero, all you're hearing is a wet mix of the reverb itself. Can we just sort of jack up the back two speakers in the center? Um... So I can change the mix of the reverb to have both a mix between small and large room sizes.
So if I look at the small mix first, and I can change the mix between the small and large You'll get some tweaking on some of these parameters. Some of them you shouldn't change in real time, some you can. So if you hear any of those artifacts, that's for... you're sort of expecting that. Now I'm going to a fairly wet mix here. This is the size of the wet room.
Let's do that. You can hear that that's quite spacious, and you've got basically the dry signal from the reverb is only coming from the synth, it's coming from the left and right, and the reverb is coming from all five. One of the things I can do here is actually filter the sound that goes from the large mix, so I can push that down, which will make it... The audio interface here, that gets very muffled and it's like a room that's got a lot of curtains in it against a room that would be a bit brighter.
The two views that you're seeing here, the one on the left, multi-channel reverb view, this is made by a view component that is just what we call a generic Carbon view. What it does is it interrogates the AudioUnit and it asks the AudioUnit what's your parameters, what is their range, their default values, and so forth. It will just interrogate any AudioUnit and put up this view for you.
We'll be talking more about the view stuff in tomorrow's session. The one on the right is actually a custom view that I've made using the C++ base classes that we put in our SDK. I've just created a custom view for my mixer because I've got two ins and one output. Let's have a bit of fun here. I'll stop yabbing and get Doug to play some sounds.
[Transcript missing]
So, every sound that you heard was coming from the Mac. All that we have in the Mac. We decided this year, last year we showed a device from eMagic. It was a little USB device. It's about this big. It has six channels of out, two in. This year we thought we'd not want to show too much favouritism to any of our vendors because we love them all. We've got a Miniman 1010 card. There's drivers for this on Mac OS X, Delta 1010. It's a PCI card. We're just running five channels out of the box. That goes just straight into the speakers. There really is no tricks. Nothing up my sleeve.
This is just a list of some of the other forums that we've got. The Feedback Forum on Friday is a great place to come and yell at us for all the things we've done wrong and all the things we've done right, hopefully. There's a couple of sessions tomorrow using the basic levels of the system, both the audio and the MIDI stuff, at 3.30. And then at 5, there'll be some in-depth discussions about AudioUnits and the Codex, how to use the AudioUnit views.
And there's a short overview of AAC, which is also in your Jaguar seeds, in the QuickTime session at the same time as the Feedback Forum, which was good scheduling, I thought. So I think we do Q&A now. So Chris and Jeff and Doug will come up and... Go to the mics. Here's some URLs.
We have extensive developer support in Core Audio. We do lots of things. We have a mailing list that we're very active on, and you can get details of that at list.apple.com. We also try to keep our SDKs fairly up-to-date, and we have a website, developer.apple.com/audio, and we're constantly tweaking that. There you go.