comparison engine/core/audio/soundemitter.cpp @ 0:4a0efb7baf70

* Datasets becomes the new trunk and retires after that :-)
author mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222
date Sun, 29 Jun 2008 18:44:17 +0000
parents
children 90005975cdbb
comparison
equal deleted inserted replaced
-1:000000000000 0:4a0efb7baf70
1 /***************************************************************************
2 * Copyright (C) 2005-2008 by the FIFE Team *
3 * http://www.fifengine.de *
4 * This file is part of FIFE. *
5 * *
6 * FIFE is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
20 ***************************************************************************/
21
22 // Standard C++ library includes
23
24 // Platform specific includes
25
26 // 3rd party library includes
27
28 // FIFE includes
29 // These includes are split up in two parts, separated by one empty line
30 // First block: files included from the FIFE root src directory
31 // Second block: files included from the same folder
32 #include "util/log/logger.h"
33 #include "util/time/timemanager.h"
34 #include "util/base/exception.h"
35 #include "soundemitter.h"
36 #include "soundmanager.h"
37 #include "soundclippool.h"
38
39 namespace FIFE {
40 static Logger _log(LM_AUDIO);
41
42 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),
43 m_emitterid(uid), m_loop(false) {
44 if (!m_manager->isActive()) {
45 return;
46 }
47
48 TimeManager::instance()->registerEvent(this);
49 setPeriod(-1);
50 alGenSources(1, &m_source);
51
52 CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error creating source")
53 }
54
55 SoundEmitter::~SoundEmitter() {
56 if (!m_manager->isActive()) {
57 return;
58 }
59
60 setPeriod(-1);
61 TimeManager::instance()->unregisterEvent(this);
62 reset();
63 alDeleteSources(1, &m_source);
64 }
65
66 void SoundEmitter::reset(bool defaultall) {
67 if (m_soundclip != NULL) {
68
69 setPeriod(-1);
70 alSourceStop(m_source);
71
72 // Release all buffers
73 alSourcei(m_source, AL_BUFFER, AL_NONE);
74 alGetError();
75
76 if (m_soundclip->isStream()) {
77 m_soundclip->quitStreaming(m_streamid);
78 }
79
80 // release the soundclip
81 m_pool->release(m_soundclipid, true);
82 m_soundclip = NULL;
83
84 // default source properties
85 if (defaultall) {
86 setPosition(0.0f, 0.0f, 0.0f);
87 setVelocity(0.0f, 0.0f, 0.0f);
88 setGain(1.0f);
89 setPositioning(false);
90 alSourcei(m_source, AL_LOOPING, AL_FALSE);
91 }
92 }
93 }
94
95 void SoundEmitter::release() {
96 m_manager->releaseEmitter(m_emitterid);
97 }
98
99 void SoundEmitter::setSoundClip(unsigned int sound_id) {
100 m_soundclipid = sound_id;
101 m_soundclip = &(m_pool->getSoundClip(m_soundclipid));
102 m_soundclip->addRef();
103
104 attachSoundClip();
105 }
106
107 void SoundEmitter::attachSoundClip() {
108 if (!m_soundclip->isStream()) {
109 // non-streaming
110 alSourceQueueBuffers(m_source, m_soundclip->countBuffers(), m_soundclip->getBuffers());
111 alSourcei(m_source, AL_LOOPING, m_loop ? AL_TRUE : AL_FALSE);
112
113 } else {
114 // streaming
115 m_streamid = m_soundclip->beginStreaming();
116 m_soundclip->acquireStream(m_streamid);
117
118 // queue initial buffers
119 alSourceQueueBuffers(m_source, BUFFER_NUM, m_soundclip->getBuffers(m_streamid));
120 alSourcei(m_source, AL_LOOPING, AL_FALSE);
121 }
122
123 CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error attaching sound clip")
124 }
125
126 void SoundEmitter::updateEvent(unsigned long time) {
127 ALint procs;
128 ALint bufs;
129 ALuint buffer;
130
131 alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &procs);
132
133 while (procs--) {
134 alSourceUnqueueBuffers(m_source, 1, &buffer);
135
136 if (m_soundclip->getStream(m_streamid, buffer)) {
137 // EOF!
138 if (m_loop) {
139 // play again from the beginning
140 m_soundclip->setStreamPos(m_streamid, SD_BYTE_POS, 0);
141 m_soundclip->getStream(m_streamid, buffer);
142 } else {
143
144 // check if the playback has been finished
145 alGetSourcei(m_source, AL_BUFFERS_QUEUED, &bufs);
146 if (bufs == 0) {
147 setPeriod(-1);
148 alSourceStop(m_source);
149 }
150 continue;
151 }
152 }
153 alSourceQueueBuffers(m_source, 1, &buffer);
154 }
155
156 CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error while streaming")
157 }
158
159 void SoundEmitter::setLooping(bool loop) {
160 if (m_soundclip) {
161 if (!m_soundclip->isStream()) {
162 alSourcei(m_source, AL_LOOPING, loop ? AL_TRUE : AL_FALSE);
163 } else {
164 alSourcei(m_source, AL_LOOPING, AL_FALSE);
165 }
166 }
167 m_loop = loop;
168 }
169
170 void SoundEmitter::play() {
171 if (m_soundclip) {
172 alSourcePlay(m_source);
173 if (m_soundclip->isStream()) {
174 setPeriod(5000);
175 }
176 }
177 }
178
179 void SoundEmitter::stop() {
180 if (m_soundclip) {
181 alSourceStop(m_source);
182
183 if (m_soundclip->isStream()) {
184 setPeriod(-1);
185 setCursor(SD_BYTE_POS, 0);
186 } else {
187 alSourceRewind(m_source);
188 }
189 }
190 }
191
192 void SoundEmitter::setCursor(SoundPositionType type, float value) {
193 if (!m_soundclip) {
194 return;
195 }
196
197 ALint state = 0;
198
199 if (!m_soundclip->isStream()) {
200 switch(type) {
201 case SD_BYTE_POS:
202 alSourcef(m_source, AL_BYTE_OFFSET, value);
203 break;
204 case SD_SAMPLE_POS:
205 alSourcef(m_source, AL_SAMPLE_OFFSET, value);
206 break;
207 case SD_TIME_POS:
208 alSourcef(m_source, AL_SEC_OFFSET, value);
209 break;
210 }
211
212 CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error setting cursor position")
213 }
214 else {
215 alGetSourcei(m_source, AL_SOURCE_STATE, &state);
216
217 if (state == AL_PLAYING || AL_PAUSED) {
218 setPeriod(-1);
219 alSourceStop(m_source);
220 }
221
222 m_soundclip->setStreamPos(m_streamid, type, value);
223
224 // detach all buffers
225 alSourcei(m_source, AL_BUFFER, 0);
226
227 // queue the buffers with new data
228 m_soundclip->acquireStream(m_streamid);
229 alSourceQueueBuffers(m_source, BUFFER_NUM, m_soundclip->getBuffers(m_streamid));
230
231 if (state == AL_PLAYING) {
232 setPeriod(5000);
233 alSourcePlay(m_source);
234 }
235
236 CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error setting stream cursor position")
237 }
238 }
239
240 float SoundEmitter::getCursor(SoundPositionType type) {
241 if (!m_soundclip) {
242 return 0.0f;
243 }
244
245 ALfloat pos = 0.0f;
246
247 switch(type) {
248 case SD_BYTE_POS:
249 alGetSourcef(m_source, AL_BYTE_OFFSET, &pos);
250 break;
251 case SD_SAMPLE_POS:
252 alGetSourcef(m_source, AL_SAMPLE_OFFSET, &pos);
253 break;
254 case SD_TIME_POS:
255 alGetSourcef(m_source, AL_SEC_OFFSET, &pos);
256 break;
257 }
258
259 if (m_soundclip->isStream()) {
260 pos += m_soundclip->getStreamPos(m_streamid, type);
261 }
262
263 CHECK_OPENAL_LOG(_log, LogManager::LEVEL_ERROR, "error getting cursor")
264
265 return pos;
266 }
267 }