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