/*========================================================================= sound.cpp Author: PKG Created: Project: Spongebob Purpose: Copyright (c) 2000 Climax Development Ltd ===========================================================================*/ /*---------------------------------------------------------------------- Includes -------- */ #include "sound.h" #ifndef __SYSTEM_DBG_H__ #include "system\dbg.h" #endif /* Std Lib ------- */ /* Data ---- */ /*---------------------------------------------------------------------- Tyepdefs && Defines ------------------- */ /*---------------------------------------------------------------------- Structure defintions -------------------- */ typedef struct XMFILEDATA { FileEquate m_vh,m_vb,m_pxm; }; typedef struct SFXDETAILS { int m_channels; int m_pattern; int m_looping; }; /*---------------------------------------------------------------------- Function Prototypes ------------------- */ /*---------------------------------------------------------------------- Vars ---- */ static XMFILEDATA s_xmSongData[CSoundMediator::NUM_SONGIDS]= { { MUSIC_HYPERMMX_VH, MUSIC_HYPERMMX_VB, MUSIC_HYPERMMX_PXM }, // HYPERMMX { MUSIC_DROPPOP_VH, MUSIC_DROPPOP_VB, MUSIC_DROPPOP_PXM }, // DROPPOP { MUSIC_MUSIC_VH, MUSIC_MUSIC_VB, MUSIC_MUSIC_PXM }, // MUSIC }; static XMFILEDATA s_xmSfxData[CSoundMediator::NUM_SFXBANKIDS]= { { SFX_INGAME_VH, SFX_INGAME_VB, SFX_INGAME_PXM }, // INGAME }; static SFXDETAILS s_sfxDetails[]= { { 1, 0, 0 }, { 1, 1, 0 }, { 1, 2, 0 }, { 1, 3, 0 }, }; int CSoundMediator::s_initialised=false; int /*CSoundMediator::*/s_currentVolume[CSoundMediator::NUM_VOLUMETYPES]; int /*CSoundMediator::*/s_targetVolume[CSoundMediator::NUM_VOLUMETYPES]; int /*CSoundMediator::*/s_volumeDirty[CSoundMediator::NUM_VOLUMETYPES]; static CSpuSound *s_spuSound; static CXMPlaySound *s_xmplaySound; static xmSampleId s_songSampleId=NO_SAMPLE; static xmSongId s_songDataId=NO_SONG; static xmPlayingSongId s_songPlayingId=NOT_PLAYING; static xmSampleId s_sfxSampleId=NO_SAMPLE; static xmSongId s_sfxDataId=NO_SONG; /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ void CSoundMediator::initialise() { int i; ASSERT(!s_initialised); s_spuSound=new ("SPUSound") CSpuSound(); s_spuSound->initialise(); s_xmplaySound=new ("XMPlaySound") CXMPlaySound(); s_xmplaySound->initialise(); CXAStream::Init(); for(i=0;ishutdown(); delete s_xmplaySound; s_spuSound->shutdown(); delete s_spuSound; SOUND_DBGMSG("Sound mediator shutdown"); s_initialised=false; } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ int tgt=255; int val; static int s_spuChannelUse[24]={-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1}; void CSoundMediator::think(int _frames) { int i; int diff,speed; int *current,*target,*dirty; ASSERT(s_initialised); { int id; id=-1; for(i=SONG_CHANNELS;i<24;i++) { if(id!=s_spuChannelUse[i]) { id=s_spuChannelUse[i]; if(id!=-1) { /* if(id>=5000) { PAUL_DBGMSG("%d is now free.. ( was on chnl %d )",id-5000,i); while(s_spuChannelUse[i]==id&&i<24) { s_spuChannelUse[i++]=-1; } i--; } else if(id>=100) { while(s_spuChannelUse[i]==id&&i<24) { s_spuChannelUse[i++]+=100; } i--; } else */ if(!s_xmplaySound->isSfxActive((xmPlayingSongId)id)) { PAUL_DBGMSG("%d end.. ( was on chnl %d )",id,i); while(s_spuChannelUse[i]==id&&i<24) { s_spuChannelUse[i++]=-1; } i--; } //else //{ // PAUL_DBGMSG("channel %d playing",i); //} } } } } // Fade to target volume speed=(_frames*VOLUME_CHANGE_SPEED)>>10; current=s_currentVolume; target=s_targetVolume; dirty=s_volumeDirty; for(i=0;i0) { *current+=speed; if(*current>*target)*current=*target; *dirty=true; } current++; target++; dirty++; } // Manual update of anything that needs it // CXAStream::ControlXA(); // Push through any changes in volume if(s_volumeDirty[SONG]||s_volumeDirty[SONGFADE]) { if(s_songPlayingId!=NOT_PLAYING) { int vol=(s_currentVolume[SONG]*((s_currentVolume[SONGFADE]>>1)+128))>>8; s_xmplaySound->setVolume(s_songPlayingId,(char)vol); } s_volumeDirty[SONG]=s_volumeDirty[SONGFADE]=false; } if(s_volumeDirty[SFX]) { s_volumeDirty[SFX]=false; } // if(s_volumeDirty[SPEECH]) // { // int vol=s_currentVolume[SPEECH]<<7; // CXAStream::SetVolume(vol,vol); // s_volumeDirty[SPEECH]=false; // } } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ void CSoundMediator::setSong(SONGID _songId) { XMFILEDATA *song; ASSERT(s_songSampleId==NO_SAMPLE); ASSERT(s_songDataId==NO_SONG); song=&s_xmSongData[_songId]; s_songDataId=s_xmplaySound->loadSongData(song->m_pxm); s_songSampleId=s_xmplaySound->loadSamples(song->m_vh,song->m_vb); } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ void CSoundMediator::playSong() { ASSERT(s_songSampleId!=NO_SAMPLE); ASSERT(s_songDataId!=NO_SONG); ASSERT(s_songPlayingId==NOT_PLAYING); s_songPlayingId=s_xmplaySound->playSong(s_songSampleId,s_songDataId,SONG_BASE_CHANNEL); s_volumeDirty[SONG]=true; // Force a volume update } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ void CSoundMediator::dumpSong() { ASSERT(s_songSampleId!=NO_SAMPLE); ASSERT(s_songDataId!=NO_SONG); if(s_songPlayingId!=NOT_PLAYING)s_xmplaySound->stopSong(s_songPlayingId); s_xmplaySound->dumpSamples(s_songSampleId); s_xmplaySound->dumpSongData(s_songDataId); s_songSampleId=NO_SAMPLE; s_songDataId=NO_SONG; s_songPlayingId=NOT_PLAYING; } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ void CSoundMediator::setSfxBank(SFXBANKID _bankId) { XMFILEDATA *song; ASSERT(s_sfxSampleId==NO_SAMPLE); ASSERT(s_sfxDataId==NO_SONG); song=&s_xmSfxData[_bankId]; s_sfxDataId=s_xmplaySound->loadSongData(song->m_pxm); s_sfxSampleId=s_xmplaySound->loadSamples(song->m_vh,song->m_vb); } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ int CSoundMediator::playSfx(int _sfxId) { ASSERT(s_sfxSampleId!=NO_SAMPLE); ASSERT(s_sfxDataId!=NO_SONG); int baseChannel; int channelCount=0; int sfxChannelMask,maskCopy; int i,j; int valid; int maskCheck=1; int playId; sfxChannelMask=3; // Count channels maskCopy=sfxChannelMask; for(i=0;i<24&&maskCopy;i++) { if(maskCopy&1) channelCount++; maskCopy>>=1; } // Find some spare channels to play on valid=false; for(i=SFX_BASE_CHANNEL;iplaySfx(s_sfxSampleId,s_sfxDataId,baseChannel,_sfxId,sfxChannelMask); s_volumeDirty[SFX]=true; // Force a volume update // Clear any dead channels //for(i=SFX_BASE_CHANNEL;i=MIN_VOLUME&&_val<=MAX_VOLUME); s_targetVolume[_type]=_val; s_volumeDirty[_type]=true; // Otherwise we could miss volume changes under rare conditions } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ int CSoundMediator::getVolume(VOLUMETYPE _type) { return s_targetVolume[_type]; } /*=========================================================================== end */