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 "soundclipmanager.h"
00038
00039 namespace FIFE {
00040 static Logger _log(LM_AUDIO);
00041
00042 SoundEmitter::SoundEmitter(SoundManager* manager, uint32_t uid) : m_manager(manager), m_source(0), m_soundclip(), 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) {
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
00081 m_soundclip.reset();
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(SoundClipPtr soundclip) {
00099 m_soundclipid = soundclip->getHandle();
00100 m_soundclip = soundclip;
00101
00102 attachSoundClip();
00103 }
00104
00105 void SoundEmitter::setCallback(const type_callback& cb) {
00106 m_callback = cb;
00107 }
00108
00109 void SoundEmitter::attachSoundClip() {
00110 if (!m_soundclip->isStream()) {
00111
00112 alSourceQueueBuffers(m_source, m_soundclip->countBuffers(), m_soundclip->getBuffers());
00113 alSourcei(m_source, AL_LOOPING, m_loop ? AL_TRUE : AL_FALSE);
00114
00115 } else {
00116
00117 m_streamid = m_soundclip->beginStreaming();
00118 m_soundclip->acquireStream(m_streamid);
00119
00120
00121 alSourceQueueBuffers(m_source, BUFFER_NUM, m_soundclip->getBuffers(m_streamid));
00122 alSourcei(m_source, AL_LOOPING, AL_FALSE);
00123 }
00124
00125 CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error attaching sound clip")
00126 }
00127
00128 void SoundEmitter::updateEvent(uint32_t time) {
00129 ALint procs;
00130 ALint bufs;
00131 ALuint buffer;
00132
00133 alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &procs);
00134
00135 while (procs--) {
00136 alSourceUnqueueBuffers(m_source, 1, &buffer);
00137
00138 if (m_soundclip->getStream(m_streamid, buffer)) {
00139
00140 if (m_loop) {
00141
00142 m_soundclip->setStreamPos(m_streamid, SD_BYTE_POS, 0);
00143 m_soundclip->getStream(m_streamid, buffer);
00144 } else {
00145
00146
00147 alGetSourcei(m_source, AL_BUFFERS_QUEUED, &bufs);
00148 if (bufs == 0) {
00149 setPeriod(-1);
00150 alSourceStop(m_source);
00151 if(m_callback) {
00152 m_callback();
00153 }
00154 }
00155 continue;
00156 }
00157 }
00158 alSourceQueueBuffers(m_source, 1, &buffer);
00159 }
00160
00161 CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error while streaming")
00162 }
00163
00164 void SoundEmitter::setLooping(bool loop) {
00165 if (m_soundclip) {
00166 if (!m_soundclip->isStream()) {
00167 alSourcei(m_source, AL_LOOPING, loop ? AL_TRUE : AL_FALSE);
00168 } else {
00169 alSourcei(m_source, AL_LOOPING, AL_FALSE);
00170 }
00171 }
00172 m_loop = loop;
00173 }
00174
00175 void SoundEmitter::play() {
00176 if (m_soundclip) {
00177 alSourcePlay(m_source);
00178 if (m_soundclip->isStream()) {
00179 setPeriod(5000);
00180 }
00181 }
00182 }
00183
00184 void SoundEmitter::stop() {
00185 if (m_soundclip) {
00186 alSourceStop(m_source);
00187
00188 if (m_soundclip->isStream()) {
00189 setPeriod(-1);
00190 setCursor(SD_BYTE_POS, 0);
00191 } else {
00192 alSourceRewind(m_source);
00193 }
00194 }
00195 }
00196
00197 void SoundEmitter::setCursor(SoundPositionType type, float value) {
00198 if (!m_soundclip) {
00199 return;
00200 }
00201
00202 ALint state = 0;
00203
00204 if (!m_soundclip->isStream()) {
00205 switch(type) {
00206 case SD_BYTE_POS:
00207 alSourcef(m_source, AL_BYTE_OFFSET, value);
00208 break;
00209 case SD_SAMPLE_POS:
00210 alSourcef(m_source, AL_SAMPLE_OFFSET, value);
00211 break;
00212 case SD_TIME_POS:
00213 alSourcef(m_source, AL_SEC_OFFSET, value);
00214 break;
00215 }
00216
00217 CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error setting cursor position")
00218 }
00219 else {
00220 alGetSourcei(m_source, AL_SOURCE_STATE, &state);
00221
00222 if (state == AL_PLAYING || AL_PAUSED) {
00223 setPeriod(-1);
00224 alSourceStop(m_source);
00225 }
00226
00227 m_soundclip->setStreamPos(m_streamid, type, value);
00228
00229
00230 alSourcei(m_source, AL_BUFFER, 0);
00231
00232
00233 m_soundclip->acquireStream(m_streamid);
00234 alSourceQueueBuffers(m_source, BUFFER_NUM, m_soundclip->getBuffers(m_streamid));
00235
00236 if (state == AL_PLAYING) {
00237 setPeriod(5000);
00238 alSourcePlay(m_source);
00239 }
00240
00241 CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error setting stream cursor position")
00242 }
00243 }
00244
00245 float SoundEmitter::getCursor(SoundPositionType type) {
00246 if (!m_soundclip) {
00247 return 0.0f;
00248 }
00249
00250 ALfloat pos = 0.0f;
00251
00252 switch(type) {
00253 case SD_BYTE_POS:
00254 alGetSourcef(m_source, AL_BYTE_OFFSET, &pos);
00255 break;
00256 case SD_SAMPLE_POS:
00257 alGetSourcef(m_source, AL_SAMPLE_OFFSET, &pos);
00258 break;
00259 case SD_TIME_POS:
00260 alGetSourcef(m_source, AL_SEC_OFFSET, &pos);
00261 break;
00262 }
00263
00264 if (m_soundclip->isStream()) {
00265 pos += m_soundclip->getStreamPos(m_streamid, type);
00266 }
00267
00268 CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error getting cursor")
00269
00270 return pos;
00271 }
00272 }