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