Release 2.0  Copyright ã1991 by NeXT Computer, Inc.  All Rights Reserved.

Chapter 5
Music Performance

This chapter describes the classes and functions that you use to create a musical performance with the Music Kit.  The material presented here falls roughly into three sections:  realizing music data, Music Kit scheduling, and guidelines for building an efficient application.  To fully appreciate this chapter, you should be familiar with the material in the preceding two chapters, Chapter 3, ªRepresenting Music Data,º and Chapter 4, ªMusic Synthesis.º

Design Philosophy

The primary task in a musical performance is to take a representation of music and render it in an appropriate fashion.  Traditionally, this task is met by a performer wielding an instrument.  Similarly, the Music Kit has its Performer and Instrument objects:  A Performer obtains a Note object, either by reading it from a database such as a Part or scorefile or by improvising the Note itself.  The Performer then relays the Note to an Instrument that provides the machinery for rendering, or realizing, the Note.

Of Instrument and Performer, the former is the more crucial to a Music Kit performance.  Realization is the whole point of a performance, thus Instruments are ubiquitous.  Performers provide a convenient means for acquiring or generating Notes but they're not essential to a performance application; in fact, some applications can't use Performers but, instead, must manufacture Notes themselves and send them directly to Instruments.  In any case, the means by which a Note is acquired is separated from its means of realization and the mechanism for connecting an agent of acquisition to that of realization is extremely general.  Specifically, any Performer (or your application) can be connected to anyÐand any number ofÐInstruments.  These connections can be created and severed dynamically, allowing you to create a kaleidoscopic network of Note sources and destinations.

