Controller Speaker Encoding (WENC) Library Overview

Introduction
Libraries
Sample Programs
Sending Data for the Controller Speaker
Playing Sound Effects Using SP
Controlling the Controller Speaker

Introduction

The following describes how to play sounds from the speaker of the Wii remote. The speaker will be referred to as the controller speaker.

The Cafe SDK AX library has been expanded with features to synthesize sounds for the controller speaker. By using this new AX library, you can play sounds from the controller speaker in the same way that normal sounds are played.

Libraries

The following libraries are required for playing sounds from the controller speaker:

AX This library synthesizes audio data for the controller speaker.
WENC This library encodes the PCM data output by the AX library into data for the controller speaker.
WPAD This library controls the controller speaker. It also sends audio data to the controller speaker.

In addition to the above libraries, there are AX application libraries corresponding to each type of audio data played through the controller speaker.

Sample Programs

The Cafe SDK has several sample programs that use the controller speaker. These are listed below.

wpad_spdemo.c This sample program uses SP (+AX, MIX) to play sound effects through the controller speaker.

The sample programs are all located in src/demo/wpad/.

Sending Data for the Controller Speaker

The sample programs all use the same code to send audio data synthesized by AX to the controller speaker. That code is shown below.

#define SAMPLES_PER_AUDIO_PACKET    40
#define AUDIO_PACKET_MAX_LEN        20

static void UpdateSpeaker( OSAlarm *alarm, OSContext *context )
{
    s16   pcmData[SAMPLES_PER_AUDIO_PACKET];
    u8    encData[AUDIO_PACKET_LEN];
    s32   chan = 0;

    if (SAMPLES_PER_AUDIO_PACKET <= AXRmtGetSamplesLeft())
    {
        BOOL  gotSamples = FALSE;
        for (chan = 0; chan < WPAD_MAX_CONTROLLERS; chan++)
        {
            if (WPADCanSendStreamData(chan))
            {
                AXRmtGetSamples(chan, pcmData, SAMPLES_PER_AUDIO_PACKET);
                gotSamples = TRUE;

                if (info[chan].Speakers.active)
                {
                    u32 flag = (info[chan].Speakers.first) ? (u32)WENC_FLAG_FIRST : (u32)WENC_FLAG_CONT;

                    if (info[chan].Speakers.first)
                        info[chan].Speakers.first = FALSE;

                    WENCGetEncodeData(
                            &info[chan].Speakers.encInfo,
                            flag,
                            pcmData,
                            SAMPLES_PER_AUDIO_PACKET,
                            encData
                            );

                    WPADSendStreamData(
                            chan,
                            encData,
                            AUDIO_PACKET_LEN
                            );
                }
            }
        }

        if (gotSamples)
        {
            AXRmtAdvancePtr(SAMPLES_PER_AUDIO_PACKET);
        }
    }
}

The UpdateSpeaker function performs the following processes on each controller:

  1. Using the AXRmtGetSamples function, it gets 40 samples of audio data synthesized by AX for the controller speaker (6 KHz, 16-bit monaural PCM data) and puts it in the local pcmData[ ].
  2. Using the WENCGetEncodeData function, it takes the data in pcmData[ ], encodes it for use by the controller speaker and outputs it to encData[ ].The WENCGetEncodeData function compresses the 16-bit PCM data that was input into 4 bits, so the 40 samples fetched from AX are encoded into 20 bytes.
  3. Using the WPADSendStreamData function, it sends the data in encData[ ] to the controller speaker.

After these three functions have been processed, the pointer of the controller speaker audio buffer managed by AX is moved 40 samples forward by the AXRmtAdvancePtr function.

The size (in bytes) of audio data sent to the controller speaker can be specified in the argument of the WPADSendStreamData function. However, the chance of generating a transfer error increases if the size of a single transfer is reduced.

NOTE:
The size of a single transfer should use the maximum size (=20 bytes) that can be specified using the WPADSendStreamData function.

The UpdateSpeaker function is registered to an alarm and called once every 6.6666...msec (= 40 samples/6KHz).

Playing Sound Effects Using SP

The sample program wpad_spdemo.c uses SP to play sound effects through the controller speaker. It is based on the SP sample program spdemo.c (build/demos/spdemo/) and has been modified for playback through the controller speaker.

The excerpts of code shown below are the places where changes have been made to accommodate the controller speaker.

