Added some debug tracing abilities for sound related issues. Added a little protected to the open_al sound wrapper to avoid having queued sound buffers not being cleaned up properly in some cases. (Need to test on Windows now)

This commit is contained in:
Mark Vejvoda 2010-03-27 18:35:47 +00:00
parent 42919a50f2
commit 25dea73abc
6 changed files with 903 additions and 8 deletions

View File

@ -0,0 +1,160 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Martiño Figueroa
//
// 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 "intro.h"
#include "main_menu.h"
#include "util.h"
#include "game_util.h"
#include "config.h"
#include "program.h"
#include "renderer.h"
#include "sound_renderer.h"
#include "core_data.h"
#include "metrics.h"
#include "auto_test.h"
#include "util.h"
#include "leak_dumper.h"
using namespace Shared::Util;
using namespace Shared::Graphics;
namespace Glest{ namespace Game{
// =====================================================
// class Text
// =====================================================
Text::Text(const string &text, const Vec2i &pos, int time, const Font2D *font){
this->text= text;
this->pos= pos;
this->time= time;
this->texture= NULL;
this->font= font;
}
Text::Text(const Texture2D *texture, const Vec2i &pos, const Vec2i &size, int time){
this->pos= pos;
this->size= size;
this->time= time;
this->texture= texture;
this->font= NULL;
}
// =====================================================
// class Intro
// =====================================================
const int Intro::introTime= 24000;
const int Intro::appearTime= 2500;
const int Intro::showTime= 2500;
const int Intro::disapearTime= 2500;
Intro::Intro(Program *program):
ProgramState(program)
{
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
CoreData &coreData= CoreData::getInstance();
const Metrics &metrics= Metrics::getInstance();
int w= metrics.getVirtualW();
int h= metrics.getVirtualH();
timer=0;
texts.push_back(Text(coreData.getLogoTexture(), Vec2i(w/2-128, h/2-64), Vec2i(256, 128), 4000));
texts.push_back(Text(glestVersionString, Vec2i(w/2+64, h/2-32), 4000, coreData.getMenuFontNormal()));
texts.push_back(Text("www.glest.org", Vec2i(w/2, h/2), 12000, coreData.getMenuFontVeryBig()));
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
soundRenderer.playMusic(CoreData::getInstance().getIntroMusic());
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
void Intro::update(){
timer++;
if(timer>introTime*GameConstants::updateFps/1000){
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
program->setState(new MainMenu(program));
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
if(Config::getInstance().getBool("AutoTest")){
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
AutoTest::getInstance().updateIntro(program);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
}
void Intro::render(){
Renderer &renderer= Renderer::getInstance();
int difTime;
renderer.reset2d();
renderer.clearBuffers();
for(int i=0; i<texts.size(); ++i){
Text *text= &texts[i];
difTime= 1000*timer/GameConstants::updateFps-text->getTime();
if(difTime>0 && difTime<appearTime+showTime+disapearTime){
float alpha= 1.f;
if(difTime>0 && difTime<appearTime){
//apearing
alpha= static_cast<float>(difTime)/appearTime;
}
else if(difTime>0 && difTime<appearTime+showTime+disapearTime){
//disappearing
alpha= 1.f- static_cast<float>(difTime-appearTime-showTime)/disapearTime;
}
if(!text->getText().empty()){
renderer.renderText(
text->getText(), text->getFont(), alpha,
text->getPos().x, text->getPos().y, true);
}
if(text->getTexture()!=NULL){
renderer.renderTextureQuad(
text->getPos().x, text->getPos().y,
text->getSize().x, text->getSize().y,
text->getTexture(), alpha);
}
}
}
renderer.swapBuffers();
}
void Intro::keyDown(char key){
mouseUpLeft(0, 0);
}
void Intro::mouseUpLeft(int x, int y){
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
soundRenderer.stopMusic(CoreData::getInstance().getIntroMusic());
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
soundRenderer.playMusic(CoreData::getInstance().getMenuMusic());
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
program->setState(new MainMenu(program));
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
}}//end namespace

View File

@ -22,11 +22,12 @@
#include "game_util.h"
#include "platform_util.h"
#include "platform_main.h"
#include "leak_dumper.h"
#include "network_interface.h"
#include "sound_renderer.h"
#include "ImageReaders.h"
#include "leak_dumper.h"
using namespace std;
using namespace Shared::Platform;
using namespace Shared::Util;
@ -269,6 +270,8 @@ int glestMain(int argc, char** argv){
program->initNormal(mainWindow);
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
// test
//Shared::Platform::MessageBox(NULL,"Mark's test.","Test",0);
//throw runtime_error("test!");
@ -285,7 +288,11 @@ int glestMain(int argc, char** argv){
ExceptionHandler::handleRuntimeError(e.what());
}
//SoundRenderer &soundRenderer= SoundRenderer::getInstance();
//soundRenderer.stopAllSounds();
delete mainWindow;
//SystemFlags::Close();
return 0;

View File

@ -15,8 +15,10 @@
#include "config.h"
#include "sound_interface.h"
#include "factory_repository.h"
#include "util.h"
#include "leak_dumper.h"
using namespace Shared::Util;
using namespace Shared::Graphics;
using namespace Shared::Sound;
@ -30,27 +32,50 @@ const float SoundRenderer::audibleDist= 50.f;
// =====================================================
SoundRenderer::SoundRenderer(){
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
soundPlayer = NULL;
loadConfig();
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
void SoundRenderer::init(Window *window){
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
SoundInterface &si= SoundInterface::getInstance();
FactoryRepository &fr= FactoryRepository::getInstance();
Config &config= Config::getInstance();
si.setFactory(fr.getSoundFactory(config.getString("FactorySound")));
soundPlayer= si.newSoundPlayer();
//if(soundPlayer == NULL) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
si.setFactory(fr.getSoundFactory(config.getString("FactorySound")));
SoundPlayerParams soundPlayerParams;
soundPlayerParams.staticBufferCount= config.getInt("SoundStaticBuffers");
soundPlayerParams.strBufferCount= config.getInt("SoundStreamingBuffers");
soundPlayer->init(&soundPlayerParams);
stopAllSounds();
soundPlayer= si.newSoundPlayer();
SoundPlayerParams soundPlayerParams;
soundPlayerParams.staticBufferCount= config.getInt("SoundStaticBuffers");
soundPlayerParams.strBufferCount= config.getInt("SoundStreamingBuffers");
soundPlayer->init(&soundPlayerParams);
//}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
SoundRenderer::~SoundRenderer(){
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
stopAllSounds();
delete soundPlayer;
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
soundPlayer = NULL;
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
SoundRenderer &SoundRenderer::getInstance(){

View File

@ -0,0 +1,126 @@
//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.
#ifndef _SHARED_SOUND_SOUNDPLAYEROPENAL_H_
#define _SHARED_SOUND_SOUNDPLAYEROPENAL_H_
#include "sound_player.h"
#include "platform_util.h"
#include <SDL.h>
#include <AL/alc.h>
#include <AL/al.h>
#include <vector>
using std::vector;
namespace Shared{ namespace Sound{ namespace OpenAL{
class SoundSource {
public:
SoundSource();
virtual ~SoundSource();
bool playing();
void stop();
void unQueueBuffers();
protected:
friend class SoundPlayerOpenAL;
ALenum getFormat(Sound* sound);
ALuint source;
};
class StaticSoundSource : public SoundSource {
public:
StaticSoundSource();
virtual ~StaticSoundSource();
void play(StaticSound* sound);
protected:
friend class SoundPlayerOpenAL;
bool bufferAllocated;
ALuint buffer;
};
class StreamSoundSource : public SoundSource {
public:
StreamSoundSource();
virtual ~StreamSoundSource();
void play(StrSound* sound, int64 fade);
void update();
void stop();
void stop(int64 fade);
protected:
friend class SoundPlayerOpenAL;
static const size_t STREAMBUFFERSIZE = 1024 * 500;
static const size_t STREAMFRAGMENTS = 5;
static const size_t STREAMFRAGMENTSIZE
= STREAMBUFFERSIZE / STREAMFRAGMENTS;
bool fillBufferAndQueue(ALuint buffer);
StrSound* sound;
ALuint buffers[STREAMFRAGMENTS];
ALenum format;
enum FadeState { NoFading, FadingOn, FadingOff };
FadeState fadeState;
Chrono chrono; // delay-fade chrono
int64 fade;
};
// ==============================================================
// class SoundPlayerSDL
//
/// SoundPlayer implementation using SDL_mixer
// ==============================================================
class SoundPlayerOpenAL : public SoundPlayer {
public:
SoundPlayerOpenAL();
virtual ~SoundPlayerOpenAL();
virtual void init(const SoundPlayerParams *params);
virtual void end();
virtual void play(StaticSound *staticSound);
virtual void play(StrSound *strSound, int64 fadeOn=0);
virtual void stop(StrSound *strSound, int64 fadeOff=0);
virtual void stopAllSounds();
virtual void updateStreams(); //updates str buffers if needed
private:
friend class SoundSource;
friend class StaticSoundSource;
friend class StreamSoundSource;
void printOpenALInfo();
StaticSoundSource* findStaticSoundSource();
StreamSoundSource* findStreamSoundSource();
void checkAlcError(const char* message);
static void checkAlError(const char* message);
ALCdevice* device;
ALCcontext* context;
typedef std::vector<StaticSoundSource*> StaticSoundSources;
StaticSoundSources staticSources;
typedef std::vector<StreamSoundSource*> StreamSoundSources;
StreamSoundSources streamSources;
SoundPlayerParams params;
};
}}}//end namespace
#endif

View File

@ -0,0 +1,537 @@
//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 "leak_dumper.h"
namespace Shared{ namespace Sound{ namespace OpenAL{
using namespace Util;
SoundSource::SoundSource()
{
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
alGenSources(1, &source);
SoundPlayerOpenAL::checkAlError("Couldn't create audio source: ");
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
SoundSource::~SoundSource()
{
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
stop();
alDeleteSources(1, &source);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
bool SoundSource::playing()
{
ALint state = AL_PLAYING;
alGetSourcei(source, AL_SOURCE_STATE, &state);
return state != AL_STOPPED;
}
void SoundSource::unQueueBuffers() {
int queued;
alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
while(queued--) {
ALuint buffer;
alSourceUnqueueBuffers(source, 1, &buffer);
}
}
void SoundSource::stop()
{
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
alSourceStop(source);
SoundPlayerOpenAL::checkAlError("Problem stopping audio source: ");
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
unQueueBuffers();
SoundPlayerOpenAL::checkAlError("Problem unqueuing buffers in audio source: ");
alSourcei(source, AL_BUFFER, AL_NONE);
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
SoundPlayerOpenAL::checkAlError("Problem stopping audio source: ");
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__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("Sample format not supported");
} 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("Sample format not supported");
}
throw std::runtime_error("Sample format not supported");
}
//---------------------------------------------------------------------------
StaticSoundSource::StaticSoundSource() {
bufferAllocated = false;
}
StaticSoundSource::~StaticSoundSource() {
if(bufferAllocated) {
stop();
alDeleteBuffers(1, &buffer);
}
}
void StaticSoundSource::play(StaticSound* sound)
{
if(bufferAllocated) {
stop();
alDeleteBuffers(1, &buffer);
}
ALenum format = getFormat(sound);
alGenBuffers(1, &buffer);
SoundPlayerOpenAL::checkAlError("Couldn't create audio buffer: ");
bufferAllocated = true;
alBufferData(buffer, format, sound->getSamples(),
static_cast<ALsizei> (sound->getInfo()->getSize()),
static_cast<ALsizei> (sound->getInfo()->getSamplesPerSecond()));
SoundPlayerOpenAL::checkAlError("Couldn't fill audio buffer: ");
alSourcei(source, AL_BUFFER, buffer);
alSourcef(source, AL_GAIN, sound->getVolume());
alSourcePlay(source);
SoundPlayerOpenAL::checkAlError("Couldn't start audio source: ");
}
StreamSoundSource::StreamSoundSource()
{
sound = 0;
alGenBuffers(STREAMFRAGMENTS, buffers);
SoundPlayerOpenAL::checkAlError("Couldn't allocate audio buffers: ");
}
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);
fadeState = FadingOn;
fade = fadeon;
chrono.start();
} else {
fadeState = NoFading;
alSourcef(source, AL_GAIN, sound->getVolume());
}
alSourcePlay(source);
}
void StreamSoundSource::update()
{
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(sound == 0) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
return;
}
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
ALint processed = 0;
alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
while(processed > 0) {
processed--;
ALuint buffer;
alSourceUnqueueBuffers(source, 1, &buffer);
SoundPlayerOpenAL::checkAlError("Couldn't unqueue audio buffer: ");
if(!fillBufferAndQueue(buffer))
break;
}
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
// we might have to restart the source if we had a buffer underrun
if(!playing()) {
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
std::cerr
<< "Restarting audio source because of buffer underrun.\n";
alSourcePlay(source);
SoundPlayerOpenAL::checkAlError("Couldn't restart audio source: ");
}
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
// handle fading
switch(fadeState) {
case FadingOn:
if(chrono.getMillis() > fade) {
alSourcef(source, AL_GAIN, sound->getVolume());
fadeState = NoFading;
} else {
alSourcef(source, AL_GAIN, sound->getVolume() *
static_cast<float> (chrono.getMillis())/fade);
}
break;
case FadingOff:
if(chrono.getMillis() > fade) {
stop();
} else {
alSourcef(source, AL_GAIN, sound->getVolume() *
(1.0f - static_cast<float>(chrono.getMillis())/fade));
}
break;
default:
break;
}
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
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() {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
device = 0;
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
SoundPlayerOpenAL::~SoundPlayerOpenAL() {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
end();
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
void SoundPlayerOpenAL::printOpenALInfo()
{
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";
}
void SoundPlayerOpenAL::init(const SoundPlayerParams* params) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
this->params = *params;
device = alcOpenDevice(0);
if(device == 0) {
printOpenALInfo();
throw std::runtime_error("Couldn't open audio device.");
}
try {
int attributes[] = { 0 };
context = alcCreateContext(device, attributes);
checkAlcError("Couldn't create audio context: ");
alcMakeContextCurrent(context);
checkAlcError("Couldn't select audio context: ");
checkAlError("Audio error after init: ");
} catch(...) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
printOpenALInfo();
throw;
}
}
void SoundPlayerOpenAL::end() {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
for(StaticSoundSources::iterator i = staticSources.begin();
i != staticSources.end(); ++i) {
StaticSoundSource *src = (*i);
src->stop();
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
for(StreamSoundSources::iterator i = streamSources.begin();
i != streamSources.end(); ++i) {
StreamSoundSource *src = (*i);
src->stop();
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
for(StaticSoundSources::iterator i = staticSources.begin();
i != staticSources.end(); ++i) {
delete *i;
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
for(StreamSoundSources::iterator i = streamSources.begin();
i != streamSources.end(); ++i) {
delete *i;
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
alcMakeContextCurrent( NULL );
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(context != 0) {
alcDestroyContext(context);
context = 0;
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(device != 0) {
alcCloseDevice(device);
device = 0;
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
void SoundPlayerOpenAL::play(StaticSound* staticSound) {
assert(staticSound != 0);
try {
StaticSoundSource* source = findStaticSoundSource();
if(source == 0)
return;
source->play(staticSound);
} catch(std::exception& e) {
std::cerr << "Couldn't play static sound: " << e.what() << "\n";
}
}
void SoundPlayerOpenAL::play(StrSound* strSound, int64 fadeOn) {
assert(strSound != 0);
try {
StreamSoundSource* source = findStreamSoundSource();
source->play(strSound, fadeOn);
} catch(std::exception& e) {
std::cerr << "Couldn't play streaming sound: " << e.what() << "\n";
}
}
void SoundPlayerOpenAL::stop(StrSound* strSound, int64 fadeOff) {
assert(strSound != 0);
for(StreamSoundSources::iterator i = streamSources.begin();
i != streamSources.end(); ++i) {
StreamSoundSource* source = *i;
if(source->sound == strSound) {
source->stop(fadeOff);
}
}
}
void SoundPlayerOpenAL::stopAllSounds() {
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();
}
}
void SoundPlayerOpenAL::updateStreams() {
assert(context != 0);
try {
for(StreamSoundSources::iterator i = streamSources.begin();
i != streamSources.end(); ++i) {
StreamSoundSource* source = *i;
try {
source->update();
} catch(std::exception& e) {
std::cerr << "Error while updating sound stream: "
<< e.what() << "\n";
}
}
alcProcessContext(context);
checkAlcError("Error while processing audio context: ");
} catch(...) {
printOpenALInfo();
throw;
}
}
StaticSoundSource* SoundPlayerOpenAL::findStaticSoundSource() {
// try to find a stopped source
for(StaticSoundSources::iterator i = staticSources.begin();
i != staticSources.end(); ++i) {
StaticSoundSource* source = *i;
if(! source->playing()) {
return source;
}
}
// create a new source
if(staticSources.size() >= params.staticBufferCount) {
return 0;
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
StaticSoundSource* source = new StaticSoundSource();
staticSources.push_back(source);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
return source;
}
StreamSoundSource* SoundPlayerOpenAL::findStreamSoundSource() {
// 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");
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
StreamSoundSource* source = new StreamSoundSource();
streamSources.push_back(source);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
return source;
}
void SoundPlayerOpenAL::checkAlcError(const char* message)
{
int err = alcGetError(device);
if(err != ALC_NO_ERROR) {
std::stringstream msg;
msg << message << alcGetString(device, err);
throw std::runtime_error(msg.str());
}
}
void SoundPlayerOpenAL::checkAlError(const char* message)
{
int err = alGetError();
if(err != AL_NO_ERROR) {
std::stringstream msg;
msg << message << alGetString(err);
throw std::runtime_error(msg.str());
}
}
}}} // end of namespace

View File

@ -0,0 +1,40 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Martiño Figueroa
//
// 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_interface.h"
#include "util.h"
#include "leak_dumper.h"
using namespace Shared::Util;
namespace Shared{ namespace Sound{
// =====================================================
// class SoundInterface
// =====================================================
SoundInterface &SoundInterface::getInstance(){
static SoundInterface soundInterface;
return soundInterface;
}
void SoundInterface::setFactory(SoundFactory *soundFactory){
this->soundFactory= soundFactory;
}
SoundPlayer *SoundInterface::newSoundPlayer(){
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__);
return soundFactory->newSoundPlayer();
}
}}//end namespace