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