00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
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
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
00080 m_pool->release(m_soundclipid, true);
00081 m_soundclip = NULL;
00082
00083
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
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
00118 m_streamid = m_soundclip->beginStreaming();
00119 m_soundclip->acquireStream(m_streamid);
00120
00121
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
00141 if (m_loop) {
00142
00143 m_soundclip->setStreamPos(m_streamid, SD_BYTE_POS, 0);
00144 m_soundclip->getStream(m_streamid, buffer);
00145 } else {
00146
00147
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
00231 alSourcei(m_source, AL_BUFFER, 0);
00232
00233
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 }