1 /*---------------------------------------------------------------------------*
2 Project: Sound Pipeline (SP) for AX
3 File: sp.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: sp.c,v $
14 Revision 1.3 2006/11/21 04:26:28 aka
15 Removed #ifndef HOLLYWOOD_REV - #else - #endif.
16 Removed assertion of the zero buffer.
17 Changed not to use the zero buffer.
18
19 Revision 1.2 2006/01/31 07:12:23 aka
20 Changed arguments of SPInitSoundTable().
21 Added #ifndef HOLLYWOOD_REV - #else - #endif.
22
23 Revision 1.1.1.1 2005/05/12 02:15:50 yasuh-to
24 Imported from dolphin tree.
25
26 1 8/15/01 11:16a Billyjack
27 created
28
29 $NoKeywords: $
30 *---------------------------------------------------------------------------*/
31 #include <revolution.h>
32 #include <revolution/sp.h>
33
34
35 /*---------------------------------------------------------------------------*
36 *---------------------------------------------------------------------------*/
SPInitSoundTable(SPSoundTable * table,u8 * samples,u8 * zerobuffer)37 void SPInitSoundTable(SPSoundTable *table, u8 *samples, u8 *zerobuffer)
38 {
39 #pragma unused(zerobuffer)
40
41 int i;
42 SPSoundEntry *sound;
43 SPAdpcmEntry *adpcm;
44 u32 mramBase, mramBase4, mramBase8, mramBase16;
45
46 ASSERT(table);
47 ASSERT(samples);
48 //ASSERT(zerobuffer);
49
50 // pre compute base addresses
51 mramBase = OSCachedToPhysical(samples);
52 mramBase4 = mramBase << 1;
53 mramBase8 = mramBase;
54 mramBase16 = mramBase >> 1;
55
56 // initialize pointers to objects
57 sound = &table->sound[0];
58 adpcm = (SPAdpcmEntry*)&table->sound[table->entries];
59
60 // intialize objects
61 for (i = 0; i < table->entries; i++)
62 {
63 switch (sound->type)
64 {
65 case SP_TYPE_ADPCM_ONESHOT:
66
67 sound->loopAddr = mramBase4 + sound->currentAddr; // dummy
68 sound->loopEndAddr = 0; // not used
69 sound->endAddr = mramBase4 + sound->endAddr;
70 sound->currentAddr = mramBase4 + sound->currentAddr;
71 sound->adpcm = adpcm;
72
73 adpcm++;
74
75 break;
76
77 case SP_TYPE_ADPCM_LOOPED:
78
79 sound->loopAddr = mramBase4 + sound->loopAddr;
80 sound->loopEndAddr = mramBase4 + sound->loopEndAddr;
81 sound->endAddr = mramBase4 + sound->endAddr;
82 sound->currentAddr = mramBase4 + sound->currentAddr;
83 sound->adpcm = adpcm;
84
85 adpcm++;
86
87 break;
88
89 case SP_TYPE_PCM16_ONESHOT:
90
91 sound->loopAddr = mramBase16 + sound->currentAddr; // dummy
92 sound->loopEndAddr = 0; // not used
93 sound->endAddr = mramBase16 + sound->endAddr;
94 sound->currentAddr = mramBase16 + sound->currentAddr;
95
96 break;
97
98 case SP_TYPE_PCM16_LOOPED:
99
100 sound->loopAddr = mramBase16 + sound->loopAddr;
101 sound->loopEndAddr = mramBase16 + sound->loopEndAddr;
102 sound->endAddr = mramBase16 + sound->endAddr;
103 sound->currentAddr = mramBase16 + sound->currentAddr;
104
105 break;
106
107 case SP_TYPE_PCM8_ONESHOT:
108
109 sound->loopAddr = mramBase8 + sound->currentAddr; // dummy
110 sound->loopEndAddr = 0; // not used
111 sound->endAddr = mramBase8 + sound->endAddr;
112 sound->currentAddr = mramBase8 + sound->currentAddr;
113
114 break;
115
116 case SP_TYPE_PCM8_LOOPED:
117
118 sound->loopAddr = mramBase8 + sound->loopAddr;
119 sound->loopEndAddr = mramBase8 + sound->loopEndAddr;
120 sound->endAddr = mramBase8 + sound->endAddr;
121 sound->currentAddr = mramBase8 + sound->currentAddr;
122
123 break;
124 }
125
126 sound++;
127 }
128 }
129
130
131 /*---------------------------------------------------------------------------*
132 *---------------------------------------------------------------------------*/
SPGetSoundEntry(SPSoundTable * table,u32 index)133 SPSoundEntry * SPGetSoundEntry(SPSoundTable *table, u32 index)
134 {
135 ASSERT(table);
136
137 if (table->entries > index)
138 return &table->sound[index];
139
140 return NULL;
141 }
142
143
144 /*---------------------------------------------------------------------------*
145 *---------------------------------------------------------------------------*/
SPPrepareSound(SPSoundEntry * sound,AXVPB * axvpb,u32 sampleRate)146 void SPPrepareSound(SPSoundEntry *sound, AXVPB *axvpb, u32 sampleRate)
147 {
148 int old;
149 u32 srcBits, loopAddr, endAddr, currentAddr;
150 u16 *p, *p1;
151
152 ASSERT(sound);
153 ASSERT(axvpb);
154
155 srcBits = (u32)(0x00010000 * ((f32)sampleRate / AX_IN_SAMPLES_PER_SEC));
156
157 switch (sound->type)
158 {
159 case SP_TYPE_ADPCM_ONESHOT:
160
161 loopAddr = sound->loopAddr;
162 endAddr = sound->endAddr;
163 currentAddr = sound->currentAddr;
164
165 p = (u16*)&axvpb->pb.addr;
166 p1 = (u16*)sound->adpcm;
167
168 old = OSDisableInterrupts();
169
170 // addr bits
171 *p++ = AXPBADDR_LOOP_OFF;
172 *p++ = AX_PB_FORMAT_ADPCM;
173 *p++ = (u16)(loopAddr >> 16);
174 *p++ = (u16)(loopAddr & 0xffff);
175 *p++ = (u16)(endAddr >> 16);
176 *p++ = (u16)(endAddr & 0xffff);
177 *p++ = (u16)(currentAddr >> 16);
178 *p++ = (u16)(currentAddr & 0xffff);
179 // adpcm bits
180 *p++ = *p1++;
181 *p++ = *p1++;
182 *p++ = *p1++;
183 *p++ = *p1++;
184 *p++ = *p1++;
185 *p++ = *p1++;
186 *p++ = *p1++;
187 *p++ = *p1++;
188 *p++ = *p1++;
189 *p++ = *p1++;
190 *p++ = *p1++;
191 *p++ = *p1++;
192 *p++ = *p1++;
193 *p++ = *p1++;
194 *p++ = *p1++;
195 *p++ = *p1++;
196 *p++ = *p1++;
197 *p++ = *p1++;
198 *p++ = *p1++;
199 *p++ = *p1++;
200 // src bits
201 *p++ = (u16)(srcBits >> 16);
202 *p++ = (u16)(srcBits & 0xFFFF);
203 *p++ = 0;
204 *p++ = 0;
205 *p++ = 0;
206 *p++ = 0;
207 *p++ = 0;
208 // don't need ADPCM loop context
209
210 axvpb->sync |= AX_SYNC_USER_ADDR | AX_SYNC_USER_ADPCM | AX_SYNC_USER_SRC;
211
212 OSRestoreInterrupts(old);
213
214 break;
215
216 case SP_TYPE_ADPCM_LOOPED:
217
218 loopAddr = sound->loopAddr;
219 endAddr = sound->loopEndAddr;
220 currentAddr = sound->currentAddr;
221
222 p = (u16*)&axvpb->pb.addr;
223 p1 = (u16*)sound->adpcm;
224
225 old = OSDisableInterrupts();
226
227 // addr bits
228 *p++ = AXPBADDR_LOOP_ON;
229 *p++ = AX_PB_FORMAT_ADPCM;
230 *p++ = (u16)(loopAddr >> 16);
231 *p++ = (u16)(loopAddr & 0xffff);
232 *p++ = (u16)(endAddr >> 16);
233 *p++ = (u16)(endAddr & 0xffff);
234 *p++ = (u16)(currentAddr >> 16);
235 *p++ = (u16)(currentAddr & 0xffff);
236 // adpcm bits
237 *p++ = *p1++;
238 *p++ = *p1++;
239 *p++ = *p1++;
240 *p++ = *p1++;
241 *p++ = *p1++;
242 *p++ = *p1++;
243 *p++ = *p1++;
244 *p++ = *p1++;
245 *p++ = *p1++;
246 *p++ = *p1++;
247 *p++ = *p1++;
248 *p++ = *p1++;
249 *p++ = *p1++;
250 *p++ = *p1++;
251 *p++ = *p1++;
252 *p++ = *p1++;
253 *p++ = *p1++;
254 *p++ = *p1++;
255 *p++ = *p1++;
256 *p++ = *p1++;
257 // src bits
258 *p++ = (u16)(srcBits >> 16);
259 *p++ = (u16)(srcBits & 0xFFFF);
260 *p++ = 0;
261 *p++ = 0;
262 *p++ = 0;
263 *p++ = 0;
264 *p++ = 0;
265 // ADPCM loop bits
266 *p++ = *p1++;
267 *p++ = *p1++;
268 *p++ = *p1++;
269
270 axvpb->sync |= AX_SYNC_USER_ADDR | AX_SYNC_USER_ADPCM | AX_SYNC_USER_SRC | AX_SYNC_USER_ADPCMLOOP;
271
272 OSRestoreInterrupts(old);
273
274 break;
275
276 case SP_TYPE_PCM16_ONESHOT:
277
278 loopAddr = sound->loopAddr;
279 endAddr = sound->endAddr;
280 currentAddr = sound->currentAddr;
281
282 p = (u16*)&axvpb->pb.addr;
283
284 old = OSDisableInterrupts();
285
286 // addr bits
287 *p++ = AXPBADDR_LOOP_OFF;
288 *p++ = AX_PB_FORMAT_PCM16;
289 *p++ = (u16)(loopAddr >> 16);
290 *p++ = (u16)(loopAddr & 0xffff);
291 *p++ = (u16)(endAddr >> 16);
292 *p++ = (u16)(endAddr & 0xffff);
293 *p++ = (u16)(currentAddr >> 16);
294 *p++ = (u16)(currentAddr & 0xffff);
295 // adpcm bits
296 *p++ = 0;
297 *p++ = 0;
298 *p++ = 0;
299 *p++ = 0;
300 *p++ = 0;
301 *p++ = 0;
302 *p++ = 0;
303 *p++ = 0;
304 *p++ = 0;
305 *p++ = 0;
306 *p++ = 0;
307 *p++ = 0;
308 *p++ = 0;
309 *p++ = 0;
310 *p++ = 0;
311 *p++ = 0;
312 *p++ = 0x0800;
313 *p++ = 0;
314 *p++ = 0;
315 *p++ = 0;
316 // src bits
317 *p++ = (u16)(srcBits >> 16);
318 *p++ = (u16)(srcBits & 0xFFFF);
319 *p++ = 0;
320 *p++ = 0;
321 *p++ = 0;
322 *p++ = 0;
323 *p++ = 0;
324 // don't need ADPCM loop context
325
326 axvpb->sync |= AX_SYNC_USER_ADDR | AX_SYNC_USER_ADPCM | AX_SYNC_USER_SRC;
327
328 OSRestoreInterrupts(old);
329
330 break;
331
332 case SP_TYPE_PCM16_LOOPED:
333
334 loopAddr = sound->loopAddr;
335 endAddr = sound->loopEndAddr;
336 currentAddr = sound->currentAddr;
337
338 p = (u16*)&axvpb->pb.addr;
339
340 old = OSDisableInterrupts();
341
342 // addr bits
343 *p++ = AXPBADDR_LOOP_ON;
344 *p++ = AX_PB_FORMAT_PCM16;
345 *p++ = (u16)(loopAddr >> 16);
346 *p++ = (u16)(loopAddr & 0xffff);
347 *p++ = (u16)(endAddr >> 16);
348 *p++ = (u16)(endAddr & 0xffff);
349 *p++ = (u16)(currentAddr >> 16);
350 *p++ = (u16)(currentAddr & 0xffff);
351 // adpcm bits
352 *p++ = 0;
353 *p++ = 0;
354 *p++ = 0;
355 *p++ = 0;
356 *p++ = 0;
357 *p++ = 0;
358 *p++ = 0;
359 *p++ = 0;
360 *p++ = 0;
361 *p++ = 0;
362 *p++ = 0;
363 *p++ = 0;
364 *p++ = 0;
365 *p++ = 0;
366 *p++ = 0;
367 *p++ = 0;
368 *p++ = 0x0800;
369 *p++ = 0;
370 *p++ = 0;
371 *p++ = 0;
372 // src bits
373 *p++ = (u16)(srcBits >> 16);
374 *p++ = (u16)(srcBits & 0xFFFF);
375 *p++ = 0;
376 *p++ = 0;
377 *p++ = 0;
378 *p++ = 0;
379 *p++ = 0;
380 // don't need ADPCM loop context
381
382 axvpb->sync |= AX_SYNC_USER_ADDR | AX_SYNC_USER_ADPCM | AX_SYNC_USER_SRC;
383
384 OSRestoreInterrupts(old);
385
386 break;
387
388 case SP_TYPE_PCM8_ONESHOT:
389
390 loopAddr = sound->loopAddr;
391 endAddr = sound->endAddr;
392 currentAddr = sound->currentAddr;
393
394 p = (u16*)&axvpb->pb.addr;
395
396 old = OSDisableInterrupts();
397
398 // addr bits
399 *p++ = AXPBADDR_LOOP_OFF;
400 *p++ = AX_PB_FORMAT_PCM8;
401 *p++ = (u16)(loopAddr >> 16);
402 *p++ = (u16)(loopAddr & 0xffff);
403 *p++ = (u16)(endAddr >> 16);
404 *p++ = (u16)(endAddr & 0xffff);
405 *p++ = (u16)(currentAddr >> 16);
406 *p++ = (u16)(currentAddr & 0xffff);
407 // adpcm bits
408 *p++ = 0;
409 *p++ = 0;
410 *p++ = 0;
411 *p++ = 0;
412 *p++ = 0;
413 *p++ = 0;
414 *p++ = 0;
415 *p++ = 0;
416 *p++ = 0;
417 *p++ = 0;
418 *p++ = 0;
419 *p++ = 0;
420 *p++ = 0;
421 *p++ = 0;
422 *p++ = 0;
423 *p++ = 0;
424 *p++ = 0x0100;
425 *p++ = 0;
426 *p++ = 0;
427 *p++ = 0;
428 // src bits
429 *p++ = (u16)(srcBits >> 16);
430 *p++ = (u16)(srcBits & 0xFFFF);
431 *p++ = 0;
432 *p++ = 0;
433 *p++ = 0;
434 *p++ = 0;
435 *p++ = 0;
436 // don't need ADPCM loop context
437
438 axvpb->sync |= AX_SYNC_USER_ADDR | AX_SYNC_USER_ADPCM | AX_SYNC_USER_SRC;
439
440 OSRestoreInterrupts(old);
441
442 break;
443
444 case SP_TYPE_PCM8_LOOPED:
445
446 loopAddr = sound->loopAddr;
447 endAddr = sound->loopEndAddr;
448 currentAddr = sound->currentAddr;
449
450 p = (u16*)&axvpb->pb.addr;
451
452 old = OSDisableInterrupts();
453
454 // addr bits
455 *p++ = AXPBADDR_LOOP_ON;
456 *p++ = AX_PB_FORMAT_PCM8;
457 *p++ = (u16)(loopAddr >> 16);
458 *p++ = (u16)(loopAddr & 0xffff);
459 *p++ = (u16)(endAddr >> 16);
460 *p++ = (u16)(endAddr & 0xffff);
461 *p++ = (u16)(currentAddr >> 16);
462 *p++ = (u16)(currentAddr & 0xffff);
463 // adpcm bits
464 *p++ = 0;
465 *p++ = 0;
466 *p++ = 0;
467 *p++ = 0;
468 *p++ = 0;
469 *p++ = 0;
470 *p++ = 0;
471 *p++ = 0;
472 *p++ = 0;
473 *p++ = 0;
474 *p++ = 0;
475 *p++ = 0;
476 *p++ = 0;
477 *p++ = 0;
478 *p++ = 0;
479 *p++ = 0;
480 *p++ = 0x0100;
481 *p++ = 0;
482 *p++ = 0;
483 *p++ = 0;
484 // src bits
485 *p++ = (u16)(srcBits >> 16);
486 *p++ = (u16)(srcBits & 0xFFFF);
487 *p++ = 0;
488 *p++ = 0;
489 *p++ = 0;
490 *p++ = 0;
491 *p++ = 0;
492 // don't need ADPCM loop context
493
494 axvpb->sync |= AX_SYNC_USER_ADDR | AX_SYNC_USER_ADPCM | AX_SYNC_USER_SRC;
495
496 OSRestoreInterrupts(old);
497
498 break;
499 }
500 }
501
502
503 /*---------------------------------------------------------------------------*
504 *---------------------------------------------------------------------------*/
SPPrepareEnd(SPSoundEntry * sound,AXVPB * axvpb)505 void SPPrepareEnd(SPSoundEntry *sound, AXVPB *axvpb)
506 {
507 int old;
508
509 ASSERT(sound);
510 ASSERT(axvpb);
511
512 old = OSDisableInterrupts();
513
514 axvpb->pb.addr.loopFlag = AXPBADDR_LOOP_OFF;
515 axvpb->pb.addr.endAddressHi = (u16)(sound->endAddr >> 16);
516 axvpb->pb.addr.endAddressLo = (u16)(sound->endAddr & 0xFFFF);
517
518 axvpb->sync |= AX_SYNC_USER_LOOP | AX_SYNC_USER_ENDADDR;
519
520 OSRestoreInterrupts(old);
521 }
522