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