rpcs3/rpcs3/Emu/Audio/AL/OpenALThread.cpp
2014-07-12 16:33:04 +10:00

159 lines
3.6 KiB
C++

#include "stdafx.h"
#include "Utilities/Log.h"
#include "Emu/System.h"
#include "rpcs3/Ini.h"
#include "OpenALThread.h"
ALenum g_last_al_error = AL_NO_ERROR;
ALCenum g_last_alc_error = ALC_NO_ERROR;
#define checkForAlError(sit) if((g_last_al_error = alGetError()) != AL_NO_ERROR) printAlError(g_last_al_error, sit)
#define checkForAlcError(sit) if((g_last_alc_error = alcGetError(m_device)) != ALC_NO_ERROR) printAlcError(g_last_alc_error, sit)
static const ALenum g_audio_format = Ini.AudioConvertToU16.GetValue() ? AL_FORMAT_STEREO16 : AL_FORMAT_STEREO_FLOAT32;
void printAlError(ALenum err, const char* situation)
{
if(err != AL_NO_ERROR)
{
LOG_ERROR(HLE, "%s: OpenAL error 0x%04x", situation, err);
Emu.Pause();
}
}
void printAlcError(ALCenum err, const char* situation)
{
if(err != ALC_NO_ERROR)
{
LOG_ERROR(HLE, "%s: OpenALC error 0x%04x", situation, err);
Emu.Pause();
}
}
OpenALThread::~OpenALThread()
{
Quit();
}
void OpenALThread::Init()
{
m_device = alcOpenDevice(nullptr);
checkForAlcError("alcOpenDevice");
m_context = alcCreateContext(m_device, nullptr);
checkForAlcError("alcCreateContext");
alcMakeContextCurrent(m_context);
checkForAlcError("alcMakeContextCurrent");
}
void OpenALThread::Quit()
{
m_context = alcGetCurrentContext();
m_device = alcGetContextsDevice(m_context);
alcMakeContextCurrent(nullptr);
alcDestroyContext(m_context);
alcCloseDevice(m_device);
}
void OpenALThread::Play()
{
ALint state;
alGetSourcei(m_source, AL_SOURCE_STATE, &state);
checkForAlError("OpenALThread::Play -> alGetSourcei");
if(state != AL_PLAYING)
{
alSourcePlay(m_source);
checkForAlError("alSourcePlay");
}
}
void OpenALThread::Close()
{
alSourceStop(m_source);
checkForAlError("alSourceStop");
if (alIsSource(m_source))
alDeleteSources(1, &m_source);
alDeleteBuffers(g_al_buffers_count, m_buffers);
checkForAlError("alDeleteBuffers");
}
void OpenALThread::Stop()
{
alSourceStop(m_source);
checkForAlError("alSourceStop");
}
void OpenALThread::Open(const void* src, ALsizei size)
{
alGenSources(1, &m_source);
checkForAlError("alGenSources");
alGenBuffers(g_al_buffers_count, m_buffers);
checkForAlError("alGenBuffers");
alSourcei(m_source, AL_LOOPING, AL_FALSE);
checkForAlError("OpenALThread::Open ->alSourcei");
m_buffer_size = size;
for(uint i=0; i<g_al_buffers_count; ++i)
{
AddBlock(m_buffers[i], m_buffer_size, src);
}
alSourceQueueBuffers(m_source, g_al_buffers_count, m_buffers);
checkForAlError("alSourceQueueBuffers");
Play();
}
void OpenALThread::AddData(const void* src, ALsizei size)
{
const char* bsrc = (const char*)src;
ALuint buffer;
ALint buffers_count;
alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &buffers_count);
checkForAlError("OpenALThread::AddData -> alGetSourcei");
while(size)
{
if(buffers_count-- <= 0)
{
Play();
alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &buffers_count);
checkForAlError("OpenALThread::AddData(in loop) -> alGetSourcei");
continue;
}
alSourceUnqueueBuffers(m_source, 1, &buffer);
checkForAlError("alSourceUnqueueBuffers");
int bsize = size < m_buffer_size ? size : m_buffer_size;
if (!AddBlock(buffer, bsize, bsrc))
LOG_ERROR(HLE, "OpenALThread::AddBlock: invalid block size: %d", bsize);
alSourceQueueBuffers(m_source, 1, &buffer);
checkForAlError("alSourceQueueBuffers");
size -= bsize;
bsrc += bsize;
}
Play();
}
bool OpenALThread::AddBlock(const ALuint buffer_id, const ALsizei size, const void* src)
{
if (size < 1) return false;
alBufferData(buffer_id, g_audio_format, src, size, 48000);
checkForAlError("alBufferData");
return true;
}