ftp.nice.ch/peanuts/GeneralData/Documents/NeXT/SndMusicDSP_Concepts.tar.gz#/Concepts/05_Performance.rtf

This is 05_Performance.rtf in view mode; [Download] [Up]

paperh22175 margl-907 margr0 margt0 margb0 {fonttblf0fswiss Helvetica;f1froman Times;f2fmodern Courier;f3ftech Symbol;f4froman Palantino;}fi0 ri0 ql sb0 f1 fs24 Release 2.0  Copyright f3 'e3f1 1991 by NeXT Computer, Inc.  All Rights Reserved.

pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 f1 fs28 fs16 
fs28 
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 
fs16 
fs28 s6 fs56 Chapter 5
s21 Music Performance
fs16 








fs56 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs28 fs16 fs28 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, 'aaRepresenting Music Data,'ba and Chapter 4, 'aaMusic Synthesis.'ba
fs16 
fs28 s11 li100 fi2015 fi0 b fs36 fs16 



fs36 Design Philosophy
fs16 
fs36 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 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 i realizingi0 , the Note.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 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'27re not essential to a performance application; in fact, some applications can'27t 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'd0and any number of'd0Instruments.  These connections can be created and severed dynamically, allowing you to create a kaleidoscopic network of Note sources and destinations.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 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'27s similar to the timed entry mechanism of Display PostScript, but with a more sophisticated interface).  For example, it'27s through a Conductor that a Performer schedules the messages that relay Notes to an Instrument.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 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'd0it isn'27t easy stopping a highly charged fugue that has jumped the rails'd0well-debugged and fine-tuned applications will find great benefit in these enhancements.  
fs16 
fs28 pard s11 li100 fi0 ri1007 ql b fs36 fs16 



fs36 Performance Outline
fs16 
fs36 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 A Music Kit performance can be divided into three phases:
fs16 
fs28 pard s0 li2620 fi-503 ri1007 ql tx2620 tx3124 tx3628 tx4132 fs16 fs28 'b7	Preparation:  You must determine the sources and destinations of the Notes that you wish to perform and establish other characteristics of the performance.
fs16 
fs28 fs16 fs28 'b7	Commencement:  This is always accomplished by sending b startPerformanceb0  to the Conductor class.
fs16 
fs28 fs16 fs28 'b7	Termination:  This is achieved by sending b finishPerformanceb0  to the Conductor class.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 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'27s synthesized on the DSP, you perform both tasks in a single performance'd0you don'27t have to set up separate environments.  Obviously, the two endeavors involve different classes of objects, but when the Conductor class receives the b startPerformanceb0  message, everybody starts wheezing.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 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 i Referencei0  to check for the conditions under which a method may be invoked.  
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 The following sections examine the three primary classes involved in a performance:  Instrument, Performer, and Conductor.
fs16 
fs28 s11 li100 fi2015 fi0 b fs36 fs16 



fs36 The Instrument Class
fs16 
fs36 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 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.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 At the heart of an Instrument is itsb  realizeNote:fromNoteReceiver: b0 method.  The Instrument class itself is abstract and doesn'27t implement this method; it'27s the responsibility of each Instrument subclass to provide an implementation of b realizeNote:fromNoteReceiver:b0  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.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 One of the principals of Instrument design is that an Instrument doesn'27t 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'27t reinvent the Note-reception mechanism for each Instrument subclass.  
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 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.
fs16 
fs28 s17 li1108 fi1007 fi0 b fs36 fs16 



fs36 Receiving Notes
fs16 
fs36 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 An Instrument receives Notes through the same method that defines their realization, b realizeNote:fromNoteReceiver:b0 .  However, you don'27t send Notes to an Instrument by invoking this method directly; instead, you send the Notes to one of the Instrument'27s NoteReceiver objects which, in turn, invokes b realizeNote:fromNoteReceiver:b0  for you.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 NoteReceiver is an auxiliary class that acts as a 'aaNote port'ba for an Instrument.  This is manifested as the three features that a NoteReceiver brings to an Instrument:
fs16 
fs28 pard s0 li2620 fi-503 ri1007 ql tx2620 tx3124 tx3628 tx4132 fs16 fs28 'b7	It provides methods through which an Instrument receives Notes (in other words, methods that invoke Instrument'27s b realizeNote:fromNoteReceiver:b0 ).
fs16 
fs28 fs16 fs28 'b7	It lets you control the stream of Notes into an Instrument by allowing you to toggle its ability to forward Notes to an Instrument.  
fs16 
fs28 fs16 fs28 'b7	It acts as a jack into which you can plug a Performer object'27s 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.  
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 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'27s b addNoteReceiver:b0 .  While an Instrument can own more than one NoteReceiver, a single NoteReceiver can belong to only one Instrument:  An invocation of b addNoteReceiver: b0 removes the argument (the NoteReceiver) from its current owner.
fs16 
fs28 s18 b fs28 fs16 



fs28 The receiveNote: Method
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 The fundamental method through which a NoteReceiver itself receives Notes'd0and thereby forwards them to its owning Instrument'd0is called b receiveNote:b0 .  However, before you can send b receiveNote:b0  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'27t pose a problem'd0you made them, you should know where they are.  But keep in mind that many Instruments create and add NoteReceivers for you.  Any Instrument'27s NoteReceivers can be retrieved as a List object by sending the b noteReceiversb0  message to the Instrument; members of this List can then be sent the b receiveNote:b0  message.  As a convenience, the first NoteReceiver in this List can be retrieved through the b noteReceiverb0  method.  This is particularly handy for Instruments that define only one NoteReceiver, or in situations where you don'27t 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 b initb0  method:
fs16 
fs28 s14 li2620 fi-503 fi0 f2 fs24 /* Create a SynthInstrument and send it a Note (assumed to exist). */
fi0 aSynthIns = [[SynthInstrument alloc] init];
fi0 
fi0 [Conductor lockPerformance];
fi0 [[aSynthIns noteReceiver] receiveNote:aNote];
fi0 [Conductor unlockPerformance];
pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 f1 fs28 fs16 
fs28 You'27ll note the presence of the Conductor class methods b lockPerformanceb0  and b unlockPerformanceb0 ; invocations of these two methods should bracket all invocations of b receiveNote:b0  (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 b lockPerformanceb0  and b unlockPerformanceb0  is given in 'aaLocking the Performance,'ba later in this chapter.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 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'd0notably that described in the next section'd0there isn'27t much reason to do so:  One NoteReceiver is as good as the next.  Any number of Note-producing agents'd0whether Performers or different mechanisms in your application'd0can all send b receiveNote:b0  to the same NoteReceiver.  In general, adding a gaggle of NoteReceivers to an Instrument doesn'27t make the Instrument more interesting, it simply makes it bigger.
fs16 
fs28 s18 b fs28 fs16 



