17.5 Writing Your Own Player

A Player is an Audio Library software object that works through the Synthesis Driver to construct audio command lists. Both the Sequence Player and Sound player are examples of Players.

A Player operates by signing into the driver and then responding to driver callback with driver API calls, described in Section on synthesis driver. The initialization procedure and the callback routine are detailed below.

UP

17.5.1 Initializing the Player

In order for your player to receive driver callbacks and to use the synthesis driver voice functions, you must first add the player as a driver client. This is accomplished with the alSynAddPlayer() call, which takes two arguments: a reference to the synthesis driver, and a reference to the ALPlayer structure that represents the player to be added. A reference to the synthesis driver may be obtained from the Audio Library globals structure alGlobals. The ALPlayer structure contains a reference to the voice handler callback function and a pointer that the player can use.

Example 17-1 Player Initialization
typedef struct MyPlayer_s {
        ALPlayer node;
        /*
         * include other player specific state here
         */
} MyPlayer;

void playerNew(Myplayer *p)
{
        /*
         * Initialize any player specific state here
         */

        /*
         * Sign into the synthesis driver so that the next time
         * alAudioFrame is called, it will call the
         * __voiceHandler function.
         */
        p->node.next    = NULL;
        p->node.handler = __voiceHandler;
        p->node.clientData      = p;
        alSynAddPlayer(&alGlobals->drvr, &p->node);
}

void playerDelete(MyPlayer *p)
{
        /*
         * remove this player from the synthesis driver
         */
        alSynRemovePlayer(&alGlobals ->drvr, &p->node);
}

In the previous example, you will notice that the player structure contains a reference to __voiceHandler. This field points to a callback procedure, of type ALVoiceHandler, which the driver calls in the process of building the audio command list.

UP

17.5.2 Implementing a Voice Handler

When your application calls alAudioFrame(), the driver iterates through its list of players, calling the player's voice handler functions at the appropriate offset (which translates to time) in the command list.

Typically, the player maintains a time-based list of events which the voice handler parses and translates into driver calls. The voice handler contributes to the construction of the command list by making driver voice calls.

Note: Driver voice calls can be made only from within the voice handler function.

The voice handler returns the time, in microseconds, for the next callback.

Example 17-2 The Voice Handler
ALMicroTime __voiceHandler(void *node)
{
      MyPlayer  *p = (MyPlayer *)node;
      /*
       * You can now make calls to the following synthesis
       * driver voice functions
       *
       *        alSynAllocVoice()
       *        alSynFreeVoice()
       *        alSynStartVoice()
       *        alSynStopVoice()
       *        alSynSetVol()
       *        alSynSetPitch()
       *        alSynSetPan()
       *        alSynSetFXMix()
       *        alSynSetPriority()
       *        alSynGetPriority()
       *        alSynSetFXParam()
       */
      return 1000;   /* call back in 1 millisecond */
}
UP