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