fs28 Squelching a NoteReceiver
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 You can throttle a NoteReceiver'27s ability to invoke b realizeNote:fromNoteReceiver:b0  by sending it the b squelchb0  message.  To release this clench, you invoke b unsquelchb0 .  Through this simple feature, you can easily and quickly mute an Instrument.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 While a NoteReceiver is squelched, the b receiveNote:b0  method ceases to function:  It immediately returns b nilb0  without forwarding the argument Note to the NoteReceiver'27s owner (unsquelched, b receiveNote:b0  returns b selfb0 ).  Realization of the Note isn'27t merely deferred, it'27s abandoned for good.  You can determine whether a NoteReceiver is squelched by sending it the b isSquelchedb0  message:  If the message returns YES, the object is squelched.
fs16 
fs28 fs16 fs28 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.  
fs16 
fs28 s18 b fs28 fs16 



fs28 Performance Status
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 An Instrument is considered to be in performance from the time that you send b receiveNote:b0  to any of its unsquelched NoteReceivers until the performance is over'd0in other words, until the Conductor class receives the b finishPerformanceb0  message.  You can query an Instrument'27s performance status by sending it the b inPerformanceb0  message, where a return of YES signifies that the object is currently in performance.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 The performance status of an Instrument is significant because some Instrument methods aren'27t effective while the Instrument is in performance.  This can be a particularly devilish source of confusion since the state of an Instrument'27s performance doesn'27t require a performance, in the larger sense, to be in progress.  Specifically, if you send b receiveNote:b0  to an Instrument'27s NoteReceiver i beforei0  the Conductor class receives b startPerformanceb0 , the Instrument will, nonetheless, be considered to be performing (and thus the aforementioned performance-status dependent methods will have no effect).  
fs16 
fs28 s17 li1108 fi1007 fi0 b fs36 fs16 



fs36 Realizing Notes
fs16 
fs36 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 There are very few rules when it comes to realizing Notes:  You can implement b realizeNote:fromNoteReceiver:b0  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.  
fs16 
fs28 s18 b fs28 fs16 



fs28 SynthInstrument
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 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:
fs16 
fs28 pard s0 li2620 fi-503 ri1007 ql tx2620 tx3124 tx3628 tx4132 fs16 fs28 'b7	Every instance of SynthInstrument is associated with a single subclass of SynthPatch.
fs16 
fs28 fs16 fs28 'b7	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.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 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.
fs16 
fs28 s25 b i fs16 



