1 /*---------------------------------------------------------------------------*
2   Project:  Revolution WPAD AX demo
3   File:     wpad_seqdemo.c
4 
5   Copyright (C)2006 Nintendo  All Rights Reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Log: wpad_seqdemo.c,v $
14   Revision 1.13.6.1  2008/08/27 04:50:20  tojo
15   Modified the error handling of controller data.
16 
17   Revision 1.13  2007/07/10 12:14:46  tojo
18   (none)
19 
20   Revision 1.12  2007/05/10 04:17:34  aka
21   Revised to use AXRmtGetSamplesLeft().
22 
23   Revision 1.11  2007/04/23 09:16:08  tojo
24   (none)
25 
26   Revision 1.10  2007/02/09 06:45:13  tojo
27   Modifed to follow the guideline.
28 
29   Revision 1.9  2006/11/21 08:38:15  aka
30   Removed the zero buffer.
31 
32   Revision 1.8  2006/10/23 02:16:23  aka
33   Changed from AXInit() to AXInitSpecifyMem().
34   Changed from MIXInit() to MIXInitSpecifyMem().
35   Changed from SYNInit() to SYNInitSpecifyMem().
36 
37   Revision 1.7  2006/10/23 01:18:00  tojo
38   Called WPADSetConnectCallback before initialization complete.
39 
40   Revision 1.6  2006/10/11 03:03:50  aka
41   Revised AXInit(), MIXInit() and SYNInit().
42 
43   Revision 1.5  2006/09/19 06:35:07  tojo
44   (none)
45 
46   Revision 1.4  2006/09/18 11:59:38  tojo
47   (none)
48 
49   Revision 1.3  2006/09/15 05:49:02  tojo
50   Fixed to corrupt audio streaming
51 
52   Revision 1.2  2006/08/03 13:32:55  tojo
53   Removed old apis.
54 
55   Revision 1.1  2006/07/26 07:47:32  aka
56   Initial check-in.
57 
58 
59   $NoKeywords: $
60  *---------------------------------------------------------------------------*/
61 
62 #include <string.h>
63 
64 #include <demo.h>
65 #include <revolution/mem.h>
66 #include <revolution/mix.h>
67 #include <revolution/syn.h>
68 #include <revolution/seq.h>
69 #include <revolution/wenc.h>
70 #include <revolution/wpad.h>
71 
72 /*---------------------------------------------------------------------------*
73   SEQ
74  *---------------------------------------------------------------------------*/
75 
76 // data
77 #define GM_WT            "/axdemo/synth/gm16adpcm.wt"
78 #define GM_PCM           "/axdemo/synth/gm16adpcm.pcm"
79 #define MIDI_FILE_MAIN   "/axdemo/midi/2nd_time.mid"
80 #define MIDI_FILE_REMOTE "/axdemo/midi/autumnal.mid"
81 
82 // function prototypes
83 static void *LoadFileIntoRam     ( char *path );
84 static void  AudioFrameCallback  ( void );
85 static void  VoiceInitCallback   ( AXVPB *axvpb, SYNSYNTH *synth, u8 midiChannel );
86 static void  VoiceUpdateCallback ( AXVPB *axvpb, SYNSYNTH *synth, u8 midiChannel );
87 
88 /*---------------------------------------------------------------------------*
89   WPAD
90  *---------------------------------------------------------------------------*/
91 
92 // Audio buffers
93 #define SAMPLES_PER_AUDIO_PACKET  40
94 #define AUDIO_PACKET_LEN          20 // SAMPLES_PER_AUDIO_PACKET / 2
95 
96 // allocator functions for WPAD
97 static void *myAlloc ( u32 size );
98 static u8    myFree  ( void *ptr );
99 
100 // function prototypes
101 static void  UpdateSpeaker     ( OSAlarm *alarm, OSContext *context );
102 static void  SpeakerCallback   ( s32 chan, s32 result );
103 static void  SpeakerOnCallback ( s32 chan, s32 result );
104 static void  SpeakerOffCallback( s32 chan, s32 result );
105 static void  ConnectCallback   ( s32 chan, s32 reason );
106 static void  ExtensionCallback ( s32 chan, s32 result );
107 
108 // Speaker Status
109 typedef struct SpeakerInfo
110 {
111     u8           active;
112     WENCInfo     encInfo;
113     BOOL         first;
114     BOOL         last;
115 
116     s32          status;
117     s16          pcmData[SAMPLES_PER_AUDIO_PACKET];
118     u8           encData[AUDIO_PACKET_LEN];
119 
120     OSTime       pending;
121 } SpeakerInfo;
122 
123 typedef union Status
124 {
125     WPADStatus      cr;
126     WPADFSStatus    fs;
127     WPADCLStatus    cl;
128 } Status;
129 
130 // Controller Status
131 typedef struct ContInfo
132 {
133     u32          type;
134     s32          status;
135     Status      currStat;
136     Status      prevStat;
137     SpeakerInfo  Speakers;
138 
139     SEQSEQUENCE  Sequence;
140     u8           play;
141 
142 } ContInfo;
143 
144 static ContInfo  info[WPAD_MAX_CONTROLLERS];
145 
146 // Periodic Alarms for audio streaming
147 static OSAlarm  SpeakerAlarm;
148 
149 
150 /*---------------------------------------------------------------------------*
151   etc.
152  *---------------------------------------------------------------------------*/
153 
154 // Exp Heap
155 static MEMHeapHandle  hExpHeap;
156 
157 // function prototypes
158 static void  initialize();
159 static void  RenderOperation();
160 static void  RenderControllerStatus();
161 
162 /*---------------------------------------------------------------------------*
163  * Name        : main
164  * Description : main
165  * Arguments   : None.
166  * Returns     : None.
167  *---------------------------------------------------------------------------*/
main(void)168 void main ( void )
169 {
170     s32          i;
171     s32          chan;
172     u16          button;
173 
174     void        *arenaMem2Lo;
175     void        *arenaMem2Hi;
176 
177     SEQSEQUENCE  SequenceMain;
178     u8          *MidiFileMain;
179     u8          *MidiFileRemote;
180     u8          *Wavetable;
181     u8          *Pcm;
182     void        *axBuffer;
183     void        *mixBuffer;
184     void        *synBuffer;
185 
186     // Initialize DEMO
187     initialize();
188 
189     // initialize Exp Heap on MEM2
190     arenaMem2Lo = OSGetMEM2ArenaLo();
191     arenaMem2Hi = OSGetMEM2ArenaHi();
192     hExpHeap    = MEMCreateExpHeap(arenaMem2Lo, (u32)arenaMem2Hi - (u32) arenaMem2Lo);
193     ASSERT(hExpHeap != NULL);
194 
195     //
196     // Initialize Audio
197     //
198 
199     axBuffer  = OSAlloc(AXGetMemorySize(AX_MAX_VOICES));
200     mixBuffer = MEMAllocFromExpHeap(hExpHeap, MIXGetMemorySize(AX_MAX_VOICES));
201     synBuffer = MEMAllocFromExpHeap(hExpHeap, SYNGetMemorySize(AX_MAX_VOICES));
202 
203     AIInit(NULL);
204     AXInitSpecifyMem(AX_MAX_VOICES, axBuffer);
205     MIXInitSpecifyMem(mixBuffer);
206     SYNInitSpecifyMem(synBuffer);
207     SEQInit();
208 
209     // Load Audio Data
210     Wavetable      = LoadFileIntoRam(GM_WT);
211     Pcm            = LoadFileIntoRam(GM_PCM);
212     MidiFileMain   = LoadFileIntoRam(MIDI_FILE_MAIN);
213     MidiFileRemote = LoadFileIntoRam(MIDI_FILE_REMOTE);
214 
215     // Register Callback with AX for audio processing
216     AXRegisterCallback(&AudioFrameCallback);
217 
218     // Prepare Sequence for Main
219     SEQAddSequence(&SequenceMain,
220                    MidiFileMain,
221                    Wavetable,
222                    Pcm,
223                    NULL,
224                    16,
225                    15,
226                    1
227                   );
228 
229     // Play Sequence for Main
230     SEQSetState(&SequenceMain, SEQ_STATE_RUNLOOPED);
231 
232     // Prepare Sequence for Remotes
233     for (i = 0; i < WPAD_MAX_CONTROLLERS; i++)
234     {
235         SEQAddSequence(&info[i].Sequence,
236                        MidiFileRemote,
237                        Wavetable,
238                        Pcm,
239                        NULL,
240                        16,
241                        15,
242                        1
243                       );
244         SYNSetMasterVolume(  &info[i].Sequence.synth, -960);
245         SYNSetInitCallback(  &info[i].Sequence.synth, VoiceInitCallback);
246         SYNSetUpdateCallback(&info[i].Sequence.synth, VoiceUpdateCallback);
247     }
248 
249     //
250     // Initialize WPAD
251     //
252 
253     WPADRegisterAllocator(myAlloc, myFree);
254 
255     WPADInit();
256 
257     for (i = 0; i < WPAD_MAX_CONTROLLERS; i++)
258     {
259         WPADSetConnectCallback((s32)i, ConnectCallback);
260     }
261 
262     while (WPADGetStatus() != WPAD_STATE_SETUP)
263     {
264         ;
265     }
266 
267     OSCreateAlarm(&SpeakerAlarm);
268     OSSetPeriodicAlarm(&SpeakerAlarm, OSGetTime(), WPAD_STRM_INTERVAL, UpdateSpeaker);
269 
270     // Spin
271     while (1)
272     {
273         for (chan = 0; chan < WPAD_MAX_CONTROLLERS; chan++)
274         {
275             info[chan].status = WPADProbe(chan, &info[chan].type);
276 
277             if (info[chan].status != WPAD_ERR_NO_CONTROLLER)
278             {
279                 WPADRead(chan, &info[chan].currStat.cr);
280 
281                 if (info[chan].currStat.cr.err == WPAD_ERR_NONE
282                 ||  info[chan].currStat.cr.err == WPAD_ERR_CORRUPTED)
283                 {
284                     button = WPADButtonDown(info[chan].prevStat.cr.button, info[chan].currStat.cr.button);
285                     info[chan].prevStat.cr = info[chan].currStat.cr;
286                 }
287                 else
288                 {
289                     button = 0;
290                 }
291                 if (button & WPAD_BUTTON_A)
292                 {
293                     switch (info[chan].Speakers.active)
294                     {
295                         case 0: WPADControlSpeaker(chan, WPAD_SPEAKER_ON, SpeakerOnCallback);   break;
296                         case 1: WPADControlSpeaker(chan, WPAD_SPEAKER_OFF, SpeakerOffCallback); break;
297                         default:                                                                break;
298                     }
299                 }
300 
301                 if (SEQGetState(&info[chan].Sequence) == SEQ_STATE_RUN)
302                 {
303                     info[chan].play = 1;
304                 }
305                 else
306                 {
307                     info[chan].play = 0;
308 
309                     if (info[chan].Speakers.active == 1)
310                     {
311                         info[chan].Speakers.active = 2;
312                         WPADControlSpeaker(chan, WPAD_SPEAKER_OFF, SpeakerOffCallback);
313                     }
314                 }
315             }
316         }
317 
318         DEMOBeforeRender();
319 
320         DEMOPrintf( 16, 16, 0, "WPAD Demo -- WPAD Seqdemo");
321         RenderOperation();
322         RenderControllerStatus();
323         DEMODoneRender();
324     }
325 
326     OSCancelAlarm(&SpeakerAlarm);
327 }
328 
329 /*---------------------------------------------------------------------------*
330  * Name        : UpdateSpeaker
331  * Description :
332  * Arguments   :
333  * Returns     : None.
334  *---------------------------------------------------------------------------*/
UpdateSpeaker(OSAlarm * alarm,OSContext * context)335 static void UpdateSpeaker( OSAlarm *alarm, OSContext *context )
336 {
337 #pragma unused(alarm, context)
338 
339     u32   flag;
340     s32   chan;
341     BOOL  intr;
342 
343     if (SAMPLES_PER_AUDIO_PACKET <= AXRmtGetSamplesLeft())
344     {
345 
346         for(chan = 0; chan < WPAD_MAX_CONTROLLERS; chan++)
347         {
348 
349             AXRmtGetSamples(chan, info[chan].Speakers.pcmData, SAMPLES_PER_AUDIO_PACKET);
350 
351             if (info[chan].Speakers.active)
352             {
353                 intr = OSDisableInterrupts();
354 
355                 if (WPADCanSendStreamData(chan))
356                 {
357                     flag = (info[chan].Speakers.first) ? (u32)WENC_FLAG_FIRST : (u32)WENC_FLAG_CONT;
358                     if (info[chan].Speakers.first)
359                     {
360                         info[chan].Speakers.first = FALSE;
361                     }
362 
363                     WENCGetEncodeData(&info[chan].Speakers.encInfo,
364                                       flag,
365                                       info[chan].Speakers.pcmData,
366                                       SAMPLES_PER_AUDIO_PACKET,
367                                       info[chan].Speakers.encData);
368                     info[chan].Speakers.status = WPADSendStreamData(chan, info[chan].Speakers.encData, AUDIO_PACKET_LEN);
369                 }
370 
371                 OSRestoreInterrupts(intr);
372             }
373         }
374 
375         AXRmtAdvancePtr(SAMPLES_PER_AUDIO_PACKET);
376     }
377 }
378 
379 /*---------------------------------------------------------------------------*
380  * Name        : SpeakerCallback
381  * Description :
382  * Arguments   :
383  * Returns     : None.
384  *---------------------------------------------------------------------------*/
SpeakerCallback(s32 chan,s32 result)385 static void SpeakerCallback( s32 chan, s32 result )
386 {
387     if (result == WPAD_ERR_NONE)
388     {
389         info[chan].Speakers.active = 1;
390         info[chan].Speakers.first  = TRUE;
391         info[chan].Speakers.last   = FALSE;
392         memset(&info[chan].Speakers.encInfo, 0, sizeof(WENCInfo));
393 
394         info[chan].Speakers.status = WPAD_ERR_NONE;
395         memset(info[chan].Speakers.pcmData, 0, SAMPLES_PER_AUDIO_PACKET);
396         memset(info[chan].Speakers.encData, 0, AUDIO_PACKET_LEN);
397         SEQSetState(&info[chan].Sequence, SEQ_STATE_RUN);
398 
399         OSReport("Chan[%d] is ready\n", chan);
400     }
401 }
402 
403 /*---------------------------------------------------------------------------*
404  * Name        : SpeakerOffCallback
405  * Description :
406  * Arguments   :
407  * Returns     : None.
408  *---------------------------------------------------------------------------*/
SpeakerOffCallback(s32 chan,s32 result)409 static void SpeakerOffCallback( s32 chan, s32 result )
410 {
411 #pragma unused(result)
412 
413     SEQSetState(&info[chan].Sequence, SEQ_STATE_STOP);
414     info[chan].Speakers.active = 0;
415 
416     OSReport("Chan[%d] is stopped.\n", chan);
417 }
418 
419 /*---------------------------------------------------------------------------*
420  * Name        : SpeakerOnCallback
421  * Description :
422  * Arguments   :
423  * Returns     : None.
424  *---------------------------------------------------------------------------*/
SpeakerOnCallback(s32 chan,s32 result)425 static void SpeakerOnCallback( s32 chan, s32 result )
426 {
427     if (result == WPAD_ERR_NONE)
428     {
429         WPADControlSpeaker(chan, WPAD_SPEAKER_PLAY, SpeakerCallback);
430     }
431 }
432 
433 /*---------------------------------------------------------------------------*
434  * Name        : ExtensionCallback
435  * Description :
436  * Arguments   :
437  * Returns     : None.
438  *---------------------------------------------------------------------------*/
ExtensionCallback(s32 chan,s32 result)439 static void ExtensionCallback( s32 chan, s32 result )
440 {
441     switch(result)
442     {
443         case WPAD_DEV_CORE:
444         case WPAD_DEV_FUTURE:
445         case WPAD_DEV_NOT_SUPPORTED: WPADSetDataFormat(chan, WPAD_FMT_CORE);      break;
446         case WPAD_DEV_FREESTYLE:     WPADSetDataFormat(chan, WPAD_FMT_FREESTYLE); break;
447         case WPAD_DEV_CLASSIC:       WPADSetDataFormat(chan, WPAD_FMT_CLASSIC);   break;
448     }
449 }
450 
451 /*---------------------------------------------------------------------------*
452  * Name        : ConnectCallback
453  * Description :
454  * Arguments   :
455  * Returns     : None.
456  *---------------------------------------------------------------------------*/
ConnectCallback(s32 chan,s32 reason)457 static void ConnectCallback( s32 chan, s32 reason )
458 {
459     OSReport("ConnectCallback(%d) : %s\n", chan, (reason < 0) ? "disconnect" : "connect");
460 
461     info[chan].Speakers.active = 0;
462     if (reason >= 0)
463     {
464         WPADSetDataFormat(chan, WPAD_FMT_CORE);
465         WPADSetExtensionCallback(chan, ExtensionCallback);
466     }
467     else
468     {
469         SEQSetState(&info[chan].Sequence, SEQ_STATE_STOP);
470         info[chan].play = 0;
471     }
472 }
473 
474 /*---------------------------------------------------------------------------*
475  * Name        : myAlloc
476  * Description :
477  * Arguments   : None.
478  * Returns     : None.
479  *---------------------------------------------------------------------------*/
myAlloc(u32 size)480 static void *myAlloc( u32 size )
481 {
482     void *ptr;
483 
484     ptr = MEMAllocFromExpHeap(hExpHeap, size);
485     ASSERTMSG(ptr, "Memory allocation failed\n");
486 
487     return(ptr);
488 }
489 
490 /*---------------------------------------------------------------------------*
491  * Name        : myFree
492  * Description :
493  * Arguments   : None.
494  * Returns     : None.
495  *---------------------------------------------------------------------------*/
myFree(void * ptr)496 static u8 myFree( void *ptr )
497 {
498     MEMFreeToExpHeap(hExpHeap, ptr);
499     return(1);
500 }
501 
502 /*---------------------------------------------------------------------------*
503  * Name        : AudioFrameCallback
504  * Description : Callback that process audio data per 3ms audio frame.
505  * Arguments   : None.
506  * Returns:    : None.
507  *---------------------------------------------------------------------------*/
AudioFrameCallback(void)508 static void AudioFrameCallback( void )
509 {
510     // run the sequencer
511     SEQRunAudioFrame();
512 
513     // run the synth
514     SYNRunAudioFrame();
515 
516     // tell the mixer to update settings
517     MIXUpdateSettings();
518 }
519 
520 /*---------------------------------------------------------------------------*
521  * Name        : LoadFileIntoRam
522  * Description : Loads a file into memory. Memory is allocated.
523  * Arguments   : path    File to load into main memory
524  * Returns:    : pointer to file in main memory or NULL if not opened
525  *---------------------------------------------------------------------------*/
LoadFileIntoRam(char * path)526 static void *LoadFileIntoRam( char *path )
527 {
528     DVDFileInfo  handle;
529     u32          round_length;
530     s32          read_length;
531     void        *buffer;
532 
533     // Open File
534     if (!DVDOpen(path, &handle))
535     {
536         OSReport("WARNING! Failed to open %s\n", path);
537         return NULL;
538     }
539 
540     // Make sure file length is not 0
541     if (DVDGetLength(&handle) == 0)
542     {
543         OSReport("WARNING! File length is 0\n");
544         return NULL;
545     }
546 
547     round_length = OSRoundUp32B(DVDGetLength(&handle));
548     buffer       = MEMAllocFromExpHeapEx(hExpHeap, round_length,  32);
549 
550     // Make sure we got a buffer
551     if (buffer == NULL)
552     {
553         OSReport("WARNING! Unable to allocate buffer\n");
554         return NULL;
555     }
556 
557     // Read Files
558     read_length  = DVDRead(&handle, buffer, (s32)(round_length), 0);
559 
560     // Make sure we read the file correctly
561     if (read_length <= 0)
562     {
563         OSReport("WARNING! File lenght is wrong\n");
564         return NULL;
565     }
566 
567     return buffer;
568 }
569 
570 /*---------------------------------------------------------------------------*
571  * Name        : RenderOperation
572  * Description :
573  * Arguments   : None.
574  * Returns:    : None.
575  *---------------------------------------------------------------------------*/
576 static const s16 HEIGHT = 10;
RenderOperation(void)577 static void RenderOperation( void )
578 {
579     s16 y = 80;
580 
581     DEMOPrintf( 16, y += HEIGHT, 0, "button A : Start/Stop Sequence");
582 }
583 
584 /*---------------------------------------------------------------------------*
585  * Name        : RenderControllerStatus
586  * Description :
587  * Arguments   : None.
588  * Returns:    : None.
589  *---------------------------------------------------------------------------*/
RenderControllerStatus(void)590 static void RenderControllerStatus( void )
591 {
592     s16 y = 32;
593     int chan;
594 
595     DEMOPrintf( 150, y, 0, "speaker");
596     DEMOPrintf( 220, y, 0, "sequence");
597     for( chan = 0; chan < WPAD_MAX_CONTROLLERS; chan++)
598     {
599         y += HEIGHT;
600         DEMOPrintf( 16, y, 0, "CHAN_%d [%s]",
601             chan,
602             (info[chan].status == WPAD_ERR_NO_CONTROLLER) ? "--" :
603             (info[chan].type == 0) ? "CORE"     :
604             (info[chan].type == 1) ? "NUNCHAKU" :
605             (info[chan].type == 2) ? "CLASSIC"  :
606                                      "UNKNOWN"
607         );
608         DEMOPrintf( 150, y, 0, "%s", (info[chan].Speakers.active == 1) ? "ON"   :
609                                      (info[chan].Speakers.active == 2) ? "MUTE" :
610                                                                          "OFF");
611         DEMOPrintf( 220, y, 0, "%s", (info[chan].play == 0) ?            "STOP" :
612                                                                          "PLAY");
613     }
614 }
615 
616 /*---------------------------------------------------------------------------*
617  * Name        : initialize
618  * Description : Initialize GX.
619  * Arguments   : None.
620  * Returns:    : None.
621  *---------------------------------------------------------------------------*/
initialize(void)622 static void initialize( void )
623 {
624     const GXColor DARKBLUE      = { 0, 0, 64, 255 };
625     const int     SCREEN_WIDTH  = 320;
626     const int     SCREEN_HEIGHT = 240;
627 
628     DEMOInit( &GXNtsc480IntDf );
629     GXSetCopyClear( DARKBLUE, GX_MAX_Z24 );
630     GXCopyDisp( DEMOGetCurrentBuffer(), GX_TRUE );
631     DEMOInitCaption( DM_FT_XLU, SCREEN_WIDTH, SCREEN_HEIGHT );
632     GXSetZMode( GX_ENABLE, GX_ALWAYS, GX_ENABLE );                       // Set pixel processing mode
633     GXSetBlendMode( GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR );    // Translucent mode
634 
635     DEMOPadInit();
636 }
637 
638 /*---------------------------------------------------------------------------*
639  * Name        : VoiceInitCallback
640  * Description :
641  * Arguments   :
642  * Returns:    : None.
643  *---------------------------------------------------------------------------*/
VoiceInitCallback(AXVPB * axvpb,SYNSYNTH * synth,u8 midiChannel)644 static void VoiceInitCallback( AXVPB *axvpb, SYNSYNTH *synth, u8 midiChannel )
645 {
646 #pragma unused(midiChannel)
647 
648     s32 i;
649 
650     for (i = 0; i < WPAD_MAX_CONTROLLERS; i++)
651     {
652         if (synth == &info[i].Sequence.synth)
653         {
654             break;
655         }
656     }
657 
658     switch(i)
659     {
660         case 0:
661             MIXRmtSetVolumes(axvpb, 0, 0, -960, -960, -960, -960, -960, -960, -960);
662             break;
663         case 1:
664             MIXRmtSetVolumes(axvpb, 0, -960, 0, -960, -960, -960, -960, -960, -960);
665             break;
666         case 2:
667             MIXRmtSetVolumes(axvpb, 0, -960, -960, 0, -960, -960, -960, -960, -960);
668             break;
669         default:
670             MIXRmtSetVolumes(axvpb, 0, -960, -960, -960, 0, -960, -960, -960, -960);
671             break;
672     }
673 
674     AXSetVoiceRmtOn(axvpb, AX_PB_REMOTE_ON);
675 }
676 
677 /*---------------------------------------------------------------------------*
678  * Name        : VoiceUpdateCallback
679  * Description :
680  * Arguments   :
681  * Returns:    : None.
682  *---------------------------------------------------------------------------*/
VoiceUpdateCallback(AXVPB * axvpb,SYNSYNTH * synth,u8 midiChannel)683 static void VoiceUpdateCallback( AXVPB *axvpb, SYNSYNTH *synth, u8 midiChannel )
684 {
685 #pragma unused(axvpb)
686 #pragma unused(synth)
687 #pragma unused(midiChannel)
688 }
689