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