SBSPSS/source/sound/sound.cpp

497 lines
12 KiB
C++
Raw Normal View History

2000-10-10 01:30:58 +02:00
/*
position
adjust channels ( watery-mario64 style music changes )
*/
2000-10-05 16:16:09 +02:00
/*=========================================================================
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
2000-10-11 18:47:03 +02:00
#ifndef __UTILS_HEADER__
#include "utils\utils.h"
#endif
2000-10-10 01:30:58 +02:00
2000-10-05 16:16:09 +02:00
/* Std Lib
------- */
/* Data
---- */
/*----------------------------------------------------------------------
Tyepdefs && Defines
------------------- */
/*----------------------------------------------------------------------
Structure defintions
-------------------- */
2001-01-19 17:25:05 +01:00
typedef struct XMSONGDATA
2000-10-05 16:16:09 +02:00
{
FileEquate m_vh,m_vb,m_pxm;
2001-01-19 17:25:05 +01:00
int m_startPattern;
2000-10-05 16:16:09 +02:00
};
2001-01-19 17:25:05 +01:00
typedef struct XMSFXFILEDATA
{
FileEquate m_vh,m_vb,m_pxm;
};
2000-10-06 00:40:39 +02:00
typedef struct SFXDETAILS
{
2000-10-10 00:06:20 +02:00
int m_channelMask;
2000-10-10 01:30:58 +02:00
int m_pattern; // ..or instrument number for loopers
2000-10-06 00:40:39 +02:00
int m_looping;
};
2000-10-05 16:16:09 +02:00
/*----------------------------------------------------------------------
Function Prototypes
------------------- */
/*----------------------------------------------------------------------
Vars
---- */
2000-10-10 01:30:58 +02:00
// Static stuff for CSoundMediator
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];
xmSampleId CSoundMediator::s_songSampleId=NO_SAMPLE;
xmModId CSoundMediator::s_songModId=NO_SONG;
xmPlayingId CSoundMediator::s_songPlayingId=NOT_PLAYING;
2001-01-19 17:25:05 +01:00
int CSoundMediator::s_songStartPattern=0;
2000-10-10 01:30:58 +02:00
xmSampleId CSoundMediator::s_sfxSampleId=NO_SAMPLE;
xmModId CSoundMediator::s_sfxModId=NO_SONG;
static CSpuSound *s_spuSound;
static CXMPlaySound *s_xmplaySound;
// Songs
2001-01-19 17:25:05 +01:00
static XMSONGDATA s_xmSongData[CSoundMediator::NUM_SONGIDS]=
2000-10-05 16:16:09 +02:00
{
2001-01-19 17:25:05 +01:00
{ MUSIC_INGAME_VH, MUSIC_INGAME_VB, MUSIC_INGAME_PXM, 0 }, // SONG_INGAME
{ MUSIC_SB_TITLE_VH, MUSIC_SB_TITLE_VB, MUSIC_SB_TITLE_PXM, 0 }, // SONG_TITLE
{ MUSIC_SB_TITLE_VH, MUSIC_SB_TITLE_VB, MUSIC_SB_TITLE_PXM, 0xa }, // SONG_OPTIONS
{ MUSIC_SB_TITLE_VH, MUSIC_SB_TITLE_VB, MUSIC_SB_TITLE_PXM, 0x13 }, // SONG_MEMORYCARD
{ MUSIC_SB_TITLE_VH, MUSIC_SB_TITLE_VB, MUSIC_SB_TITLE_PXM, 0x14 }, // SONG_GAMECOMPLETE
{ MUSIC_SB_TITLE_VH, MUSIC_SB_TITLE_VB, MUSIC_SB_TITLE_PXM, 0x23 }, // SONG_GAMEOVER
2000-10-05 16:16:09 +02:00
};
2000-10-10 01:30:58 +02:00
// SFX banks
2001-01-19 17:25:05 +01:00
static XMSFXFILEDATA s_xmSfxData[CSoundMediator::NUM_SFXBANKIDS]=
2000-10-05 16:16:09 +02:00
{
2001-01-03 21:43:49 +01:00
{ SFX_INGAME_VH, SFX_INGAME_VB, SFX_INGAME_PXM }, // SFX_INGAME
2000-10-05 16:16:09 +02:00
};
2000-10-10 01:30:58 +02:00
// Individual SFX details
2000-10-06 00:40:39 +02:00
static SFXDETAILS s_sfxDetails[]=
{
2000-10-10 00:06:20 +02:00
{ 1, 6, 1 },
2000-10-10 18:49:01 +02:00
{ 1, 4, 0 },
{ 1, 5, 0 },
2000-10-10 00:06:20 +02:00
{ 1, 0, 1 },
2000-10-06 00:40:39 +02:00
};
2000-10-10 18:49:01 +02:00
// Reverb details
static ReverbDetails s_reverbDetails[CSoundMediator::NUM_REVERBTYPES]=
{
2001-01-03 21:43:49 +01:00
{ SPU_REV_MODE_OFF, 0, 0, 0 }, // REV_NONE
{ SPU_REV_MODE_ECHO, 75, 0x3000, 100 }, // REV_ECHOTEST
2000-10-10 18:49:01 +02:00
};
2000-10-06 00:40:39 +02:00
2000-10-05 16:16:09 +02:00
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
void CSoundMediator::initialise()
{
int i;
ASSERT(!s_initialised);
s_spuSound=new ("SPUSound") CSpuSound(); s_spuSound->initialise();
2000-10-10 00:06:20 +02:00
s_xmplaySound=new ("XMPlaySound") CXMPlaySound(); s_xmplaySound->initialise();
2000-10-05 16:16:09 +02:00
CXAStream::Init();
for(i=0;i<NUM_VOLUMETYPES;i++)
{
s_currentVolume[i]=MIN_VOLUME;
s_targetVolume[i]=INITIAL_VOLUME;
s_volumeDirty[i]=true;
}
2000-10-12 17:18:47 +02:00
ASSERT(CXAStream::MIN_VOLUME==0); // Just incase someone decides to change any of these.. things in here will break ( PKG )
ASSERT(CXAStream::MAX_VOLUME==32767);
2000-10-05 16:16:09 +02:00
2000-10-10 18:49:01 +02:00
// Initial reverb settings
2001-01-03 21:43:49 +01:00
setReverbType(REV_NONE);//REV_ECHOTEST);
2000-10-05 16:16:09 +02:00
SOUND_DBGMSG("Sound mediator initialised");
s_initialised=true;
}
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
void CSoundMediator::shutdown()
{
ASSERT(0);
ASSERT(s_initialised);
s_xmplaySound->shutdown(); delete s_xmplaySound;
s_spuSound->shutdown(); delete s_spuSound;
SOUND_DBGMSG("Sound mediator shutdown");
s_initialised=false;
}
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
void CSoundMediator::think(int _frames)
{
int i;
int diff,speed;
int *current,*target,*dirty;
ASSERT(s_initialised);
// Fade to target volume
2000-12-11 16:35:55 +01:00
ASSERT(_frames!=0);
if(_frames==0)_frames=1;
speed=_frames*VOLUME_CHANGE_SPEED;
2000-10-05 16:16:09 +02:00
current=s_currentVolume;
target=s_targetVolume;
dirty=s_volumeDirty;
for(i=0;i<NUM_VOLUMETYPES;i++)
{
diff=*target-*current;
if(diff<0)
{
*current-=speed;
if(*current<*target)*current=*target;
*dirty=true;
}
else if(diff>0)
{
*current+=speed;
if(*current>*target)*current=*target;
*dirty=true;
}
current++;
target++;
dirty++;
}
2000-10-11 18:47:03 +02:00
// Update of anything that needs it
2000-10-12 17:18:47 +02:00
CXAStream::ControlXA();
2000-10-10 00:06:20 +02:00
s_xmplaySound->think();
2000-10-05 16:16:09 +02:00
// Push through any changes in volume
2001-01-03 21:43:49 +01:00
if(s_volumeDirty[VOL_FADE])
2000-10-05 16:16:09 +02:00
{
2001-01-03 21:43:49 +01:00
s_volumeDirty[VOL_SONG]=true;
s_volumeDirty[VOL_SFX]=true;
s_volumeDirty[VOL_SPEECH]=true;
2001-01-04 18:10:13 +01:00
s_volumeDirty[VOL_FADE]=false;
2000-10-05 16:16:09 +02:00
}
2001-01-03 21:43:49 +01:00
if(s_volumeDirty[VOL_SONG])
2000-10-05 16:16:09 +02:00
{
2001-01-03 21:43:49 +01:00
s_xmplaySound->setMasterSongVolume((s_currentVolume[VOL_SONG]*s_currentVolume[VOL_FADE])>>8);
s_volumeDirty[VOL_SONG]=false;
2000-10-05 16:16:09 +02:00
}
2001-01-03 21:43:49 +01:00
if(s_volumeDirty[VOL_SFX])
2000-10-12 17:18:47 +02:00
{
2001-01-03 21:43:49 +01:00
s_xmplaySound->setMasterSfxVolume((s_currentVolume[VOL_SFX]*s_currentVolume[VOL_FADE])>>8);
s_volumeDirty[VOL_SFX]=false;
}
if(s_volumeDirty[VOL_SPEECH])
{
int vol=((s_currentVolume[VOL_SPEECH]*s_currentVolume[VOL_FADE])>>8)<<7;
2000-10-12 17:18:47 +02:00
CXAStream::setMasterVolume(vol,vol);
2001-01-03 21:43:49 +01:00
s_volumeDirty[VOL_SPEECH]=false;
2000-10-12 17:18:47 +02:00
}
2000-10-05 16:16:09 +02:00
}
2000-10-10 18:49:01 +02:00
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
void CSoundMediator::setReverbType(REVERBTYPE _type)
{
s_spuSound->setReverbDetails(&s_reverbDetails[_type]);
s_spuSound->setReverbActive(true);
}
2000-10-05 16:16:09 +02:00
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
void CSoundMediator::setSong(SONGID _songId)
{
2001-01-19 17:25:05 +01:00
XMSONGDATA *song;
2000-10-05 16:16:09 +02:00
ASSERT(s_songSampleId==NO_SAMPLE);
2000-10-10 00:06:20 +02:00
ASSERT(s_songModId==NO_SONG);
2000-10-05 16:16:09 +02:00
song=&s_xmSongData[_songId];
2000-10-10 00:06:20 +02:00
s_songModId=s_xmplaySound->loadModData(song->m_pxm);
s_songSampleId=s_xmplaySound->loadSampleData(song->m_vh,song->m_vb);
2001-01-19 17:25:05 +01:00
s_songStartPattern=song->m_startPattern;
2000-10-05 16:16:09 +02:00
}
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
void CSoundMediator::playSong()
{
ASSERT(s_songSampleId!=NO_SAMPLE);
2000-10-10 00:06:20 +02:00
ASSERT(s_songModId!=NO_SONG);
2000-10-05 16:16:09 +02:00
ASSERT(s_songPlayingId==NOT_PLAYING);
2001-01-19 17:25:05 +01:00
s_songPlayingId=s_xmplaySound->playSong(s_songSampleId,s_songModId,s_songStartPattern);
2000-10-11 18:47:03 +02:00
// s_volumeDirty[SONG]=true; // Force a volume update
2000-10-05 16:16:09 +02:00
}
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
void CSoundMediator::dumpSong()
{
ASSERT(s_songSampleId!=NO_SAMPLE);
2000-10-10 00:06:20 +02:00
ASSERT(s_songModId!=NO_SONG);
2000-10-05 16:16:09 +02:00
2000-10-10 00:06:20 +02:00
if(s_songPlayingId!=NOT_PLAYING)
{
s_xmplaySound->stopPlayingId(s_songPlayingId);
s_xmplaySound->unlockPlayingId(s_songPlayingId);
}
s_xmplaySound->dumpSampleData(s_songSampleId);
s_xmplaySound->dumpModData(s_songModId);
2000-10-05 16:16:09 +02:00
s_songSampleId=NO_SAMPLE;
2000-10-10 00:06:20 +02:00
s_songModId=NO_SONG;
2000-10-05 16:16:09 +02:00
s_songPlayingId=NOT_PLAYING;
}
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
void CSoundMediator::setSfxBank(SFXBANKID _bankId)
{
2001-01-19 17:25:05 +01:00
XMSFXFILEDATA *sfx;
2000-10-05 16:16:09 +02:00
ASSERT(s_sfxSampleId==NO_SAMPLE);
2000-10-10 00:06:20 +02:00
ASSERT(s_sfxModId==NO_SONG);
2000-10-05 16:16:09 +02:00
2001-01-19 17:25:05 +01:00
sfx=&s_xmSfxData[_bankId];
s_sfxModId=s_xmplaySound->loadModData(sfx->m_pxm);
s_sfxSampleId=s_xmplaySound->loadSampleData(sfx->m_vh,sfx->m_vb);
2000-10-05 16:16:09 +02:00
}
/*----------------------------------------------------------------------
Function:
Purpose:
2000-10-11 18:47:03 +02:00
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.
2000-10-05 16:16:09 +02:00
Returns:
---------------------------------------------------------------------- */
2000-10-11 18:47:03 +02:00
xmPlayingId CSoundMediator::playSfx(int _sfxId,int _lock=false)
2000-10-05 16:16:09 +02:00
{
2000-10-10 00:06:20 +02:00
int sfxChannelMask;
xmPlayingId playId;
SFXDETAILS *sfx;
2000-10-05 16:16:09 +02:00
2000-10-10 00:06:20 +02:00
ASSERT(s_sfxSampleId!=NO_SAMPLE);
ASSERT(s_sfxModId!=NO_SONG);
2000-10-05 16:16:09 +02:00
2000-10-10 00:06:20 +02:00
// Play!
sfx=&s_sfxDetails[_sfxId];
if(sfx->m_looping)
2000-10-05 16:16:09 +02:00
{
2000-10-10 00:06:20 +02:00
playId=s_xmplaySound->playLoopingSfx(s_sfxSampleId,s_sfxModId,sfx->m_pattern,10);
2000-10-05 16:16:09 +02:00
}
2000-10-10 00:06:20 +02:00
else
2000-10-05 16:16:09 +02:00
{
2000-10-10 00:06:20 +02:00
playId=s_xmplaySound->playSfx(s_sfxSampleId,s_sfxModId,sfx->m_pattern,sfx->m_channelMask,20);
2000-10-11 18:47:03 +02:00
if(!_lock&&playId!=NOT_PLAYING)
2000-10-10 01:30:58 +02:00
{
s_xmplaySound->unlockPlayingId(playId); // We really don't care about one-shot sfx..
playId=NOT_PLAYING;
}
2000-10-05 16:16:09 +02:00
}
2000-10-11 18:47:03 +02:00
// s_volumeDirty[SFX]=true; // Force a volume update
2000-10-05 16:16:09 +02:00
2000-10-10 00:06:20 +02:00
return playId;
}
2000-10-05 16:16:09 +02:00
2000-10-11 18:47:03 +02:00
/*----------------------------------------------------------------------
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(volume<CXMPlaySound::MIN_VOLUME)volume=CXMPlaySound::MIN_VOLUME;
pan=(pos->vx/2)+CXMPlaySound::PAN_CENTRE;
if(pan<CXMPlaySound::PAN_LEFT)pan=CXMPlaySound::PAN_LEFT;
else if(pan>CXMPlaySound::PAN_RIGHT)pan=CXMPlaySound::PAN_RIGHT;
s_xmplaySound->setVolume(_playingId,volume);
s_xmplaySound->setPanning(_playingId,pan);
}
2000-10-10 00:06:20 +02:00
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
2000-10-10 01:30:58 +02:00
void CSoundMediator::stopSfx(xmPlayingId _playingId)
2000-10-10 00:06:20 +02:00
{
2000-10-10 01:30:58 +02:00
s_xmplaySound->stopPlayingId(_playingId);
s_xmplaySound->unlockPlayingId(_playingId);
2000-10-05 16:16:09 +02:00
}
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
void CSoundMediator::playSpeech(SpeechEquate _speech)
{
2000-10-12 17:18:47 +02:00
stopSpeech();
CXAStream::PlaySpeech(_speech);
2000-10-05 16:16:09 +02:00
// s_volumeDirty[SPEECH]=true; // Force a volume update
}
2000-10-12 17:18:47 +02:00
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
void CSoundMediator::stopSpeech()
{
if(CXAStream::IsPlaying())
CXAStream::Stop();
}
2000-10-05 16:16:09 +02:00
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
void CSoundMediator::setVolume(VOLUMETYPE _type,int _val)
{
ASSERT(_val>=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];
}
2000-10-11 18:47:03 +02:00
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
void CSoundMediator::stopAllSound()
{
s_xmplaySound->stopAndUnlockAllSound();
2000-10-12 17:18:47 +02:00
CXAStream::Stop();
2000-10-11 18:47:03 +02:00
}
2000-10-05 16:16:09 +02:00
/*===========================================================================
end */