1 /*---------------------------------------------------------------------------*
2   Project: Delay (expanded version : Dpl2) Test
3   File:    expdelayDpl2.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: expdelayDpl2.c,v $
14   Revision 1.2  06/09/2006 11:49:25  aka
15   Revised mode from SURROUND to DPL2.
16 
17   Revision 1.1  06/08/2006 08:16:15  aka
18   Imported new demos for new AXFX made by Kawamura-san (EAD).
19 
20   $NoKeywords: $
21  *---------------------------------------------------------------------------*/
22 
23 
24 /*---------------------------------------------------------------------------*
25  * Includes
26  *---------------------------------------------------------------------------*/
27 
28 #include <demo.h>
29 #include <demo/DEMOWin.h>
30 #include <revolution.h>
31 #include <revolution/mix.h>
32 #include <revolution/sp.h>
33 #include <revolution/axfx.h>
34 #include <revolution/axfx_presets.h>
35 #include <revolution/mem.h>
36 #include <string.h>
37 
38 #include "dpl2reverb.h"
39 
40 /*---------------------------------------------------------------------------*
41  * SP data
42  *---------------------------------------------------------------------------*/
43 
44 #define SPT_FILE "/axdemo/dpl2/dpl2reverb.spt"
45 #define SPD_FILE "/axdemo/dpl2/dpl2reverb.spd"
46 
47 // use only a single SP sound table
48 static SPSoundTable *sp_table;
49 static u8           *sp_data;
50 
51 /*---------------------------------------------------------------------------*
52  * Exp Heap
53  *---------------------------------------------------------------------------*/
54 static MEMHeapHandle hExpHeap;
55 
56 /*---------------------------------------------------------------------------*
57  * Zero Buffer
58  *---------------------------------------------------------------------------*/
59 
60 #define ZEROBUFFER_BYTES 256
61 
62 /*---------------------------------------------------------------------------*
63  * AX and Application-layer voice abstraction
64  *---------------------------------------------------------------------------*/
65 
66 // Max number of voices we will support in the abstraction layer
67 #define MAX_DEMO_VOICES 64
68 
69 // Checks SP entry 'type' to see if the voice is looped or not
70 #define mISLOOPED(x) ((x->type)&0x1)
71 
72 int panX;   // pan value for left/right
73 int panY;   // pan value for front/back
74 
75 // Each voice has an associated AX parameter block and an SP entry
76 typedef struct
77 {
78     AXVPB *ax_voice;
79     SPSoundEntry *sp_entry;
80 } DEMO_VOICE;
81 
82 DEMO_VOICE demo_voices[MAX_DEMO_VOICES];
83 
84 // Constructs for Aux-bus effects
85 static AXFX_DELAY_EXP_DPL2       delay;
86 
87 // AX profiling structures
88 
89 // store up to 8 frames, just to be safe
90 #define NUM_AX_PROFILE_FRAMES 8
91 
92 static AXPROFILE        ax_profile[NUM_AX_PROFILE_FRAMES];
93 
94 /*---------------------------------------------------------------------------*
95  * Prototypes
96  *---------------------------------------------------------------------------*/
97 
98 // for AX and voice abstraction layer
99 static void         ax_demo_callback        (void);
100 static void         ax_drop_voice_callback  (void *p);
101 static void         stop_all_voices         (void);
102 static void         stop_voice              (DEMO_VOICE *v);
103 static DEMO_VOICE  *play_sfx                (u32 sfx);
104 
105 // for UI menus
106 static void         MNU_sound               (DEMOWinMenuInfo *menu, u32 item, u32 *result);
107 static void         MNU_position            (DEMOWinMenuInfo *menu, u32 item, u32 *result);
108 static void         MNU_stop_sfx            (DEMOWinMenuInfo *menu, u32 item, u32 *result);
109 static void         MNU_auxa                (DEMOWinMenuInfo *menu, u32 item, u32 *result);
110 static void         MNU_compressor          (DEMOWinMenuInfo *menu, u32 item, u32 *result);
111 static void         MNU_kill_all            (DEMOWinMenuInfo *menu, u32 item, u32 *result);
112 
113 /*---------------------------------------------------------------------------*
114  * User Interface stuff
115  *---------------------------------------------------------------------------*/
116 
117 static u32 soundIndex    = 0;   // current sound effect to play
118 static u32 positionIndex = 0;   // current panning
119 static u32 auxaIndex     = 0;   // current effect to apply to AuxA bus
120 static u32 compressFlag  = 0;   // current compressor state
121 
122 DEMOWinInfo *DebugWin;
123 DEMOWinInfo *PositionWin;
124 
125 DEMOWinMenuItem MenuItem[] =
126 {
127     { "Sound   : (none)",            DEMOWIN_ITM_NONE,       MNU_sound,        NULL },
128     { "AuxA    : (none)",            DEMOWIN_ITM_NONE,       MNU_auxa,         NULL },
129     { "",                            DEMOWIN_ITM_SEPARATOR,  NULL,             NULL },
130     { "Position: C Stick",           DEMOWIN_ITM_NONE,       MNU_position,     NULL },
131     { "",                            DEMOWIN_ITM_SEPARATOR,  NULL,             NULL },
132     { "Compress: No",                DEMOWIN_ITM_NONE,       MNU_compressor,   NULL },
133     { "",                            DEMOWIN_ITM_SEPARATOR,  NULL,             NULL },
134     { "Kill All Voices",             DEMOWIN_ITM_NONE,       MNU_kill_all,     NULL },
135     { "",                            DEMOWIN_ITM_TERMINATOR, NULL,             NULL }
136 
137 };
138 
139 DEMOWinMenuInfo Menu =
140 {
141     "AX DelayExpDpl2 Test",     // title
142     NULL,                       // window handle
143     MenuItem,                   // list of menu items
144      9,                         // max num of items to display at a time
145     DEMOWIN_MNU_NONE,           // attribute flags
146 
147     // user callbacks
148     NULL,                       // callback for menu open event
149     NULL,                       // callback for cursor move event
150     NULL,                       // callback for item select event
151     NULL,                       // callback for cancel event
152 
153     // private members
154     0, 0, 0, 0, 0
155 };
156 
157 DEMOWinMenuInfo *MenuPtr;
158 
159 /*===========================================================================*
160  *                   F U N C T I O N    D E F I N I T I O N S
161  *===========================================================================*/
162 
163 
164 /*---------------------------------------------------------------------------*
165  * VOICE ABSTRACTION LAYER STUFF
166 /*---------------------------------------------------------------------------*
167 
168 
169 /*---------------------------------------------------------------------------*
170  * Name        :
171  * Description :
172  * Arguments   :
173  * Returns     :
174  *---------------------------------------------------------------------------*/
175 
176 
stop_voice(DEMO_VOICE * v)177 static void stop_voice(DEMO_VOICE *v)
178 {
179 
180     u32  i;
181     BOOL old;
182 
183         old = OSDisableInterrupts();
184 
185         for (i=0; i<MAX_DEMO_VOICES; i++)
186         {
187             if (v == &demo_voices[i])
188             {
189                 if (demo_voices[i].ax_voice)
190                 {
191                     if (mISLOOPED(demo_voices[i].sp_entry))
192                     {
193                         SPPrepareEnd(demo_voices[i].sp_entry, demo_voices[i].ax_voice);
194                     }
195                     else
196                     {
197                         AXSetVoiceState(demo_voices[i].ax_voice, AX_PB_STATE_STOP);
198                     }
199 
200                     break;
201                 }
202 
203             }
204         }
205 
206         (void)OSRestoreInterrupts(old);
207 
208 
209 } // end stop_voice()
210 
211 /*---------------------------------------------------------------------------*
212  * Name        :
213  * Description :
214  * Arguments   :
215  * Returns     :
216  *---------------------------------------------------------------------------*/
217 
stop_all_voices(void)218 static void stop_all_voices(void)
219 {
220 
221     u32  i;
222     BOOL old;
223 
224 
225 
226         old = OSDisableInterrupts();
227 
228         for (i=0; i<MAX_DEMO_VOICES; i++)
229         {
230             if (demo_voices[i].ax_voice)
231             {
232                 if (mISLOOPED(demo_voices[i].sp_entry))
233                 {
234                     SPPrepareEnd(demo_voices[i].sp_entry, demo_voices[i].ax_voice);
235                 }
236                 else
237                 {
238                     AXSetVoiceState(demo_voices[i].ax_voice, AX_PB_STATE_STOP);
239                 }
240 
241             }
242 
243         }
244 
245         (void)OSRestoreInterrupts(old);
246 
247 
248 } // end stop_voice()
249 
250 /*---------------------------------------------------------------------------*
251  * Name        :
252  * Description :
253  * Arguments   :
254  * Returns     :
255  *---------------------------------------------------------------------------*/
256 
257 
play_sfx(u32 sfx)258 static DEMO_VOICE *play_sfx(u32 sfx)
259 {
260 
261     AXVPB      *ax_v;
262     DEMO_VOICE *v;
263 
264     BOOL        old;
265 
266 
267         old = OSDisableInterrupts();
268 
269         ax_v = AXAcquireVoice(15, ax_drop_voice_callback, 0);
270 
271         if (ax_v)
272         {
273             // use AX voice index to reference a voice in the demo abstraction layer
274             demo_voices[ax_v->index].ax_voice = ax_v;
275 
276             // assign a pointer for convenience
277             v = &demo_voices[ax_v->index];
278 
279             // grab the requested sound from the SP table
280             v->sp_entry = SPGetSoundEntry(sp_table, sfx);
281 
282             SPPrepareSound(v->sp_entry, v->ax_voice, (v->sp_entry)->sampleRate);
283 
284 
285             MIXInitChannel(v->ax_voice, 0, 0, 0, -960, -960, panX, 127-panY, 0);
286             AXSetVoiceState(v->ax_voice, AX_PB_STATE_RUN);
287 
288             (void)OSRestoreInterrupts(old);
289         }
290         else
291         {
292             v = NULL;
293             (void)OSRestoreInterrupts(old);
294             DEMOWinLogPrintf(DebugWin, "ERROR: AX voice allocation failed.\n");
295 
296         }
297 
298         return(v);
299 
300 } // end play_sfx()
301 
302 
303 /*---------------------------------------------------------------------------*
304  * Name        :
305  * Description :
306  * Arguments   : None.
307  * Returns     : None.
308  *---------------------------------------------------------------------------*/
ax_demo_callback(void)309 static void ax_demo_callback(void)
310 {
311 
312     u32 i;
313 
314         // check for voices which have stopped and remove them from the
315         // abstraction layer
316         for (i=0; i<MAX_DEMO_VOICES; i++)
317         {
318             if (demo_voices[i].ax_voice)
319             {
320                 if ( AX_PB_STATE_STOP == ((demo_voices[i].ax_voice)->pb.state))
321                 {
322                     // if the voice has stopped, clear it from the abstraction layer
323                     MIXReleaseChannel(demo_voices[i].ax_voice);
324                     AXFreeVoice(demo_voices[i].ax_voice);
325                     demo_voices[i].ax_voice = NULL;
326                 }
327                 else
328                 {
329                     // otherwise, update the panning
330                     MIXSetPan(demo_voices[i].ax_voice, panX);
331                     MIXSetSPan(demo_voices[i].ax_voice, 127 - panY);
332                     MIXUpdateSettings();
333                 }
334             }
335         }
336 
337 } // end ax_demo_callback()
338 
339 
340 /*---------------------------------------------------------------------------*
341  * Name        : ax_drop_voice_callback()
342  * Description : Invoked by AX when a voice has been forciby dropped.
343  *               Must delete references to the voice from our abstraction layer
344  *               and release the associated MIXer channel.
345  * Arguments   : None.
346  * Returns     : None.
347  *---------------------------------------------------------------------------*/
ax_drop_voice_callback(void * p)348 static void ax_drop_voice_callback(void *p)
349 {
350 
351     AXVPB *v;
352 
353         v = (AXVPB *)p;
354 
355         MIXReleaseChannel(demo_voices[v->index].ax_voice);
356         demo_voices[v->index].ax_voice = NULL;
357         demo_voices[v->index].sp_entry = NULL;
358 
359 } // end ax_demo_callback()
360 
361 
362 
363 /*---------------------------------------------------------------------------*
364  * MENU FUNCTIONS
365 /*---------------------------------------------------------------------------*
366 
367 /*---------------------------------------------------------------------------*
368  * Name        :
369  * Description :
370  * Arguments   :
371  * Returns     :
372  *---------------------------------------------------------------------------*/
373 
MNU_compressor(DEMOWinMenuInfo * menu,u32 item,u32 * result)374 static void MNU_compressor(DEMOWinMenuInfo *menu, u32 item, u32 *result)
375 {
376 #pragma unused(menu, item, result)
377 
378     BOOL old;
379 
380         old = OSDisableInterrupts();
381 
382         compressFlag ^= 1;
383         AXSetCompressor(compressFlag);
384 
385         (void)OSRestoreInterrupts(old);
386 
387         if (compressFlag)
388         {
389             menu->items[item].name = "Compress: YES";
390         }
391         else
392         {
393             menu->items[item].name = "Compress: NO ";
394         }
395 
396 
397 } // end MNU_compressor()
398 
399 /*---------------------------------------------------------------------------*
400  * Name        :
401  * Description :
402  * Arguments   :
403  * Returns     :
404  *---------------------------------------------------------------------------*/
405 
MNU_kill_all(DEMOWinMenuInfo * menu,u32 item,u32 * result)406 static void MNU_kill_all(DEMOWinMenuInfo *menu, u32 item, u32 *result)
407 {
408 #pragma unused(menu, item, result)
409 
410 
411     u32  i;
412     BOOL old;
413 
414         old = OSDisableInterrupts();
415 
416         for (i=0; i<MAX_DEMO_VOICES; i++)
417         {
418             if (demo_voices[i].ax_voice)
419             {
420                 AXSetVoiceState(demo_voices[i].ax_voice, AX_PB_STATE_STOP);
421             }
422         }
423 
424         (void)OSRestoreInterrupts(old);
425 
426 
427 } // end MNU_kill_all()
428 
429 
430 
431 /*---------------------------------------------------------------------------*
432  * Name        :
433  * Description :
434  * Arguments   :
435  * Returns     :
436  *---------------------------------------------------------------------------*/
437 
MNU_auxa(DEMOWinMenuInfo * menu,u32 item,u32 * result)438 static void MNU_auxa(DEMOWinMenuInfo *menu, u32 item, u32 *result)
439 {
440 #pragma unused(menu, item, result)
441 
442     auxaIndex++;
443 
444     auxaIndex %= 5;
445 
446     switch (auxaIndex)
447     {
448         case 0:
449             AXFXDelayExpShutdownDpl2(&delay);
450             AXRegisterAuxACallback(NULL, NULL);
451             menu->items[item].name = "Delay : (none)";
452             break;
453         case 1:
454             AXFX_PRESET_DELAY_EXP_TYPE1(&delay);
455             AXFXDelayExpSettingsDpl2(&delay);
456             AXRegisterAuxACallback((void*)&AXFXDelayExpCallbackDpl2, (void*)&delay);
457             menu->items[item].name = "Delay : Type 1";
458             break;
459 
460 
461         case 2:
462             AXFX_PRESET_DELAY_EXP_TYPE2(&delay);
463             AXFXDelayExpSettingsDpl2(&delay);
464             AXRegisterAuxACallback((void*)&AXFXDelayExpCallbackDpl2, (void*)&delay);
465             menu->items[item].name = "Delay : Type 2";
466             break;
467 
468         case 3:
469             AXFX_PRESET_DELAY_EXP_FLANGE1(&delay);
470             AXFXDelayExpSettingsDpl2(&delay);
471             AXRegisterAuxACallback((void*)&AXFXDelayExpCallbackDpl2, (void*)&delay);
472             menu->items[item].name = "Delay : Flange 1";
473             break;
474 
475         case 4:
476             AXFX_PRESET_DELAY_EXP_FLANGE2(&delay);
477             AXFXDelayExpSettingsDpl2(&delay);
478             AXRegisterAuxACallback((void*)&AXFXDelayExpCallbackDpl2, (void*)&delay);
479             menu->items[item].name = "Delay : Flange 2";
480             break;
481 
482 
483     }
484 
485 
486 } // end MNU_auxa()
487 
488 
489 /*---------------------------------------------------------------------------*
490  * Name        :
491  * Description :
492  * Arguments   :
493  * Returns     :
494  *---------------------------------------------------------------------------*/
495 
MNU_sound(DEMOWinMenuInfo * menu,u32 item,u32 * result)496 static void MNU_sound(DEMOWinMenuInfo *menu, u32 item, u32 *result)
497 {
498 #pragma unused(result)
499 
500         soundIndex++;
501         soundIndex %= 5;
502 
503 
504         stop_all_voices();
505 
506         switch (soundIndex)
507         {
508             case 0: // None
509 
510                 menu->items[item].name = "Sound   : None";
511                 break;
512 
513             case 1:
514 
515                 play_sfx(SFX_TICK);
516                 menu->items[item].name = "Sound   : TICK";
517 
518                 break;
519 
520             case 2:
521 
522                 play_sfx(SFX_EXPLODE);
523                 menu->items[item].name = "Sound   : EXPLOSION";
524 
525                 break;
526 
527             case 3:
528 
529                 play_sfx(SFX_MACHINEGUN);
530                 menu->items[item].name = "Sound   : MACHINEGUN";
531 
532                 break;
533 
534             case 4:
535 
536                 play_sfx(SFX_SYNTH);
537                 menu->items[item].name = "Sound   : SYNTH";
538 
539                 break;
540 
541         } // end switch()
542 
543 } // end MNU_sound
544 
545 
546 
547 
548 
549 /*---------------------------------------------------------------------------*
550  * Name        :
551  * Description :
552  * Arguments   :
553  * Returns     :
554  *---------------------------------------------------------------------------*/
555 
MNU_position(DEMOWinMenuInfo * menu,u32 item,u32 * result)556 static void MNU_position(DEMOWinMenuInfo *menu, u32 item, u32 *result)
557 {
558 #pragma unused(result)
559 
560         positionIndex++;
561         positionIndex %= 7;
562 
563         switch (positionIndex)
564         {
565             case 0:
566 
567                 menu->items[item].name = "Position: C Stick";
568 
569                 break;
570 
571             case 1:
572 
573                 panX = 0;
574                 panY = 0;
575                 menu->items[item].name = "Position: L";
576 
577                 break;
578 
579             case 2:
580 
581                 panX = 63;
582                 panY = 0;
583                 menu->items[item].name = "Position: C";
584 
585                 break;
586 
587             case 3:
588 
589                 panX = 127;
590                 panY = 0;
591                 menu->items[item].name = "Position: R";
592 
593                 break;
594 
595             case 4:
596 
597                 panX = 0;
598                 panY = 127;
599                 menu->items[item].name = "Position: Ls";
600 
601                 break;
602 
603             case 5:
604 
605                 panX = 127;
606                 panY = 127;
607                 menu->items[item].name = "Position: Rs";
608 
609                 break;
610 
611             case 6:
612 
613                 panX = 63;
614                 panY = 127;
615                 menu->items[item].name = "Position: Bs";
616 
617                 break;
618 
619             }
620 
621 } // end MNU_position()
622 
623 
624 /*---------------------------------------------------------------------------*
625  * Name        : position_win_update()
626  * Description : refresh callback for position window
627  * Arguments   :
628  * Returns     :
629  *---------------------------------------------------------------------------*/
630 
position_win_update(DEMOWinInfo * window)631 static void position_win_update(DEMOWinInfo *window)
632 {
633 
634 
635     int substickX;
636     int substickY;
637 
638     BOOL old;
639 
640     u32 i;
641 
642     u32 cpuCycles;
643     u32 userCycles;
644     u32 axCycles;
645     u32 voices;
646 
647     u32 maxCpuCycles =0;
648     u32 maxUserCycles=0;
649     u32 maxAxCycles  =0;
650     u32 maxVoices    =0;
651 
652 
653         substickX = (MenuPtr->handle)->pad.pads[0].substickX;
654         substickY = (MenuPtr->handle)->pad.pads[0].substickY;
655 
656         // Update panning position
657         if (positionIndex == 0)
658         {
659 
660             // if positionIndex is zero, then get panning information from
661             // the C-stick
662             panX = substickX + 63;
663             panY = (substickY - 63) * -1;
664 
665         }
666 
667         DEMOWinPrintfXY(window, 0, 1, "Pan       : %1.2f ", (f32)panX/127);
668         DEMOWinPrintfXY(window, 0, 2, "SPan      : %1.2f ", (f32)panY/127);
669 
670         old = OSDisableInterrupts();
671 
672         i = AXGetProfile();
673 
674         if (i)
675         {
676             // up to 4 audio frames can complete within a 60Hz video frame
677             // so spin thru the accumulated audio frame profiles and find the peak values
678             while (i)
679             {
680                 i--;
681 
682                 cpuCycles   = (u32)(ax_profile[i].axFrameEnd      - ax_profile[i].axFrameStart);
683                 userCycles  = (u32)(ax_profile[i].userCallbackEnd - ax_profile[i].userCallbackStart);
684                 axCycles    = cpuCycles - userCycles;
685                 voices      = ax_profile[i].axNumVoices;
686 
687                 // find peak values over the last i audio frames
688                 if (cpuCycles > maxCpuCycles)     maxCpuCycles    = cpuCycles;
689                 if (userCycles > maxUserCycles)   maxUserCycles   = userCycles;
690                 if (axCycles > maxAxCycles)       maxAxCycles     = axCycles;
691                 if (voices > maxVoices)           maxVoices       = voices;
692 
693             }
694             (void)OSRestoreInterrupts(old);
695 
696             DEMOWinPrintfXY(window, 0, 4, "Total CPU : %5.2f\n", (f32)OSTicksToNanoseconds(maxCpuCycles) / 50000);
697             DEMOWinPrintfXY(window, 0, 6, "User      : %5.2f\n", (f32)OSTicksToNanoseconds(maxUserCycles) / 50000);
698             DEMOWinPrintfXY(window, 0, 7, "AX        : %5.2f\n", (f32)OSTicksToNanoseconds(maxAxCycles) / 50000);
699             DEMOWinPrintfXY(window, 0, 9, "Voices    : %5d",    maxVoices);
700 
701         }
702 
703         (void)OSRestoreInterrupts(old);
704 
705 }
706 
707 /*---------------------------------------------------------------------------*
708  *---------------------------------------------------------------------------*/
LoadFileIntoRam(char * path)709 static void* LoadFileIntoRam(char *path)
710 {
711     DVDFileInfo handle;
712     u32         round_length;
713     s32         read_length;
714     void        *buffer;
715 
716     // Open File
717     if (!DVDOpen(path, &handle))
718     {
719         OSReport("WARNING! Failed to open %s\n", path);
720         return NULL;
721     }
722 
723     // Make sure file length is not 0
724     if (DVDGetLength(&handle) == 0)
725     {
726         OSReport("WARNING! File length is 0\n");
727         return NULL;
728     }
729 
730     round_length = OSRoundUp32B(DVDGetLength(&handle));
731     buffer       = MEMAllocFromExpHeapEx(hExpHeap, round_length,  32);
732 
733     // Make sure we got a buffer
734     if (buffer == NULL)
735     {
736         OSReport("WARNING! Unable to allocate buffer\n");
737         return NULL;
738     }
739 
740     // Read Files
741     read_length = DVDRead(&handle, buffer, (s32)(round_length), 0);
742 
743     // Make sure we read the file correctly
744     if (read_length <= 0)
745     {
746         OSReport("WARNING! File lenght is wrong\n");
747         return NULL;
748     }
749 
750     return buffer;
751 }
752 
753 /*---------------------------------------------------------------------------*
754  *---------------------------------------------------------------------------*/
PrivateAlloc(u32 size)755 static void* PrivateAlloc(u32 size)
756 {
757     return MEMAllocFromExpHeapEx(hExpHeap, size, 32);
758 }
759 
760 /*---------------------------------------------------------------------------*
761  *---------------------------------------------------------------------------*/
PrivateFree(void * addr)762 static void PrivateFree(void* addr)
763 {
764     MEMFreeToExpHeap(hExpHeap, addr);
765 }
766 
767 /*---------------------------------------------------------------------------*
768  * Name        : main()
769  * Description : Hold on to your seatbelts!
770  * Arguments   : None.
771  * Returns     : None.
772  *---------------------------------------------------------------------------*/
main(void)773 void main(void)
774 {
775     void       *arenaMem2Lo;
776     void       *arenaMem2Hi;
777     u8         *zeroBuffer;
778 
779     // initialize system
780     DEMOInit(NULL);
781     DEMOWinInit();
782 
783     SISetSamplingRate(5);
784 
785     arenaMem2Lo = OSGetMEM2ArenaLo();
786     arenaMem2Hi = OSGetMEM2ArenaHi();
787     hExpHeap    = MEMCreateExpHeap(arenaMem2Lo, (u32)arenaMem2Hi - (u32) arenaMem2Lo);
788 
789     // initialize AI subsystem
790     AIInit(NULL);
791 
792     // initialize AX audio system and MIXer application
793     AXInit();
794     MIXInit();
795 
796     AXSetMode(AX_MODE_DPL2);
797     MIXSetSoundMode(MIX_SOUND_MODE_DPL2);
798 
799     // -----------------------------------------------------------
800     // Load SP data!
801     // -----------------------------------------------------------
802 
803     // Load sound table
804     sp_table = LoadFileIntoRam(SPT_FILE);
805 
806     // Load sound effects
807     sp_data  = LoadFileIntoRam(SPD_FILE);
808 
809     // -----------------------------------------------------------
810     // Prepare Zero Buffer
811     // -----------------------------------------------------------
812     zeroBuffer = MEMAllocFromExpHeapEx(hExpHeap, ZEROBUFFER_BYTES, 8);
813     memset(zeroBuffer, 0, ZEROBUFFER_BYTES);
814     DCFlushRange(zeroBuffer, ZEROBUFFER_BYTES);
815 
816     // -----------------------------------------------------------
817     // initialize sound table!
818     // -----------------------------------------------------------
819     SPInitSoundTable(sp_table, sp_data, zeroBuffer);
820 
821     // -----------------------------------------------------------
822     // Initialize demo voice abstraction layer
823     // -----------------------------------------------------------
824     AXRegisterCallback(ax_demo_callback);
825 
826     // -----------------------------------------------------------
827     // Initialize AUX-bus effects
828     // -----------------------------------------------------------
829     AXFXSetHooks((AXFXAlloc)PrivateAlloc, (AXFXFree)PrivateFree);
830     AXFX_PRESET_DELAY_EXP_TYPE1(&delay);
831     AXFXDelayExpInitDpl2(&delay);
832 
833     // -----------------------------------------------------------
834     // initialize profiling for AX
835     // -----------------------------------------------------------
836     AXInitProfile(ax_profile, NUM_AX_PROFILE_FRAMES);
837 
838     // -----------------------------------------------------------
839     // Invoke menu system!
840     // -----------------------------------------------------------
841     MenuPtr     = DEMOWinCreateMenuWindow(
842         &Menu,
843         20,
844         120
845         );
846 
847     DebugWin    = DEMOWinCreateWindow(
848         (u16)(MenuPtr->handle->x2+10),
849         20,
850         620,
851         440,
852         "Debug",
853         1024,
854         NULL
855         );
856 
857     PositionWin = DEMOWinCreateWindow(
858         (u16)(MenuPtr->handle->x1),
859         (u16)(MenuPtr->handle->y2+10),
860         (u16)(MenuPtr->handle->x2),
861         (u16)(MenuPtr->handle->y2+120),
862         "Position",
863         0,
864         position_win_update
865         );
866 
867     DEMOWinOpenWindow(DebugWin);
868     DEMOWinOpenWindow(PositionWin);
869 
870     DEMOWinLogPrintf(DebugWin, "-------------------------------------\n");
871     DEMOWinLogPrintf(DebugWin, "Delay (expanded version : Dpl2 ) Test\n");
872     DEMOWinLogPrintf(DebugWin, "-------------------------------------\n");
873 
874     DEMOWinLogPrintf(DebugWin, "\n");
875 
876     DEMOWinLogPrintf(DebugWin, "Mode is AX_MODE_DPL2.\n");
877 
878     while (1)
879     {
880 
881         DEMOWinMenu(MenuPtr);
882 
883     }
884 
885 } // end main()
886