With Performer and Instrument, the Conductor class completes the triumvirate of preeminent performance classes.  A Conductor object acts as a time keeper as it determines the tempo of the performance and starts and stops groups of Performers.  Essentially, a Conductor is a timed-message sending object that dispatches Objective-C messages at distinct times (in this regard, it's similar to the timed entry mechanism of Display PostScript, but with a more sophisticated interface).  For example, it's through a Conductor that a Performer schedules the messages that relay Notes to an Instrument.

Asking a computer to perform music often pushes it to its computational limits.  Because of the demands of music performance, the Music Kit provides hooks into the operating system that allow you to create applications that can run with heightened priority.  While this can sometimes be a dangerous gameÐit isn't easy stopping a highly charged fugue that has jumped the railsÐwell-debugged and fine-tuned applications will find great benefit in these enhancements.  

Performance Outline

A Music Kit performance can be divided into three phases:

·	Preparation:  You must determine the sources and destinations of the Notes that you wish to perform and establish other characteristics of the performance.

·	Commencement:  This is always accomplished by sending startPerformance to the Conductor class.

·	Termination:  This is achieved by sending finishPerformance to the Conductor class.

This sequence of activities can be repeated any number of times while an application is running.  While a single application can have but a single performance in progress at any particular time, that single performance can do any number of things.  For example, if you want to capture MIDI input as a scorefile while playing along to a Part that's synthesized on the DSP, you perform both tasks in a single performanceÐyou don't have to set up separate environments.  Obviously, the two endeavors involve different classes of objects, but when the Conductor class receives the startPerformance message, everybody starts wheezing.

Much of the work that goes into a performance is involved in setting it up; in fact, many of the methods that are defined by the classes that are involved in a performance can only be invoked before the performance starts (or between performances).  As you design your own application, you should consult the class descriptions in Chapter 2 of Reference to check for the conditions under which a method may be invoked.  

The following sections examine the three primary classes involved in a performance:  Instrument, Performer, and Conductor.

The Instrument Class

Instruments are the agents through which Note objects are realized.  Since realization is the ultimate destiny of a Note object, the Instrument class is the ultimate focus of a Music Kit performance:  Every performance involves at least one Instrument.

At the heart of an Instrument is its realizeNote:fromNoteReceiver: method.  The Instrument class itself is abstract and doesn't implement this method; it's the responsibility of each Instrument subclass to provide an implementation of realizeNote:fromNoteReceiver: to establish the manner in which instances of the subclass realize Notes.  The Music Kit includes a number of Instrument subclasses (and pseudo-Instruments) that realize Notes by synthesizing them on the DSP or an external MIDI synthesizer, and that store Notes by adding them to a Part or Score or by writing them to a file.

One of the principals of Instrument design is that an Instrument doesn't create the Notes that it realizes.  Instead, it realizes Notes that are sent to it by another object or by your application.  The machinery by which an Instrument receives Notes is well defined by the Music Kit; unlike that for Note-realization, you don't reinvent the Note-reception mechanism for each Instrument subclass.  

The following sections examine the Instrument class according to its two tasks:  receiving and realizing Notes.  The latter topic centers upon descriptions of the Instrument subclasses included in the Music Kit, followed by an example of Instrument subclass design.

Receiving Notes

An Instrument receives Notes through the same method that defines their realization, realizeNote:fromNoteReceiver:.  However, you don't send Notes to an Instrument by invoking this method directly; instead, you send the Notes to one of the Instrument's NoteReceiver objects which, in turn, invokes realizeNote:fromNoteReceiver: for you.

NoteReceiver is an auxiliary class that acts as a ªNote portº for an Instrument.  This is manifested as the three features that a NoteReceiver brings to an Instrument:

·	It provides methods through which an Instrument receives Notes (in other words, methods that invoke Instrument's realizeNote:fromNoteReceiver:).

·	It lets you control the stream of Notes into an Instrument by allowing you to toggle its ability to forward Notes to an Instrument.  

·	It acts as a jack into which you can plug a Performer object's NoteSender.  This connects the Performer that owns the NoteSender to the Instrument that owns the NoteReceiver, such that the Notes generated by the Performer are automatically delivered to and realized on the connected Instrument.  The methods by which you marry a NoteReceiver to a NoteSender are described later in the section on Performers and NoteSenders.  

Creating and adding NoteReceivers is usually part of the design of the Instrument subclass, although some subclasses require you to create and add NoteReceivers yourself.  In either case, the method by which a NoteReceiver is added to an Instrument is the same:  Instrument's addNoteReceiver:.  While an Instrument can own more than one NoteReceiver, a single NoteReceiver can belong to only one Instrument:  An invocation of addNoteReceiver: removes the argument (the NoteReceiver) from its current owner.

The receiveNote: Method

The fundamental method through which a NoteReceiver itself receives NotesÐand thereby forwards them to its owning InstrumentÐis called receiveNote:.  However, before you can send receiveNote: to a NoteReceiver, you must be able to locate the object.  If you created and added NoteReceivers to an Instrument yourself, finding these objects shouldn't pose a problemÐyou made them, you should know where they are.  But keep in mind that many Instruments create and add NoteReceivers for you.  Any Instrument's NoteReceivers can be retrieved as a List object by sending the noteReceivers message to the Instrument; members of this List can then be sent the receiveNote: message.  As a convenience, the first NoteReceiver in this List can be retrieved through the noteReceiver method.  This is particularly handy for Instruments that define only one NoteReceiver, or in situations where you don't care which NoteReceiver you send the Note to.  In the following example, an instance of SynthInstrument is created and a Note is sent to its NoteReceiver.  SynthInstrument is a subclass of Instrument that realizes Notes by synthesizing them on the DSP; it creates a single NoteReceiver as part of its init method:

/* Create a SynthInstrument and send it a Note (assumed to exist). */
aSynthIns = [[SynthInstrument alloc] init];

[Conductor lockPerformance];
[[aSynthIns noteReceiver] receiveNote:aNote];
[Conductor unlockPerformance];

You'll note the presence of the Conductor class methods lockPerformance and unlockPerformance; invocations of these two methods should bracket all invocations of receiveNote: (with some exceptions, as noted in the sections on Conductors and Performers, later in this chapter).  Briefly, these methods ensure that your cast of characters are in synch and primed for timely Note realization.  A fuller explanation of lockPerformance and unlockPerformance is given in ªLocking the Performance,º later in this chapter.

You can create and add any number of NoteReceivers to the Instruments that you allocate, even if these Instruments create NoteReceivers themselves.  However, with some exceptionsÐnotably that described in the next sectionÐthere isn't much reason to do so:  One NoteReceiver is as good as the next.  Any number of Note-producing agentsÐwhether Performers or different mechanisms in your applicationÐcan all send receiveNote: to the same NoteReceiver.  In general, adding a gaggle of NoteReceivers to an Instrument doesn't make the Instrument more interesting, it simply makes it bigger.

Squelching a NoteReceiver

You can throttle a NoteReceiver's ability to invoke realizeNote:fromNoteReceiver: by sending it the squelch message.  To release this clench, you invoke unsquelch.  Through this simple feature, you can easily and quickly mute an Instrument.

While a NoteReceiver is squelched, the receiveNote: method ceases to function:  It immediately returns nil without forwarding the argument Note to the NoteReceiver's owner (unsquelched, receiveNote: returns self).  Realization of the Note isn't merely deferred, it's abandoned for good.  You can determine whether a NoteReceiver is squelched by sending it the isSquelched message:  If the message returns YES, the object is squelched.

The squelch feature, in certain applications, argues for the use of multiple NoteReceivers for a single Instrument.  For example, you can create an application in which Notes are generated from MIDI input and read from a Part object at the same time.  If you feed these two Note sources to the same Instrument, you may want to create and add two distinct NoteReceivers, one for either source, so you can independently squelch the two streams of Notes.  

Performance Status

An Instrument is considered to be in performance from the time that you send receiveNote: to any of its unsquelched NoteReceivers until the performance is overÐin other words, until the Conductor class receives the finishPerformance message.  You can query an Instrument's performance status by sending it the inPerformance message, where a return of YES signifies that the object is currently in performance.

The performance status of an Instrument is significant because some Instrument methods aren't effective while the Instrument is in performance.  This can be a particularly devilish source of confusion since the state of an Instrument's performance doesn't require a performance, in the larger sense, to be in progress.  Specifically, if you send receiveNote: to an Instrument's NoteReceiver before the Conductor class receives startPerformance, the Instrument will, nonetheless, be considered to be performing (and thus the aforementioned performance-status dependent methods will have no effect).  

Realizing Notes

There are very few rules when it comes to realizing Notes:  You can implement realizeNote:fromNoteReceiver: to realize a Note in almost any arbitrary manner.  As mentioned earlier, the Music Kit includes Instruments that synthesize and store Notes as their forms of realization.  For many performance applications, the Instruments provided by the Music Kit are sufficient.  The following sections describe these subclasses.  

SynthInstrument

A SynthInstrument is by far the most complicated Instrument; it realizes Notes by causing them to be synthesized on the DSP.  It operates on three basic principles:

·	Every instance of SynthInstrument is associated with a single subclass of SynthPatch.

·	Before or during a performance, a SynthInstrument object allocates (through requests to the Orchestra) and manages instances of its SynthPatch subclass.  These SynthPatch objects are used to synthesize the Notes that the SynthInstrument receives through its NoteReceiver.

Following these principles, the primary decisions you need to make regarding a SynthInstrument are which SynthPatch subclass to assign it and which of two schemes it should use to allocate instances of the SynthPatch subclass.

Setting the SynthPatch Subclass

You set a SynthInstrument's SynthPatch subclass by invoking the setSynthPatchClass: method.  As the method's argument you specify one of the SynthPatch classes included in the Music Kit, or one of your own.  If you have a multiple-DSP system, the SynthInstrument will allocate its SynthPatch objects on the first DSP that has sufficient available resources.  You can restrict allocation to a specific DSP by invoking setSynthPatchClass:orchestra:, passing an Orchestra object as the second argument.

Note:  If you use a SynthPatch class included in the Music Kit, you must import the file <musickit/synthpatches/ClassName.h>, where ClassName is the name of the class you wish to use.  Alternatively, the file <musickit/synthpatches/synthpatches.h> will import all the Music Kit SynthPatch interface files.

The setSynthPatchClass: method (and the ...orchestra: version) checks its (first) argument to ensure that it's a class that inherits from SynthPatch, returning nil if it doesn't.  It also returns nil (and doesn't set the class) if the SynthInstrument is already involved in a performance.

Allocation Mode

SynthInstrument defines two allocation modes:

·	In automatic allocation mode the SynthInstrument allocates SynthPatch objects as it receives Notes, tagging each SynthPatch with the note tag of the Note for which it was allocated.  As it receives subsequent Notes, the SynthInstrument compares each Note's note tag to those of the SynthPatches it has already allocated.  If it finds a match, the Note is sent to that SynthPatch.  If it doesn't match, the SynthInstrument allocates a new SynthPatch.

·	In manual allocation mode the SynthPatch objects are allocated all at once, before Notes begin to arrive.  The number of SynthPatches to allocate is set through the method setSynthPatchCount:.  The number of SynthPatches that are actually allocated may be less than the number requested, depending on the availability of DSP resources at the time that the message is sent.  The method returns the number of SynthPatches that were actually allocated.  

By default, a SynthInstrument is in automatic allocation mode.  Simply sending setSynthPatchCount: places it in manual mode.  To set it back to automatic mode, you send it the autoAlloc message.  A SynthInstrument can't switch modes while it's performing.

You can query a SynthInstrument's allocation mode by invoking allocMode, a method that returns one of the following integer constants:

Constant	Mode 
MK_AUTOALLOC	Automatic allocation
MK_MANUALALLOC	Manual allocation

Changing the SynthPatch Count

You can change the number of manually allocated SynthPatches at any timeÐeven during a performanceÐsimply by resending the setSynthPatchCount: message.  (If the object is performing, it must have been placed in manual mode before the performance began.)  Notice, however, that the argument is always taken as the total number of SynthPatches that are allocated to the SynthInstrumentÐit doesn't represent the number of new objects to allocate.  For example, in the following sequence of messages, a total of four SynthPatches are allocated.

/* Allocate three SynthPatches. */
[aSynthIns setSynthPatchCount:3];
. . .

/* Allocate one more. */
[aSynthIns setSynthPatchCount:4];

The synthPatchCount method returns the number of manually allocated SynthPatches.  Thus, the previous example can be rewritten as

/* Allocate three SynthPatches. */
[aSynthIns setSynthPatchCount:3];
. . .

/* Allocate one more. */
[aSynthIns setSynthPatchCount:[aSynthIns synthPatchCount]+1];

If the SynthInstrument is in automatic mode, synthPatchCount returns 0.

Deallocating SynthPatch objects is also possible:

/* Allocate three SynthPatches. */
[aSynthIns setSynthPatchCount:3];
. . .

/* Deallocate two of them. */
[aSynthIns setSynthPatchCount:[aSynthIns synthPatchCount]-2];

If the argument signifies a deallocation, the SynthInstrument's idle SynthPatches, if any, are deallocated first; the balance are deallocated as they become inactive.

The PatchTemplate

Some SynthPatches come in a variety of configurations.  For example, the Fm1vi SynthPatch (frequency modulation with optional vibrato) is configured differently depending on whether the Note it's synthesizing specifies vibrato.  It does this to be as efficient as possibleÐexcluding vibrato from Fm1vi's configuration means that it uses less of the Orchestra's resources.

A SynthPatch represents each of its configurations as a different PatchTemplate object.  When you set a SynthInstrument to manual allocation mode, you can specify the number of SynthPatches with a particular PatchTemplate by invoking the setSynthPatchCount:forPatchTemplate: method.  The second argument is the id of the PatchTemplate that you want.  This is returned by sending the patchTemplateFor: message to the SynthInstrument's SynthPatch class, with a Note object as the argument.  This is best explained by example:

/* Create a SynthInstrument. */
id  aSynthIns = [[SynthInstrument init] alloc];

/* Create a variable to store the PatchTemplate. */
id  noVibTemplate;

/* Create a dummy Note. */
id  aNote = [[Note init] alloc];

/* Set its vibrato amplitudes to 0.0. */
[aNote setPar:MK_svibAmp toDouble:0.0];
[aNote setPar:MK_rvibAmp toDouble:0.0];

/* Retrieve the PatchTemplate senza vibrato. */
noVibTemplate = [[aSynthIns synthPatchClass]
            patchTemplateFor:aNote];

/* Allocate three vibratoless SynthPatches. */
[aSynthIns setSynthPatchCount:3
            forPatchTemplate:noVibTemplate];

If the PatchTemplate isn't specified, the SynthPatches are created using the default PatchTemplate.  Each subclass of SynthPatch designates one of its PatchTemplates as the default for that class; by convention, the most extravagant PatchTemplate is provided as the default.  Thus, the default Fm1vi PatchTemplate includes vibrato.  In the example, the Fm1vi PatchTemplate without vibrato is retrieved by passing (as the second argument to patchTemplateFor:) a Note that explicitly sets the vibrato parameters to 0.0.

Within the same SynthInstrument, you can manually allocate SynthPatches that use different PatchTemplates.  The following extension of the previous example demonstrates this:

/* Allocate one vibratoless SynthPatch. */
[aSynthIns setSynthPatchCount:1
            forPatchTemplate:noVibTemplate];

/* And two with vibrato. */
[aSynthIns setSynthPatchCount:2];

setSynthPatchCount: always uses the default PatchTemplate (which, as mentioned earlier, includes vibrato for Fm1vi).  When the SynthInstrument in the example receives a Note that initiates a new phrase, it automatically forwards the Note to the proper SynthPatch:  If the Note contains vibrato parameters with zero values (similar to the dummy Note used in the previous example), it's forwarded to the SynthPatch that excludes vibrato; otherwise, it's sent to one of the other two SynthPatches.  

The SynthInstrument keeps a count of the number of SynthPatches it has manually allocated for each PatchTemplate.  The count for a particular PatchTemplate is returned by the method synthPatchCountForPatchTemplate:.  The synthPatchCount method, used in an example in the previous section, returns the count for the default PatchTemplate.

If the SynthPatch is in automatic mode, you don't need to specify which PatchTemplate to use.  The SynthInstrument automatically creates a SynthPatch with the correct PatchTemplate to accommodate the parameters in the Notes it receives.

Talking to the SynthPatches

A SynthInstrument's primary task is to forward Notes to its SynthPatches.  The SynthPatch class defines three methods that are designed to be invoked by a SynthInstrument for this purpose:

·	noteOn: is used to forward a noteOn type Note.
·	noteUpdate: forwards noteUpdates.
·	noteOff:, likely enough, forwards noteOffs.

The Note itself is passed as the argument to the method.  Invocation of these methods is automatic; when a SynthInstrument receives a Note during a performance, it automatically invokes the appropriate method.

Notice that noteDurs and mutes aren't included in this scheme.  A noteDur is split into a noteOn/noteOff pair.  If the noteDur doesn't have a noteTag, a unique noteTag is created and given to the two new Notes.  Mutes are simply ignored.

Besides forwarding Notes, the noteOn: and noteOff: methods also set a SynthPatch's synthesis status.  This describes the object's current synthesis state as one of the following MKSynthStatus constants:

Constant	Meaning 
MK_idle	The SynthPatch is currently inactive.
MK_running	The SynthPatch is synthesizing the body of a musical note.
MK_finishing	The SynthPatch is in the release portions of its Envelopes.

The noteOn: message sets the synthesis status to MK_running; noteOff: sets it to MK_finishing.  In either of these states, the SynthPatch is considered to be active.  The status is set to MK_idle when the release portion of the SynthPatch's amplitude Envelope (in other words, the object set as the value of the MK_ampEnv parameter of the Note that the SynthPatch is realizing) is complete.  None of the other Envelopes are taken into consideration when determining if the SynthPatch is idle:  It's assumed that the amplitude Envelope will ultimately fall to an amplitude of 0.0, thus whatever course the other Envelopes take after that point is for nought since the SynthPatch will no longer be making any noise.

The Update State

The SynthInstrument class gives special consideration to a noteUpdate that doesn't have a note tag:

·	The noteUpdate is forwarded to all the active SynthPatches (within the SynthInstrument that received the Note).

·	The Note's parameters are stored in the SynthInstrument's update state.

Every SynthInstrument has an update state.  When a SynthInstrument begins a new phrase, the parameters in the update state are merged into the Note that initiated the phrase (always a noteOn, whether by nature or due to a noteDur split).  The update state parameters never overwrite the value of a parameter already present in a noteOnÐin the case of a parameter collision, the noteOn's parameter takes precedence.  Conversely, a noteOn's parameters never affect the update state, it can only be changed by another noteUpdate with no note tag.

As a demonstration of these principles, consider the following scorefile excerpt:

/* Scorefile body excerpt. */
t 0.0;
part1 (noteUpdate) amp:.25;

t 1.0;
part1 (noteOn 1) freq:c4;     /* amplitude is .25 */
t 2.0;
part1 (noteOff 1);
t 3.0;
part1 (noteOn 2) freq:d4 amp:.75; /* amplitude is .75 */
t 4.0;
part1 (noteOff 2);

t 5.0;
part1 (noteOn 3) freq:e4;     /* amplitude is, once again, .25 */
t 6.0;
part1 (noteUpdate) amp:.5; 
t 7.0;
part1 (noteUpdate 3) amp:.25; 
t 8.0;
part1 (noteOff 3);

t 9.0;
part1 (noteOn 4) freq: f4;    /* amplitude is .5 */
t 10.0;
part1 (noteOff 4);

The initial note tag-less noteUpdate sets the amplitude parameter in the SynthInstrument's update state; notice that the update state is set even though the SynthInstrument doesn't have any active SynthPatches.  Of the four subsequent noteOns, the first, third, and fourth don't have amplitude parameters so they inherit the one in the update state.  The second noteOn has its own amplitude; it ignores the parameter in the update state.

While the third musical note is sounding, two more noteUpdates arrive.  The first has no note tag, so it affects both the active SynthPatch and the update state.  The second noteUpdate's note tag matches that of the active SynthPatch; it's forwarded to the SynthPatch but doesn't affect the update state.

Preempting a SynthPatch

While the DSP makes a great synthesizer, its resources are by no means unlimited.  It's possible to ask it to synthesize, at the same time, more Notes than it can accommodate.  The number of Notes that can be synthesized at one time depends on a number of factors, the most significant being the sampling rate and the requirements of the SynthPatches that are being used.  There sometimes comes a time in the life of a SynthInstrument when it tries to allocate just one more SynthPatch and finds that the well is empty.

When a SynthInstrument can't get the resources to synthesize a new Note, it tries to preempt an active SynthPatch rather than lose the Note.  The following steps are taken to determine which SynthPatch to preempt:

1.	The preempted SynthPatch should have sufficient resources to synthesize the Note, thus the SynthInstrument first looks for a SynthPatch that uses the same PatchTemplate that's needed to synthesize the new Note.

2.	If there's more than one such SynthPatch, the one that first received a noteOff: message, if any, is preempted.  In other words, the preemption scheme first looks for a SynthPatch whose synthesis status is MK_finishing.

3.	If there aren't any finishing SynthPatches, the oldest SynthPatch is chosen.

4.	If a SynthPatch with the appropriate PatchTemplate isn't available, the SynthInstrument tries other SynthPatches until one is found that has sufficient resources to synthesize the new Note.

A SynthInstrument object can only preempt its own SynthPatchesÐit can't steal one from another SynthInstrument.  The search for a preemptible SynthPatch is sometimes unsuccessful; for example, if there are no more resources to build a new SynthPatch, the new Note can't be synthesized.

Providing Your Own Preemption Scheme

The determination of which SynthPatch to preempt is performed in the preemptSynthPatchFor:patches: method:  The method's return value is taken as the SynthPatch to preempt.  If you want to provide your own system for preempting SynthPatches, you have to create your own subclass of SynthInstrument in which to reimplement this method.

The method is automatically invoked when the SynthInstrument has to preempt a SynthPatch.  The two arguments are:

·	The newly arrived Note
·	The first in a list of candidate SynthPatches

Notice that the second argument is a single SynthPatch object.  To get to the next object in the list, you send next to the SynthPatch at hand.

Midi

The Midi class isn't a true InstrumentÐit inherits from Object.  However, it creates NoteReceivers and implements realizeNote:fromNoteReceiver: and so can be used as an Instrument.

A Midi object creates 17 NoteReceivers, one for the Basic Channel and one each for the 16 Voice Channels.  You can retrieve the NoteReceiver that corresponds to a particular channel through the channelNoteReceiver: message, passing the channel number that you want:  0 retrieves the NoteReceiver for System and Channel Mode Messages; 1-16 retrieves the NoteReceiver for the corresponding Voice Channel.  You create a Midi object to correspond to a serial port, specified as ªmidi0º or ªmidi1,º in the allocFromZone:onDevice: method.

When it receives a Note, the Midi object translates it into a series of MIDI messages, based on the Note's note type and parameters that it contains.  It then sends the messages out the serial port.

A Midi object has a device status that's much like the device status of the Orchestra object, as described in Chapter 4.  Before you can send Notes to a Midi object (more accurately, before the object will do anything with these Notes), you must open and run it, through the open and run methods.

PartRecorder and ScoreRecorder

PartRecorder is a fairly straightforward Instrument:  The Notes that it receives through its single NoteReceiver are copied and added to the Part with which it's associated.  The NoteReceiver is created automatically; the Part must be set by your application, through the setPart: method.  

A PartRecorder sets a Note's time tag to the current time as it receives the Note; the measure of the current time is either in beats or seconds, depending on the value of its ªtime unit.º  You can set the time unit through the setTimeUnit: method, passing either MK_second or MK_beat as the argument.  Other than the manipulation of the time tag, the Note is unchanged by the PartRecorder.

ScoreRecorder isn't actually an Instrument; it's used to correspond to Score just as a PartRecorder corresponds to a Part.  A ScoreRecorder actually creates and controls some number of PartRecorders, one for each Part in its Score.

ScorefileWriter

A ScorefileWriter object realizes Notes by writing them to a scorefile.  It's the one Instrument defined by the Music Kit that requires you to create and add NoteReceivers from your application.  Each NoteReceiver that you add corresponds to a Part that will be represented in the scorefile that's written.  Typically, you name the NoteReceivers that you create; these names are used to identify the corresponding Part-representations in the scorefile:

/* Create a ScorefileWriter and add to it 3 NoteReceivers. */
id aSFWriter = [[ScorefileWriter alloc] init];
id fordReceiver = [[NoteReceiver alloc] init];
id pageReceiver = [[NoteReceiver alloc] init];
id quicklyReceiver = [[NoteReceiver alloc] init];

/* Name the NoteReceivers. */
MKNameObject("Ford", fordReceiver);
MKNameObject("Page", pageReceiver);
MKNameObject("Quickly", quicklyReceiver);

/* Add the NoteReceivers. */
[aSFWriter addNoteReceiver:fordReceiver];
[aSFWriter addNoteReceiver:pageReceiver];
[aSFWriter addNoteReceiver:quicklyReceiver];

/* Set the ScorefileWriter's file by name. */
[aSFWriter setFile: "Falstaff.score"];

Creating an Instrument Subclass

While there are no strict rules governing realization, intelligent Instrument design should follow these guidelines:

·	An Instrument should realize Notes as it receives them.  It's possible to design an Instrument that, for instance, reschedules its Notes to be realized later, but for the sake of generality, an Instrument should act immediately upon the Notes it receives.  

·	If an Instrument needs to alter or store a Note, it should create a copy of the Note and act upon the copy.  

·	An Instrument shouldn't be a source of Notes.  The task of generating new Notes belongs to a Performer or to your application.  The role of an Instrument is to respond, not to conceive.  This doesn't mean that an Instrument can't create Notes, but it should only do so in response to receiving a Note.

Along with these guidelines, keep in mind that an Instrument should, if possible, create and add to itself some number of NoteReceivers, usually in its init method.

The Conductor Class

The Conductor class defines the mechanism that controls the timing of a Music Kit performance.  This control is divided between the class object and instances of Conductor:

·	The Conductor class itself represents an entire Music Kit performance.  The class methods perform global operations such as setting characteristics that apply to all Conductor instances, and starting and stopping a performance.

·	Each Conductor instance embodies a message request queue, a list of messages that are to be sent to particular objects at specific times.  Most of the instance methods are designed to affect a Conductor's queue in some way.  The most commonly invoked of these are the methods that enqueue message requests, and those that determine how quickly a Conductor processes the requests in its queue (in other words, the Conductor's tempo).

Conductors Created by the Music Kit

The Music Kit automatically creates two Conductor instances for you, the clockConductor and the defaultConductor:  

·	As its name implies, the clockConductor acts as a clock:  It ticks away at a steady and immutable 60.0 beats per minute.  Any timing information that's reckoned by the other Conductor instances is computed in reference to the clockConductor.  

·	Many applications need only a single Conductor instance (in addition to the clockConductor); the defaultConductor is created as a convenience to meet this need.  The defaultConductor is more pliable than the clockConductor in that its tempo can be altered and its activities can be temporarily suspended during a performance.

The clockConductor is retrieved by sending the clockConductor message to the Conductor class; similarly, defaultConductor retrieves the defaultConductor.

The Message Request Queue

Every instance of Conductor (this includes the clockConductor and defaultConductor) maintains a message request queue.  This queue consists of a list of structures, each of which encapsulates a request for a message to be sent to some object.  Every request is given a timestamp that indicates when its message should be sent.  The requests in a message request queue are sorted according to these timestamps.  When a performance starts (through the startPerformance class method), the Conductor instances begin processing their message queues, sending the requested messages at the appropriate times.  

Note:  The structures in the message request queues are of type MKMsgStruct.  All the fields of this structure are private:  You can examine them, but you should never alter their values directly.  Detailed knowledge of the MKMsgStruct isn't necessary.  The structure is defined without further explanation in the file /usr/include/musickit/Conductor.h.

Creating and Scheduling a Message Request

To enqueue a message request with a Conductor, you invoke the sel:to:atTime:argCount: or sel:to:withDelay:argCount: method.  The arguments to these methods are similar:

Keyword	Argument
sel:	Selector that identifies the method you wish to invoke
to:	The object that implements the desired method
atTime: or withDelay:	The time at which you wish the method to be invoked
argCount:	The number of method arguments, followed by the 
	arguments themselves, separated by commas

The difference between the two methods is the manner in which the time argument is interpreted.  A message request enqueued through the ...atTime:... method is sent at the specified time measured from the beginning of the performance.  If you use the ...withDelay:... method, the requested message is sent after the specified amount of time has elapsed since the sel:to:withDelay:argCount: method itself was invoked (given that a performance is in progress).  Invoked before a performance begins, the two methods are identical.  

Once you've made a message request through one of these methods, you can't rescind the action; if you need more control over message requestsÐfor example, if you need to be able to reschedule or to remove a requestÐyou should use the following C functions:

·	MKNewMsgRequest(double time, SEL selector, id receiver, int argCount,...) creates a new MKMsgStruct structure and returns a pointer to it.  The arguments are similar, although in a different order, to those of the sel:to:atTime:argCount: method.

·	MKScheduleMsgRequest(MKMsgStruct *aMsgStructPtr, id conductor) places the structure pointed to by aMsgStructPtr, which was previously created through MKNewMsgRequest(), in conductor's message request queue.

·	MKRepositionMsgRequest(MKMsgStruct *aMsgStructPtr, double time) repositions a message request within a Conductor's queue.  The value of the time argument is absolute:  It indicates the request's new position as the number of beats since the beginning of the performance.  

·	MKCancelMsgRequest(MKMsgStruct *aMsgStructPtr) removes a message request.

The Conductor class provides two special message request queues, one that contains messages that are sent at the beginning of a performance and another for messages that are sent after a performance ends.  The class methods beforePerformanceSel:to:argCount: and afterPerformanceSel:to:argCount: enqueue message requests in the before- and after-performance queues, respectively.

Controlling a Performance

As previously mentioned, a Music Kit performance starts when the Conductor class receives the startPerformance message.  This starts the Conductor's clock ticking (as represented by the clockConductor).  If you're synthesizing music on the DSP or sending messages to an external MIDI synthesizer, you should send the run message to the Orchestra class or to your Midi object at virtually the same time that you invoke startPerformance:

/* Start Midi, the DSP, and the performance at the same time. */
[aMidi run];  /* assuming aMidi was previously created */ 
[Orchestra run];
[Conductor startPerformance];

When it receives startPerformance, the Conductor class sends the messages in its before-performance queue and then the Conductor instances start processing their individual message request queues.  As a message is sent, the request that prompted the message is removed from its queue.  The performance ends when the Conductor class receives finishPerformance, at which time the after-performance messages are sent.  Any message requests that remain in the individual Conductors' message request queues are removed.  Note, however, that the before-performance queue isn't cleared.  If you invoke beforePerformanceSel:to:argCount: during a performance, the message request will survive a subsequent finishPerformance and will affect the next performance.  

By default, if all the Conductors' queues become empty at the same time (not including the before- and after-performance queues), finishPerformance is invoked automatically.  This is convenient if you're performing a Part or a Score and you want the performance to end when all the Notes have been played.  However, for many applications, such as those that create and perform Notes in response to a user's actions, universally empty queues aren't necessarily an indication that the performance is over.  To allow a performance to continue even if all the queues are empty, send setFinishWhenEmpty:NO to the Conductor class.

While a performance is in progress, you can pause all Conductor's by sending pausePerformance to the Conductor class.  A paused performance is resumed through the resumePerformance method.  Individual Conductor objects can be paused and resumed through the pause and resume methods.

Setting the Tempo

A Conductor's tempo controls the rate with which it processes the requests in its message request queue.  Two methods are provided for setting a Conductor object's tempo:

·	setTempo:, which takes a double argument, sets the tempo in beats-per-minute.

·	setBeatSize: also takes a double, but it sets the tempo by defining the duration, in seconds, of a single beat.

Regardless of which method you use to set the tempo, the values returned by the retrieval methods tempo and beatSize are computed appropriately, as shown in the following example:

double bSize;

/* Sets the defaultConductor's tempo. */ 
[[Conductor defaultConductor] setTempo:240.0];

/* Return the beat size; bSize will be 60.0/240.0, or 0.25. */ 
bSize = [[Conductor defaultConductor] beatSize];

You can change a Conductor's tempo at any time, even during a performance.  If your application requires multiple simultaneous tempi, you need to create more than one Conductor, one for each tempo.  A Conductor's tempo is initialized to 60.0 beats per minute.

Locking the Performance

Every Conductor instance has a notion of the current time, measured in beats.  This notion is updated by the Conductor class only when a message from one of the request queues is sent; all Conductors are updated when any Conductor sends such a message.  If your application sends a message (or calls a C function) that depends on a Conductor's notion of time being current, you must first send lockPerformance to the Conductor class.  Every invocation of lockPerformance should be balanced by an invocation of unlockPerformance.  For example, if you send receiveNote: to an Instrument's NoteReceiver, you must bracket the message with lockPerformance and unlockPerformance.  (However, invocations of receiveNote: that are requested through a Conductor's messge request queue shouldn't be bracketed by these methods.)

Conductors and Notes

Every Note is associated with a Conductor object.  By default, a Note is associated with the defaultConductor.  You can't change a Note's Conductor directly; only a Performer object can do that (as described in the section on Performers).

The association between a Note and a Conductor is of particular importance if the Note is a noteDur that's sent to a SynthInstrument or Midi object.  Both of these Instruments split a noteDur into a noteOn/noteOff pair.  The noteOn is realized immediately and the noteOff is scheduled for realization at a later time, as indicated by the original Note's duration value.  To do this, a request for the noteOff to be sent in a receiveNote: message is enqueued with the Note's Conductor.  The exact time at which the Note arrives depends, therefore, on this Conductor's tempo.  

A Note's Conductor is also important if you send the Note to an Instrument through NoteReceiver's receiveNote:atTime: or receiveNote:withDelay: methods.  These methods cause the NoteReceiver to enqueue a receiveNote: request with the Note's Conductor at the specified time:  The former method takes the atTime: argument as an absolute measure from the beginning of the performance, while the latter measures the withDelay: argument as some number of beats from the time that it's invoked.

Conductors and Envelopes

The relationship between an Envelope and a Conductor is as important as it is inflexible:  The dispatching of an Envelope's breakpoints during DSP synthesis is always done through message requests with the clockConductor.  You don't have to do anything to obtain this behavior, it happens automatically through MKUpdateAsymp(), the function that you use in the design of a SynthPatch subclass to apply an Envelope to a synthesis patch.  

This association is particularly important not for the particular Conductor with which the breakpoints are scheduled, but that they are scheduled at all.  Since the clockConductor handles breakpoint dispatching, this means that its queue may be filled with breakpoint messages without you knowing it.  As a result, if you set the performance to finish when the queues are empty, the performance won't finish until all the breakpoint messages are sent from the clockConductor's queue.  This is generally desirable behavior.  Where things can become confusing is if you pause an entire performance (through Conductor's pausePerformance class method) while Envelopes are being handled.  Not only will all Note handling stop, all Envelopes will freeze as well.  This usually isn't pleasant.  

One way to avoid the problem is to pause all your Conductor objects, through the pause method, rather than pause the entire performance.

The Performer Class

A Performer object does two things:

·	It generates or otherwise obtains a series of Note objects during a performance.

·	It acts as a cover for Conductor's scheduling mechanism by sequentially and repeatedly requesting invocations of its own perform method.  

The Performer class itself is abstract; you create a subclass of Performer to correspond to a unique sources of Notes.  The Music Kit includes subclasses that read Notes from a Part (PartPerformer) or a scorefile (ScorefilePerformer)Ðthe latter actually inherits from the FilePerformer class, a subclass of Performer that defines methods for managing files.  The Music Kit also includes pseudo-Performers that fashion Notes from MIDI input (Midi), and that read Notes from a Score (ScorePerformer, which creates a PartPerformer for each Part in the Score).  Consult Chapter 2 of Reference for further descriptions of these classes.

Using a Performer object is quite simple; creating your own subclass is a bit more complicated and requires a firm understanding of how a Performer goes about its business.  These two topics are presented below.

Using a Performer

To use a Performer, you need to do two things:  connect it to an Instrument and tell it to go.  Every Performer contains some number of NoteSenders, auxiliary objects that are created by the Performer to act as Note ªspigots.º  NoteSenders are analogous to an Instrument's NoteReceivers.

To connect a Performer to an Instrument, you retrieve a NoteSender and NoteReceiver from either, respectively, and connect these objects through the connect: method, as defined by both NoteSender and NoteReceiver.  For example, to connect a PartPerformer to a SynthInstrument, you would do the following:

/* aPartPerformer and aSynthIns are assumed to exist. */
[[aPartPerformer noteSender] connect:[aSynthIns noteReceiver]];

Since both classes define the connect: method, the following is equivalent:

/* aPartPerformer and aSynthIns are assumed to exist. */
[[aSynthIns noteReceiver] connect:[aPartPerformer noteSender]];

The noteSender method returns one of a Performer's NoteSenders, just as the noteReceiver method retrieves one of an Instrument's NoteReceivers.  If you're using a Music Kit Performer subclass, you should refer to its description to determine if it creates more than one NoteSender.  If it creates only one, then the noteSender method is sufficient.  If it creates more than one, you can retrieve the entire set as a List through the noteSenders method and then choose the NoteSender that you want by plucking it from the List.  A ScorefilePerformer, for example, creates a NoteSender for each Part that's represented in its scorefile.

Activating a Performer

To make a Performer run, you send it the activate message.  This prepares the object for a performance but it doesn't actually start performing Notes until you send startPerformance to the Conductor class.  If you invoke activate while a performance is in progress (in other words, after you send startPerformance), the Performer will immediately start running.  In addition, the Performer may require subclass-specific preparation; for example, you have to set a PartPerformer's Part before you send it the activate message.  

While a Performer is running, you can pause and resume its activity through the pause, pauseFor:, and resume methods.  To completely stop a Performer you invoke deactivate.  In addition, all Performers are automatically deactivated when the Conductor class receives the finishPerformance message.  A Performer can be given a delegate object that can be designed to respond to the messages performerDidActivate:, performerDidPause:, performerDidResume:, and performerDidDeactivate:.  These messages are sent by the Performer at the obvious junctures in its performance.

Performers and Conductors

Every Performer object is associated with a Conductor.  If you don't set a Performer's Conductor explicitly (through setConductor:), it will be associated with the defaultConductor.  The rate at which a Performer performs its Notes is controlled by its Conductor's tempo.  In general, all the Performers you create can be associated with the same Conductor.  The only case in which a Performer demands its own Conductor is if you want the Performer to proceed at a different tempo from its fellow Performers.  

Creating a Performer Subclass

The design of a Performer subclass must address three tasks:  acquiring a Note, sending it into a performance, and scheduling the next Note.

Acquiring Notes

Each subclass of Performer defines a unique system for acquiring Notes.  You can design your own Performers that, for example, read Notes from a specialized database or create Notes algorithmically.  Regardless of how a Performer acquires its Notes, it does so as part of the implementation of its perform method.  

The perform method can be designed to acquire any number of Notes with a single invocation.   

Sending Notes

To send a Note into a performance, a Performer relies on its NoteSender objects.  A Performer creates and adds some number of NoteSenders to itself, usually as part of its init method.  NoteSenders are created through the usual sequence of alloc and init messages; they're added to a Performer through Performer's addNoteSender: method.  A Performer can add any number of NoteSenders to itself, although it's anticipated that most Performers will need only one.

As part of its implementation of the perform method, a Performer passes the Note it has acquired as the argument in a sendNote: message, which it sends to its NoteSenders.  Each NoteSender then relays the Note to the NoteReceivers to which it's connected; each NoteReceiver passes the Note to the Instrument that it (the NoteReceiver) belongs to.  Thus, by sending sendNote: to a NoteSender, a Performer communicates Notes to one or more Instruments.  If more than one Note is acquired in the perform method, each is sent in a separate sendNote: message.

Note:  Methods that are invoked from within the perform methodÐand this includes the sendNote: methodÐshouldn't be bracketed by lockPerformance and unlockPerformance.  

Scheduling Notes

As described above, every time a Performer receives the perform message it acquires a Note and then sends it to its NoteSenders.  The final obligation of the perform method is to schedule its own next invocation.  This is done by setting the value of the nextPerform instance variable.  The value of nextPerform is measured in beats according to the tempo of the Conductor and, most important, it's taken as a time delay:  If you set nextPerform to 3.0, for example, the perform method will be invoked after 3.0 beats.

To get things started, a Performer's first perform message is automatically scheduled to be sent just after the Performer is activated.  You can delay this initial invocation by setting the nextPerform variable from within the activateSelf method.  The default implementation of activateSelf does nothing; a subclass can implement it to provide pre-performance initialization just such as this.  

An important implication of this scheduling mechanism is that a Performer must be able to determine when it wants to perform its next Note at the time that it acquires and performs its current Note.  

Fine-Tuning a Performance Application

Responsiveness

The responsiveness of a performance to the user's actions depends on whether the Conductor class is clocked or unclocked, and upon the value of the performance's delta time.  By default, the Conductor class is clocked.  This means that the messages in the message request queues are sent at the times indicated by their timestamps.  When the Conductor class is clocked, a running Application object must be present (unless the performance is being run in a separate thread, as described below).  

If you don't need interactive control over a performance, you may find it beneficial to set it to unclocked by sending setClocked:NO to the Conductor class.  In an unclocked performance, messages in the message request queues are sent one after another as quickly as possible, leaving it to some other deviceÐthe DSP or the MIDI device driverÐto handle the timing of the actual realization.  

Setting the delta time further refines the responsiveness of a performance.  Delta time is set through the MKSetDeltaT() C function; the argument defines an imposed time lag, in seconds, between the Conductor's notion of time and that of the DSP and MIDI device drivers.  It acts as a timing cushion that can help to maintain rhythmic integrity by granting your application a sort of computational head start:  As you set the delta time to larger values, your application has more time to process Notes before they are realized.  However, this computational advantage is obtained at the expense of degraded responsiveness.  Choosing the proper delta time value depends on how responsive your application needs to be.  For example, if you are driving DSP synthesis from MIDI input, a delta time of as much as 10 milliseconds (0.01 seconds) is generally acceptable.  If you are adjusting Note parameters by moving a Slider with the mouse, a delta time of 100 milliseconds or more can be tolerated.  Finding the right delta time for your application is largely a matter of experimentation.

Separate-Threaded Performance

To enhance the efficiency of a performance, you can run it in its own thread.  This is done by sending useSeparateThread:YES to the Conductor class.  Running a performance in its own thread separates it from the main event loop, thus allowing music to play with greater independence from your application's other computations.  However, certain restrictions must be adhered to when running a performance in its own thread:

·	You can't use ScorefileWriter or ScorefilePerformer objects in the performance.

·	You can't invoke an Orchestra method that changes the Orchestra's status; these are open, run, stop, close, and abort.

·	You can't send messages to instances of classes defined by the Application Kit, or to instances of the Sound Kit's SoundView and SoundMeter classes.  In addition, you can't read or write soundfiles, or play or record sounds through an instance of the Sound Kit's Sound class (note, however, that you can use the sound library functions).

·	You can't call DPS client functions.

·	You can't call NXStreams functions.

·	You can't call C functions that rely on standard input and output; these are functions such as printf() and scanf().  Because of this, DSP error logging and Music Kit tracing can't be used.  In addition, if you need to handle Music Kit errors, you must provide your own error handler function through MKSetErrorProc().

These restrictions apply only to that part of your application that's running in the performance thread; specifically, messages sent by a Conductor through its message request queue, and method invocations and C function class that are part of the design of a Performer or Instrument (or pseudo-Performers such as Midi) must follow these restrictions.  For example, you can't use an Instrument that sends messages to an Application Kit Window object; however, you can send messages to the Window from your application's main thread.

The performance thread can cause a restricted method to be invoked or a restricted function to be called by sending a Mach message to a message port.  To do this, you must first register the port through DPSAddPort() in the main thread.  This is demonstrated in the Ensemble programming example (/NextDeveloper/Examples/MusicKit/Ensemble).

An important restriction in a multi-threaded performance is that all messages (or groups of messages) to Music Kit objects sent from the main thread should be bracketed with lockPerformance and unlockPerformance.

Performance Priority

Give your application an unfair advantage through the setTheadPriority: Conductor class method.  This method sets the Mach-scheduling priority of the performance thread, whether or not it's separate.  Performance priority values are between 0.0 and 1.0, where 0.0 is unheightened (the default) and 1.0 is the maximum priority for a user process.  Normally, Mach priorities degrade over time; you can subvert this degradation by giving ownership of your application to root and setting the application's protection to include the set user ID bit.  In a Terminal window, you would type the following:

su root 
chown root yourAppHere
chmod u + s yourAppHere

Performing with the DSP

You can also shape your performance's capabilities by affecting the Orchestra class, thus influencing the manner in which DSP resources are used.

Sampling Rate

The DSP can output stereo samples at two rates, 22050 samples per second, or 44100 samples per second.  By default, it runs at the low sampling rate.  You can improve a performance's response time with regard to DSP synthesis by using the high sampling rate, as accomplished by sending the message

[Orchestra setSamplingRate:44100.0];

However, by asking the DSP to run at a higher sampling rate, you rob it of some of its power.  In general, the DSP can be considered to be twice as ªbigº at the low sampling rate as at the high.  In other words, if the DSP is able to synthesize twelve simultaneous voices at the low sampling rate using a particular SynthPatch, it may only be able to synthesize six such voices at the high sampling rate.

Sound Buffer Sizes

While the speed of the DSP makes real-time synthesis approachable, there's always an imposed time delay that's equal to the size of the buffer used to collect computed samples before they're shovelled to the DAC.  To accommodate applications that require the best possible response time (the time between the initiation of a sound and its actual broadcast from the DAC), a smaller sample output buffer can be requested by sending the setFastResponse:YES message to an Orchestra.  However, the more frequent attention demanded by the smaller buffer will detract from the DSP's synthesis computation and, again, fewer simultaneous voices may result.

Headroom

The Orchestra doesn't know, at the beginning of a Note, if the DSP can execute a given set of UnitGenerators quickly enough to produce a steady supply of output samples for the entire duration of the Note.  However, it makes an educated estimate and will deny allocation requests that it thinks will overload the DSP and cause it to fall out of real time.  Such a denial may result in a smaller number of simultaneously synthesized voices.  

You can adjust the Orchestra's DSP processing estimate, or headroom, by invoking the setHeadroom: Orchestra method.  This takes an argument between -1.0 and 1.0; a negative headroom allows a more liberal estimate of the DSP resourcesÐresulting in more simultaneous voicesÐbut it runs the risk of causing the DSP to fall out of real time.  Conversely, a positive headroom is more conservative:  You have a greater assurance that the DSP won't fall out of real time but the number of simultaneous voices is decreased.  The default is a somewhat conservative 0.1.