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