SBSPSS/source/sound/xmplay.cpp
2000-10-05 14:16:09 +00:00

463 lines
9.5 KiB
C++

unsigned char *xmPtr;
/*=========================================================================
spu.cpp
Author: PKG
Created:
Project: Spongebob
Purpose:
Copyright (c) 2000 Climax Development Ltd
===========================================================================*/
/*----------------------------------------------------------------------
Includes
-------- */
#include "xmplay.h"
#ifndef __SYSTEM_DBG_H__
#include "system\dbg.h"
#endif
#ifndef __VID_HEADER_
#include "system\vid.h"
#endif
#ifndef XMPlayer
#include "system\global.h"
#include <xmplay.h>
#endif
/* Std Lib
------- */
/* Data
---- */
/*----------------------------------------------------------------------
Tyepdefs && Defines
------------------- */
#define XM_SONGID 0
#define MAX_XM_SONGS 5
#define MAX_XM_VABS 5
/*----------------------------------------------------------------------
Structure defintions
-------------------- */
typedef struct XMSong
{
unsigned char *m_xmData;
FileEquate m_file;
int m_refCount;
// refcount these!
};
static XMSong s_xmSongs[MAX_XM_SONGS];
typedef struct XMVab
{
int m_vabId;
FileEquate m_vhFile,m_vbFile;
int m_refCount;
};
static XMVab s_xmVabs[MAX_XM_VABS];
/*----------------------------------------------------------------------
Function Prototypes
------------------- */
/*----------------------------------------------------------------------
Vars
---- */
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
void CXMPlaySound::initialise()
{
int size,i;
#if defined(__TERRITORY_USA__) || defined(__TERRITORY_JAP__)
XM_OnceOffInit(XM_NTSC);
#else
XM_OnceOffInit(XM_PAL);
#endif
setStereo(true);
size=XM_GetSongSize();
for(i=0;i<MAX_SONG_HEADERS;i++)
{
s_songPtr[i]=(u8*)MemAlloc(size,"XMSong");
XM_SetSongAddress(s_songPtr[i]);
}
size=XM_GetFileHeaderSize();
for(i=0;i<MAX_XM_HEADERS;i++)
{
s_fhPtr[i]=(u8*)MemAlloc(size,"XMHeader");
XM_SetFileHeaderAddress(s_fhPtr[i]);
}
VidAddVSyncFunc(XM_Update);
// Clear internal data
for(i=0;i<MAX_XM_SONGS;i++)
{
XMSong *song=&s_xmSongs[i];
song->m_refCount=0;
}
for(i=0;i<MAX_XM_VABS;i++)
{
XMVab *vab=&s_xmVabs[i];
vab->m_refCount=0;
}
SOUND_DBGMSG("XMPlay sound initialised");
}
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
void CXMPlaySound::shutdown()
{
SOUND_DBGMSG("XMPlay sound shutdown");
}
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
xmSampleId CXMPlaySound::loadSamples(FileEquate _vhFe,FileEquate _vbFe)
{
int vabId;
XMVab *vab;
unsigned char *VbPtr,*VhPtr;
// Is the bank already loaded?
vab=s_xmVabs;
for(vabId=0;vabId<MAX_XM_VABS;vabId++)
{
if(vab->m_refCount&&vab->m_vhFile==_vhFe&&vab->m_vbFile==_vbFe)
{
// Yup..
vab->m_refCount++;
return(xmSampleId)vabId;
}
}
// Find next free vab slot
vabId=0;
vab=s_xmVabs;
while(1)
{
ASSERT(vabId<MAX_XM_VABS);
if(vab->m_refCount==0)
{
VhPtr=(u8*)CFileIO::loadFile(_vhFe);
VbPtr=(u8*)CFileIO::loadFile(_vbFe);
vab->m_vabId=XM_VABInit(VhPtr,VbPtr);
//defragSpuMemory(); somewhere around here..
MemFree(VhPtr);
MemFree(VbPtr);
vab->m_vhFile=_vhFe;
vab->m_vbFile=_vbFe;
vab->m_refCount=1;
break;
}
vabId++;vab++;
}
return (xmSampleId)vabId;
}
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
xmSongId CXMPlaySound::loadSongData(FileEquate _songFe)
{
int songId;
XMSong *song;
// Is the song already loaded?
song=s_xmSongs;
for(songId=0;songId<MAX_XM_SONGS;songId++)
{
if(song->m_refCount&&song->m_file==_songFe)
{
// Yup..
song->m_refCount++;
return(xmSongId)songId;
}
}
// Find next free song slot
song=s_xmSongs;
songId=0;
while(1)
{
ASSERT(songId<MAX_XM_SONGS);
if(song->m_refCount==0)
{
song->m_xmData=(u8*)CFileIO::loadFile(_songFe);
InitXMData(song->m_xmData,songId,XM_UseS3MPanning);
song->m_file=_songFe;
song->m_refCount=1;
break;
}
songId++;song++;
}
return (xmSongId)songId;
}
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
void CXMPlaySound::dumpSamples(xmSampleId _sampleId)
{
XMVab *vab;
vab=&s_xmVabs[_sampleId];
vab->m_refCount--;
if(vab->m_refCount==0)
{
XM_CloseVAB(vab->m_vabId);
}
}
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
void CXMPlaySound::dumpSongData(xmSongId _songId)
{
XMSong *song;
song=&s_xmSongs[_songId];
song->m_refCount--;
if(song->m_refCount==0)
{
MemFree(song->m_xmData);
}
}
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
void CXMPlaySound::setStereo(int _stereo)
{
if(_stereo)
XM_SetStereo();
else
XM_SetMono();
}
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
void CXMPlaySound::setVolume(xmPlayingSongId _songId,unsigned char _volume)
{
XM_SetMasterVol(_songId,_volume>>1);
}
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
void CXMPlaySound::setPanning(xmPlayingSongId _songId,char _pan)
{
XM_SetMasterPan(_songId,_pan);
}
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
//int sid=0;
//int chan=0;
xmPlayingSongId CXMPlaySound::playSong(xmSampleId _sampleId,xmSongId _songId,int _baseChannel)
{
XMVab *vab;
int id;
ASSERT(s_xmVabs[_sampleId].m_refCount!=0);
ASSERT(s_xmSongs[_songId].m_refCount!=0);
vab=&s_xmVabs[_sampleId];
id=XM_Init(vab->m_vabId, // id from XM_VABInit
_songId, // XM id ( as passed to InitXMData )
-1, // Song id
_baseChannel, // First channel
XM_Loop, // Loop
-1, // Play mask
XM_Music, // Music
0); // Pattern to start at
return (xmPlayingSongId)id;
}
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
void CXMPlaySound::stopSong(xmPlayingSongId _songId)
{
XM_PlayStop(_songId);
}
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
//int sid=0;
//int chan=0;
int SONGNUM=1;
xmPlayingSongId CXMPlaySound::playSfx(xmSampleId _sampleId,xmSongId _songId,int _baseChannel,int _sfxPattern,int _playMask=-1)
{
int i, maskCopy,channelCount=0;
XMVab *vab;
int id;
ASSERT(s_xmVabs[_sampleId].m_refCount!=0);
ASSERT(s_xmSongs[_songId].m_refCount!=0);
maskCopy=_playMask;
for(i=0;i<24&&maskCopy;i++)
{
if(maskCopy&1)
channelCount++;
maskCopy>>=1;
}
vab=&s_xmVabs[_sampleId];
XM_SetSFXRange(_baseChannel,channelCount);
id=XM_Init(vab->m_vabId, // id from XM_VABInit
_songId, // XM id ( as passed to InitXMData )
SONGNUM, // Song id
-1, // First channel
XM_NoLoop, // Loop
_playMask, // Play mask
XM_SFX, // Music
_sfxPattern); // Pattern to start at
SONGNUM++;
if(SONGNUM>=24)SONGNUM=1;
PAUL_DBGMSG("sfx - ret:%d",id);
return (xmPlayingSongId)id;
}
/*----------------------------------------------------------------------
Function:
Purpose:
Params:
Returns:
---------------------------------------------------------------------- */
int CXMPlaySound::isSfxActive(xmPlayingSongId _id)
{
XM_Feedback fb;
int ret;
XM_GetFeedback(_id,&fb);
ret=fb.Status==XM_PLAYING;
//PAUL_DBGMSG("check %d ( %d )",_id,fb.Status);
return ret;
}
/*----------------------------------------------------------------------
Function:
Purpose: Defrag SPU memory by reloading sample banks. Should mean that
bank load order isn't so vital.
Really needs to check for and pause playing sounds first.. hmm..
Params:
Returns:
---------------------------------------------------------------------- */
void CXMPlaySound::defragSpuMemory()
{
int vabId;
XMVab *vab;
unsigned char *VbPtr,*VhPtr;
SOUND_DBGMSG("CXMPlaySound is defragging..");
// Dump banks
vab=s_xmVabs;
for(vabId=0;vabId<MAX_XM_VABS;vabId++,vab++)
{
if(vab->m_refCount)
{
XM_CloseVAB(vab->m_vabId);
}
}
// Now reload them
vab=s_xmVabs;
for(vabId=0;vabId<MAX_XM_VABS;vabId++,vab++)
{
if(vab->m_refCount)
{
VhPtr=(u8*)CFileIO::loadFile(vab->m_vhFile);
VbPtr=(u8*)CFileIO::loadFile(vab->m_vbFile);
vab->m_vabId=XM_VABInit(VhPtr,VbPtr);
MemFree(VhPtr);
MemFree(VbPtr);
}
}
SOUND_DBGMSG("..done!");
}
/*===========================================================================
end */