fs28 Setting the SynthPatch Subclass
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 i0 fs16 fs28 You set a SynthInstrument'27s SynthPatch subclass by invoking the b setSynthPatchClass:b0  method.  As the method'27s 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 b setSynthPatchClass:orchestra:b0 , passing an Orchestra object as the second argument.
fs16 
fs28 s20 fs16 fs28 b Note:  b0 If you use a SynthPatch class included in the Music Kit, you must import the file b <musickit/synthpatches/i ClassNamei0 .h>b0 , where b i ClassNamei0 b0  is the name of the class you wish to use.  Alternatively, the file b <musickit/synthpatches/synthpatches.h>b0  will import all the Music Kit SynthPatch interface files.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 b The setSynthPatchClass:b0  method (and theb  ...orchestra:b0  version) checks its (first) argument to ensure that it'27s a class that inherits from SynthPatch, returning b nilb0  if it doesn'27t.  It also returns b nilb0  (and doesn'27t set the class) if the SynthInstrument is already involved in a performance.
fs16 
fs28 s25 b i fs16 



fs28 Allocation Mode
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 i0 fs16 fs28 SynthInstrument defines two allocation modes:
fs16 
fs28 pard s0 li2620 fi-503 ri1007 ql tx2620 tx3124 tx3628 tx4132 fs16 fs28 'b7	Ini  automatic allocation modei0  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'27s 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'27t match, the SynthInstrument allocates a new SynthPatch.
fs16 
fs28 fs16 fs28 'b7	In i manual allocation modei0  the SynthPatch objects are allocated all at once, before Notes begin to arrive.  The number of SynthPatches to allocate is set through the method b setSynthPatchCount:b0 .  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.  
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 By default, a SynthInstrument is in automatic allocation mode.  Simply sending b setSynthPatchCount: b0 places it in manual mode.  To set it back to automatic mode, you send it the b autoAllocb0  message.  A SynthInstrument can'27t switch modes while it'27s performing.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 You can query a SynthInstrument'27s allocation mode by invoking b allocModeb0 , a method that returns one of the following integer constants:
fs16 
fs28 pard s28 li2620 fi0 ri1007 ql b tx6652 tx8668 tx10684 fs16 fs28 Constant	Modeb0  
s16 tx6652 tx8668 tx10684 MK_AUTOALLOC	Automatic allocation
fi0 MK_MANUALALLOC	Manual allocation
fs16 
fs28 pard s25 li2116 fi0 ri1007 ql b i fs16 



fs28 Changing the SynthPatch Count
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 i0 fs16 fs28 You can change the number of manually allocated SynthPatches at any time'd0even during a performance'd0simply by resending the b setSynthPatchCount:b0  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'd0it doesn'27t represent the number of new objects to allocate.  For example, in the following sequence of messages, a total of four SynthPatches are allocated.
fs16 
fs28 s14 li2620 fi-503 fi0 f2 fs24 /* Allocate three SynthPatches. */
fi0 [aSynthIns setSynthPatchCount:3];
fi0 . . .
fi0 
fi0 /* Allocate one more. */
fi0 [aSynthIns setSynthPatchCount:4];
pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 f1 fs28 fs16 
fs28 The b synthPatchCountb0  method returns the number of manually allocated SynthPatches.  Thus, the previous example can be rewritten as
fs16 
fs28 s14 li2620 fi-503 fi0 f2 fs24 /* Allocate three SynthPatches. */
fi0 [aSynthIns setSynthPatchCount:3];
fi0 . . .
fi0 
fi0 /* Allocate one more. */
fi0 [aSynthIns setSynthPatchCount:[aSynthIns synthPatchCount]+1];
pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 f1 fs28 fs16 
fs28 If the SynthInstrument is in automatic mode, b synthPatchCountb0  returns 0.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 Deallocating SynthPatch objects is also possible:
fs16 
fs28 s14 li2620 fi-503 fi0 f2 fs24 /* Allocate three SynthPatches. */
fi0 [aSynthIns setSynthPatchCount:3];
fi0 . . .
fi0 
fi0 /* Deallocate two of them. */
fi0 [aSynthIns setSynthPatchCount:[aSynthIns synthPatchCount]f1 fs28 -f2 fs24 2];
pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 f1 fs28 fs16 
fs28 If the argument signifies a deallocation, the SynthInstrument'27s idle SynthPatches, if any, are deallocated first; the balance are deallocated as they become inactive.
fs16 
fs28 s25 b i fs16 



fs28 The PatchTemplate
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 i0 fs16 fs28 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'27s synthesizing specifies vibrato.  It does this to be as efficient as possible'd0excluding vibrato from Fm1vi'27s configuration means that it uses less of the Orchestra'27s resources.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 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 b setSynthPatchCount:forPatchTemplate:b0  method.  The second argument is the b idb0  of the PatchTemplate that you want.  This is returned by sending the b patchTemplateFor:b0  message to the SynthInstrument'27s SynthPatch class, with a Note object as the argument.  This is best explained by example:
fs16 
fs28 s14 li2620 fi-503 fi0 f2 fs24 /* Create a SynthInstrument. */
fi0 id  aSynthIns = [[SynthInstrument init] alloc];
fi0 
/* Create a variable to store the PatchTemplate. */
fi0 id  noVibTemplate;
fi0 
/* Create a dummy Note. */
fi0 id  aNote = [[Note init] alloc];
fi0 
/* Set its vibrato amplitudes to 0.0. */
fi0 [aNote setPar:MK_svibAmp toDouble:0.0];
fi0 [aNote setPar:MK_rvibAmp toDouble:0.0];
fi0 
fi0 /* Retrieve the PatchTemplate senza vibrato. */
fi0 noVibTemplate = [[aSynthIns synthPatchClass]
fi0             patchTemplateFor:aNote];
fi0 
fi0 /* Allocate three vibratoless SynthPatches. */
fi0 [aSynthIns setSynthPatchCount:3
fi0             forPatchTemplate:noVibTemplate];
pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 f1 fs28 fs16 
fs28 If the PatchTemplate isn'27t specified, the SynthPatches are created using the i default PatchTemplatei0 .  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 b patchTemplateFor:b0 ) a Note that explicitly sets the vibrato parameters to 0.0.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 Within the same SynthInstrument, you can manually allocate SynthPatches that use different PatchTemplates.  The following extension of the previous example demonstrates this:
fs16 
fs28 s14 li2620 fi-503 fi0 f2 fs24 /* Allocate one vibratoless SynthPatch. */
fi0 [aSynthIns setSynthPatchCount:1
fi0             forPatchTemplate:noVibTemplate];
fi0 
fi0 /* And two with vibrato. */
fi0 [aSynthIns setSynthPatchCount:2];
pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 f1 fs28 fs16 
fs28 b setSynthPatchCount:b0  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'27s forwarded to the SynthPatch that excludes vibrato; otherwise, it'27s sent to one of the other two SynthPatches.  
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 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 b synthPatchCountForPatchTemplate:b0 .  The b synthPatchCountb0  method, used in an example in the previous section, returns the count for the default PatchTemplate.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 If the SynthPatch is in automatic mode, you don'27t 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.
fs16 
fs28 s25 b i fs16 



fs28 Talking to the SynthPatches
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 i0 fs16 fs28 A SynthInstrument'27s 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:
fs16 
fs28 pard s10 li2620 fi-503 ri1007 ql tx2620 tx3124 tx3628 tx4132 'b7	b noteOn:b0  is used to forward a noteOn type Note.
'b7	b noteUpdate:b0  forwards noteUpdates.
'b7	b noteOff:b0 , likely enough, forwards noteOffs.
pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 
fs28 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.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 Notice that noteDurs and mutes aren'27t included in this scheme.  A noteDur is split into a noteOn/noteOff pair.  If the noteDur doesn'27t have a noteTag, a unique noteTag is created and given to the two new Notes.  Mutes are simply ignored.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 Besides forwarding Notes, the b noteOn:b0  and b noteOff:b0  methods also set a SynthPatch'27s i synthesis statusi0 .  This describes the object'27s current synthesis state as one of the following MKSynthStatus constants:
fs16 
fs28 pard s28 li2620 fi0 ri1007 ql b tx5140 tx6652 tx8668 tx10684 fs16 fs28 Constant	Meaningb0  
s16 tx5140 tx6652 tx8668 tx10684 MK_idle	The SynthPatch is currently inactive.
fi0 MK_running	The SynthPatch is synthesizing the body of a musical note.
fi0 MK_finishing	The SynthPatch is in the release portions of its Envelopes.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 The b noteOn:b0  message sets the synthesis status to b b0 MK_running; b noteOff:b0  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'27s 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'27s 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.
fs16 
fs28 s25 b i fs16 



fs28 The Update State
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 i0 fs16 fs28 The SynthInstrument class gives special consideration to a noteUpdate that doesn'27t have a note tag:
fs16 
fs28 pard s0 li2620 fi-503 ri1007 ql tx2620 tx3124 tx3628 tx4132 fs16 fs28 'b7	The noteUpdate is forwarded to all the active SynthPatches (within the SynthInstrument that received the Note).
fs16 
fs28 fs16 fs28 'b7	The Note'27s parameters are stored in the SynthInstrument'27s i update statei0 .
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 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'd0in the case of a parameter collision, the noteOn'27s parameter takes precedence.  Conversely, a noteOn'27s parameters never affect the update state, it can only be changed by another noteUpdate with no note tag.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 As a demonstration of these principles, consider the following scorefile excerpt:
fs16 
fs28 s14 li2620 fi-503 fi0 f2 fs24 /* Scorefile body excerpt. */
fi0 t 0.0;
fi0 part1 (noteUpdate) amp:.25;
fi0 
fi0 t 1.0;
fi0 part1 (noteOn 1) freq:c4;     /* amplitude is .25 */
fi0 t 2.0;
fi0 part1 (noteOff 1);
fi0 t 3.0;
fi0 part1 (noteOn 2) freq:d4 amp:.75; /* amplitude is .75 */
fi0 t 4.0;
fi0 part1 (noteOff 2);
fi0 
fi0 t 5.0;
fi0 part1 (noteOn 3) freq:e4;     /* amplitude is, once again, .25 */
fi0 t 6.0;
fi0 part1 (noteUpdate) amp:.5; 
fi0 t 7.0;
fi0 part1 (noteUpdate 3) amp:.25; 
fi0 t 8.0;
fi0 part1 (noteOff 3);
fi0 
fi0 t 9.0;
fi0 part1 (noteOn 4) freq: f4;    /* amplitude is .5 */
fi0 t 10.0;
fi0 part1 (noteOff 4);
pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 f1 fs28 fs16 
fs28 The initial note tag-less noteUpdate sets the amplitude parameter in the SynthInstrument'27s update state; notice that the update state is set even though the SynthInstrument doesn'27t have any active SynthPatches.  Of the four subsequent noteOns, the first, third, and fourth don'27t 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.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 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'27s note tag matches that of the active SynthPatch; it'27s forwarded to the SynthPatch but doesn'27t affect the update state.
fs16 
fs28 s25 b i fs16 



fs28 Preempting a SynthPatch
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 i0 fs16 fs28 While the DSP makes a great synthesizer, its resources are by no means unlimited.  It'27s 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.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 When a SynthInstrument can'27t 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:
fs16 
fs28 pard s19 li2620 fi-503 ri1007 ql tx2620 tx3124 tx3628 tx4132 fs16 fs28 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'27s needed to synthesize the new Note.
fs16 
fs28 s23 fs16 fs28 2.	If there'27s more than one such SynthPatch, the one that first received a b noteOff:b0  message, if any, is preempted.  In other words, the preemption scheme first looks for a SynthPatch whose synthesis status is MK_finishing.
fs16 
fs28 fs16 fs28 3.	If there aren'27t any finishing SynthPatches, the oldest SynthPatch is chosen.
fs16 
fs28 fs16 fs28 4.	If a SynthPatch with the appropriate PatchTemplate isn'27t available, the SynthInstrument tries other SynthPatches until one is found that has sufficient resources to synthesize the new Note.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 A SynthInstrument object can only preempt its own SynthPatches'd0it can'27t 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'27t be synthesized.
fs16 
fs28 s25 b i fs16 



fs28 Providing Your Own Preemption Scheme
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 i0 fs16 fs28 The determination of which SynthPatch to preempt is performed in the b preemptSynthPatchFor:patches:b0  method:  The method'27s 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.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 The method is automatically invoked when the SynthInstrument has to preempt a SynthPatch.  The two arguments are:
fs16 
fs28 pard s10 li2620 fi-503 ri1007 ql tx2620 tx3124 tx3628 tx4132 'b7	The newly arrived Note
'b7	The first in a list of candidate SynthPatches
pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 
fs28 Notice that the second argument is a single SynthPatch object.  To get to the next object in the list, you send b nextb0  to the SynthPatch at hand.
fs16 
fs28 s18 b fs28 fs16 



fs28 Midi
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 The Midi class isn'27t a true Instrument'd0it inherits from Object.  However, it creates NoteReceivers and implements b realizeNote:fromNoteReceiver:b0  and so can be used as an Instrument.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 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 b channelNoteReceiver:b0  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 'aamidi0'ba or 'aamidi1,'ba in the b allocFromZone:onDevice: b0 method.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 When it receives a Note, the Midi object translates it into a series of MIDI messages, based on the Note'27s note type and parameters that it contains.  It then sends the messages out the serial port.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 A Midi object has a device status that'27s 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 b openb0  and b runb0  methods.
fs16 
fs28 s18 b fs28 fs16 



fs28 PartRecorder and ScoreRecorder
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 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'27s associated.  The NoteReceiver is created automatically; the Part must be set by your application, through the b setPart:b0  method.  
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 A PartRecorder sets a Note'27s 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 'aatime unit.'ba  You can set the time unit through the b setTimeUnit:b0  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.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 ScoreRecorder isn'27t actually an Instrument; it'27s 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.
fs16 
fs28 s18 b fs28 fs16 



fs28 ScorefileWriter
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 A ScorefileWriter object realizes Notes by writing them to a scorefile.  It'27s 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'27s written.  Typically, you name the NoteReceivers that you create; these names are used to identify the corresponding Part-representations in the scorefile:
fs16 
fs28 s14 li2620 fi-503 fi0 f2 fs24 /* Create a ScorefileWriter and add to it 3 NoteReceivers. */
fi0 id aSFWriter = [[ScorefileWriter alloc] init];
fi0 id fordReceiver = [[NoteReceiver alloc] init];
fi0 id pageReceiver = [[NoteReceiver alloc] init];
fi0 id quicklyReceiver = [[NoteReceiver alloc] init];
fi0 
fi0 /* Name the NoteReceivers. */
fi0 MKNameObject("Ford", fordReceiver);
fi0 MKNameObject("Page", pageReceiver);
fi0 MKNameObject("Quickly", quicklyReceiver);
fi0 
fi0 /* Add the NoteReceivers. */
fi0 [aSFWriter addNoteReceiver:fordReceiver];
fi0 [aSFWriter addNoteReceiver:pageReceiver];
fi0 [aSFWriter addNoteReceiver:quicklyReceiver];
fi0 
fi0 /* Set the ScorefileWriter'27s file by name. */
fi0 [aSFWriter setFile: "Falstaff.score"];
s17 li1108 fi0 f1 b fs36 fs16 




fs36 Creating an Instrument Subclass
fs16 
fs36 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 While there are no strict rules governing realization, intelligent Instrument design should follow these guidelines:
fs16 
fs28 pard s0 li2620 fi-503 ri1007 ql tx2620 tx3124 tx3628 tx4132 fs16 fs28 'b7	An Instrument should realize Notes as it receives them.  It'27s 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.  
fs16 
fs28 fs16 fs28 'b7	If an Instrument needs to alter or store a Note, it should create a copy of the Note and act upon the copy.  
fs16 
fs28 fs16 fs28 'b7	An Instrument shouldn'27t 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'27t mean that an Instrument can'27t create Notes, but it should only do so in response to receiving a Note.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 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 b initb0  method.
fs16 
fs28 s11 li100 fi2015 fi0 b fs36 fs16 



fs36 The Conductor Class
fs16 
fs36 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 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:
fs16 
fs28 pard s0 li2620 fi-503 ri1007 ql tx2620 tx3124 tx3628 tx4132 fs16 fs28 'b7	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.
fs16 
fs28 fs16 fs28 'b7	Each Conductor instance embodies a i message request queuei0 , 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'27s 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'27s tempo).
fs16 
fs28 pard s17 li1108 fi0 ri1007 ql b fs36 fs16 



fs36 Conductors Created by the Music Kit
fs16 
fs36 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 The Music Kit automatically creates two Conductor instances for you, the i clockConductori0  and the i defaultConductori0 :  
fs16 
fs28 pard s0 li2620 fi-503 ri1007 ql tx2620 tx3124 tx3628 tx4132 fs16 fs28 'b7	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'27s reckoned by the other Conductor instances is computed in reference to the clockConductor.  
fs16 
fs28 fs16 fs28 'b7	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.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 The clockConductor is retrieved by sending the b clockConductorb0  message to the Conductor class; similarly, b defaultConductorb0  retrieves the defaultConductor.
fs16 
fs28 s17 li1108 fi1007 fi0 b fs36 fs16 



fs36 The Message Request Queue
fs16 
fs36 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 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 b startPerformanceb0  class method), the Conductor instances begin processing their message queues, sending the requested messages at the appropriate times.  
fs16 
fs28 s20 fs16 fs28 b Note:  b0 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'27t necessary.  The structure is defined without further explanation in the file b /usr/include/musickit/Conductor.hb0 .
fs16 
fs28 s18 b fs28 fs16 



