FIFE
2008.0
|
00001 /*************************************************************************** 00002 * Copyright (C) 2005-2008 by the FIFE team * 00003 * http://www.fifengine.de * 00004 * This file is part of FIFE. * 00005 * * 00006 * FIFE is free software; you can redistribute it and/or * 00007 * modify it under the terms of the GNU Lesser General Public * 00008 * License as published by the Free Software Foundation; either * 00009 * version 2.1 of the License, or (at your option) any later version. * 00010 * * 00011 * This library is distributed in the hope that it will be useful, * 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00014 * Lesser General Public License for more details. * 00015 * * 00016 * You should have received a copy of the GNU Lesser General Public * 00017 * License along with this library; if not, write to the * 00018 * Free Software Foundation, Inc., * 00019 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 00020 ***************************************************************************/ 00021 00022 // Standard C++ library includes 00023 00024 // Platform specific includes 00025 00026 // 3rd party library includes 00027 00028 // FIFE includes 00029 // These includes are split up in two parts, separated by one empty line 00030 // First block: files included from the FIFE root src directory 00031 // Second block: files included from the same folder 00032 #include "util/log/logger.h" 00033 #include "util/time/timemanager.h" 00034 #include "util/base/exception.h" 00035 #include "soundemitter.h" 00036 #include "soundmanager.h" 00037 #include "soundclippool.h" 00038 00039 namespace FIFE { 00040 static Logger _log(LM_AUDIO); 00041 00042 SoundEmitter::SoundEmitter(SoundManager* manager, SoundClipPool* pool, unsigned int uid) : m_manager(manager), m_pool(pool), m_source(0), m_soundclip(NULL), m_soundclipid(0), m_streamid(0), 00043 m_emitterid(uid), m_loop(false) { 00044 if (!m_manager->isActive()) { 00045 return; 00046 } 00047 00048 TimeManager::instance()->registerEvent(this); 00049 setPeriod(-1); 00050 alGenSources(1, &m_source); 00051 CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error creating source") 00052 } 00053 00054 SoundEmitter::~SoundEmitter() { 00055 if (!m_manager->isActive()) { 00056 return; 00057 } 00058 00059 setPeriod(-1); 00060 TimeManager::instance()->unregisterEvent(this); 00061 reset(); 00062 alDeleteSources(1, &m_source); 00063 } 00064 00065 void SoundEmitter::reset(bool defaultall) { 00066 if (m_soundclip != NULL) { 00067 00068 setPeriod(-1); 00069 alSourceStop(m_source); 00070 00071 // Release all buffers 00072 alSourcei(m_source, AL_BUFFER, AL_NONE); 00073 alGetError(); 00074 00075 if (m_soundclip->isStream()) { 00076 m_soundclip->quitStreaming(m_streamid); 00077 } 00078 00079 // release the soundclip 00080 m_pool->release(m_soundclipid, true); 00081 m_soundclip = NULL; 00082 00083 // default source properties 00084 if (defaultall) { 00085 setPosition(0.0f, 0.0f, 0.0f); 00086 setVelocity(0.0f, 0.0f, 0.0f); 00087 setGain(1.0f); 00088 setPositioning(false); 00089 alSourcei(m_source, AL_LOOPING, AL_FALSE); 00090 } 00091 } 00092 } 00093 00094 void SoundEmitter::release() { 00095 m_manager->releaseEmitter(m_emitterid); 00096 } 00097 00098 void SoundEmitter::setSoundClip(unsigned int sound_id) { 00099 m_soundclipid = sound_id; 00100 m_soundclip = &(m_pool->getSoundClip(m_soundclipid)); 00101 m_soundclip->addRef(); 00102 00103 attachSoundClip(); 00104 } 00105 00106 void SoundEmitter::setCallback(const type_callback& cb) { 00107 m_callback = cb; 00108 } 00109 00110 void SoundEmitter::attachSoundClip() { 00111 if (!m_soundclip->isStream()) { 00112 // non-streaming 00113 alSourceQueueBuffers(m_source, m_soundclip->countBuffers(), m_soundclip->getBuffers()); 00114 alSourcei(m_source, AL_LOOPING, m_loop ? AL_TRUE : AL_FALSE); 00115 00116 } else { 00117 // streaming 00118 m_streamid = m_soundclip->beginStreaming(); 00119 m_soundclip->acquireStream(m_streamid); 00120 00121 // queue initial buffers 00122 alSourceQueueBuffers(m_source, BUFFER_NUM, m_soundclip->getBuffers(m_streamid)); 00123 alSourcei(m_source, AL_LOOPING, AL_FALSE); 00124 } 00125 00126 CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error attaching sound clip") 00127 } 00128 00129 void SoundEmitter::updateEvent(unsigned long time) { 00130 ALint procs; 00131 ALint bufs; 00132 ALuint buffer; 00133 00134 alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &procs); 00135 00136 while (procs--) { 00137 alSourceUnqueueBuffers(m_source, 1, &buffer); 00138 00139 if (m_soundclip->getStream(m_streamid, buffer)) { 00140 // EOF! 00141 if (m_loop) { 00142 // play again from the beginning 00143 m_soundclip->setStreamPos(m_streamid, SD_BYTE_POS, 0); 00144 m_soundclip->getStream(m_streamid, buffer); 00145 } else { 00146 00147 // check if the playback has been finished 00148 alGetSourcei(m_source, AL_BUFFERS_QUEUED, &bufs); 00149 if (bufs == 0) { 00150 setPeriod(-1); 00151 alSourceStop(m_source); 00152 if(m_callback) { 00153 m_callback(); 00154 } 00155 } 00156 continue; 00157 } 00158 } 00159 alSourceQueueBuffers(m_source, 1, &buffer); 00160 } 00161 00162 CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error while streaming") 00163 } 00164 00165 void SoundEmitter::setLooping(bool loop) { 00166 if (m_soundclip) { 00167 if (!m_soundclip->isStream()) { 00168 alSourcei(m_source, AL_LOOPING, loop ? AL_TRUE : AL_FALSE); 00169 } else { 00170 alSourcei(m_source, AL_LOOPING, AL_FALSE); 00171 } 00172 } 00173 m_loop = loop; 00174 } 00175 00176 void SoundEmitter::play() { 00177 if (m_soundclip) { 00178 alSourcePlay(m_source); 00179 if (m_soundclip->isStream()) { 00180 setPeriod(5000); 00181 } 00182 } 00183 } 00184 00185 void SoundEmitter::stop() { 00186 if (m_soundclip) { 00187 alSourceStop(m_source); 00188 00189 if (m_soundclip->isStream()) { 00190 setPeriod(-1); 00191 setCursor(SD_BYTE_POS, 0); 00192 } else { 00193 alSourceRewind(m_source); 00194 } 00195 } 00196 } 00197 00198 void SoundEmitter::setCursor(SoundPositionType type, float value) { 00199 if (!m_soundclip) { 00200 return; 00201 } 00202 00203 ALint state = 0; 00204 00205 if (!m_soundclip->isStream()) { 00206 switch(type) { 00207 case SD_BYTE_POS: 00208 alSourcef(m_source, AL_BYTE_OFFSET, value); 00209 break; 00210 case SD_SAMPLE_POS: 00211 alSourcef(m_source, AL_SAMPLE_OFFSET, value); 00212 break; 00213 case SD_TIME_POS: 00214 alSourcef(m_source, AL_SEC_OFFSET, value); 00215 break; 00216 } 00217 00218 CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error setting cursor position") 00219 } 00220 else { 00221 alGetSourcei(m_source, AL_SOURCE_STATE, &state); 00222 00223 if (state == AL_PLAYING || AL_PAUSED) { 00224 setPeriod(-1); 00225 alSourceStop(m_source); 00226 } 00227 00228 m_soundclip->setStreamPos(m_streamid, type, value); 00229 00230 // detach all buffers 00231 alSourcei(m_source, AL_BUFFER, 0); 00232 00233 // queue the buffers with new data 00234 m_soundclip->acquireStream(m_streamid); 00235 alSourceQueueBuffers(m_source, BUFFER_NUM, m_soundclip->getBuffers(m_streamid)); 00236 00237 if (state == AL_PLAYING) { 00238 setPeriod(5000); 00239 alSourcePlay(m_source); 00240 } 00241 00242 CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error setting stream cursor position") 00243 } 00244 } 00245 00246 float SoundEmitter::getCursor(SoundPositionType type) { 00247 if (!m_soundclip) { 00248 return 0.0f; 00249 } 00250 00251 ALfloat pos = 0.0f; 00252 00253 switch(type) { 00254 case SD_BYTE_POS: 00255 alGetSourcef(m_source, AL_BYTE_OFFSET, &pos); 00256 break; 00257 case SD_SAMPLE_POS: 00258 alGetSourcef(m_source, AL_SAMPLE_OFFSET, &pos); 00259 break; 00260 case SD_TIME_POS: 00261 alGetSourcef(m_source, AL_SEC_OFFSET, &pos); 00262 break; 00263 } 00264 00265 if (m_soundclip->isStream()) { 00266 pos += m_soundclip->getStreamPos(m_streamid, type); 00267 } 00268 00269 CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error getting cursor") 00270 00271 return pos; 00272 } 00273 }