710 lines
24 KiB
C++
710 lines
24 KiB
C++
//This file is part of Glest Shared Library (www.glest.org)
|
|
//Copyright (C) 2005 Matthias Braun <matze@braunis.de>
|
|
|
|
//You can redistribute this code and/or modify it under
|
|
//the terms of the GNU General Public License as published by the Free Software
|
|
//Foundation; either version 2 of the License, or (at your option) any later
|
|
//version.
|
|
#include "sound_player_openal.h"
|
|
|
|
#include <cassert>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <stdexcept>
|
|
|
|
#include "platform_util.h"
|
|
#include "util.h"
|
|
#include "conversion.h"
|
|
#include "leak_dumper.h"
|
|
|
|
namespace Shared{ namespace Sound{ namespace OpenAL{
|
|
|
|
using namespace Util;
|
|
|
|
SoundSource::SoundSource()
|
|
{
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
|
|
alGenSources(1, &source);
|
|
SoundPlayerOpenAL::checkAlError("Couldn't create audio source: ");
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
}
|
|
|
|
SoundSource::~SoundSource()
|
|
{
|
|
stop();
|
|
alDeleteSources(1, &source);
|
|
}
|
|
|
|
bool SoundSource::playing()
|
|
{
|
|
ALint state = AL_STOPPED;
|
|
alGetSourcei(source, AL_SOURCE_STATE, &state);
|
|
return(state == AL_PLAYING || state == AL_PAUSED);
|
|
}
|
|
|
|
void SoundSource::unQueueBuffers() {
|
|
SoundPlayerOpenAL::checkAlError("Problem unqueuing buffers START OF METHOD: ");
|
|
|
|
ALint queued=0;
|
|
alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
|
|
alSourcei(source, AL_LOOPING, AL_FALSE);
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
|
|
ALint processed=0;
|
|
alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
|
|
while(processed--) {
|
|
ALuint buffer=0;
|
|
alSourceUnqueueBuffers(source, 1, &buffer);
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
}
|
|
|
|
// ALint queued=0;
|
|
// alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
|
|
// while(queued--) {
|
|
// ALuint buffer=0;
|
|
// alSourceUnqueueBuffers(source, 1, &buffer);
|
|
// SoundPlayerOpenAL::checkAlError("Problem unqueuing buffers (alSourceUnqueueBuffers) in audio source: ");
|
|
// }
|
|
//
|
|
// SoundPlayerOpenAL::checkAlError("Problem unqueuing buffers (alGetSourcei AL_BUFFERS_QUEUED) in audio source: ");
|
|
|
|
}
|
|
|
|
void SoundSource::stop() {
|
|
alSourceStop(source);
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
|
|
unQueueBuffers();
|
|
|
|
alSourcei(source, AL_BUFFER, AL_NONE);
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
|
|
//unQueueBuffers();
|
|
|
|
alSourceRewind(source); // stops the source
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
|
|
while(playing() == true) {
|
|
//alSourceStop(source);
|
|
//SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
ALint state = AL_STOPPED;
|
|
alGetSourcei(source, AL_SOURCE_STATE, &state);
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
|
|
sleep(1);
|
|
printf("$$$ WAITING FOR OPENAL TO STOP state = %d!\n",state);
|
|
}
|
|
//unQueueBuffers();
|
|
//SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
}
|
|
|
|
ALenum SoundSource::getFormat(Sound* sound)
|
|
{
|
|
if(sound->getInfo()->getChannels() == 2) {
|
|
if(sound->getInfo()->getBitsPerSample() == 16) {
|
|
return AL_FORMAT_STEREO16;
|
|
}
|
|
else if(sound->getInfo()->getBitsPerSample() == 8) {
|
|
return AL_FORMAT_STEREO8;
|
|
}
|
|
else {
|
|
throw std::runtime_error("[1] Sample format not supported in file: " + sound->getFileName());
|
|
}
|
|
}
|
|
else if(sound->getInfo()->getChannels() == 1) {
|
|
if(sound->getInfo()->getBitsPerSample() == 16) {
|
|
return AL_FORMAT_MONO16;
|
|
}
|
|
else if(sound->getInfo()->getBitsPerSample() == 8) {
|
|
return AL_FORMAT_MONO8;
|
|
}
|
|
else {
|
|
throw std::runtime_error("[2] Sample format not supported in file: " + sound->getFileName());
|
|
}
|
|
}
|
|
|
|
throw std::runtime_error("[3] Sample format not supported in file: " + sound->getFileName());
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
StaticSoundSource::StaticSoundSource() {
|
|
bufferAllocated = false;
|
|
buffer = 0;
|
|
}
|
|
|
|
StaticSoundSource::~StaticSoundSource() {
|
|
if(bufferAllocated) {
|
|
stop();
|
|
alDeleteBuffers(1, &buffer);
|
|
}
|
|
}
|
|
|
|
void StaticSoundSource::play(StaticSound* sound) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
|
|
if(bufferAllocated) {
|
|
stop();
|
|
alDeleteBuffers(1, &buffer);
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
}
|
|
ALenum format = getFormat(sound);
|
|
|
|
alGenBuffers(1, &buffer);
|
|
SoundPlayerOpenAL::checkAlError("Couldn't create audio buffer: ");
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s Line: %d] filename [%s] format = %d, sound->getSamples() = %d, sound->getInfo()->getSize() = %d, sound->getInfo()->getSamplesPerSecond() = %d\n",__FILE__,__FUNCTION__,__LINE__,sound->getFileName().c_str(),format,sound->getSamples(),sound->getInfo()->getSize(),sound->getInfo()->getSamplesPerSecond());
|
|
|
|
bufferAllocated = true;
|
|
alBufferData(buffer, format, sound->getSamples(),
|
|
static_cast<ALsizei> (sound->getInfo()->getSize()),
|
|
static_cast<ALsizei> (sound->getInfo()->getSamplesPerSecond()));
|
|
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
|
|
alSourcei(source, AL_BUFFER, buffer);
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
alSourcef(source, AL_GAIN, sound->getVolume());
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
|
|
alSourcePlay(source);
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
}
|
|
|
|
StreamSoundSource::StreamSoundSource()
|
|
{
|
|
sound = 0;
|
|
fadeState = NoFading;
|
|
format = 0;
|
|
fade = 0;
|
|
alGenBuffers(STREAMFRAGMENTS, buffers);
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
}
|
|
|
|
StreamSoundSource::~StreamSoundSource()
|
|
{
|
|
stop();
|
|
alDeleteBuffers(STREAMFRAGMENTS, buffers);
|
|
SoundPlayerOpenAL::checkAlError("Couldn't delete audio buffers: ");
|
|
}
|
|
|
|
void StreamSoundSource::stop()
|
|
{
|
|
sound = 0;
|
|
SoundSource::stop();
|
|
}
|
|
|
|
void StreamSoundSource::stop(int64 fadeoff)
|
|
{
|
|
if(fadeoff > 0) {
|
|
fadeState = FadingOff;
|
|
fade = fadeoff;
|
|
chrono.start();
|
|
} else {
|
|
stop();
|
|
}
|
|
}
|
|
|
|
void StreamSoundSource::play(StrSound* sound, int64 fadeon)
|
|
{
|
|
stop();
|
|
|
|
this->sound = sound;
|
|
|
|
format = getFormat(sound);
|
|
for(size_t i = 0; i < STREAMFRAGMENTS; ++i) {
|
|
fillBufferAndQueue(buffers[i]);
|
|
}
|
|
if(fadeon > 0) {
|
|
alSourcef(source, AL_GAIN, 0);
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
|
|
fadeState = FadingOn;
|
|
fade = fadeon;
|
|
chrono.start();
|
|
} else {
|
|
fadeState = NoFading;
|
|
alSourcef(source, AL_GAIN, sound->getVolume());
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
}
|
|
alSourcePlay(source);
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
}
|
|
|
|
void StreamSoundSource::update()
|
|
{
|
|
if(sound == 0) {
|
|
return;
|
|
}
|
|
|
|
if(fadeState == NoFading){
|
|
alSourcef(source, AL_GAIN, sound->getVolume());
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
}
|
|
|
|
ALint processed = 0;
|
|
alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
while(processed > 0) {
|
|
processed--;
|
|
|
|
ALuint buffer;
|
|
alSourceUnqueueBuffers(source, 1, &buffer);
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
|
|
if(!fillBufferAndQueue(buffer))
|
|
break;
|
|
}
|
|
|
|
// we might have to restart the source if we had a buffer underrun
|
|
if(!playing()) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s %d] Restarting audio source because of buffer underrun.\n",__FILE__,__FUNCTION__,__LINE__);
|
|
|
|
std::cerr << "Restarting audio source because of buffer underrun.\n";
|
|
alSourcePlay(source);
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
}
|
|
|
|
// handle fading
|
|
switch(fadeState) {
|
|
case FadingOn:
|
|
if(chrono.getMillis() > fade) {
|
|
alSourcef(source, AL_GAIN, sound->getVolume());
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
|
|
fadeState = NoFading;
|
|
} else {
|
|
alSourcef(source, AL_GAIN, sound->getVolume() *
|
|
static_cast<float> (chrono.getMillis())/fade);
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
}
|
|
break;
|
|
case FadingOff:
|
|
if(chrono.getMillis() > fade) {
|
|
stop();
|
|
} else {
|
|
alSourcef(source, AL_GAIN, sound->getVolume() *
|
|
(1.0f - static_cast<float>(chrono.getMillis())/fade));
|
|
SoundPlayerOpenAL::checkAlError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool StreamSoundSource::fillBufferAndQueue(ALuint buffer)
|
|
{
|
|
// fill buffer
|
|
int8* bufferdata = new int8[STREAMFRAGMENTSIZE];
|
|
uint32 bytesread = 0;
|
|
do {
|
|
bytesread += sound->read(bufferdata + bytesread,STREAMFRAGMENTSIZE - bytesread);
|
|
if(bytesread < STREAMFRAGMENTSIZE) {
|
|
StrSound* next = sound->getNext();
|
|
if(next == 0)
|
|
next = sound;
|
|
next->restart();
|
|
next->setVolume(sound->getVolume());
|
|
sound = next;
|
|
}
|
|
} while(bytesread < STREAMFRAGMENTSIZE);
|
|
|
|
alBufferData(buffer, format, bufferdata, STREAMFRAGMENTSIZE,
|
|
sound->getInfo()->getSamplesPerSecond());
|
|
delete[] bufferdata;
|
|
SoundPlayerOpenAL::checkAlError("Couldn't refill audio buffer: ");
|
|
|
|
alSourceQueueBuffers(source, 1, &buffer);
|
|
SoundPlayerOpenAL::checkAlError("Couldn't queue audio buffer: ");
|
|
|
|
return true;
|
|
}
|
|
|
|
// ================================
|
|
// Sound Player OpenAL
|
|
// ================================
|
|
|
|
SoundPlayerOpenAL::SoundPlayerOpenAL() {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
|
|
device = 0;
|
|
context = 0;
|
|
initOk = false;
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
}
|
|
|
|
SoundPlayerOpenAL::~SoundPlayerOpenAL() {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
|
|
end();
|
|
initOk = false;
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
}
|
|
|
|
void SoundPlayerOpenAL::printOpenALInfo()
|
|
{
|
|
printf("OpenAL Vendor: %s\n",alGetString(AL_VENDOR));
|
|
printf("OpenAL Version: %s\n",alGetString(AL_VERSION));
|
|
printf("OpenAL Renderer: %s\n",alGetString(AL_RENDERER));
|
|
printf("OpenAL Extensions: %s\n",alGetString(AL_RENDERER));
|
|
|
|
/*
|
|
std::cout << "OpenAL Vendor: " << alGetString(AL_VENDOR) << "\n"
|
|
<< "OpenAL Version: " << alGetString(AL_VERSION) << "\n"
|
|
<< "OpenAL Renderer: " << alGetString(AL_RENDERER) << "\n"
|
|
<< "OpenAl Extensions: " << alGetString(AL_RENDERER) << "\n";
|
|
*/
|
|
}
|
|
|
|
bool SoundPlayerOpenAL::init(const SoundPlayerParams* params) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
|
|
initOk = false;
|
|
|
|
if(params == NULL) {
|
|
throw std::runtime_error("params == NULL");
|
|
}
|
|
|
|
this->params = *params;
|
|
|
|
try {
|
|
|
|
if(context != 0) {
|
|
alcMakeContextCurrent( NULL );
|
|
alcDestroyContext(context);
|
|
context = 0;
|
|
}
|
|
|
|
if(device != 0) {
|
|
alcCloseDevice(device);
|
|
device = 0;
|
|
}
|
|
|
|
// Allows platforms to specify which sound device to use
|
|
// using the environment variable: MEGAGLEST_SOUND_DEVICE
|
|
char *deviceName = getenv("MEGAGLEST_SOUND_DEVICE");
|
|
device = alcOpenDevice(deviceName);
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) {
|
|
std::ostringstream os;
|
|
if (alcIsExtensionPresent (NULL, (const ALCchar *) "ALC_ENUMERATION_EXT") == AL_TRUE) {
|
|
const char *s = (const char *) alcGetString(NULL, ALC_DEVICE_SPECIFIER);
|
|
while (*s != '\0') {
|
|
os << "OpenAL available device: " << s << std::endl;
|
|
while (*s++ != '\0')
|
|
;
|
|
}
|
|
}
|
|
else {
|
|
os << "OpenAL device enumeration isn't available." << std::endl;
|
|
}
|
|
|
|
// Print default device name
|
|
os << "OpenAL default device: "
|
|
<< (const char *)alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER)
|
|
<< std::endl;
|
|
|
|
// Print current device name
|
|
if (device) {
|
|
os << "OpenAL current device: "
|
|
<< (const char *)alcGetString(device, ALC_DEVICE_SPECIFIER)
|
|
<< std::endl;
|
|
}
|
|
|
|
SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s %d] OpenAL device info [%s]\n",__FILE__,__FUNCTION__,__LINE__,os.str().c_str());
|
|
printf("OpenAL device info:\n%s\n",os.str().c_str());
|
|
}
|
|
|
|
if(device == 0) {
|
|
//printOpenALInfo();
|
|
throw std::runtime_error("Couldn't open audio device.");
|
|
}
|
|
|
|
//int attributes[] = { 0 };
|
|
//context = alcCreateContext(device, attributes);
|
|
context = alcCreateContext(device, 0);
|
|
checkAlcError("Couldn't create audio context: ");
|
|
|
|
if(context == NULL) {
|
|
alcCloseDevice(device);
|
|
device = NULL;
|
|
throw std::runtime_error("Couldn't create an audio context (NULL).");
|
|
}
|
|
|
|
alcMakeContextCurrent(context);
|
|
checkAlcError("Couldn't select audio context: ");
|
|
|
|
checkAlError("Audio error after init: ");
|
|
|
|
initOk = true;
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
}
|
|
catch(const exception &ex) {
|
|
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s %d] error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
|
|
printOpenALInfo();
|
|
}
|
|
|
|
return initOk;
|
|
}
|
|
|
|
void SoundPlayerOpenAL::end() {
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
|
|
|
|
for(StaticSoundSources::iterator i = staticSources.begin();
|
|
i != staticSources.end(); ++i) {
|
|
StaticSoundSource *src = (*i);
|
|
src->stop();
|
|
}
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
|
|
for(StreamSoundSources::iterator i = streamSources.begin();
|
|
i != streamSources.end(); ++i) {
|
|
StreamSoundSource *src = (*i);
|
|
src->stop();
|
|
}
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
|
|
for(StaticSoundSources::iterator i = staticSources.begin();
|
|
i != staticSources.end(); ++i) {
|
|
delete *i;
|
|
}
|
|
staticSources.clear();
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
|
|
for(StreamSoundSources::iterator i = streamSources.begin();
|
|
i != streamSources.end(); ++i) {
|
|
delete *i;
|
|
}
|
|
streamSources.clear();
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
|
|
if(context != 0) {
|
|
alcMakeContextCurrent( NULL );
|
|
SoundPlayerOpenAL::checkAlcError(string(__FILE__) + string(" ") + string(__FUNCTION__) + string(" ") + intToStr(__LINE__));
|
|
}
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
|
|
if(context != 0) {
|
|
alcDestroyContext(context);
|
|
context = 0;
|
|
}
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
|
|
if(device != 0) {
|
|
alcCloseDevice(device);
|
|
device = 0;
|
|
initOk = false;
|
|
}
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
}
|
|
|
|
void SoundPlayerOpenAL::play(StaticSound* staticSound, bool force ) {
|
|
assert(staticSound != 0);
|
|
|
|
if(initOk == false) return;
|
|
|
|
try {
|
|
StaticSoundSource* source = findStaticSoundSource();
|
|
|
|
if(source == 0 ) {
|
|
if( force == false )
|
|
return;
|
|
else {
|
|
// force usage of first StaticSoundSource
|
|
source = staticSources.front();
|
|
source->stop();
|
|
}
|
|
}
|
|
source->play(staticSound);
|
|
}
|
|
catch(std::exception& e) {
|
|
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,e.what());
|
|
std::cerr << "Couldn't play static sound: [" << e.what() << "]\n";
|
|
}
|
|
}
|
|
|
|
void SoundPlayerOpenAL::play(StrSound* strSound, int64 fadeOn) {
|
|
assert(strSound != 0);
|
|
|
|
if(initOk == false) return;
|
|
|
|
try {
|
|
StreamSoundSource* source = findStreamSoundSource();
|
|
source->play(strSound, fadeOn);
|
|
}
|
|
catch(std::exception& e) {
|
|
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,e.what());
|
|
std::cerr << "Couldn't play streaming sound: " << e.what() << "\n";
|
|
}
|
|
}
|
|
|
|
void SoundPlayerOpenAL::stop(StrSound* strSound, int64 fadeOff) {
|
|
assert(strSound != 0);
|
|
|
|
if(initOk == false) return;
|
|
|
|
for(StreamSoundSources::iterator i = streamSources.begin();
|
|
i != streamSources.end(); ++i) {
|
|
StreamSoundSource* source = *i;
|
|
if(source->sound == strSound) {
|
|
source->stop(fadeOff);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SoundPlayerOpenAL::stopAllSounds(int64 fadeOff) {
|
|
if(initOk == false) return;
|
|
|
|
for(StaticSoundSources::iterator i = staticSources.begin();
|
|
i != staticSources.end(); ++i) {
|
|
StaticSoundSource* source = *i;
|
|
source->stop();
|
|
}
|
|
for(StreamSoundSources::iterator i = streamSources.begin();
|
|
i != streamSources.end(); ++i) {
|
|
StreamSoundSource* source = *i;
|
|
source->stop(fadeOff);
|
|
}
|
|
}
|
|
|
|
void SoundPlayerOpenAL::updateStreams() {
|
|
if(initOk == false) return;
|
|
|
|
assert(context != 0);
|
|
try {
|
|
for(StreamSoundSources::iterator i = streamSources.begin();
|
|
i != streamSources.end(); ++i) {
|
|
StreamSoundSource* source = *i;
|
|
try {
|
|
source->update();
|
|
}
|
|
catch(std::exception& e) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,e.what());
|
|
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,e.what());
|
|
|
|
std::cerr << "Error while updating sound stream: "<< e.what() << "\n";
|
|
}
|
|
}
|
|
alcProcessContext(context);
|
|
checkAlcError("Error while processing audio context: ");
|
|
}
|
|
catch(exception &ex) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
|
|
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
|
|
printOpenALInfo();
|
|
throw megaglest_runtime_error(ex.what());
|
|
}
|
|
catch(...) {
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s Line: %d] UNKNOWN Error\n",__FILE__,__FUNCTION__,__LINE__);
|
|
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] UNKNOWN Error\n",__FILE__,__FUNCTION__,__LINE__);
|
|
printOpenALInfo();
|
|
throw;
|
|
}
|
|
}
|
|
|
|
StaticSoundSource* SoundPlayerOpenAL::findStaticSoundSource() {
|
|
if(initOk == false) return NULL;
|
|
|
|
// try to find a stopped source
|
|
int playingCount = 0;
|
|
for(StaticSoundSources::iterator i = staticSources.begin();
|
|
i != staticSources.end(); ++i) {
|
|
StaticSoundSource* source = *i;
|
|
if(! source->playing()) {
|
|
return source;
|
|
}
|
|
else {
|
|
playingCount++;
|
|
}
|
|
}
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s %d] playingCount = %d, staticSources.size() = " MG_SIZE_T_SPECIFIER ", params.staticBufferCount = %u\n",__FILE__,__FUNCTION__,__LINE__,playingCount,(unsigned long)staticSources.size(),params.staticBufferCount);
|
|
|
|
// create a new source
|
|
if(staticSources.size() >= params.staticBufferCount) {
|
|
return 0;
|
|
}
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
|
|
StaticSoundSource* source = new StaticSoundSource();
|
|
staticSources.push_back(source);
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
|
|
return source;
|
|
}
|
|
|
|
StreamSoundSource* SoundPlayerOpenAL::findStreamSoundSource() {
|
|
if(initOk == false) return NULL;
|
|
|
|
// try to find a stopped source
|
|
for(StreamSoundSources::iterator i = streamSources.begin();
|
|
i != streamSources.end(); ++i) {
|
|
StreamSoundSource* source = *i;
|
|
if(! source->playing()) {
|
|
return source;
|
|
}
|
|
}
|
|
|
|
// create a new source
|
|
if(streamSources.size() >= params.strBufferCount) {
|
|
throw std::runtime_error("Too many stream sounds played at once");
|
|
}
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
|
|
StreamSoundSource* source = new StreamSoundSource();
|
|
streamSources.push_back(source);
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled) SystemFlags::OutputDebug(SystemFlags::debugSound,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
|
|
return source;
|
|
}
|
|
|
|
void SoundPlayerOpenAL::checkAlcError(string message) {
|
|
int err = alcGetError(device);
|
|
if(err != ALC_NO_ERROR) {
|
|
char szBuf[8096]="";
|
|
snprintf(szBuf,8096,"%s [%s]",message.c_str(),alcGetString(device, err));
|
|
|
|
//std::stringstream msg;
|
|
//msg << message.c_str() << alcGetString(device, err);
|
|
printf("openalc error [%s]\n",szBuf);
|
|
throw std::runtime_error(szBuf);
|
|
}
|
|
}
|
|
|
|
void SoundPlayerOpenAL::checkAlError(string message) {
|
|
int err = alGetError();
|
|
if(err != AL_NO_ERROR) {
|
|
char szBuf[8096]="";
|
|
snprintf(szBuf,8096,"%s [%s]",message.c_str(),alGetString(err));
|
|
//std::stringstream msg;
|
|
//msg << message.c_str() << alGetString(err);
|
|
printf("openal error [%s]\n",szBuf);
|
|
throw std::runtime_error(szBuf);
|
|
}
|
|
}
|
|
|
|
}}} // end of namespace
|
|
|