fs28 Creating and Scheduling a Message Request
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 To enqueue a message request with a Conductor, you invoke the b sel:to:atTime:argCount:b0  or b sel:to:withDelay:argCount:b0  method.  The arguments to these methods are similar:
fs16 
fs28 pard s28 li2620 fi0 ri1007 ql b tx6148 tx8668 tx10684 fs16 fs28 Keyword	Argument
s16 b0 tx6148 tx8668 tx10684 sel:	Selector that identifies the method you wish to invoke
fi0 to:	The object that implements the desired method
fi0 atTime: i ori0  withDelay:b 	b0 The time at which you wish the method to be invoked
fi0 argCount:	The number of method arguments, followed by the 
fi0 	arguments themselves, separated by commas
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 The difference between the two methods is the manner in which the time argument is interpreted.  A message request enqueued through the b ...atTime:... b0 method is sent at the specified time measured from the beginning of the performance.  If you use the b ...withDelay:...b0  method, the requested message is sent after the specified amount of time has elapsed since the b sel:to:withDelay:argCount:b0  method itself was invoked (given that a performance is in progress).  Invoked before a performance begins, the two methods are identical.  
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 Once you'27ve made a message request through one of these methods, you can'27t rescind the action; if you need more control over message requests'd0for example, if you need to be able to reschedule or to remove a request'd0you should use the following C functions:
fs16 
fs28 pard s0 li2620 fi-503 ri1007 ql tx2620 tx3124 tx3628 tx4132 fs16 fs28 'b7	b MKNewMsgRequest(double b0 i timei0 ,b  SEL b0 i selectori0 ,b  id b0 i receiveri0 ,b  int b0 i argCounti0 ,b ...)b0  creates a new MKMsgStruct structure and returns a pointer to it.  The arguments are similar, although in a different order, to those of the b sel:to:atTime:argCount:b0  method.
fs16 
fs28 fs16 fs28 'b7	b MKScheduleMsgRequest(MKMsgStruct b0 *i aMsgStructPtri0 ,b  id b0 i conductorb i0 )b0  places the structure pointed to by i aMsgStructPtri0 , which was previously created through b MKNewMsgRequest()b0 , in i conductori0 '27s message request queue.
fs16 
fs28 fs16 fs28 'b7	b MKRepositionMsgRequest(MKMsgStruct b0 *i aMsgStructPtri0 , b double b0 i timeb i0 )b0  repositions a message request within a Conductor'27s queue.  The value of the i timei0  argument is absolute:  It indicates the request'27s new position as the number of beats since the beginning of the performance.  
fs16 
fs28 fs16 fs28 'b7	b MKCancelMsgRequest(MKMsgStruct b0 *i aMsgStructPtrb i0 )b0  removes a message request.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 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 b beforePerformanceSel:to:argCount:b0  and b afterPerformanceSel:to:argCount: b0 enqueue message requests in the before- and after-performance queues, respectively.
fs16 
fs28 pard s18 li2116 fi0 ri1007 ql b fs28 fs16 



