1 /*---------------------------------------------------------------------------*
2   Project:  AX Compressor Demo
3   File:     compressor.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: compressor.c,v $
14   Revision 1.9  2006/03/06 09:59:03  kawaset
15   Eliminated warnings.
16 
17   Revision 1.8  02/21/2006 01:04:15  mitu
18   modified am.h path.
19 
20   Revision 1.7  02/20/2006 04:13:07  mitu
21   changed include path from dolphin/ to revolution/.
22 
23   Revision 1.6  02/02/2006 07:30:11  aka
24   Modified using MEM functions instead of OSAlloc()/OSFree().
25 
26   Revision 1.5  02/01/2006 07:47:40  aka
27   Added #ifndef(#ifdef) HOLLYWOOD_REV - #else - #endif.
28 
29   Revision 1.4  2006/01/31 08:07:05  aka
30   Added cast from u32 to u8* in relation to changing API around ARAM.
31 
32   Revision 1.3  2006/01/27 04:54:59  ekwon
33   Corrected "\%" escape sequence warning (replaced with "%%").
34 
35   Revision 1.2  11/08/2005 02:55:02  aka
36   Changed suiting to Revolution's audio spec.
37 
38   Revision 1.1  11/04/2005 05:01:39  aka
39   Imported from dolphin tree.
40 
41     1     1/11/02 3:43p Eugene
42     Demonstration of AX compressor.
43 
44 
45   $NoKeywords: $
46  *---------------------------------------------------------------------------*/
47 
48 /*---------------------------------------------------------------------------*
49  * Includes
50  *---------------------------------------------------------------------------*/
51 
52 #include <demo.h>
53 #include <demo/DEMOWin.h>
54 #include <demo/DEMOAVX.h>
55 #include <revolution.h>
56 #include <revolution/mix.h>
57 #include <revolution/sp.h>
58 #ifndef HOLLYWOOD_REV
59 #include <dolphin/am.h>
60 #else
61 #include <revolution/mem.h>
62 #include <string.h>
63 #endif
64 
65 #include "comp_sp.h"
66 
67 /*---------------------------------------------------------------------------*
68  * SP data
69  *---------------------------------------------------------------------------*/
70 
71 #define SPT_FILE "/AXDEMO/compressor/comp_sp.spt"
72 #define SPD_FILE "/AXDEMO/compressor/comp_sp.spd"
73 
74 static SPSoundTable *sp_table;
75 #ifdef HOLLYWOOD_REV
76 static u8           *sp_data;
77 #endif
78 
79 #ifndef HOLLYWOOD_REV
80  /*---------------------------------------------------------------------------*
81  * ARAM initialization
82  *---------------------------------------------------------------------------*/
83 
84 // Use AR allocator to divide ARAM into 3 blocks
85 #define MAX_ARAM_BLOCKS  3
86 
87 // Give a whopping 8MB of ARAM to audio!
88 #define AUDIO_BLOCK_SIZE_BYTES (8*1024*1024)
89 
90 
91 static u32  aramZeroBase;
92 static u32  aramUserBase;
93 static u32  aramMemArray[MAX_ARAM_BLOCKS];
94 
95 
96 // transfer buffer for ARAM audio manager (AM)
97 #define XFER_BUFFER_SIZE_BYTES (16*1024)
98 
99 u8 xfer_buffer[XFER_BUFFER_SIZE_BYTES] ATTRIBUTE_ALIGN(32);
100 
101 #else
102 /*---------------------------------------------------------------------------*
103  * Exp Heap
104  *---------------------------------------------------------------------------*/
105 static MEMHeapHandle hExpHeap;
106 
107 /*---------------------------------------------------------------------------*
108  * Zero Buffer
109  *---------------------------------------------------------------------------*/
110 #define ZEROBUFFER_BYTES 256
111 #endif
112 
113 /*---------------------------------------------------------------------------*
114  * AX Profiling
115  *---------------------------------------------------------------------------*/
116 
117 // store up to 8 frames, just to be safe
118 #define NUM_AX_PROFILE_FRAMES 8
119 
120 static AXPROFILE        ax_profile[NUM_AX_PROFILE_FRAMES];
121 
122 /*---------------------------------------------------------------------------*
123  * Application-layer voice abstraction
124  *---------------------------------------------------------------------------*/
125 
126 #define MAX_DEMO_VOICES  64
127 
128 typedef struct
129 {
130     AXVPB *ax_voice;
131     SPSoundEntry *sp_entry;
132 
133 } DEMO_VOICE;
134 
135 DEMO_VOICE demo_voice[MAX_DEMO_VOICES];
136 
137 // Checks SP entry 'type' to see if the voice is looped or not
138 #define mISLOOPED(x) ((x->type)&0x1)
139 
140 // flag to track state of compressor!
141 static u32 compressor_mode = AX_COMPRESSOR_ON;
142 
143 
144 /*---------------------------------------------------------------------------*
145  * DEMO-AVX: for snooping output of DSP for clipping
146  *---------------------------------------------------------------------------*/
147 
148 #define AVX_BUFFER_SIZE_WORDS 160
149 
150 s16 __left_channel  [AVX_BUFFER_SIZE_WORDS] ATTRIBUTE_ALIGN(32);
151 s16 __right_channel [AVX_BUFFER_SIZE_WORDS] ATTRIBUTE_ALIGN(32);
152 
153 static u32 clip_tick_left;      // for animating the clip detector
154 static u32 clip_tick_right;     // for animating the clip detector
155 static u32 clip_left;           // for counting number of clips, just for fun
156 static u32 clip_right;          // for counting number of clips, just for fun
157 
158 
159 /*---------------------------------------------------------------------------*
160  * Alarms and such for test processes
161  *---------------------------------------------------------------------------*/
162 
163 #define PING_PERIOD     100   // in milliseconds
164 
165 static OSAlarm PingAlarm;
166 static u32 ping_counter;
167 
168 
169 /*---------------------------------------------------------------------------*
170  * Prototypes
171  *---------------------------------------------------------------------------*/
172 
173 
174 // for user interface
175 static void         MNU_play_click          (DEMOWinMenuInfo *menu, u32 item);
176 static void         MNU_play_hum            (DEMOWinMenuInfo *menu, u32 item, u32 *result);
177 static void         MNU_play_ping           (DEMOWinMenuInfo *menu, u32 item, u32 *result);
178 static void         MNU_play_voice          (DEMOWinMenuInfo *menu, u32 item, u32 *result);
179 static void         MNU_stop_sfx            (DEMOWinMenuInfo *menu, u32 item, u32 *result);
180 static void         MNU_toggle_comp         (DEMOWinMenuInfo *menu, u32 item, u32 *result);
181 static void         MNU_start_ping_test     (DEMOWinMenuInfo *menu, u32 item, u32 *result);
182 static void         MNU_start_voice_test    (DEMOWinMenuInfo *menu, u32 item, u32 *result);
183 
184 
185 // for voice abstraction layer
186 static DEMO_VOICE  *get_demo_voice          (void);
187 static void         init_demo_voices        (void);
188 static void         ax_demo_callback        (void);
189 static void         ax_drop_voice_callback  (void *p);
190 static void         play_sfx                (u32 sfx);
191 static void         stop_all_sfx            (void);
192 static void         ax_profile_update       (DEMOWinInfo *window);
193 
194 // test infrastructure
195 static void         ping_test_refresh       (DEMOWinInfo *handle);
196 static void         ping_alarm_handler      (OSAlarm *alarm, OSContext *context);
197 static void         voice_alarm_handler     (OSAlarm *alarm, OSContext *context);
198 static void         do_test                 (u32 sfx);
199 
200 
201 /*---------------------------------------------------------------------------*
202  * UI Stuff
203  *---------------------------------------------------------------------------*/
204 
205 DEMOWinInfo *DebugWin;      // debug messages
206 DEMOWinInfo *ProfileWin;    // AX state information
207 
208 DEMOWinMenuItem MenuItem[] =
209 {
210     { "Tests",                  DEMOWIN_ITM_SEPARATOR,  NULL,                 NULL },
211     { "  Ping test",            DEMOWIN_ITM_NONE,       MNU_start_ping_test,  NULL },
212     { "  Voice test",           DEMOWIN_ITM_NONE,       MNU_start_voice_test, NULL },
213     { " ",                      DEMOWIN_ITM_SEPARATOR,  NULL,                 NULL },
214     { "Manual AX Controls",     DEMOWIN_ITM_SEPARATOR,  NULL,                 NULL },
215     { "  Toggle Compressor",    DEMOWIN_ITM_NONE,       MNU_toggle_comp,      NULL },
216     { "  Play Looping Hum",     DEMOWIN_ITM_NONE,       MNU_play_hum,         NULL },
217     { "  Play Ping",            DEMOWIN_ITM_NONE,       MNU_play_ping,        NULL },
218     { "  Play Voice",           DEMOWIN_ITM_NONE,       MNU_play_voice,       NULL },
219     { "  Stop All Voices",      DEMOWIN_ITM_NONE,       MNU_stop_sfx,         NULL },
220     { " ",                      DEMOWIN_ITM_SEPARATOR,  NULL,                 NULL },
221     { "",                       DEMOWIN_ITM_TERMINATOR, NULL,                 NULL }
222 };
223 
224 DEMOWinMenuInfo Menu =
225 {
226     "AX Compressor Demo",       // title
227     NULL,                       // window handle
228     MenuItem,                   // list of menu items
229     12,                         // max num of items to display at a time
230     DEMOWIN_MNU_NONE,           // attribute flags
231 
232     // user callbacks
233     NULL,                       // callback for menu open event
234     MNU_play_click,             // callback for cursor move event
235     NULL,                       // callback for item select event
236     NULL,                       // callback for cancel event
237 
238     // private members
239     0, 0, 0, 0, 0
240 };
241 
242 DEMOWinMenuInfo *MenuPtr;
243 
244 /*===========================================================================*
245  *                   F U N C T I O N    D E F I N I T I O N S
246  *===========================================================================*/
247 
248 /*---------------------------------------------------------------------------*
249  * Name        : ax_profile_updatek()
250  * Description : refresh callback for AX profile window
251  * Arguments   :
252  * Returns     :
253  *---------------------------------------------------------------------------*/
254 
ax_profile_update(DEMOWinInfo * window)255 static void ax_profile_update(DEMOWinInfo *window)
256 {
257 
258     BOOL old;
259 
260     u32 i;
261 
262     u32 cpuCycles;
263     u32 userCycles;
264     u32 axCycles;
265     u32 voices;
266 
267     u32 maxCpuCycles =0;
268     u32 maxUserCycles=0;
269     u32 maxAxCycles  =0;
270     u32 maxVoices    =0;
271 
272         old = OSDisableInterrupts();
273 
274         i = AXGetProfile();
275 
276         if (i)
277         {
278             // up to 4 audio frames can complete within a 60Hz video frame
279             // so spin thru the accumulated audio frame profiles and find the peak values
280             while (i)
281             {
282                 i--;
283 
284                 cpuCycles   = (u32)(ax_profile[i].axFrameEnd      - ax_profile[i].axFrameStart);
285                 userCycles  = (u32)(ax_profile[i].userCallbackEnd - ax_profile[i].userCallbackStart);
286                 axCycles    = cpuCycles - userCycles;
287                 voices      = ax_profile[i].axNumVoices;
288 
289                 // find peak values over the last i audio frames
290                 if (cpuCycles > maxCpuCycles)     maxCpuCycles    = cpuCycles;
291                 if (userCycles > maxUserCycles)   maxUserCycles   = userCycles;
292                 if (axCycles > maxAxCycles)       maxAxCycles     = axCycles;
293                 if (voices > maxVoices)           maxVoices       = voices;
294 
295             }
296             OSRestoreInterrupts(old);
297 
298             DEMOWinPrintfXY(window, 0, 2, "Total CPU : %5.2f%%", (f32)OSTicksToNanoseconds(maxCpuCycles) / 50000);
299             DEMOWinPrintfXY(window, 0, 4, "User      : %5.2f%%", (f32)OSTicksToNanoseconds(maxUserCycles) / 50000);
300             DEMOWinPrintfXY(window, 0, 5, "AX        : %5.2f%%", (f32)OSTicksToNanoseconds(maxAxCycles) / 50000);
301             DEMOWinPrintfXY(window, 0, 7, "Voices    : %5d",    maxVoices);
302             DEMOWinPrintfXY(window, 0, 9, "Compressor: %s", (compressor_mode ? "ON " : "OFF"));
303 
304         }
305 
306         OSRestoreInterrupts(old);
307 
308 } // end profile_update()
309 
310 /*---------------------------------------------------------------------------*
311  * Name        : MNU_play_click()
312  * Description : Callback for menu system, plays 'click' for cursor movement
313  * Arguments   :
314  * Returns     :
315  *---------------------------------------------------------------------------*/
316 
MNU_play_click(DEMOWinMenuInfo * menu,u32 item)317 static void MNU_play_click(DEMOWinMenuInfo *menu, u32 item)
318 {
319 
320 #pragma unused(menu)
321 #pragma unused(item)
322 
323     play_sfx(SFX_MENU);
324 
325 
326 } // end MNU_play_click()
327 
328 
329 /*---------------------------------------------------------------------------*
330  * Name        :
331  * Description :
332  * Arguments   :
333  * Returns     :
334  *---------------------------------------------------------------------------*/
335 
MNU_play_hum(DEMOWinMenuInfo * menu,u32 item,u32 * result)336 static void MNU_play_hum(DEMOWinMenuInfo *menu, u32 item, u32 *result)
337 {
338 
339 #pragma unused(menu, item, result)
340 
341     play_sfx(SFX_HUM_LOOPED);
342 
343 } // end MNU_play_sfx()
344 
345 
346 /*---------------------------------------------------------------------------*
347  * Name        :
348  * Description :
349  * Arguments   :
350  * Returns     :
351  *---------------------------------------------------------------------------*/
352 
MNU_play_ping(DEMOWinMenuInfo * menu,u32 item,u32 * result)353 static void MNU_play_ping(DEMOWinMenuInfo *menu, u32 item, u32 *result)
354 {
355 
356 #pragma unused(menu, item, result)
357 
358     play_sfx(SFX_PING);
359 
360 } // end MNU_play_sfx()
361 
362 /*---------------------------------------------------------------------------*
363  * Name        :
364  * Description :
365  * Arguments   :
366  * Returns     :
367  *---------------------------------------------------------------------------*/
368 
MNU_play_voice(DEMOWinMenuInfo * menu,u32 item,u32 * result)369 static void MNU_play_voice(DEMOWinMenuInfo *menu, u32 item, u32 *result)
370 {
371 
372 #pragma unused(menu, item, result)
373 
374     play_sfx(SFX_VOICE_NGC_MAN);
375 
376 } // end MNU_play_sfx()
377 
378 
379 
380 /*---------------------------------------------------------------------------*
381  * Name        : MNU_stop_sfx()
382  * Description : Stops all voices. Note that voices are freed by the AX user
383  *               callback on the next frame.
384  * Arguments   :
385  * Returns     :
386  *---------------------------------------------------------------------------*/
387 
MNU_stop_sfx(DEMOWinMenuInfo * menu,u32 item,u32 * result)388 static void MNU_stop_sfx(DEMOWinMenuInfo *menu, u32 item, u32 *result)
389 {
390 #pragma unused(menu)
391 #pragma unused(item)
392 #pragma unused(result)
393 
394 
395     stop_all_sfx();
396 
397 
398 } // end MNU_stop_sfx()
399 
400 
401 
402 /*---------------------------------------------------------------------------*
403  * Name        : MNU_toggle_comp()
404  * Description : Toggles the AX compressor.
405  * Arguments   :
406  * Returns     :
407  *---------------------------------------------------------------------------*/
408 
MNU_toggle_comp(DEMOWinMenuInfo * menu,u32 item,u32 * result)409 static void MNU_toggle_comp(DEMOWinMenuInfo *menu, u32 item, u32 *result)
410 {
411 #pragma unused(menu)
412 #pragma unused(item)
413 #pragma unused(result)
414 
415     BOOL old;
416 
417         old = OSDisableInterrupts();
418 
419         compressor_mode ^= 1;
420         AXSetCompressor(compressor_mode);
421 
422         OSRestoreInterrupts(old);
423 
424 } // end MNU_stop_sfx()
425 
426 /*---------------------------------------------------------------------------*
427  * Name        :
428  * Description :
429  * Arguments   : None.
430  * Returns     : None.
431  *---------------------------------------------------------------------------*/
init_demo_voices()432 static void init_demo_voices()
433 {
434 
435     u32 i;
436 
437         for (i=0; i<MAX_DEMO_VOICES; i++)
438         {
439             demo_voice[i].ax_voice = NULL;
440             demo_voice[i].sp_entry = NULL;
441         }
442 
443 } // end init_demo_voices()
444 
445 
446 /*---------------------------------------------------------------------------*
447  * Name        :
448  * Description :
449  * Arguments   : None.
450  * Returns     : None.
451  *---------------------------------------------------------------------------*/
get_demo_voice()452 static DEMO_VOICE *get_demo_voice()
453 {
454 
455     u32 i;
456 
457         i=0;
458         while (i < MAX_DEMO_VOICES)
459         {
460 
461             if (NULL == demo_voice[i].ax_voice)
462             {
463                 return(&demo_voice[i]);
464             }
465             i++;
466         }
467 
468         return(NULL);
469 
470 }  // end get_demo_voice()
471 
472 /*---------------------------------------------------------------------------*
473  * Name        :
474  * Description :
475  * Arguments   : None.
476  * Returns     : None.
477  *---------------------------------------------------------------------------*/
478 
ax_demo_callback(void)479 static void ax_demo_callback(void)
480 {
481 
482     u32 i;
483 
484         for (i=0; i<MAX_DEMO_VOICES; i++)
485         {
486             if (demo_voice[i].ax_voice)
487             {
488                 if ( AX_PB_STATE_STOP == ((demo_voice[i].ax_voice)->pb.state))
489                 {
490                     MIXReleaseChannel(demo_voice[i].ax_voice);
491                     AXFreeVoice(demo_voice[i].ax_voice);
492                     demo_voice[i].ax_voice = NULL;
493                 }
494             }
495         }
496 
497 } // end ax_demo_callback()
498 
499 /*---------------------------------------------------------------------------*
500  * Name        : ax_drop_voice_callback()
501  * Description : Invoked by AX when a voice has been forciby dropped.
502  *               Must delete references to the voice from our abstraction layer
503  *               and release the associated MIXer channel.
504  * Arguments   : None.
505  * Returns     : None.
506  *---------------------------------------------------------------------------*/
507 
ax_drop_voice_callback(void * p)508 static void ax_drop_voice_callback(void *p)
509 {
510 
511     u32 i;
512 
513         OSReport("Voice dropped!\n");
514 
515 
516         // search for abstracted voice associated with low-level AX voice.
517         for (i=0; i<MAX_DEMO_VOICES; i++)
518         {
519             // found it!
520             if  ( (AXVPB *)(p) == demo_voice[i].ax_voice)
521             {
522                 // release mixer channel, delete reference to AX voice (and SP entry, just for neatness)
523                 MIXReleaseChannel(demo_voice[i].ax_voice);
524                 demo_voice[i].ax_voice = NULL;
525                 demo_voice[i].sp_entry = NULL;
526 
527 
528                 break;
529             }
530         }
531 
532         // freak out if the voice doesn't exist in our voice abstraction list
533         ASSERTMSG(i != MAX_DEMO_VOICES, "AXVoiceCallback: unknown voice reference!\n");
534 
535 } // end ax_demo_callback()
536 
537 /*---------------------------------------------------------------------------*
538  * Name        : stop_all_sfx()
539  * Description :
540  * Arguments   : None.
541  * Returns     : None.
542  *---------------------------------------------------------------------------*/
stop_all_sfx(void)543 static void stop_all_sfx(void)
544 {
545 
546     u32    i;
547     BOOL old;
548 
549         old = OSDisableInterrupts();
550 
551         for (i=0; i<MAX_DEMO_VOICES; i++)
552         {
553             if (demo_voice[i].ax_voice)
554             {
555                 AXSetVoiceState(demo_voice[i].ax_voice, AX_PB_STATE_STOP);
556             }
557         }
558 
559         OSRestoreInterrupts(old);
560 
561 
562 } // end stop_all_sfx()
563 
564 
565 
566 /*---------------------------------------------------------------------------*
567  * Name        : play_sfx()
568  * Description :
569  * Arguments   : None.
570  * Returns     : None.
571  *---------------------------------------------------------------------------*/
572 
play_sfx(u32 sfx)573 static void play_sfx(u32 sfx)
574 {
575 
576     DEMO_VOICE *v;
577     BOOL old;
578 
579 
580         old = OSDisableInterrupts();
581 
582         v = get_demo_voice();
583         if (v)
584         {
585 
586             v->ax_voice = AXAcquireVoice(15, ax_drop_voice_callback, 0);
587             if (v->ax_voice)
588             {
589 
590                 v->sp_entry = SPGetSoundEntry(sp_table, sfx);
591 
592                 SPPrepareSound(v->sp_entry, v->ax_voice, (v->sp_entry)->sampleRate);
593 
594                 MIXInitChannel(v->ax_voice, 0, 0, -960, -960, -960, 64, 127, 0);
595                 AXSetVoiceState(v->ax_voice, AX_PB_STATE_RUN);
596 
597                 OSRestoreInterrupts(old);
598 
599             }
600             else
601             {
602                 OSRestoreInterrupts(old);
603                 DEMOWinLogPrintf(DebugWin, "SFX: AX Voice allocation failed.\n");
604             }
605 
606         }
607         else
608         {
609             OSRestoreInterrupts(old);
610             DEMOWinLogPrintf(DebugWin, "(No free voices in abstraction layer)\n");
611         }
612 
613 } // end play_sfx()
614 
615 /*---------------------------------------------------------------------------*
616  * Name        : ping_alarm_handler()
617  * Description :
618  * Arguments   : None.
619  * Returns     : None.
620  *---------------------------------------------------------------------------*/
621 
ping_alarm_handler(OSAlarm * alarm,OSContext * context)622 static void ping_alarm_handler(OSAlarm *alarm, OSContext *context)
623 {
624 #pragma unused(alarm, context)
625 
626 
627     // last four counts, play a ping
628     if (ping_counter > 7 )
629     {
630         play_sfx(SFX_PING);
631     }
632 
633     // for the first eight counts, stay silent
634     ping_counter = (ping_counter + 1) % 12;
635 
636 
637 }
638 
639 /*---------------------------------------------------------------------------*
640  * Name        : voice_alarm_handler()
641  * Description :
642  * Arguments   : None.
643  * Returns     : None.
644  *---------------------------------------------------------------------------*/
645 
voice_alarm_handler(OSAlarm * alarm,OSContext * context)646 static void voice_alarm_handler(OSAlarm *alarm, OSContext *context)
647 {
648 #pragma unused(alarm, context)
649 
650 
651     // play the voice for just one count
652     if (ping_counter == 19 )
653     {
654         play_sfx(SFX_VOICE_NGC_MAN);
655     }
656 
657     // for the remaining counts, stay silent
658     ping_counter = (ping_counter + 1) % 25;
659 
660 }
661 
662 /*---------------------------------------------------------------------------*
663  * Name        : ping_test_refresh()
664  * Description :
665  * Arguments   : None.
666  * Returns     : None.
667  *---------------------------------------------------------------------------*/
668 
669 
ping_test_refresh(DEMOWinInfo * handle)670 static void ping_test_refresh(DEMOWinInfo *handle)
671 {
672 
673     DEMOWinPrintfXY(handle, 0, 3, "Compressor: %s", (compressor_mode ? "ON " : "OFF"));
674     DEMOWinPrintfXY(handle, 0, 5, "Clip Left : %s", ((clip_tick_left > 0) && (clip_tick_left < 19))   ? "CLIP" : "    ");
675     DEMOWinPrintfXY(handle, 0, 6, "Clip Right: %s", ((clip_tick_right > 0) && (clip_tick_right < 19)) ? "CLIP" : "    ");
676 
677 
678 } // end of ping_test_refresh()
679 
680 
681 
682 /*---------------------------------------------------------------------------*
683  * Name        : MNU_start_ping_test()
684  * Description :
685  * Arguments   : None.
686  * Returns     : None.
687  *---------------------------------------------------------------------------*/
688 
MNU_start_ping_test(DEMOWinMenuInfo * menu,u32 item,u32 * result)689 static void MNU_start_ping_test(DEMOWinMenuInfo *menu, u32 item, u32 *result)
690 {
691 #pragma unused(menu, item, result)
692 
693     do_test(SFX_PING);
694 
695 }
696 
697 /*---------------------------------------------------------------------------*
698  * Name        : NNU_start_voice_test()
699  * Description :
700  * Arguments   : None.
701  * Returns     : None.
702  *---------------------------------------------------------------------------*/
703 
MNU_start_voice_test(DEMOWinMenuInfo * menu,u32 item,u32 * result)704 static void MNU_start_voice_test(DEMOWinMenuInfo *menu, u32 item, u32 *result)
705 {
706 #pragma unused(menu, item, result)
707 
708     do_test(SFX_VOICE_NGC_MAN);
709 }
710 
711 
712 
713 /*---------------------------------------------------------------------------*
714  * Name        : do_test()
715  * Description :
716  * Arguments   : sound effect with which to induce clipping.
717  * Returns     : None.
718  *---------------------------------------------------------------------------*/
719 
do_test(u32 sfx)720 static void do_test(u32 sfx)
721 {
722 
723     DEMOWinInfo   *handle;
724     DEMOWinPadInfo pad;
725 
726     BOOL old;
727 
728     OSTime now;
729 
730     u32 num_samples = 0;
731     u32 start_index = 0;
732     u32 end_index   = 0;
733 
734     u32 index       = 0;
735 
736     u32 i;
737 
738 
739         // stop all voices, just in case
740         stop_all_sfx();
741 
742         handle = DEMOWinCreateWindow(150, 90, 540, 180, "Compressor Test", 0, ping_test_refresh);
743 
744         DEMOWinOpenWindow(handle);
745 
746         DEMOWinPrintfXY(handle, 0, 0, "A: Toggle Compressor");
747         DEMOWinPrintfXY(handle, 0, 1, "B: Exit");
748 
749         // debounce
750         DEMOWinPadInit(&pad);
751 
752         DEMOBeforeRender();
753         DEMOWinRefresh();
754         DEMODoneRender();
755 
756         DEMOWinPadRead(&pad);
757 
758         DEMOBeforeRender();
759         DEMOWinRefresh();
760         DEMODoneRender();
761 
762         DEMOWinPadRead(&pad);
763 
764         // start low-freq hum
765         play_sfx(SFX_HUM_LOOPED);
766 
767 
768         // start periodic ping
769         ping_counter = 0;
770         OSCreateAlarm(&PingAlarm);
771         now = OSGetTime();
772 
773         if (SFX_PING == sfx)
774         {
775             // set alarm using "ping" handler
776             OSSetPeriodicAlarm(&PingAlarm, now, OSMillisecondsToTicks(PING_PERIOD), ping_alarm_handler);
777         }
778         else if (SFX_VOICE_NGC_MAN)
779         {
780             // set alarm using "voice" handler
781             OSSetPeriodicAlarm(&PingAlarm, now, OSMillisecondsToTicks(PING_PERIOD), voice_alarm_handler);
782         }
783         else
784         {
785 
786             OSHalt("Unknown sound effect reference for test!\n");
787         }
788 
789 
790         // reset clip-o-meter
791         clip_left       = 0;
792         clip_right      = 0;
793         clip_tick_left  = 0;
794         clip_tick_right = 0;
795 
796 
797         while (1)
798         {
799 
800             if (pad.changed_button[0] & PAD_BUTTON_B)
801             {
802                 break;
803             }
804 
805             if (pad.changed_button[0] & PAD_BUTTON_A)
806             {
807 
808                 old = OSDisableInterrupts();
809 
810                 compressor_mode ^= 1;
811                 AXSetCompressor(compressor_mode);
812 
813                 OSRestoreInterrupts(old);
814             }
815 
816 
817 
818             // Clip detection
819             num_samples = DEMOAVXRefreshBuffer(&start_index, &end_index);
820 
821             index = start_index;
822             for (i=0; i<num_samples; i++)
823             {
824 
825                 if ((__left_channel[index] > 32766) || (__right_channel[index] < -32766))
826                 {
827                     clip_left++;            // count number of clips, just for fun
828                     clip_tick_left = 20;
829                 }
830 
831                 if ((__right_channel[index] > 32766) || (__right_channel[index] < -32766))
832                 {
833                     clip_right++;           // count number of clips, just for fun
834                     clip_tick_right = 20;
835                 }
836 
837                 index = (index + 1) % AVX_BUFFER_SIZE_WORDS;
838             }
839 
840             DEMOBeforeRender();
841             DEMOWinRefresh();
842             DEMODoneRender();
843 
844             DEMOWinPadRead(&pad);
845 
846             // decrement clip-o-meter animation ticks
847             clip_tick_right = (clip_tick_right ? (clip_tick_right - 1) : 0);
848             clip_tick_left  = (clip_tick_left  ? (clip_tick_left  - 1) : 0);
849 
850         }
851 
852         stop_all_sfx();
853 
854         OSRestoreInterrupts(old);
855         OSCancelAlarm(&PingAlarm);
856 
857         DEMOWinCloseWindow(handle);
858         DEMOWinDestroyWindow(handle);
859 
860         DEMOWinLogPrintf(DebugWin, "Left : clipped %d times.\n", clip_left);
861         DEMOWinLogPrintf(DebugWin, "Right: clipped %d times.\n", clip_right);
862         DEMOWinLogPrintf(DebugWin, "\n");
863 
864 
865 } // end do_test()
866 
867 #ifdef HOLLYWOOD_REV
868 /*---------------------------------------------------------------------------*
869  *---------------------------------------------------------------------------*/
LoadFileIntoRam(char * path)870 static void* LoadFileIntoRam(char *path)
871 {
872     DVDFileInfo handle;
873     u32         round_length;
874     s32         read_length;
875     void        *buffer;
876 
877     // Open File
878     if (!DVDOpen(path, &handle))
879     {
880         OSReport("WARNING! Failed to open %s\n", path);
881         return NULL;
882     }
883 
884     // Make sure file length is not 0
885     if (DVDGetLength(&handle) == 0)
886     {
887         OSReport("WARNING! File length is 0\n");
888         return NULL;
889     }
890 
891     round_length = OSRoundUp32B(DVDGetLength(&handle));
892     buffer       = MEMAllocFromExpHeapEx(hExpHeap, round_length,  32);
893 
894     // Make sure we got a buffer
895     if (buffer == NULL)
896     {
897         OSReport("WARNING! Unable to allocate buffer\n");
898         return NULL;
899     }
900 
901     // Read Files
902     read_length = DVDRead(&handle, buffer, (s32)(round_length), 0);
903 
904     // Make sure we read the file correctly
905     if (read_length <= 0)
906     {
907         OSReport("WARNING! File lenght is wrong\n");
908         return NULL;
909     }
910 
911     return buffer;
912 }
913 #endif
914 
915 /*---------------------------------------------------------------------------*
916  * Name        : main()
917  * Description : Hold on to your seatbelts!
918  * Arguments   : None.
919  * Returns     : None.
920  *---------------------------------------------------------------------------*/
921 
main(void)922 void main(void)
923 {
924 #ifdef HOLLYWOOD_REV
925     void       *arenaMem2Lo;
926     void       *arenaMem2Hi;
927     u8         *zeroBuffer;
928 #endif
929 
930     // initialize system
931     DEMOInit(NULL);
932     DEMOWinInit();
933 
934 #ifndef HOLLYWOOD_REV
935     // initialize ARAM w/ stack allocator
936     ARInit(aramMemArray, MAX_ARAM_BLOCKS);
937     ARQInit();
938 #else
939     arenaMem2Lo = OSGetMEM2ArenaLo();
940     arenaMem2Hi = OSGetMEM2ArenaHi();
941     hExpHeap    = MEMCreateExpHeap(arenaMem2Lo, (u32)arenaMem2Hi - (u32) arenaMem2Lo);
942 #endif
943 
944     // initialize AI subsystem
945     AIInit(NULL);
946 
947     // initialize AX audio system and MIXer application
948     AXInit();
949     MIXInit();
950 
951     // turn on compressor!
952     AXSetCompressor(compressor_mode);
953 
954 #ifndef HOLLYWOOD_REV
955     // -----------------------------------------------------------
956     // Initialize ARAM audio manager (AM)
957     // -----------------------------------------------------------
958 
959     // get a block from the AR ARAM allocator
960     aramUserBase = ARAlloc(AUDIO_BLOCK_SIZE_BYTES);
961 
962     // initialize AM with the block
963     AMInit(aramUserBase, AUDIO_BLOCK_SIZE_BYTES);
964 
965     // retrieve start of zero buffer, as created by AM
966     aramZeroBase = AMGetZeroBuffer();
967 #endif
968 
969     // -----------------------------------------------------------
970     // Load SP data!
971     // -----------------------------------------------------------
972 #ifndef HOLLYWOOD_REV
973     // Retrieve sound table
974     sp_table = (SPSoundTable *)AMLoadFile(SPT_FILE, NULL);
975 
976     // Load sound effects into ARAM
977     aramUserBase = AMPushBuffered(SPD_FILE, (void *)xfer_buffer, XFER_BUFFER_SIZE_BYTES);
978 #else
979     // Load sound table
980     sp_table = LoadFileIntoRam(SPT_FILE);
981 
982     // Load sound effects
983     sp_data  = LoadFileIntoRam(SPD_FILE);
984 #endif
985 
986 #ifdef HOLLYWOOD_REV
987     // -----------------------------------------------------------
988     // Prepare Zero Buffer
989     // -----------------------------------------------------------
990     zeroBuffer = MEMAllocFromExpHeapEx(hExpHeap, ZEROBUFFER_BYTES, 8);
991     memset(zeroBuffer, 0, ZEROBUFFER_BYTES);
992     DCFlushRange(zeroBuffer, ZEROBUFFER_BYTES);
993 #endif
994 
995     // -----------------------------------------------------------
996     // initialize sound table!
997     // -----------------------------------------------------------
998 #ifndef HOLLYWOOD_REV
999     SPInitSoundTable(sp_table, (u8*)aramUserBase, (u8*)aramZeroBase);
1000 #else
1001     SPInitSoundTable(sp_table, sp_data, zeroBuffer);
1002 #endif
1003 
1004     // -----------------------------------------------------------
1005     // Initialize demo voice abstraction layer
1006     // -----------------------------------------------------------
1007     init_demo_voices();
1008     AXRegisterCallback(ax_demo_callback);
1009 
1010     // initialize profiling for AX
1011     AXInitProfile(ax_profile, NUM_AX_PROFILE_FRAMES);
1012 
1013     // -----------------------------------------------------------
1014     // Initialize DEMO-AVX functions.
1015     // This allows us to snoop a copy of the contents of the DSP
1016     // DSP output before it is consumed by the DAC. We want this
1017     // data so we can search for clipping.
1018     // -----------------------------------------------------------
1019     DEMOAVXInit(__left_channel, __right_channel, AVX_BUFFER_SIZE_WORDS);
1020 
1021     // -----------------------------------------------------------
1022     // Invoke menu system!
1023     // -----------------------------------------------------------
1024 
1025     MenuPtr    = DEMOWinCreateMenuWindow(&Menu, 20, 100);
1026     DebugWin   = DEMOWinCreateWindow((u16)(MenuPtr->handle->x2+10), 20, 620, 440, "Debug", 1024, NULL);
1027     ProfileWin = DEMOWinCreateWindow((u16)(MenuPtr->handle->x1), (u16)(MenuPtr->handle->y2+10), (u16)(MenuPtr->handle->x2), (u16)(MenuPtr->handle->y2+160), "AX Status", 0, ax_profile_update);
1028 
1029     DEMOWinOpenWindow(DebugWin);
1030     DEMOWinOpenWindow(ProfileWin);
1031 
1032     DEMOWinLogPrintf(DebugWin, "-------------------------------\n");
1033     DEMOWinLogPrintf(DebugWin, "AX Compressor Demo\n");
1034     DEMOWinLogPrintf(DebugWin, "-------------------------------\n");
1035 
1036     while (1)
1037     {
1038 
1039         DEMOWinMenu(MenuPtr);
1040 
1041     }
1042 
1043 } // end main()
1044