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