1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2
3<html>
4
5<head>
6<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
7<LINK rel="stylesheet" type="text/css" href="../CSS/revolution.css">
8<base target="main">
9<title>How to Use Controller Speakers</title>
10</head>
11
12<body>
13
14<h1>Playback from the Controller Speakers</h1>
15
16<P>
17<A href="#Introduction" target="_self">Introduction</A><BR> <A href="#Library"      target="_self">Libraries</A><BR> <A href="#Samples"      target="_self">Sample Programs</A><BR> <A href="#Transfer"     target="_self">Sending Data for the Controller Speaker</A><BR> <A href="#AX_SE"        target="_self">Playing Sound Effects Using AX</A><BR> <A href="#SP_SE"        target="_self">Playing Sound Effects Using SP</A><BR> <A href="#SEQ_MIDI"     target="_self">Using SEQ to Play MIDI</A><BR> <A href="#Control"      target="_self">Controlling the Controller Speaker</A><BR>
18</P>
19
20<H2><A name="Introduction">Introduction</A></H2>
21
22<p>This document explains how to play sounds from the speaker of the Wii Remote, which is the Standard Controller for the Wii. For the rest of this document, the speaker will be referred to as the Controller speaker.</p>
23
24<p>The Revolution 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 normal sounds are played.</p>
25
26<H2><A name="Library">Libraries</A></H2>
27
28<p>The following libraries are required to play sounds from the Controller speaker:</p>
29
30<table border="1" >
31  <tbody>
32	<tr>
33	  <td width="120" align="center" bgcolor="#98FB98">AX</td>
34<td>This library synthesizes audio data for the Controller speaker.</td>
35	</tr>
36	<tr>
37	  <td align="center" bgcolor="#F0E68C">WENC</td>
38<td>This library encodes the PCM data output by the AX library into data for the Controller speaker.</td>
39	</tr>
40	<tr>
41	  <td align="center" bgcolor="#98FB98">WPAD</td>
42<td>This library controls the Controller speaker. It also sends audio data to the Controller speaker.</td>
43	</tr>
44  </tbody>
45</table>
46
47<p>In addition to the above libraries, there are also AX application libraries corresponding to each type of audio data played through the Controller speaker.</p>
48
49<H2><A name="Samples">Sample Programs</A></H2>
50
51<p>The Revolution SDK has several sample programs that use the Controller speaker. These are listed below.</p>
52
53<table border="1" >
54  <tbody>
55	<tr>
56	  <td width="120" align="center" bgcolor="#98FB98">wpad_axdemo.c</td>
57<td>This sample program uses AX to play sound effects through the Controller speaker.</td>
58	</tr>
59	<tr>
60	  <td align="center" bgcolor="#F0E68C">wpad_spdemo.c</td>
61<td>This sample program uses SP (+AX, MIX) to play sound effects through the Controller speaker.</td>
62	</tr>
63	<tr>
64	  <td align="center" bgcolor="#98FB98">wpad_seqdemo.c</td>
65<td>This sample program uses SEQ (+AX, MIX, SYN) to play MIDI data through the Controller speaker.</td>
66	</tr>
67  </tbody>
68</table>
69
70<p>The sample programs are all located in <CODE>build/demos/wpaddemo/</CODE>.</p>
71
72<H2><A name="Transfer">Sending Data for the Controller Speaker</A></H2>
73
74<p>The sample programs all use the same code to send audio data synthesized by AX to the Controller speaker. That code is shown below.</p>
75
76<blockquote><pre><code>
77#define SAMPLES_PER_AUDIO_PACKET    40
78#define AUDIO_PACKET_MAX_LEN        20
79
80static void UpdateSpeaker(OSAlarm *alarm, OSContext *context)
81{
82#pragma unused(alarm, context)
83
84    u8 data[24];
85    u32 flag;
86    s32 chan;
87    BOOL adv = FALSE;
88
89    for(chan=0; chan&lt;WPAD_MAX_CONTROLLERS; chan++)
90    {
91        if (SAMPLES_PER_AUDIO_PACKET == AXRmtGetSamples(chan, AudioBuffer[chan], SAMPLES_PER_AUDIO_PACKET))
92        {
93            adv = TRUE;
94
95            if (info[chan].Speakers.active)
96            {
97                flag = (info[chan].Speakers.first) ? (u32)WENC_FLAG_FIRST : (u32)WENC_FLAG_CONT;
98                if (info[chan].Speakers.first)
99                {
100                    info[chan].Speakers.first = FALSE;
101                }
102                WENCGetEncodeData(&amp;info[chan].Speakers.encInfo, flag, (const s16*)AudioBuffer[chan], SAMPLES_PER_AUDIO_PACKET, data);
103
104                WPADSendStreamData(chan, data, AUDIO_PACKET_MAX_LEN);
105            }
106        }
107    }
108
109    if (adv)
110    {
111        AXRmtAdvancePtr(SAMPLES_PER_AUDIO_PACKET);
112    }
113}
114</code></pre></blockquote>
115
116<p>The <code>UpdateSpeaker</code> function performs the following processes on each Controller:</p>
117<ol>
118<li>Using the <A href="../ax/Remote/AXRmtGetSamples.html"><code>AXRmtGetSamples</code></A> 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 <code>AudioBuffer[]</code>.</li>
119<li>Using the <A href="../wenc/WENCGetEncodeData.html"><code>WENCGetEncodeData</code></A> function, it takes the data in <code>AudioBuffer[]</code>, encodes it for use by the Controller speaker and outputs it to <code>data[].</code>The <A href="../wenc/WENCGetEncodeData.html"><code>WENCGetEncodeData</code></A> 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.</li>
120<li>Using the <A href="../wpad/WPADSendStreamData.html"><code>WPADSendStreamData</code></A> function, it sends the data in <code>data[]</code> to the Controller speaker.</li>
121</ol>
122<p>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 <A href="../ax/Remote/AXRmtAdvancePtr.html"><code>AXRmtAdvancePtr</code></A> function.</p>
123
124<p>The size (in bytes) of audio data sent to the Controller speaker can be specified in the argument of the <A href="../wpad/WPADSendStreamData.html"><code>WPADSendStreamData</code></A> function. However, the chance of generating a transfer error increases if the size of a single transfer is reduced. <strong>The size of a single transfer should use the maximum size (=20 bytes) that can be specified using the <A href="../wpad/WPADSendStreamData.html"><code>WPADSendStreamData</code></A> function.</strong></p>
125
126<p>The <code>UpdateSpeaker</code> function is registered to an alarm and called once every 6.6666...msec (= 40 samples/6KHz).</p>
127
128<H2><A name="AX_SE">Playing Sound Effects Using AX</A></H2>
129
130<p>The sample program <CODE>wpad_axdemo.c</CODE> uses only AX to play sound effects through the Controller speaker. It is based on the AX sample program <CODE>axsimple.c</CODE> (<CODE>build/demos/axdemo/</CODE>) and has been modified for playback through the Controller speaker.</p>
131
132<p>The excerpts of code shown below are the places where changes have been made to accommodate the Controller speaker.</p>
133
134<blockquote><pre><code>
135static AXVPB* AquireVoiceADPCM(s32 chan, void *pDSPADPCMData)
136{
137    DSPADPCM            *ps = (DSPADPCM*)pDSPADPCMData;
138    AXPBADDR            addr;
139    AXPBADPCM           adpcm;
140    AXPBSRC             src;
141    AXPBADPCMLOOP       adpcmLoop;
142    AXVPB*              voice;
143    u32                 srcBits;
144    u32                 mramAddress;
145    u32                 pMRAMStart;
146
147    // Allocate a voice for use
148    voice = AXAcquireVoice(VOICE_PRIO_MED, VoiceCallback, 0);
149
150         :
151Omitted
152         :
153
154    // Set simple volumes
155    AXSetVoiceMix(voice, &amp;g_mix);
156    AXSetVoiceVe(voice, &amp;g_ve);
157
158    // Set controller speaker
159    AXSetVoiceRmtOn(voice, AX_PB_REMOTE_ON);
160    memset(&amp;g_rmix, 0, sizeof(AXPBRMTMIX));
161    switch(chan)
162    {
163        case WPAD_CHAN0:
164            g_rmix.vMain0 = 0x8000;      // chan0 main
165            g_rmix.vAux0  = 0x8000;      // chan0 aux
166            break;
167        case WPAD_CHAN1:
168            g_rmix.vMain1 = 0x8000;      // chan1 main
169            g_rmix.vAux1  = 0x8000;      // chan1 aux
170            break;
171        case WPAD_CHAN2:
172            g_rmix.vMain2 = 0x8000;      // chan2 main
173            g_rmix.vAux2  = 0x8000;      // chan2 aux
174            break;
175        case WPAD_CHAN3:
176            g_rmix.vMain3 = 0x8000;      // chan3 main
177            g_rmix.vAux3  = 0x8000;      // chan3 aux
178            break;
179    }
180    AXSetVoiceRmtMix(voice, &amp;g_rmix);
181
182    // Set sample rate
183    AXSetVoiceSrcType(voice, AX_SRC_TYPE_LINEAR);
184    AXSetVoiceSrc(voice, &amp;src);
185
186    return voice;
187}
188</code></pre></blockquote>
189
190<p>The code between <code>AXAcquireVoice()</code> and <code>AXSetVoiceVe()</code> is the same as for normal sound playback.</p>
191
192<p>After the settings for normal sound playback are configured, the AX settings for Controller speaker playback are configured.</p>
193
194<ol>
195<li>The <A href="../ax/Voice_Parameters/AXSetVoiceRmtOn.html"><code>AXSetVoiceRmtOn</code></A> function enables the process for synthesizing the configured voices for the Controller speaker.</li>
196<li>The <A href="../ax/Voice_Parameters/AXSetVoiceRmtMix.html"><code>AXSetVoiceRmtMix</code></A> function specifies the mixing parameters of the buses for each Controller speaker. AX has two buses for each Controller speaker: a Main bus and an Aux bus. Note: The Aux bus for the Controller speaker is not yet implemented.</strong></li>
197</ol>
198
199<p>The above settings enable sound effects to be played from the Controller speaker.</p>
200
201<p>Because <CODE>wpad_axdemo.c</CODE> has specifications for playing sound effects only from the Controller speaker, the mixing parameters for normal playback (<CODE>AXPBMIX g_mix</CODE>) all take <CODE>0</CODE>. By entering an appropriate value for <code>g_mix</code> you can play the same sound effect from the Controller speaker and from the TV.</p>
202
203<p>You do not need to be concerned with the playback frequency, 6 KHz, of the Controller speaker. Set the SRC parameters to be the same as they are for normal playback.</p>
204
205<H2><A name="SP_SE">Playing Sound Effects Using SP</A></H2>
206
207<p>The sample program <CODE>wpad_spdemo.c</CODE> uses SP to play sound effects through the Controller speaker. It is based on the SP sample program <CODE>spdemo.c</CODE> (<CODE>build/demos/spdemo/</CODE>) and has been modified for playback through the Controller speaker.</p>
208
209<p>The excerpts of code shown below are the places where changes have been made to accommodate the Controller speaker.</p>
210
211<blockquote><pre><code>
212static void PlaySfx(s32 chan)
213{
214    VoiceInfo *v;
215    BOOL       old;
216
217    old = OSDisableInterrupts();
218
219    v = GetVoice();
220    if (v)
221    {
222        v-&gt;voice = AXAcquireVoice(15, DropVoiceCallback, 0);
223        if (v-&gt;voice)
224        {
225            v-&gt;entry = SPGetSoundEntry(SpTable, (u32)(chan + 1));
226            v-&gt;chan  = chan;
227
228            SPPrepareSound(v-&gt;entry, v-&gt;voice, (v-&gt;entry)-&gt;sampleRate);
229
230            MIXInitChannel(v-&gt;voice, 0, 0, -960, -960, -960, 64, 127, -960);
231            switch(chan)
232            {
233                case 0:
234                    MIXRmtSetVolumes(v-&gt;voice, 0, 0, -960, -960, -960, -960, -960, -960, -960);
235                    break;
236                case 1:
237                    MIXRmtSetVolumes(v-&gt;voice, 0, -960, 0, -960, -960, -960, -960, -960, -960);
238                    break;
239                case 2:
240                    MIXRmtSetVolumes(v-&gt;voice, 0, -960, -960, 0, -960, -960, -960, -960, -960);
241                    break;
242                default:
243                    MIXRmtSetVolumes(v-&gt;voice, 0, -960, -960, -960, 0, -960, -960, -960, -960);
244                    break;
245            }
246
247            AXSetVoiceRmtOn(v-&gt;voice, AX_PB_REMOTE_ON);
248            AXSetVoiceState(v-&gt;voice, AX_PB_STATE_RUN);
249
250            info[chan].play = 1;
251        }
252    }
253
254    OSRestoreInterrupts(old);
255}
256</code></pre></blockquote>
257
258<p>For <CODE>spdemo.c/wpad_spdemo.c</CODE> the mixing parameters are set with the MIX API and not the AX API.</p>
259
260<p>In addition to the settings for normal sound playback, <CODE>wpad_spdemo.c</CODE> also has the following settings for the Controller speaker:</p>
261
262<ol>
263<li>The <A href="./Mixer/MIXRmtSetVolumes.html"><code>MIXRmtSetVolumes</code></A> function specifies the mixing parameters of the buses for each Controller speaker.</li>
264<li>The <A href="../ax/Voice_Parameters/AXSetVoiceRmtOn.html"><code>AXSetVoiceRmtOn</code></A> function enables the process for synthesizing the configured voices for the Controller speaker.</li>
265</ol>
266
267<p>By using the <A href="./Mixer/MIXInitChannel.html"><code>MIXInitChannel</code></A> and <A href="./Mixer/MIXRmtSetVolumes.html"><code>MIXRmtSetVolumes</code></A> functions to set the appropriate mixing parameters for normal playback and for the Controller speakers, you can choose from a variety of combinations of playback routes.</p>
268
269<H2><A name="SEQ_MIDI">Playing MIDI using SEQ</A></H2>
270
271<p>The sample program <CODE>wpad_seqdemo.c</CODE> uses SEQ to play MIDI data through the Controller speaker. It is based on the AX sample program <CODE>seqdemo.c (build/demos/axdemo/)</CODE> and has been modified for playback through the Controller speaker.</p>
272
273<p>The excerpts of code shown below are the places where changes have been made to accommodate the Controller speaker.</p>
274
275<blockquote><pre><code>
276void main (void)
277{
278    s32          i;
279
280         :
281         :
282
283    // Prepare Sequence for Remotes
284    for (i = 0; i &lt; WPAD_MAX_CONTROLLERS; i++)
285    {
286        SEQAddSequence(&amp;info[i].Sequence,
287                       MidiFileRemote,
288                       Wavetable,
289                       Pcm,
290                       ZeroBuffer,
291                       16,
292                       15,
293                       1
294                      );
295        SYNSetMasterVolume(  &amp;info[i].Sequence.synth, -960);
296        SYNSetInitCallback(  &amp;info[i].Sequence.synth, VoiceInitCallback);
297        SYNSetUpdateCallback(&amp;info[i].Sequence.synth, VoiceUpdateCallback);
298    }
299
300         :
301         :
302
303}
304
305static void VoiceInitCallback(AXVPB *axvpb, SYNSYNTH *synth, u8 midiChannel)
306{
307#pragma unused(midiChannel)
308
309    s32 i;
310
311    for (i = 0; i &lt; WPAD_MAX_CONTROLLERS; i++)
312    {
313        if (synth == &amp;info[i].Sequence.synth)
314        {
315            break;
316        }
317    }
318
319    switch(i)
320    {
321        case 0:
322            MIXRmtSetVolumes(axvpb, 0, 0, -960, -960, -960, -960, -960, -960, -960);
323            break;
324        case 1:
325            MIXRmtSetVolumes(axvpb, 0, -960, 0, -960, -960, -960, -960, -960, -960);
326            break;
327        case 2:
328            MIXRmtSetVolumes(axvpb, 0, -960, -960, 0, -960, -960, -960, -960, -960);
329            break;
330        default:
331            MIXRmtSetVolumes(axvpb, 0, -960, -960, -960, 0, -960, -960, -960, -960);
332            break;
333    }
334
335    AXSetVoiceRmtOn(axvpb, AX_PB_REMOTE_ON);
336}
337
338static void VoiceUpdateCallback(AXVPB *axvpb, SYNSYNTH *synth, u8 midiChannel)
339{
340#pragma unused(axvpb)
341#pragma unused(synth)
342#pragma unused(midiChannel)
343}
344</code></pre></blockquote>
345
346<p>In <CODE>wpad_seqdemo.c</CODE>, each Controller speaker plays MIDI data independently. For this purpose, a sequence structure is prepared for each separate Controller speaker.</p>
347
348<p>In order to use the Controller speakers, the following processes are performed inside the <code>main</code> function for each Controller speaker.</p>
349
350<ol>
351<li>The <A href="./Sequencer/SEQAddSequence.html"><code>SEQAddSequence</code></A> function registers the sequence structure for each Controller speaker in the sequence list.</li>
352<li>The <A href="./Synthesizer/SYNSetMasterVolume.html"><code>SYNSetMasterVolume</code></A> function sets the master volume for MIDI playback. The master volume is set to <CODE>-960</CODE> because <CODE>wpad_seqdemo.c</CODE> does not have a specification for playing the MIDI data on TV speakers that normally is played on each Controller speaker.</li>
353<li>The <A href="./Synthesizer/SYNSetInitCallback.html"><code>SYNSetInitCallback</code></A> function registers the callback function that is called during MIDI data playback when the synthesizer status is Note On.</li>
354<li>The <A href="./Synthesizer/SYNSetUpdateCallback.html"><code>SYNSetUpdateCallback</code></A> function registers the callback function called when the synthesizer starts each audio frame during MIDI data playback.</li>
355</ol>
356
357<p>The Note-On callback function <code>VoiceInitCallback</code> is called immediately after the synthesizer performs the Note-On process for normal playback. The synthesizer will pass these arguments to the callback:</p>
358
359<table border="1" >
360  <tbody>
361	<tr>
362	  <td width="120" align="center" bgcolor="#98FB98">axvpb</td>
363<td>The pointer to the voice allocated by the synthesizer at the time of Note-On.</td>
364	</tr>
365	<tr>
366	  <td align="center" bgcolor="#F0E68C">synth</td>
367<td>The pointer to the synthesizer instance to which the voice belongs.</td>
368	</tr>
369	<tr>
370	  <td align="center" bgcolor="#98FB98">midiChannel</td>
371<td>The MIDI channel of the voice.</td>
372	</tr>
373  </tbody>
374</table>
375
376<p>Using these arguments, the settings are configured for playing MIDI data through Controller speakers. The <CODE>wpad_seqdemo.c</CODE> callback function <CODE>VoiceInitCallback</CODE> performs these processes:</p>
377
378<ol>
379<li>Using the <code>synth</code> argument it checks which synthesizer instance for Controller speakers the voice belongs to.</li>
380<li>The <A href="./Mixer/MIXRmtSetVolumes.html"><code>MIXRmtSetVolumes</code></A> function specifies the mixing parameters of the buses for each Controller speaker.</li>
381<li>The <A href="../ax/Voice_Parameters/AXSetVoiceRmtOn.html"><code>AXSetVoiceRmtOn</code></A> function enables the process for synthesizing the configured voices for the Controller speaker.</li>
382</ol>
383
384<p>The <code>VoiceUpdateCallback</code> function, which is the callback at the start of the audio frame, is called immediately after the synthesizer performs the normal playback process, just like the <code>VoiceInitCallback</code> function. The same arguments are also passed from the synthesizer.</p>
385
386<p>In the <CODE>wpad_seqdemo.c</CODE> sample program, no processes are conducted inside the <CODE>VoiceUpdateCallback</CODE> function. However, you could utilize functions like <A href="./Mixer/MIXRmtSetFader.html"><code>MIXRmtSetFader</code></A> to control output from Controller speakers during playback.</p>
387
388<H2><A name="Control">Controlling the Controller Speaker</A></H2>
389
390<p>The <A href="../wpad/WPADControlSpeaker.html"><code>WPADControlSpeaker</code></A> function controls the Controller speaker. It can specify the following commands:</p>
391
392<blockquote><pre><code>
393  #define WPAD_SPEAKER_OFF              0
394  #define WPAD_SPEAKER_ON               1
395  #define WPAD_SPEAKER_MUTE             2
396  #define WPAD_SPEAKER_MUTE_OFF         3
397  #define WPAD_SPEAKER_PLAY             4
398</code></pre></blockquote>
399
400<p>Each command is explained in greater detail below.</p>
401
402<ol>
403<li><code>SPEAKER_ON</code><br> <br> This command powers on and initializes the Sound Module on the Wii Remote. <br><br> When the initialization is complete, the decoder that decompresses audio data transmitted from the Wii console is in the halted state. The <code>PLAY</code> command (explained below) must be used to launch the decoder and play sounds through the Controller speaker.<br><br> Because the decoder state will be initialized, you must specify <code>WENC_FLAG_FIRST</code> for the <code>flag</code> argument of the <A href="../wenc/WENCGetEncodeData.html"><code>WENCGetEncodeData</code></A> function the first time data is encoded after the <code>SPEAKER_ON</code> command is specified.<br><br> If the <code>SPEAKER_ON</code> command is issued again while the Sound Module is running, the decoder state will be initialized.<br> <br></li>
404
405<li><code>SPEAKER_OFF</code><br> <br>This command stops the Sound Module.<br> <br>
406
407<li><code>PLAY</code><br> <br>This command starts the decoder.<br><br> If there are data in Wii Remote audio buffer, the decoder will decompress that data and plays it through the Controller speaker.<br> <br>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.<br><br> When the Wii 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.<br> <br>You may turn the Controller speaker ON and OFF using the <code>SPEAKER_ON</code> and <code>SPEAKER_OFF</code> commands. However, you can control the speaker more effectively and with better response if you retain the <code>PLAY</code> command and control the data transmission to the Controller speaker.<br><br><br> <strong>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).</strong><br> <br></li>
408
409<li><code>MUTE</code><br> <br> This command mutes the output of the Controller speaker.<br><br> When <code>MUTE</code> is specified, the output from the Controller speaker is gradually throttled down.<br><br><br> 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 <code>MUTE</code> command. For this reason, there will be times when playback does not begin from where it left off when the <code>MUTE_OFF</code> command releases the mute on the Controller speaker.<br> <br></li>
410
411<li><code>MUTE_OFF</code><br> <br> This command releases the mute on the output of the Controller speaker.<br> <br></li>
412
413</ol>
414
415<h2>Revision History</h2>
416<p>
4172006/08/10 Initial version.<br>
418</p>
419
420<hr><p>CONFIDENTIAL</p></body>
421</html>
422