rendered paste bodyclass CSoundFile
{
public:
CSoundFile(const std::string& sFilename);
~CSoundFile();
const std::string& GetName();
Uint8* GetData();
Uint32 GetLength();
protected:
std::string m_sName;
std::vector<Uint8> m_vAudioData;
};
class CSoundPlay
{
public:
CSoundPlay(CSoundFile& SoundFile, Uint32 nVolume);
CSoundPlay(CSoundFile& SoundFile, const CVector& vecPosition, Uint32 nVolume);
~CSoundPlay();
bool Mix(Uint8* pStream, int nLength);
protected:
CSoundFile& m_SoundFile;
Uint32 m_nPlayed;
Uint32 m_nVolume;
CVector m_vecPosition;
bool m_bPositioned;
};
class CSound
{
public:
CSound();
~CSound();
void Preload(const std::string& sFilename);
void Play(const std::string& sFilename, Uint32 nVolume = SDL_MIX_MAXVOLUME);
void Play(const std::string& sFilename, const CVector& vecPosition, Uint32 nVolume = SDL_MIX_MAXVOLUME);
static void MixAudio_Gateway(void* pUserdata, Uint8* pStream, int nLength);
protected:
CSoundFile& FindSound(const std::string& sFilename);
void MixAudio(Uint8* pStream, int nLength);
std::vector<CSoundFile> m_vSounds;
std::list<CSoundPlay> m_vPlay;
};
CSound::CSound()
{
/* Set 16-bit stereo audio at 22Khz */
SDL_AudioSpec AudioFormat;
AudioFormat.freq = 44100;
AudioFormat.format = AUDIO_S16;
AudioFormat.channels = 2;
AudioFormat.samples = 4096;
AudioFormat.callback = &MixAudio_Gateway;
AudioFormat.userdata = this;
/* Open the audio device and start playing sound! */
if (SDL_OpenAudio(&AudioFormat, NULL) < 0) {
throw CSDLError("SDL_OpenAudio");
}
SDL_PauseAudio(0);
}
CSound::~CSound()
{
SDL_CloseAudio();
}
void CSound::Preload(const std::string& sFilename)
{
/* Preload a sound */
m_vSounds.push_back(CSoundFile(sFilename));
}
void CSound::Play(const std::string& sFilename, Uint32 nVolume)
{
m_vPlay.push_back(CSoundPlay(FindSound(sFilename), nVolume));
}
void CSound::Play(const std::string& sFilename, const CVector& vecPosition, Uint32 nVolume)
{
m_vPlay.push_back(CSoundPlay(FindSound(sFilename), vecPosition, nVolume));
}
CSoundFile& CSound::FindSound(const std::string& sFilename)
{
std::vector<CSoundFile>::iterator pEnd = m_vSounds.end();
for (std::vector<CSoundFile>::iterator pIterator = m_vSounds.begin(); pIterator < pEnd; pIterator++)
{
if (pIterator->GetName() == sFilename)
{
return *pIterator;
}
}
throw CSDLError("Couldn't find sound " + sFilename);
}
void CSound::MixAudio(Uint8* pStream, int nLength)
{
/* Play all the sounds */
for (std::list<CSoundPlay>::iterator pIterator = m_vPlay.begin(); pIterator != m_vPlay.end(); )
{
// Crappy way of solving - pIterator++ after erasing fucks up (do this better)
std::list<CSoundPlay>::iterator pNext = pIterator;
pNext++;
if (!pIterator->Mix(pStream, nLength))
{
m_vPlay.erase(pIterator);
}
pIterator = pNext;
}
}
void CSound::MixAudio_Gateway(void* pUserdata, Uint8* pStream, int nLength)
{
((CSound*) pUserdata)->MixAudio(pStream, nLength);
}
/*** ***/
CSoundFile::CSoundFile(const std::string& sFilename):
m_sName(sFilename)
{
SDL_AudioSpec AudioFormat;
SDL_AudioCVT AudioConverter;
Uint8* pAudioData;
Uint32 nAudioLength;
int nConvert;
/* Load WAV file */
if (!SDL_LoadWAV(("sounds/" + sFilename + ".wav").c_str(), &AudioFormat, &pAudioData, &nAudioLength))
{
throw CSDLError("SDL_LoadWAV");
}
/* Convert to 44100 + 2 channels + 16bit */
nConvert = SDL_BuildAudioCVT(
&AudioConverter,
AudioFormat.format, AudioFormat.channels, AudioFormat.freq,
AUDIO_S16, 2, 44100
);
/* This can't be converted */
if (nConvert == -1)
{
throw CSDLError("SDL_BuildAudioCVT");
}
/* Use vector to save the data instead of malloc/free */
m_vAudioData.resize(nAudioLength * AudioConverter.len_mult);
memcpy(&m_vAudioData[0], pAudioData, nAudioLength);
SDL_FreeWAV(pAudioData);
/* If we need to convert it do it here */
if (nConvert == 1)
{
/* Setup for conversion */
AudioConverter.buf = &m_vAudioData[0];
AudioConverter.len = nAudioLength;
/* And now we're ready to convert */
SDL_ConvertAudio(&AudioConverter);
}
}
CSoundFile::~CSoundFile()
{}
Uint8* CSoundFile::GetData()
{
return &m_vAudioData[0];
}
Uint32 CSoundFile::GetLength()
{
return m_vAudioData.size();
}
const std::string& CSoundFile::GetName()
{
return m_sName;
}
/*** ***/
CSoundPlay::CSoundPlay(CSoundFile& SoundFile, Uint32 nVolume):
m_SoundFile(SoundFile),
m_nPlayed(0),
m_nVolume(nVolume),
m_bPositioned(false)
{}
CSoundPlay::CSoundPlay(CSoundFile& SoundFile, const CVector& vecPosition, Uint32 nVolume):
m_SoundFile(SoundFile),
m_nPlayed(0),
m_nVolume(nVolume),
m_vecPosition(vecPosition),
m_bPositioned(true)
{}
CSoundPlay::~CSoundPlay()
{}
bool CSoundPlay::Mix(Uint8* pStream, int nLength)
{
int nMixLength;
bool bFinished;
nMixLength = m_SoundFile.GetLength() - m_nPlayed;
if (nMixLength > nLength)
{
nMixLength = nLength;
bFinished = true;
}
else
{
bFinished = false;
}
if (m_bPositioned)
{
// do something really smart here !
}
SDL_MixAudio(pStream, m_SoundFile.GetData() + m_nPlayed, nMixLength, m_nVolume);
m_nPlayed += nMixLength;
return bFinished;
}