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:
parent
42919a50f2
commit
25dea73abc
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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(){
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
Loading…
Reference in New Issue