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
33 #include "alc/context.h"
34 #include "alnumeric.h"
36 #include "direct_defs.h"
42 inline void UpdateProps(ALCcontext
*context
)
44 if(!context
->mDeferUpdates
)
46 UpdateContextProps(context
);
49 context
->mPropsDirty
= true;
52 inline void CommitAndUpdateProps(ALCcontext
*context
)
54 if(!context
->mDeferUpdates
)
57 if(context
->eaxNeedsCommit())
59 context
->mPropsDirty
= true;
60 context
->applyAllUpdates();
64 UpdateContextProps(context
);
67 context
->mPropsDirty
= true;
72 AL_API
DECL_FUNC2(void, alListenerf
, ALenum
,param
, ALfloat
,value
)
73 FORCE_ALIGN
void AL_APIENTRY
alListenerfDirect(ALCcontext
*context
, ALenum param
, ALfloat value
) noexcept
75 ALlistener
&listener
= context
->mListener
;
76 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
80 if(!(value
>= 0.0f
&& std::isfinite(value
)))
81 throw al::context_error
{AL_INVALID_VALUE
, "Listener gain out of range"};
82 listener
.Gain
= value
;
86 case AL_METERS_PER_UNIT
:
87 if(!(value
>= AL_MIN_METERS_PER_UNIT
&& value
<= AL_MAX_METERS_PER_UNIT
))
88 throw al::context_error
{AL_INVALID_VALUE
, "Listener meters per unit out of range"};
89 listener
.mMetersPerUnit
= value
;
93 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener float property 0x%x", param
};
95 catch(al::context_error
& e
) {
96 context
->setError(e
.errorCode(), "%s", e
.what());
99 AL_API
DECL_FUNC4(void, alListener3f
, ALenum
,param
, ALfloat
,value1
, ALfloat
,value2
, ALfloat
,value3
)
100 FORCE_ALIGN
void AL_APIENTRY
alListener3fDirect(ALCcontext
*context
, ALenum param
, ALfloat value1
,
101 ALfloat value2
, ALfloat value3
) noexcept
103 ALlistener
&listener
= context
->mListener
;
104 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
108 if(!(std::isfinite(value1
) && std::isfinite(value2
) && std::isfinite(value3
)))
109 throw al::context_error
{AL_INVALID_VALUE
, "Listener position out of range"};
110 listener
.Position
[0] = value1
;
111 listener
.Position
[1] = value2
;
112 listener
.Position
[2] = value3
;
113 CommitAndUpdateProps(context
);
117 if(!(std::isfinite(value1
) && std::isfinite(value2
) && std::isfinite(value3
)))
118 throw al::context_error
{AL_INVALID_VALUE
, "Listener velocity out of range"};
119 listener
.Velocity
[0] = value1
;
120 listener
.Velocity
[1] = value2
;
121 listener
.Velocity
[2] = value3
;
122 CommitAndUpdateProps(context
);
125 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener 3-float property 0x%x", param
};
127 catch(al::context_error
& e
) {
128 context
->setError(e
.errorCode(), "%s", e
.what());
131 AL_API
DECL_FUNC2(void, alListenerfv
, ALenum
,param
, const ALfloat
*,values
)
132 FORCE_ALIGN
void AL_APIENTRY
alListenerfvDirect(ALCcontext
*context
, ALenum param
,
133 const ALfloat
*values
) noexcept
136 throw al::context_error
{AL_INVALID_VALUE
, "NULL pointer"};
141 case AL_METERS_PER_UNIT
:
142 alListenerfDirect(context
, param
, *values
);
147 auto vals
= al::span
<const float,3>{values
, 3_uz
};
148 alListener3fDirect(context
, param
, vals
[0], vals
[1], vals
[2]);
152 ALlistener
&listener
= context
->mListener
;
153 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
157 auto vals
= al::span
<const float,6>{values
, 6_uz
};
158 if(!std::all_of(vals
.cbegin(), vals
.cend(), [](float f
) { return std::isfinite(f
); }))
159 return context
->setError(AL_INVALID_VALUE
, "Listener orientation out of range");
161 std::copy_n(vals
.cbegin(), 3, listener
.OrientAt
.begin());
162 std::copy_n(vals
.cbegin()+3, 3, listener
.OrientUp
.begin());
163 CommitAndUpdateProps(context
);
166 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener float-vector property 0x%x", param
};
168 catch(al::context_error
& e
) {
169 context
->setError(e
.errorCode(), "%s", e
.what());
173 AL_API
DECL_FUNC2(void, alListeneri
, ALenum
,param
, ALint
,value
)
174 FORCE_ALIGN
void AL_APIENTRY
alListeneriDirect(ALCcontext
*context
, ALenum param
, ALint
/*value*/) noexcept
176 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
177 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener integer property 0x%x", param
};
179 catch(al::context_error
& e
) {
180 context
->setError(e
.errorCode(), "%s", e
.what());
183 AL_API
DECL_FUNC4(void, alListener3i
, ALenum
,param
, ALint
,value1
, ALint
,value2
, ALint
,value3
)
184 FORCE_ALIGN
void AL_APIENTRY
alListener3iDirect(ALCcontext
*context
, ALenum param
, ALint value1
,
185 ALint value2
, ALint value3
) noexcept
191 alListener3fDirect(context
, param
, static_cast<ALfloat
>(value1
),
192 static_cast<ALfloat
>(value2
), static_cast<ALfloat
>(value3
));
196 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
197 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener 3-integer property 0x%x", param
};
199 catch(al::context_error
& e
) {
200 context
->setError(e
.errorCode(), "%s", e
.what());
203 AL_API
DECL_FUNC2(void, alListeneriv
, ALenum
,param
, const ALint
*,values
)
204 FORCE_ALIGN
void AL_APIENTRY
alListenerivDirect(ALCcontext
*context
, ALenum param
,
205 const ALint
*values
) noexcept
208 throw al::context_error
{AL_INVALID_VALUE
, "NULL pointer"};
210 al::span
<const ALint
> vals
;
215 vals
= {values
, 3_uz
};
216 alListener3fDirect(context
, param
, static_cast<ALfloat
>(vals
[0]),
217 static_cast<ALfloat
>(vals
[1]), static_cast<ALfloat
>(vals
[2]));
221 vals
= {values
, 6_uz
};
222 const std::array fvals
{static_cast<ALfloat
>(vals
[0]), static_cast<ALfloat
>(vals
[1]),
223 static_cast<ALfloat
>(vals
[2]), static_cast<ALfloat
>(vals
[3]),
224 static_cast<ALfloat
>(vals
[4]), static_cast<ALfloat
>(vals
[5]),
226 alListenerfvDirect(context
, param
, fvals
.data());
230 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
231 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener integer-vector property 0x%x",
234 catch(al::context_error
& e
) {
235 context
->setError(e
.errorCode(), "%s", e
.what());
239 AL_API
DECL_FUNC2(void, alGetListenerf
, ALenum
,param
, ALfloat
*,value
)
240 FORCE_ALIGN
void AL_APIENTRY
alGetListenerfDirect(ALCcontext
*context
, ALenum param
,
241 ALfloat
*value
) noexcept
244 throw al::context_error
{AL_INVALID_VALUE
, "NULL pointer"};
246 ALlistener
&listener
= context
->mListener
;
247 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
250 case AL_GAIN
: *value
= listener
.Gain
; return;
251 case AL_METERS_PER_UNIT
: *value
= listener
.mMetersPerUnit
; return;
253 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener float property 0x%x", param
};
255 catch(al::context_error
& e
) {
256 context
->setError(e
.errorCode(), "%s", e
.what());
259 AL_API
DECL_FUNC4(void, alGetListener3f
, ALenum
,param
, ALfloat
*,value1
, ALfloat
*,value2
, ALfloat
*,value3
)
260 FORCE_ALIGN
void AL_APIENTRY
alGetListener3fDirect(ALCcontext
*context
, ALenum param
,
261 ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
) noexcept
263 if(!value1
|| !value2
|| !value3
)
264 throw al::context_error
{AL_INVALID_VALUE
, "NULL pointer"};
266 ALlistener
&listener
= context
->mListener
;
267 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
271 *value1
= listener
.Position
[0];
272 *value2
= listener
.Position
[1];
273 *value3
= listener
.Position
[2];
277 *value1
= listener
.Velocity
[0];
278 *value2
= listener
.Velocity
[1];
279 *value3
= listener
.Velocity
[2];
282 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener 3-float property 0x%x", param
};
284 catch(al::context_error
& e
) {
285 context
->setError(e
.errorCode(), "%s", e
.what());
288 AL_API
DECL_FUNC2(void, alGetListenerfv
, ALenum
,param
, ALfloat
*,values
)
289 FORCE_ALIGN
void AL_APIENTRY
alGetListenerfvDirect(ALCcontext
*context
, ALenum param
,
290 ALfloat
*values
) noexcept
293 throw al::context_error
{AL_INVALID_VALUE
, "NULL pointer"};
298 case AL_METERS_PER_UNIT
:
299 alGetListenerfDirect(context
, param
, values
);
304 auto vals
= al::span
<ALfloat
,3>{values
, 3_uz
};
305 alGetListener3fDirect(context
, param
, &vals
[0], &vals
[1], &vals
[2]);
309 ALlistener
&listener
= context
->mListener
;
310 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
314 al::span
<ALfloat
,6> vals
{values
, 6_uz
};
316 std::copy_n(listener
.OrientAt
.cbegin(), 3, vals
.begin());
317 std::copy_n(listener
.OrientUp
.cbegin(), 3, vals
.begin()+3);
320 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener float-vector property 0x%x", param
};
322 catch(al::context_error
& e
) {
323 context
->setError(e
.errorCode(), "%s", e
.what());
327 AL_API
DECL_FUNC2(void, alGetListeneri
, ALenum
,param
, ALint
*,value
)
328 FORCE_ALIGN
void AL_APIENTRY
alGetListeneriDirect(ALCcontext
*context
, ALenum param
, ALint
*value
) noexcept
330 if(!value
) throw al::context_error
{AL_INVALID_VALUE
, "NULL pointer"};
331 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
332 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener integer property 0x%x", param
};
334 catch(al::context_error
& e
) {
335 context
->setError(e
.errorCode(), "%s", e
.what());
338 AL_API
DECL_FUNC4(void, alGetListener3i
, ALenum
,param
, ALint
*,value1
, ALint
*,value2
, ALint
*,value3
)
339 FORCE_ALIGN
void AL_APIENTRY
alGetListener3iDirect(ALCcontext
*context
, ALenum param
,
340 ALint
*value1
, ALint
*value2
, ALint
*value3
) noexcept
342 if(!value1
|| !value2
|| !value3
)
343 throw al::context_error
{AL_INVALID_VALUE
, "NULL pointer"};
345 ALlistener
&listener
= context
->mListener
;
346 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
350 *value1
= static_cast<ALint
>(listener
.Position
[0]);
351 *value2
= static_cast<ALint
>(listener
.Position
[1]);
352 *value3
= static_cast<ALint
>(listener
.Position
[2]);
356 *value1
= static_cast<ALint
>(listener
.Velocity
[0]);
357 *value2
= static_cast<ALint
>(listener
.Velocity
[1]);
358 *value3
= static_cast<ALint
>(listener
.Velocity
[2]);
361 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener 3-integer property 0x%x", param
};
363 catch(al::context_error
& e
) {
364 context
->setError(e
.errorCode(), "%s", e
.what());
367 AL_API
DECL_FUNC2(void, alGetListeneriv
, ALenum
,param
, ALint
*,values
)
368 FORCE_ALIGN
void AL_APIENTRY
alGetListenerivDirect(ALCcontext
*context
, ALenum param
,
369 ALint
*values
) noexcept
372 throw al::context_error
{AL_INVALID_VALUE
, "NULL pointer"};
378 auto vals
= al::span
<ALint
,3>{values
, 3_uz
};
379 alGetListener3iDirect(context
, param
, &vals
[0], &vals
[1], &vals
[2]);
383 ALlistener
&listener
= context
->mListener
;
384 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
386 static constexpr auto f2i
= [](const float val
) noexcept
{ return static_cast<ALint
>(val
); };
390 auto vals
= al::span
<ALint
,6>{values
, 6_uz
};
392 std::transform(listener
.OrientAt
.cbegin(), listener
.OrientAt
.cend(), vals
.begin(), f2i
);
393 std::transform(listener
.OrientUp
.cbegin(), listener
.OrientUp
.cend(), vals
.begin()+3, f2i
);
396 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener integer-vector property 0x%x",
399 catch(al::context_error
& e
) {
400 context
->setError(e
.errorCode(), "%s", e
.what());