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