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