All pastes #338741 Raw Edit

Anonymous

public text v1 · immutable
·published 2007-02-03 17:40 UTC
rendered paste body
class 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;
}