fs28 Controlling a Performance
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 As previously mentioned, a Music Kit performance starts when the Conductor class receives the b startPerformanceb0  message.  This starts the Conductor'27s clock ticking (as represented by the clockConductor).  If you'27re synthesizing music on the DSP or sending messages to an external MIDI synthesizer, you should send the b runb0  message to the Orchestra class or to your Midi object at virtually the same time that you invoke b startPerformanceb0 :
fs16 
fs28 s14 li2620 fi-503 fi0 f2 fs24 /* Start Midi, the DSP, and the performance at the same time. */
fi0 [aMidi run];  /* assuming aMidi was previously created */ 
fi0 [Orchestra run];
fi0 [Conductor startPerformance];
pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 f1 fs28 fs16 
fs28 When it receives b startPerformanceb0 , 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 b finishPerformanceb0 , at which time the after-performance messages are sent.  Any message requests that remain in the individual Conductors'27 message request queues are removed.  Note, however, that the before-performance queue isn'27t cleared.  If you invoke b beforePerformanceSel:to:argCount: b0 during a performance, the message request will survive a subsequent b finishPerformanceb0  and will affect the next performance.  
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 By default, if all the Conductors'27 queues become empty at the same time (not including the before- and after-performance queues), b finishPerformanceb0  is invoked automatically.  This is convenient if you'27re 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'27s actions, universally empty queues aren'27t necessarily an indication that the performance is over.  To allow a performance to continue even if all the queues are empty, send b setFinishWhenEmpty:NO b0 to the Conductor class.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 While a performance is in progress, you can pause all Conductor'27s by sending b pausePerformanceb0  to the Conductor class.  A paused performance is resumed through the b resumePerformanceb0  method.  Individual Conductor objects can be paused and resumed through the b pauseb0  and b resumeb0  methods.
fs16 
fs28 s18 b fs28 fs16 



