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