alSource.c 64 KB

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