fs28 Setting the Tempo
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 A Conductor'27s tempo controls the rate with which it processes the requests in its message request queue.  Two methods are provided for setting a Conductor object'27s tempo:
fs16 
fs28 pard s0 li2620 fi-503 ri1007 ql tx2620 tx3124 tx3628 tx4132 fs16 fs28 'b7	b setTempo:b0 , which takes a b doubleb0  argument, sets the tempo in beats-per-minute.
fs16 
fs28 s10 'b7	b setBeatSize:b0  also takes a b doubleb0 , but it sets the tempo by defining the duration, in seconds, of a single beat.
pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 
fs28 Regardless of which method you use to set the tempo, the values returned by the retrieval methods b tempob0  and b beatSizeb0  are computed appropriately, as shown in the following example:
fs16 
fs28 s14 li2620 fi-503 fi0 f2 fs24 double bSize;
fi0 
fi0 /* Sets the defaultConductor'27s tempo. */ 
fi0 [[Conductor defaultConductor] setTempo:240.0];
fi0 
fi0 /* Return the beat size; bSize will be 60.0/240.0, or 0.25. */ 
fi0 bSize = [[Conductor defaultConductor] beatSize];
pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 f1 fs28 fs16 
fs28 You can change a Conductor'27s 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'27s tempo is initialized to 60.0 beats per minute.
fs16 
fs28 s18 b fs28 fs16 



fs28 Locking the Performance
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 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; i alli0  Conductors are updated when i anyi0  Conductor sends such a message.  If your application sends a message (or calls a C function) that depends on a Conductor'27s notion of time being current, you must first send b lockPerformanceb0  to the Conductor class.  Every invocation of b lockPerformanceb0  should be balanced by an invocation of b unlockPerformanceb0 .  For example, if you send b receiveNote:b0  to an Instrument'27s NoteReceiver, you must bracket the message with b lockPerformanceb0  and b unlockPerformanceb0 .  (However, invocations of b receiveNote: b0 that areb  b0 requested through a Conductor'27s messge request queue shouldn'27t be bracketed by these methods.)
fs16 
fs28 s18 b fs28 fs16 



fs28 Conductors and Notes
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 Every Note is associated with a Conductor object.  By default, a Note is associated with the defaultConductor.  You can'27t change a Note'27s Conductor directly; only a Performer object can do that (as described in the section on Performers).
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 The association between a Note and a Conductor is of particular importance if the Note is a noteDur that'27s 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'27s duration value.  To do this, a request for the noteOff to be sent in a b receiveNote:b0  message is enqueued with the Note'27s Conductor.  The exact time at which the Note arrives depends, therefore, on this Conductor'27s tempo.  
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 A Note'27s Conductor is also important if you send the Note to an Instrument through NoteReceiver'27s b receiveNote:atTime:b0  or b receiveNote:withDelay:b0  methods.  These methods cause the NoteReceiver to enqueue a b receiveNote:b0  request with the Note'27s Conductor at the specified time:  The former method takes the b atTime:b0  argument as an absolute measure from the beginning of the performance, while the latter measures the b withDelay:b0  argument as some number of beats from the time that it'27s invoked.
fs16 
fs28 s18 b fs28 fs16 



