diff --git a/source/paul/paul.cpp b/source/paul/paul.cpp index 6a46647d7..dddccb606 100644 --- a/source/paul/paul.cpp +++ b/source/paul/paul.cpp @@ -74,6 +74,7 @@ char *s_mem[3]; Params: Returns: ---------------------------------------------------------------------- */ +int ploopid=0; void CPaulScene::init() { s_fontBank.initialise(&standardFont); @@ -87,6 +88,8 @@ void CPaulScene::init() //CXAStream::Init(); PAUL_DBGMSG("initialised.."); + + ploopid=CSoundMediator::playSfx(0); } @@ -133,12 +136,14 @@ int pkill=0; #include "sound\speech.h" int mvol=10; int svol=255; +VECTOR ppos; void CPaulScene::think() { int pad; int sfxId=-1; - int setVolumes=false; + int setSfxVolume=false; + int setSongVolume=false; pad=PadGetDown(0); if(pad&PAD_R1) @@ -164,39 +169,51 @@ void CPaulScene::think() if(sfxId!=-1) { CSoundMediator::playSfx(sfxId); - } if(pad&PAD_START) { + PAUL_DBGMSG("stop %d",pkill); CSoundMediator::stopSfx((xmPlayingId)pkill); } + if(pad&PAD_R2) + { + PAUL_DBGMSG("stop all"); + CSoundMediator::stopAllSound(); + } +//CSoundMediator::setposition((xmPlayingId)ploopid,&ppos); pad=PadGetHeld(0); if(pad&PAD_UP) { - if(++mvol>CSoundMediator::MAX_VOLUME)mvol=CSoundMediator::MAX_VOLUME; - setVolumes=true; + mvol+=16; + if(mvol>CSoundMediator::MAX_VOLUME)mvol=CSoundMediator::MAX_VOLUME; + setSongVolume=true; } if(pad&PAD_DOWN) { - if(--mvolCSoundMediator::MAX_VOLUME)svol=CSoundMediator::MAX_VOLUME; - setVolumes=true; + svol+=16; + if(svol>CSoundMediator::MAX_VOLUME)svol=CSoundMediator::MAX_VOLUME; + setSfxVolume=true; } if(pad&PAD_LEFT) { - if(--svolthink(); // Push through any changes in volume - if(s_volumeDirty[SONG]||s_volumeDirty[SONGFADE]) + if(s_volumeDirty[SONG]) { - 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; + s_xmplaySound->setMasterSongVolume(s_currentVolume[SONG]); + s_volumeDirty[SONG]=false; } if(s_volumeDirty[SFX]) { + s_xmplaySound->setMasterSfxVolume(s_currentVolume[SFX]); s_volumeDirty[SFX]=false; } // if(s_volumeDirty[SPEECH]) @@ -283,8 +280,8 @@ void CSoundMediator::playSong() ASSERT(s_songModId!=NO_SONG); ASSERT(s_songPlayingId==NOT_PLAYING); - s_songPlayingId=s_xmplaySound->playSong(s_songSampleId,s_songModId,s_songChannelCount); - s_volumeDirty[SONG]=true; // Force a volume update + s_songPlayingId=s_xmplaySound->playSong(s_songSampleId,s_songModId); +// s_volumeDirty[SONG]=true; // Force a volume update } @@ -335,10 +332,12 @@ void CSoundMediator::setSfxBank(SFXBANKID _bankId) /*---------------------------------------------------------------------- Function: Purpose: - Params: + Params: Pass _lock as true if you wanna keep hold of one-shot sfx. + This'll be necessary if you have a *long* one-shot at the + same time as *lots* of other sfx. Returns: ---------------------------------------------------------------------- */ -xmPlayingId CSoundMediator::playSfx(int _sfxId) +xmPlayingId CSoundMediator::playSfx(int _sfxId,int _lock=false) { int sfxChannelMask; xmPlayingId playId; @@ -356,18 +355,44 @@ xmPlayingId CSoundMediator::playSfx(int _sfxId) else { playId=s_xmplaySound->playSfx(s_sfxSampleId,s_sfxModId,sfx->m_pattern,sfx->m_channelMask,20); - if(playId!=NOT_PLAYING) + if(!_lock&&playId!=NOT_PLAYING) { s_xmplaySound->unlockPlayingId(playId); // We really don't care about one-shot sfx.. playId=NOT_PLAYING; } } - s_volumeDirty[SFX]=true; // Force a volume update +// s_volumeDirty[SFX]=true; // Force a volume update return playId; } +/*---------------------------------------------------------------------- + Function: + Purpose: Calculate volume and panning for a sound base upon its + position in space. Takes a position in space which describes + the sound position relative to the camera/microphone. + Volume comes from distance from origin and panning comes from + the position along the x axis. + Params: + Returns: + ---------------------------------------------------------------------- */ +void CSoundMediator::setposition(xmPlayingId _playingId,VECTOR *pos) +{ + int volume,pan; + + volume=CXMPlaySound::MAX_VOLUME-(CalcLengthV(pos)); + if(volumevx/2)+CXMPlaySound::PAN_CENTRE; + if(panCXMPlaySound::PAN_RIGHT)pan=CXMPlaySound::PAN_RIGHT; + + s_xmplaySound->setVolume(_playingId,volume); + s_xmplaySound->setPanning(_playingId,pan); +} + + /*---------------------------------------------------------------------- Function: Purpose: @@ -423,5 +448,17 @@ int CSoundMediator::getVolume(VOLUMETYPE _type) } +/*---------------------------------------------------------------------- + Function: + Purpose: + Params: + Returns: + ---------------------------------------------------------------------- */ +void CSoundMediator::stopAllSound() +{ + s_xmplaySound->stopAndUnlockAllSound(); +} + + /*=========================================================================== end */ \ No newline at end of file diff --git a/source/sound/sound.h b/source/sound/sound.h index 9205becca..e432e0baa 100644 --- a/source/sound/sound.h +++ b/source/sound/sound.h @@ -66,8 +66,6 @@ public: SFX, SPEECH, - SONGFADE, - NUM_VOLUMETYPES, }; @@ -98,13 +96,11 @@ public: static void setSong(SONGID _songId); static void playSong(); static void dumpSong(); - static void setSongToFadedOut() {setVolume(SONGFADE,0);} - static void setSongToFadedIn() {setVolume(SONGFADE,255);} // SFX interface static void setSfxBank(SFXBANKID _bankId); - static xmPlayingId playSfx(int _sfxId); -// static void setposition(int _playId,vector pos ); + static xmPlayingId playSfx(int _sfxId,int _lock=false); + static void setposition(xmPlayingId _playingId,VECTOR *pos); static void stopSfx(xmPlayingId _playingId); // Speech interface @@ -113,7 +109,7 @@ public: // Control static void setVolume(VOLUMETYPE _type,int _val); static int getVolume(VOLUMETYPE _type); -// static void stopAllSound(); + static void stopAllSound(); private: diff --git a/source/sound/xmplay.cpp b/source/sound/xmplay.cpp index 03bf4d10e..62fc55a58 100644 --- a/source/sound/xmplay.cpp +++ b/source/sound/xmplay.cpp @@ -89,12 +89,12 @@ void CXMPlaySound::initialise() // Clear internal data for(i=0;im_refCount=0; } for(i=0;im_refCount=0; } @@ -104,6 +104,8 @@ void CXMPlaySound::initialise() m_spuChannelUse[i].m_locked=false; } + m_masterSongVolume=0; + m_masterSfxVolume=0; SOUND_DBGMSG("XMPlay sound initialised"); } @@ -147,7 +149,7 @@ void CXMPlaySound::think() { if(XM_GetFeedback(ch->m_internalId,&fb)) { -PAUL_DBGMSG("%d finished.. ( was on chnl %d )",id,i); + //PAUL_DBGMSG("%d finished.. ( was on chnl %d )",id,i); while(ch->m_playingId==id&&im_useType=SILENT; @@ -163,6 +165,72 @@ PAUL_DBGMSG("%d finished.. ( was on chnl %d )",id,i); } +/*---------------------------------------------------------------------- + Function: + Purpose: + Params: + Returns: +---------------------------------------------------------------------- */ +void CXMPlaySound::setMasterSongVolume(unsigned char _vol) +{ + int i; + spuChannelUse *ch; + xmPlayingId lastId; + + // New volume + if(m_masterSongVolume==_vol) return; + m_masterSongVolume=_vol; + + // Now update any active songs + ch=m_spuChannelUse; + lastId=NOT_PLAYING; + for(i=0;im_playingId!=lastId&&ch->m_useType==SONG) + { + int oldLock=ch->m_locked; // hmm.. + ch->m_locked=true; // not too.. + setVolume(ch->m_playingId,ch->m_vol); + ch->m_locked=oldLock; // ..ugly I suppose + lastId=ch->m_playingId; + } + } +} + + +/*---------------------------------------------------------------------- + Function: + Purpose: + Params: + Returns: +---------------------------------------------------------------------- */ +void CXMPlaySound::setMasterSfxVolume(unsigned char _vol) +{ + int i; + spuChannelUse *ch; + xmPlayingId lastId; + + // New volume + if(m_masterSfxVolume==_vol) return; + m_masterSfxVolume=_vol; + + // Now update any active sfx + ch=m_spuChannelUse; + lastId=NOT_PLAYING; + for(i=0;im_playingId!=lastId&&ch->m_useType==SFX||ch->m_useType==LOOPINGSFX) + { + int oldLock=ch->m_locked; // hmm.. + ch->m_locked=true; // not too.. + setVolume(ch->m_playingId,ch->m_vol); + ch->m_locked=oldLock; // ..ugly I suppose + lastId=ch->m_playingId; + } + } +} + + /*---------------------------------------------------------------------- Function: Purpose: @@ -177,7 +245,7 @@ xmSampleId CXMPlaySound::loadSampleData(FileEquate _vhFe,FileEquate _vbFe) // Is the bank already loaded? - vab=s_xmVabs; + vab=m_xmVabs; for(vabId=0;vabIdm_refCount&&vab->m_vhFile==_vhFe&&vab->m_vbFile==_vbFe) @@ -190,7 +258,7 @@ xmSampleId CXMPlaySound::loadSampleData(FileEquate _vhFe,FileEquate _vbFe) // Find next free vab slot vabId=0; - vab=s_xmVabs; + vab=m_xmVabs; while(1) { ASSERT(vabIdm_refCount&&mod->m_file==_modFe) @@ -237,7 +305,7 @@ xmModId CXMPlaySound::loadModData(FileEquate _modFe) } // Find next free song slot - mod=s_xmMods; + mod=m_xmMods; modId=0; while(1) { @@ -245,7 +313,7 @@ xmModId CXMPlaySound::loadModData(FileEquate _modFe) if(mod->m_refCount==0) { mod->m_xmData=(u8*)CFileIO::loadFile(_modFe); - InitXMData(mod->m_xmData,modId,XM_UseS3MPanning); + InitXMData(mod->m_xmData,modId,0);//XM_UseS3MPanning); mod->m_file=_modFe; mod->m_refCount=1; break; @@ -267,7 +335,7 @@ void CXMPlaySound::dumpSampleData(xmSampleId _sampleId) { XMVab *vab; - vab=&s_xmVabs[_sampleId]; + vab=&m_xmVabs[_sampleId]; vab->m_refCount--; if(vab->m_refCount==0) { @@ -286,7 +354,7 @@ void CXMPlaySound::dumpModData(xmModId _modId) { XMMod *mod; - mod=&s_xmMods[_modId]; + mod=&m_xmMods[_modId]; mod->m_refCount--; if(mod->m_refCount==0) { @@ -318,7 +386,40 @@ void CXMPlaySound::setStereo(int _stereo) ---------------------------------------------------------------------- */ void CXMPlaySound::setVolume(xmPlayingId _playingId,unsigned char _volume) { - XM_SetMasterVol(_playingId,_volume>>1); + int i; + spuChannelUse *ch; + int vol; + + ch=m_spuChannelUse; + for(i=0;im_playingId==_playingId) + { + ASSERT(ch->m_locked!=false); // Cant alter unlocked channels! + ch->m_vol=_volume; // Update volume + switch(ch->m_useType) + { + case SILENT: + break; + + case SONG: + vol=(_volume*m_masterSongVolume)>>8; + XM_SetMasterVol(ch->m_internalId,vol>>1); + break; + + case SFX: + vol=(_volume*m_masterSfxVolume)>>8; + XM_SetMasterVol(ch->m_internalId,vol>>1); + break; + + case LOOPINGSFX: + updateLoopingSfx(ch); + break; + } + return; + } + } + ASSERT(0); // Couldn't find the sound to unlock it! } @@ -330,7 +431,66 @@ void CXMPlaySound::setVolume(xmPlayingId _playingId,unsigned char _volume) ---------------------------------------------------------------------- */ void CXMPlaySound::setPanning(xmPlayingId _playingId,char _pan) { - XM_SetMasterPan(_playingId,_pan); + int i; + spuChannelUse *ch; + + ch=m_spuChannelUse; + for(i=0;im_playingId==_playingId) + { + ASSERT(ch->m_locked!=false); // Cant alter unlocked channels! + ch->m_pan=_pan; // Update pan + switch(ch->m_useType) + { + case SILENT: + break; + + case SONG: + XM_SetMasterPan(ch->m_internalId,_pan-128); + break; + + case SFX: + XM_SetMasterPan(ch->m_internalId,_pan-128); + break; + + case LOOPINGSFX: + updateLoopingSfx(ch); + break; + } + return; + } + } + ASSERT(0); // Couldn't find the sound to unlock it! +} + + + +/*---------------------------------------------------------------------- + Function: + Purpose: + Params: + Returns: + ---------------------------------------------------------------------- */ +void CXMPlaySound::stopAndUnlockAllSound() +{ + int i; + spuChannelUse *ch; + + ch=m_spuChannelUse; + for(i=0;im_useType!=SILENT) + { + int oldLock=ch->m_locked; // hmm.. + ch->m_locked=true; // not too.. + stopPlayingId(ch->m_playingId); + ch->m_locked=oldLock; // ..ugly I suppose + + // Need to unlock too + if(oldLock)unlockPlayingId(ch->m_playingId); + } + } } @@ -340,31 +500,36 @@ void CXMPlaySound::setPanning(xmPlayingId _playingId,char _pan) Params: Returns: ---------------------------------------------------------------------- */ -xmPlayingId CXMPlaySound::playSong(xmSampleId _sampleId,xmModId _songId,int _channelCount) +xmPlayingId CXMPlaySound::playSong(xmSampleId _sampleId,xmModId _modId) { - int baseChannel; + int channelCount,baseChannel; XMVab *vab; int id; xmPlayingId retId; - ASSERT(s_xmVabs[_sampleId].m_refCount!=0); - ASSERT(s_xmMods[_songId].m_refCount!=0); + ASSERT(m_xmVabs[_sampleId].m_refCount!=0); + ASSERT(m_xmMods[_modId].m_refCount!=0); - baseChannel=findSpareChannels(_channelCount,255); + // Let's grab the channel count from the XM data.. :) + channelCount=(short int)*(m_xmMods[_modId].m_xmData+68); + SOUND_DBGMSG("Playing song with %d channels reserved",channelCount); + + baseChannel=findSpareChannels(channelCount,255); if(baseChannel!=-1) { retId=getNextSparePlayingId(); - vab=&s_xmVabs[_sampleId]; - id=XM_Init(vab->m_vabId, // id from XM_VABInit - _songId, // XM id ( as passed to InitXMData ) - -1,//baseChannel,//0, // Song id - baseChannel, // First channel - XM_Loop, // Loop - -1, // Play mask - XM_Music, // Music - 0); // Pattern to start at - markChannelsAsActive(baseChannel,_channelCount,SONG,retId,id,255); -PAUL_DBGMSG("playSong %d/%d ( on %d-%d )",retId,id,baseChannel,baseChannel+_channelCount-1); + vab=&m_xmVabs[_sampleId]; + id=XM_Init(vab->m_vabId, // id from XM_VABInit + _modId, // XM id ( as passed to InitXMData ) + -1, // Let xmplay give us a song id + baseChannel, // First channel + XM_Loop, // Play song continuously + -1, // Play all channels + XM_Music, // Music + 0); // Begin at the beginning + markChannelsAsActive(baseChannel,channelCount,SONG,retId,id,255); + setVolume(retId,MAX_VOLUME); + //PAUL_DBGMSG("playSong %d/%d ( on %d-%d )",retId,id,baseChannel,baseChannel+channelCount-1); } else { @@ -391,7 +556,7 @@ void CXMPlaySound::unlockPlayingId(xmPlayingId _playingId) { if(ch->m_playingId==_playingId) { -PAUL_DBGMSG("unlocking %d",_playingId); + //PAUL_DBGMSG("unlocking %d",_playingId); ASSERT(ch->m_locked!=false); while(ch->m_playingId==_playingId) { @@ -421,24 +586,21 @@ void CXMPlaySound::stopPlayingId(xmPlayingId _playingId) { if(ch->m_playingId==_playingId) { + ASSERT(ch->m_locked!=false); // Cant stop unlocked channels! switch(ch->m_useType) { case SILENT: - PAUL_DBGMSG("stopping.. woah! %d is already stopped",_playingId); break; case SONG: - PAUL_DBGMSG("stopping song on %d",_playingId); XM_PlayStop(ch->m_internalId); break; case SFX: - PAUL_DBGMSG("stopping sfx on %d",_playingId); XM_PlayStop(ch->m_internalId); break; case LOOPINGSFX: - PAUL_DBGMSG("stopping loopingsfx on %d",_playingId); XM_StopSample(ch->m_internalId); break; } @@ -461,7 +623,7 @@ void CXMPlaySound::stopPlayingId(xmPlayingId _playingId) Params: Returns: ---------------------------------------------------------------------- */ -xmPlayingId CXMPlaySound::playSfx(xmSampleId _sampleId,xmModId _songId,int _sfxPattern,int _playMask,u8 _priority) +xmPlayingId CXMPlaySound::playSfx(xmSampleId _sampleId,xmModId _modId,int _sfxPattern,int _playMask,u8 _priority) { int i,j; int maskCopy,channelCount; @@ -472,8 +634,8 @@ xmPlayingId CXMPlaySound::playSfx(xmSampleId _sampleId,xmModId _songId,int _sfxP int id; xmPlayingId retId; - ASSERT(s_xmVabs[_sampleId].m_refCount!=0); - ASSERT(s_xmMods[_songId].m_refCount!=0); + ASSERT(m_xmVabs[_sampleId].m_refCount!=0); + ASSERT(m_xmMods[_modId].m_refCount!=0); // Count channels maskCopy=_playMask; @@ -490,19 +652,20 @@ xmPlayingId CXMPlaySound::playSfx(xmSampleId _sampleId,xmModId _songId,int _sfxP if(baseChannel!=-1) { retId=getNextSparePlayingId(); - vab=&s_xmVabs[_sampleId]; + vab=&m_xmVabs[_sampleId]; XM_SetSFXRange(baseChannel,channelCount); - id=XM_Init(vab->m_vabId, // id from XM_VABInit - _songId, // XM id ( as passed to InitXMData ) - -1,//baseChannel,//SONGNUM, // Song id - -1, // First channel - XM_NoLoop, // Loop - _playMask, // Play mask - XM_SFX, // Music - _sfxPattern); // Pattern to start at + id=XM_Init(vab->m_vabId, // id from XM_VABInit + _modId, // XM id ( as passed to InitXMData ) + -1, // Let xmplay give us a song id + -1, // Use SFX range to get first channel + XM_NoLoop, // One-shot + _playMask, // Play mask + XM_SFX, // SFX + _sfxPattern); // SFX pattern to play XM_ClearSFXRange(); -PAUL_DBGMSG("playSfx %d/%d ( on %d-%d )",retId,id,baseChannel,baseChannel+channelCount-1); + //PAUL_DBGMSG("playSfx %d/%d ( on %d-%d )",retId,id,baseChannel,baseChannel+channelCount-1); markChannelsAsActive(baseChannel,channelCount,SFX,retId,id,_priority); + setVolume(retId,MAX_VOLUME); } else { @@ -519,7 +682,7 @@ PAUL_DBGMSG("playSfx %d/%d ( on %d-%d )",retId,id,baseChannel,baseChanne Params: Returns: ---------------------------------------------------------------------- */ -xmPlayingId CXMPlaySound::playLoopingSfx(xmSampleId _sampleId,xmModId _songId,int _soundId,u8 _priority,int _pitch) +xmPlayingId CXMPlaySound::playLoopingSfx(xmSampleId _sampleId,xmModId _modId,int _soundId,u8 _priority,int _pitch) { int baseChannel; xmPlayingId retId; @@ -528,9 +691,10 @@ xmPlayingId CXMPlaySound::playLoopingSfx(xmSampleId _sampleId,xmModId _songId,in if(baseChannel!=-1) { retId=getNextSparePlayingId(); -PAUL_DBGMSG("playLoopingSfx %d/- ( on %d-%d )",retId,baseChannel,baseChannel); + //PAUL_DBGMSG("playLoopingSfx %d/- ( on %d-%d )",retId,baseChannel,baseChannel); XM_PlaySample(XM_GetSampleAddress(_sampleId,_soundId),baseChannel,0x3fff,0x3fff,_pitch); markChannelsAsActive(baseChannel,1,LOOPINGSFX,retId,baseChannel,_priority); + setVolume(retId,MAX_VOLUME); } else { @@ -624,6 +788,8 @@ void CXMPlaySound::markChannelsAsActive(int _baseChannel,int _channelCount,CHANN details.m_playingId=_playingId; details.m_priority=_priority; details.m_locked=true; + details.m_vol=MAX_VOLUME; + details.m_pan=PAN_CENTRE; ch=&m_spuChannelUse[_baseChannel]; for(i=_baseChannel;i<_baseChannel+_channelCount;i++,ch++) @@ -649,7 +815,7 @@ void CXMPlaySound::defragSpuMemory() SOUND_DBGMSG("CXMPlaySound is defragging.."); // Dump banks - vab=s_xmVabs; + vab=m_xmVabs; for(vabId=0;vabIdm_refCount) @@ -659,7 +825,7 @@ void CXMPlaySound::defragSpuMemory() } // Now reload them - vab=s_xmVabs; + vab=m_xmVabs; for(vabId=0;vabIdm_refCount) @@ -676,5 +842,34 @@ void CXMPlaySound::defragSpuMemory() } +/*---------------------------------------------------------------------- + Function: + Purpose: + Params: + Returns: + ---------------------------------------------------------------------- */ +void CXMPlaySound::updateLoopingSfx(spuChannelUse *ch) +{ + int actualVol,actualPan; + int leftVol,rightVol; + SpuVoiceAttr attr; + + actualVol=(ch->m_vol*m_masterSfxVolume)>>8; // 0=silent, 255=full vol + actualPan=ch->m_pan; // 0=hard left, 255=hard right + + leftVol=(actualVol*actualPan)>>2; + rightVol=(actualVol*(255-actualPan))>>2; + ASSERT(leftVol<=0x3fff); ASSERT(leftVol>=0); + ASSERT(rightVol<=0x3fff); ASSERT(rightVol>=0); + + attr.voice=(1<m_internalId); + attr.mask=(SPU_VOICE_VOLL|SPU_VOICE_VOLR); + attr.volume.left=leftVol; + attr.volume.right=rightVol; + + SpuSetVoiceAttr(&attr); +} + + /*=========================================================================== end */ \ No newline at end of file diff --git a/source/sound/xmplay.h b/source/sound/xmplay.h index ed74b7fe6..5b40f64c0 100644 --- a/source/sound/xmplay.h +++ b/source/sound/xmplay.h @@ -44,10 +44,23 @@ typedef enum {NOT_PLAYING=-1} xmPlayingId; class CXMPlaySound { public: + enum + { + MIN_VOLUME=0, + MAX_VOLUME=255, + PAN_LEFT=0, + PAN_CENTRE=127, + PAN_RIGHT=255, + }; + + void initialise(); void shutdown(); void think(); + void setMasterSongVolume(unsigned char _vol); + void setMasterSfxVolume(unsigned char _vol); + xmSampleId loadSampleData(FileEquate _vhFe,FileEquate _vbFe); xmModId loadModData(FileEquate _modFe); void dumpSampleData(xmSampleId _sampleId); @@ -58,9 +71,11 @@ public: void setVolume(xmPlayingId _playingId,unsigned char _volume); void setPanning(xmPlayingId _playingId,char _pan); - xmPlayingId playSong(xmSampleId _sampleId,xmModId _songId,int _channelCount); - xmPlayingId playSfx(xmSampleId _sampleId,xmModId _songId,int _sfxPattern,int _playMask,u8 _priority); - xmPlayingId playLoopingSfx(xmSampleId _sampleId,xmModId _songId,int _soundId,u8 _priority,int _pitch=0x400); + void stopAndUnlockAllSound(); + + xmPlayingId playSong(xmSampleId _sampleId,xmModId _modId); + xmPlayingId playSfx(xmSampleId _sampleId,xmModId _modId,int _sfxPattern,int _playMask,u8 _priority); + xmPlayingId playLoopingSfx(xmSampleId _sampleId,xmModId _modId,int _soundId,u8 _priority,int _pitch=0x400); void unlockPlayingId(xmPlayingId _playingId); void stopPlayingId(xmPlayingId _playingId); @@ -86,7 +101,7 @@ private: LOOPINGSFX, } CHANNELUSETYPE; - // Internal representation of loaded songs + // Internal representation of loaded mods typedef struct XMMod { unsigned char *m_xmData; @@ -111,6 +126,7 @@ private: u8 m_internalId; u8 m_priority; u8 m_locked; + u8 m_vol,m_pan; } spuChannelUse; xmPlayingId getNextSparePlayingId(); @@ -119,11 +135,17 @@ private: void defragSpuMemory(); + void updateLoopingSfx(spuChannelUse *ch); + + unsigned char *m_fhPtr[MAX_XM_HEADERS]; unsigned char *m_songPtr[MAX_SONG_HEADERS]; - XMMod s_xmMods[MAX_XM_SONGS]; - XMVab s_xmVabs[MAX_XM_VABS]; + XMMod m_xmMods[MAX_XM_SONGS]; + XMVab m_xmVabs[MAX_XM_VABS]; spuChannelUse m_spuChannelUse[NUM_SPU_CHANNELS]; + + unsigned char m_masterSongVolume; + unsigned char m_masterSfxVolume; };