WWDC2001 Session 209
Transcript
Kind: captions
Language: en
thank you for coming this is a session
on audio processing and sequencing
services and just before I bring Chris
Rodgers up is going to be doing most of
conversation just thought I'd welcome
you my name is Bill Stewart on the
engineering manager of the Chorio - if
you missed the talk yesterday we talked
just very briefly about the audio
hardware layer that we have in Mac OS 10
and all of this sort of fits in the
general frame of what we call core audio
and aside from the audio hardware stuff
yesterday we talked about the default
output unit as a way of very easily
having your application get up sound out
the current output device is selected by
the control panel so what we're going to
be doing today is to talk about Audio
Units and Chris will go through that in
a moment and the default output unit is
one of them so if you were at the talk
yesterday and a little bit confused
about well that fits in you should be
quite clear by the end of this talk we
hope so without any further ado I'll
bring Chris Rogers up from the cordilla
- thank you good afternoon pleased to be
here to speak with you a little bit
about some of the higher level services
available for audio on Mac OS 10
overview the talk is first thing I'm
going to talk about is audio unit
architecture audio units are components
for processing audio or just dealing
with audio in some general manner and
then I'm going to talk about the audio
toolbox hooking audio units together and
processing graphs and lastly I'll be
speaking about some timing and
scheduling services that are available
using music sequencing services so let's
take a look at where these higher level
services sit in our audio stack Audio
Units are one level above the core audio
audio how api's which Jeff spoke about
yesterday and then above that we have
what are known as the a you graph
services which are a set of API is for
connecting these audio units together
and the music sequencing services will
see can talk to au graphs and audio
units and core MIDI is off to the side
there and later on Doug will be going
over that in quite some detail I'm
actually showing how there are some
relationships between the MIDI services
and in some of the audio unit technology
that we provide so audio units are
components components that are handled
by the component manager that QuickTime
makes wide use of like all components
individual components are identified by
a four character type subtype and
identifier field and the component
manager can query a list of available
components of a given type Audio Units
are the ones we're interested in this
case so you can call find next component
to go through the list of available
components and then once you've gotten
to the one that you're interested in
opening you can call open a component
and to close it you call closed
component
and the component manager has some
pretty good documentation so you can
refer to our developer documentation
about the component manager for that the
audio unit component in general it
generates receives processes translates
or otherwise manipulates streams of
audio as I have my slide and they're
good high level building blocks that can
be connected together just to create
networks of audio processing and you can
also use them singly and just the for
instance instantiate a a software synth
and up and wire it up so this output
goes directly to the hardware we provide
a set of audio units that ships with OS
10 and we'll be adding more in future
and future releases and developers are
free to create their own Audio Units and
will be providing an SDK to make that a
lot easier than it would be otherwise so
what kinds of Audio Units are there
there are other units that just provide
audio data so they're sources they have
no inputs to them an example of that
type of audio unit would be what's known
as a music device it's a software
synthesizer and Apple ships DLS to
soundfont compliant software synths in
OS 10 also there are other units which
interface with the hardware they provide
a higher level abstraction of hardware
IO devices so they talked to the audio
how and one of the most common types of
audio units on the category of DSP
processors reverbs filters mixers this
type of thing so these type of audio
units typically they take input and
process it somehow and output the audio
stream another kind of audio unit is
format converter converting between 16
bits floating point
interleaving stereo streams into
discrete mono streams sample rate
converters and there you know quite a
few other types as well and then another
class
is what I call it after class of audio
unit and this is a little bit strange
because it doesn't actually process the
audio in any way using DSP and also
doesn't change the format of the audio
stream but instead it somehow does some
other kind of impedance matching between
the input and output for instance it may
do some kind of internal buffering so
that the input buffer size is different
from the output buffer size or it may
lay on top of a thread scheduling scheme
so that everything before that audio
unit in the chain would get deferred to
another thread and this way you could
potentially take advantage of multi
processing on multiprocessor machines is
very interesting application so I guess
we're gonna try running a little demo
here and I should probably explain a
little bit what I've done
oh this is your demo okay so if we can
have the machine oh I can't see anything
oh and neither can you
I can see this okay let me just get this
to run so
since the big tease
so what I'm actually running here is a
Java program the Java program is quite
simple and me just this is very
interesting trying to do it this way
this is dis demonstrating how to use the
component description and the component
services from Java it's the same as you
would do in C as we've been talking
about in those sessions you have both a
Java and C API to this I thought it
might be interesting just to show you
some simple Java code that is quite
clear about the concept of what we're
doing so we create a component
description this describes to the
component manager the type of components
we're looking for the type is okay audio
unit type and then what I'm going to do
here is I've just told it to look for
the first component of this type and
I'll use the au component which is
actually in this package in Java and
this will find the first one and then
I'm going to print out some information
about it and then I'm going to keep
finding the next component from the one
that I've already found until I don't
find any more and then my program
finishes so this will give you an idea
of the audio units that we ship with the
current version of system of this system
so there's delay some filters as a
matrix reverb in de levers D into
louvers a mixer unit there's the DLS
music device you can see it's type
subtype manufacturer there's the audio
device output to default output unit
which is actually an extension of the
basic unit that will talk to any device
to default output device will track a
default output that the user might set
and various others thanks go back to the
slides
and of course I can't see my screen okay
I just just before the demo I went over
some of the categories of audio units
and this is just a little simple diagram
showing that not even it's a basically a
box that can have an arbitrary number of
inputs arbitrary number of outputs and I
think this diagram is showing that DSP
FX would have both inputs and outputs
with some kind of processing going on
software synth music device may only
have outputs because it's actually
synthesizing sound was creating it from
scratch a default output you know which
Doug talked about yesterday it would
just take inputs and it would send that
audio to a hardware device talk about
audio unit properties properties are
very very fundamental to the way that
Audio Units work and a very general and
extensible way to pass information to
and from audio units out of units
themselves they implement a very small
set of functions which which can be
called to deal with getting audio in and
out and setting parameters and so on but
we created this property mechanism to
allow other units to be extensible so
when we come up with some new feature
that audio units need to implement we
can always use the the property api's
and pass in data via void star pointer
and the length of the data is indicated
by a byte size parameter the we define
several different properties today and
the type of property is identified by an
audio unit property ID
it's just 32 bit integer both the MIDI
API is in the audio how API is also
support this concept of properties it's
almost identical type of mechanism in
the API between a three
secondary to the the property identifier
identifying which property we have
addressing within the audio unit to tell
which part to specify which part of the
audio unit is to deal with the property
so there's a scope which can be global
input output or group global means that
the property applies to the audio unit
as a whole input scope means the
property applies to a particular input
output is pretty clear and group is a
particular type of scope that is
relevant for software synthesizers music
devices audio unit element is an index
specifying which particular input output
or group we're identifying so if we want
to talk to input number two then this
argument would be 2 or actually it would
probably be depending on how we're
numbering starting at 1 or 0 the IDs are
defined in audio unit properties that H
and it's important to understand what
the data formats of the properties are
because we're just passing information
as a void start pointer and a length
parameter you have to understand the
structure of the data so those data
formats are defined also in the header
file we have a couple properties defined
right now and additional properties will
be added as needed and developers are
free to implement their own private
properties for their own Audio Units and
there's a range of reserved property IDs
for that but all audio units should
support the general system properties so
yesterday at Jeff's talk somebody was
interested in knowing about the
performance capabilities of our system
and somebody asked about well how many
audio units can you connect together and
is there going to be a problem well the
que audio unit property fast dispatch
property is a way of getting access to
function pointers which call directly
into the
audio unit and this bypasses the
component manager dispatch overhead that
is typically encouraged so basically
you're just dealing with function call
overhead when you're doing your
processing it's no different from any
other kind of DSP you might be doing in
your own code so really the time the the
bandwidth limiting factor is actual DSP
that is occurring so the answer to the
question of how many units can you
string together is really a function of
well how much processing are you doing
among all these audio units it's not a
limitation of the Audio Units themselves
this particular property can be used as
an optimization but you're not required
to use it here's the second example of a
property and that's the the K music
device property sound bank FS spec this
is a way of telling the software
synthesizer which sample bank it should
use so you identify the sample bank with
an FS spec pointer and you pass that
information in by calling audio unit set
property and the first argument is the
actual component instance the second
argument is the property ID the sound
Bank at that spec ID then it's global
scope because it applies to the simp as
a whole the element doesn't really
matter in the case of global scope
second to last argument is pointer to
the file spec and then the size of the
of the data is the size of the FS spec
so that that shows you how you can
communicate property information to an
audio unit without a unit step property
and all properties are dealt with in a
similar way
of course the specifics of what the
property information is and what it does
will vary parameters are less for
configuring attributes of audio units
and more for changing real time control
points and we have the audio unit get
parameter and audio units set parameter
functions for this
allows real-time control of processing
algorithms the parameters are identified
with audio unit parameter ID and the
value is a 32-bit floating-point number
and these parameters are very similar to
MIDI continuous controllers but they're
much more resolute there are 32-bit
floating-point numbers as I pointed out
and it's much much higher resolution
than seven bit MIDI value the set
parameter function includes a timestamp
allowing the audio unit to schedule the
parameter change for a very specific
time within a buffer of audio so the
timestamp is in units of sample frames
on the next buffer of audio to be
processed an audio unit supplies its
list of supported parameters with the ke
audio unit property parameter list and
individual parameters can be queried
with the parameter info property and
information such as the name of the
parameter what units the parameter uses
whether it be Hertz cents decibels
whatever min Max and default value for
that parameter and some flags as well
and information provided by this
property could be used by a client to
put up some kind of user interface
representing this particular parameter
so if the parameter represents volume in
decibels or something like that from
maybe I don't know - 150 decibels up to
zero DB or who knows the control is
actually able to display the the units
and the minimum and maximum value
appropriately I'm just information Audio
Units are in one of several states and
it's important to understand the state
transitions that Audio Units go through
when an audio unit is first opened with
open a component it's considered to be
an open State once the component is
closed then it doesn't even exist
anymore
so that's kind of like the base level
constructor destructor
if you're thinking in object-oriented
terms but there's an additional level of
construction and destruction and Audio
Units that's the initialized and
uninitialized state and we have the
audio unit initialized and audio unit
uninitialized functions for that
once the ADI unit is initialized you can
actually start it start at running with
audio unit start and that applies
specifically to io audio units such as
the default output unit actual actually
start the hardware through the audio Hal
so let's go into a little more detail
about what's the difference between just
opening the component in the first place
and initializing it it seems like it's
the same thing well when you open the
component you have a component instance
and you can make calls to the component
but at this time the component is not
expected to allocate any significant
amount of resources such as memory but
you are able to make property calls to
the audio unit to configure it in some
particular way for example you might
want to configure it sample rate or bit
depth or maybe you're interested in
setting up some other aspect of the
audio unit before you actually
initialize it then once you call audio
unit initialize and you've made your
property calls to configure it just like
you want then the appropriate
allocations can occur optimizing for the
particular configuration so if you're
configuring a reverb for a certain
number of delays or something like that
it's able to allocate exactly the amount
of memory it needs so the running state
this is what audio is actually being
processed it's actually going through
from input/output an audio unit or the
hardware it's running whatever the case
may be and the audio output unit
implements the audio units start and
other units stop functions
and if you have a graph of audio units
connected together this this is where
the audio actually starts being
processed or stops being processed and
it the audio output unit generally
represents the terminal node in a
connection and as Doug talked about a
bit yesterday the default audio unit it
starts the hardware device that the
audio Hal is connected to here's another
API to Audio Units audio unit reset it
basically is used when an other unit is
initialized and it may even be running
but if you want to clear the state of
the audio unit it's typically used with
DSP Audio Units
so for delay effects you would clear the
delay line for reverbs you would clear
out the reverb memory for filters you
clear the filter State and this is
important if if the graph is actively
processing audio but you perhaps
reposition the playhead to a different
part and the audio stream and you don't
want reverb tail from from a later part
of the of the score to be appearing in
the in the mix
audio unit IO management audio units
process audio or deal with audio using a
pole IO model and what I mean by that is
that there's a function a particular
function you call to be the audio output
stream from the audio unit and when you
do that the audio unit has to go and
fetch its audio input so it typically
does that by calling the same function
on the output of another audio unit and
then that audio even has to get its
audio input from somewhere so if you
imagine a chain of these audio units
connected together one after the other
you would pull on the very end one and
in turn it would go down the chain each
one would fetch its input from the one
before and you pull the audio through
the chain it's possible to connect these
audio units up in more complicated
configurations than just simple linear
chains but the idea is still the same
the audio is pulled through to the
terminal node which is typically ending
with the hardware output device all
units specify their number of inputs and
outputs through properties and the
format of the audio data is canonically
it's N channel interleaved audio or it
could be signed sideband data such as
spectral analysis data and this is
linear PCM 32-bit floating-point
okay I've been talking about connecting
these outer units together and this is
just a picture showing that so I'm going
to talk about how to get audio into an
audio unit and then I'm going to talk
about how do you get audio out of an
audio unit so there are two ways to
provide an audio unit with its audio
data the first way is using a property
called a audio unit property make
connection and with this property you
specify a source audio unit and its
output number and then that connection
is made and the audio unit knows that
it's to read its audio data for a
particular input from another Audio
Units output a second way of providing
audio data to an audio unit is by
registering a client callback and this
is the standard sort of callback that we
get in the audio Haller and the sound
manager or in many other audio systems
such as a CO and the in this using this
method the the client just specifies a
callback function and then every buffers
life cycle this callback function is
called and the client is able to provide
the audio for a particular input of an
audio unit and in the case where audio
units have multiple inputs each input
may be configured separately using
either of these two methods so our unit
has two inputs
first may be connected to the output of
another audio unit in the second input
may be connected up with a client
callback so that audio is provided
directly by the client in this case I'm
going to be talking soon about the a you
graph API which is a higher level
abstraction for connecting these audio
units together so I've just gone over
two ways that you provide audio input
data to the audio unit now it's
important to understand how do you
actually get the rendered audio out of
the output
and you have to use the audio unit
render slice function call for this it
pulls the audio or reads audio from a
particular audio unit output and it must
be called once per output so if there
are three outputs then it would be
called three times each audio output can
be an n-channel interleaved stream like
I said before so it's possible that an
audio unit might just have one output
and provide actually eight discrete
channels internally in that one output
let me go over some of the important
arguments to the audio unit render slice
function it's actually very similar to
the the audio Hal callback arguments the
audio timestamp it's exactly the same
audio timestamp structure as an audio
Hal and it specifies the start time of
the buffer that is to be rendered it
provides information about host time the
current host time of the machine or the
host time that corresponds to the start
of the buffer along with the sample time
that that corresponds to so it's
possible to synchronize other system
events such as MIDI events which use
this host time to the audio stream which
are synchronizing based on sample time
the audio buffer argument is where you
can pass a buffer that you expect the
audio unit to render into or optionally
you can pass a null for this and it will
pass back a returned buffer that it did
it caches and let me just
the audio buffer is also a structure
that's used in audio house so we we
share we share the same data structures
between the high level and the low level
parts of the audio stack so with audio
unit render slice
it's optionally possible to schedule
events before a given IO cycle so before
audio unit render slice is called you
may want to do some scheduling parameter
changes with Audio Units set parameter
or in the case of software synthesis you
might want to schedule some notes to
start or stop playing during that that
slice of audio so there's its two phase
scheduled render model and step one you
would schedule events and in step two
you call audio unit render slice an
advanced feature of the rendering model
is the pre and post rendering
notification mechanism it's an optional
callback that a client can install on an
output of an audio unit which gets
called before rendering occurs and after
rendering occurs so every time that
audio unit render slice is called the
audio unit will call this notification
callback do performance rendering and
then call the callback again to say that
it's done rendering and this allows the
client who installs this notification to
perform arbitrary tasks some examples
would be scheduling which you might do
in exactly the same way as it's as I
described here before every render slice
and another use that you might make of
this is to perform CPU load measurement
you can actually measure the time that
the audio unit takes to performance
rendering so how do you write one well
how do units are components
the same kind of components that have
been used in QuickTime for a very long
time so anybody who's familiar with
writing components in QuickTime should
be able to get up and running pretty
quickly with Audio Units for people who
haven't written components before it can
be a little bit difficult unless you
have some help and we have an SDK that
makes this very simple all you really
have to do is override one or two basic
functions and in fact at the base level
you really only have to override one and
that's the function which does your
actual DSP processing if your audio unit
is as a processing type of audio unit
and this SDK will be placed on our
website soon in the next few days we
hope so finish talking about Audio Units
at the lower level I'm going to talk
about a you graph this stands for audio
unit graph and this is set of API is for
connecting these components together
represents is a high level
representation of a set of other units
and the connections between them allows
you to construct arbitrary signal paths
fairly arbitrary anyway and represents a
modular routing system and it can deal
with large numbers of them why use a you
graph one of the reasons is that
connections and disconnections between
audio units can be performed while audio
is actually being pulled through the
chain and if you are talking to the
audio units at the lower level you have
to take great care at at changing
connections distant making connections
and disconnections while the audio is
being pulled through you can get all
kinds of bad things happening there's a
lot of synchronization involved and a
you graph takes care of this for you
another reason you might want to use a
you graph is that it maintains a
representation of the graph even when
the audio units themselves are not
instantiated and it also takes care of
and embodies the state that the audio
units are in as we'll see
hey you note is primary object that's
represented in a you graph an au note
actually represents a particular audio
unit in the graph whether that outer
unit is instantiated yet or not it's a
placeholder representing that audio unit
to create a node you can call a u graph
new node and argument to this function
is a component description which
specifies the type subtype and ID of the
component this is this information that
you would get from fine next component
component manager call it's also
possible to pass this what we call class
data to initial initialize an audio unit
width and we'll talk about that in a
minute
may you graph remove node just takes it
out of the graph to create connections
between these nodes once you've added a
bunch of nodes you've got to connect
node input disconnect note input clear
connections that clears all the
connections in the graph and update for
synchronizing real time changes you can
also walk through the graph and look at
all the nodes with get node count get
ant node get node info these are in the
hey you graph H header file in our audio
toolbox framework and I think that the
api's are fairly self-explanatory if you
looking at header file so we're not
going to go into detail with all the
arguments just like the audio units
themselves the a you graph mirrors the
state of the other units in them and I
and this slide is just pretty much going
over what I talked about concerning the
states of audio units here an important
thing is that a you graph state
corresponds with the audio unit state
so the state API is through our graph
our graph open close so a you graph open
when you call that it actually opens all
of the audio units represented by the
nodes in the graph and close closes all
the audio units and correspondingly
initialize on initialize it calls the
audio unit functions and start and stop
same thing in addition there inspection
or introspection API is how you graph is
open is initialized is running so you
can determine what state the graph is in
oh this class data when an au node is
added to the graph it's possible to pass
arbitrary data in with a void star
pointer and a length similar to the
properties and if you add this
information this optional class info
when the audio unit is opened a property
call will be made on the audio unit with
this data and the audio unit is able to
make use of this data in any way that it
wants it's there's no data format that's
defined currently for it but it's a way
it's a way to maintain persistence
because when the graph is closed
data can be gotten from the audio unit
and stored in the node so it can be
recreated in the same configuration that
it was so a little bit earlier I tried
to explain the notion of this head audio
unit in a graph in a very simple case
you would have a chain of audio units
say you might have three first one
connected in a second
connected to the last one the third
audio unit which is maybe an output
device and this last one represents the
head of the graph and we talked about
the pole map model the head audio unit
is very important because it controls
the hardware it controls what the
processing is is being pulled through
the graph or not and so there are
special audio unit API is our unit start
and stop which I talked about before and
the AU graph
has corresponding calls a you graph
start and stop okay done talking about
audio units and a you graph so finally
I'm going to talk about some sequencing
services for performing scheduling a few
slides back I had a diagram up showing
the schedule render model we're in step
one you schedule events to audio units
and secondly you would render a slice of
audio the music sequencing services
actually would be one mechanism where
the scheduling could occur it's a simple
API for creating and editing multitrack
MIDI sequences individual events in the
tracks can address Audio Units and
software's synthesize their music
devices it provides a runtime for the
playback of these sequences and has a
bunch of api's for doing live edits cut
copy paste merge this type of thing so
while the sequence is playing you can be
editing it's important in a sequence
their application be able to do that for
those developers who already have a
sequencing engine in their application
this set of API is might not be so
interesting but for somebody developing
a new application because the api's are
there for doing the basic edits and for
actually providing the runtime system
for playing back the sequences it's only
necessary to write a UI which is not
necessarily easy but if you're good at
writing UI
at least you don't have to write all of
the underlying engine which can be
difficult sometimes the scheduling uses
units of beats and it's floating-point
32-bit numbers representing
beats and it can also represent
represent seconds to in certain cases
there's a tempo map for converting
between the beat time and real time
seconds API is for reading writing
standard MIDI files tracks have
attributes you can mute solo loop tracks
the music player is the highest level
object and it provides transport so you
can you can seek the sequence to a
particular time and start the sequence
playing as top of the sequence playing
with the music player and it provides
the appropriate synchronization between
host host base processing and MIDI music
sequence is the next level object and a
music sequence contains multiple
playback tracks which are called music
tracks each music track contains a
series of time ordered time-stamped
events and each music track with these
events addresses a particular au node in
in the a graph that we spoke about
before so for instance if you have a
graph with a software synth
there would be a node representing the
software synth and one of these tracks
might be addressing its events to the
software synth there might be another
audio unit in a graph which is a filter
of some kind there might be another
track which is addressing parameter
changes to the filter to sweep to the
filter cutoff
there are also attributes to the track
commute solo as I said before you can
set up the loop length number of
repetitions of the loop and also offset
the start of the track relative to the
other tracks there are several different
types of events the most basic one is a
MIDI note message
it's MIDI note number with velocity MIDI
Channel and a duration the note off is
not a music event as such it's implied
in this MIDI note message using the
duration there's a MIDI channel message
for all the other channel messages
there's raw data for a system exclusive
there's a tempo event for doing tempo
changes and there's this extended note
API which is very much like the MIDI
MIDI note message but it provides for
more sophisticated control and esoteric
applications MIDI note event only has
the note number and velocity and a MIDI
channel associated with it and this
extended note event allows for an
arbitrary number of floating-point
arguments to be associated with the
instantiation of a note not everybody
may be interested in that but it's there
the extended control represents a 32-bit
floating-point parameter change and
ultimately it may end up calling Audio
Units set parameter at the exactly the
right moment in the audio processing for
sweeping filter for changing volumes for
panning positioning audio all different
kinds of parameter changes there's also
a user event to arbitrary data can be
placed and meta event for MIDI so here's
the one example there are there's an API
corresponding to each one of these types
of events and all of them are very
similar to this one so I'm just going to
go over the one this is how you add a
MIDI note event the first argument
is the the music track you're adding the
event to the second argument to think
they got the arguments wind up a little
bit funny but the second argument if you
can make sense of that is the timestamp
it's 32 bits actually I think it's a 64
64 bit it's a double precision timestamp
representing the beat and then you have
a pointer to a structure the MIDI note
message structure which essentially just
has the note number velocity
MIDI channel and the duration of the
note in it so this is a diagram showing
how you can have a music sequence with
multiple tracks three in this case where
each track is addressing a separate
audio unit in an a you graph and this
corresponds with the previous diagram
the two-phase schedule render model if
you remember there are some editing
api's for copy cut paste this type of
thing and I think if you look into music
player dot H header file and audio
toolbox framework it will be very clear
how to use these one of the lowest level
objects in music sequencing services is
a music event iterator and it allows you
to actually walk through the events in a
track see what they are and it could be
useful if you're writing sequence or
application you're writing the UI
sitting on top of this engine for just
walking through the events seeing what
they are so you can display them also if
you want to create custom editing
operations on track you could use this
music event iterator to walk through all
of the events in a particular time range
so there are a couple different api's
for dealing with these iterators you can
the music event and Reuter is a
first-class object so you create it with
new and dispose and you can seek the
iterator to a particular point in the
track it finds the first event at or
after the time that you're seeking to
you can move the iterator one event
forward in time with next event one
event previous with previous event and
you can actually ask the iterator if
it's at the end or beginning of a track
what has previous event and has next
event then the music event iterator get
event info function can be used to find
out what type of events you have at that
points so you can find out what the
event type is what time the event occurs
at and you get a void star pointer which
you cast to the appropriate event type
to get access to the particulars of that
event for instance if it's a MIDI note
event you can find out what it's no
numbers so on you can delete an event at
the point where the iterator is or you
can change the events time okay I'm
going to play a demo it's kind of kind
of a little bit vague what I'm trying to
illustrate here but I think what I'm
trying to show is how all of these
services work together so in the example
I've created a graph I have a software
synth the DLS music device it's loaded
up with a twelve string guitar sample
Bank and it's playing through kind of an
arpeggio really quickly and then I have
some additional audio units in the graph
I think there's a digital delay in there
there's a limiter look-ahead limiter
node to keep the volume pretty steady
and there's a reverb at the end and I
also have a bandpass filter in the graph
whose center frequency I'm sweeping
using the music sequencing services so
I've set up music sequence and have one
of the tracks addressing the node in the
graph
which is the bandpass filter and
sweeping that around and it basically
just ends up sounding like some kind of
ethereal wash but you should hear that
there are these kind of filter sweeps
going in and out and there's a reverb in
there for sure and let's see if I can
weight this machine up and get this
going here okay got my cursor
unfortunately it's not nearly as
impressive as Jeff Moore's multi-channel
demo the other day but this will give
you an idea okay it's I'm only launching
an application actually it's it's
nothing too visual it's just to hear but
I'll I'll show you double click and you
should hear something
[Music]
[Applause]
[Music]
[Applause]
[Music]
so it's a little bit vague but thanks
but it's showing it's showing all the
parts of the system that I talked about
I think bill I'd like Bill Stewart to
come up and he's gonna show us some some
more demonstrations and talk about the
Java interfaces thought I'd might
mention that all of that sound you hid
was just some nerds coming from the tall
string guitar so it's pretty interesting
I think now if I can have the demo
machine but I've got to get my mouse to
somewhere
okay so okay I'll just get this guy
running and
this is cool I can just show you what I
want to show you so this is my java
application and do we have sound coming
out from this
so I'll very quickly walk through the
code with you after this basically I'm
using a sound font that we got the same
sound font the criticism from mu which
is a 12 string guitar and I've written a
java application and we'll go through
the MIDI side of this in the next
session and I'll go through the audio
unit or graph cited in this session and
basically the media application is
listening to the MIDI point getting the
MIDI in messages from this keyboard and
telling the music device to play notes
in response to keyboard input I'm
actually guitarist so I had to use the
12 string and I'll probably have to do
[Music]
[Laughter]
so I'm going to quit this guy and let me
just bring up the project and you have
to just bear with me while I find it and
this will give you sort of some feel for
how this this code looks that Chris has
been taking talking about things so let
me just move it over here look what's
going on
okay so I can barely see what I'm doing
here
alright so there's a bunch of stuff here
just to sort of set the thing running
I'm loading the sound Bank here which
I've just installed with Mac OS 10 we
also wanted to make sure that there were
directories that were available as
standard places for you to put standard
resources that you may want to share
between different applications so in
this case I'm putting the sound bar a
sound Bank in the slash library audio
sounds banks and then this is the name
of the sound font file here and there's
also a mirror of this directory in the
users directory as well so sound banks
that were stored here would be available
to any user that came onto the machine
so you might imagine like a lab where
you could have a setup that you want
available to every user and then
individual users can have their own
sound banks in their own user version of
this thing and there are fine folder
constants that you can use for look for
these in systems that have been
localized and there's other folders
there for audio units themselves if you
want to make them available for
different types of sounds there's a
whole bunch of MIDI stuffie that I'll go
through later on and what I want to show
you is just basically how the graph is
set up and we'll just ignore the first
thing so this constructor here is
creating the graph and that just calls
through to the C API to create the graph
here and then this is me creating two
synth two nodes one for the DLS music
device and i give it a component
description and I already know what I'm
looking for here I could use the find
component stuff to actually hunt around
for components I'm just creating two
nodes I'm creating a music device and
I'm going to use the DLS synthesis the
the that one for that and yeah we're
very hopeful to see other music devices
from you guys like you know some
acoustic modeling synthesizer devices
and
all that kind of stuff and if I get the
mousepad here and then the second one is
the default output unit I'm just going
to create that because I want the sound
to actually come out of the computer and
then to connect those I just tell the
graph to connect the node the output
from the synth into the input of the
output node and just to show you that
there's some stuff going on with the
graph after I create the graph I'm going
to get the note I get the node count
here and I get the index node starting
from 0 to the number of nodes and I'm I
print that out and I can show you what
that guy looks like so you can see there
that it's telling me I've got two nodes
and there's a component which is the
music node and the default output node
and I've lost my mouse again notice ok
so after I do the connection of the
nodes I'm going to open the graph and
this will open the audio units and that
will actually it's really a constructor
until you do open on the graph you don't
have an audio unit you just have the
node itself it's an abstract
representation of the graph so when I
open the graph I can ask the graph to
give me the audio unit that's associated
with a particular node and if we have a
look back up here you'd see that I had
kept this guy around I could actually go
and look in the graph and find out the
nodes here and I could ask her for
information but I've kept this note here
so I know that what I want to do is get
the music device which is a subclass of
audio unit for that particular node and
what we do in the cord
Audio Driver API is is we actually give
you the subclasses that correspond to
the extensions of the component
selectors so you could have a basic
audio unit which is your parent class
and you've got an extension of that was
your output audio unit another extension
is the music device and that in
component terms just provides additional
component selectors additional
functionality if I've specified a sound
Bank which I'd be kind of bit lame if I
didn't then I'm going to set the
property of the sound Bank on the music
synthesis is a convenience routine in
Java does the same thing as what I
crocheted in the C file and it just
takes the Java file i/o object it does
all the necessary conversions to the
native structures and instantiate that
and you notice that I'm doing this when
I've opened the graph but before I
initialize it so this is one of these
things where this is a property that we
want the synthesizer to have when it's
initialized and until the Center is
initialized it's not going to try to use
a particular sound bang until you
initialize it and then just to get the
synth sort of up and running I'm going
to set some default volume and channel
stuff and there's some commented out
code there I'm not going to worry about
and because I want this to be responsive
I must have acquitted tonight so because
I want this to be responsive what I'm
actually doing at this point is to get
the the audio device output unit which
is the default output unit that I'm
sending out to and from that guy I'm
going to get the device that it's
attached to and I'm going to set its
buffer size so that's going to basically
take the default callback buffer which
is about 11 milliseconds 512 sample
frames and I'm going to set that to 64
sample frame so the responsiveness of
the system is about 1 and 1/2
milliseconds so I get creating a memory
object that I can pass that information
in and then I just set the output
properties straight on the device
so I get the device from the output unit
and it's actually a device output unit
and I set the property to 64 frames
which is 64 times 2 because it's a
stereo device times 4 which is the
number of the size of the float and of
course in Java you don't do size of
light because
it's Java and not serious math and then
I actually get that property as well and
I print it out and you can see if I can
find my mouse and you can see there that
it's telling me that the buffer size for
the i/o clock is 512 which is what we'd
expect 64 by 2 by 4 so that's all we do
and then after I've set the buffer size
up and I've initialized the synthesizer
I then just start the graph and that
will start the device that will start
pulling through the chain and away we go
and then in the next session I'll go
through how I you set up the MIDI
pausing stuff so that I can actually
send MIDI events to the music device so
I can we go back to slides ok so just
some notes about the Java there's also
Java doc available on the on the website
we're also preparing a PDF of just the
core to architecture itself and they'll
be available at the web site early next
week
and as we stressed yesterday we sort of
look at coreos basically an architecture
that you should understand how it works
and that's really a language neutral
feature that the job and the C API is
represent the same API to the same
functionality that's implemented
underneath and in a variety of different
ways so we also have a mailing list it's
at least our apple.com it's called core
do api and we welcome you to involve
yourself in that mailing list and it's a
good way to send information to us and
we will answer questions on that list
and there's a website I don't know if
it's completely up yet if it's not up
today will be over the next few days
developer.apple.com slash audio and
there's some related sessions for the
DVD viewers of this wonderful thing and
the next session which should be MIDI
is at five o'clock today audio services
and Mac os10 was yesterday and there's a
sound networking ghost before this one
if you're have any questions related to
firewire in USB
there's a lot of fire wire a lot of USB
audio devices and many devices and stuff
that's coming out you can contact Craig
Keithley Keith lead Apple comm if you're
interested in in seeding we obviously
you know constantly working on these
technologies if you're interested in
getting access to that before we release
it publicly you can contact us at audio
Apple comm or talk to your developer
tech developer relations manager and
inquire about seeding
you