1 /*---------------------------------------------------------------------------*
2 Project: Revolution AX + sequencer Demo
3 File: seqdemo.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: seqdemo.c,v $
14 Revision 1.13 2006/11/21 08:04:25 aka
15 Removed the zero buffer.
16
17 Revision 1.12 2006/10/24 06:39:45 aka
18 Added SPECIFY_MEM.
19
20 Revision 1.11 2006/10/23 02:05:52 aka
21 Changed from AXInit() to AXInitSpecifyMem().
22 Changed from MIXInit() to MIXInitSpecifyMem().
23 Changed from SYNInit() to SYNInitSpecifyMem().
24
25 Revision 1.10 2006/10/10 08:30:06 aka
26 Revised AXInit(), MIXInit() and SYNInit().
27
28 Revision 1.9 2006/06/08 06:06:07 aka
29 Removed setting of tempDisableFX for new AXFX.
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 08:31:17 aka
38 Added AXFXSetHooks() to alloc from MEM2 in AXFX.
39
40 Revision 1.5 2006/02/02 07:03:05 aka
41 Modified using MEM functions instead of OSAlloc()/OSFree().
42
43 Revision 1.4 2006/02/01 07:30:40 aka
44 Added #ifndef(#ifdef) HOLLYWOOD_REV - #else - #endif.
45
46 Revision 1.3 2006/01/31 08:07:20 aka
47 Added cast from u32 to u8* in relation to changing API around ARAM.
48
49 Revision 1.2 2006/01/27 04:54:59 ekwon
50 Corrected "\%" escape sequence warning (replaced with "%%").
51
52 Revision 1.1 2005/11/04 05:01:39 aka
53 Imported from dolphin tree.
54
55 14 03/04/01 16:20 Sak
56 murakami: Remove unused variables
57
58 13 4/11/02 1:59p Billyjack
59
60 12 12/11/01 7:02p Billyjack
61 - keep interrupts disabled during audio frame callback
62
63 11 9/06/01 3:17p Billyjack
64 fixed profile bug
65
66 10 9/05/01 4:33p Eugene
67 Updated AM API.
68
69 9 8/29/01 1:52p Billyjack
70
71 8 8/17/01 10:59a Billyjack
72 changed AMLoadFile() API
73
74 7 8/16/01 12:25p Billyjack
75 - now uses AM
76 - changed code for SYN and SEQ init API change
77
78 6 8/03/01 4:32p Billyjack
79 added OSEnableInterrupts() and OSRestoreInterrupts() to AX aufdio frame
80 callback per change in AX lib.
81
82 5 7/06/01 11:50a Billyjack
83 commented DCInvalidateRange for DVD to RAM transfers
84
85 4 5/21/01 12:01p Billyjack
86 changed demowin.h location
87
88 3 5/14/01 1:39p Billyjack
89 - reworked for DVDDATA file location and names
90 - uses ARGetBaseAddress where applicable
91
92 2 5/10/01 7:03p Billyjack
93 now uses DEMOWin
94
95 1 5/09/01 6:09p Billyjack
96 created
97
98 $NoKeywords: $
99 *---------------------------------------------------------------------------*/
100
101 /*---------------------------------------------------------------------------*
102 This program shows how to set up and use the AX
103 *---------------------------------------------------------------------------*/
104
105 #include <string.h>
106 #include <demo.h>
107 #include <revolution.h>
108 #include <revolution/mix.h>
109 #include <revolution/seq.h>
110 #include <revolution/syn.h>
111 #include <revolution/axfx.h>
112 #include <revolution/mem.h>
113 #include <demo/demowin.h>
114
115 #define SPECIFY_MEM
116 //#undef SPECIFY_MEM
117
118 #define AXBUFFER_ON_MEM2
119 #undef AXBUFFER_ON_MEM2
120
121 static u32 maxCpuCycles, maxAuxCycles, maxUserCycles, maxAxCycles, maxVoices;
122
123 static AXFX_REVERBSTD reverbStd;
124 static AXFX_REVERBHI reverbHi;
125 static AXFX_CHORUS chorus;
126 static AXFX_DELAY delay;
127 static AXPROFILE profile[256];
128 static u32 auxa;
129 static u32 auxb;
130 static u32 sampleset;
131
132 static MEMHeapHandle hExpHeap;
133
134 static SEQSEQUENCE sequence;
135 static u32 sequenceInitialized;
136
137 static u8 *wavetable;
138 static u8 *wavetablePcm;
139 static u8 *wavetableAdpcm;
140 static u8 *midiFile;
141 static char filename[1024];
142
143 static u8 *samples;
144 static u8 *samplesPcm;
145 static u8 *samplesAdpcm;
146 static void *axBuffer;
147 static void *mixBuffer;
148 static void *synBuffer;
149
150 DEMOWinInfo *log_win;
151
152 static u32 exitProgram;
153
154 static void* LoadFileIntoRam(char *path);
155
156 /*---------------------------------------------------------------------------*
157 *---------------------------------------------------------------------------*/
callbackAudioFrame(void)158 static void callbackAudioFrame(void)
159 {
160 // run the sequencer
161 SEQRunAudioFrame();
162
163 // run the synth
164 SYNRunAudioFrame();
165
166 // tell the mixer to update settings
167 MIXUpdateSettings();
168 }
169
170 /*---------------------------------------------------------------------------*
171 *---------------------------------------------------------------------------*/
exceedCallback(u32 cycles)172 static void exceedCallback(u32 cycles)
173 {
174 DEMOWinLogPrintf(log_win, "Exceed DSP capacity (over %ld DSP cycles).\n", cycles);
175 }
176
177 /*---------------------------------------------------------------------------*
178 setup the audio system for MIDI sequencer playback and profiling
179 *---------------------------------------------------------------------------*/
setupAudioSystem(void)180 static void setupAudioSystem(void)
181 {
182 #ifdef SPECIFY_MEM
183 AXInitSpecifyMem(AX_MAX_VOICES, axBuffer); // initialize AX
184 MIXInitSpecifyMem(mixBuffer); // initialize mixer
185 SYNInitSpecifyMem(synBuffer); // initialize synthesizer
186 #else
187 AXInit(); // initialize AX
188 MIXInit(); // initialize mixer
189 SYNInit(); // initialize synthesizer
190 #endif
191 SEQInit(); // initialize sequencer
192
193 AXRegisterExceedCallback(&exceedCallback);
194
195 AXRegisterCallback(&callbackAudioFrame);
196 AXInitProfile(profile, 256); // initialize profiling for AX
197
198 reverbStd.time = 3.0f;
199 reverbStd.preDelay = 0.1f;
200 reverbStd.damping = 0.5f;
201 reverbStd.coloration = 0.5f;
202 reverbStd.mix = 1.0f;
203
204 reverbHi.time = 3.0f;
205 reverbHi.preDelay = 0.1f;
206 reverbHi.damping = 0.5f;
207 reverbHi.coloration = 0.5f;
208 reverbHi.crosstalk = 0.0f;
209 reverbHi.mix = 1.0f;
210
211 chorus.baseDelay = 15;
212 chorus.variation = 0;
213 chorus.period = 500;
214
215 delay.delay[0] = 500;
216 delay.delay[1] = 500;
217 delay.delay[2] = 500;
218 delay.feedback[0] = 50;
219 delay.feedback[1] = 50;
220 delay.feedback[2] = 50;
221 delay.output[0] = 100;
222 delay.output[1] = 100;
223 delay.output[2] = 100;
224
225 AXFXReverbStdInit(&reverbStd); // initialize reverb
226 AXFXReverbHiInit(&reverbHi); // initialize reverb
227 AXFXChorusInit(&chorus); // initialize chorus
228 AXFXDelayInit(&delay); // initialize delay
229 }
230
231
232 /*---------------------------------------------------------------------------*
233 shutdown the audio system
234 *---------------------------------------------------------------------------*/
shutdownAudioSystem(void)235 static void shutdownAudioSystem(void)
236 {
237 AXFXReverbStdShutdown(&reverbStd);
238 AXFXReverbHiShutdown(&reverbHi);
239 AXFXChorusShutdown(&chorus);
240 AXFXDelayShutdown(&delay);
241
242 SEQQuit();
243 SYNQuit();
244 MIXQuit();
245 AXQuit();
246 }
247
248
249 /*---------------------------------------------------------------------------*
250 * Directory listing stuff!
251 *---------------------------------------------------------------------------*/
252 #define MAX_DIR_ENTRIES 512
253 #define MAX_FILENAME_LENGTH 128
254
255 DEMOWinMenuItem dir_entry[MAX_DIR_ENTRIES+1];
256 DEMOWinMenuInfo dir_list;
257
258 char dir_entry_name[MAX_DIR_ENTRIES][MAX_FILENAME_LENGTH];
259
260
261 /*---------------------------------------------------------------------------*
262 * Name :
263 * Description :
264 * Arguments : None.
265 * Returns : None.
266 *---------------------------------------------------------------------------*/
267
MNU_change_dir_up(DEMOWinMenuInfo * menu,u32 item,u32 * result)268 static void MNU_change_dir_up(DEMOWinMenuInfo *menu, u32 item, u32 *result)
269 {
270 #pragma unused(menu)
271 #pragma unused(item)
272 #pragma unused(result)
273
274 menu->items[item].flags |= DEMOWIN_ITM_EOF;
275
276 DEMOWinLogPrintf(log_win, "Changing to parent directory.\n");
277
278 DVDChangeDir("..");
279
280 *result = 0xDEADBEEF;
281
282 } // MNU_change_dir_up
283
284
285 /*---------------------------------------------------------------------------*
286 * Name :
287 * Description :
288 * Arguments : None.
289 * Returns : None.
290 *---------------------------------------------------------------------------*/
MNU_change_dir(DEMOWinMenuInfo * menu,u32 item,u32 * result)291 static void MNU_change_dir(DEMOWinMenuInfo *menu, u32 item, u32 *result)
292 {
293 #pragma unused(menu)
294 #pragma unused(item)
295 #pragma unused(result)
296
297
298 DVDDir dir;
299 DVDDirEntry dirent;
300
301 u32 i;
302
303 DEMOWinLogPrintf(log_win, "Changing directory to: '%s'.\n", menu->items[item].name);
304
305 DVDOpenDir(".", &dir);
306 for (i=1; i<=item; i++)
307 {
308 DVDReadDir(&dir, &dirent);
309 }
310 if (dirent.isDir)
311 {
312 DVDChangeDir(dirent.name);
313 menu->items[item].flags |= DEMOWIN_ITM_EOF;
314
315 }
316 else
317 {
318 DEMOWinLogPrintf(log_win, "Unable to change directory...??\n");
319 menu->items[item].flags &= ~DEMOWIN_ITM_EOF;
320 }
321
322 DVDCloseDir(&dir);
323
324 *result = 0xDEADBEEF;
325
326 } // MNU_change_dir
327
toupper(char c)328 static char toupper(char c)
329 {
330
331 if ((c >= 'a') && (c <= 'z'))
332 return((char)(c-32));
333 else
334 return(c);
335 }
336
337
compare_strings(char * s1,char * s2)338 static BOOL compare_strings(char *s1, char *s2)
339 {
340 u32 i;
341
342 for (i=0; i<strlen(s1); i++)
343 {
344 if (toupper(s1[i]) != toupper(s2[i]))
345 return(FALSE);
346 }
347 return(TRUE);
348 }
349
350
MNU_select_file(DEMOWinMenuInfo * menu,u32 item,u32 * result)351 static void MNU_select_file(DEMOWinMenuInfo *menu, u32 item, u32 *result)
352 {
353 u32 i;
354
355 i = strlen(menu->items[item].name);
356
357 while ((i >=0) && (menu->items[item].name[i] != '.'))
358 i--;
359
360 if (compare_strings(&menu->items[item].name[i], ".mid"))
361 {
362 strcpy(filename, menu->items[item].name);
363
364 DEMOWinLogPrintf(log_win, "Selected %s.\n", menu->items[item].name);
365
366 midiFile = LoadFileIntoRam(menu->items[item].name);
367
368 if (midiFile)
369 {
370 DEMOWinLogPrintf(log_win, "%s loaded into memory.\n", menu->items[item].name);
371
372 SEQAddSequence(
373 &sequence,
374 midiFile,
375 wavetable,
376 samples,
377 NULL,
378 16,
379 15,
380 1
381 );
382
383 DEMOWinLogPrintf(log_win, "%s initialized\n", menu->items[item].name);
384 sequenceInitialized = 1;
385 }
386
387 *result = sequenceInitialized;
388 }
389 else
390 {
391 DEMOWinLogPrintf(log_win, "--> File '%s' is not an .mid file!\n", menu->items[item].name);
392 }
393
394 } // end __select_file
395
396 /*---------------------------------------------------------------------------*
397 * Name :
398 * Description :
399 * Arguments : None.
400 * Returns : None.
401 *---------------------------------------------------------------------------*/
__create_dir_menu(void)402 static DEMOWinMenuInfo *__create_dir_menu(void)
403 {
404
405 DVDDir dir;
406 DVDDirEntry dirent;
407
408 u32 index;
409 u32 len;
410
411 index = 0;
412
413
414 // first entry is always parent directory
415 strcpy(dir_entry_name[index], "../");
416
417 dir_entry[index].name = &dir_entry_name[index][0];
418 dir_entry[index].flags = DEMOWIN_ITM_EOF;
419 dir_entry[index].function = MNU_change_dir_up;
420 dir_entry[index].link = NULL;
421
422 index++;
423
424
425 DVDOpenDir(".", &dir);
426
427 while ( (DVDReadDir(&dir, &dirent)) && (index < MAX_DIR_ENTRIES))
428 {
429 // get name, append '/' if it's a directory
430 strcpy(dir_entry_name[index], dirent.name);
431 if (dirent.isDir)
432 {
433 len = strlen(dirent.name);
434 dir_entry_name[index][len] = '/';
435 dir_entry_name[index][len+1] = 0;
436
437 dir_entry[index].function = MNU_change_dir;
438 dir_entry[index].flags = DEMOWIN_ITM_EOF;
439 }
440 else
441 {
442 dir_entry[index].function = MNU_select_file;
443 dir_entry[index].flags = DEMOWIN_ITM_EOF;
444 }
445
446 dir_entry[index].name = &dir_entry_name[index][0];
447 dir_entry[index].link = NULL;
448 index++;
449 }
450
451 // terminate list
452 dir_entry[index].flags = DEMOWIN_ITM_TERMINATOR;
453 dir_entry[index].function = NULL;
454 dir_entry[index].link = NULL;
455
456
457 // Initialize Menu info structure
458
459 dir_list.title = "Directory Listing"; // later, init with directory name
460 dir_list.handle = NULL; // placeholder for window handle
461 dir_list.items = &dir_entry[0]; // list of items
462
463 dir_list.max_display_items = 24; // display 22 files at a time
464 dir_list.flags = 0; // no flags
465
466 dir_list.cb_open = NULL; // no callbacks
467 dir_list.cb_move = NULL;
468 dir_list.cb_select = NULL;
469 dir_list.cb_cancel = NULL;
470
471 // private members; initialize to zero, they will be calculated at runtime
472 dir_list.num_display_items = 0;
473 dir_list.num_items = 0;
474 dir_list.max_str_len = 0;
475 dir_list.curr_pos = 0;
476 dir_list.display_pos = 0;
477
478 DVDCloseDir(&dir);
479
480 if (index)
481 {
482 return(&dir_list);
483 }
484 else
485 {
486 return(NULL);
487 }
488
489
490 } // end __create_dir_menu()
491
492 /*---------------------------------------------------------------------------*
493 *---------------------------------------------------------------------------*/
MNU_select(DEMOWinMenuInfo * menu,u32 item,u32 * result)494 static void MNU_select(DEMOWinMenuInfo *menu, u32 item, u32 *result)
495 {
496 #pragma unused(menu)
497 #pragma unused(item)
498 #pragma unused(result)
499
500 DEMOWinInfo *p; // parent window
501 DEMOWinMenuInfo *m; // directory menu
502
503 u32 val = 0;
504
505 DEMOWinLogPrintf(log_win, "Please select MIDI file to play.\n");
506
507 if (sequenceInitialized)
508 {
509 DEMOWinLogPrintf(log_win, "Removing sequence.\n");
510
511 SEQRemoveSequence(&sequence);
512 sequenceInitialized = 0;
513
514 if (midiFile)
515 {
516 DEMOWinLogPrintf(log_win, "Free MIDI file from memory.\n");
517 MEMFreeToExpHeap(hExpHeap, midiFile);
518 }
519 }
520
521 p = menu->handle;
522
523 do
524 {
525 m = __create_dir_menu();
526
527 if (m)
528 {
529 DEMOWinCreateMenuWindow(m, (u16)(p->x2-10), (u16)(p->y1+24));
530 val = DEMOWinMenu(m);
531 DEMOWinDestroyMenuWindow(m);
532 }
533 else
534 {
535 DEMOWinLogPrintf(log_win, "Failed to create directory list.\n");
536 }
537
538 } while (val == 0xDEADBEEF);
539 }
540
541
542 /*---------------------------------------------------------------------------*
543 *---------------------------------------------------------------------------*/
MNU_play(DEMOWinMenuInfo * menu,u32 item,u32 * result)544 static void MNU_play(DEMOWinMenuInfo *menu, u32 item, u32 *result)
545 {
546 #pragma unused(menu)
547 #pragma unused(item)
548 #pragma unused(result)
549
550 if (sequenceInitialized)
551 {
552 DEMOWinLogPrintf(log_win, "Setting sequence state to SEQ_STATE_RUN.\n");
553 SEQSetState(&sequence, SEQ_STATE_RUN);
554 }
555 else
556 {
557 DEMOWinLogPrintf(log_win, "Please select a MIDI file to play!!!\n");
558 }
559 }
560
561 /*---------------------------------------------------------------------------*
562 *---------------------------------------------------------------------------*/
MNU_playloop(DEMOWinMenuInfo * menu,u32 item,u32 * result)563 static void MNU_playloop(DEMOWinMenuInfo *menu, u32 item, u32 *result)
564 {
565 #pragma unused(menu)
566 #pragma unused(item)
567 #pragma unused(result)
568
569 if (sequenceInitialized)
570 {
571 DEMOWinLogPrintf(log_win, "Setting sequence state to SEQ_STATE_RUNLOOPED.\n");
572 SEQSetState(&sequence, SEQ_STATE_RUNLOOPED);
573 }
574 }
575
576
577 /*---------------------------------------------------------------------------*
578 *---------------------------------------------------------------------------*/
MNU_pause(DEMOWinMenuInfo * menu,u32 item,u32 * result)579 static void MNU_pause(DEMOWinMenuInfo *menu, u32 item, u32 *result)
580 {
581 #pragma unused(menu)
582 #pragma unused(item)
583 #pragma unused(result)
584
585 if (sequenceInitialized)
586 {
587 DEMOWinLogPrintf(log_win, "Setting sequence state to SEQ_STATE_PAUSE.\n");
588 SEQSetState(&sequence, SEQ_STATE_PAUSE);
589 }
590 }
591
592
593 /*---------------------------------------------------------------------------*
594 *---------------------------------------------------------------------------*/
MNU_stop(DEMOWinMenuInfo * menu,u32 item,u32 * result)595 static void MNU_stop(DEMOWinMenuInfo *menu, u32 item, u32 *result)
596 {
597 #pragma unused(menu)
598 #pragma unused(item)
599 #pragma unused(result)
600
601 if (sequenceInitialized)
602 {
603 DEMOWinLogPrintf(log_win, "Setting sequence state to SEQ_STATE_STOP.\n");
604 SEQSetState(&sequence, SEQ_STATE_STOP);
605 }
606 }
607
608
609 /*---------------------------------------------------------------------------*
610 *---------------------------------------------------------------------------*/
MNU_auxa(DEMOWinMenuInfo * menu,u32 item,u32 * result)611 static void MNU_auxa(DEMOWinMenuInfo *menu, u32 item, u32 *result)
612 {
613 #pragma unused(menu)
614 #pragma unused(item)
615 #pragma unused(result)
616
617 auxa ++;
618
619 switch(auxa % 3)
620 {
621 case 0:
622
623 AXRegisterAuxACallback(NULL, NULL);
624 menu->items[item].name = " AUX A None";
625
626 break;
627
628 case 1:
629
630 AXRegisterAuxACallback((void*)&AXFXReverbStdCallback, (void*)&reverbStd);
631 menu->items[item].name = " AUX A AXFXReverbStd";
632
633 break;
634
635 case 2:
636
637 AXRegisterAuxACallback((void*)&AXFXReverbHiCallback, (void*)&reverbHi);
638 menu->items[item].name = " AUX A AXFXReverbHi";
639
640 break;
641 }
642 }
643
644
645 /*---------------------------------------------------------------------------*
646 *---------------------------------------------------------------------------*/
MNU_auxb(DEMOWinMenuInfo * menu,u32 item,u32 * result)647 static void MNU_auxb(DEMOWinMenuInfo *menu, u32 item, u32 *result)
648 {
649 #pragma unused(menu)
650 #pragma unused(item)
651 #pragma unused(result)
652
653 auxb ++;
654
655 switch(auxb % 3)
656 {
657 case 0:
658
659 AXRegisterAuxBCallback(NULL, NULL);
660 menu->items[item].name = " AUX B None";
661
662 break;
663
664 case 1:
665
666 AXRegisterAuxBCallback((void*)&AXFXChorusCallback, (void*)&chorus);
667 menu->items[item].name = " AUX B AXFXChorus";
668
669 break;
670
671 case 2:
672
673 AXRegisterAuxBCallback((void*)&AXFXDelayCallback, (void*)&delay);
674 menu->items[item].name = " AUX B AXFXDelay";
675
676 break;
677 }
678 }
679
680
681 /*---------------------------------------------------------------------------*
682 *---------------------------------------------------------------------------*/
MNU_sample(DEMOWinMenuInfo * menu,u32 item,u32 * result)683 static void MNU_sample(DEMOWinMenuInfo *menu, u32 item, u32 *result)
684 {
685 #pragma unused(menu)
686 #pragma unused(item)
687 #pragma unused(result)
688
689 sampleset ++;
690
691 switch(sampleset % 2)
692 {
693 case 0:
694
695 wavetable = wavetablePcm;
696 samples = samplesPcm;
697
698 menu->items[item].name = " PCM Samples";
699
700 break;
701
702 case 1:
703
704 wavetable = wavetableAdpcm;
705 samples = samplesAdpcm;
706
707 menu->items[item].name = " ADPCM Samples";
708
709 break;
710 }
711
712 // if the sequence is running, initialize the synth with the new wavetable
713 if ((SEQGetState(&sequence) == SEQ_STATE_RUN) ||
714 (SEQGetState(&sequence) == SEQ_STATE_RUNLOOPED))
715 {
716 u32 state = SEQGetState(&sequence);
717
718 DEMOWinLogPrintf(log_win, "Stopping playback to change wavetable.\n");
719 SEQSetState(&sequence, SEQ_STATE_STOP);
720 }
721
722 if (sequenceInitialized)
723 {
724 SYNQuitSynth(&sequence.synth);
725
726 SYNInitSynth(
727 &sequence.synth,
728 wavetable,
729 samples,
730 NULL,
731 16,
732 15,
733 1
734 );
735 }
736
737 if (samples == samplesPcm)
738 DEMOWinLogPrintf(log_win, "Now using PCM samples.\n");
739 else
740 DEMOWinLogPrintf(log_win, "Now using ADPCM samples.\n");
741 }
742
743
744 /*---------------------------------------------------------------------------*
745 *---------------------------------------------------------------------------*/
MNU_clearmax(DEMOWinMenuInfo * menu,u32 item,u32 * result)746 static void MNU_clearmax(DEMOWinMenuInfo *menu, u32 item, u32 *result)
747 {
748 #pragma unused(menu)
749 #pragma unused(item)
750 #pragma unused(result)
751
752 maxCpuCycles = maxAuxCycles = maxUserCycles = maxAxCycles = maxVoices = 0;
753 }
754
755
756 /*---------------------------------------------------------------------------*
757 *---------------------------------------------------------------------------*/
MNU_exit(DEMOWinMenuInfo * menu,u32 item,u32 * result)758 static void MNU_exit(DEMOWinMenuInfo *menu, u32 item, u32 *result)
759 {
760 #pragma unused(menu)
761 #pragma unused(item)
762 #pragma unused(result)
763
764 exitProgram = 1;
765 }
766
767
768 /*---------------------------------------------------------------------------*
769 *---------------------------------------------------------------------------*/
updateProfile(DEMOWinInfo * window)770 static void updateProfile(DEMOWinInfo *window)
771 {
772 u32 cpuCycles, auxCycles, userCycles, axCycles, voices, i;
773
774 i = AXGetProfile();
775
776 if (i)
777 {
778 while (i)
779 {
780 // i--;
781
782 cpuCycles = (u32)(profile[i].axFrameEnd - profile[i].axFrameStart);
783 auxCycles = (u32)(profile[i].auxProcessingEnd - profile[i].auxProcessingStart);
784 userCycles = (u32)(profile[i].userCallbackEnd - profile[i].userCallbackStart);
785 axCycles = cpuCycles - auxCycles - userCycles;
786 voices = profile[i].axNumVoices;
787
788 if (cpuCycles > maxCpuCycles) maxCpuCycles = cpuCycles;
789 if (auxCycles > maxAuxCycles) maxAuxCycles = auxCycles;
790 if (userCycles > maxUserCycles) maxUserCycles = userCycles;
791 if (axCycles > maxAxCycles) maxAxCycles = axCycles;
792 if (voices > maxVoices) maxVoices = voices;
793
794 i--;
795 }
796
797 DEMOWinLogPrintf(window,"Current profile for 5ms frame\n\n");
798 DEMOWinLogPrintf(window,"Total: %f%%\n", (f32)OSTicksToNanoseconds(cpuCycles) / 50000);
799 DEMOWinLogPrintf(window,"AX: %f%%\n", (f32)OSTicksToNanoseconds(axCycles) / 50000);
800 DEMOWinLogPrintf(window,"AUX: %f%%\n", (f32)OSTicksToNanoseconds(auxCycles) / 50000);
801 DEMOWinLogPrintf(window,"MIX, SYN, SEQ: %f%%\n", (f32)OSTicksToNanoseconds(userCycles) / 50000);
802 DEMOWinLogPrintf(window,"Voices: %d\n", voices);
803
804 DEMOWinLogPrintf(window,"\nMax profile for 5ms frame\n\n");
805 DEMOWinLogPrintf(window,"Total: %f%%\n", (f32)OSTicksToNanoseconds(maxCpuCycles) / 50000);
806 DEMOWinLogPrintf(window,"AX: %f%%\n", (f32)OSTicksToNanoseconds(maxAxCycles) / 50000);
807 DEMOWinLogPrintf(window,"AUX: %f%%\n", (f32)OSTicksToNanoseconds(maxAuxCycles) / 50000);
808 DEMOWinLogPrintf(window,"MIX, SYN, SEQ: %f%%\n", (f32)OSTicksToNanoseconds(maxUserCycles) / 50000);
809 DEMOWinLogPrintf(window,"Voices: %d\n", maxVoices);
810 }
811 }
812
813
814 /*---------------------------------------------------------------------------*
815 *---------------------------------------------------------------------------*/
updateStatus(DEMOWinInfo * window)816 static void updateStatus(DEMOWinInfo *window)
817 {
818 if (sequenceInitialized)
819 {
820 DEMOWinLogPrintf(window, "MIDI File: %s\n", filename);
821 DEMOWinLogPrintf(window, "Tracks: %d\n", sequence.nTracks);
822 DEMOWinLogPrintf(window, "Remaining: %d\n", sequence.tracksRunning);
823 }
824 else
825 {
826 DEMOWinLogPrintf(window, "MIDI File: None\n");
827 DEMOWinLogPrintf(window, "Tracks: 0\n");
828 DEMOWinLogPrintf(window, "Running: 0\n");
829 }
830
831 switch (SEQGetState(&sequence))
832 {
833 case SEQ_STATE_STOP:
834
835 DEMOWinLogPrintf(window, "State: SEQ_STATE_STOP\n");
836
837 break;
838
839 case SEQ_STATE_RUN:
840
841 DEMOWinLogPrintf(window, "State: SEQ_STATE_RUN\n");
842
843 break;
844
845 case SEQ_STATE_RUNLOOPED:
846
847 DEMOWinLogPrintf(window, "State: SEQ_STATE_RUNLOOPED\n");
848
849 break;
850
851 case SEQ_STATE_PAUSE:
852
853 DEMOWinLogPrintf(window, "State: SEQ_STATE_PAUSE\n");
854
855 break;
856 }
857
858
859 DEMOWinLogPrintf(window, "Voices: %d\n", SYNGetActiveNotes(&sequence.synth));
860 }
861
862
863 /*---------------------------------------------------------------------------*
864 *---------------------------------------------------------------------------*/
865 DEMOWinMenuItem control_menu_items[] =
866 {
867 { "", DEMOWIN_ITM_SEPARATOR, NULL, NULL },
868 { " Select MIDI File", DEMOWIN_ITM_NONE, MNU_select, NULL },
869 { "", DEMOWIN_ITM_SEPARATOR, NULL, NULL },
870 { " Play", DEMOWIN_ITM_NONE, MNU_play, NULL },
871 { " Play Looped", DEMOWIN_ITM_NONE, MNU_playloop, NULL },
872 { " Pause", DEMOWIN_ITM_NONE, MNU_pause, NULL },
873 { " Stop", DEMOWIN_ITM_NONE, MNU_stop, NULL },
874 { "", DEMOWIN_ITM_SEPARATOR, NULL, NULL },
875 { " AUX A None", DEMOWIN_ITM_NONE, MNU_auxa, NULL },
876 { " AUX B None", DEMOWIN_ITM_NONE, MNU_auxb, NULL },
877 { "", DEMOWIN_ITM_SEPARATOR, NULL, NULL },
878 { " PCM Samples", DEMOWIN_ITM_NONE, MNU_sample, NULL },
879 { "", DEMOWIN_ITM_SEPARATOR, NULL, NULL },
880 { " Clear Max Profile", DEMOWIN_ITM_NONE, MNU_clearmax, NULL },
881 { "", DEMOWIN_ITM_SEPARATOR, NULL, NULL },
882 { " Exit Program", DEMOWIN_ITM_EOF, MNU_exit, NULL },
883 { "", DEMOWIN_ITM_TERMINATOR, NULL, NULL }
884 };
885
886 DEMOWinMenuInfo control_menu =
887 {
888 #ifdef NDEBUG
889 "Seqdemo - NDEBUG build", // title
890 #else
891 "Seqdemo - DEBUG build", // title
892 #endif
893 NULL, // window handle
894 control_menu_items, // list of menu items
895 18, // max num of items to display at a time
896 DEMOWIN_MNU_NONE, // attribute flags?
897
898 // user callbacks for misc menu operations
899 NULL, NULL, NULL, NULL,
900 // private menu info members; do not touch
901 0, 0, 0, 0, 0
902 };
903
904 /*---------------------------------------------------------------------------*
905 *---------------------------------------------------------------------------*/
LoadFileIntoRam(char * path)906 static void* LoadFileIntoRam(char *path)
907 {
908 DVDFileInfo handle;
909 u32 round_length;
910 s32 read_length;
911 void *buffer;
912
913 // Open File
914 if (!DVDOpen(path, &handle))
915 {
916 OSReport("WARNING! Failed to open %s\n", path);
917 return NULL;
918 }
919
920 // Make sure file length is not 0
921 if (DVDGetLength(&handle) == 0)
922 {
923 OSReport("WARNING! File length is 0\n");
924 return NULL;
925 }
926
927 round_length = OSRoundUp32B(DVDGetLength(&handle));
928 buffer = MEMAllocFromExpHeapEx(hExpHeap, round_length, 32);
929
930 // Make sure we got a buffer
931 if (buffer == NULL)
932 {
933 OSReport("WARNING! Unable to allocate buffer\n");
934 return NULL;
935 }
936
937 // Read Files
938 read_length = DVDRead(&handle, buffer, (s32)(round_length), 0);
939
940 // Make sure we read the file correctly
941 if (read_length <= 0)
942 {
943 OSReport("WARNING! File lenght is wrong\n");
944 return NULL;
945 }
946
947 return buffer;
948 }
949
950 /*---------------------------------------------------------------------------*
951 *---------------------------------------------------------------------------*/
PrivateAlloc(u32 size)952 static void* PrivateAlloc(u32 size)
953 {
954 return MEMAllocFromExpHeapEx(hExpHeap, size, 32);
955 }
956
957 /*---------------------------------------------------------------------------*
958 *---------------------------------------------------------------------------*/
PrivateFree(void * addr)959 static void PrivateFree(void* addr)
960 {
961 MEMFreeToExpHeap(hExpHeap, addr);
962 }
963
964 /*---------------------------------------------------------------------------*
965 *---------------------------------------------------------------------------*/
main(void)966 void main(void)
967 {
968 DEMOWinInfo *profile_win;
969 DEMOWinInfo *status_win;
970 DEMOWinMenuInfo *control_menu_ptr;
971
972 void *arenaMem2Lo;
973 void *arenaMem2Hi;
974
975 // set flags used for menu
976 auxa = auxb = sampleset = 0;
977 exitProgram = 0;
978 sequenceInitialized = 0;
979
980 // initialize bean counters for profiling
981 maxCpuCycles = maxAuxCycles = maxUserCycles = maxAxCycles = maxVoices = 0;
982
983 // initialize subsystems
984 DEMOInit(NULL);
985 DEMOWinInit();
986
987 arenaMem2Lo = OSGetMEM2ArenaLo();
988 arenaMem2Hi = OSGetMEM2ArenaHi();
989 hExpHeap = MEMCreateExpHeap(arenaMem2Lo, (u32)arenaMem2Hi - (u32) arenaMem2Lo);
990
991 AIInit(NULL);
992
993 // initialize windows on the TV
994 control_menu_ptr = DEMOWinCreateMenuWindow(&control_menu, 20, 20);
995
996 profile_win = DEMOWinCreateWindow(300, 20, 600, 170, "AX Profile", 1024, updateProfile);
997 status_win = DEMOWinCreateWindow(300, 175, 600, 245, "Sequence Status", 1024, updateStatus);
998 log_win = DEMOWinCreateWindow(20, 250, 600, 400, "Log", 1024, NULL);
999
1000 DEMOWinOpenWindow(control_menu_ptr->handle);
1001 DEMOWinOpenWindow(profile_win);
1002 DEMOWinOpenWindow(status_win);
1003 DEMOWinOpenWindow(log_win);
1004
1005 DEMOWinLogPrintf(log_win, "Setting up audio\n");
1006
1007 #ifdef AXBUFFER_ON_MEM2
1008 axBuffer = MEMAllocFromExpHeapEx(hExpHeap, AXGetMemorySize(AX_MAX_VOICES), 32);
1009 #else
1010 axBuffer = OSAlloc(AXGetMemorySize(AX_MAX_VOICES));
1011 #endif
1012 mixBuffer = MEMAllocFromExpHeap(hExpHeap, MIXGetMemorySize(AX_MAX_VOICES));
1013 synBuffer = MEMAllocFromExpHeap(hExpHeap, SYNGetMemorySize(AX_MAX_VOICES));
1014
1015 setupAudioSystem();
1016
1017 // load sample data into main memory
1018 samplesPcm = LoadFileIntoRam("/axdemo/synth/gm16pcm.pcm");
1019 samplesAdpcm = LoadFileIntoRam("/axdemo/synth/gm16adpcm.pcm");
1020
1021 // load table data into main memory
1022 wavetablePcm = LoadFileIntoRam("/axdemo/synth/gm16pcm.wt");
1023 wavetableAdpcm = LoadFileIntoRam("/axdemo/synth/gm16adpcm.wt");
1024
1025 // default to PCM samples
1026 wavetable = wavetablePcm;
1027 samples = samplesPcm;
1028
1029 AXFXSetHooks((AXFXAlloc)PrivateAlloc, (AXFXFree)PrivateFree);
1030
1031 while (1)
1032 {
1033 DEMOWinMenu(control_menu_ptr);
1034
1035 if (exitProgram == 1)
1036 break;
1037 }
1038
1039 DEMOWinLogPrintf(log_win, "Shutting down up audio\n");
1040 DEMOBeforeRender();
1041 DEMOWinRefresh();
1042 DEMODoneRender();
1043
1044 shutdownAudioSystem();
1045
1046 DEMOWinLogPrintf(log_win, "Free wavetable\n");
1047 DEMOBeforeRender();
1048 DEMOWinRefresh();
1049 DEMODoneRender();
1050
1051 if (wavetablePcm)
1052 {
1053 MEMFreeToExpHeap(hExpHeap, wavetablePcm);
1054 }
1055
1056 if (wavetableAdpcm)
1057 {
1058 MEMFreeToExpHeap(hExpHeap, wavetableAdpcm);
1059 }
1060
1061 if (midiFile)
1062 {
1063 MEMFreeToExpHeap(hExpHeap, midiFile);
1064 }
1065
1066 if (samplesPcm)
1067 {
1068 MEMFreeToExpHeap(hExpHeap, samplesPcm);
1069 }
1070
1071 if (samplesAdpcm)
1072 {
1073 MEMFreeToExpHeap(hExpHeap, samplesAdpcm);
1074 }
1075
1076 if (axBuffer)
1077 {
1078 #ifdef AXBUFFER_ON_MEM2
1079 MEMFreeToExpHeap(hExpHeap, axBuffer);
1080 #else
1081 OSFree(axBuffer);
1082 #endif
1083 }
1084
1085 if (mixBuffer)
1086 {
1087 MEMFreeToExpHeap(hExpHeap, mixBuffer);
1088 }
1089
1090 if (synBuffer)
1091 {
1092 MEMFreeToExpHeap(hExpHeap, synBuffer);
1093 }
1094
1095 OSHalt("End of program\n");
1096 }
1097