Revision: 2379 http://rigsofrods.svn.sourceforge.net/rigsofrods/?rev=2379&view=rev Author: ulteq Date: 2012-01-28 20:48:12 +0000 (Sat, 28 Jan 2012) Log Message: ----------- fixed merge
Removed Paths: ------------- branches/bugfixes/source/main/audio/SoundManager.cpp.backup branches/bugfixes/source/main/audio/SoundManager.h.backup Deleted: branches/bugfixes/source/main/audio/SoundManager.cpp.backup =================================================================== --- branches/bugfixes/source/main/audio/SoundManager.cpp.backup 2012-01-28 20:43:42 UTC (rev 2378) +++ branches/bugfixes/source/main/audio/SoundManager.cpp.backup 2012-01-28 20:48:12 UTC (rev 2379) @@ -1,563 +0,0 @@ -/* -This source file is part of Rigs of Rods -Copyright 2005-2012 Pierre-Michel Ricordel -Copyright 2007-2012 Thomas Fischer - -For more information, see http://www.rigsofrods.com/ - -Rigs of Rods is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License version 3, as -published by the Free Software Foundation. - -Rigs of Rods is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Rigs of Rods. If not, see <http://www.gnu.org/licenses/>. -*/ -#ifdef USE_OPENAL - -#include "Ogre.h" -#include "Settings.h" -#include "SoundManager.h" - -// some gcc fixes -#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX -#pragma GCC diagnostic ignored "-Wfloat-equal" -#endif // OGRE_PLATFORM_LINUX - -using namespace Ogre; - -SoundManager::SoundManager() -{ - device=NULL; - context=NULL; - free_input_source=0; - free_buffer=0; - num_hardware_sources=0; - used_hardware_sources=0; - maxDistance=500.0; - rolloffFactor=1.0; - referenceDistance=7.5; - pthread_mutex_init(&audio_mutex, NULL); - - for (int i=0; i<MAX_HARDWARE_SOURCES; i++) hardware_sources_input_map[i]=0; - - if (SSETTING("3D Sound renderer") == "No sound") return; - - char str[256]; - if (SSETTING("3D Sound renderer") == "Default") str[0]=0; - else sprintf(str, "DirectSound Software on %s", SSETTING("3D Sound renderer").c_str()); - - LOG("Opening Device: '"+String(str)+"'"); - - //we loop alcOpenDevice() because there is a potential race condition with the asynchronous DSound enumeration callback - for (int i=0; i<100; i++) - { - device=alcOpenDevice(str); - if (device) break; //all right we got it - else - { - ALint error; - error=alGetError(); - if (error!=ALC_INVALID_VALUE) - { - //this is unexpected error - LOG("Could not create OpenAL device, error code: "+TOSTRING(error)); - return; - } //else just loop - } - } - if (!device) //we looped and we got nothing - { - //last ditch attempt with the default sound device, in case the user has a messed-up config file - device=alcOpenDevice(""); - if (!device) - { - LOG("Could not create OpenAL device after many tries."); - return; - } - else - LOG("Warning: invalid sound device configuration, I will use the default sound source. Run configurator!"); - } - context=alcCreateContext(device, NULL); - if (!context) - { - ALint error; - error=alGetError(); - LOG("Could not create OpenAL context, error code: "+TOSTRING(error)); - alcCloseDevice(device); - device=NULL; - return; - } - alcMakeContextCurrent(context); - //generate the AL sources - for (num_hardware_sources=0; num_hardware_sources<MAX_HARDWARE_SOURCES; num_hardware_sources++) - { - alGetError(); - alGenSources(1, &hardware_sources[num_hardware_sources]); - if(alGetError()!=AL_NO_ERROR) - break; - alSourcef(hardware_sources[num_hardware_sources], AL_REFERENCE_DISTANCE, referenceDistance); - alSourcef(hardware_sources[num_hardware_sources], AL_ROLLOFF_FACTOR, rolloffFactor); - alSourcef(hardware_sources[num_hardware_sources], AL_MAX_DISTANCE, maxDistance); - } -} - -Sound* SoundManager::createSound(String filename) -{ - if (!device) return NULL; - MUTEX_LOCK(&audio_mutex); - ALuint buffer=0; - //first, search if we need to create the buffer - for (int i=0; i<free_buffer; i++) - if (filename==buffer_filenames[i]) - { - buffer=buffers[i]; - break; - } - if (!buffer) - { - //load the file - if (free_buffer==MAX_BUFFERS) - { - MUTEX_UNLOCK(&audio_mutex); - return NULL; - } - alGenBuffers(1, &buffers[free_buffer]); - buffer_filenames[free_buffer]=filename; - if (loadWAVFile(filename, buffers[free_buffer])) - { - //there was an error! - alDeleteBuffers(1, &buffers[free_buffer]); - buffer_filenames[free_buffer]=String(""); - MUTEX_UNLOCK(&audio_mutex); - return NULL; - } - buffer=buffers[free_buffer++]; - } - if (free_input_source==MAX_INPUT_SOURCES) - { - MUTEX_UNLOCK(&audio_mutex); - return NULL; - } - input_sources[free_input_source++]=new Sound(buffer, this); - //don't recompute, because sounds do not play automatically - //recomputeSource(free_input_source-1); - MUTEX_UNLOCK(&audio_mutex); - return input_sources[free_input_source-1]; -} - -void SoundManager::setCamera(Ogre::Vector3 position, Ogre::Vector3 direction, Ogre::Vector3 up, Ogre::Vector3 velocity) -{ - if (!device) return; - MUTEX_LOCK(&audio_mutex); - cameraPosition=position; - recomputeAllSources(); - float dir[6]; - //at - dir[0]=direction.x; - dir[1]=direction.y; - dir[2]=direction.z; - //up - dir[3]=up.x; - dir[4]=up.y; - dir[5]=up.z; - alListener3f(AL_POSITION, position.x,position.y, position.z); - alListener3f(AL_VELOCITY, velocity.x,velocity.y,velocity.z); - alListenerfv(AL_ORIENTATION, dir); - MUTEX_UNLOCK(&audio_mutex); -} - -void SoundManager::pauseAllSounds() -{ - if (!device) return; - //no need for mutex - alListenerf(AL_GAIN, 0.0); -} - -void SoundManager::resumeAllSounds() -{ - if (!device) return; - //no need for mutex - alListenerf(AL_GAIN, 1.0); -} - -bool compareByAudibility(Sound *a, Sound *b) -{ - if (a == 0 || b == 0) - return b == 0; - - return a->audibility > b->audibility; -} - -//this function is called when the camera moves -void SoundManager::recomputeAllSources() -{ - if (!device) return; - //mutex is supposed to be already taken - for (int i=0; i<free_input_source; i++) input_sources[i]->computeAudibility(cameraPosition); - //sort first 'num_hardware_sources' sources by audibility - //see: https://en.wikipedia.org/wiki/Selection_algorithm - if ((free_input_source-1) > num_hardware_sources) - std::nth_element(input_sources, input_sources+num_hardware_sources, input_sources+free_input_source-1, compareByAudibility); - //retire out of range sources first - for (int i=0; i<free_input_source; i++) - if (input_sources[i]->hardware_index != -1 && (i >= num_hardware_sources || input_sources[i]->audibility == 0)) - retire(input_sources[i]); - //assign new sources - for (int i=0; i<std::min(free_input_source, num_hardware_sources); i++) - { - if (input_sources[i]->hardware_index == -1 && input_sources[i]->audibility > 0) - { - for (int j=0; j<num_hardware_sources; j++) - { - if (hardware_sources_input_map[j] == 0) - { - assign(input_sources[i], j); - break; - } - } - } - } -} - -void SoundManager::recomputeSource(Sound* source, int reason, float vfl, Vector3 *vvec) -{ - if (!device) return; - //mutex is supposed to be already taken - - //something has changed in a source - source->computeAudibility(cameraPosition); - if (source->audibility == 0) - { - //this is an extinct source, retire if currently playing - if (source->hardware_index != -1) retire(source); - } - else - { - //this is a potentially audible source - if (source->hardware_index!=-1) - { - //source already playing - //update the AL settings - switch (reason) - { - case REASON_PLAY: alSourcePlay(hardware_sources[source->hardware_index]);break; - case REASON_STOP: alSourceStop(hardware_sources[source->hardware_index]);break; - case REASON_GAIN: alSourcef(hardware_sources[source->hardware_index], AL_GAIN, vfl);break; - case REASON_LOOP: alSourcei(hardware_sources[source->hardware_index], AL_LOOPING, (vfl>0.5)?AL_TRUE:AL_FALSE);break; - case REASON_PTCH: alSourcef(hardware_sources[source->hardware_index], AL_PITCH, vfl);break; - case REASON_POSN: alSource3f(hardware_sources[source->hardware_index], AL_POSITION, vvec->x,vvec->y,vvec->z);break; - case REASON_VLCT: alSource3f(hardware_sources[source->hardware_index], AL_VELOCITY, vvec->x,vvec->y,vvec->z);break; - default:break; - } - } - else - { - //try to make it play by the hardware - //check if there is one free source in the pool - if (used_hardware_sources<num_hardware_sources) - { - //yes! - for (int i=0; i<num_hardware_sources; i++) - if (hardware_sources_input_map[i] == 0) - { - assign(source, i); - break; - } - } - else - { - //no, compute who is the faintest - //note: we know the table hardware_sources_input_map is full! - float fv=1.0; - int al_faintest=0; - for (int i=0; i<num_hardware_sources; i++) - if (hardware_sources_input_map[i] && hardware_sources_input_map[i]->audibility<fv) - { - fv=hardware_sources_input_map[i]->audibility; - al_faintest=i; - } - //find if the the faintest source is louder or not - if (fv<source->audibility) - { - //this new source is louder than the faintest! - retire(hardware_sources_input_map[al_faintest]); - assign(source, al_faintest); - } - //else this source is too faint, we don't play it! - } - } - } -} - -void SoundManager::assign(Sound* source, int hardware_index) -{ - if (!device) return; - //mutex is supposed to be taken - source->hardware_index=hardware_index; - hardware_sources_input_map[hardware_index++]=source; - - //the hardware index is supposed to be stopped! - alSourcei(hardware_sources[hardware_index], AL_BUFFER, source->buffer); - alSourcef(hardware_sources[hardware_index], AL_GAIN, source->gain); - alSourcei(hardware_sources[hardware_index], AL_LOOPING, (source->loop)?AL_TRUE:AL_FALSE); - alSourcef(hardware_sources[hardware_index], AL_PITCH, source->pitch); - alSource3f(hardware_sources[hardware_index], AL_POSITION, source->position.x,source->position.y,source->position.z); - alSource3f(hardware_sources[hardware_index], AL_VELOCITY, source->velocity.x,source->velocity.y,source->velocity.z); - if (source->should_play) - alSourcePlay(hardware_sources[hardware_index]); -} - -void SoundManager::retire(Sound* source) -{ - if (!device) return; - //mutex is supposed to be taken - if (source->hardware_index == -1) return; - alSourceStop(hardware_sources[source->hardware_index]); - hardware_sources_input_map[source->hardware_index]=0; - source->hardware_index=-1; - used_hardware_sources--; -} - -int SoundManager::loadWAVFile(String filename, ALuint buffer) -{ - if (!device) return -1; - LOG("Loading WAV file "+filename); - //creating Stream - ResourceGroupManager *rgm=ResourceGroupManager::getSingletonPtr(); - String group=rgm->findGroupContainingResource(filename); - DataStreamPtr stream=rgm->openResource(filename, group); - //load RIFF/WAVE - char magic[5]; - magic[4]=0; - unsigned int lbuf; // uint32_t - unsigned short sbuf; // uint16_t - - // check magic - if (stream->read(magic, 4)!=4) {LOG("Could not read file "+filename);return -1;} - if (String(magic)!=String("RIFF")) {LOG("Invalid WAV file (no RIFF): "+filename);return -1;} - //skip filesize - stream->skip(4); - // check file format - if (stream->read(magic, 4)!=4) {LOG("Could not read file "+filename);return -1;} - if (String(magic)!=String("WAVE")) {LOG("Invalid WAV file (no WAVE): "+filename);return -1;} - // check 'fmt ' sub chunk (1) - if (stream->read(magic, 4)!=4) {LOG("Could not read file "+filename);return -1;} - if (String(magic)!=String("fmt ")) {LOG("Invalid WAV file (no fmt): "+filename);return -1;} - // read (1)'s size - if (stream->read(&lbuf, 4)!=4) {LOG("Could not read file "+filename);return -1;} - unsigned long subChunk1Size=lbuf; - if (subChunk1Size<16) {LOG("Invalid WAV file (invalid subChunk1Size): "+filename);return -1;} - // check PCM audio format - if (stream->read(&sbuf, 2)!=2) {LOG("Could not read file "+filename);return -1;} - unsigned short audioFormat=sbuf; - if (audioFormat!=1) {LOG("Invalid WAV file (invalid audioformat "+TOSTRING(audioFormat)+"): "+filename);return -1;} - // read number of channels - if (stream->read(&sbuf, 2)!=2) {LOG("Could not read file "+filename);return -1;} - unsigned short channels=sbuf; - // read frequency (sample rate) - if (stream->read(&lbuf, 4)!=4) {LOG("Could not read file "+filename);return -1;} - unsigned long freq=lbuf; - // skip 6 bytes (Byte rate (4), Block align (2)) - stream->skip(6); - // read bits per sample - if (stream->read(&sbuf, 2)!=2) {LOG("Could not read file "+filename);return -1;} - unsigned short bps=sbuf; - // check 'data' sub chunk (2) - if (stream->read(magic, 4)!=4) {LOG("Could not read file "+filename);return -1;} - if (String(magic)!=String("data") && String(magic)!=String("fact")) {LOG("Invalid WAV file (no data/fact): "+filename);return -1;} - // fact is an option section we don't need to worry about - if(String(magic)==String("fact")) - { - stream->skip(8); - // Now we shoudl hit the data chunk - if (stream->read(magic, 4)!=4) {LOG("Could not read file "+filename);return -1;} - if (String(magic)!=String("data")) {LOG("Invalid WAV file (no data): "+filename);return -1;} - } - // The next four bytes are the remaining size of the file - if (stream->read(&lbuf, 4)!=4) {LOG("Could not read file "+filename);return -1;} - unsigned long dataSize=lbuf; - - int format; - if (channels==1 && bps==8) - { - format=AL_FORMAT_MONO8; - } else - if (channels==1 && bps==16) - { - format=AL_FORMAT_MONO16; - } else - if (channels==2 && bps==8) - { - format=AL_FORMAT_STEREO16; - } else - if (channels==2 && bps==16) - { - format=AL_FORMAT_STEREO16; - } else - { - LOG("Invalid WAV file (wrong channels/bps): "+filename); - return -1; - } - if(channels != 1) - { - LOG("Invalid WAV file: the file needs to be mono, and nothing else. Will try to continue anyways ..."); - } - //okay, creating buffer - void* bdata=malloc(dataSize); - if (!bdata) {LOG("Memory error reading file "+filename);return -1;} - if (stream->read(bdata, dataSize)!=dataSize) {LOG("Could not read file "+filename);return -1;} - - //LOG("alBufferData: format "+TOSTRING(format)+" size "+TOSTRING(dataSize)+" freq "+TOSTRING(freq)); - alGetError(); //reset errors - ALint error; - alBufferData(buffer, format, bdata, dataSize, freq); - error=alGetError(); - if(error!=AL_NO_ERROR) - { - LOG("OpenAL error while loading buffer for "+filename+" : "+TOSTRING(error)); - free(bdata); - return -1; - } - - free(bdata); - //stream will be closed by itself - - return 0; -} - -//----------------------------------------------------------------------------------- - -Sound::Sound(ALuint buffer, SoundManager *sm) -{ - //mutex is supposed to be taken - this->sm=sm; - this->buffer=buffer; - hardware_index=-1; - gain=1.0; - pitch=1.0; - loop=false; - enabled=true; - should_play=false; - position=Vector3::ZERO; - velocity=Vector3::ZERO; -} - -void Sound::computeAudibility(Vector3 pos_at) -{ - //disable sound? - if(!enabled) - { - audibility=0; - return; - } - - //mutex is supposed to be taken - //first check if the sound is finished! - if (!loop && hardware_index!=-1 && should_play) - { - int value; - alGetSourcei(sm->hardware_sources[hardware_index], AL_SOURCE_STATE, &value); - if (value!=AL_PLAYING) should_play=false; - } - if (!should_play) {audibility=0.0; return;} - if (gain==0.0) {audibility=0.0; return;} - - float distance=(pos_at-position).length(); - - if (distance > sm->maxDistance) {audibility=0.0; return;} - if (distance < sm->referenceDistance) {audibility=gain; return;} - - audibility=gain*(sm->referenceDistance/(sm->referenceDistance+ (sm->rolloffFactor*(distance-sm->referenceDistance)))); -} - -bool Sound::isPlaying() -{ - MUTEX_LOCK(&sm->audio_mutex); - if (hardware_index!=-1) - { - int value; - alGetSourcei(sm->hardware_sources[hardware_index], AL_SOURCE_STATE, &value); - MUTEX_UNLOCK(&sm->audio_mutex); - return (value==AL_PLAYING); - } - MUTEX_UNLOCK(&sm->audio_mutex); - return false; -} - -void Sound::setEnabled(bool e) -{ - MUTEX_LOCK(&sm->audio_mutex); - enabled = e; - sm->recomputeSource(this, REASON_PLAY, 0, NULL); - MUTEX_UNLOCK(&sm->audio_mutex); -} - -bool Sound::getEnabled() -{ - MUTEX_LOCK(&sm->audio_mutex); - return enabled; - MUTEX_UNLOCK(&sm->audio_mutex); -} - -void Sound::play() -{ - MUTEX_LOCK(&sm->audio_mutex); - should_play=true; - sm->recomputeSource(this, REASON_PLAY, 0, NULL); - MUTEX_UNLOCK(&sm->audio_mutex); -} - -void Sound::stop() -{ - MUTEX_LOCK(&sm->audio_mutex); - should_play=false; - sm->recomputeSource(this, REASON_STOP, 0, NULL); - MUTEX_UNLOCK(&sm->audio_mutex); -} - -void Sound::setGain(float gain) -{ - MUTEX_LOCK(&sm->audio_mutex); - this->gain=gain; - sm->recomputeSource(this, REASON_GAIN, gain, NULL); - MUTEX_UNLOCK(&sm->audio_mutex); -} - -void Sound::setLoop(bool loop) -{ - MUTEX_LOCK(&sm->audio_mutex); - this->loop=loop; - sm->recomputeSource(this, REASON_LOOP, (loop)?1.0:0.0, NULL); - MUTEX_UNLOCK(&sm->audio_mutex); -} - -void Sound::setPitch(float pitch) -{ - MUTEX_LOCK(&sm->audio_mutex); - this->pitch=pitch; - sm->recomputeSource(this, REASON_PTCH, pitch, NULL); - MUTEX_UNLOCK(&sm->audio_mutex); -} - -void Sound::setPosition(Ogre::Vector3 pos) -{ - MUTEX_LOCK(&sm->audio_mutex); - this->position=pos; - sm->recomputeSource(this, REASON_POSN, 0, &pos); - MUTEX_UNLOCK(&sm->audio_mutex); -} - -void Sound::setVelocity(Ogre::Vector3 vel) -{ - MUTEX_LOCK(&sm->audio_mutex); - this->velocity=vel; - sm->recomputeSource(this, REASON_VLCT, 0, &vel); - MUTEX_UNLOCK(&sm->audio_mutex); -} - -#endif // USE_OPENAL Deleted: branches/bugfixes/source/main/audio/SoundManager.h.backup =================================================================== --- branches/bugfixes/source/main/audio/SoundManager.h.backup 2012-01-28 20:43:42 UTC (rev 2378) +++ branches/bugfixes/source/main/audio/SoundManager.h.backup 2012-01-28 20:48:12 UTC (rev 2379) @@ -1,134 +0,0 @@ -/* -This source file is part of Rigs of Rods -Copyright 2005-2012 Pierre-Michel Ricordel -Copyright 2007-2012 Thomas Fischer - -For more information, see http://www.rigsofrods.com/ - -Rigs of Rods is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License version 3, as -published by the Free Software Foundation. - -Rigs of Rods is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Rigs of Rods. If not, see <http://www.gnu.org/licenses/>. -*/ -#ifdef USE_OPENAL -#ifndef __SoundManager_H__ -#define __SoundManager_H__ - -#include "RoRPrerequisites.h" -#include "Ogre.h" -#include "AL/al.h" -#include "AL/alc.h" -#include "pthread.h" -using namespace Ogre; - -// Maximum number of really mixed sources -#define MAX_HARDWARE_SOURCES 32 -// Maximum number of potential sound sources -#define MAX_INPUT_SOURCES 8192 -// Maximum number of sound files -#define MAX_BUFFERS 2048 - -#define REASON_PLAY 0 -#define REASON_STOP 1 -#define REASON_GAIN 2 -#define REASON_LOOP 3 -#define REASON_PTCH 4 -#define REASON_POSN 5 -#define REASON_VLCT 6 - - -class Sound -{ -public: - Sound(ALuint buffer, SoundManager* sm); - - void computeAudibility(Vector3 pos_at); - void setPitch(float pitch); - void setGain(float gain); - void setPosition(Vector3 pos); - void setVelocity(Vector3 vel); - void setLoop(bool loop); - void setEnabled(bool e); - void play(); - void stop(); - bool getEnabled(); - bool isPlaying(); - - float audibility; - float gain; - float pitch; - bool loop; - bool enabled; - bool should_play; - - // The hardware index, this value is dynamically updated as this input is played or not - int hardware_index; - ALuint buffer; - - Vector3 position; - Vector3 velocity; - -private: - SoundManager* sm; -}; - -class SoundManager -{ -public: - SoundManager(); - - Sound* createSound(String filename); - - void setCamera(Vector3 position, Vector3 direction, Vector3 up, Vector3 velocity); - void pauseAllSounds(); - void resumeAllSounds(); - void recomputeAllSources(); - void recomputeSource(Sound* source, int reason, float vfl, Vector3 *vvec); - - float maxDistance; - float rolloffFactor; - float referenceDistance; - - int maxSources() { return num_hardware_sources; } - - // AL hardware sources : this buffer contains valid AL handles up to num_hardware_sources - ALuint hardware_sources[MAX_HARDWARE_SOURCES]; - // Access mutex - pthread_mutex_t audio_mutex; - -private: - void assign(Sound* source, int hardware_index); - void retire(Sound* source); - int loadWAVFile(String filename, ALuint buffer); - - // Input sources: Array of Sound - int free_input_source; - Sound* input_sources[MAX_INPUT_SOURCES]; - - // Buffers: Array of AL buffers and filenames - int free_buffer; - ALuint buffers[MAX_BUFFERS]; - String buffer_filenames[MAX_BUFFERS]; - - // Total number of available hardware sources <= MAX_HARDWARE_SOURCES - int num_hardware_sources; - // Number of used hardware sources - int used_hardware_sources; - // Stores the sound for each hardware index. Value 0 means unmapped hardware source - Sound* hardware_sources_input_map[MAX_HARDWARE_SOURCES]; - - Vector3 cameraPosition; - ALCdevice *device; - ALCcontext *context; - -}; - -#endif // __SoundManager_H__ -#endif // USE_OPENAL This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Try before you buy = See our experts in action! The most comprehensive online learning library for Microsoft developers is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3, Metro Style Apps, more. Free future releases when you subscribe now! http://p.sf.net/sfu/learndevnow-dev2 _______________________________________________ Rigsofrods-devel mailing list Rigsofrods-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/rigsofrods-devel