static void PlaySfx( s32 chan )
{
    AXVPB *p_voice = AXAcquireVoiceEx(15, DropVoiceCallback, 0);

    if (p_voice)
    {
        VoiceInfo *p_vinfo;
        AXPB_RMT_ID axRemoteId = AX_RMT_ID0;
        MIXCntrlStruct mixCtrl = { {0, -960, -960}, 64, 127, 0, 0};

        AXVoiceBegin(p_voice); // protect voices under construction

        p_vinfo         = &vInfo[p_voice->index];
        p_vinfo->voice  = p_voice;
        p_vinfo->entry  = SPGetSoundEntry(sp_table, soundIndex);
        p_vinfo->chan   = chan;

        //soundIndex = (soundIndex+1)%(MAX_SOUND_INDEX+1);

        SPPrepareSound(p_vinfo->entry, p_voice, (p_vinfo->entry)->sampleRate);

        AXSetVoiceSrcType(p_voice, AX_SRC_TYPE_LINEAR);
        MIXAssignChannel(p_voice);
        MIXInitInputControl(p_voice, 0, 0);

        switch(chan)
        {
            case WPAD_CHAN0: axRemoteId = AX_RMT_ID0; break;
            case WPAD_CHAN1: axRemoteId = AX_RMT_ID1; break;
            case WPAD_CHAN2: axRemoteId = AX_RMT_ID2; break;
            case WPAD_CHAN3: axRemoteId = AX_RMT_ID3; break;
        }

        MIXInitDeviceControl(p_voice, AX_DEVICE_RMT, axRemoteId, &mixCtrl, 0);
        MIXSetDeviceFader(p_voice, AX_DEVICE_RMT, axRemoteId, volume);

        AXSetVoiceRmtOn(p_voice, AX_PB_REMOTE_ON);
        AXSetVoiceState(p_voice, AX_PB_STATE_RUN);

        info[chan].play = 1;

        AXVoiceEnd(p_voice);
    }
}

For wpad_spdemo.c the mixing parameters are set with the MIX API and not the AX API.

In addition to the settings for normal sound playback, wpad_spdemo.c also has the AXSetVoiceRmtOn function, which enables the process for synthesizing the configured voices for the controller speaker.

Controlling the Controller Speaker

The WPADControlSpeaker function controls the controller speaker. It can specify the following commands:

  #define WPAD_SPEAKER_OFF              0
  #define WPAD_SPEAKER_ON               1
  #define WPAD_SPEAKER_MUTE             2
  #define WPAD_SPEAKER_MUTE_OFF         3
  #define WPAD_SPEAKER_PLAY             4
  #define WPAD_SPEAKER_RESET            5

Each command is explained in greater detail below.

  1. WPAD_SPEAKER_ON

    This command powers on and initializes the Sound Module on the Wii remote.

    When initialization is complete, the decoder that decompresses audio data transmitted from the Wii U console is in the halted state. The PLAY command (explained below) must be used to launch the decoder and play sounds through the controller speaker.

    Because the decoder state is initialized, specify WENC_FLAG_FIRST for the flag argument of the WENCGetEncodeData function when data is encoded for the first time after the SPEAKER_ON command is specified. Even if the SPEAKER_ON command is issued again while the Sound Module is running, the decoder state will be initialized.

  2. WPAD_SPEAKER_OFF

    This command stops the Sound Module.

  3. WPAD_SPEAKER_PLAY

    This command starts the decoder.

    If there are data in Wii remote audio buffer, the decoder will decompress that data and plays it through the controller speaker.

    If there are not any data in the Wii remote audio buffer (or if the buffer has been emptied of data), the decoder will pause (i.e., stop but maintain its state). While paused, the last sample decompressed by the decoder will continue being output to the controller speaker, and this keeps a lid on the level of noise caused by the shortage of data.

    When the Wii U console transmits valid data to the audio buffer while the decoder is in the paused state, the decoder will resume its task of decompressing data.

    You may turn the controller speaker ON and OFF using the SPEAKER_ON and SPEAKER_OFF commands. However, you can control the speaker more effectively and with better response if you retain the PLAY command and control the data transmission to the controller speaker.

    NOTE:
    You should quickly stop data transmissions to the controller speaker when it is no longer necessary to play sound through the controller speaker (i.e., when there is silence).
  4. WPAD_SPEAKER_MUTE

    This command mutes the output of the controller speaker.

    When MUTE is specified, the output from the controller speaker is gradually throttled down.

    This command affects the amplifier of the controller speaker, and not the operations of the decoder. The decoder will continue to consume any valid data in the audio buffer even after the controller speaker output has been throttled down by the MUTE command. For this reason, there will be times when playback does not begin from where it left off when the MUTE_OFF command releases the mute on the controller speaker.

  5. WPAD_SPEAKER_MUTE_OFF

    This command releases the mute on the output of the controller speaker.

  6. WPAD_SPEAKER_RESET

    This command performs the same task as the WPAD_SPEAKER_ON command.

Revision History

2014/03/05 Update the demo code and added WPAD_SPEAKER_RESET definition.
2013/05/08 Automated cleanup pass.
2013/01/15 Fixed bug in the example code.
2012/08/01 Cleanup Pass
2011/08/05 Initial version.


CONFIDENTIAL