alState.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  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., 59 Temple Place - Suite 330,
  17. * Boston, MA 02111-1307, USA.
  18. * Or go to http://www.gnu.org/copyleft/lgpl.html
  19. */
  20. #include "config.h"
  21. #include <stdlib.h>
  22. #include "alMain.h"
  23. #include "AL/alc.h"
  24. #include "AL/alext.h"
  25. #include "alError.h"
  26. #include "alSource.h"
  27. #include "alAuxEffectSlot.h"
  28. #include "alState.h"
  29. static const ALchar alVendor[] = "OpenAL Community";
  30. static const ALchar alVersion[] = "1.1 ALSOFT "ALSOFT_VERSION;
  31. static const ALchar alRenderer[] = "OpenAL Soft";
  32. // Error Messages
  33. static const ALchar alNoError[] = "No Error";
  34. static const ALchar alErrInvalidName[] = "Invalid Name";
  35. static const ALchar alErrInvalidEnum[] = "Invalid Enum";
  36. static const ALchar alErrInvalidValue[] = "Invalid Value";
  37. static const ALchar alErrInvalidOp[] = "Invalid Operation";
  38. static const ALchar alErrOutOfMemory[] = "Out of Memory";
  39. AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
  40. {
  41. ALCcontext *Context;
  42. Context = GetContextRef();
  43. if(!Context) return;
  44. switch(capability)
  45. {
  46. case AL_SOURCE_DISTANCE_MODEL:
  47. Context->SourceDistanceModel = AL_TRUE;
  48. Context->UpdateSources = AL_TRUE;
  49. break;
  50. default:
  51. alSetError(Context, AL_INVALID_ENUM);
  52. break;
  53. }
  54. ALCcontext_DecRef(Context);
  55. }
  56. AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
  57. {
  58. ALCcontext *Context;
  59. Context = GetContextRef();
  60. if(!Context) return;
  61. switch(capability)
  62. {
  63. case AL_SOURCE_DISTANCE_MODEL:
  64. Context->SourceDistanceModel = AL_FALSE;
  65. Context->UpdateSources = AL_TRUE;
  66. break;
  67. default:
  68. alSetError(Context, AL_INVALID_ENUM);
  69. break;
  70. }
  71. ALCcontext_DecRef(Context);
  72. }
  73. AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
  74. {
  75. ALCcontext *Context;
  76. ALboolean value=AL_FALSE;
  77. Context = GetContextRef();
  78. if(!Context) return AL_FALSE;
  79. switch(capability)
  80. {
  81. case AL_SOURCE_DISTANCE_MODEL:
  82. value = Context->SourceDistanceModel;
  83. break;
  84. default:
  85. alSetError(Context, AL_INVALID_ENUM);
  86. break;
  87. }
  88. ALCcontext_DecRef(Context);
  89. return value;
  90. }
  91. AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
  92. {
  93. ALCcontext *Context;
  94. ALboolean value=AL_FALSE;
  95. Context = GetContextRef();
  96. if(!Context) return AL_FALSE;
  97. switch(pname)
  98. {
  99. case AL_DOPPLER_FACTOR:
  100. if(Context->DopplerFactor != 0.0f)
  101. value = AL_TRUE;
  102. break;
  103. case AL_DOPPLER_VELOCITY:
  104. if(Context->DopplerVelocity != 0.0f)
  105. value = AL_TRUE;
  106. break;
  107. case AL_DISTANCE_MODEL:
  108. if(Context->DistanceModel == AL_INVERSE_DISTANCE_CLAMPED)
  109. value = AL_TRUE;
  110. break;
  111. case AL_SPEED_OF_SOUND:
  112. if(Context->flSpeedOfSound != 0.0f)
  113. value = AL_TRUE;
  114. break;
  115. case AL_DEFERRED_UPDATES_SOFT:
  116. value = Context->DeferUpdates;
  117. break;
  118. default:
  119. alSetError(Context, AL_INVALID_ENUM);
  120. break;
  121. }
  122. ALCcontext_DecRef(Context);
  123. return value;
  124. }
  125. AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
  126. {
  127. ALCcontext *Context;
  128. ALdouble value = 0.0;
  129. Context = GetContextRef();
  130. if(!Context) return 0.0;
  131. switch(pname)
  132. {
  133. case AL_DOPPLER_FACTOR:
  134. value = (double)Context->DopplerFactor;
  135. break;
  136. case AL_DOPPLER_VELOCITY:
  137. value = (double)Context->DopplerVelocity;
  138. break;
  139. case AL_DISTANCE_MODEL:
  140. value = (double)Context->DistanceModel;
  141. break;
  142. case AL_SPEED_OF_SOUND:
  143. value = (double)Context->flSpeedOfSound;
  144. break;
  145. case AL_DEFERRED_UPDATES_SOFT:
  146. value = (ALdouble)Context->DeferUpdates;
  147. break;
  148. default:
  149. alSetError(Context, AL_INVALID_ENUM);
  150. break;
  151. }
  152. ALCcontext_DecRef(Context);
  153. return value;
  154. }
  155. AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
  156. {
  157. ALCcontext *Context;
  158. ALfloat value = 0.0f;
  159. Context = GetContextRef();
  160. if(!Context) return 0.0f;
  161. switch(pname)
  162. {
  163. case AL_DOPPLER_FACTOR:
  164. value = Context->DopplerFactor;
  165. break;
  166. case AL_DOPPLER_VELOCITY:
  167. value = Context->DopplerVelocity;
  168. break;
  169. case AL_DISTANCE_MODEL:
  170. value = (float)Context->DistanceModel;
  171. break;
  172. case AL_SPEED_OF_SOUND:
  173. value = Context->flSpeedOfSound;
  174. break;
  175. case AL_DEFERRED_UPDATES_SOFT:
  176. value = (ALfloat)Context->DeferUpdates;
  177. break;
  178. default:
  179. alSetError(Context, AL_INVALID_ENUM);
  180. break;
  181. }
  182. ALCcontext_DecRef(Context);
  183. return value;
  184. }
  185. AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
  186. {
  187. ALCcontext *Context;
  188. ALint value = 0;
  189. Context = GetContextRef();
  190. if(!Context) return 0;
  191. switch(pname)
  192. {
  193. case AL_DOPPLER_FACTOR:
  194. value = (ALint)Context->DopplerFactor;
  195. break;
  196. case AL_DOPPLER_VELOCITY:
  197. value = (ALint)Context->DopplerVelocity;
  198. break;
  199. case AL_DISTANCE_MODEL:
  200. value = (ALint)Context->DistanceModel;
  201. break;
  202. case AL_SPEED_OF_SOUND:
  203. value = (ALint)Context->flSpeedOfSound;
  204. break;
  205. case AL_DEFERRED_UPDATES_SOFT:
  206. value = (ALint)Context->DeferUpdates;
  207. break;
  208. default:
  209. alSetError(Context, AL_INVALID_ENUM);
  210. break;
  211. }
  212. ALCcontext_DecRef(Context);
  213. return value;
  214. }
  215. AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname,ALboolean *data)
  216. {
  217. ALCcontext *Context;
  218. if(data)
  219. {
  220. switch(pname)
  221. {
  222. case AL_DOPPLER_FACTOR:
  223. case AL_DOPPLER_VELOCITY:
  224. case AL_DISTANCE_MODEL:
  225. case AL_SPEED_OF_SOUND:
  226. case AL_DEFERRED_UPDATES_SOFT:
  227. *data = alGetBoolean(pname);
  228. return;
  229. }
  230. }
  231. Context = GetContextRef();
  232. if(!Context) return;
  233. if(data)
  234. {
  235. switch(pname)
  236. {
  237. default:
  238. alSetError(Context, AL_INVALID_ENUM);
  239. break;
  240. }
  241. }
  242. else
  243. {
  244. // data is a NULL pointer
  245. alSetError(Context, AL_INVALID_VALUE);
  246. }
  247. ALCcontext_DecRef(Context);
  248. }
  249. AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname,ALdouble *data)
  250. {
  251. ALCcontext *Context;
  252. if(data)
  253. {
  254. switch(pname)
  255. {
  256. case AL_DOPPLER_FACTOR:
  257. case AL_DOPPLER_VELOCITY:
  258. case AL_DISTANCE_MODEL:
  259. case AL_SPEED_OF_SOUND:
  260. case AL_DEFERRED_UPDATES_SOFT:
  261. *data = alGetDouble(pname);
  262. return;
  263. }
  264. }
  265. Context = GetContextRef();
  266. if(!Context) return;
  267. if(data)
  268. {
  269. switch(pname)
  270. {
  271. default:
  272. alSetError(Context, AL_INVALID_ENUM);
  273. break;
  274. }
  275. }
  276. else
  277. {
  278. // data is a NULL pointer
  279. alSetError(Context, AL_INVALID_VALUE);
  280. }
  281. ALCcontext_DecRef(Context);
  282. }
  283. AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname,ALfloat *data)
  284. {
  285. ALCcontext *Context;
  286. if(data)
  287. {
  288. switch(pname)
  289. {
  290. case AL_DOPPLER_FACTOR:
  291. case AL_DOPPLER_VELOCITY:
  292. case AL_DISTANCE_MODEL:
  293. case AL_SPEED_OF_SOUND:
  294. case AL_DEFERRED_UPDATES_SOFT:
  295. *data = alGetFloat(pname);
  296. return;
  297. }
  298. }
  299. Context = GetContextRef();
  300. if(!Context) return;
  301. if(data)
  302. {
  303. switch(pname)
  304. {
  305. default:
  306. alSetError(Context, AL_INVALID_ENUM);
  307. break;
  308. }
  309. }
  310. else
  311. {
  312. // data is a NULL pointer
  313. alSetError(Context, AL_INVALID_VALUE);
  314. }
  315. ALCcontext_DecRef(Context);
  316. }
  317. AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname,ALint *data)
  318. {
  319. ALCcontext *Context;
  320. if(data)
  321. {
  322. switch(pname)
  323. {
  324. case AL_DOPPLER_FACTOR:
  325. case AL_DOPPLER_VELOCITY:
  326. case AL_DISTANCE_MODEL:
  327. case AL_SPEED_OF_SOUND:
  328. case AL_DEFERRED_UPDATES_SOFT:
  329. *data = alGetInteger(pname);
  330. return;
  331. }
  332. }
  333. Context = GetContextRef();
  334. if(!Context) return;
  335. if(data)
  336. {
  337. switch(pname)
  338. {
  339. default:
  340. alSetError(Context, AL_INVALID_ENUM);
  341. break;
  342. }
  343. }
  344. else
  345. {
  346. // data is a NULL pointer
  347. alSetError(Context, AL_INVALID_VALUE);
  348. }
  349. ALCcontext_DecRef(Context);
  350. }
  351. AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
  352. {
  353. const ALchar *value;
  354. ALCcontext *Context;
  355. Context = GetContextRef();
  356. if(!Context) return NULL;
  357. switch(pname)
  358. {
  359. case AL_VENDOR:
  360. value=alVendor;
  361. break;
  362. case AL_VERSION:
  363. value=alVersion;
  364. break;
  365. case AL_RENDERER:
  366. value=alRenderer;
  367. break;
  368. case AL_EXTENSIONS:
  369. value=Context->ExtensionList;
  370. break;
  371. case AL_NO_ERROR:
  372. value=alNoError;
  373. break;
  374. case AL_INVALID_NAME:
  375. value=alErrInvalidName;
  376. break;
  377. case AL_INVALID_ENUM:
  378. value=alErrInvalidEnum;
  379. break;
  380. case AL_INVALID_VALUE:
  381. value=alErrInvalidValue;
  382. break;
  383. case AL_INVALID_OPERATION:
  384. value=alErrInvalidOp;
  385. break;
  386. case AL_OUT_OF_MEMORY:
  387. value=alErrOutOfMemory;
  388. break;
  389. default:
  390. value=NULL;
  391. alSetError(Context, AL_INVALID_ENUM);
  392. break;
  393. }
  394. ALCcontext_DecRef(Context);
  395. return value;
  396. }
  397. AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value)
  398. {
  399. ALCcontext *Context;
  400. Context = GetContextRef();
  401. if(!Context) return;
  402. if(value >= 0.0f && isfinite(value))
  403. {
  404. Context->DopplerFactor = value;
  405. Context->UpdateSources = AL_TRUE;
  406. }
  407. else
  408. alSetError(Context, AL_INVALID_VALUE);
  409. ALCcontext_DecRef(Context);
  410. }
  411. AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value)
  412. {
  413. ALCcontext *Context;
  414. Context = GetContextRef();
  415. if(!Context) return;
  416. if(value > 0.0f && isfinite(value))
  417. {
  418. Context->DopplerVelocity=value;
  419. Context->UpdateSources = AL_TRUE;
  420. }
  421. else
  422. alSetError(Context, AL_INVALID_VALUE);
  423. ALCcontext_DecRef(Context);
  424. }
  425. AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat flSpeedOfSound)
  426. {
  427. ALCcontext *Context;
  428. Context = GetContextRef();
  429. if(!Context) return;
  430. if(flSpeedOfSound > 0.0f && isfinite(flSpeedOfSound))
  431. {
  432. Context->flSpeedOfSound = flSpeedOfSound;
  433. Context->UpdateSources = AL_TRUE;
  434. }
  435. else
  436. alSetError(Context, AL_INVALID_VALUE);
  437. ALCcontext_DecRef(Context);
  438. }
  439. AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
  440. {
  441. ALCcontext *Context;
  442. Context = GetContextRef();
  443. if(!Context) return;
  444. switch(value)
  445. {
  446. case AL_NONE:
  447. case AL_INVERSE_DISTANCE:
  448. case AL_INVERSE_DISTANCE_CLAMPED:
  449. case AL_LINEAR_DISTANCE:
  450. case AL_LINEAR_DISTANCE_CLAMPED:
  451. case AL_EXPONENT_DISTANCE:
  452. case AL_EXPONENT_DISTANCE_CLAMPED:
  453. Context->DistanceModel = value;
  454. Context->UpdateSources = AL_TRUE;
  455. break;
  456. default:
  457. alSetError(Context, AL_INVALID_VALUE);
  458. break;
  459. }
  460. ALCcontext_DecRef(Context);
  461. }
  462. AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void)
  463. {
  464. ALCcontext *Context;
  465. Context = GetContextRef();
  466. if(!Context) return;
  467. if(!Context->DeferUpdates)
  468. {
  469. ALboolean UpdateSources;
  470. ALsource **src, **src_end;
  471. ALeffectslot **slot, **slot_end;
  472. int fpuState;
  473. fpuState = SetMixerFPUMode();
  474. LockContext(Context);
  475. Context->DeferUpdates = AL_TRUE;
  476. /* Make sure all pending updates are performed */
  477. UpdateSources = ExchangeInt(&Context->UpdateSources, AL_FALSE);
  478. src = Context->ActiveSources;
  479. src_end = src + Context->ActiveSourceCount;
  480. while(src != src_end)
  481. {
  482. if((*src)->state != AL_PLAYING)
  483. {
  484. Context->ActiveSourceCount--;
  485. *src = *(--src_end);
  486. continue;
  487. }
  488. if(ExchangeInt(&(*src)->NeedsUpdate, AL_FALSE) || UpdateSources)
  489. ALsource_Update(*src, Context);
  490. src++;
  491. }
  492. slot = Context->ActiveEffectSlots;
  493. slot_end = slot + Context->ActiveEffectSlotCount;
  494. while(slot != slot_end)
  495. {
  496. if(ExchangeInt(&(*slot)->NeedsUpdate, AL_FALSE))
  497. ALeffectState_Update((*slot)->EffectState, Context->Device, *slot);
  498. slot++;
  499. }
  500. UnlockContext(Context);
  501. RestoreFPUMode(fpuState);
  502. }
  503. ALCcontext_DecRef(Context);
  504. }
  505. AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void)
  506. {
  507. ALCcontext *Context;
  508. Context = GetContextRef();
  509. if(!Context) return;
  510. if(ExchangeInt(&Context->DeferUpdates, AL_FALSE))
  511. {
  512. ALsizei pos;
  513. LockContext(Context);
  514. LockUIntMapRead(&Context->SourceMap);
  515. for(pos = 0;pos < Context->SourceMap.size;pos++)
  516. {
  517. ALsource *Source = Context->SourceMap.array[pos].value;
  518. ALenum new_state;
  519. if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
  520. Source->lOffset != -1)
  521. ApplyOffset(Source);
  522. new_state = ExchangeInt(&Source->new_state, AL_NONE);
  523. if(new_state)
  524. SetSourceState(Source, Context, new_state);
  525. }
  526. UnlockUIntMapRead(&Context->SourceMap);
  527. UnlockContext(Context);
  528. }
  529. ALCcontext_DecRef(Context);
  530. }