00001
00002
00003
00004
00005 #include <list>
00006 #include <vector>
00007 #include <algorithm>
00008 #include "Log.h"
00009 #include <AL/al.h>
00010 #include <AL/alut.h>
00011 #include "OpenALSource.h"
00012 #include "ISound.h"
00013 #include "ISubSystem.h"
00014 #include "SoundSystem.h"
00015
00016 using namespace std;
00017
00018 SoundSystem *SoundSystem::s_soundSystem = NULL;
00019
00020 void SoundSystem::Initialize(unsigned int numSources) {
00021 if (s_soundSystem != NULL) {
00022 Log::s_log->Message("Warning: Attempt to re-initialize sound subsystem");
00023 return;
00024 }
00025
00026 s_soundSystem = new SoundSystem(numSources);
00027 }
00028
00029 void SoundSystem::Shutdown() {
00030 if (s_soundSystem == NULL) {
00031 Log::s_log->Message("Warning: Attempt to re-shutdown sound subsystem");
00032 return;
00033 }
00034 delete s_soundSystem;
00035 }
00036
00037 SoundSystem::SoundSystem(unsigned int numSources) {
00038 alutInit(0, NULL);
00039
00040 SetListener();
00041
00042 m_sources.resize(numSources);
00043 for (unsigned int i = 0; i < numSources; i++) {
00044 m_sources[i] = new OpenALSource();
00045 }
00046 m_availSources = m_sources;
00047
00048 Log::s_log->DebugMessage("Post-initialization...");
00049 LogDebugInfo();
00050
00051 Log::s_log->Message("Audio initialized");
00052 }
00053
00054 SoundSystem::~SoundSystem() {
00055 Log::s_log->DebugMessage("Pre-shutdown...");
00056 LogDebugInfo();
00057 StopAll();
00058 if (!m_playingSounds.empty()) {
00059 Log::s_log->Message("Sound system shutdown with sounds still active (likely memory leak!)");
00060 m_playingSounds.clear();
00061 }
00062
00063 m_availSources.clear();
00064
00065 for (unsigned int i = 0; i < m_sources.size(); i++) {
00066 delete m_sources[i];
00067 }
00068 m_sources.clear();
00069
00070 Log::s_log->DebugMessage("Post-shutdown...");
00071 LogDebugInfo();
00072
00073 alutExit();
00074 alGetError();
00075 Log::s_log->Message("Audio shutdown");
00076 }
00077
00078 void SoundSystem::LogDebugInfo() {
00079 Log::s_log->DebugMessage("%d sources", m_sources.size());
00080 Log::s_log->DebugMessage("%d sources available", m_availSources.size());
00081 Log::s_log->DebugMessage("%d sounds playing", m_playingSounds.size());
00082 }
00083
00084 void SoundSystem::SetListener() {
00085 ALfloat listenerPos[] = { 0.0, 0.0, 0.0 };
00086 ALfloat listenerVel[] = { 0.0, 0.0, 0.0 };
00087
00088
00089 ALfloat listenerOri[] = { 0.0, 0.0, -1.0, 0.0, 1.0, 0.0 };
00090
00091 alListenerfv(AL_POSITION, listenerPos);
00092 alListenerfv(AL_VELOCITY, listenerVel);
00093 alListenerfv(AL_ORIENTATION, listenerOri);
00094 }
00095
00096 void SoundSystem::Update(unsigned int ticks) {
00097 list< ISound* >::iterator p;
00098 list< ISound* >::iterator endIterator;
00099
00100 endIterator = m_playingSounds.end();
00101 for (p = m_playingSounds.begin(); p != endIterator; ++p) {
00102 (*p)->Update(ticks);
00103 }
00104 }
00105
00106 void SoundSystem::Play(ISound *sound) {
00107 sound->Prepare();
00108 MoveToFrontOfQueue(sound);
00109 sound->Play();
00110 }
00111
00112 OpenALSource* SoundSystem::AquireSource() {
00113 OpenALSource *source;
00114 list< ISound* >::reverse_iterator p;
00115 list< ISound* >::reverse_iterator endIterator;
00116 ISound *victim;
00117
00118 if (!m_availSources.empty()) {
00119
00120 source = m_availSources.back();
00121 m_availSources.pop_back();
00122
00123 return source;
00124 } else {
00125
00126 p = m_playingSounds.rbegin();
00127 endIterator = m_playingSounds.rend();
00128 while (p != endIterator) {
00129 victim = (*p);
00130 if ((!victim->m_locked) && (victim->m_source != NULL)) {
00131 source = victim->m_source;
00132 victim->RevokeSource();
00133
00134 return source;
00135 }
00136 ++p;
00137 }
00138 }
00139 throw string("Could not aquire source");
00140 }
00141
00142 void SoundSystem::ReleaseSound(ISound *sound) {
00143 OpenALSource *source;
00144
00145 sound->Stop();
00146 m_playingSounds.remove(sound);
00147
00148 source = sound->GetSource();
00149 if (source != NULL) {
00150 m_availSources.push_back(sound->GetSource());
00151 }
00152 }
00153
00154 void SoundSystem::PauseAll() {
00155 list< ISound* >::iterator p;
00156 list< ISound* >::const_iterator endIterator = m_playingSounds.end();
00157
00158 for (p = m_playingSounds.begin(); p != endIterator; ++p) {
00159 (*p)->Pause();
00160 }
00161 }
00162
00163 void SoundSystem::StopAll() {
00164 list< ISound* >::const_iterator p;
00165 list< ISound* >::const_iterator endIterator = m_playingSounds.end();
00166
00167 for (p = m_playingSounds.begin(); p != endIterator; ++p) {
00168 (*p)->Stop();
00169 }
00170 }
00171
00172 void SoundSystem::MoveToFrontOfQueue(ISound *sound) {
00173 m_playingSounds.remove(sound);
00174 m_playingSounds.push_front(sound);
00175 }