fs28 Conductors and Envelopes
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 The relationship between an Envelope and a Conductor is as important as it is inflexible:  The dispatching of an Envelope'27s breakpoints during DSP synthesis is always done through message requests with the clockConductor.  You don'27t have to do anything to obtain this behavior, it happens automatically through b MKUpdateAsymp()b0 , the function that you use in the design of a SynthPatch subclass to apply an Envelope to a synthesis patch.  
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 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'27t finish until all the breakpoint messages are sent from the clockConductor'27s queue.  This is generally desirable behavior.  Where things can become confusing is if you pause an entire performance (through Conductor'27s b pausePerformanceb0  class method) while Envelopes are being handled.  Not only will all Note handling stop, all Envelopes will freeze as well.  This usually isn'27t pleasant.  
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 One way to avoid the problem is to pause all your Conductor objects, through the b pauseb0  method, rather than pause the entire performance.
fs16 
fs28 s11 li100 fi2015 fi0 b fs36 fs16 



fs36 The Performer Class
fs16 
fs36 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 A Performer object does two things:
fs16 
fs28 pard s0 li2620 fi-503 ri1007 ql tx2620 tx3124 tx3628 tx4132 fs16 fs28 'b7	It generates or otherwise obtains a series of Note objects during a performance.
fs16 
fs28 fs16 fs28 'b7	It acts as a cover for Conductor'27s scheduling mechanism by sequentially and repeatedly requesting invocations of its own b performb0  method.  
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 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)'d0the 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 i Referencei0  for further descriptions of these classes.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 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.
fs16 
fs28 s17 li1108 fi1007 fi0 b fs36 fs16 



fs36 Using a Performer
fs16 
fs36 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 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 'aaspigots.'ba  NoteSenders are analogous to an Instrument'27s NoteReceivers.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 To connect a Performer to an Instrument, you retrieve a NoteSender and NoteReceiver from either, respectively, and connect these objects through the b connect:b0  method, as defined by both NoteSender and NoteReceiver.  For example, to connect a PartPerformer to a SynthInstrument, you would do the following:
fs16 
fs28 s14 li2620 fi-503 fi0 f2 fs24 /* aPartPerformer and aSynthIns are assumed to exist. */
fi0 [[aPartPerformer noteSender] connect:[aSynthIns noteReceiver]];
pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 f1 fs28 fs16 
fs28 Since both classes define the b connect:b0  method, the following is equivalent:
fs16 
fs28 s14 li2620 fi-503 fi0 f2 fs24 /* aPartPerformer and aSynthIns are assumed to exist. */
fi0 [[aSynthIns noteReceiver] connect:[aPartPerformer noteSender]];
pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 f1 fs28 fs16 
fs28 The b noteSenderb0  method returns one of a Performer'27s NoteSenders, just as the b noteReceiverb0  method retrieves one of an Instrument'27s NoteReceivers.  If you'27re 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 b noteSenderb0  method is sufficient.  If it creates more than one, you can retrieve the entire set as a List through the b noteSendersb0  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'27s represented in its scorefile.
fs16 
fs28 s18 b fs28 fs16 



fs28 Activating a Performer
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 To make a Performer run, you send it the b activateb0  message.  This prepares the object for a performance but it doesn'27t actually start performing Notes until you send b startPerformanceb0  to the Conductor class.  If you invoke b activateb0  while a performance is in progress (in other words, i afteri0  you send b startPerformanceb0 ), the Performer will immediately start running.  In addition, the Performer may require subclass-specific preparation; for example, you have to set a PartPerformer'27s Part before you send it the b activateb0  message.  
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 While a Performer is running, you can pause and resume its activity through the b pauseb0 , b pauseFor:b0 , and b resumeb0  methods.  To completely stop a Performer you invoke b deactivateb0 .  In addition, all Performers are automatically deactivated when the Conductor class receives the b finishPerformanceb0  message.  A Performer can be given a delegate object that can be designed to respond to the messages b performerDidActivate:b0 , b performerDidPause:b0 , b performerDidResume:b0 , and b performerDidDeactivate:b0 .  These messages are sent by the Performer at the obvious junctures in its performance.
fs16 
fs28 s18 b fs28 fs16 



fs28 Performers and Conductors
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 Every Performer object is associated with a Conductor.  If you don'27t set a Performer'27s Conductor explicitly (through b setConductor:b0 ), it will be associated with the defaultConductor.  The rate at which a Performer performs its Notes is controlled by its Conductor'27s 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.  
fs16 
fs28 s17 li1108 fi1007 fi0 b fs36 fs16 



fs36 Creating a Performer Subclass
fs16 
fs36 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 The design of a Performer subclass must address three tasks:  acquiring a Note, sending it into a performance, and scheduling the next Note.
fs16 
fs28 s18 b fs28 fs16 



fs28 Acquiring Notes
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 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 b performb0  method.  
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 The b performb0  method can be designed to acquire any number of Notes with a single invocation.   
fs16 
fs28 s18 b fs28 fs16 



fs28 Sending Notes
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 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 b initb0  method.  NoteSenders are created through the usual sequence of b allocb0  and b initb0  messages; they'27re added to a Performer through Performer'27s b addNoteSender:b0  method.  A Performer can add any number of NoteSenders to itself, although it'27s anticipated that most Performers will need only one.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 As part of its implementation of theb  performb0  method, a Performer passes the Note it has acquired as the argument in a b sendNote:b0  message, which it sends to its NoteSenders.  Each NoteSender then relays the Note to the NoteReceivers to which it'27s connected; each NoteReceiver passes the Note to the Instrument that it (the NoteReceiver) belongs to.  Thus, by sending b sendNote:b0  to a NoteSender, a Performer communicates Notes to one or more Instruments.  If more than one Note is acquired in the b performb0  method, each is sent in a separate b sendNote:b0  message.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 b Note:  b0 Methods that are invoked from within the b performb0  method'd0and this includes the b sendNote:b0  method'd0i shouldn'27ti0  be bracketed by b lockPerformanceb0  and b unlockPerformanceb0 .  
fs16 
fs28 s18 b fs28 fs16 



fs28 Scheduling Notes
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 As described above, every time a Performer receives the b performb0  message it acquires a Note and then sends it to its NoteSenders.  The final obligation of the b performb0  method is to schedule its own next invocation.  This is done by setting the value of the b nextPerformb0  instance variable.  The value of b nextPerformb0  is measured in beats according to the tempo of the Conductor and, most important, it'27s taken as a time delay:  If you set b nextPerformb0  to 3.0, for example, the b performb0  method will be invoked after 3.0 beats.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 To get things started, a Performer'27s first b performb0  message is automatically scheduled to be sent just after the Performer is activated.  You can delay this initial invocation by setting the b nextPerformb0  variable from within theb  activateSelfb0  method.  The default implementation of b activateSelfb0  does nothing; a subclass can implement it to provide pre-performance initialization just such as this.  
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 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.  
fs16 
fs28 s11 li100 fi2015 fi0 b fs36 fs16 



