/*---------------------------------------------------------------------------* Project: Sound Pipeline (SP) for AX File: sp.c Copyright (C)1998-2006 Nintendo All Rights Reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Log: sp.c,v $ Revision 1.3 2006/11/21 04:26:28 aka Removed #ifndef HOLLYWOOD_REV - #else - #endif. Removed assertion of the zero buffer. Changed not to use the zero buffer. Revision 1.2 2006/01/31 07:12:23 aka Changed arguments of SPInitSoundTable(). Added #ifndef HOLLYWOOD_REV - #else - #endif. Revision 1.1.1.1 2005/05/12 02:15:50 yasuh-to Imported from dolphin tree. 1 8/15/01 11:16a Billyjack created $NoKeywords: $ *---------------------------------------------------------------------------*/ #include #include /*---------------------------------------------------------------------------* *---------------------------------------------------------------------------*/ void SPInitSoundTable(SPSoundTable *table, u8 *samples, u8 *zerobuffer) { #pragma unused(zerobuffer) int i; SPSoundEntry *sound; SPAdpcmEntry *adpcm; u32 mramBase, mramBase4, mramBase8, mramBase16; ASSERT(table); ASSERT(samples); //ASSERT(zerobuffer); // pre compute base addresses mramBase = OSCachedToPhysical(samples); mramBase4 = mramBase << 1; mramBase8 = mramBase; mramBase16 = mramBase >> 1; // initialize pointers to objects sound = &table->sound[0]; adpcm = (SPAdpcmEntry*)&table->sound[table->entries]; // intialize objects for (i = 0; i < table->entries; i++) { switch (sound->type) { case SP_TYPE_ADPCM_ONESHOT: sound->loopAddr = mramBase4 + sound->currentAddr; // dummy sound->loopEndAddr = 0; // not used sound->endAddr = mramBase4 + sound->endAddr; sound->currentAddr = mramBase4 + sound->currentAddr; sound->adpcm = adpcm; adpcm++; break; case SP_TYPE_ADPCM_LOOPED: sound->loopAddr = mramBase4 + sound->loopAddr; sound->loopEndAddr = mramBase4 + sound->loopEndAddr; sound->endAddr = mramBase4 + sound->endAddr; sound->currentAddr = mramBase4 + sound->currentAddr; sound->adpcm = adpcm; adpcm++; break; case SP_TYPE_PCM16_ONESHOT: sound->loopAddr = mramBase16 + sound->currentAddr; // dummy sound->loopEndAddr = 0; // not used sound->endAddr = mramBase16 + sound->endAddr; sound->currentAddr = mramBase16 + sound->currentAddr; break; case SP_TYPE_PCM16_LOOPED: sound->loopAddr = mramBase16 + sound->loopAddr; sound->loopEndAddr = mramBase16 + sound->loopEndAddr; sound->endAddr = mramBase16 + sound->endAddr; sound->currentAddr = mramBase16 + sound->currentAddr; break; case SP_TYPE_PCM8_ONESHOT: sound->loopAddr = mramBase8 + sound->currentAddr; // dummy sound->loopEndAddr = 0; // not used sound->endAddr = mramBase8 + sound->endAddr; sound->currentAddr = mramBase8 + sound->currentAddr; break; case SP_TYPE_PCM8_LOOPED: sound->loopAddr = mramBase8 + sound->loopAddr; sound->loopEndAddr = mramBase8 + sound->loopEndAddr; sound->endAddr = mramBase8 + sound->endAddr; sound->currentAddr = mramBase8 + sound->currentAddr; break; } sound++; } } /*---------------------------------------------------------------------------* *---------------------------------------------------------------------------*/ SPSoundEntry * SPGetSoundEntry(SPSoundTable *table, u32 index) { ASSERT(table); if (table->entries > index) return &table->sound[index]; return NULL; } /*---------------------------------------------------------------------------* *---------------------------------------------------------------------------*/ void SPPrepareSound(SPSoundEntry *sound, AXVPB *axvpb, u32 sampleRate) { int old; u32 srcBits, loopAddr, endAddr, currentAddr; u16 *p, *p1; ASSERT(sound); ASSERT(axvpb); srcBits = (u32)(0x00010000 * ((f32)sampleRate / AX_IN_SAMPLES_PER_SEC)); switch (sound->type) { case SP_TYPE_ADPCM_ONESHOT: loopAddr = sound->loopAddr; endAddr = sound->endAddr; currentAddr = sound->currentAddr; p = (u16*)&axvpb->pb.addr; p1 = (u16*)sound->adpcm; old = OSDisableInterrupts(); // addr bits *p++ = AXPBADDR_LOOP_OFF; *p++ = AX_PB_FORMAT_ADPCM; *p++ = (u16)(loopAddr >> 16); *p++ = (u16)(loopAddr & 0xffff); *p++ = (u16)(endAddr >> 16); *p++ = (u16)(endAddr & 0xffff); *p++ = (u16)(currentAddr >> 16); *p++ = (u16)(currentAddr & 0xffff); // adpcm bits *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; // src bits *p++ = (u16)(srcBits >> 16); *p++ = (u16)(srcBits & 0xFFFF); *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; // don't need ADPCM loop context axvpb->sync |= AX_SYNC_USER_ADDR | AX_SYNC_USER_ADPCM | AX_SYNC_USER_SRC; OSRestoreInterrupts(old); break; case SP_TYPE_ADPCM_LOOPED: loopAddr = sound->loopAddr; endAddr = sound->loopEndAddr; currentAddr = sound->currentAddr; p = (u16*)&axvpb->pb.addr; p1 = (u16*)sound->adpcm; old = OSDisableInterrupts(); // addr bits *p++ = AXPBADDR_LOOP_ON; *p++ = AX_PB_FORMAT_ADPCM; *p++ = (u16)(loopAddr >> 16); *p++ = (u16)(loopAddr & 0xffff); *p++ = (u16)(endAddr >> 16); *p++ = (u16)(endAddr & 0xffff); *p++ = (u16)(currentAddr >> 16); *p++ = (u16)(currentAddr & 0xffff); // adpcm bits *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; // src bits *p++ = (u16)(srcBits >> 16); *p++ = (u16)(srcBits & 0xFFFF); *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; // ADPCM loop bits *p++ = *p1++; *p++ = *p1++; *p++ = *p1++; axvpb->sync |= AX_SYNC_USER_ADDR | AX_SYNC_USER_ADPCM | AX_SYNC_USER_SRC | AX_SYNC_USER_ADPCMLOOP; OSRestoreInterrupts(old); break; case SP_TYPE_PCM16_ONESHOT: loopAddr = sound->loopAddr; endAddr = sound->endAddr; currentAddr = sound->currentAddr; p = (u16*)&axvpb->pb.addr; old = OSDisableInterrupts(); // addr bits *p++ = AXPBADDR_LOOP_OFF; *p++ = AX_PB_FORMAT_PCM16; *p++ = (u16)(loopAddr >> 16); *p++ = (u16)(loopAddr & 0xffff); *p++ = (u16)(endAddr >> 16); *p++ = (u16)(endAddr & 0xffff); *p++ = (u16)(currentAddr >> 16); *p++ = (u16)(currentAddr & 0xffff); // adpcm bits *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0x0800; *p++ = 0; *p++ = 0; *p++ = 0; // src bits *p++ = (u16)(srcBits >> 16); *p++ = (u16)(srcBits & 0xFFFF); *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; // don't need ADPCM loop context axvpb->sync |= AX_SYNC_USER_ADDR | AX_SYNC_USER_ADPCM | AX_SYNC_USER_SRC; OSRestoreInterrupts(old); break; case SP_TYPE_PCM16_LOOPED: loopAddr = sound->loopAddr; endAddr = sound->loopEndAddr; currentAddr = sound->currentAddr; p = (u16*)&axvpb->pb.addr; old = OSDisableInterrupts(); // addr bits *p++ = AXPBADDR_LOOP_ON; *p++ = AX_PB_FORMAT_PCM16; *p++ = (u16)(loopAddr >> 16); *p++ = (u16)(loopAddr & 0xffff); *p++ = (u16)(endAddr >> 16); *p++ = (u16)(endAddr & 0xffff); *p++ = (u16)(currentAddr >> 16); *p++ = (u16)(currentAddr & 0xffff); // adpcm bits *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0x0800; *p++ = 0; *p++ = 0; *p++ = 0; // src bits *p++ = (u16)(srcBits >> 16); *p++ = (u16)(srcBits & 0xFFFF); *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; // don't need ADPCM loop context axvpb->sync |= AX_SYNC_USER_ADDR | AX_SYNC_USER_ADPCM | AX_SYNC_USER_SRC; OSRestoreInterrupts(old); break; case SP_TYPE_PCM8_ONESHOT: loopAddr = sound->loopAddr; endAddr = sound->endAddr; currentAddr = sound->currentAddr; p = (u16*)&axvpb->pb.addr; old = OSDisableInterrupts(); // addr bits *p++ = AXPBADDR_LOOP_OFF; *p++ = AX_PB_FORMAT_PCM8; *p++ = (u16)(loopAddr >> 16); *p++ = (u16)(loopAddr & 0xffff); *p++ = (u16)(endAddr >> 16); *p++ = (u16)(endAddr & 0xffff); *p++ = (u16)(currentAddr >> 16); *p++ = (u16)(currentAddr & 0xffff); // adpcm bits *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0x0100; *p++ = 0; *p++ = 0; *p++ = 0; // src bits *p++ = (u16)(srcBits >> 16); *p++ = (u16)(srcBits & 0xFFFF); *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; // don't need ADPCM loop context axvpb->sync |= AX_SYNC_USER_ADDR | AX_SYNC_USER_ADPCM | AX_SYNC_USER_SRC; OSRestoreInterrupts(old); break; case SP_TYPE_PCM8_LOOPED: loopAddr = sound->loopAddr; endAddr = sound->loopEndAddr; currentAddr = sound->currentAddr; p = (u16*)&axvpb->pb.addr; old = OSDisableInterrupts(); // addr bits *p++ = AXPBADDR_LOOP_ON; *p++ = AX_PB_FORMAT_PCM8; *p++ = (u16)(loopAddr >> 16); *p++ = (u16)(loopAddr & 0xffff); *p++ = (u16)(endAddr >> 16); *p++ = (u16)(endAddr & 0xffff); *p++ = (u16)(currentAddr >> 16); *p++ = (u16)(currentAddr & 0xffff); // adpcm bits *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0x0100; *p++ = 0; *p++ = 0; *p++ = 0; // src bits *p++ = (u16)(srcBits >> 16); *p++ = (u16)(srcBits & 0xFFFF); *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; // don't need ADPCM loop context axvpb->sync |= AX_SYNC_USER_ADDR | AX_SYNC_USER_ADPCM | AX_SYNC_USER_SRC; OSRestoreInterrupts(old); break; } } /*---------------------------------------------------------------------------* *---------------------------------------------------------------------------*/ void SPPrepareEnd(SPSoundEntry *sound, AXVPB *axvpb) { int old; ASSERT(sound); ASSERT(axvpb); old = OSDisableInterrupts(); axvpb->pb.addr.loopFlag = AXPBADDR_LOOP_OFF; axvpb->pb.addr.endAddressHi = (u16)(sound->endAddr >> 16); axvpb->pb.addr.endAddressLo = (u16)(sound->endAddr & 0xFFFF); axvpb->sync |= AX_SYNC_USER_LOOP | AX_SYNC_USER_ENDADDR; OSRestoreInterrupts(old); }