Apple Developer Connection
Member Login Log In | Not a Member? Contact ADC

< Previous PageNext Page > Hide TOC

Playing Notes With the Note Allocator

Playing a few notes with the note allocator component is simple and straightforward. To play notes that have a piano sound, for example, you need to open up the note allocator component, allocate a note channel with a request for piano, and play. When you’ve finished playing notes, you dispose of the note channel and close the note allocator component. The code to accomplish this is shown in Listing 2-2. Before working through the code, you need to look at some important related data structures.

In this section:

Note-Related Data Structures
Playing Piano Sounds With the Note Allocator


Note-Related Data Structures

A note channel is analogous to a sound channel in that you allocate it, issue commands to it to produce sound, and close it when you’re done. To specify details about the note channel, you use a data structure called a NoteRequest (see Listing 2-1).

Listing 2-1  Note-related data structures

 
struct NoteRequest {
    NoteRequestInfo  info;
    ToneDescription  tone;
};
struct NoteRequestInfo {
    UInt8    flags;
    UInt8    reserved;
    short    polyphony;
    Fixed    typicalPolyphony;
};
struct ToneDescription {
    OSType     synthesizerType;
    Str31    synthesizerName;
    Str31    instrumentName;
    long     instrumentNumber;
    long     gmNumber;
};

The next two fields specify the probable polyphony that the note channel will be used for. Polyphony means, literally, many sounds. A polyphony of 5 means that five notes can be playing simultaneously. The polyphony field enables QTMA to make sure that the allocated note channel can play all the notes you need. The typical polyphony field is a fixed-point number that should be set to the average number of voices the note channel will play; it may be whole or fractional. Some music components use this field to adjust the mixing level for a good volume. If in doubt, set the typical polyphony field to 0X00010000.

The ToneDescription structure is used throughout QTMA to specify a musical instrument sound in a device-independent fashion. This structure’s synthesizerType and synthesizerName fields can request a particular synthesizer to play notes on. Usually, they’re set to 0, meaning “choose the best General MIDI synthesizer.” The gmNumber field indicates the General MIDI (GM) instrument or drum kit sound, which may be any of 135 such sounds supported by many synthesizer manufacturers. (All these sounds are available on a General MIDI Sound Module.) The GM instruments are numbered 1 through 128, and the seven drum kits are numbered 16385 and higher. For synthesizers that accept sounds outside the GM library, you can use the instrumentName and instrumentNumber fields to specify some other sound.

Playing Piano Sounds With the Note Allocator

The routine in Listing 2-2 plays notes in a piano sound with the note allocator component.

Listing 2-2  Playing notes with the note allocator component

 
void PlaySomeNotes(void)
{
    NoteAllocator   na;
    NoteChannel     nc;
    NoteRequest     nr;
    ComponentResult  thisError;
    long        t, i;
    na = 0;
    nc = 0;
    // Open up the note allocator.
    na = OpenDefaultComponent(kNoteAllocatorType, 0);
    if (!na)
        goto goHome;
    // Fill out a NoteRequest using NAStuffToneDescription to help, and
    // allocate a NoteChannel.
    nr.info.flags = 0;
    nr.info.reserved = 0;
    nr.info.polyphony = 2;   // simultaneous tones
    nr.info.typicalPolyphony = 0x00010000; // usually just one note
    thisError = NAStuffToneDescription(na, 1, &nr.tone); // 1 is piano
    thisError = NANewNoteChannel(na, &nr, &nc);
    if (thisError || !nc)
        goto goHome;
    // If we've gotten this far, OK to play some musical notes.
    NAPlayNote(na, nc, 60, 80);     // middle C at velocity 80
    Delay(40, &t);         // delay 2/3 of a second
    NAPlayNote(na, nc, 60, 0);   // middle C at velocity 0: end note
    Delay(40, &t);         // delay 2/3 of a second
    // Obligatory do-loop of rising tones
    for (i = 60; i <= 84; i++) {
        NAPlayNote(na, nc, i, 80);    // pitch i at velocity 80
        NAPlayNote(na, nc, i+7, 80);    // pitch i+7 (musical fifth) at
                                         // velocity 80 
        Delay(10, &t);                   // delay 1/6 of a second
        NAPlayNote(na, nc, i, 0); // pitch i at velocity 0: end note
        NAPlayNote(na, nc, i+7, 0);  // pitch i+7 at velocity 0:
                                        // end note 
    }
goHome:
    if (nc)
        NADisposeNoteChannel(na, nc);
    if (na)
        CloseComponent(na);
}

You start by calling OpenDefaultComponent to open a connection to the note allocator. If this routine returns 0, the component wasn’t opened, most likely because QTMA wasn’t present. Next, you fill in the NoteRequestInfo and ToneDescription structures, calling the note allocator’s NAStuffToneDescription routine and passing it the GM instrument number for piano. This routine fills in the gmNumber field and also fills in the other ToneDescription fields with sensible values, such as the instrument’s name in text form in the instrumentName field. (The routine can be useful for converting a GM instrument number to its text equivalent.)

After allocating the note channel with NANewNoteChannel, you call NAPlayNote to play each note. Notice the last two parameters to NAPlayNote:

ComponentResult NAPlayNote(NoteAllocator na, NoteChannel nc,
    long pitch, long velocity);

The value of the pitch parameter is an integer from 1 to 127, where 60 is middle C, 61 is C sharp, and 59 is C flat, or B. Similarly, 69 is concert A and is played at a nominal audio frequency of 440 Hz.

The velocity parameter’s value is also an integer from 1 to 127, or 0. A velocity of 1 corresponds to just barely touching the musical keyboard, and 127 indicates that the key was struck as hard as possible. Different velocities produce tones of different volumes from the synthesizer. A velocity of 0 means the key was released; the note stops or fades out, as appropriate to the kind of sound being played.

You stop the notes at this point after delaying an appropriate amount of time with a call to the Delay routine. Finally, you dispose of the note channel and close the note allocator component.



< Previous PageNext Page > Hide TOC


Last updated: 2006-01-10




Did this document help you?
Yes: Tell us what works for you.

It’s good, but: Report typos, inaccuracies, and so forth.

It wasn’t helpful: Tell us what would have helped.
Get information on Apple products.
Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Copyright © 2007 Apple Inc.
All rights reserved. | Terms of use | Privacy Notice