alSource.c 63 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217
  1. /**
  2. * OpenAL cross platform audio library
  3. * Copyright (C) 1999-2007 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 <math.h>
  23. #include <float.h>
  24. #include "alMain.h"
  25. #include "AL/al.h"
  26. #include "AL/alc.h"
  27. #include "alError.h"
  28. #include "alSource.h"
  29. #include "alBuffer.h"
  30. #include "alThunk.h"
  31. #include "alAuxEffectSlot.h"
  32. enum Resampler DefaultResampler = LinearResampler;
  33. const ALsizei ResamplerPadding[ResamplerMax] = {
  34. 0, /* Point */
  35. 1, /* Linear */
  36. 2, /* Cubic */
  37. };
  38. const ALsizei ResamplerPrePadding[ResamplerMax] = {
  39. 0, /* Point */
  40. 0, /* Linear */
  41. 1, /* Cubic */
  42. };
  43. static ALvoid InitSourceParams(ALsource *Source);
  44. static ALvoid GetSourceOffset(ALsource *Source, ALenum eName, ALdouble *Offsets, ALdouble updateLen);
  45. static ALint GetSampleOffset(ALsource *Source);
  46. AL_API ALvoid AL_APIENTRY alGenSources(ALsizei n,ALuint *sources)
  47. {
  48. ALCcontext *Context;
  49. Context = GetContextRef();
  50. if(!Context) return;
  51. if(n < 0 || IsBadWritePtr((void*)sources, n * sizeof(ALuint)))
  52. alSetError(Context, AL_INVALID_VALUE);
  53. else
  54. {
  55. ALenum err;
  56. ALsizei i;
  57. // Add additional sources to the list
  58. i = 0;
  59. while(i < n)
  60. {
  61. ALsource *source = calloc(1, sizeof(ALsource));
  62. if(!source)
  63. {
  64. alSetError(Context, AL_OUT_OF_MEMORY);
  65. alDeleteSources(i, sources);
  66. break;
  67. }
  68. InitSourceParams(source);
  69. err = NewThunkEntry(&source->source);
  70. if(err == AL_NO_ERROR)
  71. err = InsertUIntMapEntry(&Context->SourceMap, source->source, source);
  72. if(err != AL_NO_ERROR)
  73. {
  74. FreeThunkEntry(source->source);
  75. memset(source, 0, sizeof(ALsource));
  76. free(source);
  77. alSetError(Context, err);
  78. alDeleteSources(i, sources);
  79. break;
  80. }
  81. sources[i++] = source->source;
  82. }
  83. }
  84. ALCcontext_DecRef(Context);
  85. }
  86. AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
  87. {
  88. ALCcontext *Context;
  89. ALsource *Source;
  90. ALsizei i, j;
  91. ALbufferlistitem *BufferList;
  92. Context = GetContextRef();
  93. if(!Context) return;
  94. if(n < 0)
  95. alSetError(Context, AL_INVALID_VALUE);
  96. else
  97. {
  98. // Check that all Sources are valid (and can therefore be deleted)
  99. for(i = 0;i < n;i++)
  100. {
  101. if(LookupSource(Context, sources[i]) == NULL)
  102. {
  103. alSetError(Context, AL_INVALID_NAME);
  104. n = 0;
  105. break;
  106. }
  107. }
  108. // All Sources are valid, and can be deleted
  109. for(i = 0;i < n;i++)
  110. {
  111. ALsource **srclist, **srclistend;
  112. // Remove Source from list of Sources
  113. if((Source=RemoveSource(Context, sources[i])) == NULL)
  114. continue;
  115. FreeThunkEntry(Source->source);
  116. LockContext(Context);
  117. srclist = Context->ActiveSources;
  118. srclistend = srclist + Context->ActiveSourceCount;
  119. while(srclist != srclistend)
  120. {
  121. if(*srclist == Source)
  122. {
  123. Context->ActiveSourceCount--;
  124. *srclist = *(--srclistend);
  125. break;
  126. }
  127. srclist++;
  128. }
  129. UnlockContext(Context);
  130. // For each buffer in the source's queue...
  131. while(Source->queue != NULL)
  132. {
  133. BufferList = Source->queue;
  134. Source->queue = BufferList->next;
  135. if(BufferList->buffer != NULL)
  136. DecrementRef(&BufferList->buffer->ref);
  137. free(BufferList);
  138. }
  139. for(j = 0;j < MAX_SENDS;++j)
  140. {
  141. if(Source->Send[j].Slot)
  142. DecrementRef(&Source->Send[j].Slot->ref);
  143. Source->Send[j].Slot = NULL;
  144. }
  145. memset(Source,0,sizeof(ALsource));
  146. free(Source);
  147. }
  148. }
  149. ALCcontext_DecRef(Context);
  150. }
  151. AL_API ALboolean AL_APIENTRY alIsSource(ALuint source)
  152. {
  153. ALCcontext *Context;
  154. ALboolean result;
  155. Context = GetContextRef();
  156. if(!Context) return AL_FALSE;
  157. result = (LookupSource(Context, source) ? AL_TRUE : AL_FALSE);
  158. ALCcontext_DecRef(Context);
  159. return result;
  160. }
  161. AL_API ALvoid AL_APIENTRY alSourcef(ALuint source, ALenum eParam, ALfloat flValue)
  162. {
  163. ALCcontext *pContext;
  164. ALsource *Source;
  165. pContext = GetContextRef();
  166. if(!pContext) return;
  167. if((Source=LookupSource(pContext, source)) != NULL)
  168. {
  169. switch(eParam)
  170. {
  171. case AL_PITCH:
  172. if(flValue >= 0.0f)
  173. {
  174. Source->flPitch = flValue;
  175. Source->NeedsUpdate = AL_TRUE;
  176. }
  177. else
  178. alSetError(pContext, AL_INVALID_VALUE);
  179. break;
  180. case AL_CONE_INNER_ANGLE:
  181. if(flValue >= 0.0f && flValue <= 360.0f)
  182. {
  183. Source->flInnerAngle = flValue;
  184. Source->NeedsUpdate = AL_TRUE;
  185. }
  186. else
  187. alSetError(pContext, AL_INVALID_VALUE);
  188. break;
  189. case AL_CONE_OUTER_ANGLE:
  190. if(flValue >= 0.0f && flValue <= 360.0f)
  191. {
  192. Source->flOuterAngle = flValue;
  193. Source->NeedsUpdate = AL_TRUE;
  194. }
  195. else
  196. alSetError(pContext, AL_INVALID_VALUE);
  197. break;
  198. case AL_GAIN:
  199. if(flValue >= 0.0f)
  200. {
  201. Source->flGain = flValue;
  202. Source->NeedsUpdate = AL_TRUE;
  203. }
  204. else
  205. alSetError(pContext, AL_INVALID_VALUE);
  206. break;
  207. case AL_MAX_DISTANCE:
  208. if(flValue >= 0.0f)
  209. {
  210. Source->flMaxDistance = flValue;
  211. Source->NeedsUpdate = AL_TRUE;
  212. }
  213. else
  214. alSetError(pContext, AL_INVALID_VALUE);
  215. break;
  216. case AL_ROLLOFF_FACTOR:
  217. if(flValue >= 0.0f)
  218. {
  219. Source->flRollOffFactor = flValue;
  220. Source->NeedsUpdate = AL_TRUE;
  221. }
  222. else
  223. alSetError(pContext, AL_INVALID_VALUE);
  224. break;
  225. case AL_REFERENCE_DISTANCE:
  226. if(flValue >= 0.0f)
  227. {
  228. Source->flRefDistance = flValue;
  229. Source->NeedsUpdate = AL_TRUE;
  230. }
  231. else
  232. alSetError(pContext, AL_INVALID_VALUE);
  233. break;
  234. case AL_MIN_GAIN:
  235. if(flValue >= 0.0f && flValue <= 1.0f)
  236. {
  237. Source->flMinGain = flValue;
  238. Source->NeedsUpdate = AL_TRUE;
  239. }
  240. else
  241. alSetError(pContext, AL_INVALID_VALUE);
  242. break;
  243. case AL_MAX_GAIN:
  244. if(flValue >= 0.0f && flValue <= 1.0f)
  245. {
  246. Source->flMaxGain = flValue;
  247. Source->NeedsUpdate = AL_TRUE;
  248. }
  249. else
  250. alSetError(pContext, AL_INVALID_VALUE);
  251. break;
  252. case AL_CONE_OUTER_GAIN:
  253. if(flValue >= 0.0f && flValue <= 1.0f)
  254. {
  255. Source->flOuterGain = flValue;
  256. Source->NeedsUpdate = AL_TRUE;
  257. }
  258. else
  259. alSetError(pContext, AL_INVALID_VALUE);
  260. break;
  261. case AL_CONE_OUTER_GAINHF:
  262. if(flValue >= 0.0f && flValue <= 1.0f)
  263. {
  264. Source->OuterGainHF = flValue;
  265. Source->NeedsUpdate = AL_TRUE;
  266. }
  267. else
  268. alSetError(pContext, AL_INVALID_VALUE);
  269. break;
  270. case AL_AIR_ABSORPTION_FACTOR:
  271. if(flValue >= 0.0f && flValue <= 10.0f)
  272. {
  273. Source->AirAbsorptionFactor = flValue;
  274. Source->NeedsUpdate = AL_TRUE;
  275. }
  276. else
  277. alSetError(pContext, AL_INVALID_VALUE);
  278. break;
  279. case AL_ROOM_ROLLOFF_FACTOR:
  280. if(flValue >= 0.0f && flValue <= 10.0f)
  281. {
  282. Source->RoomRolloffFactor = flValue;
  283. Source->NeedsUpdate = AL_TRUE;
  284. }
  285. else
  286. alSetError(pContext, AL_INVALID_VALUE);
  287. break;
  288. case AL_DOPPLER_FACTOR:
  289. if(flValue >= 0.0f && flValue <= 1.0f)
  290. {
  291. Source->DopplerFactor = flValue;
  292. Source->NeedsUpdate = AL_TRUE;
  293. }
  294. else
  295. alSetError(pContext, AL_INVALID_VALUE);
  296. break;
  297. case AL_SEC_OFFSET:
  298. case AL_SAMPLE_OFFSET:
  299. case AL_BYTE_OFFSET:
  300. if(flValue >= 0.0f)
  301. {
  302. LockContext(pContext);
  303. Source->lOffsetType = eParam;
  304. // Store Offset (convert Seconds into Milliseconds)
  305. if(eParam == AL_SEC_OFFSET)
  306. Source->lOffset = (ALint)(flValue * 1000.0f);
  307. else
  308. Source->lOffset = (ALint)flValue;
  309. if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
  310. !pContext->DeferUpdates)
  311. {
  312. if(ApplyOffset(Source) == AL_FALSE)
  313. alSetError(pContext, AL_INVALID_VALUE);
  314. }
  315. UnlockContext(pContext);
  316. }
  317. else
  318. alSetError(pContext, AL_INVALID_VALUE);
  319. break;
  320. default:
  321. alSetError(pContext, AL_INVALID_ENUM);
  322. break;
  323. }
  324. }
  325. else
  326. {
  327. // Invalid Source Name
  328. alSetError(pContext, AL_INVALID_NAME);
  329. }
  330. ALCcontext_DecRef(pContext);
  331. }
  332. AL_API ALvoid AL_APIENTRY alSource3f(ALuint source, ALenum eParam, ALfloat flValue1,ALfloat flValue2,ALfloat flValue3)
  333. {
  334. ALCcontext *pContext;
  335. ALsource *Source;
  336. pContext = GetContextRef();
  337. if(!pContext) return;
  338. if((Source=LookupSource(pContext, source)) != NULL)
  339. {
  340. switch(eParam)
  341. {
  342. case AL_POSITION:
  343. if(isfinite(flValue1) && isfinite(flValue2) && isfinite(flValue3))
  344. {
  345. LockContext(pContext);
  346. Source->vPosition[0] = flValue1;
  347. Source->vPosition[1] = flValue2;
  348. Source->vPosition[2] = flValue3;
  349. UnlockContext(pContext);
  350. Source->NeedsUpdate = AL_TRUE;
  351. }
  352. else
  353. alSetError(pContext, AL_INVALID_VALUE);
  354. break;
  355. case AL_VELOCITY:
  356. if(isfinite(flValue1) && isfinite(flValue2) && isfinite(flValue3))
  357. {
  358. LockContext(pContext);
  359. Source->vVelocity[0] = flValue1;
  360. Source->vVelocity[1] = flValue2;
  361. Source->vVelocity[2] = flValue3;
  362. UnlockContext(pContext);
  363. Source->NeedsUpdate = AL_TRUE;
  364. }
  365. else
  366. alSetError(pContext, AL_INVALID_VALUE);
  367. break;
  368. case AL_DIRECTION:
  369. if(isfinite(flValue1) && isfinite(flValue2) && isfinite(flValue3))
  370. {
  371. LockContext(pContext);
  372. Source->vOrientation[0] = flValue1;
  373. Source->vOrientation[1] = flValue2;
  374. Source->vOrientation[2] = flValue3;
  375. UnlockContext(pContext);
  376. Source->NeedsUpdate = AL_TRUE;
  377. }
  378. else
  379. alSetError(pContext, AL_INVALID_VALUE);
  380. break;
  381. default:
  382. alSetError(pContext, AL_INVALID_ENUM);
  383. break;
  384. }
  385. }
  386. else
  387. alSetError(pContext, AL_INVALID_NAME);
  388. ALCcontext_DecRef(pContext);
  389. }
  390. AL_API ALvoid AL_APIENTRY alSourcefv(ALuint source, ALenum eParam, const ALfloat *pflValues)
  391. {
  392. ALCcontext *pContext;
  393. if(pflValues)
  394. {
  395. switch(eParam)
  396. {
  397. case AL_PITCH:
  398. case AL_CONE_INNER_ANGLE:
  399. case AL_CONE_OUTER_ANGLE:
  400. case AL_GAIN:
  401. case AL_MAX_DISTANCE:
  402. case AL_ROLLOFF_FACTOR:
  403. case AL_REFERENCE_DISTANCE:
  404. case AL_MIN_GAIN:
  405. case AL_MAX_GAIN:
  406. case AL_CONE_OUTER_GAIN:
  407. case AL_CONE_OUTER_GAINHF:
  408. case AL_SEC_OFFSET:
  409. case AL_SAMPLE_OFFSET:
  410. case AL_BYTE_OFFSET:
  411. case AL_AIR_ABSORPTION_FACTOR:
  412. case AL_ROOM_ROLLOFF_FACTOR:
  413. alSourcef(source, eParam, pflValues[0]);
  414. return;
  415. case AL_POSITION:
  416. case AL_VELOCITY:
  417. case AL_DIRECTION:
  418. alSource3f(source, eParam, pflValues[0], pflValues[1], pflValues[2]);
  419. return;
  420. }
  421. }
  422. pContext = GetContextRef();
  423. if(!pContext) return;
  424. if(pflValues)
  425. {
  426. if(LookupSource(pContext, source) != NULL)
  427. {
  428. switch(eParam)
  429. {
  430. default:
  431. alSetError(pContext, AL_INVALID_ENUM);
  432. break;
  433. }
  434. }
  435. else
  436. alSetError(pContext, AL_INVALID_NAME);
  437. }
  438. else
  439. alSetError(pContext, AL_INVALID_VALUE);
  440. ALCcontext_DecRef(pContext);
  441. }
  442. AL_API ALvoid AL_APIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue)
  443. {
  444. ALCcontext *pContext;
  445. ALsource *Source;
  446. ALbufferlistitem *BufferListItem;
  447. switch(eParam)
  448. {
  449. case AL_MAX_DISTANCE:
  450. case AL_ROLLOFF_FACTOR:
  451. case AL_CONE_INNER_ANGLE:
  452. case AL_CONE_OUTER_ANGLE:
  453. case AL_REFERENCE_DISTANCE:
  454. alSourcef(source, eParam, (ALfloat)lValue);
  455. return;
  456. }
  457. pContext = GetContextRef();
  458. if(!pContext) return;
  459. if((Source=LookupSource(pContext, source)) != NULL)
  460. {
  461. ALCdevice *device = pContext->Device;
  462. switch(eParam)
  463. {
  464. case AL_SOURCE_RELATIVE:
  465. if(lValue == AL_FALSE || lValue == AL_TRUE)
  466. {
  467. Source->bHeadRelative = (ALboolean)lValue;
  468. Source->NeedsUpdate = AL_TRUE;
  469. }
  470. else
  471. alSetError(pContext, AL_INVALID_VALUE);
  472. break;
  473. case AL_LOOPING:
  474. if(lValue == AL_FALSE || lValue == AL_TRUE)
  475. Source->bLooping = (ALboolean)lValue;
  476. else
  477. alSetError(pContext, AL_INVALID_VALUE);
  478. break;
  479. case AL_BUFFER:
  480. LockContext(pContext);
  481. if(Source->state == AL_STOPPED || Source->state == AL_INITIAL)
  482. {
  483. ALbufferlistitem *oldlist;
  484. ALbuffer *buffer = NULL;
  485. if(lValue == 0 || (buffer=LookupBuffer(device, lValue)) != NULL)
  486. {
  487. Source->BuffersInQueue = 0;
  488. Source->BuffersPlayed = 0;
  489. // Add the buffer to the queue (as long as it is NOT the NULL buffer)
  490. if(buffer != NULL)
  491. {
  492. // Source is now in STATIC mode
  493. Source->lSourceType = AL_STATIC;
  494. // Add the selected buffer to the queue
  495. BufferListItem = malloc(sizeof(ALbufferlistitem));
  496. BufferListItem->buffer = buffer;
  497. BufferListItem->next = NULL;
  498. BufferListItem->prev = NULL;
  499. // Increment reference counter for buffer
  500. IncrementRef(&buffer->ref);
  501. oldlist = ExchangePtr((XchgPtr*)&Source->queue, BufferListItem);
  502. Source->BuffersInQueue = 1;
  503. ReadLock(&buffer->lock);
  504. Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
  505. Source->SampleSize = BytesFromFmt(buffer->FmtType);
  506. ReadUnlock(&buffer->lock);
  507. if(buffer->FmtChannels == FmtMono)
  508. Source->Update = CalcSourceParams;
  509. else
  510. Source->Update = CalcNonAttnSourceParams;
  511. Source->NeedsUpdate = AL_TRUE;
  512. }
  513. else
  514. {
  515. // Source is now in UNDETERMINED mode
  516. Source->lSourceType = AL_UNDETERMINED;
  517. oldlist = ExchangePtr((XchgPtr*)&Source->queue, NULL);
  518. }
  519. // Delete all previous elements in the queue
  520. while(oldlist != NULL)
  521. {
  522. BufferListItem = oldlist;
  523. oldlist = BufferListItem->next;
  524. if(BufferListItem->buffer)
  525. DecrementRef(&BufferListItem->buffer->ref);
  526. free(BufferListItem);
  527. }
  528. }
  529. else
  530. alSetError(pContext, AL_INVALID_VALUE);
  531. }
  532. else
  533. alSetError(pContext, AL_INVALID_OPERATION);
  534. UnlockContext(pContext);
  535. break;
  536. case AL_SOURCE_STATE:
  537. // Query only
  538. alSetError(pContext, AL_INVALID_OPERATION);
  539. break;
  540. case AL_SEC_OFFSET:
  541. case AL_SAMPLE_OFFSET:
  542. case AL_BYTE_OFFSET:
  543. if(lValue >= 0)
  544. {
  545. LockContext(pContext);
  546. Source->lOffsetType = eParam;
  547. // Store Offset (convert Seconds into Milliseconds)
  548. if(eParam == AL_SEC_OFFSET)
  549. Source->lOffset = lValue * 1000;
  550. else
  551. Source->lOffset = lValue;
  552. if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
  553. !pContext->DeferUpdates)
  554. {
  555. if(ApplyOffset(Source) == AL_FALSE)
  556. alSetError(pContext, AL_INVALID_VALUE);
  557. }
  558. UnlockContext(pContext);
  559. }
  560. else
  561. alSetError(pContext, AL_INVALID_VALUE);
  562. break;
  563. case AL_DIRECT_FILTER: {
  564. ALfilter *filter = NULL;
  565. if(lValue == 0 || (filter=LookupFilter(pContext->Device, lValue)) != NULL)
  566. {
  567. LockContext(pContext);
  568. if(!filter)
  569. {
  570. Source->DirectGain = 1.0f;
  571. Source->DirectGainHF = 1.0f;
  572. }
  573. else
  574. {
  575. Source->DirectGain = filter->Gain;
  576. Source->DirectGainHF = filter->GainHF;
  577. }
  578. UnlockContext(pContext);
  579. Source->NeedsUpdate = AL_TRUE;
  580. }
  581. else
  582. alSetError(pContext, AL_INVALID_VALUE);
  583. } break;
  584. case AL_DIRECT_FILTER_GAINHF_AUTO:
  585. if(lValue == AL_TRUE || lValue == AL_FALSE)
  586. {
  587. Source->DryGainHFAuto = lValue;
  588. Source->NeedsUpdate = AL_TRUE;
  589. }
  590. else
  591. alSetError(pContext, AL_INVALID_VALUE);
  592. break;
  593. case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
  594. if(lValue == AL_TRUE || lValue == AL_FALSE)
  595. {
  596. Source->WetGainAuto = lValue;
  597. Source->NeedsUpdate = AL_TRUE;
  598. }
  599. else
  600. alSetError(pContext, AL_INVALID_VALUE);
  601. break;
  602. case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
  603. if(lValue == AL_TRUE || lValue == AL_FALSE)
  604. {
  605. Source->WetGainHFAuto = lValue;
  606. Source->NeedsUpdate = AL_TRUE;
  607. }
  608. else
  609. alSetError(pContext, AL_INVALID_VALUE);
  610. break;
  611. case AL_DIRECT_CHANNELS_SOFT:
  612. if(lValue == AL_TRUE || lValue == AL_FALSE)
  613. {
  614. Source->DirectChannels = lValue;
  615. Source->NeedsUpdate = AL_TRUE;
  616. }
  617. else
  618. alSetError(pContext, AL_INVALID_VALUE);
  619. break;
  620. case AL_DISTANCE_MODEL:
  621. if(lValue == AL_NONE ||
  622. lValue == AL_INVERSE_DISTANCE ||
  623. lValue == AL_INVERSE_DISTANCE_CLAMPED ||
  624. lValue == AL_LINEAR_DISTANCE ||
  625. lValue == AL_LINEAR_DISTANCE_CLAMPED ||
  626. lValue == AL_EXPONENT_DISTANCE ||
  627. lValue == AL_EXPONENT_DISTANCE_CLAMPED)
  628. {
  629. Source->DistanceModel = lValue;
  630. if(pContext->SourceDistanceModel)
  631. Source->NeedsUpdate = AL_TRUE;
  632. }
  633. else
  634. alSetError(pContext, AL_INVALID_VALUE);
  635. break;
  636. default:
  637. alSetError(pContext, AL_INVALID_ENUM);
  638. break;
  639. }
  640. }
  641. else
  642. alSetError(pContext, AL_INVALID_NAME);
  643. ALCcontext_DecRef(pContext);
  644. }
  645. AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum eParam, ALint lValue1, ALint lValue2, ALint lValue3)
  646. {
  647. ALCcontext *pContext;
  648. ALsource *Source;
  649. switch(eParam)
  650. {
  651. case AL_POSITION:
  652. case AL_VELOCITY:
  653. case AL_DIRECTION:
  654. alSource3f(source, eParam, (ALfloat)lValue1, (ALfloat)lValue2, (ALfloat)lValue3);
  655. return;
  656. }
  657. pContext = GetContextRef();
  658. if(!pContext) return;
  659. if((Source=LookupSource(pContext, source)) != NULL)
  660. {
  661. ALCdevice *device = pContext->Device;
  662. switch(eParam)
  663. {
  664. case AL_AUXILIARY_SEND_FILTER: {
  665. ALeffectslot *ALEffectSlot = NULL;
  666. ALfilter *ALFilter = NULL;
  667. LockContext(pContext);
  668. if((ALuint)lValue2 < device->NumAuxSends &&
  669. (lValue1 == 0 || (ALEffectSlot=LookupEffectSlot(pContext, lValue1)) != NULL) &&
  670. (lValue3 == 0 || (ALFilter=LookupFilter(device, lValue3)) != NULL))
  671. {
  672. /* Release refcount on the previous slot, and add one for
  673. * the new slot */
  674. if(ALEffectSlot) IncrementRef(&ALEffectSlot->ref);
  675. ALEffectSlot = ExchangePtr((XchgPtr*)&Source->Send[lValue2].Slot, ALEffectSlot);
  676. if(ALEffectSlot) DecrementRef(&ALEffectSlot->ref);
  677. if(!ALFilter)
  678. {
  679. /* Disable filter */
  680. Source->Send[lValue2].WetGain = 1.0f;
  681. Source->Send[lValue2].WetGainHF = 1.0f;
  682. }
  683. else
  684. {
  685. Source->Send[lValue2].WetGain = ALFilter->Gain;
  686. Source->Send[lValue2].WetGainHF = ALFilter->GainHF;
  687. }
  688. Source->NeedsUpdate = AL_TRUE;
  689. }
  690. else
  691. alSetError(pContext, AL_INVALID_VALUE);
  692. UnlockContext(pContext);
  693. } break;
  694. default:
  695. alSetError(pContext, AL_INVALID_ENUM);
  696. break;
  697. }
  698. }
  699. else
  700. alSetError(pContext, AL_INVALID_NAME);
  701. ALCcontext_DecRef(pContext);
  702. }
  703. AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum eParam, const ALint* plValues)
  704. {
  705. ALCcontext *pContext;
  706. if(plValues)
  707. {
  708. switch(eParam)
  709. {
  710. case AL_SOURCE_RELATIVE:
  711. case AL_CONE_INNER_ANGLE:
  712. case AL_CONE_OUTER_ANGLE:
  713. case AL_LOOPING:
  714. case AL_BUFFER:
  715. case AL_SOURCE_STATE:
  716. case AL_SEC_OFFSET:
  717. case AL_SAMPLE_OFFSET:
  718. case AL_BYTE_OFFSET:
  719. case AL_MAX_DISTANCE:
  720. case AL_ROLLOFF_FACTOR:
  721. case AL_REFERENCE_DISTANCE:
  722. case AL_DIRECT_FILTER:
  723. case AL_DIRECT_FILTER_GAINHF_AUTO:
  724. case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
  725. case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
  726. case AL_DISTANCE_MODEL:
  727. case AL_DIRECT_CHANNELS_SOFT:
  728. alSourcei(source, eParam, plValues[0]);
  729. return;
  730. case AL_POSITION:
  731. case AL_VELOCITY:
  732. case AL_DIRECTION:
  733. case AL_AUXILIARY_SEND_FILTER:
  734. alSource3i(source, eParam, plValues[0], plValues[1], plValues[2]);
  735. return;
  736. }
  737. }
  738. pContext = GetContextRef();
  739. if(!pContext) return;
  740. if(plValues)
  741. {
  742. if(LookupSource(pContext, source) != NULL)
  743. {
  744. switch(eParam)
  745. {
  746. default:
  747. alSetError(pContext, AL_INVALID_ENUM);
  748. break;
  749. }
  750. }
  751. else
  752. alSetError(pContext, AL_INVALID_NAME);
  753. }
  754. else
  755. alSetError(pContext, AL_INVALID_VALUE);
  756. ALCcontext_DecRef(pContext);
  757. }
  758. AL_API ALvoid AL_APIENTRY alGetSourcef(ALuint source, ALenum eParam, ALfloat *pflValue)
  759. {
  760. ALCcontext *pContext;
  761. ALsource *Source;
  762. ALdouble Offsets[2];
  763. ALdouble updateLen;
  764. pContext = GetContextRef();
  765. if(!pContext) return;
  766. if(pflValue)
  767. {
  768. if((Source=LookupSource(pContext, source)) != NULL)
  769. {
  770. switch(eParam)
  771. {
  772. case AL_PITCH:
  773. *pflValue = Source->flPitch;
  774. break;
  775. case AL_GAIN:
  776. *pflValue = Source->flGain;
  777. break;
  778. case AL_MIN_GAIN:
  779. *pflValue = Source->flMinGain;
  780. break;
  781. case AL_MAX_GAIN:
  782. *pflValue = Source->flMaxGain;
  783. break;
  784. case AL_MAX_DISTANCE:
  785. *pflValue = Source->flMaxDistance;
  786. break;
  787. case AL_ROLLOFF_FACTOR:
  788. *pflValue = Source->flRollOffFactor;
  789. break;
  790. case AL_CONE_OUTER_GAIN:
  791. *pflValue = Source->flOuterGain;
  792. break;
  793. case AL_CONE_OUTER_GAINHF:
  794. *pflValue = Source->OuterGainHF;
  795. break;
  796. case AL_SEC_OFFSET:
  797. case AL_SAMPLE_OFFSET:
  798. case AL_BYTE_OFFSET:
  799. LockContext(pContext);
  800. updateLen = (ALdouble)pContext->Device->UpdateSize /
  801. pContext->Device->Frequency;
  802. GetSourceOffset(Source, eParam, Offsets, updateLen);
  803. UnlockContext(pContext);
  804. *pflValue = (ALfloat)Offsets[0];
  805. break;
  806. case AL_CONE_INNER_ANGLE:
  807. *pflValue = Source->flInnerAngle;
  808. break;
  809. case AL_CONE_OUTER_ANGLE:
  810. *pflValue = Source->flOuterAngle;
  811. break;
  812. case AL_REFERENCE_DISTANCE:
  813. *pflValue = Source->flRefDistance;
  814. break;
  815. case AL_AIR_ABSORPTION_FACTOR:
  816. *pflValue = Source->AirAbsorptionFactor;
  817. break;
  818. case AL_ROOM_ROLLOFF_FACTOR:
  819. *pflValue = Source->RoomRolloffFactor;
  820. break;
  821. case AL_DOPPLER_FACTOR:
  822. *pflValue = Source->DopplerFactor;
  823. break;
  824. default:
  825. alSetError(pContext, AL_INVALID_ENUM);
  826. break;
  827. }
  828. }
  829. else
  830. alSetError(pContext, AL_INVALID_NAME);
  831. }
  832. else
  833. alSetError(pContext, AL_INVALID_VALUE);
  834. ALCcontext_DecRef(pContext);
  835. }
  836. AL_API ALvoid AL_APIENTRY alGetSource3f(ALuint source, ALenum eParam, ALfloat* pflValue1, ALfloat* pflValue2, ALfloat* pflValue3)
  837. {
  838. ALCcontext *pContext;
  839. ALsource *Source;
  840. pContext = GetContextRef();
  841. if(!pContext) return;
  842. if(pflValue1 && pflValue2 && pflValue3)
  843. {
  844. if((Source=LookupSource(pContext, source)) != NULL)
  845. {
  846. switch(eParam)
  847. {
  848. case AL_POSITION:
  849. LockContext(pContext);
  850. *pflValue1 = Source->vPosition[0];
  851. *pflValue2 = Source->vPosition[1];
  852. *pflValue3 = Source->vPosition[2];
  853. UnlockContext(pContext);
  854. break;
  855. case AL_VELOCITY:
  856. LockContext(pContext);
  857. *pflValue1 = Source->vVelocity[0];
  858. *pflValue2 = Source->vVelocity[1];
  859. *pflValue3 = Source->vVelocity[2];
  860. UnlockContext(pContext);
  861. break;
  862. case AL_DIRECTION:
  863. LockContext(pContext);
  864. *pflValue1 = Source->vOrientation[0];
  865. *pflValue2 = Source->vOrientation[1];
  866. *pflValue3 = Source->vOrientation[2];
  867. UnlockContext(pContext);
  868. break;
  869. default:
  870. alSetError(pContext, AL_INVALID_ENUM);
  871. break;
  872. }
  873. }
  874. else
  875. alSetError(pContext, AL_INVALID_NAME);
  876. }
  877. else
  878. alSetError(pContext, AL_INVALID_VALUE);
  879. ALCcontext_DecRef(pContext);
  880. }
  881. AL_API ALvoid AL_APIENTRY alGetSourcefv(ALuint source, ALenum eParam, ALfloat *pflValues)
  882. {
  883. ALCcontext *pContext;
  884. ALsource *Source;
  885. ALdouble Offsets[2];
  886. ALdouble updateLen;
  887. switch(eParam)
  888. {
  889. case AL_PITCH:
  890. case AL_GAIN:
  891. case AL_MIN_GAIN:
  892. case AL_MAX_GAIN:
  893. case AL_MAX_DISTANCE:
  894. case AL_ROLLOFF_FACTOR:
  895. case AL_DOPPLER_FACTOR:
  896. case AL_CONE_OUTER_GAIN:
  897. case AL_SEC_OFFSET:
  898. case AL_SAMPLE_OFFSET:
  899. case AL_BYTE_OFFSET:
  900. case AL_CONE_INNER_ANGLE:
  901. case AL_CONE_OUTER_ANGLE:
  902. case AL_REFERENCE_DISTANCE:
  903. case AL_CONE_OUTER_GAINHF:
  904. case AL_AIR_ABSORPTION_FACTOR:
  905. case AL_ROOM_ROLLOFF_FACTOR:
  906. alGetSourcef(source, eParam, pflValues);
  907. return;
  908. case AL_POSITION:
  909. case AL_VELOCITY:
  910. case AL_DIRECTION:
  911. alGetSource3f(source, eParam, pflValues+0, pflValues+1, pflValues+2);
  912. return;
  913. }
  914. pContext = GetContextRef();
  915. if(!pContext) return;
  916. if(pflValues)
  917. {
  918. if((Source=LookupSource(pContext, source)) != NULL)
  919. {
  920. switch(eParam)
  921. {
  922. case AL_SAMPLE_RW_OFFSETS_SOFT:
  923. case AL_BYTE_RW_OFFSETS_SOFT:
  924. LockContext(pContext);
  925. updateLen = (ALdouble)pContext->Device->UpdateSize /
  926. pContext->Device->Frequency;
  927. GetSourceOffset(Source, eParam, Offsets, updateLen);
  928. UnlockContext(pContext);
  929. pflValues[0] = (ALfloat)Offsets[0];
  930. pflValues[1] = (ALfloat)Offsets[1];
  931. break;
  932. default:
  933. alSetError(pContext, AL_INVALID_ENUM);
  934. break;
  935. }
  936. }
  937. else
  938. alSetError(pContext, AL_INVALID_NAME);
  939. }
  940. else
  941. alSetError(pContext, AL_INVALID_VALUE);
  942. ALCcontext_DecRef(pContext);
  943. }
  944. AL_API ALvoid AL_APIENTRY alGetSourcei(ALuint source, ALenum eParam, ALint *plValue)
  945. {
  946. ALbufferlistitem *BufferList;
  947. ALCcontext *pContext;
  948. ALsource *Source;
  949. ALdouble Offsets[2];
  950. ALdouble updateLen;
  951. pContext = GetContextRef();
  952. if(!pContext) return;
  953. if(plValue)
  954. {
  955. if((Source=LookupSource(pContext, source)) != NULL)
  956. {
  957. switch(eParam)
  958. {
  959. case AL_MAX_DISTANCE:
  960. *plValue = (ALint)Source->flMaxDistance;
  961. break;
  962. case AL_ROLLOFF_FACTOR:
  963. *plValue = (ALint)Source->flRollOffFactor;
  964. break;
  965. case AL_REFERENCE_DISTANCE:
  966. *plValue = (ALint)Source->flRefDistance;
  967. break;
  968. case AL_SOURCE_RELATIVE:
  969. *plValue = Source->bHeadRelative;
  970. break;
  971. case AL_CONE_INNER_ANGLE:
  972. *plValue = (ALint)Source->flInnerAngle;
  973. break;
  974. case AL_CONE_OUTER_ANGLE:
  975. *plValue = (ALint)Source->flOuterAngle;
  976. break;
  977. case AL_LOOPING:
  978. *plValue = Source->bLooping;
  979. break;
  980. case AL_BUFFER:
  981. LockContext(pContext);
  982. BufferList = Source->queue;
  983. if(Source->lSourceType != AL_STATIC)
  984. {
  985. ALuint i = Source->BuffersPlayed;
  986. while(i > 0)
  987. {
  988. BufferList = BufferList->next;
  989. i--;
  990. }
  991. }
  992. *plValue = ((BufferList && BufferList->buffer) ?
  993. BufferList->buffer->buffer : 0);
  994. UnlockContext(pContext);
  995. break;
  996. case AL_SOURCE_STATE:
  997. *plValue = Source->state;
  998. break;
  999. case AL_BUFFERS_QUEUED:
  1000. *plValue = Source->BuffersInQueue;
  1001. break;
  1002. case AL_BUFFERS_PROCESSED:
  1003. LockContext(pContext);
  1004. if(Source->bLooping || Source->lSourceType != AL_STREAMING)
  1005. {
  1006. /* Buffers on a looping source are in a perpetual state
  1007. * of PENDING, so don't report any as PROCESSED */
  1008. *plValue = 0;
  1009. }
  1010. else
  1011. *plValue = Source->BuffersPlayed;
  1012. UnlockContext(pContext);
  1013. break;
  1014. case AL_SOURCE_TYPE:
  1015. *plValue = Source->lSourceType;
  1016. break;
  1017. case AL_SEC_OFFSET:
  1018. case AL_SAMPLE_OFFSET:
  1019. case AL_BYTE_OFFSET:
  1020. LockContext(pContext);
  1021. updateLen = (ALdouble)pContext->Device->UpdateSize /
  1022. pContext->Device->Frequency;
  1023. GetSourceOffset(Source, eParam, Offsets, updateLen);
  1024. UnlockContext(pContext);
  1025. *plValue = (ALint)Offsets[0];
  1026. break;
  1027. case AL_DIRECT_FILTER_GAINHF_AUTO:
  1028. *plValue = Source->DryGainHFAuto;
  1029. break;
  1030. case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
  1031. *plValue = Source->WetGainAuto;
  1032. break;
  1033. case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
  1034. *plValue = Source->WetGainHFAuto;
  1035. break;
  1036. case AL_DOPPLER_FACTOR:
  1037. *plValue = (ALint)Source->DopplerFactor;
  1038. break;
  1039. case AL_DIRECT_CHANNELS_SOFT:
  1040. *plValue = Source->DirectChannels;
  1041. break;
  1042. case AL_DISTANCE_MODEL:
  1043. *plValue = Source->DistanceModel;
  1044. break;
  1045. default:
  1046. alSetError(pContext, AL_INVALID_ENUM);
  1047. break;
  1048. }
  1049. }
  1050. else
  1051. alSetError(pContext, AL_INVALID_NAME);
  1052. }
  1053. else
  1054. alSetError(pContext, AL_INVALID_VALUE);
  1055. ALCcontext_DecRef(pContext);
  1056. }
  1057. AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum eParam, ALint* plValue1, ALint* plValue2, ALint* plValue3)
  1058. {
  1059. ALCcontext *pContext;
  1060. ALsource *Source;
  1061. pContext = GetContextRef();
  1062. if(!pContext) return;
  1063. if(plValue1 && plValue2 && plValue3)
  1064. {
  1065. if((Source=LookupSource(pContext, source)) != NULL)
  1066. {
  1067. switch(eParam)
  1068. {
  1069. case AL_POSITION:
  1070. LockContext(pContext);
  1071. *plValue1 = (ALint)Source->vPosition[0];
  1072. *plValue2 = (ALint)Source->vPosition[1];
  1073. *plValue3 = (ALint)Source->vPosition[2];
  1074. UnlockContext(pContext);
  1075. break;
  1076. case AL_VELOCITY:
  1077. LockContext(pContext);
  1078. *plValue1 = (ALint)Source->vVelocity[0];
  1079. *plValue2 = (ALint)Source->vVelocity[1];
  1080. *plValue3 = (ALint)Source->vVelocity[2];
  1081. UnlockContext(pContext);
  1082. break;
  1083. case AL_DIRECTION:
  1084. LockContext(pContext);
  1085. *plValue1 = (ALint)Source->vOrientation[0];
  1086. *plValue2 = (ALint)Source->vOrientation[1];
  1087. *plValue3 = (ALint)Source->vOrientation[2];
  1088. UnlockContext(pContext);
  1089. break;
  1090. default:
  1091. alSetError(pContext, AL_INVALID_ENUM);
  1092. break;
  1093. }
  1094. }
  1095. else
  1096. alSetError(pContext, AL_INVALID_NAME);
  1097. }
  1098. else
  1099. alSetError(pContext, AL_INVALID_VALUE);
  1100. ALCcontext_DecRef(pContext);
  1101. }
  1102. AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum eParam, ALint* plValues)
  1103. {
  1104. ALCcontext *pContext;
  1105. ALsource *Source;
  1106. ALdouble Offsets[2];
  1107. ALdouble updateLen;
  1108. switch(eParam)
  1109. {
  1110. case AL_SOURCE_RELATIVE:
  1111. case AL_CONE_INNER_ANGLE:
  1112. case AL_CONE_OUTER_ANGLE:
  1113. case AL_LOOPING:
  1114. case AL_BUFFER:
  1115. case AL_SOURCE_STATE:
  1116. case AL_BUFFERS_QUEUED:
  1117. case AL_BUFFERS_PROCESSED:
  1118. case AL_SEC_OFFSET:
  1119. case AL_SAMPLE_OFFSET:
  1120. case AL_BYTE_OFFSET:
  1121. case AL_MAX_DISTANCE:
  1122. case AL_ROLLOFF_FACTOR:
  1123. case AL_DOPPLER_FACTOR:
  1124. case AL_REFERENCE_DISTANCE:
  1125. case AL_SOURCE_TYPE:
  1126. case AL_DIRECT_FILTER:
  1127. case AL_DIRECT_FILTER_GAINHF_AUTO:
  1128. case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
  1129. case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
  1130. case AL_DISTANCE_MODEL:
  1131. case AL_DIRECT_CHANNELS_SOFT:
  1132. alGetSourcei(source, eParam, plValues);
  1133. return;
  1134. case AL_POSITION:
  1135. case AL_VELOCITY:
  1136. case AL_DIRECTION:
  1137. alGetSource3i(source, eParam, plValues+0, plValues+1, plValues+2);
  1138. return;
  1139. }
  1140. pContext = GetContextRef();
  1141. if(!pContext) return;
  1142. if(plValues)
  1143. {
  1144. if((Source=LookupSource(pContext, source)) != NULL)
  1145. {
  1146. switch(eParam)
  1147. {
  1148. case AL_SAMPLE_RW_OFFSETS_SOFT:
  1149. case AL_BYTE_RW_OFFSETS_SOFT:
  1150. LockContext(pContext);
  1151. updateLen = (ALdouble)pContext->Device->UpdateSize /
  1152. pContext->Device->Frequency;
  1153. GetSourceOffset(Source, eParam, Offsets, updateLen);
  1154. UnlockContext(pContext);
  1155. plValues[0] = (ALint)Offsets[0];
  1156. plValues[1] = (ALint)Offsets[1];
  1157. break;
  1158. default:
  1159. alSetError(pContext, AL_INVALID_ENUM);
  1160. break;
  1161. }
  1162. }
  1163. else
  1164. alSetError(pContext, AL_INVALID_NAME);
  1165. }
  1166. else
  1167. alSetError(pContext, AL_INVALID_VALUE);
  1168. ALCcontext_DecRef(pContext);
  1169. }
  1170. AL_API ALvoid AL_APIENTRY alSourcePlay(ALuint source)
  1171. {
  1172. alSourcePlayv(1, &source);
  1173. }
  1174. AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources)
  1175. {
  1176. ALCcontext *Context;
  1177. ALsource *Source;
  1178. ALsizei i;
  1179. Context = GetContextRef();
  1180. if(!Context) return;
  1181. if(n < 0)
  1182. {
  1183. alSetError(Context, AL_INVALID_VALUE);
  1184. goto done;
  1185. }
  1186. if(n > 0 && !sources)
  1187. {
  1188. alSetError(Context, AL_INVALID_VALUE);
  1189. goto done;
  1190. }
  1191. // Check that all the Sources are valid
  1192. for(i = 0;i < n;i++)
  1193. {
  1194. if(!LookupSource(Context, sources[i]))
  1195. {
  1196. alSetError(Context, AL_INVALID_NAME);
  1197. goto done;
  1198. }
  1199. }
  1200. LockContext(Context);
  1201. while(Context->MaxActiveSources-Context->ActiveSourceCount < n)
  1202. {
  1203. void *temp = NULL;
  1204. ALsizei newcount;
  1205. newcount = Context->MaxActiveSources << 1;
  1206. if(newcount > 0)
  1207. temp = realloc(Context->ActiveSources,
  1208. sizeof(*Context->ActiveSources) * newcount);
  1209. if(!temp)
  1210. {
  1211. UnlockContext(Context);
  1212. alSetError(Context, AL_OUT_OF_MEMORY);
  1213. goto done;
  1214. }
  1215. Context->ActiveSources = temp;
  1216. Context->MaxActiveSources = newcount;
  1217. }
  1218. for(i = 0;i < n;i++)
  1219. {
  1220. Source = LookupSource(Context, sources[i]);
  1221. if(Context->DeferUpdates) Source->new_state = AL_PLAYING;
  1222. else SetSourceState(Source, Context, AL_PLAYING);
  1223. }
  1224. UnlockContext(Context);
  1225. done:
  1226. ALCcontext_DecRef(Context);
  1227. }
  1228. AL_API ALvoid AL_APIENTRY alSourcePause(ALuint source)
  1229. {
  1230. alSourcePausev(1, &source);
  1231. }
  1232. AL_API ALvoid AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources)
  1233. {
  1234. ALCcontext *Context;
  1235. ALsource *Source;
  1236. ALsizei i;
  1237. Context = GetContextRef();
  1238. if(!Context) return;
  1239. if(n < 0)
  1240. {
  1241. alSetError(Context, AL_INVALID_VALUE);
  1242. goto done;
  1243. }
  1244. if(n > 0 && !sources)
  1245. {
  1246. alSetError(Context, AL_INVALID_VALUE);
  1247. goto done;
  1248. }
  1249. // Check all the Sources are valid
  1250. for(i = 0;i < n;i++)
  1251. {
  1252. if(!LookupSource(Context, sources[i]))
  1253. {
  1254. alSetError(Context, AL_INVALID_NAME);
  1255. goto done;
  1256. }
  1257. }
  1258. LockContext(Context);
  1259. for(i = 0;i < n;i++)
  1260. {
  1261. Source = LookupSource(Context, sources[i]);
  1262. if(Context->DeferUpdates) Source->new_state = AL_PAUSED;
  1263. else SetSourceState(Source, Context, AL_PAUSED);
  1264. }
  1265. UnlockContext(Context);
  1266. done:
  1267. ALCcontext_DecRef(Context);
  1268. }
  1269. AL_API ALvoid AL_APIENTRY alSourceStop(ALuint source)
  1270. {
  1271. alSourceStopv(1, &source);
  1272. }
  1273. AL_API ALvoid AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources)
  1274. {
  1275. ALCcontext *Context;
  1276. ALsource *Source;
  1277. ALsizei i;
  1278. Context = GetContextRef();
  1279. if(!Context) return;
  1280. if(n < 0)
  1281. {
  1282. alSetError(Context, AL_INVALID_VALUE);
  1283. goto done;
  1284. }
  1285. if(n > 0 && !sources)
  1286. {
  1287. alSetError(Context, AL_INVALID_VALUE);
  1288. goto done;
  1289. }
  1290. // Check all the Sources are valid
  1291. for(i = 0;i < n;i++)
  1292. {
  1293. if(!LookupSource(Context, sources[i]))
  1294. {
  1295. alSetError(Context, AL_INVALID_NAME);
  1296. goto done;
  1297. }
  1298. }
  1299. LockContext(Context);
  1300. for(i = 0;i < n;i++)
  1301. {
  1302. Source = LookupSource(Context, sources[i]);
  1303. Source->new_state = AL_NONE;
  1304. SetSourceState(Source, Context, AL_STOPPED);
  1305. }
  1306. UnlockContext(Context);
  1307. done:
  1308. ALCcontext_DecRef(Context);
  1309. }
  1310. AL_API ALvoid AL_APIENTRY alSourceRewind(ALuint source)
  1311. {
  1312. alSourceRewindv(1, &source);
  1313. }
  1314. AL_API ALvoid AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources)
  1315. {
  1316. ALCcontext *Context;
  1317. ALsource *Source;
  1318. ALsizei i;
  1319. Context = GetContextRef();
  1320. if(!Context) return;
  1321. if(n < 0)
  1322. {
  1323. alSetError(Context, AL_INVALID_VALUE);
  1324. goto done;
  1325. }
  1326. if(n > 0 && !sources)
  1327. {
  1328. alSetError(Context, AL_INVALID_VALUE);
  1329. goto done;
  1330. }
  1331. // Check all the Sources are valid
  1332. for(i = 0;i < n;i++)
  1333. {
  1334. if(!LookupSource(Context, sources[i]))
  1335. {
  1336. alSetError(Context, AL_INVALID_NAME);
  1337. goto done;
  1338. }
  1339. }
  1340. LockContext(Context);
  1341. for(i = 0;i < n;i++)
  1342. {
  1343. Source = LookupSource(Context, sources[i]);
  1344. Source->new_state = AL_NONE;
  1345. SetSourceState(Source, Context, AL_INITIAL);
  1346. }
  1347. UnlockContext(Context);
  1348. done:
  1349. ALCcontext_DecRef(Context);
  1350. }
  1351. AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei n, const ALuint *buffers)
  1352. {
  1353. ALCcontext *Context;
  1354. ALCdevice *device;
  1355. ALsource *Source;
  1356. ALsizei i;
  1357. ALbufferlistitem *BufferListStart = NULL;
  1358. ALbufferlistitem *BufferList;
  1359. ALbuffer *BufferFmt;
  1360. if(n == 0)
  1361. return;
  1362. Context = GetContextRef();
  1363. if(!Context) return;
  1364. if(n < 0)
  1365. {
  1366. alSetError(Context, AL_INVALID_VALUE);
  1367. goto error;
  1368. }
  1369. // Check that all buffers are valid or zero and that the source is valid
  1370. // Check that this is a valid source
  1371. if((Source=LookupSource(Context, source)) == NULL)
  1372. {
  1373. alSetError(Context, AL_INVALID_NAME);
  1374. goto error;
  1375. }
  1376. LockContext(Context);
  1377. // Check that this is not a STATIC Source
  1378. if(Source->lSourceType == AL_STATIC)
  1379. {
  1380. UnlockContext(Context);
  1381. // Invalid Source Type (can't queue on a Static Source)
  1382. alSetError(Context, AL_INVALID_OPERATION);
  1383. goto error;
  1384. }
  1385. device = Context->Device;
  1386. BufferFmt = NULL;
  1387. // Check existing Queue (if any) for a valid Buffers and get its frequency and format
  1388. BufferList = Source->queue;
  1389. while(BufferList)
  1390. {
  1391. if(BufferList->buffer)
  1392. {
  1393. BufferFmt = BufferList->buffer;
  1394. break;
  1395. }
  1396. BufferList = BufferList->next;
  1397. }
  1398. for(i = 0;i < n;i++)
  1399. {
  1400. ALbuffer *buffer = NULL;
  1401. if(buffers[i] && (buffer=LookupBuffer(device, buffers[i])) == NULL)
  1402. {
  1403. UnlockContext(Context);
  1404. alSetError(Context, AL_INVALID_NAME);
  1405. goto error;
  1406. }
  1407. if(!BufferListStart)
  1408. {
  1409. BufferListStart = malloc(sizeof(ALbufferlistitem));
  1410. BufferListStart->buffer = buffer;
  1411. BufferListStart->next = NULL;
  1412. BufferListStart->prev = NULL;
  1413. BufferList = BufferListStart;
  1414. }
  1415. else
  1416. {
  1417. BufferList->next = malloc(sizeof(ALbufferlistitem));
  1418. BufferList->next->buffer = buffer;
  1419. BufferList->next->next = NULL;
  1420. BufferList->next->prev = BufferList;
  1421. BufferList = BufferList->next;
  1422. }
  1423. if(!buffer) continue;
  1424. // Increment reference counter for buffer
  1425. IncrementRef(&buffer->ref);
  1426. ReadLock(&buffer->lock);
  1427. if(BufferFmt == NULL)
  1428. {
  1429. BufferFmt = buffer;
  1430. Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
  1431. Source->SampleSize = BytesFromFmt(buffer->FmtType);
  1432. if(buffer->FmtChannels == FmtMono)
  1433. Source->Update = CalcSourceParams;
  1434. else
  1435. Source->Update = CalcNonAttnSourceParams;
  1436. Source->NeedsUpdate = AL_TRUE;
  1437. }
  1438. else if(BufferFmt->Frequency != buffer->Frequency ||
  1439. BufferFmt->OriginalChannels != buffer->OriginalChannels ||
  1440. BufferFmt->OriginalType != buffer->OriginalType)
  1441. {
  1442. ReadUnlock(&buffer->lock);
  1443. UnlockContext(Context);
  1444. alSetError(Context, AL_INVALID_OPERATION);
  1445. goto error;
  1446. }
  1447. ReadUnlock(&buffer->lock);
  1448. }
  1449. // Change Source Type
  1450. Source->lSourceType = AL_STREAMING;
  1451. if(Source->queue == NULL)
  1452. Source->queue = BufferListStart;
  1453. else
  1454. {
  1455. // Find end of queue
  1456. BufferList = Source->queue;
  1457. while(BufferList->next != NULL)
  1458. BufferList = BufferList->next;
  1459. BufferListStart->prev = BufferList;
  1460. BufferList->next = BufferListStart;
  1461. }
  1462. // Update number of buffers in queue
  1463. Source->BuffersInQueue += n;
  1464. UnlockContext(Context);
  1465. ALCcontext_DecRef(Context);
  1466. return;
  1467. error:
  1468. while(BufferListStart)
  1469. {
  1470. BufferList = BufferListStart;
  1471. BufferListStart = BufferList->next;
  1472. if(BufferList->buffer)
  1473. DecrementRef(&BufferList->buffer->ref);
  1474. free(BufferList);
  1475. }
  1476. ALCcontext_DecRef(Context);
  1477. }
  1478. // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
  1479. // an array of buffer IDs that are to be filled with the names of the buffers removed
  1480. AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers( ALuint source, ALsizei n, ALuint* buffers )
  1481. {
  1482. ALCcontext *Context;
  1483. ALsource *Source;
  1484. ALsizei i;
  1485. ALbufferlistitem *BufferList;
  1486. if(n == 0)
  1487. return;
  1488. Context = GetContextRef();
  1489. if(!Context) return;
  1490. if(n < 0)
  1491. {
  1492. alSetError(Context, AL_INVALID_VALUE);
  1493. goto done;
  1494. }
  1495. if((Source=LookupSource(Context, source)) == NULL)
  1496. {
  1497. alSetError(Context, AL_INVALID_NAME);
  1498. goto done;
  1499. }
  1500. LockContext(Context);
  1501. if(Source->bLooping || Source->lSourceType != AL_STREAMING ||
  1502. (ALuint)n > Source->BuffersPlayed)
  1503. {
  1504. UnlockContext(Context);
  1505. // Some buffers can't be unqueue because they have not been processed
  1506. alSetError(Context, AL_INVALID_VALUE);
  1507. goto done;
  1508. }
  1509. for(i = 0;i < n;i++)
  1510. {
  1511. BufferList = Source->queue;
  1512. Source->queue = BufferList->next;
  1513. Source->BuffersInQueue--;
  1514. Source->BuffersPlayed--;
  1515. if(BufferList->buffer)
  1516. {
  1517. // Record name of buffer
  1518. buffers[i] = BufferList->buffer->buffer;
  1519. // Decrement buffer reference counter
  1520. DecrementRef(&BufferList->buffer->ref);
  1521. }
  1522. else
  1523. buffers[i] = 0;
  1524. // Release memory for buffer list item
  1525. free(BufferList);
  1526. }
  1527. if(Source->queue)
  1528. Source->queue->prev = NULL;
  1529. UnlockContext(Context);
  1530. done:
  1531. ALCcontext_DecRef(Context);
  1532. }
  1533. static ALvoid InitSourceParams(ALsource *Source)
  1534. {
  1535. ALuint i;
  1536. Source->flInnerAngle = 360.0f;
  1537. Source->flOuterAngle = 360.0f;
  1538. Source->flPitch = 1.0f;
  1539. Source->vPosition[0] = 0.0f;
  1540. Source->vPosition[1] = 0.0f;
  1541. Source->vPosition[2] = 0.0f;
  1542. Source->vOrientation[0] = 0.0f;
  1543. Source->vOrientation[1] = 0.0f;
  1544. Source->vOrientation[2] = 0.0f;
  1545. Source->vVelocity[0] = 0.0f;
  1546. Source->vVelocity[1] = 0.0f;
  1547. Source->vVelocity[2] = 0.0f;
  1548. Source->flRefDistance = 1.0f;
  1549. Source->flMaxDistance = FLT_MAX;
  1550. Source->flRollOffFactor = 1.0f;
  1551. Source->bLooping = AL_FALSE;
  1552. Source->flGain = 1.0f;
  1553. Source->flMinGain = 0.0f;
  1554. Source->flMaxGain = 1.0f;
  1555. Source->flOuterGain = 0.0f;
  1556. Source->OuterGainHF = 1.0f;
  1557. Source->DryGainHFAuto = AL_TRUE;
  1558. Source->WetGainAuto = AL_TRUE;
  1559. Source->WetGainHFAuto = AL_TRUE;
  1560. Source->AirAbsorptionFactor = 0.0f;
  1561. Source->RoomRolloffFactor = 0.0f;
  1562. Source->DopplerFactor = 1.0f;
  1563. Source->DirectChannels = AL_FALSE;
  1564. Source->DistanceModel = DefaultDistanceModel;
  1565. Source->Resampler = DefaultResampler;
  1566. Source->state = AL_INITIAL;
  1567. Source->new_state = AL_NONE;
  1568. Source->lSourceType = AL_UNDETERMINED;
  1569. Source->lOffset = -1;
  1570. Source->DirectGain = 1.0f;
  1571. Source->DirectGainHF = 1.0f;
  1572. for(i = 0;i < MAX_SENDS;i++)
  1573. {
  1574. Source->Send[i].WetGain = 1.0f;
  1575. Source->Send[i].WetGainHF = 1.0f;
  1576. }
  1577. Source->NeedsUpdate = AL_TRUE;
  1578. Source->HrtfMoving = AL_FALSE;
  1579. Source->HrtfCounter = 0;
  1580. }
  1581. /*
  1582. * SetSourceState
  1583. *
  1584. * Sets the source's new play state given its current state
  1585. */
  1586. ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
  1587. {
  1588. if(state == AL_PLAYING)
  1589. {
  1590. ALbufferlistitem *BufferList;
  1591. ALsizei j, k;
  1592. /* Check that there is a queue containing at least one non-null, non zero length AL Buffer */
  1593. BufferList = Source->queue;
  1594. while(BufferList)
  1595. {
  1596. if(BufferList->buffer != NULL && BufferList->buffer->SampleLen)
  1597. break;
  1598. BufferList = BufferList->next;
  1599. }
  1600. if(Source->state != AL_PLAYING)
  1601. {
  1602. for(j = 0;j < MAXCHANNELS;j++)
  1603. {
  1604. for(k = 0;k < SRC_HISTORY_LENGTH;k++)
  1605. Source->HrtfHistory[j][k] = 0.0f;
  1606. for(k = 0;k < HRIR_LENGTH;k++)
  1607. {
  1608. Source->HrtfValues[j][k][0] = 0.0f;
  1609. Source->HrtfValues[j][k][1] = 0.0f;
  1610. }
  1611. }
  1612. }
  1613. if(Source->state != AL_PAUSED)
  1614. {
  1615. Source->state = AL_PLAYING;
  1616. Source->position = 0;
  1617. Source->position_fraction = 0;
  1618. Source->BuffersPlayed = 0;
  1619. }
  1620. else
  1621. Source->state = AL_PLAYING;
  1622. // Check if an Offset has been set
  1623. if(Source->lOffset != -1)
  1624. ApplyOffset(Source);
  1625. /* If there's nothing to play, or device is disconnected, go right to
  1626. * stopped */
  1627. if(!BufferList || !Context->Device->Connected)
  1628. {
  1629. SetSourceState(Source, Context, AL_STOPPED);
  1630. return;
  1631. }
  1632. for(j = 0;j < Context->ActiveSourceCount;j++)
  1633. {
  1634. if(Context->ActiveSources[j] == Source)
  1635. break;
  1636. }
  1637. if(j == Context->ActiveSourceCount)
  1638. Context->ActiveSources[Context->ActiveSourceCount++] = Source;
  1639. }
  1640. else if(state == AL_PAUSED)
  1641. {
  1642. if(Source->state == AL_PLAYING)
  1643. {
  1644. Source->state = AL_PAUSED;
  1645. Source->HrtfMoving = AL_FALSE;
  1646. Source->HrtfCounter = 0;
  1647. }
  1648. }
  1649. else if(state == AL_STOPPED)
  1650. {
  1651. if(Source->state != AL_INITIAL)
  1652. {
  1653. Source->state = AL_STOPPED;
  1654. Source->BuffersPlayed = Source->BuffersInQueue;
  1655. Source->HrtfMoving = AL_FALSE;
  1656. Source->HrtfCounter = 0;
  1657. }
  1658. Source->lOffset = -1;
  1659. }
  1660. else if(state == AL_INITIAL)
  1661. {
  1662. if(Source->state != AL_INITIAL)
  1663. {
  1664. Source->state = AL_INITIAL;
  1665. Source->position = 0;
  1666. Source->position_fraction = 0;
  1667. Source->BuffersPlayed = 0;
  1668. Source->HrtfMoving = AL_FALSE;
  1669. Source->HrtfCounter = 0;
  1670. }
  1671. Source->lOffset = -1;
  1672. }
  1673. }
  1674. /*
  1675. GetSourceOffset
  1676. Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
  1677. The offset is relative to the start of the queue (not the start of the current buffer)
  1678. */
  1679. static ALvoid GetSourceOffset(ALsource *Source, ALenum name, ALdouble *offset, ALdouble updateLen)
  1680. {
  1681. const ALbufferlistitem *BufferList;
  1682. const ALbuffer *Buffer = NULL;
  1683. ALuint BufferFreq = 0;
  1684. ALuint readPos, writePos;
  1685. ALuint totalBufferLen;
  1686. ALuint i;
  1687. // Find the first non-NULL Buffer in the Queue
  1688. BufferList = Source->queue;
  1689. while(BufferList)
  1690. {
  1691. if(BufferList->buffer)
  1692. {
  1693. Buffer = BufferList->buffer;
  1694. BufferFreq = Buffer->Frequency;
  1695. break;
  1696. }
  1697. BufferList = BufferList->next;
  1698. }
  1699. if((Source->state != AL_PLAYING && Source->state != AL_PAUSED) || !Buffer)
  1700. {
  1701. offset[0] = 0.0;
  1702. offset[1] = 0.0;
  1703. return;
  1704. }
  1705. if(updateLen > 0.0 && updateLen < 0.015)
  1706. updateLen = 0.015;
  1707. // Get Current SamplesPlayed (NOTE : This is the offset into the *current* buffer)
  1708. readPos = Source->position;
  1709. // Add length of any processed buffers in the queue
  1710. totalBufferLen = 0;
  1711. BufferList = Source->queue;
  1712. for(i = 0;BufferList;i++)
  1713. {
  1714. if(BufferList->buffer)
  1715. {
  1716. if(i < Source->BuffersPlayed)
  1717. readPos += BufferList->buffer->SampleLen;
  1718. totalBufferLen += BufferList->buffer->SampleLen;
  1719. }
  1720. BufferList = BufferList->next;
  1721. }
  1722. if(Source->state == AL_PLAYING)
  1723. writePos = readPos + (ALuint)(updateLen*BufferFreq);
  1724. else
  1725. writePos = readPos;
  1726. if(Source->bLooping)
  1727. {
  1728. readPos %= totalBufferLen;
  1729. writePos %= totalBufferLen;
  1730. }
  1731. else
  1732. {
  1733. // Wrap positions back to 0
  1734. if(readPos >= totalBufferLen)
  1735. readPos = 0;
  1736. if(writePos >= totalBufferLen)
  1737. writePos = 0;
  1738. }
  1739. switch(name)
  1740. {
  1741. case AL_SEC_OFFSET:
  1742. offset[0] = (ALdouble)readPos / Buffer->Frequency;
  1743. offset[1] = (ALdouble)writePos / Buffer->Frequency;
  1744. break;
  1745. case AL_SAMPLE_OFFSET:
  1746. case AL_SAMPLE_RW_OFFSETS_SOFT:
  1747. offset[0] = (ALdouble)readPos;
  1748. offset[1] = (ALdouble)writePos;
  1749. break;
  1750. case AL_BYTE_OFFSET:
  1751. case AL_BYTE_RW_OFFSETS_SOFT:
  1752. // Take into account the original format of the Buffer
  1753. if(Buffer->OriginalType == UserFmtIMA4)
  1754. {
  1755. ALuint BlockSize = 36 * ChannelsFromFmt(Buffer->FmtChannels);
  1756. ALuint FrameBlockSize = 65;
  1757. // Round down to nearest ADPCM block
  1758. offset[0] = (ALdouble)(readPos / FrameBlockSize * BlockSize);
  1759. if(Source->state != AL_PLAYING)
  1760. offset[1] = offset[0];
  1761. else
  1762. {
  1763. // Round up to nearest ADPCM block
  1764. offset[1] = (ALdouble)((writePos+FrameBlockSize-1) /
  1765. FrameBlockSize * BlockSize);
  1766. }
  1767. }
  1768. else
  1769. {
  1770. ALuint FrameSize = FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
  1771. offset[0] = (ALdouble)(readPos * FrameSize);
  1772. offset[1] = (ALdouble)(writePos * FrameSize);
  1773. }
  1774. break;
  1775. }
  1776. }
  1777. /*
  1778. ApplyOffset
  1779. Apply a playback offset to the Source. This function will update the queue (to correctly
  1780. mark buffers as 'pending' or 'processed' depending upon the new offset.
  1781. */
  1782. ALboolean ApplyOffset(ALsource *Source)
  1783. {
  1784. const ALbufferlistitem *BufferList;
  1785. const ALbuffer *Buffer;
  1786. ALint bufferLen, totalBufferLen;
  1787. ALint buffersPlayed;
  1788. ALint offset;
  1789. // Get true byte offset
  1790. offset = GetSampleOffset(Source);
  1791. // If the offset is invalid, don't apply it
  1792. if(offset == -1)
  1793. return AL_FALSE;
  1794. // Sort out the queue (pending and processed states)
  1795. BufferList = Source->queue;
  1796. totalBufferLen = 0;
  1797. buffersPlayed = 0;
  1798. while(BufferList)
  1799. {
  1800. Buffer = BufferList->buffer;
  1801. bufferLen = Buffer ? Buffer->SampleLen : 0;
  1802. if(bufferLen <= offset-totalBufferLen)
  1803. {
  1804. // Offset is past this buffer so increment BuffersPlayed
  1805. buffersPlayed++;
  1806. }
  1807. else if(totalBufferLen <= offset)
  1808. {
  1809. // Offset is within this buffer
  1810. Source->BuffersPlayed = buffersPlayed;
  1811. // SW Mixer Positions are in Samples
  1812. Source->position = offset - totalBufferLen;
  1813. return AL_TRUE;
  1814. }
  1815. // Increment the TotalBufferSize
  1816. totalBufferLen += bufferLen;
  1817. // Move on to next buffer in the Queue
  1818. BufferList = BufferList->next;
  1819. }
  1820. // Offset is out of range of the buffer queue
  1821. return AL_FALSE;
  1822. }
  1823. /*
  1824. GetSampleOffset
  1825. Returns the sample offset into the Source's queue (from the Sample, Byte or Millisecond offset
  1826. supplied by the application). This takes into account the fact that the buffer format may have
  1827. been modifed by AL
  1828. */
  1829. static ALint GetSampleOffset(ALsource *Source)
  1830. {
  1831. const ALbuffer *Buffer = NULL;
  1832. const ALbufferlistitem *BufferList;
  1833. ALint Offset = -1;
  1834. // Find the first non-NULL Buffer in the Queue
  1835. BufferList = Source->queue;
  1836. while(BufferList)
  1837. {
  1838. if(BufferList->buffer)
  1839. {
  1840. Buffer = BufferList->buffer;
  1841. break;
  1842. }
  1843. BufferList = BufferList->next;
  1844. }
  1845. if(!Buffer)
  1846. {
  1847. Source->lOffset = -1;
  1848. return -1;
  1849. }
  1850. // Determine the ByteOffset (and ensure it is block aligned)
  1851. switch(Source->lOffsetType)
  1852. {
  1853. case AL_BYTE_OFFSET:
  1854. // Take into consideration the original format
  1855. Offset = Source->lOffset;
  1856. if(Buffer->OriginalType == UserFmtIMA4)
  1857. {
  1858. // Round down to nearest ADPCM block
  1859. Offset /= 36 * ChannelsFromUserFmt(Buffer->OriginalChannels);
  1860. // Multiply by compression rate (65 sample frames per block)
  1861. Offset *= 65;
  1862. }
  1863. else
  1864. Offset /= FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
  1865. break;
  1866. case AL_SAMPLE_OFFSET:
  1867. Offset = Source->lOffset;
  1868. break;
  1869. case AL_SEC_OFFSET:
  1870. // Note - lOffset is internally stored as Milliseconds
  1871. Offset = (ALint)(Source->lOffset / 1000.0 * Buffer->Frequency);
  1872. break;
  1873. }
  1874. // Clear Offset
  1875. Source->lOffset = -1;
  1876. return Offset;
  1877. }
  1878. ALvoid ReleaseALSources(ALCcontext *Context)
  1879. {
  1880. ALsizei pos;
  1881. ALuint j;
  1882. for(pos = 0;pos < Context->SourceMap.size;pos++)
  1883. {
  1884. ALsource *temp = Context->SourceMap.array[pos].value;
  1885. Context->SourceMap.array[pos].value = NULL;
  1886. // For each buffer in the source's queue, decrement its reference counter and remove it
  1887. while(temp->queue != NULL)
  1888. {
  1889. ALbufferlistitem *BufferList = temp->queue;
  1890. temp->queue = BufferList->next;
  1891. if(BufferList->buffer != NULL)
  1892. DecrementRef(&BufferList->buffer->ref);
  1893. free(BufferList);
  1894. }
  1895. for(j = 0;j < MAX_SENDS;++j)
  1896. {
  1897. if(temp->Send[j].Slot)
  1898. DecrementRef(&temp->Send[j].Slot->ref);
  1899. temp->Send[j].Slot = NULL;
  1900. }
  1901. // Release source structure
  1902. FreeThunkEntry(temp->source);
  1903. memset(temp, 0, sizeof(ALsource));
  1904. free(temp);
  1905. }
  1906. }