#include "SH_OpenAL.h" #include "alloca_def.h" #include //#define LOGGING #define SAMPLE_RATE 44100 ALCint g_attrList[] = { ALC_FREQUENCY, SAMPLE_RATE, 0, 0}; #define CHECK_AL_ERROR() \ { \ assert(alGetError() == AL_NO_ERROR); \ } CSH_OpenAL::CSH_OpenAL() : m_context(m_device, g_attrList) , m_lastUpdateTime(0) , m_mustSync(true) { m_context.MakeCurrent(); alGenBuffers(MAX_BUFFERS, m_bufferNames); CHECK_AL_ERROR(); Reset(); } CSH_OpenAL::~CSH_OpenAL() { Reset(); alDeleteBuffers(MAX_BUFFERS, m_bufferNames); CHECK_AL_ERROR(); } CSoundHandler* CSH_OpenAL::HandlerFactory() { return new CSH_OpenAL(); } void CSH_OpenAL::Reset() { m_source.Stop(); ALint sourceState = m_source.GetState(); assert(sourceState == AL_INITIAL || sourceState == AL_STOPPED); alSourcei(m_source, AL_BUFFER, 0); CHECK_AL_ERROR(); m_availableBuffers.clear(); m_availableBuffers.insert(m_availableBuffers.begin(), m_bufferNames, m_bufferNames + MAX_BUFFERS); } void CSH_OpenAL::RecycleBuffers() { unsigned int bufferCount = m_source.GetBuffersProcessed(); CHECK_AL_ERROR(); if(bufferCount != 0) { ALuint* bufferNames = reinterpret_cast(alloca(sizeof(ALuint) * bufferCount)); alSourceUnqueueBuffers(m_source, bufferCount, bufferNames); CHECK_AL_ERROR(); m_availableBuffers.insert(m_availableBuffers.begin(), bufferNames, bufferNames + bufferCount); } } bool CSH_OpenAL::HasFreeBuffers() { return m_availableBuffers.size() != 0; } uint32 CSH_OpenAL::GetFreeBufferCount() const { return m_availableBuffers.size(); } void CSH_OpenAL::Write(int16* samples, unsigned int sampleCount, unsigned int sampleRate) { assert(m_availableBuffers.size() != 0); if(m_availableBuffers.size() == 0) return; ALuint buffer = *m_availableBuffers.begin(); m_availableBuffers.pop_front(); alBufferData(buffer, AL_FORMAT_STEREO16, samples, sampleCount * sizeof(int16), sampleRate); CHECK_AL_ERROR(); alSourceQueueBuffers(m_source, 1, &buffer); CHECK_AL_ERROR(); ALint sourceState = m_source.GetState(); if(sourceState != AL_PLAYING) { m_source.Play(); assert(m_source.GetState() == AL_PLAYING); } }