Use std::isfinite instead of isfinite
[openal-soft.git] / OpenAL32 / alListener.cpp
blobd60f5254a4dd8f8cc62c93032560e5d5a944f12c
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2000 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library 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 GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <cmath>
25 #include "alMain.h"
26 #include "alcontext.h"
27 #include "alu.h"
28 #include "alError.h"
29 #include "alListener.h"
30 #include "alSource.h"
32 #define DO_UPDATEPROPS() do { \
33 if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) \
34 UpdateListenerProps(context); \
35 else \
36 ATOMIC_STORE(&listener->PropsClean, AL_FALSE, almemory_order_release);\
37 } while(0)
40 AL_API ALvoid AL_APIENTRY alListenerf(ALenum param, ALfloat value)
42 ALlistener *listener;
43 ALCcontext *context;
45 context = GetContextRef();
46 if(!context) return;
48 listener = &context->Listener;
49 almtx_lock(&context->PropLock);
50 switch(param)
52 case AL_GAIN:
53 if(!(value >= 0.0f && std::isfinite(value)))
54 SETERR_GOTO(context, AL_INVALID_VALUE, done, "Listener gain out of range");
55 listener->Gain = value;
56 DO_UPDATEPROPS();
57 break;
59 case AL_METERS_PER_UNIT:
60 if(!(value >= AL_MIN_METERS_PER_UNIT && value <= AL_MAX_METERS_PER_UNIT))
61 SETERR_GOTO(context, AL_INVALID_VALUE, done, "Listener meters per unit out of range");
62 context->MetersPerUnit = value;
63 if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
64 UpdateContextProps(context);
65 else
66 ATOMIC_STORE(&context->PropsClean, AL_FALSE, almemory_order_release);
67 break;
69 default:
70 alSetError(context, AL_INVALID_ENUM, "Invalid listener float property");
73 done:
74 almtx_unlock(&context->PropLock);
75 ALCcontext_DecRef(context);
79 AL_API ALvoid AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3)
81 ALlistener *listener;
82 ALCcontext *context;
84 context = GetContextRef();
85 if(!context) return;
87 listener = &context->Listener;
88 almtx_lock(&context->PropLock);
89 switch(param)
91 case AL_POSITION:
92 if(!(std::isfinite(value1) && std::isfinite(value2) && std::isfinite(value3)))
93 SETERR_GOTO(context, AL_INVALID_VALUE, done, "Listener position out of range");
94 listener->Position[0] = value1;
95 listener->Position[1] = value2;
96 listener->Position[2] = value3;
97 DO_UPDATEPROPS();
98 break;
100 case AL_VELOCITY:
101 if(!(std::isfinite(value1) && std::isfinite(value2) && std::isfinite(value3)))
102 SETERR_GOTO(context, AL_INVALID_VALUE, done, "Listener velocity out of range");
103 listener->Velocity[0] = value1;
104 listener->Velocity[1] = value2;
105 listener->Velocity[2] = value3;
106 DO_UPDATEPROPS();
107 break;
109 default:
110 alSetError(context, AL_INVALID_ENUM, "Invalid listener 3-float property");
113 done:
114 almtx_unlock(&context->PropLock);
115 ALCcontext_DecRef(context);
119 AL_API ALvoid AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values)
121 ALlistener *listener;
122 ALCcontext *context;
124 if(values)
126 switch(param)
128 case AL_GAIN:
129 case AL_METERS_PER_UNIT:
130 alListenerf(param, values[0]);
131 return;
133 case AL_POSITION:
134 case AL_VELOCITY:
135 alListener3f(param, values[0], values[1], values[2]);
136 return;
140 context = GetContextRef();
141 if(!context) return;
143 listener = &context->Listener;
144 almtx_lock(&context->PropLock);
145 if(!values) SETERR_GOTO(context, AL_INVALID_VALUE, done, "NULL pointer");
146 switch(param)
148 case AL_ORIENTATION:
149 if(!(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2]) &&
150 std::isfinite(values[3]) && std::isfinite(values[4]) && std::isfinite(values[5])))
151 SETERR_GOTO(context, AL_INVALID_VALUE, done, "Listener orientation out of range");
152 /* AT then UP */
153 listener->Forward[0] = values[0];
154 listener->Forward[1] = values[1];
155 listener->Forward[2] = values[2];
156 listener->Up[0] = values[3];
157 listener->Up[1] = values[4];
158 listener->Up[2] = values[5];
159 DO_UPDATEPROPS();
160 break;
162 default:
163 alSetError(context, AL_INVALID_ENUM, "Invalid listener float-vector property");
166 done:
167 almtx_unlock(&context->PropLock);
168 ALCcontext_DecRef(context);
172 AL_API ALvoid AL_APIENTRY alListeneri(ALenum param, ALint UNUSED(value))
174 ALCcontext *context;
176 context = GetContextRef();
177 if(!context) return;
179 almtx_lock(&context->PropLock);
180 switch(param)
182 default:
183 alSetError(context, AL_INVALID_ENUM, "Invalid listener integer property");
185 almtx_unlock(&context->PropLock);
187 ALCcontext_DecRef(context);
191 AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, ALint value3)
193 ALCcontext *context;
195 switch(param)
197 case AL_POSITION:
198 case AL_VELOCITY:
199 alListener3f(param, (ALfloat)value1, (ALfloat)value2, (ALfloat)value3);
200 return;
203 context = GetContextRef();
204 if(!context) return;
206 almtx_lock(&context->PropLock);
207 switch(param)
209 default:
210 alSetError(context, AL_INVALID_ENUM, "Invalid listener 3-integer property");
212 almtx_unlock(&context->PropLock);
214 ALCcontext_DecRef(context);
218 AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values)
220 ALCcontext *context;
222 if(values)
224 ALfloat fvals[6];
225 switch(param)
227 case AL_POSITION:
228 case AL_VELOCITY:
229 alListener3f(param, (ALfloat)values[0], (ALfloat)values[1], (ALfloat)values[2]);
230 return;
232 case AL_ORIENTATION:
233 fvals[0] = (ALfloat)values[0];
234 fvals[1] = (ALfloat)values[1];
235 fvals[2] = (ALfloat)values[2];
236 fvals[3] = (ALfloat)values[3];
237 fvals[4] = (ALfloat)values[4];
238 fvals[5] = (ALfloat)values[5];
239 alListenerfv(param, fvals);
240 return;
244 context = GetContextRef();
245 if(!context) return;
247 almtx_lock(&context->PropLock);
248 if(!values)
249 alSetError(context, AL_INVALID_VALUE, "NULL pointer");
250 else switch(param)
252 default:
253 alSetError(context, AL_INVALID_ENUM, "Invalid listener integer-vector property");
255 almtx_unlock(&context->PropLock);
257 ALCcontext_DecRef(context);
261 AL_API ALvoid AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value)
263 ALCcontext *context;
265 context = GetContextRef();
266 if(!context) return;
268 almtx_lock(&context->PropLock);
269 if(!value)
270 alSetError(context, AL_INVALID_VALUE, "NULL pointer");
271 else switch(param)
273 case AL_GAIN:
274 *value = context->Listener.Gain;
275 break;
277 case AL_METERS_PER_UNIT:
278 *value = context->MetersPerUnit;
279 break;
281 default:
282 alSetError(context, AL_INVALID_ENUM, "Invalid listener float property");
284 almtx_unlock(&context->PropLock);
286 ALCcontext_DecRef(context);
290 AL_API ALvoid AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
292 ALCcontext *context;
294 context = GetContextRef();
295 if(!context) return;
297 almtx_lock(&context->PropLock);
298 if(!value1 || !value2 || !value3)
299 alSetError(context, AL_INVALID_VALUE, "NULL pointer");
300 else switch(param)
302 case AL_POSITION:
303 *value1 = context->Listener.Position[0];
304 *value2 = context->Listener.Position[1];
305 *value3 = context->Listener.Position[2];
306 break;
308 case AL_VELOCITY:
309 *value1 = context->Listener.Velocity[0];
310 *value2 = context->Listener.Velocity[1];
311 *value3 = context->Listener.Velocity[2];
312 break;
314 default:
315 alSetError(context, AL_INVALID_ENUM, "Invalid listener 3-float property");
317 almtx_unlock(&context->PropLock);
319 ALCcontext_DecRef(context);
323 AL_API ALvoid AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values)
325 ALCcontext *context;
327 switch(param)
329 case AL_GAIN:
330 case AL_METERS_PER_UNIT:
331 alGetListenerf(param, values);
332 return;
334 case AL_POSITION:
335 case AL_VELOCITY:
336 alGetListener3f(param, values+0, values+1, values+2);
337 return;
340 context = GetContextRef();
341 if(!context) return;
343 almtx_lock(&context->PropLock);
344 if(!values)
345 alSetError(context, AL_INVALID_VALUE, "NULL pointer");
346 else switch(param)
348 case AL_ORIENTATION:
349 // AT then UP
350 values[0] = context->Listener.Forward[0];
351 values[1] = context->Listener.Forward[1];
352 values[2] = context->Listener.Forward[2];
353 values[3] = context->Listener.Up[0];
354 values[4] = context->Listener.Up[1];
355 values[5] = context->Listener.Up[2];
356 break;
358 default:
359 alSetError(context, AL_INVALID_ENUM, "Invalid listener float-vector property");
361 almtx_unlock(&context->PropLock);
363 ALCcontext_DecRef(context);
367 AL_API ALvoid AL_APIENTRY alGetListeneri(ALenum param, ALint *value)
369 ALCcontext *context;
371 context = GetContextRef();
372 if(!context) return;
374 almtx_lock(&context->PropLock);
375 if(!value)
376 alSetError(context, AL_INVALID_VALUE, "NULL pointer");
377 else switch(param)
379 default:
380 alSetError(context, AL_INVALID_ENUM, "Invalid listener integer property");
382 almtx_unlock(&context->PropLock);
384 ALCcontext_DecRef(context);
388 AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *value2, ALint *value3)
390 ALCcontext *context;
392 context = GetContextRef();
393 if(!context) return;
395 almtx_lock(&context->PropLock);
396 if(!value1 || !value2 || !value3)
397 alSetError(context, AL_INVALID_VALUE, "NULL pointer");
398 else switch(param)
400 case AL_POSITION:
401 *value1 = (ALint)context->Listener.Position[0];
402 *value2 = (ALint)context->Listener.Position[1];
403 *value3 = (ALint)context->Listener.Position[2];
404 break;
406 case AL_VELOCITY:
407 *value1 = (ALint)context->Listener.Velocity[0];
408 *value2 = (ALint)context->Listener.Velocity[1];
409 *value3 = (ALint)context->Listener.Velocity[2];
410 break;
412 default:
413 alSetError(context, AL_INVALID_ENUM, "Invalid listener 3-integer property");
415 almtx_unlock(&context->PropLock);
417 ALCcontext_DecRef(context);
421 AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint* values)
423 ALCcontext *context;
425 switch(param)
427 case AL_POSITION:
428 case AL_VELOCITY:
429 alGetListener3i(param, values+0, values+1, values+2);
430 return;
433 context = GetContextRef();
434 if(!context) return;
436 almtx_lock(&context->PropLock);
437 if(!values)
438 alSetError(context, AL_INVALID_VALUE, "NULL pointer");
439 else switch(param)
441 case AL_ORIENTATION:
442 // AT then UP
443 values[0] = (ALint)context->Listener.Forward[0];
444 values[1] = (ALint)context->Listener.Forward[1];
445 values[2] = (ALint)context->Listener.Forward[2];
446 values[3] = (ALint)context->Listener.Up[0];
447 values[4] = (ALint)context->Listener.Up[1];
448 values[5] = (ALint)context->Listener.Up[2];
449 break;
451 default:
452 alSetError(context, AL_INVALID_ENUM, "Invalid listener integer-vector property");
454 almtx_unlock(&context->PropLock);
456 ALCcontext_DecRef(context);
460 void UpdateListenerProps(ALCcontext *context)
462 ALlistener *listener{&context->Listener};
463 struct ALlistenerProps *props;
465 /* Get an unused proprty container, or allocate a new one as needed. */
466 props = context->FreeListenerProps.load(std::memory_order_acquire);
467 if(!props)
468 props = static_cast<ALlistenerProps*>(al_calloc(16, sizeof(*props)));
469 else
471 struct ALlistenerProps *next;
472 do {
473 next = props->next.load(std::memory_order_relaxed);
474 } while(context->FreeListenerProps.compare_exchange_weak(props, next,
475 std::memory_order_seq_cst, std::memory_order_acquire) == 0);
478 /* Copy in current property values. */
479 props->Position[0] = listener->Position[0];
480 props->Position[1] = listener->Position[1];
481 props->Position[2] = listener->Position[2];
483 props->Velocity[0] = listener->Velocity[0];
484 props->Velocity[1] = listener->Velocity[1];
485 props->Velocity[2] = listener->Velocity[2];
487 props->Forward[0] = listener->Forward[0];
488 props->Forward[1] = listener->Forward[1];
489 props->Forward[2] = listener->Forward[2];
490 props->Up[0] = listener->Up[0];
491 props->Up[1] = listener->Up[1];
492 props->Up[2] = listener->Up[2];
494 props->Gain = listener->Gain;
496 /* Set the new container for updating internal parameters. */
497 props = listener->Update.exchange(props, std::memory_order_acq_rel);
498 if(props)
500 /* If there was an unused update container, put it back in the
501 * freelist.
503 AtomicReplaceHead(context->FreeListenerProps, props);