1 /*---------------------------------------------------------------------------*
2   Project:  Revolution AX + synth Demo
3   File:     syndemo.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: syndemo.c,v $
14   Revision 1.8  2006/03/06 09:59:03  kawaset
15   Eliminated warnings.
16 
17   Revision 1.7  02/21/2006 01:04:15  mitu
18   modified am.h path.
19 
20   Revision 1.6  02/20/2006 04:13:07  mitu
21   changed include path from dolphin/ to revolution/.
22 
23   Revision 1.5  02/02/2006 08:22:39  aka
24   Removed unused header files.
25 
26   Revision 1.4  02/02/2006 06:53:15  aka
27   Modified using MEM functions instead of OSAlloc()/OSFree().
28 
29   Revision 1.3  02/01/2006 06:36:47  aka
30   Added #ifndef(#ifdef) HOLLYWOOD_REV - #else - #endif.
31 
32   Revision 1.2  02/01/2006 04:25:24  aka
33   Added cast from u32 to u8* in relation to changing API around ARAM.
34 
35   Revision 1.1  11/04/2005 05:01:39  aka
36   Imported from dolphin tree.
37 
38     9     12/11/01 7:02p Billyjack
39     - keep interrupts disabled during audio frame callback
40 
41     8     9/05/01 4:33p Eugene
42     Updated AM API.
43 
44     7     8/29/01 1:52p Billyjack
45 
46     6     8/17/01 10:59a Billyjack
47     changed AMLoadFile() API
48 
49     5     8/16/01 12:25p Billyjack
50     - now uses AM
51     - changed code for SYN and SEQ init API change
52 
53     4     8/03/01 4:32p Billyjack
54     added OSEnableInterrupts() and OSRestoreInterrupts() to AX audio frame
55     callback per change in AX lib.
56 
57     3     7/06/01 11:50a Billyjack
58     commented DCInvalidateRange for DVD to RAM transfers
59 
60     2     5/14/01 1:39p Billyjack
61     - reworked for DVDDATA file location and names
62     - uses ARGetBaseAddress where applicable
63 
64     1     5/09/01 6:09p Billyjack
65     created
66 
67   $NoKeywords: $
68  *---------------------------------------------------------------------------*/
69 
70 /*---------------------------------------------------------------------------*
71   This program shows how to set up and use the AX
72  *---------------------------------------------------------------------------*/
73 #include <demo.h>
74 #include <revolution.h>
75 #include <revolution/mix.h>
76 #include <revolution/syn.h>
77 #ifndef HOLLYWOOD_REV
78 #include <dolphin/am.h>
79 #else
80 #include <revolution/mem.h>
81 #include <string.h>
82 #endif
83 
84 #ifndef HOLLYWOOD_REV
85 #define MAX_ARAM_BLOCKS     2
86 static  u32 aramMemArray[MAX_ARAM_BLOCKS];
87 #else
88 static MEMHeapHandle hExpHeap;
89 #endif
90 
91 static u8 noteA = 0;
92 static u8 noteNumber = 0;
93 static u8 program = 0;
94 static int programChangeButton;
95 
96 SYNSYNTH    synth;
97 
98 static u32 hold = 0;
99 
100 #ifdef HOLLYWOOD_REV
101 #define ZEROBUFFER_BYTES 256
102 #endif
103 
104 /*---------------------------------------------------------------------------*
105  *---------------------------------------------------------------------------*/
callbackDropVoice(void * p)106 static void callbackDropVoice(void *p)
107 {
108     AXVPB *pvpb = p;
109 
110     OSReport("PVPB %.8x is being dropped context %d\n", pvpb, pvpb->userContext);
111 }
112 
113 
114 /*---------------------------------------------------------------------------*
115  *---------------------------------------------------------------------------*/
callbackAudioFrame(void)116 static void callbackAudioFrame(void)
117 {
118     // run the synth
119     SYNRunAudioFrame();
120 
121     // tell the mixer to update settings
122     MIXUpdateSettings();
123 }
124 
125 
126 /*---------------------------------------------------------------------------*
127  *---------------------------------------------------------------------------*/
programChange(void)128 static void programChange(void)
129 {
130 	u8 ch[3];
131     int old;
132 
133     if (programChangeButton)
134         return;
135 
136     programChangeButton = 1;
137 
138 	program++;
139     program %= 128;
140 
141     ch[0] = 0xC0;
142     ch[1] = program;
143     OSReport("program: %d\n", program);
144 
145     old = OSDisableInterrupts();
146 
147     SYNMidiInput(&synth, ch);
148 
149     OSRestoreInterrupts(old);
150 }
151 
152 
153 /*---------------------------------------------------------------------------*
154  *---------------------------------------------------------------------------*/
programChange_(void)155 static void programChange_(void)
156 {
157     programChangeButton = 0;
158 }
159 
160 
161 /*---------------------------------------------------------------------------*
162  *---------------------------------------------------------------------------*/
startNote(void)163 static void startNote(void)
164 {
165     if (noteA == 0)
166     {
167         u8 ch[3];
168         int old;
169 
170         ch[0] = 0x90;
171         ch[1] = noteNumber;
172         ch[2] = 0x7F;
173 
174         old = OSDisableInterrupts();
175 
176         SYNMidiInput(&synth, ch);
177 
178         OSRestoreInterrupts(old);
179         OSReport("program: %d keyNum: %d\n", program, noteNumber);
180         noteA = 1;
181     }
182 }
183 
184 
185 /*---------------------------------------------------------------------------*
186  *---------------------------------------------------------------------------*/
stopNote(void)187 static void stopNote(void)
188 {
189     if (noteA)
190     {
191         u8 ch[3];
192         int old;
193 
194         ch[0] = 0x80;
195         ch[1] = noteNumber;
196         ch[2] = 0x00;
197 
198         old = OSDisableInterrupts();
199 
200         SYNMidiInput(&synth, ch);
201 
202         noteA = 0;
203 
204         noteNumber++;
205         noteNumber %= 128;
206 
207         if (noteNumber == 127)
208         {
209             program++;
210             program %= 128;
211 
212             ch[0] = 0xC0;
213             ch[1] = program;
214 
215             SYNMidiInput(&synth, ch);
216         }
217 
218         OSRestoreInterrupts(old);
219     }
220 }
221 
222 
223 /*---------------------------------------------------------------------------*
224  *---------------------------------------------------------------------------*/
holdPedalDown(void)225 static void holdPedalDown(void)
226 {
227     u8 ch[3];
228     int old;
229 
230     if (hold)
231         return;
232 
233     ch[0] = 0xB0;
234     ch[1] = 0x40;
235     ch[2] = 127;
236 
237     old = OSDisableInterrupts();
238 
239     SYNMidiInput(&synth, ch);
240 
241     OSRestoreInterrupts(old);
242 
243     hold = 1;
244 }
245 
246 
247 /*---------------------------------------------------------------------------*
248  *---------------------------------------------------------------------------*/
holdPedalUp(void)249 static void holdPedalUp(void)
250 {
251     if (hold)
252     {
253         u8 ch[3];
254         int old;
255 
256         ch[0] = 0xB0;
257         ch[1] = 0x40;
258         ch[2] = 0;
259 
260         old = OSDisableInterrupts();
261 
262         SYNMidiInput(&synth, ch);
263 
264         OSRestoreInterrupts(old);
265 
266         hold = 0;
267     }
268 }
269 
270 #ifdef HOLLYWOOD_REV
271 /*---------------------------------------------------------------------------*
272  *---------------------------------------------------------------------------*/
LoadFileIntoRam(char * path)273 static void* LoadFileIntoRam(char *path)
274 {
275     DVDFileInfo handle;
276     u32         round_length;
277     s32         read_length;
278     void        *buffer;
279 
280     // Open File
281     if (!DVDOpen(path, &handle))
282     {
283         OSReport("WARNING! Failed to open %s\n", path);
284         return NULL;
285     }
286 
287     // Make sure file length is not 0
288     if (DVDGetLength(&handle) == 0)
289     {
290         OSReport("WARNING! File length is 0\n");
291         return NULL;
292     }
293 
294     round_length = OSRoundUp32B(DVDGetLength(&handle));
295     buffer       = MEMAllocFromExpHeapEx(hExpHeap, round_length,  32);
296 
297     // Make sure we got a buffer
298     if (buffer == NULL)
299     {
300         OSReport("WARNING! Unable to allocate buffer\n");
301         return NULL;
302     }
303 
304     // Read Files
305     read_length = DVDRead(&handle, buffer, (s32)(round_length), 0);
306 
307     // Make sure we read the file correctly
308     if (read_length <= 0)
309     {
310         OSReport("WARNING! File lenght is wrong\n");
311         return NULL;
312     }
313 
314     return buffer;
315 }
316 #endif
317 
318 /*---------------------------------------------------------------------------*
319  *---------------------------------------------------------------------------*/
main(void)320 void main(void)
321 {
322     PADStatus  pads[PAD_MAX_CONTROLLERS];
323     u8         *wavetable;
324 #ifndef HOLLYWOOD_REV
325     u32        aramBase;
326     u32        aramSize;
327     u32        aramAddr;
328 #else
329     void       *arenaMem2Lo;
330     void       *arenaMem2Hi;
331     u8         *samples;
332     u8         *zeroBuffer;
333 #endif
334 
335     DEMOInit(NULL);
336 
337 #ifndef HOLLYWOOD_REV
338     ARInit(aramMemArray, MAX_ARAM_BLOCKS);
339     ARQInit();
340 #else
341     arenaMem2Lo = OSGetMEM2ArenaLo();
342     arenaMem2Hi = OSGetMEM2ArenaHi();
343     hExpHeap    = MEMCreateExpHeap(arenaMem2Lo, (u32)arenaMem2Hi - (u32) arenaMem2Lo);
344 #endif
345 
346     AIInit(NULL);
347     AXInit();
348     MIXInit();
349     SYNInit();
350 
351 #ifndef HOLLYWOOD_REV
352     // for the purpose of this demo we take all the ARAM HAHA!
353     aramSize = ARGetSize() - ARGetBaseAddress();
354     aramBase = ARAlloc(aramSize);
355     AMInit(aramBase, aramSize);
356 
357     aramAddr   = AMPush("/axdemo/synth/gm16pcm.pcm");
358     wavetable  = AMLoadFile("/axdemo/synth/gm16pcm.wt", NULL);
359 #else
360     wavetable  = LoadFileIntoRam("/axdemo/synth/gm16pcm.wt");
361     samples    = LoadFileIntoRam("/axdemo/synth/gm16pcm.pcm");
362     zeroBuffer = MEMAllocFromExpHeapEx(hExpHeap, ZEROBUFFER_BYTES, 8);
363 
364     memset(zeroBuffer, 0, ZEROBUFFER_BYTES);
365     DCFlushRange(zeroBuffer, ZEROBUFFER_BYTES);
366 #endif
367 
368     // register user callback for audio frames notification
369     AXRegisterCallback(&callbackAudioFrame);
370 
371     // initialize synth
372 #ifndef HOLLYWOOD_REV
373     SYNInitSynth(
374         &synth,                  // pointer to synth object
375         wavetable,               // pointer to wavetable
376         (u8*)aramAddr,           // address of samples in ARAM
377         (u8*)AMGetZeroBuffer(),  // address of zero buffer in ARAM
378         16,                      // priority for voice allocation
379         15,                      // priority for notes
380         1                        // priority for notes that have been released
381         );
382 #else
383     SYNInitSynth(
384         &synth,             // pointer to synth object
385         wavetable,          // pointer to wavetable
386         samples,            // pointer to samples
387         zeroBuffer,         // pointer to zero buffer
388         16,                 // priority for voice allocation
389         15,                 // priority for notes
390         1                   // priority for notes that have been released
391         );
392 #endif
393 
394     OSReport("Press the A button to increment key number and play note.\n");
395     OSReport("Press the B button to inclrement program number and change program.\n");
396     OSReport("Press the left trigger to hold pedal.\n");
397 
398     OSReport("Press Menu button to exit program\n");
399 
400     programChangeButton = 0;
401 
402     while (1)
403     {
404         // wait for retrace
405         VIWaitForRetrace();
406 
407         // check pad
408         PADRead(pads);
409 
410         // see if we should quit
411         if (pads[0].button & PAD_BUTTON_MENU)
412             break;
413 
414         // use A button for key
415         if (pads[0].button & PAD_BUTTON_A)
416             startNote();
417         else
418             stopNote();
419 
420         // use B button for program change
421         if (pads[0].button & PAD_BUTTON_B)
422             programChange();
423         else
424             programChange_();
425 
426         // use the left trigger for a hold pedal
427         if (pads[0].button & PAD_TRIGGER_L)
428             holdPedalDown();
429         else
430             holdPedalUp();
431     }
432 
433     SYNQuit();
434     MIXQuit();
435     AXQuit();
436 
437 #ifndef HOLLYWOOD_REV
438     if (wavetable)
439     {
440         OSFree(wavetable);
441     }
442 #else
443     if (wavetable)
444     {
445         MEMFreeToExpHeap(hExpHeap, wavetable);
446     }
447 
448     if (samples)
449     {
450         MEMFreeToExpHeap(hExpHeap, samples);
451     }
452 
453     if (zeroBuffer)
454     {
455         MEMFreeToExpHeap(hExpHeap, zeroBuffer);
456     }
457 #endif
458 
459     OSHalt("End of program\n");
460 
461 } // end main()
462