alState.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900
  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.
  8. *
  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.
  13. *
  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
  19. */
  20. #include "config.h"
  21. #include "version.h"
  22. #include <stdlib.h>
  23. #include "alMain.h"
  24. #include "AL/alc.h"
  25. #include "AL/al.h"
  26. #include "AL/alext.h"
  27. #include "alError.h"
  28. #include "alListener.h"
  29. #include "alSource.h"
  30. #include "alAuxEffectSlot.h"
  31. #include "backends/base.h"
  32. static const ALchar alVendor[] = "OpenAL Community";
  33. static const ALchar alVersion[] = "1.1 ALSOFT "ALSOFT_VERSION;
  34. static const ALchar alRenderer[] = "OpenAL Soft";
  35. // Error Messages
  36. static const ALchar alNoError[] = "No Error";
  37. static const ALchar alErrInvalidName[] = "Invalid Name";
  38. static const ALchar alErrInvalidEnum[] = "Invalid Enum";
  39. static const ALchar alErrInvalidValue[] = "Invalid Value";
  40. static const ALchar alErrInvalidOp[] = "Invalid Operation";
  41. static const ALchar alErrOutOfMemory[] = "Out of Memory";
  42. /* Resampler strings */
  43. static const ALchar alPointResampler[] = "Nearest";
  44. static const ALchar alLinearResampler[] = "Linear";
  45. static const ALchar alCubicResampler[] = "Cubic";
  46. static const ALchar alBSinc12Resampler[] = "11th order Sinc";
  47. static const ALchar alBSinc24Resampler[] = "23rd order Sinc";
  48. /* WARNING: Non-standard export! Not part of any extension, or exposed in the
  49. * alcFunctions list.
  50. */
  51. AL_API const ALchar* AL_APIENTRY alsoft_get_version(void)
  52. {
  53. const char *spoof = getenv("ALSOFT_SPOOF_VERSION");
  54. if(spoof && spoof[0] != '\0') return spoof;
  55. return ALSOFT_VERSION;
  56. }
  57. #define DO_UPDATEPROPS() do { \
  58. if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) \
  59. UpdateContextProps(context); \
  60. else \
  61. ATOMIC_FLAG_CLEAR(&context->PropsClean, almemory_order_release); \
  62. } while(0)
  63. AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
  64. {
  65. ALCcontext *context;
  66. context = GetContextRef();
  67. if(!context) return;
  68. almtx_lock(&context->PropLock);
  69. switch(capability)
  70. {
  71. case AL_SOURCE_DISTANCE_MODEL:
  72. context->SourceDistanceModel = AL_TRUE;
  73. DO_UPDATEPROPS();
  74. break;
  75. default:
  76. alSetError(context, AL_INVALID_VALUE, "Invalid enable property 0x%04x", capability);
  77. }
  78. almtx_unlock(&context->PropLock);
  79. ALCcontext_DecRef(context);
  80. }
  81. AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
  82. {
  83. ALCcontext *context;
  84. context = GetContextRef();
  85. if(!context) return;
  86. almtx_lock(&context->PropLock);
  87. switch(capability)
  88. {
  89. case AL_SOURCE_DISTANCE_MODEL:
  90. context->SourceDistanceModel = AL_FALSE;
  91. DO_UPDATEPROPS();
  92. break;
  93. default:
  94. alSetError(context, AL_INVALID_VALUE, "Invalid disable property 0x%04x", capability);
  95. }
  96. almtx_unlock(&context->PropLock);
  97. ALCcontext_DecRef(context);
  98. }
  99. AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
  100. {
  101. ALCcontext *context;
  102. ALboolean value=AL_FALSE;
  103. context = GetContextRef();
  104. if(!context) return AL_FALSE;
  105. almtx_lock(&context->PropLock);
  106. switch(capability)
  107. {
  108. case AL_SOURCE_DISTANCE_MODEL:
  109. value = context->SourceDistanceModel;
  110. break;
  111. default:
  112. alSetError(context, AL_INVALID_VALUE, "Invalid is enabled property 0x%04x", capability);
  113. }
  114. almtx_unlock(&context->PropLock);
  115. ALCcontext_DecRef(context);
  116. return value;
  117. }
  118. AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
  119. {
  120. ALCcontext *context;
  121. ALboolean value=AL_FALSE;
  122. context = GetContextRef();
  123. if(!context) return AL_FALSE;
  124. almtx_lock(&context->PropLock);
  125. switch(pname)
  126. {
  127. case AL_DOPPLER_FACTOR:
  128. if(context->DopplerFactor != 0.0f)
  129. value = AL_TRUE;
  130. break;
  131. case AL_DOPPLER_VELOCITY:
  132. if(context->DopplerVelocity != 0.0f)
  133. value = AL_TRUE;
  134. break;
  135. case AL_DISTANCE_MODEL:
  136. if(context->DistanceModel == AL_INVERSE_DISTANCE_CLAMPED)
  137. value = AL_TRUE;
  138. break;
  139. case AL_SPEED_OF_SOUND:
  140. if(context->SpeedOfSound != 0.0f)
  141. value = AL_TRUE;
  142. break;
  143. case AL_DEFERRED_UPDATES_SOFT:
  144. if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
  145. value = AL_TRUE;
  146. break;
  147. case AL_GAIN_LIMIT_SOFT:
  148. if(GAIN_MIX_MAX/context->GainBoost != 0.0f)
  149. value = AL_TRUE;
  150. break;
  151. case AL_NUM_RESAMPLERS_SOFT:
  152. /* Always non-0. */
  153. value = AL_TRUE;
  154. break;
  155. case AL_DEFAULT_RESAMPLER_SOFT:
  156. value = ResamplerDefault ? AL_TRUE : AL_FALSE;
  157. break;
  158. default:
  159. alSetError(context, AL_INVALID_VALUE, "Invalid boolean property 0x%04x", pname);
  160. }
  161. almtx_unlock(&context->PropLock);
  162. ALCcontext_DecRef(context);
  163. return value;
  164. }
  165. AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
  166. {
  167. ALCcontext *context;
  168. ALdouble value = 0.0;
  169. context = GetContextRef();
  170. if(!context) return 0.0;
  171. almtx_lock(&context->PropLock);
  172. switch(pname)
  173. {
  174. case AL_DOPPLER_FACTOR:
  175. value = (ALdouble)context->DopplerFactor;
  176. break;
  177. case AL_DOPPLER_VELOCITY:
  178. value = (ALdouble)context->DopplerVelocity;
  179. break;
  180. case AL_DISTANCE_MODEL:
  181. value = (ALdouble)context->DistanceModel;
  182. break;
  183. case AL_SPEED_OF_SOUND:
  184. value = (ALdouble)context->SpeedOfSound;
  185. break;
  186. case AL_DEFERRED_UPDATES_SOFT:
  187. if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
  188. value = (ALdouble)AL_TRUE;
  189. break;
  190. case AL_GAIN_LIMIT_SOFT:
  191. value = (ALdouble)GAIN_MIX_MAX/context->GainBoost;
  192. break;
  193. case AL_NUM_RESAMPLERS_SOFT:
  194. value = (ALdouble)(ResamplerMax + 1);
  195. break;
  196. case AL_DEFAULT_RESAMPLER_SOFT:
  197. value = (ALdouble)ResamplerDefault;
  198. break;
  199. default:
  200. alSetError(context, AL_INVALID_VALUE, "Invalid double property 0x%04x", pname);
  201. }
  202. almtx_unlock(&context->PropLock);
  203. ALCcontext_DecRef(context);
  204. return value;
  205. }
  206. AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
  207. {
  208. ALCcontext *context;
  209. ALfloat value = 0.0f;
  210. context = GetContextRef();
  211. if(!context) return 0.0f;
  212. almtx_lock(&context->PropLock);
  213. switch(pname)
  214. {
  215. case AL_DOPPLER_FACTOR:
  216. value = context->DopplerFactor;
  217. break;
  218. case AL_DOPPLER_VELOCITY:
  219. value = context->DopplerVelocity;
  220. break;
  221. case AL_DISTANCE_MODEL:
  222. value = (ALfloat)context->DistanceModel;
  223. break;
  224. case AL_SPEED_OF_SOUND:
  225. value = context->SpeedOfSound;
  226. break;
  227. case AL_DEFERRED_UPDATES_SOFT:
  228. if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
  229. value = (ALfloat)AL_TRUE;
  230. break;
  231. case AL_GAIN_LIMIT_SOFT:
  232. value = GAIN_MIX_MAX/context->GainBoost;
  233. break;
  234. case AL_NUM_RESAMPLERS_SOFT:
  235. value = (ALfloat)(ResamplerMax + 1);
  236. break;
  237. case AL_DEFAULT_RESAMPLER_SOFT:
  238. value = (ALfloat)ResamplerDefault;
  239. break;
  240. default:
  241. alSetError(context, AL_INVALID_VALUE, "Invalid float property 0x%04x", pname);
  242. }
  243. almtx_unlock(&context->PropLock);
  244. ALCcontext_DecRef(context);
  245. return value;
  246. }
  247. AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
  248. {
  249. ALCcontext *context;
  250. ALint value = 0;
  251. context = GetContextRef();
  252. if(!context) return 0;
  253. almtx_lock(&context->PropLock);
  254. switch(pname)
  255. {
  256. case AL_DOPPLER_FACTOR:
  257. value = (ALint)context->DopplerFactor;
  258. break;
  259. case AL_DOPPLER_VELOCITY:
  260. value = (ALint)context->DopplerVelocity;
  261. break;
  262. case AL_DISTANCE_MODEL:
  263. value = (ALint)context->DistanceModel;
  264. break;
  265. case AL_SPEED_OF_SOUND:
  266. value = (ALint)context->SpeedOfSound;
  267. break;
  268. case AL_DEFERRED_UPDATES_SOFT:
  269. if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
  270. value = (ALint)AL_TRUE;
  271. break;
  272. case AL_GAIN_LIMIT_SOFT:
  273. value = (ALint)(GAIN_MIX_MAX/context->GainBoost);
  274. break;
  275. case AL_NUM_RESAMPLERS_SOFT:
  276. value = ResamplerMax + 1;
  277. break;
  278. case AL_DEFAULT_RESAMPLER_SOFT:
  279. value = ResamplerDefault;
  280. break;
  281. default:
  282. alSetError(context, AL_INVALID_VALUE, "Invalid integer property 0x%04x", pname);
  283. }
  284. almtx_unlock(&context->PropLock);
  285. ALCcontext_DecRef(context);
  286. return value;
  287. }
  288. AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
  289. {
  290. ALCcontext *context;
  291. ALint64SOFT value = 0;
  292. context = GetContextRef();
  293. if(!context) return 0;
  294. almtx_lock(&context->PropLock);
  295. switch(pname)
  296. {
  297. case AL_DOPPLER_FACTOR:
  298. value = (ALint64SOFT)context->DopplerFactor;
  299. break;
  300. case AL_DOPPLER_VELOCITY:
  301. value = (ALint64SOFT)context->DopplerVelocity;
  302. break;
  303. case AL_DISTANCE_MODEL:
  304. value = (ALint64SOFT)context->DistanceModel;
  305. break;
  306. case AL_SPEED_OF_SOUND:
  307. value = (ALint64SOFT)context->SpeedOfSound;
  308. break;
  309. case AL_DEFERRED_UPDATES_SOFT:
  310. if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
  311. value = (ALint64SOFT)AL_TRUE;
  312. break;
  313. case AL_GAIN_LIMIT_SOFT:
  314. value = (ALint64SOFT)(GAIN_MIX_MAX/context->GainBoost);
  315. break;
  316. case AL_NUM_RESAMPLERS_SOFT:
  317. value = (ALint64SOFT)(ResamplerMax + 1);
  318. break;
  319. case AL_DEFAULT_RESAMPLER_SOFT:
  320. value = (ALint64SOFT)ResamplerDefault;
  321. break;
  322. default:
  323. alSetError(context, AL_INVALID_VALUE, "Invalid integer64 property 0x%04x", pname);
  324. }
  325. almtx_unlock(&context->PropLock);
  326. ALCcontext_DecRef(context);
  327. return value;
  328. }
  329. AL_API void* AL_APIENTRY alGetPointerSOFT(ALenum pname)
  330. {
  331. ALCcontext *context;
  332. void *value = NULL;
  333. context = GetContextRef();
  334. if(!context) return NULL;
  335. almtx_lock(&context->PropLock);
  336. switch(pname)
  337. {
  338. case AL_EVENT_CALLBACK_FUNCTION_SOFT:
  339. value = context->EventCb;
  340. break;
  341. case AL_EVENT_CALLBACK_USER_PARAM_SOFT:
  342. value = context->EventParam;
  343. break;
  344. default:
  345. alSetError(context, AL_INVALID_VALUE, "Invalid pointer property 0x%04x", pname);
  346. }
  347. almtx_unlock(&context->PropLock);
  348. ALCcontext_DecRef(context);
  349. return value;
  350. }
  351. AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values)
  352. {
  353. ALCcontext *context;
  354. if(values)
  355. {
  356. switch(pname)
  357. {
  358. case AL_DOPPLER_FACTOR:
  359. case AL_DOPPLER_VELOCITY:
  360. case AL_DISTANCE_MODEL:
  361. case AL_SPEED_OF_SOUND:
  362. case AL_DEFERRED_UPDATES_SOFT:
  363. case AL_GAIN_LIMIT_SOFT:
  364. case AL_NUM_RESAMPLERS_SOFT:
  365. case AL_DEFAULT_RESAMPLER_SOFT:
  366. values[0] = alGetBoolean(pname);
  367. return;
  368. }
  369. }
  370. context = GetContextRef();
  371. if(!context) return;
  372. if(!values)
  373. alSetError(context, AL_INVALID_VALUE, "NULL pointer");
  374. switch(pname)
  375. {
  376. default:
  377. alSetError(context, AL_INVALID_VALUE, "Invalid boolean-vector property 0x%04x", pname);
  378. }
  379. ALCcontext_DecRef(context);
  380. }
  381. AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values)
  382. {
  383. ALCcontext *context;
  384. if(values)
  385. {
  386. switch(pname)
  387. {
  388. case AL_DOPPLER_FACTOR:
  389. case AL_DOPPLER_VELOCITY:
  390. case AL_DISTANCE_MODEL:
  391. case AL_SPEED_OF_SOUND:
  392. case AL_DEFERRED_UPDATES_SOFT:
  393. case AL_GAIN_LIMIT_SOFT:
  394. case AL_NUM_RESAMPLERS_SOFT:
  395. case AL_DEFAULT_RESAMPLER_SOFT:
  396. values[0] = alGetDouble(pname);
  397. return;
  398. }
  399. }
  400. context = GetContextRef();
  401. if(!context) return;
  402. if(!values)
  403. alSetError(context, AL_INVALID_VALUE, "NULL pointer");
  404. switch(pname)
  405. {
  406. default:
  407. alSetError(context, AL_INVALID_VALUE, "Invalid double-vector property 0x%04x", pname);
  408. }
  409. ALCcontext_DecRef(context);
  410. }
  411. AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values)
  412. {
  413. ALCcontext *context;
  414. if(values)
  415. {
  416. switch(pname)
  417. {
  418. case AL_DOPPLER_FACTOR:
  419. case AL_DOPPLER_VELOCITY:
  420. case AL_DISTANCE_MODEL:
  421. case AL_SPEED_OF_SOUND:
  422. case AL_DEFERRED_UPDATES_SOFT:
  423. case AL_GAIN_LIMIT_SOFT:
  424. case AL_NUM_RESAMPLERS_SOFT:
  425. case AL_DEFAULT_RESAMPLER_SOFT:
  426. values[0] = alGetFloat(pname);
  427. return;
  428. }
  429. }
  430. context = GetContextRef();
  431. if(!context) return;
  432. if(!values)
  433. alSetError(context, AL_INVALID_VALUE, "NULL pointer");
  434. switch(pname)
  435. {
  436. default:
  437. alSetError(context, AL_INVALID_VALUE, "Invalid float-vector property 0x%04x", pname);
  438. }
  439. ALCcontext_DecRef(context);
  440. }
  441. AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
  442. {
  443. ALCcontext *context;
  444. if(values)
  445. {
  446. switch(pname)
  447. {
  448. case AL_DOPPLER_FACTOR:
  449. case AL_DOPPLER_VELOCITY:
  450. case AL_DISTANCE_MODEL:
  451. case AL_SPEED_OF_SOUND:
  452. case AL_DEFERRED_UPDATES_SOFT:
  453. case AL_GAIN_LIMIT_SOFT:
  454. case AL_NUM_RESAMPLERS_SOFT:
  455. case AL_DEFAULT_RESAMPLER_SOFT:
  456. values[0] = alGetInteger(pname);
  457. return;
  458. }
  459. }
  460. context = GetContextRef();
  461. if(!context) return;
  462. if(!values)
  463. alSetError(context, AL_INVALID_VALUE, "NULL pointer");
  464. switch(pname)
  465. {
  466. default:
  467. alSetError(context, AL_INVALID_VALUE, "Invalid integer-vector property 0x%04x", pname);
  468. }
  469. ALCcontext_DecRef(context);
  470. }
  471. AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
  472. {
  473. ALCcontext *context;
  474. if(values)
  475. {
  476. switch(pname)
  477. {
  478. case AL_DOPPLER_FACTOR:
  479. case AL_DOPPLER_VELOCITY:
  480. case AL_DISTANCE_MODEL:
  481. case AL_SPEED_OF_SOUND:
  482. case AL_DEFERRED_UPDATES_SOFT:
  483. case AL_GAIN_LIMIT_SOFT:
  484. case AL_NUM_RESAMPLERS_SOFT:
  485. case AL_DEFAULT_RESAMPLER_SOFT:
  486. values[0] = alGetInteger64SOFT(pname);
  487. return;
  488. }
  489. }
  490. context = GetContextRef();
  491. if(!context) return;
  492. if(!values)
  493. alSetError(context, AL_INVALID_VALUE, "NULL pointer");
  494. switch(pname)
  495. {
  496. default:
  497. alSetError(context, AL_INVALID_VALUE, "Invalid integer64-vector property 0x%04x", pname);
  498. }
  499. ALCcontext_DecRef(context);
  500. }
  501. AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values)
  502. {
  503. ALCcontext *context;
  504. if(values)
  505. {
  506. switch(pname)
  507. {
  508. case AL_EVENT_CALLBACK_FUNCTION_SOFT:
  509. case AL_EVENT_CALLBACK_USER_PARAM_SOFT:
  510. values[0] = alGetPointerSOFT(pname);
  511. return;
  512. }
  513. }
  514. context = GetContextRef();
  515. if(!context) return;
  516. if(!values)
  517. alSetError(context, AL_INVALID_VALUE, "NULL pointer");
  518. switch(pname)
  519. {
  520. default:
  521. alSetError(context, AL_INVALID_VALUE, "Invalid pointer-vector property 0x%04x", pname);
  522. }
  523. ALCcontext_DecRef(context);
  524. }
  525. AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
  526. {
  527. const ALchar *value = NULL;
  528. ALCcontext *context;
  529. context = GetContextRef();
  530. if(!context) return NULL;
  531. switch(pname)
  532. {
  533. case AL_VENDOR:
  534. value = alVendor;
  535. break;
  536. case AL_VERSION:
  537. value = alVersion;
  538. break;
  539. case AL_RENDERER:
  540. value = alRenderer;
  541. break;
  542. case AL_EXTENSIONS:
  543. value = context->ExtensionList;
  544. break;
  545. case AL_NO_ERROR:
  546. value = alNoError;
  547. break;
  548. case AL_INVALID_NAME:
  549. value = alErrInvalidName;
  550. break;
  551. case AL_INVALID_ENUM:
  552. value = alErrInvalidEnum;
  553. break;
  554. case AL_INVALID_VALUE:
  555. value = alErrInvalidValue;
  556. break;
  557. case AL_INVALID_OPERATION:
  558. value = alErrInvalidOp;
  559. break;
  560. case AL_OUT_OF_MEMORY:
  561. value = alErrOutOfMemory;
  562. break;
  563. default:
  564. alSetError(context, AL_INVALID_VALUE, "Invalid string property 0x%04x", pname);
  565. }
  566. ALCcontext_DecRef(context);
  567. return value;
  568. }
  569. AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value)
  570. {
  571. ALCcontext *context;
  572. context = GetContextRef();
  573. if(!context) return;
  574. if(!(value >= 0.0f && isfinite(value)))
  575. alSetError(context, AL_INVALID_VALUE, "Doppler factor %f out of range", value);
  576. else
  577. {
  578. almtx_lock(&context->PropLock);
  579. context->DopplerFactor = value;
  580. DO_UPDATEPROPS();
  581. almtx_unlock(&context->PropLock);
  582. }
  583. ALCcontext_DecRef(context);
  584. }
  585. AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value)
  586. {
  587. ALCcontext *context;
  588. context = GetContextRef();
  589. if(!context) return;
  590. if((ATOMIC_LOAD(&context->EnabledEvts, almemory_order_relaxed)&EventType_Deprecated))
  591. {
  592. static const ALCchar msg[] =
  593. "alDopplerVelocity is deprecated in AL1.1, use alSpeedOfSound";
  594. const ALsizei msglen = (ALsizei)strlen(msg);
  595. ALbitfieldSOFT enabledevts;
  596. almtx_lock(&context->EventCbLock);
  597. enabledevts = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_relaxed);
  598. if((enabledevts&EventType_Deprecated) && context->EventCb)
  599. (*context->EventCb)(AL_EVENT_TYPE_DEPRECATED_SOFT, 0, 0, msglen, msg,
  600. context->EventParam);
  601. almtx_unlock(&context->EventCbLock);
  602. }
  603. if(!(value >= 0.0f && isfinite(value)))
  604. alSetError(context, AL_INVALID_VALUE, "Doppler velocity %f out of range", value);
  605. else
  606. {
  607. almtx_lock(&context->PropLock);
  608. context->DopplerVelocity = value;
  609. DO_UPDATEPROPS();
  610. almtx_unlock(&context->PropLock);
  611. }
  612. ALCcontext_DecRef(context);
  613. }
  614. AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value)
  615. {
  616. ALCcontext *context;
  617. context = GetContextRef();
  618. if(!context) return;
  619. if(!(value > 0.0f && isfinite(value)))
  620. alSetError(context, AL_INVALID_VALUE, "Speed of sound %f out of range", value);
  621. else
  622. {
  623. almtx_lock(&context->PropLock);
  624. context->SpeedOfSound = value;
  625. DO_UPDATEPROPS();
  626. almtx_unlock(&context->PropLock);
  627. }
  628. ALCcontext_DecRef(context);
  629. }
  630. AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
  631. {
  632. ALCcontext *context;
  633. context = GetContextRef();
  634. if(!context) return;
  635. if(!(value == AL_INVERSE_DISTANCE || value == AL_INVERSE_DISTANCE_CLAMPED ||
  636. value == AL_LINEAR_DISTANCE || value == AL_LINEAR_DISTANCE_CLAMPED ||
  637. value == AL_EXPONENT_DISTANCE || value == AL_EXPONENT_DISTANCE_CLAMPED ||
  638. value == AL_NONE))
  639. alSetError(context, AL_INVALID_VALUE, "Distance model 0x%04x out of range", value);
  640. else
  641. {
  642. almtx_lock(&context->PropLock);
  643. context->DistanceModel = value;
  644. if(!context->SourceDistanceModel)
  645. DO_UPDATEPROPS();
  646. almtx_unlock(&context->PropLock);
  647. }
  648. ALCcontext_DecRef(context);
  649. }
  650. AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void)
  651. {
  652. ALCcontext *context;
  653. context = GetContextRef();
  654. if(!context) return;
  655. ALCcontext_DeferUpdates(context);
  656. ALCcontext_DecRef(context);
  657. }
  658. AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void)
  659. {
  660. ALCcontext *context;
  661. context = GetContextRef();
  662. if(!context) return;
  663. ALCcontext_ProcessUpdates(context);
  664. ALCcontext_DecRef(context);
  665. }
  666. AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index)
  667. {
  668. const char *ResamplerNames[] = {
  669. alPointResampler, alLinearResampler,
  670. alCubicResampler, alBSinc12Resampler,
  671. alBSinc24Resampler,
  672. };
  673. const ALchar *value = NULL;
  674. ALCcontext *context;
  675. static_assert(COUNTOF(ResamplerNames) == ResamplerMax+1, "Incorrect ResamplerNames list");
  676. context = GetContextRef();
  677. if(!context) return NULL;
  678. switch(pname)
  679. {
  680. case AL_RESAMPLER_NAME_SOFT:
  681. if(index < 0 || (size_t)index >= COUNTOF(ResamplerNames))
  682. SETERR_GOTO(context, AL_INVALID_VALUE, done, "Resampler name index %d out of range",
  683. index);
  684. value = ResamplerNames[index];
  685. break;
  686. default:
  687. alSetError(context, AL_INVALID_VALUE, "Invalid string indexed property");
  688. }
  689. done:
  690. ALCcontext_DecRef(context);
  691. return value;
  692. }
  693. void UpdateContextProps(ALCcontext *context)
  694. {
  695. struct ALcontextProps *props;
  696. /* Get an unused proprty container, or allocate a new one as needed. */
  697. props = ATOMIC_LOAD(&context->FreeContextProps, almemory_order_acquire);
  698. if(!props)
  699. props = al_calloc(16, sizeof(*props));
  700. else
  701. {
  702. struct ALcontextProps *next;
  703. do {
  704. next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
  705. } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&context->FreeContextProps, &props, next,
  706. almemory_order_seq_cst, almemory_order_acquire) == 0);
  707. }
  708. /* Copy in current property values. */
  709. props->MetersPerUnit = context->MetersPerUnit;
  710. props->DopplerFactor = context->DopplerFactor;
  711. props->DopplerVelocity = context->DopplerVelocity;
  712. props->SpeedOfSound = context->SpeedOfSound;
  713. props->SourceDistanceModel = context->SourceDistanceModel;
  714. props->DistanceModel = context->DistanceModel;
  715. /* Set the new container for updating internal parameters. */
  716. props = ATOMIC_EXCHANGE_PTR(&context->Update, props, almemory_order_acq_rel);
  717. if(props)
  718. {
  719. /* If there was an unused update container, put it back in the
  720. * freelist.
  721. */
  722. ATOMIC_REPLACE_HEAD(struct ALcontextProps*, &context->FreeContextProps, props);
  723. }
  724. }