fs36 Fine-Tuning a Performance Application
fs16 
fs36 s17 li1108 fi-1007 fi0 fs36 fs16 

fs36 Responsiveness
fs16 
fs36 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 The responsiveness of a performance to the user'27s actions depends on whether the Conductor class is clocked or unclocked, and upon the value of the performance'27s i delta timei0 .  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).  
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 If you don'27t need interactive control over a performance, you may find it beneficial to set it to unclocked by sending b setClocked:NOb0  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'd0the DSP or the MIDI device driver'd0to handle the timing of the actual realization.  
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 Setting the delta time further refines the responsiveness of a performance.  Delta time is set through the b MKSetDeltaT()b0  C function; the argument defines an imposed time lag, in seconds, between the Conductor'27s 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.
fs16 
fs28 s17 li1108 fi1007 fi0 b fs36 fs16 



fs36 Separate-Threaded Performance
fs16 
fs36 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 To enhance the efficiency of a performance, you can run it in its own thread.  This is done by sending b useSeparateThread:YESb0  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'27s other computations.  However, certain restrictions must be adhered to when running a performance in its own thread:
fs16 
fs28 pard s0 li2620 fi-503 ri1007 ql tx2620 tx3124 tx3628 tx4132 fs16 fs28 'b7	You can'27t use ScorefileWriter or ScorefilePerformer objects in the performance.
fs16 
fs28 fs16 fs28 'b7	You can'27t invoke an Orchestra method that changes the Orchestra'27s status; these are b openb0 , b runb0 , b stopb0 , b closeb0 , and b abortb0 .
fs16 
fs28 fs16 fs28 'b7	You can'27t send messages to instances of classes defined by the Application Kit, or to instances of the Sound Kit'27s SoundView and SoundMeter classes.  In addition, you can'27t read or write soundfiles, or play or record sounds through an instance of the Sound Kit'27s Sound class (note, however, that you i cani0  use the sound library functions).
fs16 
fs28 pard s0 li2620 fi-503 ri1007 ql tx2620 tx3124 tx3628 tx4132 fs16 fs28 'b7	You can'27t call DPS client functions.
fs16 
fs28 fs16 fs28 'b7	You can'27t call NXStreams functions.
fs16 
fs28 fs16 fs28 'b7	You can'27t call C functions that rely on standard input and output; these are functions such as b printf()b0  and b scanf()b0 .  Because of this, DSP error logging and Music Kit tracing can'27t be used.  In addition, if you need to handle Music Kit errors, you must provide your own error handler function through b MKSetErrorProc()b0 .
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 These restrictions apply only to that part of your application that'27s 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'27t use an Instrument that sends messages to an Application Kit Window object; however, you can send messages to the Window from your application'27s main thread.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 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 b DPSAddPort()b0  in the main thread.  This is demonstrated in the Ensemble programming example (b /NextDeveloper/Examples/MusicKit/Ensembleb0 ).
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 An important restriction in a multi-threaded performance is that i all i0 messages (or groups of messages) to Music Kit objects sent from the main thread should be bracketed with b lockPerformanceb0  and b unlockPerformanceb0 .
fs16 
fs28 s17 li1108 fi1007 fi0 b fs36 fs16 



fs36 Performance Priority
fs16 
fs36 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 Give your application an unfair advantage through the b setTheadPriority:b0  Conductor class method.  This method sets the Mach-scheduling priority of the performance thread, whether or not it'27s 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 b rootb0  and setting the application'27s protection to include the b set user IDb0  bit.  In a Terminal window, you would type the following:
fs16 
fs28 s14 li2620 fi-503 fi0 f2 fs24 su root 
fi0 chown root i i0 yourAppHerei i0 
fi0 chmod u + s i i0 yourAppHere
s17 li1108 fi0 f1 b fs36 fs16 




fs36 Performing with the DSP
fs16 
fs36 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 You can also shape your performance'27s capabilities by affecting the Orchestra class, thus influencing the manner in which DSP resources are used.
fs16 
fs28 s18 b fs28 fs16 



fs28 Sampling Rate
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 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'27s response time with regard to DSP synthesis by using the high sampling rate, as accomplished by sending the message
fs16 
fs28 s14 li2620 fi-503 fi0 f2 fs24 [Orchestra setSamplingRate:44100.0];
pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 f1 fs28 fs16 
fs28 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 'aabig'ba 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.
fs16 
fs28 s18 b fs28 fs16 



fs28 Sound Buffer Sizes
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 While the speed of the DSP makes real-time synthesis approachable, there'27s always an imposed time delay that'27s equal to the size of the buffer used to collect computed samples before they'27re 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 b setFastResponse:YESb0  message to an Orchestra.  However, the more frequent attention demanded by the smaller buffer will detract from the DSP'27s synthesis computation and, again, fewer simultaneous voices may result.
fs16 
fs28 s18 b fs28 fs16 



fs28 Headroom
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 b0 fs28 fs16 fs28 The Orchestra doesn'27t 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.  
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 You can adjust the Orchestra'27s DSP processing estimate, or i headroomi0 , by invoking the b setHeadroom:b0  Orchestra method.  This takes an argument between f3 -f1 1.0 and 1.0; a negative headroom allows a more liberal estimate of the DSP resources'd0resulting in more simultaneous voices'd0but 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'27t fall out of real time but the number of simultaneous voices is decreased.  The default is a somewhat conservative 0.1.
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 
fs16 
fs28 pard s9 li2116 fi0 ri1007 ql tx2620 tx3124 tx3628 fs16 fs28 
fs16 
fs28 }

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.