zenilib: zenilib/jni/external/zenilib/zeni_audio/Sound_Source_Pool.cpp Source File

zenilib 0.5.3.0

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Sound_Source_Pool.cpp
Go to the documentation of this file.
1 /* This file is part of the Zenipex Library (zenilib).
2 * Copyright (C) 2011 Mitchell Keith Bloch (bazald).
3 *
4 * zenilib is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * zenilib is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with zenilib. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <zeni_audio.h>
19
20 #include <algorithm>
21 #include <iostream>
22
23 #include <Zeni/Define.h>
24
25 #if defined(_DEBUG) && defined(_WINDOWS)
26 #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
27 #define new DEBUG_NEW
28 #endif
29
30 #include <Zeni/Singleton.hxx>
31
32 namespace Zeni {
33
34 template class Singleton<Sound_Source_Pool>;
35
36 Sound_Source_Pool * Sound_Source_Pool::create() {
37 return new Sound_Source_Pool;
38 }
39
40 Singleton<Sound_Source_Pool>::Uninit Sound_Source_Pool::g_uninit;
41 Singleton<Sound_Source_Pool>::Reinit Sound_Source_Pool::g_reinit;
42
43 Sound_Source_Pool::Sound_Source_Pool()
44 : m_replacement_policy(new Replacement_Policy()),
45 delete_m_replacement_policy(true),
46 m_muted(false)
47 {
48 Sound::remove_post_reinit(&g_reinit);
49
50 // Ensure Sound is initialized
51 Sound &sr = get_Sound();
52
53 sr.lend_pre_uninit(&g_uninit);
54 sr.lend_post_reinit(&g_reinit);
55 }
56
57 Sound_Source_Pool::~Sound_Source_Pool() {
58 Sound::remove_pre_uninit(&g_uninit);
59
60 purge();
61
62 for(std::vector<Sound_Source *>::iterator it = m_handles.begin();
63 it != m_handles.end();
64 ++it)
65 {
66 (*it)->m_remove_from_Pool_on_destruction = false;
67 }
68
69 if(delete_m_replacement_policy)
70 delete m_replacement_policy;
71 }
72
73 bool Sound_Source_Pool::Replacement_Policy::operator()(const Sound_Source &lhs, const Sound_Source &rhs) const {
74 if(&lhs == &rhs)
75 return false;
76
77 if(!rhs.is_playing())
78 return false;
79 if(!lhs.is_playing())
80 return true;
81
82 if(rhs.get_priority() < lhs.get_priority())
83 return false;
84 if(lhs.get_priority() < rhs.get_priority())
85 return true;
86
87 if(rhs.get_gain() < lhs.get_gain())
88 return false;
89 if(lhs.get_gain() < rhs.get_gain())
90 return true;
91
92 return lhs.get_unstop_time() < rhs.get_unstop_time();
93 }
94
95 bool Sound_Source_Pool::Replacement_Policy::operator()(const Sound_Source * const &lhs, const Sound_Source * const &rhs) const {
96 return (*this)(*lhs, *rhs);
97 }
98
99 Sound_Source_Pool::Positional_Replacement_Policy::Positional_Replacement_Policy(const Point3f &listener_position_)
100 : listener_position(listener_position_)
101 {
102 }
103
104 bool Sound_Source_Pool::Positional_Replacement_Policy::operator()(const Sound_Source &lhs, const Sound_Source &rhs) const {
105 if(&lhs == &rhs)
106 return false;
107
108 if(!rhs.is_playing())
109 return false;
110 if(!lhs.is_playing())
111 return true;
112
113 if(rhs.get_priority() < lhs.get_priority())
114 return false;
115 if(lhs.get_priority() < rhs.get_priority())
116 return true;
117
118 if(rhs.get_priority() < lhs.get_priority())
119 return false;
120 if(lhs.get_priority() < rhs.get_priority())
121 return true;
122
123 const float lhs_gain = lhs.calculate_gain(listener_position);
124 const float rhs_gain = rhs.calculate_gain(listener_position);
125
126 if(rhs_gain < lhs_gain)
127 return false;
128 if(lhs_gain < rhs_gain)
129 return true;
130
131 return lhs.get_unstop_time() < rhs.get_unstop_time();
132 }
133
134 const Sound_Source_Pool::Replacement_Policy & Sound_Source_Pool::get_Replacement_Policy() const {
135 return *m_replacement_policy;
136 }
137
138 void Sound_Source_Pool::give_Replacement_Policy(Sound_Source_Pool::Replacement_Policy * const &replacement_policy) {
139 set_Replacement_Policy(replacement_policy);
140 delete_m_replacement_policy = true;
141 }
142
143 void Sound_Source_Pool::lend_Replacement_Policy(Sound_Source_Pool::Replacement_Policy * const &replacement_policy) {
144 set_Replacement_Policy(replacement_policy);
145 delete_m_replacement_policy = false;
146 }
147
148 void Sound_Source_Pool::pause_all() {
149 for(std::vector<Sound_Source *>::iterator it = m_handles.begin();
150 it != m_handles.end();
151 ++it)
152 {
153 if((*it)->is_playing())
154 (*it)->pause();
155 }
156 }
157
158 void Sound_Source_Pool::unpause_all() {
159 for(std::vector<Sound_Source *>::iterator it = m_handles.begin();
160 it != m_handles.end();
161 ++it)
162 {
163 if((*it)->is_paused())
164 (*it)->play();
165 }
166 }
167
168 void Sound_Source_Pool::purge() {
169 for(std::vector<Sound_Source *>::iterator it = m_playing_and_destroying.begin();
170 it != m_playing_and_destroying.end();
171 ++it)
172 {
173 delete *it;
174 }
175 m_playing_and_destroying.clear();
176
177 destroy_all_hw();
178 }
179
180 static void sound_quicksort(
181 const std::vector<Sound_Source *>::iterator &begin,
182 const std::vector<Sound_Source *>::iterator &end,
183 const Sound_Source_Pool::Replacement_Policy &policy)
184 {
185 typedef std::vector<Sound_Source *>::difference_type diff_t;
186 const diff_t size = end - begin;
187
188 if(size < 2)
189 return;
190
191 std::vector<Sound_Source *> less, greater;
192 std::vector<Sound_Source *>::iterator pivot = begin + size / 2;
193 Sound_Source * const pivotValue = *pivot;
194
195 for(std::vector<Sound_Source *>::iterator x = begin; x != end; ++x)
196 if(x != pivot) {
197 if(policy(*x, pivotValue))
198 less.push_back(*x);
199 else
200 greater.push_back(*x);
201 }
202
203 const std::vector<Sound_Source *>::iterator less_end = std::copy(less.begin(), less.end(), begin);
204 *less_end = pivotValue;
205 const std::vector<Sound_Source *>::iterator greater_begin = less_end + 1;
206 std::copy(greater.begin(), greater.end(), greater_begin);
207
208 less.clear();
209 greater.clear();
210
211 sound_quicksort(begin, less_end, policy);
212 sound_quicksort(greater_begin, end, policy);
213 }
214
215 void Sound_Source_Pool::update() {
216 /*** Handle the playing and destroying ***/
217
218 std::vector<Sound_Source *> keepers;
219 keepers.reserve(m_playing_and_destroying.size());
220 for(std::vector<Sound_Source *>::iterator it = m_playing_and_destroying.begin();
221 it != m_playing_and_destroying.end();
222 ++it)
223 {
224 if((*it)->is_stopped()) {
225 ZENI_LOGD("Removing Sound_Source from Sound_Source_Pool");
226 delete *it;
227 }
228 else
229 keepers.push_back(*it);
230 }
231 m_playing_and_destroying.swap(keepers);
232
233 /*** If muted, skip the rest of the update ***/
234
235 if(m_muted)
236 return;
237
238 /*** Do the regular update ***/
239
240 std::vector<Sound_Source_HW *> unassigned_hw;
241 const size_t needed_hw = m_handles.size();
242 size_t given_hw = 0;
243
244 /*** Find out how much Sound_Source_HW is needed ***/
245
246 for(std::vector<Sound_Source *>::iterator it = m_handles.begin();
247 it != m_handles.end();
248 ++it)
249 {
250 if((*it)->is_assigned())
251 ++given_hw;
252 }
253
254 /*** Acquire more Sound_Source_HW if needed (and if possible) ***/
255
256 // ZENI_LOGD("Sound_Source_Pool has " + ulltoa(given_hw) + "/" + ulltoa(needed_hw));
257 while(needed_hw > given_hw
258 #ifdef TEST_NASTY_CONDITIONS
259 && given_hw < NASTY_SOUND_SOURCE_CAP
260 #endif
261 )
262 {
263 Sound_Source_HW * const sshw = Sound_Source_HW::Try_Construct();
264
265 if(sshw) {
266 ZENI_LOGD("Sound_Source_HW added to Sound_Source_Pool");
267 unassigned_hw.push_back(sshw);
268 ++given_hw;
269 }
270 else {
271 ZENI_LOGD("Failed to add Sound_Source_HW to Sound_Source_Pool");
272 break;
273 }
274 }
275
276 /*** Strip Sound_Source_HW from low priority 'Sound_Source's, as needed ***/
277
278 const size_t cut = needed_hw - given_hw;
279
280 if(cut) {
281 sound_quicksort(m_handles.begin(), m_handles.end(), *m_replacement_policy);
282
283 for(size_t i = 0; i != cut; ++i) {
284 Sound_Source &source = *m_handles[i];
285
286 if(source.is_assigned())
287 unassigned_hw.push_back(source.unassign());
288 }
289 }
290
291 /*** Assign Sound_Source_HW to high priority 'Sound_Source's ***/
292
293 std::vector<Sound_Source_HW *>::iterator jt = unassigned_hw.begin();
294
295 for(size_t i = cut; i != needed_hw; ++i) {
296 Sound_Source &source = *m_handles[i];
297
298 if(!source.is_assigned()) {
299 source.assign(**jt);
300 ++jt;
301 }
302 }
303 }
304
305 void Sound_Source_Pool::play_and_destroy(Sound_Source * const &sound_source) {
306 m_playing_and_destroying.push_back(sound_source);
307 sound_source->play();
308 }
309
310 void Sound_Source_Pool::set_Replacement_Policy(Sound_Source_Pool::Replacement_Policy * const &replacement_policy) {
311 assert(replacement_policy);
312
313 if(delete_m_replacement_policy)
314 delete m_replacement_policy;
315
316 m_replacement_policy = replacement_policy;
317 }
318
319 void Sound_Source_Pool::insert_Sound_Source(Sound_Source &sound_source) {
320 m_handles.push_back(&sound_source);
321 }
322
323 void Sound_Source_Pool::remove_Sound_Source(Sound_Source &sound_source) {
324 sound_source.stop();
325
326 if(sound_source.m_hw) {
327 delete sound_source.m_hw;
328 sound_source.m_hw = 0;
329 }
330
331 m_handles.erase(std::find(m_handles.begin(), m_handles.end(), &sound_source));
332 }
333
334 void Sound_Source_Pool::destroy_all_hw() {
335 for(std::vector<Sound_Source *>::iterator it = m_handles.begin();
336 it != m_handles.end();
337 ++it)
338 {
339 if((*it)->is_assigned()) {
340 Sound_Source_HW * hw = (*it)->unassign();
341 hw->stop();
342 delete hw;
343 }
344 }
345 }
346
347 Sound_Source_Pool & get_Sound_Source_Pool() {
348 return Sound_Source_Pool::get();
349 }
350
351 void play_sound(
352 const String &sound_name,
353 const float &pitch,
354 const float &gain,
355 const Point3f &position,
356 const Vector3f &velocity)
357 {
358 get_Sound_Source_Pool().play_and_destroy(new Sound_Source(get_Sounds()[sound_name], pitch, gain, position, velocity));
359 }
360
361 }
362
363 #include <Zeni/Undefine.h>
Zeni::Sound_Source_Pool::pause_all
void pause_all()
Pause all Sound_Sources.
Definition: Sound_Source_Pool.cpp:148
Zeni::get_Sounds
Sounds & get_Sounds()
Get access to the singleton.
Definition: Sounds.cpp:62
NASTY_SOUND_SOURCE_CAP
#define NASTY_SOUND_SOURCE_CAP
Definition: Define.h:130
Zeni::Sound_Source::get_gain
float get_gain() const
Get the gain.
Definition: Sound_Source.hxx:65
Zeni::get_Sound_Source_Pool
Sound_Source_Pool & get_Sound_Source_Pool()
Get access to the singleton.
Definition: Sound_Source_Pool.cpp:347
Zeni::Sound_Source_Pool::Replacement_Policy::operator()
virtual bool operator()(const Sound_Source &lhs, const Sound_Source &rhs) const
(Default) Priority Sort: Playing/Not-Playing, Priority, Gain, Recency
Definition: Sound_Source_Pool.cpp:73
Zeni::Sound_Source::get_priority
int get_priority() const
Get the Sound_Source&#39;s priority.
Definition: Sound_Source.hxx:60
x
EGLSurface EGLint x
Definition: eglext.h:293
Zeni::Sound_Source::get_unstop_time
Time_HQ get_unstop_time() const
Get the Time_HQ at which the Sound_Source was most recently played or unpaused.
Definition: Sound_Source.hxx:61
Zeni::Sound_Source_Pool::purge
void purge()
Purge all Sound_Source_HW and all playing_and_destroying (created by play_sound(...))
Definition: Sound_Source_Pool.cpp:168
Zeni::Sound_Source_Pool::Positional_Replacement_Policy::Positional_Replacement_Policy
Positional_Replacement_Policy(const Point3f &listener_position_)
Definition: Sound_Source_Pool.cpp:99
assert
#define assert(x)
Definition: SDL_malloc.c:1234
Undefine.h
Zeni::Singleton< Sound >::remove_post_reinit
static void remove_post_reinit(Event::Handler *const &handler)
Zeni::Sound_Source::play
void play()
Begin playing or unpause the Sound_Source.
Definition: Sound_Source.hxx:73
Zeni::Sound_Source_Pool::unpause_all
void unpause_all()
Unpause all paused Sound_Sources.
Definition: Sound_Source_Pool.cpp:158
Zeni::String
Definition: String.h:29
Zeni::Point3f
A 3D Point represented with floats.
Definition: Coordinate.h:133
Zeni::Sound_Source_HW
Plays Sound Data.
Definition: Sound_Source.h:69
Zeni::Sound_Source_Pool::update
void update()
Redistribute hardware Sound_Sources according to the Replacement_Policy. Newer Sound_Sources are impl...
Definition: Sound_Source_Pool.cpp:215
Zeni::Sound_Source
Plays Sound Data.
Definition: Sound_Source.h:147
Zeni::get_Sound
Sound & get_Sound()
Get access to the singleton.
Definition: Sound.cpp:220
Zeni::Sound_Source_Pool::play_sound
friend void play_sound(const String &sound_name, const float &pitch, const float &gain, const Point3f &position, const Vector3f &velocity)
Definition: Sound_Source_Pool.cpp:351
Zeni::Vector3f
A Featureful 3-Space Vector Class.
Definition: Vector3f.h:58
Zeni::Singleton< Sound >::remove_pre_uninit
static void remove_pre_uninit(Event::Handler *const &handler)
Zeni::Sound_Source_Pool::give_Replacement_Policy
void give_Replacement_Policy(Replacement_Policy *const &replacement_policy)
Give the Sound_Source_Pool a new Replacement_Policy (which it will delete later)
Definition: Sound_Source_Pool.cpp:138
Define.h
Singleton.hxx
true
#define true
Definition: ftrandom.c:49
Zeni::Singleton< Sound_Source_Pool >::get
static Sound_Source_Pool & get()
ZENI_LOGD
void ZENI_LOGD(const Zeni::String &str)
Definition: Android.h:50
Zeni::Sound_Source_Pool::Positional_Replacement_Policy::operator()
virtual bool operator()(const Sound_Source &lhs, const Sound_Source &rhs) const
Positional Priority Sort: Playing/Not-Playing, Priority, Computed Gain, Recency.
Definition: Sound_Source_Pool.cpp:104
Zeni::Sound_Source::calculate_gain
float calculate_gain(const Point3f &listener_position) const
Get the actual volume gain, given gain+position+near_clamp+far_clamp+rolloff.
Definition: Sound_Source.cpp:611
Zeni::Sound_Source_Pool
This class manages Sound_Sources.
Definition: Sound_Source_Pool.h:53
Zeni::Sound_Source_Pool::Replacement_Policy
Definition: Sound_Source_Pool.h:83
Zeni::Sound_Source::is_playing
bool is_playing() const
Check to see if the Sound_Source is playing.
Definition: Sound_Source.hxx:77
end
GLuint GLuint end
Definition: glew.h:1239
Zeni::Sound_Source_Pool::get_Replacement_Policy
const Replacement_Policy & get_Replacement_Policy() const
Get the Replacement_Policy.
Definition: Sound_Source_Pool.cpp:134
Zeni::sound_quicksort
static void sound_quicksort(const std::vector< Sound_Source * >::iterator &begin, const std::vector< Sound_Source * >::iterator &end, const Sound_Source_Pool::Replacement_Policy &policy)
Definition: Sound_Source_Pool.cpp:180
i
int i
Definition: pngrutil.c:1377
source
GLsizei GLsizei GLchar * source
Definition: gl2ext.h:994
Zeni::Sound_Source::is_assigned
bool is_assigned() const
Check to see if the Sound_Source is assigned to actual hardware.
Definition: Sound_Source.hxx:81
zeni_audio.h
false
#define false
Definition: ftrandom.c:50
Zeni::Sound_Source_Pool::lend_Replacement_Policy
void lend_Replacement_Policy(Replacement_Policy *const &replacement_policy)
Give the Sound_Source_Pool a new Replacement_Policy (which it will NEVER delete)
Definition: Sound_Source_Pool.cpp:143
size
GLsizei size
Definition: gl2ext.h:1467
Zeni::Sound_Source_Pool::Sound_Source
friend class Sound_Source
Definition: Sound_Source_Pool.h:55