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