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