alSource.c 118 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705
  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.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. * Or go to http://www.gnu.org/copyleft/lgpl.html
  19. */
  20. #include "config.h"
  21. #include <stdlib.h>
  22. #include <limits.h>
  23. #include <math.h>
  24. #include <float.h>
  25. #include "AL/al.h"
  26. #include "AL/alc.h"
  27. #include "alMain.h"
  28. #include "alError.h"
  29. #include "alSource.h"
  30. #include "alBuffer.h"
  31. #include "alFilter.h"
  32. #include "alAuxEffectSlot.h"
  33. #include "ringbuffer.h"
  34. #include "backends/base.h"
  35. #include "threads.h"
  36. #include "almalloc.h"
  37. static ALsource *AllocSource(ALCcontext *context);
  38. static void FreeSource(ALCcontext *context, ALsource *source);
  39. static void InitSourceParams(ALsource *Source, ALsizei num_sends);
  40. static void DeinitSource(ALsource *source, ALsizei num_sends);
  41. static void UpdateSourceProps(ALsource *source, ALvoice *voice, ALsizei num_sends, ALCcontext *context);
  42. static ALint64 GetSourceSampleOffset(ALsource *Source, ALCcontext *context, ALuint64 *clocktime);
  43. static ALdouble GetSourceSecOffset(ALsource *Source, ALCcontext *context, ALuint64 *clocktime);
  44. static ALdouble GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context);
  45. static ALboolean GetSampleOffset(ALsource *Source, ALuint *offset, ALsizei *frac);
  46. static ALboolean ApplyOffset(ALsource *Source, ALvoice *voice);
  47. static inline void LockSourceList(ALCcontext *context)
  48. { almtx_lock(&context->SourceLock); }
  49. static inline void UnlockSourceList(ALCcontext *context)
  50. { almtx_unlock(&context->SourceLock); }
  51. static inline ALsource *LookupSource(ALCcontext *context, ALuint id)
  52. {
  53. SourceSubList *sublist;
  54. ALuint lidx = (id-1) >> 6;
  55. ALsizei slidx = (id-1) & 0x3f;
  56. if(UNLIKELY(lidx >= VECTOR_SIZE(context->SourceList)))
  57. return NULL;
  58. sublist = &VECTOR_ELEM(context->SourceList, lidx);
  59. if(UNLIKELY(sublist->FreeMask & (U64(1)<<slidx)))
  60. return NULL;
  61. return sublist->Sources + slidx;
  62. }
  63. static inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id)
  64. {
  65. BufferSubList *sublist;
  66. ALuint lidx = (id-1) >> 6;
  67. ALsizei slidx = (id-1) & 0x3f;
  68. if(UNLIKELY(lidx >= VECTOR_SIZE(device->BufferList)))
  69. return NULL;
  70. sublist = &VECTOR_ELEM(device->BufferList, lidx);
  71. if(UNLIKELY(sublist->FreeMask & (U64(1)<<slidx)))
  72. return NULL;
  73. return sublist->Buffers + slidx;
  74. }
  75. static inline ALfilter *LookupFilter(ALCdevice *device, ALuint id)
  76. {
  77. FilterSubList *sublist;
  78. ALuint lidx = (id-1) >> 6;
  79. ALsizei slidx = (id-1) & 0x3f;
  80. if(UNLIKELY(lidx >= VECTOR_SIZE(device->FilterList)))
  81. return NULL;
  82. sublist = &VECTOR_ELEM(device->FilterList, lidx);
  83. if(UNLIKELY(sublist->FreeMask & (U64(1)<<slidx)))
  84. return NULL;
  85. return sublist->Filters + slidx;
  86. }
  87. static inline ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id)
  88. {
  89. id--;
  90. if(UNLIKELY(id >= VECTOR_SIZE(context->EffectSlotList)))
  91. return NULL;
  92. return VECTOR_ELEM(context->EffectSlotList, id);
  93. }
  94. typedef enum SourceProp {
  95. srcPitch = AL_PITCH,
  96. srcGain = AL_GAIN,
  97. srcMinGain = AL_MIN_GAIN,
  98. srcMaxGain = AL_MAX_GAIN,
  99. srcMaxDistance = AL_MAX_DISTANCE,
  100. srcRolloffFactor = AL_ROLLOFF_FACTOR,
  101. srcDopplerFactor = AL_DOPPLER_FACTOR,
  102. srcConeOuterGain = AL_CONE_OUTER_GAIN,
  103. srcSecOffset = AL_SEC_OFFSET,
  104. srcSampleOffset = AL_SAMPLE_OFFSET,
  105. srcByteOffset = AL_BYTE_OFFSET,
  106. srcConeInnerAngle = AL_CONE_INNER_ANGLE,
  107. srcConeOuterAngle = AL_CONE_OUTER_ANGLE,
  108. srcRefDistance = AL_REFERENCE_DISTANCE,
  109. srcPosition = AL_POSITION,
  110. srcVelocity = AL_VELOCITY,
  111. srcDirection = AL_DIRECTION,
  112. srcSourceRelative = AL_SOURCE_RELATIVE,
  113. srcLooping = AL_LOOPING,
  114. srcBuffer = AL_BUFFER,
  115. srcSourceState = AL_SOURCE_STATE,
  116. srcBuffersQueued = AL_BUFFERS_QUEUED,
  117. srcBuffersProcessed = AL_BUFFERS_PROCESSED,
  118. srcSourceType = AL_SOURCE_TYPE,
  119. /* ALC_EXT_EFX */
  120. srcConeOuterGainHF = AL_CONE_OUTER_GAINHF,
  121. srcAirAbsorptionFactor = AL_AIR_ABSORPTION_FACTOR,
  122. srcRoomRolloffFactor = AL_ROOM_ROLLOFF_FACTOR,
  123. srcDirectFilterGainHFAuto = AL_DIRECT_FILTER_GAINHF_AUTO,
  124. srcAuxSendFilterGainAuto = AL_AUXILIARY_SEND_FILTER_GAIN_AUTO,
  125. srcAuxSendFilterGainHFAuto = AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO,
  126. srcDirectFilter = AL_DIRECT_FILTER,
  127. srcAuxSendFilter = AL_AUXILIARY_SEND_FILTER,
  128. /* AL_SOFT_direct_channels */
  129. srcDirectChannelsSOFT = AL_DIRECT_CHANNELS_SOFT,
  130. /* AL_EXT_source_distance_model */
  131. srcDistanceModel = AL_DISTANCE_MODEL,
  132. /* AL_SOFT_source_latency */
  133. srcSampleOffsetLatencySOFT = AL_SAMPLE_OFFSET_LATENCY_SOFT,
  134. srcSecOffsetLatencySOFT = AL_SEC_OFFSET_LATENCY_SOFT,
  135. /* AL_EXT_STEREO_ANGLES */
  136. srcAngles = AL_STEREO_ANGLES,
  137. /* AL_EXT_SOURCE_RADIUS */
  138. srcRadius = AL_SOURCE_RADIUS,
  139. /* AL_EXT_BFORMAT */
  140. srcOrientation = AL_ORIENTATION,
  141. /* AL_SOFT_source_resampler */
  142. srcResampler = AL_SOURCE_RESAMPLER_SOFT,
  143. /* AL_SOFT_source_spatialize */
  144. srcSpatialize = AL_SOURCE_SPATIALIZE_SOFT,
  145. /* ALC_SOFT_device_clock */
  146. srcSampleOffsetClockSOFT = AL_SAMPLE_OFFSET_CLOCK_SOFT,
  147. srcSecOffsetClockSOFT = AL_SEC_OFFSET_CLOCK_SOFT,
  148. } SourceProp;
  149. static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp prop, const ALfloat *values);
  150. static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, const ALint *values);
  151. static ALboolean SetSourcei64v(ALsource *Source, ALCcontext *Context, SourceProp prop, const ALint64SOFT *values);
  152. static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SourceProp prop, ALdouble *values);
  153. static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, ALint *values);
  154. static ALboolean GetSourcei64v(ALsource *Source, ALCcontext *Context, SourceProp prop, ALint64 *values);
  155. static inline ALvoice *GetSourceVoice(ALsource *source, ALCcontext *context)
  156. {
  157. ALint idx = source->VoiceIdx;
  158. if(idx >= 0 && idx < context->VoiceCount)
  159. {
  160. ALvoice *voice = context->Voices[idx];
  161. if(ATOMIC_LOAD(&voice->Source, almemory_order_acquire) == source)
  162. return voice;
  163. }
  164. source->VoiceIdx = -1;
  165. return NULL;
  166. }
  167. /**
  168. * Returns if the last known state for the source was playing or paused. Does
  169. * not sync with the mixer voice.
  170. */
  171. static inline bool IsPlayingOrPaused(ALsource *source)
  172. { return source->state == AL_PLAYING || source->state == AL_PAUSED; }
  173. /**
  174. * Returns an updated source state using the matching voice's status (or lack
  175. * thereof).
  176. */
  177. static inline ALenum GetSourceState(ALsource *source, ALvoice *voice)
  178. {
  179. if(!voice && source->state == AL_PLAYING)
  180. source->state = AL_STOPPED;
  181. return source->state;
  182. }
  183. /**
  184. * Returns if the source should specify an update, given the context's
  185. * deferring state and the source's last known state.
  186. */
  187. static inline bool SourceShouldUpdate(ALsource *source, ALCcontext *context)
  188. {
  189. return !ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire) &&
  190. IsPlayingOrPaused(source);
  191. }
  192. /** Can only be called while the mixer is locked! */
  193. static void SendStateChangeEvent(ALCcontext *context, ALuint id, ALenum state)
  194. {
  195. AsyncEvent evt = ASYNC_EVENT(EventType_SourceStateChange);
  196. ALbitfieldSOFT enabledevt;
  197. enabledevt = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_acquire);
  198. if(!(enabledevt&EventType_SourceStateChange)) return;
  199. evt.u.user.type = AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT;
  200. evt.u.user.id = id;
  201. evt.u.user.param = state;
  202. snprintf(evt.u.user.msg, sizeof(evt.u.user.msg), "Source ID %u state changed to %s", id,
  203. (state==AL_INITIAL) ? "AL_INITIAL" :
  204. (state==AL_PLAYING) ? "AL_PLAYING" :
  205. (state==AL_PAUSED) ? "AL_PAUSED" :
  206. (state==AL_STOPPED) ? "AL_STOPPED" : "<unknown>"
  207. );
  208. /* The mixer may have queued a state change that's not yet been processed,
  209. * and we don't want state change messages to occur out of order, so send
  210. * it through the async queue to ensure proper ordering.
  211. */
  212. if(ll_ringbuffer_write(context->AsyncEvents, (const char*)&evt, 1) == 1)
  213. alsem_post(&context->EventSem);
  214. }
  215. static ALint FloatValsByProp(ALenum prop)
  216. {
  217. if(prop != (ALenum)((SourceProp)prop))
  218. return 0;
  219. switch((SourceProp)prop)
  220. {
  221. case AL_PITCH:
  222. case AL_GAIN:
  223. case AL_MIN_GAIN:
  224. case AL_MAX_GAIN:
  225. case AL_MAX_DISTANCE:
  226. case AL_ROLLOFF_FACTOR:
  227. case AL_DOPPLER_FACTOR:
  228. case AL_CONE_OUTER_GAIN:
  229. case AL_SEC_OFFSET:
  230. case AL_SAMPLE_OFFSET:
  231. case AL_BYTE_OFFSET:
  232. case AL_CONE_INNER_ANGLE:
  233. case AL_CONE_OUTER_ANGLE:
  234. case AL_REFERENCE_DISTANCE:
  235. case AL_CONE_OUTER_GAINHF:
  236. case AL_AIR_ABSORPTION_FACTOR:
  237. case AL_ROOM_ROLLOFF_FACTOR:
  238. case AL_DIRECT_FILTER_GAINHF_AUTO:
  239. case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
  240. case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
  241. case AL_DIRECT_CHANNELS_SOFT:
  242. case AL_DISTANCE_MODEL:
  243. case AL_SOURCE_RELATIVE:
  244. case AL_LOOPING:
  245. case AL_SOURCE_STATE:
  246. case AL_BUFFERS_QUEUED:
  247. case AL_BUFFERS_PROCESSED:
  248. case AL_SOURCE_TYPE:
  249. case AL_SOURCE_RADIUS:
  250. case AL_SOURCE_RESAMPLER_SOFT:
  251. case AL_SOURCE_SPATIALIZE_SOFT:
  252. return 1;
  253. case AL_STEREO_ANGLES:
  254. return 2;
  255. case AL_POSITION:
  256. case AL_VELOCITY:
  257. case AL_DIRECTION:
  258. return 3;
  259. case AL_ORIENTATION:
  260. return 6;
  261. case AL_SEC_OFFSET_LATENCY_SOFT:
  262. case AL_SEC_OFFSET_CLOCK_SOFT:
  263. break; /* Double only */
  264. case AL_BUFFER:
  265. case AL_DIRECT_FILTER:
  266. case AL_AUXILIARY_SEND_FILTER:
  267. break; /* i/i64 only */
  268. case AL_SAMPLE_OFFSET_LATENCY_SOFT:
  269. case AL_SAMPLE_OFFSET_CLOCK_SOFT:
  270. break; /* i64 only */
  271. }
  272. return 0;
  273. }
  274. static ALint DoubleValsByProp(ALenum prop)
  275. {
  276. if(prop != (ALenum)((SourceProp)prop))
  277. return 0;
  278. switch((SourceProp)prop)
  279. {
  280. case AL_PITCH:
  281. case AL_GAIN:
  282. case AL_MIN_GAIN:
  283. case AL_MAX_GAIN:
  284. case AL_MAX_DISTANCE:
  285. case AL_ROLLOFF_FACTOR:
  286. case AL_DOPPLER_FACTOR:
  287. case AL_CONE_OUTER_GAIN:
  288. case AL_SEC_OFFSET:
  289. case AL_SAMPLE_OFFSET:
  290. case AL_BYTE_OFFSET:
  291. case AL_CONE_INNER_ANGLE:
  292. case AL_CONE_OUTER_ANGLE:
  293. case AL_REFERENCE_DISTANCE:
  294. case AL_CONE_OUTER_GAINHF:
  295. case AL_AIR_ABSORPTION_FACTOR:
  296. case AL_ROOM_ROLLOFF_FACTOR:
  297. case AL_DIRECT_FILTER_GAINHF_AUTO:
  298. case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
  299. case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
  300. case AL_DIRECT_CHANNELS_SOFT:
  301. case AL_DISTANCE_MODEL:
  302. case AL_SOURCE_RELATIVE:
  303. case AL_LOOPING:
  304. case AL_SOURCE_STATE:
  305. case AL_BUFFERS_QUEUED:
  306. case AL_BUFFERS_PROCESSED:
  307. case AL_SOURCE_TYPE:
  308. case AL_SOURCE_RADIUS:
  309. case AL_SOURCE_RESAMPLER_SOFT:
  310. case AL_SOURCE_SPATIALIZE_SOFT:
  311. return 1;
  312. case AL_SEC_OFFSET_LATENCY_SOFT:
  313. case AL_SEC_OFFSET_CLOCK_SOFT:
  314. case AL_STEREO_ANGLES:
  315. return 2;
  316. case AL_POSITION:
  317. case AL_VELOCITY:
  318. case AL_DIRECTION:
  319. return 3;
  320. case AL_ORIENTATION:
  321. return 6;
  322. case AL_BUFFER:
  323. case AL_DIRECT_FILTER:
  324. case AL_AUXILIARY_SEND_FILTER:
  325. break; /* i/i64 only */
  326. case AL_SAMPLE_OFFSET_LATENCY_SOFT:
  327. case AL_SAMPLE_OFFSET_CLOCK_SOFT:
  328. break; /* i64 only */
  329. }
  330. return 0;
  331. }
  332. static ALint IntValsByProp(ALenum prop)
  333. {
  334. if(prop != (ALenum)((SourceProp)prop))
  335. return 0;
  336. switch((SourceProp)prop)
  337. {
  338. case AL_PITCH:
  339. case AL_GAIN:
  340. case AL_MIN_GAIN:
  341. case AL_MAX_GAIN:
  342. case AL_MAX_DISTANCE:
  343. case AL_ROLLOFF_FACTOR:
  344. case AL_DOPPLER_FACTOR:
  345. case AL_CONE_OUTER_GAIN:
  346. case AL_SEC_OFFSET:
  347. case AL_SAMPLE_OFFSET:
  348. case AL_BYTE_OFFSET:
  349. case AL_CONE_INNER_ANGLE:
  350. case AL_CONE_OUTER_ANGLE:
  351. case AL_REFERENCE_DISTANCE:
  352. case AL_CONE_OUTER_GAINHF:
  353. case AL_AIR_ABSORPTION_FACTOR:
  354. case AL_ROOM_ROLLOFF_FACTOR:
  355. case AL_DIRECT_FILTER_GAINHF_AUTO:
  356. case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
  357. case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
  358. case AL_DIRECT_CHANNELS_SOFT:
  359. case AL_DISTANCE_MODEL:
  360. case AL_SOURCE_RELATIVE:
  361. case AL_LOOPING:
  362. case AL_BUFFER:
  363. case AL_SOURCE_STATE:
  364. case AL_BUFFERS_QUEUED:
  365. case AL_BUFFERS_PROCESSED:
  366. case AL_SOURCE_TYPE:
  367. case AL_DIRECT_FILTER:
  368. case AL_SOURCE_RADIUS:
  369. case AL_SOURCE_RESAMPLER_SOFT:
  370. case AL_SOURCE_SPATIALIZE_SOFT:
  371. return 1;
  372. case AL_POSITION:
  373. case AL_VELOCITY:
  374. case AL_DIRECTION:
  375. case AL_AUXILIARY_SEND_FILTER:
  376. return 3;
  377. case AL_ORIENTATION:
  378. return 6;
  379. case AL_SAMPLE_OFFSET_LATENCY_SOFT:
  380. case AL_SAMPLE_OFFSET_CLOCK_SOFT:
  381. break; /* i64 only */
  382. case AL_SEC_OFFSET_LATENCY_SOFT:
  383. case AL_SEC_OFFSET_CLOCK_SOFT:
  384. break; /* Double only */
  385. case AL_STEREO_ANGLES:
  386. break; /* Float/double only */
  387. }
  388. return 0;
  389. }
  390. static ALint Int64ValsByProp(ALenum prop)
  391. {
  392. if(prop != (ALenum)((SourceProp)prop))
  393. return 0;
  394. switch((SourceProp)prop)
  395. {
  396. case AL_PITCH:
  397. case AL_GAIN:
  398. case AL_MIN_GAIN:
  399. case AL_MAX_GAIN:
  400. case AL_MAX_DISTANCE:
  401. case AL_ROLLOFF_FACTOR:
  402. case AL_DOPPLER_FACTOR:
  403. case AL_CONE_OUTER_GAIN:
  404. case AL_SEC_OFFSET:
  405. case AL_SAMPLE_OFFSET:
  406. case AL_BYTE_OFFSET:
  407. case AL_CONE_INNER_ANGLE:
  408. case AL_CONE_OUTER_ANGLE:
  409. case AL_REFERENCE_DISTANCE:
  410. case AL_CONE_OUTER_GAINHF:
  411. case AL_AIR_ABSORPTION_FACTOR:
  412. case AL_ROOM_ROLLOFF_FACTOR:
  413. case AL_DIRECT_FILTER_GAINHF_AUTO:
  414. case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
  415. case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
  416. case AL_DIRECT_CHANNELS_SOFT:
  417. case AL_DISTANCE_MODEL:
  418. case AL_SOURCE_RELATIVE:
  419. case AL_LOOPING:
  420. case AL_BUFFER:
  421. case AL_SOURCE_STATE:
  422. case AL_BUFFERS_QUEUED:
  423. case AL_BUFFERS_PROCESSED:
  424. case AL_SOURCE_TYPE:
  425. case AL_DIRECT_FILTER:
  426. case AL_SOURCE_RADIUS:
  427. case AL_SOURCE_RESAMPLER_SOFT:
  428. case AL_SOURCE_SPATIALIZE_SOFT:
  429. return 1;
  430. case AL_SAMPLE_OFFSET_LATENCY_SOFT:
  431. case AL_SAMPLE_OFFSET_CLOCK_SOFT:
  432. return 2;
  433. case AL_POSITION:
  434. case AL_VELOCITY:
  435. case AL_DIRECTION:
  436. case AL_AUXILIARY_SEND_FILTER:
  437. return 3;
  438. case AL_ORIENTATION:
  439. return 6;
  440. case AL_SEC_OFFSET_LATENCY_SOFT:
  441. case AL_SEC_OFFSET_CLOCK_SOFT:
  442. break; /* Double only */
  443. case AL_STEREO_ANGLES:
  444. break; /* Float/double only */
  445. }
  446. return 0;
  447. }
  448. #define CHECKVAL(x) do { \
  449. if(!(x)) \
  450. { \
  451. alSetError(Context, AL_INVALID_VALUE, "Value out of range"); \
  452. return AL_FALSE; \
  453. } \
  454. } while(0)
  455. #define DO_UPDATEPROPS() do { \
  456. ALvoice *voice; \
  457. if(SourceShouldUpdate(Source, Context) && \
  458. (voice=GetSourceVoice(Source, Context)) != NULL) \
  459. UpdateSourceProps(Source, voice, device->NumAuxSends, Context); \
  460. else \
  461. ATOMIC_FLAG_CLEAR(&Source->PropsClean, almemory_order_release); \
  462. } while(0)
  463. static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp prop, const ALfloat *values)
  464. {
  465. ALCdevice *device = Context->Device;
  466. ALint ival;
  467. switch(prop)
  468. {
  469. case AL_SEC_OFFSET_LATENCY_SOFT:
  470. case AL_SEC_OFFSET_CLOCK_SOFT:
  471. /* Query only */
  472. SETERR_RETURN(Context, AL_INVALID_OPERATION, AL_FALSE,
  473. "Setting read-only source property 0x%04x", prop);
  474. case AL_PITCH:
  475. CHECKVAL(*values >= 0.0f);
  476. Source->Pitch = *values;
  477. DO_UPDATEPROPS();
  478. return AL_TRUE;
  479. case AL_CONE_INNER_ANGLE:
  480. CHECKVAL(*values >= 0.0f && *values <= 360.0f);
  481. Source->InnerAngle = *values;
  482. DO_UPDATEPROPS();
  483. return AL_TRUE;
  484. case AL_CONE_OUTER_ANGLE:
  485. CHECKVAL(*values >= 0.0f && *values <= 360.0f);
  486. Source->OuterAngle = *values;
  487. DO_UPDATEPROPS();
  488. return AL_TRUE;
  489. case AL_GAIN:
  490. CHECKVAL(*values >= 0.0f);
  491. Source->Gain = *values;
  492. DO_UPDATEPROPS();
  493. return AL_TRUE;
  494. case AL_MAX_DISTANCE:
  495. CHECKVAL(*values >= 0.0f);
  496. Source->MaxDistance = *values;
  497. DO_UPDATEPROPS();
  498. return AL_TRUE;
  499. case AL_ROLLOFF_FACTOR:
  500. CHECKVAL(*values >= 0.0f);
  501. Source->RolloffFactor = *values;
  502. DO_UPDATEPROPS();
  503. return AL_TRUE;
  504. case AL_REFERENCE_DISTANCE:
  505. CHECKVAL(*values >= 0.0f);
  506. Source->RefDistance = *values;
  507. DO_UPDATEPROPS();
  508. return AL_TRUE;
  509. case AL_MIN_GAIN:
  510. CHECKVAL(*values >= 0.0f);
  511. Source->MinGain = *values;
  512. DO_UPDATEPROPS();
  513. return AL_TRUE;
  514. case AL_MAX_GAIN:
  515. CHECKVAL(*values >= 0.0f);
  516. Source->MaxGain = *values;
  517. DO_UPDATEPROPS();
  518. return AL_TRUE;
  519. case AL_CONE_OUTER_GAIN:
  520. CHECKVAL(*values >= 0.0f && *values <= 1.0f);
  521. Source->OuterGain = *values;
  522. DO_UPDATEPROPS();
  523. return AL_TRUE;
  524. case AL_CONE_OUTER_GAINHF:
  525. CHECKVAL(*values >= 0.0f && *values <= 1.0f);
  526. Source->OuterGainHF = *values;
  527. DO_UPDATEPROPS();
  528. return AL_TRUE;
  529. case AL_AIR_ABSORPTION_FACTOR:
  530. CHECKVAL(*values >= 0.0f && *values <= 10.0f);
  531. Source->AirAbsorptionFactor = *values;
  532. DO_UPDATEPROPS();
  533. return AL_TRUE;
  534. case AL_ROOM_ROLLOFF_FACTOR:
  535. CHECKVAL(*values >= 0.0f && *values <= 10.0f);
  536. Source->RoomRolloffFactor = *values;
  537. DO_UPDATEPROPS();
  538. return AL_TRUE;
  539. case AL_DOPPLER_FACTOR:
  540. CHECKVAL(*values >= 0.0f && *values <= 1.0f);
  541. Source->DopplerFactor = *values;
  542. DO_UPDATEPROPS();
  543. return AL_TRUE;
  544. case AL_SEC_OFFSET:
  545. case AL_SAMPLE_OFFSET:
  546. case AL_BYTE_OFFSET:
  547. CHECKVAL(*values >= 0.0f);
  548. Source->OffsetType = prop;
  549. Source->Offset = *values;
  550. if(IsPlayingOrPaused(Source))
  551. {
  552. ALvoice *voice;
  553. ALCdevice_Lock(Context->Device);
  554. /* Double-check that the source is still playing while we have
  555. * the lock.
  556. */
  557. voice = GetSourceVoice(Source, Context);
  558. if(voice)
  559. {
  560. if(ApplyOffset(Source, voice) == AL_FALSE)
  561. {
  562. ALCdevice_Unlock(Context->Device);
  563. SETERR_RETURN(Context, AL_INVALID_VALUE, AL_FALSE, "Invalid offset");
  564. }
  565. }
  566. ALCdevice_Unlock(Context->Device);
  567. }
  568. return AL_TRUE;
  569. case AL_SOURCE_RADIUS:
  570. CHECKVAL(*values >= 0.0f && isfinite(*values));
  571. Source->Radius = *values;
  572. DO_UPDATEPROPS();
  573. return AL_TRUE;
  574. case AL_STEREO_ANGLES:
  575. CHECKVAL(isfinite(values[0]) && isfinite(values[1]));
  576. Source->StereoPan[0] = values[0];
  577. Source->StereoPan[1] = values[1];
  578. DO_UPDATEPROPS();
  579. return AL_TRUE;
  580. case AL_POSITION:
  581. CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
  582. Source->Position[0] = values[0];
  583. Source->Position[1] = values[1];
  584. Source->Position[2] = values[2];
  585. DO_UPDATEPROPS();
  586. return AL_TRUE;
  587. case AL_VELOCITY:
  588. CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
  589. Source->Velocity[0] = values[0];
  590. Source->Velocity[1] = values[1];
  591. Source->Velocity[2] = values[2];
  592. DO_UPDATEPROPS();
  593. return AL_TRUE;
  594. case AL_DIRECTION:
  595. CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
  596. Source->Direction[0] = values[0];
  597. Source->Direction[1] = values[1];
  598. Source->Direction[2] = values[2];
  599. DO_UPDATEPROPS();
  600. return AL_TRUE;
  601. case AL_ORIENTATION:
  602. CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]) &&
  603. isfinite(values[3]) && isfinite(values[4]) && isfinite(values[5]));
  604. Source->Orientation[0][0] = values[0];
  605. Source->Orientation[0][1] = values[1];
  606. Source->Orientation[0][2] = values[2];
  607. Source->Orientation[1][0] = values[3];
  608. Source->Orientation[1][1] = values[4];
  609. Source->Orientation[1][2] = values[5];
  610. DO_UPDATEPROPS();
  611. return AL_TRUE;
  612. case AL_SOURCE_RELATIVE:
  613. case AL_LOOPING:
  614. case AL_SOURCE_STATE:
  615. case AL_SOURCE_TYPE:
  616. case AL_DISTANCE_MODEL:
  617. case AL_DIRECT_FILTER_GAINHF_AUTO:
  618. case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
  619. case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
  620. case AL_DIRECT_CHANNELS_SOFT:
  621. case AL_SOURCE_RESAMPLER_SOFT:
  622. case AL_SOURCE_SPATIALIZE_SOFT:
  623. ival = (ALint)values[0];
  624. return SetSourceiv(Source, Context, prop, &ival);
  625. case AL_BUFFERS_QUEUED:
  626. case AL_BUFFERS_PROCESSED:
  627. ival = (ALint)((ALuint)values[0]);
  628. return SetSourceiv(Source, Context, prop, &ival);
  629. case AL_BUFFER:
  630. case AL_DIRECT_FILTER:
  631. case AL_AUXILIARY_SEND_FILTER:
  632. case AL_SAMPLE_OFFSET_LATENCY_SOFT:
  633. case AL_SAMPLE_OFFSET_CLOCK_SOFT:
  634. break;
  635. }
  636. ERR("Unexpected property: 0x%04x\n", prop);
  637. SETERR_RETURN(Context, AL_INVALID_ENUM, AL_FALSE, "Invalid source float property 0x%04x", prop);
  638. }
  639. static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, const ALint *values)
  640. {
  641. ALCdevice *device = Context->Device;
  642. ALbuffer *buffer = NULL;
  643. ALfilter *filter = NULL;
  644. ALeffectslot *slot = NULL;
  645. ALbufferlistitem *oldlist;
  646. ALfloat fvals[6];
  647. switch(prop)
  648. {
  649. case AL_SOURCE_STATE:
  650. case AL_SOURCE_TYPE:
  651. case AL_BUFFERS_QUEUED:
  652. case AL_BUFFERS_PROCESSED:
  653. /* Query only */
  654. SETERR_RETURN(Context, AL_INVALID_OPERATION, AL_FALSE,
  655. "Setting read-only source property 0x%04x", prop);
  656. case AL_SOURCE_RELATIVE:
  657. CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
  658. Source->HeadRelative = (ALboolean)*values;
  659. DO_UPDATEPROPS();
  660. return AL_TRUE;
  661. case AL_LOOPING:
  662. CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
  663. Source->Looping = (ALboolean)*values;
  664. if(IsPlayingOrPaused(Source))
  665. {
  666. ALvoice *voice = GetSourceVoice(Source, Context);
  667. if(voice)
  668. {
  669. if(Source->Looping)
  670. ATOMIC_STORE(&voice->loop_buffer, Source->queue, almemory_order_release);
  671. else
  672. ATOMIC_STORE(&voice->loop_buffer, NULL, almemory_order_release);
  673. /* If the source is playing, wait for the current mix to finish
  674. * to ensure it isn't currently looping back or reaching the
  675. * end.
  676. */
  677. while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1))
  678. althrd_yield();
  679. }
  680. }
  681. return AL_TRUE;
  682. case AL_BUFFER:
  683. LockBufferList(device);
  684. if(!(*values == 0 || (buffer=LookupBuffer(device, *values)) != NULL))
  685. {
  686. UnlockBufferList(device);
  687. SETERR_RETURN(Context, AL_INVALID_VALUE, AL_FALSE, "Invalid buffer ID %u",
  688. *values);
  689. }
  690. if(buffer && buffer->MappedAccess != 0 &&
  691. !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT))
  692. {
  693. UnlockBufferList(device);
  694. SETERR_RETURN(Context, AL_INVALID_OPERATION, AL_FALSE,
  695. "Setting non-persistently mapped buffer %u", buffer->id);
  696. }
  697. else
  698. {
  699. ALenum state = GetSourceState(Source, GetSourceVoice(Source, Context));
  700. if(state == AL_PLAYING || state == AL_PAUSED)
  701. {
  702. UnlockBufferList(device);
  703. SETERR_RETURN(Context, AL_INVALID_OPERATION, AL_FALSE,
  704. "Setting buffer on playing or paused source %u", Source->id);
  705. }
  706. }
  707. oldlist = Source->queue;
  708. if(buffer != NULL)
  709. {
  710. /* Add the selected buffer to a one-item queue */
  711. ALbufferlistitem *newlist = al_calloc(DEF_ALIGN,
  712. FAM_SIZE(ALbufferlistitem, buffers, 1));
  713. ATOMIC_INIT(&newlist->next, NULL);
  714. newlist->max_samples = buffer->SampleLen;
  715. newlist->num_buffers = 1;
  716. newlist->buffers[0] = buffer;
  717. IncrementRef(&buffer->ref);
  718. /* Source is now Static */
  719. Source->SourceType = AL_STATIC;
  720. Source->queue = newlist;
  721. }
  722. else
  723. {
  724. /* Source is now Undetermined */
  725. Source->SourceType = AL_UNDETERMINED;
  726. Source->queue = NULL;
  727. }
  728. UnlockBufferList(device);
  729. /* Delete all elements in the previous queue */
  730. while(oldlist != NULL)
  731. {
  732. ALsizei i;
  733. ALbufferlistitem *temp = oldlist;
  734. oldlist = ATOMIC_LOAD(&temp->next, almemory_order_relaxed);
  735. for(i = 0;i < temp->num_buffers;i++)
  736. {
  737. if(temp->buffers[i])
  738. DecrementRef(&temp->buffers[i]->ref);
  739. }
  740. al_free(temp);
  741. }
  742. return AL_TRUE;
  743. case AL_SEC_OFFSET:
  744. case AL_SAMPLE_OFFSET:
  745. case AL_BYTE_OFFSET:
  746. CHECKVAL(*values >= 0);
  747. Source->OffsetType = prop;
  748. Source->Offset = *values;
  749. if(IsPlayingOrPaused(Source))
  750. {
  751. ALvoice *voice;
  752. ALCdevice_Lock(Context->Device);
  753. voice = GetSourceVoice(Source, Context);
  754. if(voice)
  755. {
  756. if(ApplyOffset(Source, voice) == AL_FALSE)
  757. {
  758. ALCdevice_Unlock(Context->Device);
  759. SETERR_RETURN(Context, AL_INVALID_VALUE, AL_FALSE,
  760. "Invalid source offset");
  761. }
  762. }
  763. ALCdevice_Unlock(Context->Device);
  764. }
  765. return AL_TRUE;
  766. case AL_DIRECT_FILTER:
  767. LockFilterList(device);
  768. if(!(*values == 0 || (filter=LookupFilter(device, *values)) != NULL))
  769. {
  770. UnlockFilterList(device);
  771. SETERR_RETURN(Context, AL_INVALID_VALUE, AL_FALSE, "Invalid filter ID %u",
  772. *values);
  773. }
  774. if(!filter)
  775. {
  776. Source->Direct.Gain = 1.0f;
  777. Source->Direct.GainHF = 1.0f;
  778. Source->Direct.HFReference = LOWPASSFREQREF;
  779. Source->Direct.GainLF = 1.0f;
  780. Source->Direct.LFReference = HIGHPASSFREQREF;
  781. }
  782. else
  783. {
  784. Source->Direct.Gain = filter->Gain;
  785. Source->Direct.GainHF = filter->GainHF;
  786. Source->Direct.HFReference = filter->HFReference;
  787. Source->Direct.GainLF = filter->GainLF;
  788. Source->Direct.LFReference = filter->LFReference;
  789. }
  790. UnlockFilterList(device);
  791. DO_UPDATEPROPS();
  792. return AL_TRUE;
  793. case AL_DIRECT_FILTER_GAINHF_AUTO:
  794. CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
  795. Source->DryGainHFAuto = *values;
  796. DO_UPDATEPROPS();
  797. return AL_TRUE;
  798. case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
  799. CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
  800. Source->WetGainAuto = *values;
  801. DO_UPDATEPROPS();
  802. return AL_TRUE;
  803. case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
  804. CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
  805. Source->WetGainHFAuto = *values;
  806. DO_UPDATEPROPS();
  807. return AL_TRUE;
  808. case AL_DIRECT_CHANNELS_SOFT:
  809. CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
  810. Source->DirectChannels = *values;
  811. DO_UPDATEPROPS();
  812. return AL_TRUE;
  813. case AL_DISTANCE_MODEL:
  814. CHECKVAL(*values == AL_NONE ||
  815. *values == AL_INVERSE_DISTANCE ||
  816. *values == AL_INVERSE_DISTANCE_CLAMPED ||
  817. *values == AL_LINEAR_DISTANCE ||
  818. *values == AL_LINEAR_DISTANCE_CLAMPED ||
  819. *values == AL_EXPONENT_DISTANCE ||
  820. *values == AL_EXPONENT_DISTANCE_CLAMPED);
  821. Source->DistanceModel = *values;
  822. if(Context->SourceDistanceModel)
  823. DO_UPDATEPROPS();
  824. return AL_TRUE;
  825. case AL_SOURCE_RESAMPLER_SOFT:
  826. CHECKVAL(*values >= 0 && *values <= ResamplerMax);
  827. Source->Resampler = *values;
  828. DO_UPDATEPROPS();
  829. return AL_TRUE;
  830. case AL_SOURCE_SPATIALIZE_SOFT:
  831. CHECKVAL(*values >= AL_FALSE && *values <= AL_AUTO_SOFT);
  832. Source->Spatialize = *values;
  833. DO_UPDATEPROPS();
  834. return AL_TRUE;
  835. case AL_AUXILIARY_SEND_FILTER:
  836. LockEffectSlotList(Context);
  837. if(!(values[0] == 0 || (slot=LookupEffectSlot(Context, values[0])) != NULL))
  838. {
  839. UnlockEffectSlotList(Context);
  840. SETERR_RETURN(Context, AL_INVALID_VALUE, AL_FALSE, "Invalid effect ID %u",
  841. values[0]);
  842. }
  843. if(!((ALuint)values[1] < (ALuint)device->NumAuxSends))
  844. {
  845. UnlockEffectSlotList(Context);
  846. SETERR_RETURN(Context, AL_INVALID_VALUE, AL_FALSE, "Invalid send %u", values[1]);
  847. }
  848. LockFilterList(device);
  849. if(!(values[2] == 0 || (filter=LookupFilter(device, values[2])) != NULL))
  850. {
  851. UnlockFilterList(device);
  852. UnlockEffectSlotList(Context);
  853. SETERR_RETURN(Context, AL_INVALID_VALUE, AL_FALSE, "Invalid filter ID %u",
  854. values[2]);
  855. }
  856. if(!filter)
  857. {
  858. /* Disable filter */
  859. Source->Send[values[1]].Gain = 1.0f;
  860. Source->Send[values[1]].GainHF = 1.0f;
  861. Source->Send[values[1]].HFReference = LOWPASSFREQREF;
  862. Source->Send[values[1]].GainLF = 1.0f;
  863. Source->Send[values[1]].LFReference = HIGHPASSFREQREF;
  864. }
  865. else
  866. {
  867. Source->Send[values[1]].Gain = filter->Gain;
  868. Source->Send[values[1]].GainHF = filter->GainHF;
  869. Source->Send[values[1]].HFReference = filter->HFReference;
  870. Source->Send[values[1]].GainLF = filter->GainLF;
  871. Source->Send[values[1]].LFReference = filter->LFReference;
  872. }
  873. UnlockFilterList(device);
  874. if(slot != Source->Send[values[1]].Slot && IsPlayingOrPaused(Source))
  875. {
  876. ALvoice *voice;
  877. /* Add refcount on the new slot, and release the previous slot */
  878. if(slot) IncrementRef(&slot->ref);
  879. if(Source->Send[values[1]].Slot)
  880. DecrementRef(&Source->Send[values[1]].Slot->ref);
  881. Source->Send[values[1]].Slot = slot;
  882. /* We must force an update if the auxiliary slot changed on an
  883. * active source, in case the slot is about to be deleted.
  884. */
  885. if((voice=GetSourceVoice(Source, Context)) != NULL)
  886. UpdateSourceProps(Source, voice, device->NumAuxSends, Context);
  887. else
  888. ATOMIC_FLAG_CLEAR(&Source->PropsClean, almemory_order_release);
  889. }
  890. else
  891. {
  892. if(slot) IncrementRef(&slot->ref);
  893. if(Source->Send[values[1]].Slot)
  894. DecrementRef(&Source->Send[values[1]].Slot->ref);
  895. Source->Send[values[1]].Slot = slot;
  896. DO_UPDATEPROPS();
  897. }
  898. UnlockEffectSlotList(Context);
  899. return AL_TRUE;
  900. /* 1x float */
  901. case AL_CONE_INNER_ANGLE:
  902. case AL_CONE_OUTER_ANGLE:
  903. case AL_PITCH:
  904. case AL_GAIN:
  905. case AL_MIN_GAIN:
  906. case AL_MAX_GAIN:
  907. case AL_REFERENCE_DISTANCE:
  908. case AL_ROLLOFF_FACTOR:
  909. case AL_CONE_OUTER_GAIN:
  910. case AL_MAX_DISTANCE:
  911. case AL_DOPPLER_FACTOR:
  912. case AL_CONE_OUTER_GAINHF:
  913. case AL_AIR_ABSORPTION_FACTOR:
  914. case AL_ROOM_ROLLOFF_FACTOR:
  915. case AL_SOURCE_RADIUS:
  916. fvals[0] = (ALfloat)*values;
  917. return SetSourcefv(Source, Context, (int)prop, fvals);
  918. /* 3x float */
  919. case AL_POSITION:
  920. case AL_VELOCITY:
  921. case AL_DIRECTION:
  922. fvals[0] = (ALfloat)values[0];
  923. fvals[1] = (ALfloat)values[1];
  924. fvals[2] = (ALfloat)values[2];
  925. return SetSourcefv(Source, Context, (int)prop, fvals);
  926. /* 6x float */
  927. case AL_ORIENTATION:
  928. fvals[0] = (ALfloat)values[0];
  929. fvals[1] = (ALfloat)values[1];
  930. fvals[2] = (ALfloat)values[2];
  931. fvals[3] = (ALfloat)values[3];
  932. fvals[4] = (ALfloat)values[4];
  933. fvals[5] = (ALfloat)values[5];
  934. return SetSourcefv(Source, Context, (int)prop, fvals);
  935. case AL_SAMPLE_OFFSET_LATENCY_SOFT:
  936. case AL_SEC_OFFSET_LATENCY_SOFT:
  937. case AL_SEC_OFFSET_CLOCK_SOFT:
  938. case AL_SAMPLE_OFFSET_CLOCK_SOFT:
  939. case AL_STEREO_ANGLES:
  940. break;
  941. }
  942. ERR("Unexpected property: 0x%04x\n", prop);
  943. SETERR_RETURN(Context, AL_INVALID_ENUM, AL_FALSE, "Invalid source integer property 0x%04x",
  944. prop);
  945. }
  946. static ALboolean SetSourcei64v(ALsource *Source, ALCcontext *Context, SourceProp prop, const ALint64SOFT *values)
  947. {
  948. ALfloat fvals[6];
  949. ALint ivals[3];
  950. switch(prop)
  951. {
  952. case AL_SOURCE_TYPE:
  953. case AL_BUFFERS_QUEUED:
  954. case AL_BUFFERS_PROCESSED:
  955. case AL_SOURCE_STATE:
  956. case AL_SAMPLE_OFFSET_LATENCY_SOFT:
  957. case AL_SAMPLE_OFFSET_CLOCK_SOFT:
  958. /* Query only */
  959. SETERR_RETURN(Context, AL_INVALID_OPERATION, AL_FALSE,
  960. "Setting read-only source property 0x%04x", prop);
  961. /* 1x int */
  962. case AL_SOURCE_RELATIVE:
  963. case AL_LOOPING:
  964. case AL_SEC_OFFSET:
  965. case AL_SAMPLE_OFFSET:
  966. case AL_BYTE_OFFSET:
  967. case AL_DIRECT_FILTER_GAINHF_AUTO:
  968. case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
  969. case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
  970. case AL_DIRECT_CHANNELS_SOFT:
  971. case AL_DISTANCE_MODEL:
  972. case AL_SOURCE_RESAMPLER_SOFT:
  973. case AL_SOURCE_SPATIALIZE_SOFT:
  974. CHECKVAL(*values <= INT_MAX && *values >= INT_MIN);
  975. ivals[0] = (ALint)*values;
  976. return SetSourceiv(Source, Context, (int)prop, ivals);
  977. /* 1x uint */
  978. case AL_BUFFER:
  979. case AL_DIRECT_FILTER:
  980. CHECKVAL(*values <= UINT_MAX && *values >= 0);
  981. ivals[0] = (ALuint)*values;
  982. return SetSourceiv(Source, Context, (int)prop, ivals);
  983. /* 3x uint */
  984. case AL_AUXILIARY_SEND_FILTER:
  985. CHECKVAL(values[0] <= UINT_MAX && values[0] >= 0 &&
  986. values[1] <= UINT_MAX && values[1] >= 0 &&
  987. values[2] <= UINT_MAX && values[2] >= 0);
  988. ivals[0] = (ALuint)values[0];
  989. ivals[1] = (ALuint)values[1];
  990. ivals[2] = (ALuint)values[2];
  991. return SetSourceiv(Source, Context, (int)prop, ivals);
  992. /* 1x float */
  993. case AL_CONE_INNER_ANGLE:
  994. case AL_CONE_OUTER_ANGLE:
  995. case AL_PITCH:
  996. case AL_GAIN:
  997. case AL_MIN_GAIN:
  998. case AL_MAX_GAIN:
  999. case AL_REFERENCE_DISTANCE:
  1000. case AL_ROLLOFF_FACTOR:
  1001. case AL_CONE_OUTER_GAIN:
  1002. case AL_MAX_DISTANCE:
  1003. case AL_DOPPLER_FACTOR:
  1004. case AL_CONE_OUTER_GAINHF:
  1005. case AL_AIR_ABSORPTION_FACTOR:
  1006. case AL_ROOM_ROLLOFF_FACTOR:
  1007. case AL_SOURCE_RADIUS:
  1008. fvals[0] = (ALfloat)*values;
  1009. return SetSourcefv(Source, Context, (int)prop, fvals);
  1010. /* 3x float */
  1011. case AL_POSITION:
  1012. case AL_VELOCITY:
  1013. case AL_DIRECTION:
  1014. fvals[0] = (ALfloat)values[0];
  1015. fvals[1] = (ALfloat)values[1];
  1016. fvals[2] = (ALfloat)values[2];
  1017. return SetSourcefv(Source, Context, (int)prop, fvals);
  1018. /* 6x float */
  1019. case AL_ORIENTATION:
  1020. fvals[0] = (ALfloat)values[0];
  1021. fvals[1] = (ALfloat)values[1];
  1022. fvals[2] = (ALfloat)values[2];
  1023. fvals[3] = (ALfloat)values[3];
  1024. fvals[4] = (ALfloat)values[4];
  1025. fvals[5] = (ALfloat)values[5];
  1026. return SetSourcefv(Source, Context, (int)prop, fvals);
  1027. case AL_SEC_OFFSET_LATENCY_SOFT:
  1028. case AL_SEC_OFFSET_CLOCK_SOFT:
  1029. case AL_STEREO_ANGLES:
  1030. break;
  1031. }
  1032. ERR("Unexpected property: 0x%04x\n", prop);
  1033. SETERR_RETURN(Context, AL_INVALID_ENUM, AL_FALSE, "Invalid source integer64 property 0x%04x",
  1034. prop);
  1035. }
  1036. #undef CHECKVAL
  1037. static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SourceProp prop, ALdouble *values)
  1038. {
  1039. ALCdevice *device = Context->Device;
  1040. ClockLatency clocktime;
  1041. ALuint64 srcclock;
  1042. ALint ivals[3];
  1043. ALboolean err;
  1044. switch(prop)
  1045. {
  1046. case AL_GAIN:
  1047. *values = Source->Gain;
  1048. return AL_TRUE;
  1049. case AL_PITCH:
  1050. *values = Source->Pitch;
  1051. return AL_TRUE;
  1052. case AL_MAX_DISTANCE:
  1053. *values = Source->MaxDistance;
  1054. return AL_TRUE;
  1055. case AL_ROLLOFF_FACTOR:
  1056. *values = Source->RolloffFactor;
  1057. return AL_TRUE;
  1058. case AL_REFERENCE_DISTANCE:
  1059. *values = Source->RefDistance;
  1060. return AL_TRUE;
  1061. case AL_CONE_INNER_ANGLE:
  1062. *values = Source->InnerAngle;
  1063. return AL_TRUE;
  1064. case AL_CONE_OUTER_ANGLE:
  1065. *values = Source->OuterAngle;
  1066. return AL_TRUE;
  1067. case AL_MIN_GAIN:
  1068. *values = Source->MinGain;
  1069. return AL_TRUE;
  1070. case AL_MAX_GAIN:
  1071. *values = Source->MaxGain;
  1072. return AL_TRUE;
  1073. case AL_CONE_OUTER_GAIN:
  1074. *values = Source->OuterGain;
  1075. return AL_TRUE;
  1076. case AL_SEC_OFFSET:
  1077. case AL_SAMPLE_OFFSET:
  1078. case AL_BYTE_OFFSET:
  1079. *values = GetSourceOffset(Source, prop, Context);
  1080. return AL_TRUE;
  1081. case AL_CONE_OUTER_GAINHF:
  1082. *values = Source->OuterGainHF;
  1083. return AL_TRUE;
  1084. case AL_AIR_ABSORPTION_FACTOR:
  1085. *values = Source->AirAbsorptionFactor;
  1086. return AL_TRUE;
  1087. case AL_ROOM_ROLLOFF_FACTOR:
  1088. *values = Source->RoomRolloffFactor;
  1089. return AL_TRUE;
  1090. case AL_DOPPLER_FACTOR:
  1091. *values = Source->DopplerFactor;
  1092. return AL_TRUE;
  1093. case AL_SOURCE_RADIUS:
  1094. *values = Source->Radius;
  1095. return AL_TRUE;
  1096. case AL_STEREO_ANGLES:
  1097. values[0] = Source->StereoPan[0];
  1098. values[1] = Source->StereoPan[1];
  1099. return AL_TRUE;
  1100. case AL_SEC_OFFSET_LATENCY_SOFT:
  1101. /* Get the source offset with the clock time first. Then get the
  1102. * clock time with the device latency. Order is important.
  1103. */
  1104. values[0] = GetSourceSecOffset(Source, Context, &srcclock);
  1105. almtx_lock(&device->BackendLock);
  1106. clocktime = GetClockLatency(device);
  1107. almtx_unlock(&device->BackendLock);
  1108. if(srcclock == (ALuint64)clocktime.ClockTime)
  1109. values[1] = (ALdouble)clocktime.Latency / 1000000000.0;
  1110. else
  1111. {
  1112. /* If the clock time incremented, reduce the latency by that
  1113. * much since it's that much closer to the source offset it got
  1114. * earlier.
  1115. */
  1116. ALuint64 diff = clocktime.ClockTime - srcclock;
  1117. values[1] = (ALdouble)(clocktime.Latency - minu64(clocktime.Latency, diff)) /
  1118. 1000000000.0;
  1119. }
  1120. return AL_TRUE;
  1121. case AL_SEC_OFFSET_CLOCK_SOFT:
  1122. values[0] = GetSourceSecOffset(Source, Context, &srcclock);
  1123. values[1] = srcclock / 1000000000.0;
  1124. return AL_TRUE;
  1125. case AL_POSITION:
  1126. values[0] = Source->Position[0];
  1127. values[1] = Source->Position[1];
  1128. values[2] = Source->Position[2];
  1129. return AL_TRUE;
  1130. case AL_VELOCITY:
  1131. values[0] = Source->Velocity[0];
  1132. values[1] = Source->Velocity[1];
  1133. values[2] = Source->Velocity[2];
  1134. return AL_TRUE;
  1135. case AL_DIRECTION:
  1136. values[0] = Source->Direction[0];
  1137. values[1] = Source->Direction[1];
  1138. values[2] = Source->Direction[2];
  1139. return AL_TRUE;
  1140. case AL_ORIENTATION:
  1141. values[0] = Source->Orientation[0][0];
  1142. values[1] = Source->Orientation[0][1];
  1143. values[2] = Source->Orientation[0][2];
  1144. values[3] = Source->Orientation[1][0];
  1145. values[4] = Source->Orientation[1][1];
  1146. values[5] = Source->Orientation[1][2];
  1147. return AL_TRUE;
  1148. /* 1x int */
  1149. case AL_SOURCE_RELATIVE:
  1150. case AL_LOOPING:
  1151. case AL_SOURCE_STATE:
  1152. case AL_BUFFERS_QUEUED:
  1153. case AL_BUFFERS_PROCESSED:
  1154. case AL_SOURCE_TYPE:
  1155. case AL_DIRECT_FILTER_GAINHF_AUTO:
  1156. case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
  1157. case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
  1158. case AL_DIRECT_CHANNELS_SOFT:
  1159. case AL_DISTANCE_MODEL:
  1160. case AL_SOURCE_RESAMPLER_SOFT:
  1161. case AL_SOURCE_SPATIALIZE_SOFT:
  1162. if((err=GetSourceiv(Source, Context, (int)prop, ivals)) != AL_FALSE)
  1163. *values = (ALdouble)ivals[0];
  1164. return err;
  1165. case AL_BUFFER:
  1166. case AL_DIRECT_FILTER:
  1167. case AL_AUXILIARY_SEND_FILTER:
  1168. case AL_SAMPLE_OFFSET_LATENCY_SOFT:
  1169. case AL_SAMPLE_OFFSET_CLOCK_SOFT:
  1170. break;
  1171. }
  1172. ERR("Unexpected property: 0x%04x\n", prop);
  1173. SETERR_RETURN(Context, AL_INVALID_ENUM, AL_FALSE, "Invalid source double property 0x%04x",
  1174. prop);
  1175. }
  1176. static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, ALint *values)
  1177. {
  1178. ALbufferlistitem *BufferList;
  1179. ALdouble dvals[6];
  1180. ALboolean err;
  1181. switch(prop)
  1182. {
  1183. case AL_SOURCE_RELATIVE:
  1184. *values = Source->HeadRelative;
  1185. return AL_TRUE;
  1186. case AL_LOOPING:
  1187. *values = Source->Looping;
  1188. return AL_TRUE;
  1189. case AL_BUFFER:
  1190. BufferList = (Source->SourceType == AL_STATIC) ? Source->queue : NULL;
  1191. *values = (BufferList && BufferList->num_buffers >= 1 && BufferList->buffers[0]) ?
  1192. BufferList->buffers[0]->id : 0;
  1193. return AL_TRUE;
  1194. case AL_SOURCE_STATE:
  1195. *values = GetSourceState(Source, GetSourceVoice(Source, Context));
  1196. return AL_TRUE;
  1197. case AL_BUFFERS_QUEUED:
  1198. if(!(BufferList=Source->queue))
  1199. *values = 0;
  1200. else
  1201. {
  1202. ALsizei count = 0;
  1203. do {
  1204. count += BufferList->num_buffers;
  1205. BufferList = ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed);
  1206. } while(BufferList != NULL);
  1207. *values = count;
  1208. }
  1209. return AL_TRUE;
  1210. case AL_BUFFERS_PROCESSED:
  1211. if(Source->Looping || Source->SourceType != AL_STREAMING)
  1212. {
  1213. /* Buffers on a looping source are in a perpetual state of
  1214. * PENDING, so don't report any as PROCESSED */
  1215. *values = 0;
  1216. }
  1217. else
  1218. {
  1219. const ALbufferlistitem *BufferList = Source->queue;
  1220. const ALbufferlistitem *Current = NULL;
  1221. ALsizei played = 0;
  1222. ALvoice *voice;
  1223. if((voice=GetSourceVoice(Source, Context)) != NULL)
  1224. Current = ATOMIC_LOAD(&voice->current_buffer, almemory_order_relaxed);
  1225. else if(Source->state == AL_INITIAL)
  1226. Current = BufferList;
  1227. while(BufferList && BufferList != Current)
  1228. {
  1229. played += BufferList->num_buffers;
  1230. BufferList = ATOMIC_LOAD(&CONST_CAST(ALbufferlistitem*,BufferList)->next,
  1231. almemory_order_relaxed);
  1232. }
  1233. *values = played;
  1234. }
  1235. return AL_TRUE;
  1236. case AL_SOURCE_TYPE:
  1237. *values = Source->SourceType;
  1238. return AL_TRUE;
  1239. case AL_DIRECT_FILTER_GAINHF_AUTO:
  1240. *values = Source->DryGainHFAuto;
  1241. return AL_TRUE;
  1242. case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
  1243. *values = Source->WetGainAuto;
  1244. return AL_TRUE;
  1245. case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
  1246. *values = Source->WetGainHFAuto;
  1247. return AL_TRUE;
  1248. case AL_DIRECT_CHANNELS_SOFT:
  1249. *values = Source->DirectChannels;
  1250. return AL_TRUE;
  1251. case AL_DISTANCE_MODEL:
  1252. *values = Source->DistanceModel;
  1253. return AL_TRUE;
  1254. case AL_SOURCE_RESAMPLER_SOFT:
  1255. *values = Source->Resampler;
  1256. return AL_TRUE;
  1257. case AL_SOURCE_SPATIALIZE_SOFT:
  1258. *values = Source->Spatialize;
  1259. return AL_TRUE;
  1260. /* 1x float/double */
  1261. case AL_CONE_INNER_ANGLE:
  1262. case AL_CONE_OUTER_ANGLE:
  1263. case AL_PITCH:
  1264. case AL_GAIN:
  1265. case AL_MIN_GAIN:
  1266. case AL_MAX_GAIN:
  1267. case AL_REFERENCE_DISTANCE:
  1268. case AL_ROLLOFF_FACTOR:
  1269. case AL_CONE_OUTER_GAIN:
  1270. case AL_MAX_DISTANCE:
  1271. case AL_SEC_OFFSET:
  1272. case AL_SAMPLE_OFFSET:
  1273. case AL_BYTE_OFFSET:
  1274. case AL_DOPPLER_FACTOR:
  1275. case AL_AIR_ABSORPTION_FACTOR:
  1276. case AL_ROOM_ROLLOFF_FACTOR:
  1277. case AL_CONE_OUTER_GAINHF:
  1278. case AL_SOURCE_RADIUS:
  1279. if((err=GetSourcedv(Source, Context, prop, dvals)) != AL_FALSE)
  1280. *values = (ALint)dvals[0];
  1281. return err;
  1282. /* 3x float/double */
  1283. case AL_POSITION:
  1284. case AL_VELOCITY:
  1285. case AL_DIRECTION:
  1286. if((err=GetSourcedv(Source, Context, prop, dvals)) != AL_FALSE)
  1287. {
  1288. values[0] = (ALint)dvals[0];
  1289. values[1] = (ALint)dvals[1];
  1290. values[2] = (ALint)dvals[2];
  1291. }
  1292. return err;
  1293. /* 6x float/double */
  1294. case AL_ORIENTATION:
  1295. if((err=GetSourcedv(Source, Context, prop, dvals)) != AL_FALSE)
  1296. {
  1297. values[0] = (ALint)dvals[0];
  1298. values[1] = (ALint)dvals[1];
  1299. values[2] = (ALint)dvals[2];
  1300. values[3] = (ALint)dvals[3];
  1301. values[4] = (ALint)dvals[4];
  1302. values[5] = (ALint)dvals[5];
  1303. }
  1304. return err;
  1305. case AL_SAMPLE_OFFSET_LATENCY_SOFT:
  1306. case AL_SAMPLE_OFFSET_CLOCK_SOFT:
  1307. break; /* i64 only */
  1308. case AL_SEC_OFFSET_LATENCY_SOFT:
  1309. case AL_SEC_OFFSET_CLOCK_SOFT:
  1310. break; /* Double only */
  1311. case AL_STEREO_ANGLES:
  1312. break; /* Float/double only */
  1313. case AL_DIRECT_FILTER:
  1314. case AL_AUXILIARY_SEND_FILTER:
  1315. break; /* ??? */
  1316. }
  1317. ERR("Unexpected property: 0x%04x\n", prop);
  1318. SETERR_RETURN(Context, AL_INVALID_ENUM, AL_FALSE, "Invalid source integer property 0x%04x",
  1319. prop);
  1320. }
  1321. static ALboolean GetSourcei64v(ALsource *Source, ALCcontext *Context, SourceProp prop, ALint64 *values)
  1322. {
  1323. ALCdevice *device = Context->Device;
  1324. ClockLatency clocktime;
  1325. ALuint64 srcclock;
  1326. ALdouble dvals[6];
  1327. ALint ivals[3];
  1328. ALboolean err;
  1329. switch(prop)
  1330. {
  1331. case AL_SAMPLE_OFFSET_LATENCY_SOFT:
  1332. /* Get the source offset with the clock time first. Then get the
  1333. * clock time with the device latency. Order is important.
  1334. */
  1335. values[0] = GetSourceSampleOffset(Source, Context, &srcclock);
  1336. almtx_lock(&device->BackendLock);
  1337. clocktime = GetClockLatency(device);
  1338. almtx_unlock(&device->BackendLock);
  1339. if(srcclock == (ALuint64)clocktime.ClockTime)
  1340. values[1] = clocktime.Latency;
  1341. else
  1342. {
  1343. /* If the clock time incremented, reduce the latency by that
  1344. * much since it's that much closer to the source offset it got
  1345. * earlier.
  1346. */
  1347. ALuint64 diff = clocktime.ClockTime - srcclock;
  1348. values[1] = clocktime.Latency - minu64(clocktime.Latency, diff);
  1349. }
  1350. return AL_TRUE;
  1351. case AL_SAMPLE_OFFSET_CLOCK_SOFT:
  1352. values[0] = GetSourceSampleOffset(Source, Context, &srcclock);
  1353. values[1] = srcclock;
  1354. return AL_TRUE;
  1355. /* 1x float/double */
  1356. case AL_CONE_INNER_ANGLE:
  1357. case AL_CONE_OUTER_ANGLE:
  1358. case AL_PITCH:
  1359. case AL_GAIN:
  1360. case AL_MIN_GAIN:
  1361. case AL_MAX_GAIN:
  1362. case AL_REFERENCE_DISTANCE:
  1363. case AL_ROLLOFF_FACTOR:
  1364. case AL_CONE_OUTER_GAIN:
  1365. case AL_MAX_DISTANCE:
  1366. case AL_SEC_OFFSET:
  1367. case AL_SAMPLE_OFFSET:
  1368. case AL_BYTE_OFFSET:
  1369. case AL_DOPPLER_FACTOR:
  1370. case AL_AIR_ABSORPTION_FACTOR:
  1371. case AL_ROOM_ROLLOFF_FACTOR:
  1372. case AL_CONE_OUTER_GAINHF:
  1373. case AL_SOURCE_RADIUS:
  1374. if((err=GetSourcedv(Source, Context, prop, dvals)) != AL_FALSE)
  1375. *values = (ALint64)dvals[0];
  1376. return err;
  1377. /* 3x float/double */
  1378. case AL_POSITION:
  1379. case AL_VELOCITY:
  1380. case AL_DIRECTION:
  1381. if((err=GetSourcedv(Source, Context, prop, dvals)) != AL_FALSE)
  1382. {
  1383. values[0] = (ALint64)dvals[0];
  1384. values[1] = (ALint64)dvals[1];
  1385. values[2] = (ALint64)dvals[2];
  1386. }
  1387. return err;
  1388. /* 6x float/double */
  1389. case AL_ORIENTATION:
  1390. if((err=GetSourcedv(Source, Context, prop, dvals)) != AL_FALSE)
  1391. {
  1392. values[0] = (ALint64)dvals[0];
  1393. values[1] = (ALint64)dvals[1];
  1394. values[2] = (ALint64)dvals[2];
  1395. values[3] = (ALint64)dvals[3];
  1396. values[4] = (ALint64)dvals[4];
  1397. values[5] = (ALint64)dvals[5];
  1398. }
  1399. return err;
  1400. /* 1x int */
  1401. case AL_SOURCE_RELATIVE:
  1402. case AL_LOOPING:
  1403. case AL_SOURCE_STATE:
  1404. case AL_BUFFERS_QUEUED:
  1405. case AL_BUFFERS_PROCESSED:
  1406. case AL_SOURCE_TYPE:
  1407. case AL_DIRECT_FILTER_GAINHF_AUTO:
  1408. case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
  1409. case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
  1410. case AL_DIRECT_CHANNELS_SOFT:
  1411. case AL_DISTANCE_MODEL:
  1412. case AL_SOURCE_RESAMPLER_SOFT:
  1413. case AL_SOURCE_SPATIALIZE_SOFT:
  1414. if((err=GetSourceiv(Source, Context, prop, ivals)) != AL_FALSE)
  1415. *values = ivals[0];
  1416. return err;
  1417. /* 1x uint */
  1418. case AL_BUFFER:
  1419. case AL_DIRECT_FILTER:
  1420. if((err=GetSourceiv(Source, Context, prop, ivals)) != AL_FALSE)
  1421. *values = (ALuint)ivals[0];
  1422. return err;
  1423. /* 3x uint */
  1424. case AL_AUXILIARY_SEND_FILTER:
  1425. if((err=GetSourceiv(Source, Context, prop, ivals)) != AL_FALSE)
  1426. {
  1427. values[0] = (ALuint)ivals[0];
  1428. values[1] = (ALuint)ivals[1];
  1429. values[2] = (ALuint)ivals[2];
  1430. }
  1431. return err;
  1432. case AL_SEC_OFFSET_LATENCY_SOFT:
  1433. case AL_SEC_OFFSET_CLOCK_SOFT:
  1434. break; /* Double only */
  1435. case AL_STEREO_ANGLES:
  1436. break; /* Float/double only */
  1437. }
  1438. ERR("Unexpected property: 0x%04x\n", prop);
  1439. SETERR_RETURN(Context, AL_INVALID_ENUM, AL_FALSE, "Invalid source integer64 property 0x%04x",
  1440. prop);
  1441. }
  1442. AL_API ALvoid AL_APIENTRY alGenSources(ALsizei n, ALuint *sources)
  1443. {
  1444. ALCcontext *context;
  1445. ALsizei cur = 0;
  1446. context = GetContextRef();
  1447. if(!context) return;
  1448. if(!(n >= 0))
  1449. alSetError(context, AL_INVALID_VALUE, "Generating %d sources", n);
  1450. else for(cur = 0;cur < n;cur++)
  1451. {
  1452. ALsource *source = AllocSource(context);
  1453. if(!source)
  1454. {
  1455. alDeleteSources(cur, sources);
  1456. break;
  1457. }
  1458. sources[cur] = source->id;
  1459. }
  1460. ALCcontext_DecRef(context);
  1461. }
  1462. AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
  1463. {
  1464. ALCcontext *context;
  1465. ALsource *Source;
  1466. ALsizei i;
  1467. context = GetContextRef();
  1468. if(!context) return;
  1469. LockSourceList(context);
  1470. if(!(n >= 0))
  1471. SETERR_GOTO(context, AL_INVALID_VALUE, done, "Deleting %d sources", n);
  1472. /* Check that all Sources are valid */
  1473. for(i = 0;i < n;i++)
  1474. {
  1475. if(LookupSource(context, sources[i]) == NULL)
  1476. SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid source ID %u", sources[i]);
  1477. }
  1478. for(i = 0;i < n;i++)
  1479. {
  1480. if((Source=LookupSource(context, sources[i])) != NULL)
  1481. FreeSource(context, Source);
  1482. }
  1483. done:
  1484. UnlockSourceList(context);
  1485. ALCcontext_DecRef(context);
  1486. }
  1487. AL_API ALboolean AL_APIENTRY alIsSource(ALuint source)
  1488. {
  1489. ALCcontext *context;
  1490. ALboolean ret;
  1491. context = GetContextRef();
  1492. if(!context) return AL_FALSE;
  1493. LockSourceList(context);
  1494. ret = (LookupSource(context, source) ? AL_TRUE : AL_FALSE);
  1495. UnlockSourceList(context);
  1496. ALCcontext_DecRef(context);
  1497. return ret;
  1498. }
  1499. AL_API ALvoid AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value)
  1500. {
  1501. ALCcontext *Context;
  1502. ALsource *Source;
  1503. Context = GetContextRef();
  1504. if(!Context) return;
  1505. almtx_lock(&Context->PropLock);
  1506. LockSourceList(Context);
  1507. if((Source=LookupSource(Context, source)) == NULL)
  1508. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1509. else if(!(FloatValsByProp(param) == 1))
  1510. alSetError(Context, AL_INVALID_ENUM, "Invalid float property 0x%04x", param);
  1511. else
  1512. SetSourcefv(Source, Context, param, &value);
  1513. UnlockSourceList(Context);
  1514. almtx_unlock(&Context->PropLock);
  1515. ALCcontext_DecRef(Context);
  1516. }
  1517. AL_API ALvoid AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3)
  1518. {
  1519. ALCcontext *Context;
  1520. ALsource *Source;
  1521. Context = GetContextRef();
  1522. if(!Context) return;
  1523. almtx_lock(&Context->PropLock);
  1524. LockSourceList(Context);
  1525. if((Source=LookupSource(Context, source)) == NULL)
  1526. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1527. else if(!(FloatValsByProp(param) == 3))
  1528. alSetError(Context, AL_INVALID_ENUM, "Invalid 3-float property 0x%04x", param);
  1529. else
  1530. {
  1531. ALfloat fvals[3] = { value1, value2, value3 };
  1532. SetSourcefv(Source, Context, param, fvals);
  1533. }
  1534. UnlockSourceList(Context);
  1535. almtx_unlock(&Context->PropLock);
  1536. ALCcontext_DecRef(Context);
  1537. }
  1538. AL_API ALvoid AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values)
  1539. {
  1540. ALCcontext *Context;
  1541. ALsource *Source;
  1542. Context = GetContextRef();
  1543. if(!Context) return;
  1544. almtx_lock(&Context->PropLock);
  1545. LockSourceList(Context);
  1546. if((Source=LookupSource(Context, source)) == NULL)
  1547. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1548. else if(!values)
  1549. alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
  1550. else if(!(FloatValsByProp(param) > 0))
  1551. alSetError(Context, AL_INVALID_ENUM, "Invalid float-vector property 0x%04x", param);
  1552. else
  1553. SetSourcefv(Source, Context, param, values);
  1554. UnlockSourceList(Context);
  1555. almtx_unlock(&Context->PropLock);
  1556. ALCcontext_DecRef(Context);
  1557. }
  1558. AL_API ALvoid AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value)
  1559. {
  1560. ALCcontext *Context;
  1561. ALsource *Source;
  1562. Context = GetContextRef();
  1563. if(!Context) return;
  1564. almtx_lock(&Context->PropLock);
  1565. LockSourceList(Context);
  1566. if((Source=LookupSource(Context, source)) == NULL)
  1567. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1568. else if(!(DoubleValsByProp(param) == 1))
  1569. alSetError(Context, AL_INVALID_ENUM, "Invalid double property 0x%04x", param);
  1570. else
  1571. {
  1572. ALfloat fval = (ALfloat)value;
  1573. SetSourcefv(Source, Context, param, &fval);
  1574. }
  1575. UnlockSourceList(Context);
  1576. almtx_unlock(&Context->PropLock);
  1577. ALCcontext_DecRef(Context);
  1578. }
  1579. AL_API ALvoid AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3)
  1580. {
  1581. ALCcontext *Context;
  1582. ALsource *Source;
  1583. Context = GetContextRef();
  1584. if(!Context) return;
  1585. almtx_lock(&Context->PropLock);
  1586. LockSourceList(Context);
  1587. if((Source=LookupSource(Context, source)) == NULL)
  1588. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1589. else if(!(DoubleValsByProp(param) == 3))
  1590. alSetError(Context, AL_INVALID_ENUM, "Invalid 3-double property 0x%04x", param);
  1591. else
  1592. {
  1593. ALfloat fvals[3] = { (ALfloat)value1, (ALfloat)value2, (ALfloat)value3 };
  1594. SetSourcefv(Source, Context, param, fvals);
  1595. }
  1596. UnlockSourceList(Context);
  1597. almtx_unlock(&Context->PropLock);
  1598. ALCcontext_DecRef(Context);
  1599. }
  1600. AL_API ALvoid AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values)
  1601. {
  1602. ALCcontext *Context;
  1603. ALsource *Source;
  1604. ALint count;
  1605. Context = GetContextRef();
  1606. if(!Context) return;
  1607. almtx_lock(&Context->PropLock);
  1608. LockSourceList(Context);
  1609. if((Source=LookupSource(Context, source)) == NULL)
  1610. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1611. else if(!values)
  1612. alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
  1613. else if(!((count=DoubleValsByProp(param)) > 0 && count <= 6))
  1614. alSetError(Context, AL_INVALID_ENUM, "Invalid double-vector property 0x%04x", param);
  1615. else
  1616. {
  1617. ALfloat fvals[6];
  1618. ALint i;
  1619. for(i = 0;i < count;i++)
  1620. fvals[i] = (ALfloat)values[i];
  1621. SetSourcefv(Source, Context, param, fvals);
  1622. }
  1623. UnlockSourceList(Context);
  1624. almtx_unlock(&Context->PropLock);
  1625. ALCcontext_DecRef(Context);
  1626. }
  1627. AL_API ALvoid AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value)
  1628. {
  1629. ALCcontext *Context;
  1630. ALsource *Source;
  1631. Context = GetContextRef();
  1632. if(!Context) return;
  1633. almtx_lock(&Context->PropLock);
  1634. LockSourceList(Context);
  1635. if((Source=LookupSource(Context, source)) == NULL)
  1636. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1637. else if(!(IntValsByProp(param) == 1))
  1638. alSetError(Context, AL_INVALID_ENUM, "Invalid integer property 0x%04x", param);
  1639. else
  1640. SetSourceiv(Source, Context, param, &value);
  1641. UnlockSourceList(Context);
  1642. almtx_unlock(&Context->PropLock);
  1643. ALCcontext_DecRef(Context);
  1644. }
  1645. AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3)
  1646. {
  1647. ALCcontext *Context;
  1648. ALsource *Source;
  1649. Context = GetContextRef();
  1650. if(!Context) return;
  1651. almtx_lock(&Context->PropLock);
  1652. LockSourceList(Context);
  1653. if((Source=LookupSource(Context, source)) == NULL)
  1654. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1655. else if(!(IntValsByProp(param) == 3))
  1656. alSetError(Context, AL_INVALID_ENUM, "Invalid 3-integer property 0x%04x", param);
  1657. else
  1658. {
  1659. ALint ivals[3] = { value1, value2, value3 };
  1660. SetSourceiv(Source, Context, param, ivals);
  1661. }
  1662. UnlockSourceList(Context);
  1663. almtx_unlock(&Context->PropLock);
  1664. ALCcontext_DecRef(Context);
  1665. }
  1666. AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values)
  1667. {
  1668. ALCcontext *Context;
  1669. ALsource *Source;
  1670. Context = GetContextRef();
  1671. if(!Context) return;
  1672. almtx_lock(&Context->PropLock);
  1673. LockSourceList(Context);
  1674. if((Source=LookupSource(Context, source)) == NULL)
  1675. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1676. else if(!values)
  1677. alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
  1678. else if(!(IntValsByProp(param) > 0))
  1679. alSetError(Context, AL_INVALID_ENUM, "Invalid integer-vector property 0x%04x", param);
  1680. else
  1681. SetSourceiv(Source, Context, param, values);
  1682. UnlockSourceList(Context);
  1683. almtx_unlock(&Context->PropLock);
  1684. ALCcontext_DecRef(Context);
  1685. }
  1686. AL_API ALvoid AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value)
  1687. {
  1688. ALCcontext *Context;
  1689. ALsource *Source;
  1690. Context = GetContextRef();
  1691. if(!Context) return;
  1692. almtx_lock(&Context->PropLock);
  1693. LockSourceList(Context);
  1694. if((Source=LookupSource(Context, source)) == NULL)
  1695. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1696. else if(!(Int64ValsByProp(param) == 1))
  1697. alSetError(Context, AL_INVALID_ENUM, "Invalid integer64 property 0x%04x", param);
  1698. else
  1699. SetSourcei64v(Source, Context, param, &value);
  1700. UnlockSourceList(Context);
  1701. almtx_unlock(&Context->PropLock);
  1702. ALCcontext_DecRef(Context);
  1703. }
  1704. AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3)
  1705. {
  1706. ALCcontext *Context;
  1707. ALsource *Source;
  1708. Context = GetContextRef();
  1709. if(!Context) return;
  1710. almtx_lock(&Context->PropLock);
  1711. LockSourceList(Context);
  1712. if((Source=LookupSource(Context, source)) == NULL)
  1713. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1714. else if(!(Int64ValsByProp(param) == 3))
  1715. alSetError(Context, AL_INVALID_ENUM, "Invalid 3-integer64 property 0x%04x", param);
  1716. else
  1717. {
  1718. ALint64SOFT i64vals[3] = { value1, value2, value3 };
  1719. SetSourcei64v(Source, Context, param, i64vals);
  1720. }
  1721. UnlockSourceList(Context);
  1722. almtx_unlock(&Context->PropLock);
  1723. ALCcontext_DecRef(Context);
  1724. }
  1725. AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values)
  1726. {
  1727. ALCcontext *Context;
  1728. ALsource *Source;
  1729. Context = GetContextRef();
  1730. if(!Context) return;
  1731. almtx_lock(&Context->PropLock);
  1732. LockSourceList(Context);
  1733. if((Source=LookupSource(Context, source)) == NULL)
  1734. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1735. else if(!values)
  1736. alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
  1737. else if(!(Int64ValsByProp(param) > 0))
  1738. alSetError(Context, AL_INVALID_ENUM, "Invalid integer64-vector property 0x%04x", param);
  1739. else
  1740. SetSourcei64v(Source, Context, param, values);
  1741. UnlockSourceList(Context);
  1742. almtx_unlock(&Context->PropLock);
  1743. ALCcontext_DecRef(Context);
  1744. }
  1745. AL_API ALvoid AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value)
  1746. {
  1747. ALCcontext *Context;
  1748. ALsource *Source;
  1749. Context = GetContextRef();
  1750. if(!Context) return;
  1751. LockSourceList(Context);
  1752. if((Source=LookupSource(Context, source)) == NULL)
  1753. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1754. else if(!value)
  1755. alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
  1756. else if(!(FloatValsByProp(param) == 1))
  1757. alSetError(Context, AL_INVALID_ENUM, "Invalid float property 0x%04x", param);
  1758. else
  1759. {
  1760. ALdouble dval;
  1761. if(GetSourcedv(Source, Context, param, &dval))
  1762. *value = (ALfloat)dval;
  1763. }
  1764. UnlockSourceList(Context);
  1765. ALCcontext_DecRef(Context);
  1766. }
  1767. AL_API ALvoid AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
  1768. {
  1769. ALCcontext *Context;
  1770. ALsource *Source;
  1771. Context = GetContextRef();
  1772. if(!Context) return;
  1773. LockSourceList(Context);
  1774. if((Source=LookupSource(Context, source)) == NULL)
  1775. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1776. else if(!(value1 && value2 && value3))
  1777. alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
  1778. else if(!(FloatValsByProp(param) == 3))
  1779. alSetError(Context, AL_INVALID_ENUM, "Invalid 3-float property 0x%04x", param);
  1780. else
  1781. {
  1782. ALdouble dvals[3];
  1783. if(GetSourcedv(Source, Context, param, dvals))
  1784. {
  1785. *value1 = (ALfloat)dvals[0];
  1786. *value2 = (ALfloat)dvals[1];
  1787. *value3 = (ALfloat)dvals[2];
  1788. }
  1789. }
  1790. UnlockSourceList(Context);
  1791. ALCcontext_DecRef(Context);
  1792. }
  1793. AL_API ALvoid AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values)
  1794. {
  1795. ALCcontext *Context;
  1796. ALsource *Source;
  1797. ALint count;
  1798. Context = GetContextRef();
  1799. if(!Context) return;
  1800. LockSourceList(Context);
  1801. if((Source=LookupSource(Context, source)) == NULL)
  1802. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1803. else if(!values)
  1804. alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
  1805. else if(!((count=FloatValsByProp(param)) > 0 && count <= 6))
  1806. alSetError(Context, AL_INVALID_ENUM, "Invalid float-vector property 0x%04x", param);
  1807. else
  1808. {
  1809. ALdouble dvals[6];
  1810. if(GetSourcedv(Source, Context, param, dvals))
  1811. {
  1812. ALint i;
  1813. for(i = 0;i < count;i++)
  1814. values[i] = (ALfloat)dvals[i];
  1815. }
  1816. }
  1817. UnlockSourceList(Context);
  1818. ALCcontext_DecRef(Context);
  1819. }
  1820. AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value)
  1821. {
  1822. ALCcontext *Context;
  1823. ALsource *Source;
  1824. Context = GetContextRef();
  1825. if(!Context) return;
  1826. LockSourceList(Context);
  1827. if((Source=LookupSource(Context, source)) == NULL)
  1828. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1829. else if(!value)
  1830. alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
  1831. else if(!(DoubleValsByProp(param) == 1))
  1832. alSetError(Context, AL_INVALID_ENUM, "Invalid double property 0x%04x", param);
  1833. else
  1834. GetSourcedv(Source, Context, param, value);
  1835. UnlockSourceList(Context);
  1836. ALCcontext_DecRef(Context);
  1837. }
  1838. AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3)
  1839. {
  1840. ALCcontext *Context;
  1841. ALsource *Source;
  1842. Context = GetContextRef();
  1843. if(!Context) return;
  1844. LockSourceList(Context);
  1845. if((Source=LookupSource(Context, source)) == NULL)
  1846. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1847. else if(!(value1 && value2 && value3))
  1848. alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
  1849. else if(!(DoubleValsByProp(param) == 3))
  1850. alSetError(Context, AL_INVALID_ENUM, "Invalid 3-double property 0x%04x", param);
  1851. else
  1852. {
  1853. ALdouble dvals[3];
  1854. if(GetSourcedv(Source, Context, param, dvals))
  1855. {
  1856. *value1 = dvals[0];
  1857. *value2 = dvals[1];
  1858. *value3 = dvals[2];
  1859. }
  1860. }
  1861. UnlockSourceList(Context);
  1862. ALCcontext_DecRef(Context);
  1863. }
  1864. AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values)
  1865. {
  1866. ALCcontext *Context;
  1867. ALsource *Source;
  1868. Context = GetContextRef();
  1869. if(!Context) return;
  1870. LockSourceList(Context);
  1871. if((Source=LookupSource(Context, source)) == NULL)
  1872. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1873. else if(!values)
  1874. alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
  1875. else if(!(DoubleValsByProp(param) > 0))
  1876. alSetError(Context, AL_INVALID_ENUM, "Invalid double-vector property 0x%04x", param);
  1877. else
  1878. GetSourcedv(Source, Context, param, values);
  1879. UnlockSourceList(Context);
  1880. ALCcontext_DecRef(Context);
  1881. }
  1882. AL_API ALvoid AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value)
  1883. {
  1884. ALCcontext *Context;
  1885. ALsource *Source;
  1886. Context = GetContextRef();
  1887. if(!Context) return;
  1888. LockSourceList(Context);
  1889. if((Source=LookupSource(Context, source)) == NULL)
  1890. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1891. else if(!value)
  1892. alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
  1893. else if(!(IntValsByProp(param) == 1))
  1894. alSetError(Context, AL_INVALID_ENUM, "Invalid integer property 0x%04x", param);
  1895. else
  1896. GetSourceiv(Source, Context, param, value);
  1897. UnlockSourceList(Context);
  1898. ALCcontext_DecRef(Context);
  1899. }
  1900. AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3)
  1901. {
  1902. ALCcontext *Context;
  1903. ALsource *Source;
  1904. Context = GetContextRef();
  1905. if(!Context) return;
  1906. LockSourceList(Context);
  1907. if((Source=LookupSource(Context, source)) == NULL)
  1908. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1909. else if(!(value1 && value2 && value3))
  1910. alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
  1911. else if(!(IntValsByProp(param) == 3))
  1912. alSetError(Context, AL_INVALID_ENUM, "Invalid 3-integer property 0x%04x", param);
  1913. else
  1914. {
  1915. ALint ivals[3];
  1916. if(GetSourceiv(Source, Context, param, ivals))
  1917. {
  1918. *value1 = ivals[0];
  1919. *value2 = ivals[1];
  1920. *value3 = ivals[2];
  1921. }
  1922. }
  1923. UnlockSourceList(Context);
  1924. ALCcontext_DecRef(Context);
  1925. }
  1926. AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values)
  1927. {
  1928. ALCcontext *Context;
  1929. ALsource *Source;
  1930. Context = GetContextRef();
  1931. if(!Context) return;
  1932. LockSourceList(Context);
  1933. if((Source=LookupSource(Context, source)) == NULL)
  1934. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1935. else if(!values)
  1936. alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
  1937. else if(!(IntValsByProp(param) > 0))
  1938. alSetError(Context, AL_INVALID_ENUM, "Invalid integer-vector property 0x%04x", param);
  1939. else
  1940. GetSourceiv(Source, Context, param, values);
  1941. UnlockSourceList(Context);
  1942. ALCcontext_DecRef(Context);
  1943. }
  1944. AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value)
  1945. {
  1946. ALCcontext *Context;
  1947. ALsource *Source;
  1948. Context = GetContextRef();
  1949. if(!Context) return;
  1950. LockSourceList(Context);
  1951. if((Source=LookupSource(Context, source)) == NULL)
  1952. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1953. else if(!value)
  1954. alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
  1955. else if(!(Int64ValsByProp(param) == 1))
  1956. alSetError(Context, AL_INVALID_ENUM, "Invalid integer64 property 0x%04x", param);
  1957. else
  1958. GetSourcei64v(Source, Context, param, value);
  1959. UnlockSourceList(Context);
  1960. ALCcontext_DecRef(Context);
  1961. }
  1962. AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3)
  1963. {
  1964. ALCcontext *Context;
  1965. ALsource *Source;
  1966. Context = GetContextRef();
  1967. if(!Context) return;
  1968. LockSourceList(Context);
  1969. if((Source=LookupSource(Context, source)) == NULL)
  1970. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1971. else if(!(value1 && value2 && value3))
  1972. alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
  1973. else if(!(Int64ValsByProp(param) == 3))
  1974. alSetError(Context, AL_INVALID_ENUM, "Invalid 3-integer64 property 0x%04x", param);
  1975. else
  1976. {
  1977. ALint64 i64vals[3];
  1978. if(GetSourcei64v(Source, Context, param, i64vals))
  1979. {
  1980. *value1 = i64vals[0];
  1981. *value2 = i64vals[1];
  1982. *value3 = i64vals[2];
  1983. }
  1984. }
  1985. UnlockSourceList(Context);
  1986. ALCcontext_DecRef(Context);
  1987. }
  1988. AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values)
  1989. {
  1990. ALCcontext *Context;
  1991. ALsource *Source;
  1992. Context = GetContextRef();
  1993. if(!Context) return;
  1994. LockSourceList(Context);
  1995. if((Source=LookupSource(Context, source)) == NULL)
  1996. alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
  1997. else if(!values)
  1998. alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
  1999. else if(!(Int64ValsByProp(param) > 0))
  2000. alSetError(Context, AL_INVALID_ENUM, "Invalid integer64-vector property 0x%04x", param);
  2001. else
  2002. GetSourcei64v(Source, Context, param, values);
  2003. UnlockSourceList(Context);
  2004. ALCcontext_DecRef(Context);
  2005. }
  2006. AL_API ALvoid AL_APIENTRY alSourcePlay(ALuint source)
  2007. {
  2008. alSourcePlayv(1, &source);
  2009. }
  2010. AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources)
  2011. {
  2012. ALCcontext *context;
  2013. ALCdevice *device;
  2014. ALsource *source;
  2015. ALvoice *voice;
  2016. ALsizei i, j;
  2017. context = GetContextRef();
  2018. if(!context) return;
  2019. LockSourceList(context);
  2020. if(!(n >= 0))
  2021. SETERR_GOTO(context, AL_INVALID_VALUE, done, "Playing %d sources", n);
  2022. for(i = 0;i < n;i++)
  2023. {
  2024. if(!LookupSource(context, sources[i]))
  2025. SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid source ID %u", sources[i]);
  2026. }
  2027. device = context->Device;
  2028. ALCdevice_Lock(device);
  2029. /* If the device is disconnected, go right to stopped. */
  2030. if(!ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
  2031. {
  2032. /* TODO: Send state change event? */
  2033. for(i = 0;i < n;i++)
  2034. {
  2035. source = LookupSource(context, sources[i]);
  2036. source->OffsetType = AL_NONE;
  2037. source->Offset = 0.0;
  2038. source->state = AL_STOPPED;
  2039. }
  2040. ALCdevice_Unlock(device);
  2041. goto done;
  2042. }
  2043. while(n > context->MaxVoices-context->VoiceCount)
  2044. {
  2045. ALsizei newcount = context->MaxVoices << 1;
  2046. if(context->MaxVoices >= newcount)
  2047. {
  2048. ALCdevice_Unlock(device);
  2049. SETERR_GOTO(context, AL_OUT_OF_MEMORY, done,
  2050. "Overflow increasing voice count %d -> %d", context->MaxVoices, newcount);
  2051. }
  2052. AllocateVoices(context, newcount, device->NumAuxSends);
  2053. }
  2054. for(i = 0;i < n;i++)
  2055. {
  2056. ALbufferlistitem *BufferList;
  2057. bool start_fading = false;
  2058. ALint vidx = -1;
  2059. source = LookupSource(context, sources[i]);
  2060. /* Check that there is a queue containing at least one valid, non zero
  2061. * length buffer.
  2062. */
  2063. BufferList = source->queue;
  2064. while(BufferList && BufferList->max_samples == 0)
  2065. BufferList = ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed);
  2066. /* If there's nothing to play, go right to stopped. */
  2067. if(UNLIKELY(!BufferList))
  2068. {
  2069. /* NOTE: A source without any playable buffers should not have an
  2070. * ALvoice since it shouldn't be in a playing or paused state. So
  2071. * there's no need to look up its voice and clear the source.
  2072. */
  2073. ALenum oldstate = GetSourceState(source, NULL);
  2074. source->OffsetType = AL_NONE;
  2075. source->Offset = 0.0;
  2076. if(oldstate != AL_STOPPED)
  2077. {
  2078. source->state = AL_STOPPED;
  2079. SendStateChangeEvent(context, source->id, AL_STOPPED);
  2080. }
  2081. continue;
  2082. }
  2083. voice = GetSourceVoice(source, context);
  2084. switch(GetSourceState(source, voice))
  2085. {
  2086. case AL_PLAYING:
  2087. assert(voice != NULL);
  2088. /* A source that's already playing is restarted from the beginning. */
  2089. ATOMIC_STORE(&voice->current_buffer, BufferList, almemory_order_relaxed);
  2090. ATOMIC_STORE(&voice->position, 0, almemory_order_relaxed);
  2091. ATOMIC_STORE(&voice->position_fraction, 0, almemory_order_release);
  2092. continue;
  2093. case AL_PAUSED:
  2094. assert(voice != NULL);
  2095. /* A source that's paused simply resumes. */
  2096. ATOMIC_STORE(&voice->Playing, true, almemory_order_release);
  2097. source->state = AL_PLAYING;
  2098. SendStateChangeEvent(context, source->id, AL_PLAYING);
  2099. continue;
  2100. default:
  2101. break;
  2102. }
  2103. /* Look for an unused voice to play this source with. */
  2104. assert(voice == NULL);
  2105. for(j = 0;j < context->VoiceCount;j++)
  2106. {
  2107. if(ATOMIC_LOAD(&context->Voices[j]->Source, almemory_order_acquire) == NULL)
  2108. {
  2109. vidx = j;
  2110. break;
  2111. }
  2112. }
  2113. if(vidx == -1)
  2114. vidx = context->VoiceCount++;
  2115. voice = context->Voices[vidx];
  2116. ATOMIC_STORE(&voice->Playing, false, almemory_order_release);
  2117. ATOMIC_FLAG_TEST_AND_SET(&source->PropsClean, almemory_order_acquire);
  2118. UpdateSourceProps(source, voice, device->NumAuxSends, context);
  2119. /* A source that's not playing or paused has any offset applied when it
  2120. * starts playing.
  2121. */
  2122. if(source->Looping)
  2123. ATOMIC_STORE(&voice->loop_buffer, source->queue, almemory_order_relaxed);
  2124. else
  2125. ATOMIC_STORE(&voice->loop_buffer, NULL, almemory_order_relaxed);
  2126. ATOMIC_STORE(&voice->current_buffer, BufferList, almemory_order_relaxed);
  2127. ATOMIC_STORE(&voice->position, 0, almemory_order_relaxed);
  2128. ATOMIC_STORE(&voice->position_fraction, 0, almemory_order_relaxed);
  2129. if(ApplyOffset(source, voice) != AL_FALSE)
  2130. start_fading = ATOMIC_LOAD(&voice->position, almemory_order_relaxed) != 0 ||
  2131. ATOMIC_LOAD(&voice->position_fraction, almemory_order_relaxed) != 0 ||
  2132. ATOMIC_LOAD(&voice->current_buffer, almemory_order_relaxed) != BufferList;
  2133. for(j = 0;j < BufferList->num_buffers;j++)
  2134. {
  2135. ALbuffer *buffer = BufferList->buffers[j];
  2136. if(buffer)
  2137. {
  2138. voice->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
  2139. voice->SampleSize = BytesFromFmt(buffer->FmtType);
  2140. break;
  2141. }
  2142. }
  2143. /* Clear previous samples. */
  2144. memset(voice->PrevSamples, 0, sizeof(voice->PrevSamples));
  2145. /* Clear the stepping value so the mixer knows not to mix this until
  2146. * the update gets applied.
  2147. */
  2148. voice->Step = 0;
  2149. voice->Flags = start_fading ? VOICE_IS_FADING : 0;
  2150. if(source->SourceType == AL_STATIC) voice->Flags |= VOICE_IS_STATIC;
  2151. memset(voice->Direct.Params, 0, sizeof(voice->Direct.Params[0])*voice->NumChannels);
  2152. for(j = 0;j < device->NumAuxSends;j++)
  2153. memset(voice->Send[j].Params, 0, sizeof(voice->Send[j].Params[0])*voice->NumChannels);
  2154. if(device->AvgSpeakerDist > 0.0f)
  2155. {
  2156. ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
  2157. (device->AvgSpeakerDist * device->Frequency);
  2158. for(j = 0;j < voice->NumChannels;j++)
  2159. NfcFilterCreate(&voice->Direct.Params[j].NFCtrlFilter, 0.0f, w1);
  2160. }
  2161. ATOMIC_STORE(&voice->Source, source, almemory_order_relaxed);
  2162. ATOMIC_STORE(&voice->Playing, true, almemory_order_release);
  2163. source->state = AL_PLAYING;
  2164. source->VoiceIdx = vidx;
  2165. SendStateChangeEvent(context, source->id, AL_PLAYING);
  2166. }
  2167. ALCdevice_Unlock(device);
  2168. done:
  2169. UnlockSourceList(context);
  2170. ALCcontext_DecRef(context);
  2171. }
  2172. AL_API ALvoid AL_APIENTRY alSourcePause(ALuint source)
  2173. {
  2174. alSourcePausev(1, &source);
  2175. }
  2176. AL_API ALvoid AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources)
  2177. {
  2178. ALCcontext *context;
  2179. ALCdevice *device;
  2180. ALsource *source;
  2181. ALvoice *voice;
  2182. ALsizei i;
  2183. context = GetContextRef();
  2184. if(!context) return;
  2185. LockSourceList(context);
  2186. if(!(n >= 0))
  2187. SETERR_GOTO(context, AL_INVALID_VALUE, done, "Pausing %d sources", n);
  2188. for(i = 0;i < n;i++)
  2189. {
  2190. if(!LookupSource(context, sources[i]))
  2191. SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid source ID %u", sources[i]);
  2192. }
  2193. device = context->Device;
  2194. ALCdevice_Lock(device);
  2195. for(i = 0;i < n;i++)
  2196. {
  2197. source = LookupSource(context, sources[i]);
  2198. if((voice=GetSourceVoice(source, context)) != NULL)
  2199. ATOMIC_STORE(&voice->Playing, false, almemory_order_release);
  2200. if(GetSourceState(source, voice) == AL_PLAYING)
  2201. {
  2202. source->state = AL_PAUSED;
  2203. SendStateChangeEvent(context, source->id, AL_PAUSED);
  2204. }
  2205. }
  2206. ALCdevice_Unlock(device);
  2207. done:
  2208. UnlockSourceList(context);
  2209. ALCcontext_DecRef(context);
  2210. }
  2211. AL_API ALvoid AL_APIENTRY alSourceStop(ALuint source)
  2212. {
  2213. alSourceStopv(1, &source);
  2214. }
  2215. AL_API ALvoid AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources)
  2216. {
  2217. ALCcontext *context;
  2218. ALCdevice *device;
  2219. ALsource *source;
  2220. ALvoice *voice;
  2221. ALsizei i;
  2222. context = GetContextRef();
  2223. if(!context) return;
  2224. LockSourceList(context);
  2225. if(!(n >= 0))
  2226. SETERR_GOTO(context, AL_INVALID_VALUE, done, "Stopping %d sources", n);
  2227. for(i = 0;i < n;i++)
  2228. {
  2229. if(!LookupSource(context, sources[i]))
  2230. SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid source ID %u", sources[i]);
  2231. }
  2232. device = context->Device;
  2233. ALCdevice_Lock(device);
  2234. for(i = 0;i < n;i++)
  2235. {
  2236. ALenum oldstate;
  2237. source = LookupSource(context, sources[i]);
  2238. if((voice=GetSourceVoice(source, context)) != NULL)
  2239. {
  2240. ATOMIC_STORE(&voice->Source, NULL, almemory_order_relaxed);
  2241. ATOMIC_STORE(&voice->Playing, false, almemory_order_release);
  2242. voice = NULL;
  2243. }
  2244. oldstate = GetSourceState(source, voice);
  2245. if(oldstate != AL_INITIAL && oldstate != AL_STOPPED)
  2246. {
  2247. source->state = AL_STOPPED;
  2248. SendStateChangeEvent(context, source->id, AL_STOPPED);
  2249. }
  2250. source->OffsetType = AL_NONE;
  2251. source->Offset = 0.0;
  2252. }
  2253. ALCdevice_Unlock(device);
  2254. done:
  2255. UnlockSourceList(context);
  2256. ALCcontext_DecRef(context);
  2257. }
  2258. AL_API ALvoid AL_APIENTRY alSourceRewind(ALuint source)
  2259. {
  2260. alSourceRewindv(1, &source);
  2261. }
  2262. AL_API ALvoid AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources)
  2263. {
  2264. ALCcontext *context;
  2265. ALCdevice *device;
  2266. ALsource *source;
  2267. ALvoice *voice;
  2268. ALsizei i;
  2269. context = GetContextRef();
  2270. if(!context) return;
  2271. LockSourceList(context);
  2272. if(!(n >= 0))
  2273. SETERR_GOTO(context, AL_INVALID_VALUE, done, "Rewinding %d sources", n);
  2274. for(i = 0;i < n;i++)
  2275. {
  2276. if(!LookupSource(context, sources[i]))
  2277. SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid source ID %u", sources[i]);
  2278. }
  2279. device = context->Device;
  2280. ALCdevice_Lock(device);
  2281. for(i = 0;i < n;i++)
  2282. {
  2283. source = LookupSource(context, sources[i]);
  2284. if((voice=GetSourceVoice(source, context)) != NULL)
  2285. {
  2286. ATOMIC_STORE(&voice->Source, NULL, almemory_order_relaxed);
  2287. ATOMIC_STORE(&voice->Playing, false, almemory_order_release);
  2288. voice = NULL;
  2289. }
  2290. if(GetSourceState(source, voice) != AL_INITIAL)
  2291. {
  2292. source->state = AL_INITIAL;
  2293. SendStateChangeEvent(context, source->id, AL_INITIAL);
  2294. }
  2295. source->OffsetType = AL_NONE;
  2296. source->Offset = 0.0;
  2297. }
  2298. ALCdevice_Unlock(device);
  2299. done:
  2300. UnlockSourceList(context);
  2301. ALCcontext_DecRef(context);
  2302. }
  2303. AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALuint *buffers)
  2304. {
  2305. ALCdevice *device;
  2306. ALCcontext *context;
  2307. ALsource *source;
  2308. ALsizei i;
  2309. ALbufferlistitem *BufferListStart;
  2310. ALbufferlistitem *BufferList;
  2311. ALbuffer *BufferFmt = NULL;
  2312. if(nb == 0)
  2313. return;
  2314. context = GetContextRef();
  2315. if(!context) return;
  2316. device = context->Device;
  2317. LockSourceList(context);
  2318. if(!(nb >= 0))
  2319. SETERR_GOTO(context, AL_INVALID_VALUE, done, "Queueing %d buffers", nb);
  2320. if((source=LookupSource(context, src)) == NULL)
  2321. SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid source ID %u", src);
  2322. if(source->SourceType == AL_STATIC)
  2323. {
  2324. /* Can't queue on a Static Source */
  2325. SETERR_GOTO(context, AL_INVALID_OPERATION, done, "Queueing onto static source %u", src);
  2326. }
  2327. /* Check for a valid Buffer, for its frequency and format */
  2328. BufferList = source->queue;
  2329. while(BufferList)
  2330. {
  2331. for(i = 0;i < BufferList->num_buffers;i++)
  2332. {
  2333. if((BufferFmt=BufferList->buffers[i]) != NULL)
  2334. break;
  2335. }
  2336. if(BufferFmt) break;
  2337. BufferList = ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed);
  2338. }
  2339. LockBufferList(device);
  2340. BufferListStart = NULL;
  2341. BufferList = NULL;
  2342. for(i = 0;i < nb;i++)
  2343. {
  2344. ALbuffer *buffer = NULL;
  2345. if(buffers[i] && (buffer=LookupBuffer(device, buffers[i])) == NULL)
  2346. SETERR_GOTO(context, AL_INVALID_NAME, buffer_error, "Queueing invalid buffer ID %u",
  2347. buffers[i]);
  2348. if(!BufferListStart)
  2349. {
  2350. BufferListStart = al_calloc(DEF_ALIGN,
  2351. FAM_SIZE(ALbufferlistitem, buffers, 1));
  2352. BufferList = BufferListStart;
  2353. }
  2354. else
  2355. {
  2356. ALbufferlistitem *item = al_calloc(DEF_ALIGN,
  2357. FAM_SIZE(ALbufferlistitem, buffers, 1));
  2358. ATOMIC_STORE(&BufferList->next, item, almemory_order_relaxed);
  2359. BufferList = item;
  2360. }
  2361. ATOMIC_INIT(&BufferList->next, NULL);
  2362. BufferList->max_samples = buffer ? buffer->SampleLen : 0;
  2363. BufferList->num_buffers = 1;
  2364. BufferList->buffers[0] = buffer;
  2365. if(!buffer) continue;
  2366. IncrementRef(&buffer->ref);
  2367. if(buffer->MappedAccess != 0 && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT))
  2368. SETERR_GOTO(context, AL_INVALID_OPERATION, buffer_error,
  2369. "Queueing non-persistently mapped buffer %u", buffer->id);
  2370. if(BufferFmt == NULL)
  2371. BufferFmt = buffer;
  2372. else if(BufferFmt->Frequency != buffer->Frequency ||
  2373. BufferFmt->FmtChannels != buffer->FmtChannels ||
  2374. BufferFmt->OriginalType != buffer->OriginalType)
  2375. {
  2376. alSetError(context, AL_INVALID_OPERATION, "Queueing buffer with mismatched format");
  2377. buffer_error:
  2378. /* A buffer failed (invalid ID or format), so unlock and release
  2379. * each buffer we had. */
  2380. while(BufferListStart)
  2381. {
  2382. ALbufferlistitem *next = ATOMIC_LOAD(&BufferListStart->next,
  2383. almemory_order_relaxed);
  2384. for(i = 0;i < BufferListStart->num_buffers;i++)
  2385. {
  2386. if((buffer=BufferListStart->buffers[i]) != NULL)
  2387. DecrementRef(&buffer->ref);
  2388. }
  2389. al_free(BufferListStart);
  2390. BufferListStart = next;
  2391. }
  2392. UnlockBufferList(device);
  2393. goto done;
  2394. }
  2395. }
  2396. /* All buffers good. */
  2397. UnlockBufferList(device);
  2398. /* Source is now streaming */
  2399. source->SourceType = AL_STREAMING;
  2400. if(!(BufferList=source->queue))
  2401. source->queue = BufferListStart;
  2402. else
  2403. {
  2404. ALbufferlistitem *next;
  2405. while((next=ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed)) != NULL)
  2406. BufferList = next;
  2407. ATOMIC_STORE(&BufferList->next, BufferListStart, almemory_order_release);
  2408. }
  2409. done:
  2410. UnlockSourceList(context);
  2411. ALCcontext_DecRef(context);
  2412. }
  2413. AL_API void AL_APIENTRY alSourceQueueBufferLayersSOFT(ALuint src, ALsizei nb, const ALuint *buffers)
  2414. {
  2415. ALCdevice *device;
  2416. ALCcontext *context;
  2417. ALbufferlistitem *BufferListStart;
  2418. ALbufferlistitem *BufferList;
  2419. ALbuffer *BufferFmt = NULL;
  2420. ALsource *source;
  2421. ALsizei i;
  2422. if(nb == 0)
  2423. return;
  2424. context = GetContextRef();
  2425. if(!context) return;
  2426. device = context->Device;
  2427. LockSourceList(context);
  2428. if(!(nb >= 0 && nb < 16))
  2429. SETERR_GOTO(context, AL_INVALID_VALUE, done, "Queueing %d buffer layers", nb);
  2430. if((source=LookupSource(context, src)) == NULL)
  2431. SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid source ID %u", src);
  2432. if(source->SourceType == AL_STATIC)
  2433. {
  2434. /* Can't queue on a Static Source */
  2435. SETERR_GOTO(context, AL_INVALID_OPERATION, done, "Queueing onto static source %u", src);
  2436. }
  2437. /* Check for a valid Buffer, for its frequency and format */
  2438. BufferList = source->queue;
  2439. while(BufferList)
  2440. {
  2441. for(i = 0;i < BufferList->num_buffers;i++)
  2442. {
  2443. if((BufferFmt=BufferList->buffers[i]) != NULL)
  2444. break;
  2445. }
  2446. if(BufferFmt) break;
  2447. BufferList = ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed);
  2448. }
  2449. LockBufferList(device);
  2450. BufferListStart = al_calloc(DEF_ALIGN, FAM_SIZE(ALbufferlistitem, buffers, nb));
  2451. BufferList = BufferListStart;
  2452. ATOMIC_INIT(&BufferList->next, NULL);
  2453. BufferList->max_samples = 0;
  2454. BufferList->num_buffers = 0;
  2455. for(i = 0;i < nb;i++)
  2456. {
  2457. ALbuffer *buffer = NULL;
  2458. if(buffers[i] && (buffer=LookupBuffer(device, buffers[i])) == NULL)
  2459. SETERR_GOTO(context, AL_INVALID_NAME, buffer_error, "Queueing invalid buffer ID %u",
  2460. buffers[i]);
  2461. BufferList->buffers[BufferList->num_buffers++] = buffer;
  2462. if(!buffer) continue;
  2463. IncrementRef(&buffer->ref);
  2464. BufferList->max_samples = maxi(BufferList->max_samples, buffer->SampleLen);
  2465. if(buffer->MappedAccess != 0 && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT))
  2466. SETERR_GOTO(context, AL_INVALID_OPERATION, buffer_error,
  2467. "Queueing non-persistently mapped buffer %u", buffer->id);
  2468. if(BufferFmt == NULL)
  2469. BufferFmt = buffer;
  2470. else if(BufferFmt->Frequency != buffer->Frequency ||
  2471. BufferFmt->FmtChannels != buffer->FmtChannels ||
  2472. BufferFmt->OriginalType != buffer->OriginalType)
  2473. {
  2474. alSetError(context, AL_INVALID_OPERATION, "Queueing buffer with mismatched format");
  2475. buffer_error:
  2476. /* A buffer failed (invalid ID or format), so unlock and release
  2477. * each buffer we had. */
  2478. while(BufferListStart)
  2479. {
  2480. ALbufferlistitem *next = ATOMIC_LOAD(&BufferListStart->next,
  2481. almemory_order_relaxed);
  2482. for(i = 0;i < BufferListStart->num_buffers;i++)
  2483. {
  2484. if((buffer=BufferListStart->buffers[i]) != NULL)
  2485. DecrementRef(&buffer->ref);
  2486. }
  2487. al_free(BufferListStart);
  2488. BufferListStart = next;
  2489. }
  2490. UnlockBufferList(device);
  2491. goto done;
  2492. }
  2493. }
  2494. /* All buffers good. */
  2495. UnlockBufferList(device);
  2496. /* Source is now streaming */
  2497. source->SourceType = AL_STREAMING;
  2498. if(!(BufferList=source->queue))
  2499. source->queue = BufferListStart;
  2500. else
  2501. {
  2502. ALbufferlistitem *next;
  2503. while((next=ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed)) != NULL)
  2504. BufferList = next;
  2505. ATOMIC_STORE(&BufferList->next, BufferListStart, almemory_order_release);
  2506. }
  2507. done:
  2508. UnlockSourceList(context);
  2509. ALCcontext_DecRef(context);
  2510. }
  2511. AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint *buffers)
  2512. {
  2513. ALCcontext *context;
  2514. ALsource *source;
  2515. ALbufferlistitem *BufferList;
  2516. ALbufferlistitem *Current;
  2517. ALvoice *voice;
  2518. ALsizei i;
  2519. context = GetContextRef();
  2520. if(!context) return;
  2521. LockSourceList(context);
  2522. if(!(nb >= 0))
  2523. SETERR_GOTO(context, AL_INVALID_VALUE, done, "Unqueueing %d buffers", nb);
  2524. if((source=LookupSource(context, src)) == NULL)
  2525. SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid source ID %u", src);
  2526. /* Nothing to unqueue. */
  2527. if(nb == 0) goto done;
  2528. if(source->Looping)
  2529. SETERR_GOTO(context, AL_INVALID_VALUE, done, "Unqueueing from looping source %u", src);
  2530. if(source->SourceType != AL_STREAMING)
  2531. SETERR_GOTO(context, AL_INVALID_VALUE, done, "Unqueueing from a non-streaming source %u",
  2532. src);
  2533. /* Make sure enough buffers have been processed to unqueue. */
  2534. BufferList = source->queue;
  2535. Current = NULL;
  2536. if((voice=GetSourceVoice(source, context)) != NULL)
  2537. Current = ATOMIC_LOAD(&voice->current_buffer, almemory_order_relaxed);
  2538. else if(source->state == AL_INITIAL)
  2539. Current = BufferList;
  2540. if(BufferList == Current)
  2541. SETERR_GOTO(context, AL_INVALID_VALUE, done, "Unqueueing pending buffers");
  2542. i = BufferList->num_buffers;
  2543. while(i < nb)
  2544. {
  2545. /* If the next bufferlist to check is NULL or is the current one, it's
  2546. * trying to unqueue pending buffers.
  2547. */
  2548. ALbufferlistitem *next = ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed);
  2549. if(!next || next == Current)
  2550. SETERR_GOTO(context, AL_INVALID_VALUE, done, "Unqueueing pending buffers");
  2551. BufferList = next;
  2552. i += BufferList->num_buffers;
  2553. }
  2554. while(nb > 0)
  2555. {
  2556. ALbufferlistitem *head = source->queue;
  2557. ALbufferlistitem *next = ATOMIC_LOAD(&head->next, almemory_order_relaxed);
  2558. for(i = 0;i < head->num_buffers && nb > 0;i++,nb--)
  2559. {
  2560. ALbuffer *buffer = head->buffers[i];
  2561. if(!buffer)
  2562. *(buffers++) = 0;
  2563. else
  2564. {
  2565. *(buffers++) = buffer->id;
  2566. DecrementRef(&buffer->ref);
  2567. }
  2568. }
  2569. if(i < head->num_buffers)
  2570. {
  2571. /* This head has some buffers left over, so move them to the front
  2572. * and update the sample and buffer count.
  2573. */
  2574. ALsizei max_length = 0;
  2575. ALsizei j = 0;
  2576. while(i < head->num_buffers)
  2577. {
  2578. ALbuffer *buffer = head->buffers[i++];
  2579. if(buffer) max_length = maxi(max_length, buffer->SampleLen);
  2580. head->buffers[j++] = buffer;
  2581. }
  2582. head->max_samples = max_length;
  2583. head->num_buffers = j;
  2584. break;
  2585. }
  2586. /* Otherwise, free this item and set the source queue head to the next
  2587. * one.
  2588. */
  2589. al_free(head);
  2590. source->queue = next;
  2591. }
  2592. done:
  2593. UnlockSourceList(context);
  2594. ALCcontext_DecRef(context);
  2595. }
  2596. static void InitSourceParams(ALsource *Source, ALsizei num_sends)
  2597. {
  2598. ALsizei i;
  2599. Source->InnerAngle = 360.0f;
  2600. Source->OuterAngle = 360.0f;
  2601. Source->Pitch = 1.0f;
  2602. Source->Position[0] = 0.0f;
  2603. Source->Position[1] = 0.0f;
  2604. Source->Position[2] = 0.0f;
  2605. Source->Velocity[0] = 0.0f;
  2606. Source->Velocity[1] = 0.0f;
  2607. Source->Velocity[2] = 0.0f;
  2608. Source->Direction[0] = 0.0f;
  2609. Source->Direction[1] = 0.0f;
  2610. Source->Direction[2] = 0.0f;
  2611. Source->Orientation[0][0] = 0.0f;
  2612. Source->Orientation[0][1] = 0.0f;
  2613. Source->Orientation[0][2] = -1.0f;
  2614. Source->Orientation[1][0] = 0.0f;
  2615. Source->Orientation[1][1] = 1.0f;
  2616. Source->Orientation[1][2] = 0.0f;
  2617. Source->RefDistance = 1.0f;
  2618. Source->MaxDistance = FLT_MAX;
  2619. Source->RolloffFactor = 1.0f;
  2620. Source->Gain = 1.0f;
  2621. Source->MinGain = 0.0f;
  2622. Source->MaxGain = 1.0f;
  2623. Source->OuterGain = 0.0f;
  2624. Source->OuterGainHF = 1.0f;
  2625. Source->DryGainHFAuto = AL_TRUE;
  2626. Source->WetGainAuto = AL_TRUE;
  2627. Source->WetGainHFAuto = AL_TRUE;
  2628. Source->AirAbsorptionFactor = 0.0f;
  2629. Source->RoomRolloffFactor = 0.0f;
  2630. Source->DopplerFactor = 1.0f;
  2631. Source->HeadRelative = AL_FALSE;
  2632. Source->Looping = AL_FALSE;
  2633. Source->DistanceModel = DefaultDistanceModel;
  2634. Source->Resampler = ResamplerDefault;
  2635. Source->DirectChannels = AL_FALSE;
  2636. Source->Spatialize = SpatializeAuto;
  2637. Source->StereoPan[0] = DEG2RAD( 30.0f);
  2638. Source->StereoPan[1] = DEG2RAD(-30.0f);
  2639. Source->Radius = 0.0f;
  2640. Source->Direct.Gain = 1.0f;
  2641. Source->Direct.GainHF = 1.0f;
  2642. Source->Direct.HFReference = LOWPASSFREQREF;
  2643. Source->Direct.GainLF = 1.0f;
  2644. Source->Direct.LFReference = HIGHPASSFREQREF;
  2645. Source->Send = al_calloc(16, num_sends*sizeof(Source->Send[0]));
  2646. for(i = 0;i < num_sends;i++)
  2647. {
  2648. Source->Send[i].Slot = NULL;
  2649. Source->Send[i].Gain = 1.0f;
  2650. Source->Send[i].GainHF = 1.0f;
  2651. Source->Send[i].HFReference = LOWPASSFREQREF;
  2652. Source->Send[i].GainLF = 1.0f;
  2653. Source->Send[i].LFReference = HIGHPASSFREQREF;
  2654. }
  2655. Source->Offset = 0.0;
  2656. Source->OffsetType = AL_NONE;
  2657. Source->SourceType = AL_UNDETERMINED;
  2658. Source->state = AL_INITIAL;
  2659. Source->queue = NULL;
  2660. /* No way to do an 'init' here, so just test+set with relaxed ordering and
  2661. * ignore the test.
  2662. */
  2663. ATOMIC_FLAG_TEST_AND_SET(&Source->PropsClean, almemory_order_relaxed);
  2664. Source->VoiceIdx = -1;
  2665. }
  2666. static void DeinitSource(ALsource *source, ALsizei num_sends)
  2667. {
  2668. ALbufferlistitem *BufferList;
  2669. ALsizei i;
  2670. BufferList = source->queue;
  2671. while(BufferList != NULL)
  2672. {
  2673. ALbufferlistitem *next = ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed);
  2674. for(i = 0;i < BufferList->num_buffers;i++)
  2675. {
  2676. if(BufferList->buffers[i] != NULL)
  2677. DecrementRef(&BufferList->buffers[i]->ref);
  2678. }
  2679. al_free(BufferList);
  2680. BufferList = next;
  2681. }
  2682. source->queue = NULL;
  2683. if(source->Send)
  2684. {
  2685. for(i = 0;i < num_sends;i++)
  2686. {
  2687. if(source->Send[i].Slot)
  2688. DecrementRef(&source->Send[i].Slot->ref);
  2689. source->Send[i].Slot = NULL;
  2690. }
  2691. al_free(source->Send);
  2692. source->Send = NULL;
  2693. }
  2694. }
  2695. static void UpdateSourceProps(ALsource *source, ALvoice *voice, ALsizei num_sends, ALCcontext *context)
  2696. {
  2697. struct ALvoiceProps *props;
  2698. ALsizei i;
  2699. /* Get an unused property container, or allocate a new one as needed. */
  2700. props = ATOMIC_LOAD(&context->FreeVoiceProps, almemory_order_acquire);
  2701. if(!props)
  2702. props = al_calloc(16, FAM_SIZE(struct ALvoiceProps, Send, num_sends));
  2703. else
  2704. {
  2705. struct ALvoiceProps *next;
  2706. do {
  2707. next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
  2708. } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&context->FreeVoiceProps, &props, next,
  2709. almemory_order_acq_rel, almemory_order_acquire) == 0);
  2710. }
  2711. /* Copy in current property values. */
  2712. props->Pitch = source->Pitch;
  2713. props->Gain = source->Gain;
  2714. props->OuterGain = source->OuterGain;
  2715. props->MinGain = source->MinGain;
  2716. props->MaxGain = source->MaxGain;
  2717. props->InnerAngle = source->InnerAngle;
  2718. props->OuterAngle = source->OuterAngle;
  2719. props->RefDistance = source->RefDistance;
  2720. props->MaxDistance = source->MaxDistance;
  2721. props->RolloffFactor = source->RolloffFactor;
  2722. for(i = 0;i < 3;i++)
  2723. props->Position[i] = source->Position[i];
  2724. for(i = 0;i < 3;i++)
  2725. props->Velocity[i] = source->Velocity[i];
  2726. for(i = 0;i < 3;i++)
  2727. props->Direction[i] = source->Direction[i];
  2728. for(i = 0;i < 2;i++)
  2729. {
  2730. ALsizei j;
  2731. for(j = 0;j < 3;j++)
  2732. props->Orientation[i][j] = source->Orientation[i][j];
  2733. }
  2734. props->HeadRelative = source->HeadRelative;
  2735. props->DistanceModel = source->DistanceModel;
  2736. props->Resampler = source->Resampler;
  2737. props->DirectChannels = source->DirectChannels;
  2738. props->SpatializeMode = source->Spatialize;
  2739. props->DryGainHFAuto = source->DryGainHFAuto;
  2740. props->WetGainAuto = source->WetGainAuto;
  2741. props->WetGainHFAuto = source->WetGainHFAuto;
  2742. props->OuterGainHF = source->OuterGainHF;
  2743. props->AirAbsorptionFactor = source->AirAbsorptionFactor;
  2744. props->RoomRolloffFactor = source->RoomRolloffFactor;
  2745. props->DopplerFactor = source->DopplerFactor;
  2746. props->StereoPan[0] = source->StereoPan[0];
  2747. props->StereoPan[1] = source->StereoPan[1];
  2748. props->Radius = source->Radius;
  2749. props->Direct.Gain = source->Direct.Gain;
  2750. props->Direct.GainHF = source->Direct.GainHF;
  2751. props->Direct.HFReference = source->Direct.HFReference;
  2752. props->Direct.GainLF = source->Direct.GainLF;
  2753. props->Direct.LFReference = source->Direct.LFReference;
  2754. for(i = 0;i < num_sends;i++)
  2755. {
  2756. props->Send[i].Slot = source->Send[i].Slot;
  2757. props->Send[i].Gain = source->Send[i].Gain;
  2758. props->Send[i].GainHF = source->Send[i].GainHF;
  2759. props->Send[i].HFReference = source->Send[i].HFReference;
  2760. props->Send[i].GainLF = source->Send[i].GainLF;
  2761. props->Send[i].LFReference = source->Send[i].LFReference;
  2762. }
  2763. /* Set the new container for updating internal parameters. */
  2764. props = ATOMIC_EXCHANGE_PTR(&voice->Update, props, almemory_order_acq_rel);
  2765. if(props)
  2766. {
  2767. /* If there was an unused update container, put it back in the
  2768. * freelist.
  2769. */
  2770. ATOMIC_REPLACE_HEAD(struct ALvoiceProps*, &context->FreeVoiceProps, props);
  2771. }
  2772. }
  2773. void UpdateAllSourceProps(ALCcontext *context)
  2774. {
  2775. ALsizei num_sends = context->Device->NumAuxSends;
  2776. ALsizei pos;
  2777. for(pos = 0;pos < context->VoiceCount;pos++)
  2778. {
  2779. ALvoice *voice = context->Voices[pos];
  2780. ALsource *source = ATOMIC_LOAD(&voice->Source, almemory_order_acquire);
  2781. if(source && !ATOMIC_FLAG_TEST_AND_SET(&source->PropsClean, almemory_order_acq_rel))
  2782. UpdateSourceProps(source, voice, num_sends, context);
  2783. }
  2784. }
  2785. /* GetSourceSampleOffset
  2786. *
  2787. * Gets the current read offset for the given Source, in 32.32 fixed-point
  2788. * samples. The offset is relative to the start of the queue (not the start of
  2789. * the current buffer).
  2790. */
  2791. static ALint64 GetSourceSampleOffset(ALsource *Source, ALCcontext *context, ALuint64 *clocktime)
  2792. {
  2793. ALCdevice *device = context->Device;
  2794. const ALbufferlistitem *Current;
  2795. ALuint64 readPos;
  2796. ALuint refcount;
  2797. ALvoice *voice;
  2798. do {
  2799. Current = NULL;
  2800. readPos = 0;
  2801. while(((refcount=ATOMIC_LOAD(&device->MixCount, almemory_order_acquire))&1))
  2802. althrd_yield();
  2803. *clocktime = GetDeviceClockTime(device);
  2804. voice = GetSourceVoice(Source, context);
  2805. if(voice)
  2806. {
  2807. Current = ATOMIC_LOAD(&voice->current_buffer, almemory_order_relaxed);
  2808. readPos = (ALuint64)ATOMIC_LOAD(&voice->position, almemory_order_relaxed) << 32;
  2809. readPos |= (ALuint64)ATOMIC_LOAD(&voice->position_fraction, almemory_order_relaxed) <<
  2810. (32-FRACTIONBITS);
  2811. }
  2812. ATOMIC_THREAD_FENCE(almemory_order_acquire);
  2813. } while(refcount != ATOMIC_LOAD(&device->MixCount, almemory_order_relaxed));
  2814. if(voice)
  2815. {
  2816. const ALbufferlistitem *BufferList = Source->queue;
  2817. while(BufferList && BufferList != Current)
  2818. {
  2819. readPos += (ALuint64)BufferList->max_samples << 32;
  2820. BufferList = ATOMIC_LOAD(&CONST_CAST(ALbufferlistitem*,BufferList)->next,
  2821. almemory_order_relaxed);
  2822. }
  2823. readPos = minu64(readPos, U64(0x7fffffffffffffff));
  2824. }
  2825. return (ALint64)readPos;
  2826. }
  2827. /* GetSourceSecOffset
  2828. *
  2829. * Gets the current read offset for the given Source, in seconds. The offset is
  2830. * relative to the start of the queue (not the start of the current buffer).
  2831. */
  2832. static ALdouble GetSourceSecOffset(ALsource *Source, ALCcontext *context, ALuint64 *clocktime)
  2833. {
  2834. ALCdevice *device = context->Device;
  2835. const ALbufferlistitem *Current;
  2836. ALuint64 readPos;
  2837. ALuint refcount;
  2838. ALdouble offset;
  2839. ALvoice *voice;
  2840. do {
  2841. Current = NULL;
  2842. readPos = 0;
  2843. while(((refcount=ATOMIC_LOAD(&device->MixCount, almemory_order_acquire))&1))
  2844. althrd_yield();
  2845. *clocktime = GetDeviceClockTime(device);
  2846. voice = GetSourceVoice(Source, context);
  2847. if(voice)
  2848. {
  2849. Current = ATOMIC_LOAD(&voice->current_buffer, almemory_order_relaxed);
  2850. readPos = (ALuint64)ATOMIC_LOAD(&voice->position, almemory_order_relaxed) <<
  2851. FRACTIONBITS;
  2852. readPos |= ATOMIC_LOAD(&voice->position_fraction, almemory_order_relaxed);
  2853. }
  2854. ATOMIC_THREAD_FENCE(almemory_order_acquire);
  2855. } while(refcount != ATOMIC_LOAD(&device->MixCount, almemory_order_relaxed));
  2856. offset = 0.0;
  2857. if(voice)
  2858. {
  2859. const ALbufferlistitem *BufferList = Source->queue;
  2860. const ALbuffer *BufferFmt = NULL;
  2861. while(BufferList && BufferList != Current)
  2862. {
  2863. ALsizei i = 0;
  2864. while(!BufferFmt && i < BufferList->num_buffers)
  2865. BufferFmt = BufferList->buffers[i++];
  2866. readPos += (ALuint64)BufferList->max_samples << FRACTIONBITS;
  2867. BufferList = ATOMIC_LOAD(&CONST_CAST(ALbufferlistitem*,BufferList)->next,
  2868. almemory_order_relaxed);
  2869. }
  2870. while(BufferList && !BufferFmt)
  2871. {
  2872. ALsizei i = 0;
  2873. while(!BufferFmt && i < BufferList->num_buffers)
  2874. BufferFmt = BufferList->buffers[i++];
  2875. BufferList = ATOMIC_LOAD(&CONST_CAST(ALbufferlistitem*,BufferList)->next,
  2876. almemory_order_relaxed);
  2877. }
  2878. assert(BufferFmt != NULL);
  2879. offset = (ALdouble)readPos / (ALdouble)FRACTIONONE /
  2880. (ALdouble)BufferFmt->Frequency;
  2881. }
  2882. return offset;
  2883. }
  2884. /* GetSourceOffset
  2885. *
  2886. * Gets the current read offset for the given Source, in the appropriate format
  2887. * (Bytes, Samples or Seconds). The offset is relative to the start of the
  2888. * queue (not the start of the current buffer).
  2889. */
  2890. static ALdouble GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context)
  2891. {
  2892. ALCdevice *device = context->Device;
  2893. const ALbufferlistitem *Current;
  2894. ALuint readPos;
  2895. ALsizei readPosFrac;
  2896. ALuint refcount;
  2897. ALdouble offset;
  2898. ALvoice *voice;
  2899. do {
  2900. Current = NULL;
  2901. readPos = readPosFrac = 0;
  2902. while(((refcount=ATOMIC_LOAD(&device->MixCount, almemory_order_acquire))&1))
  2903. althrd_yield();
  2904. voice = GetSourceVoice(Source, context);
  2905. if(voice)
  2906. {
  2907. Current = ATOMIC_LOAD(&voice->current_buffer, almemory_order_relaxed);
  2908. readPos = ATOMIC_LOAD(&voice->position, almemory_order_relaxed);
  2909. readPosFrac = ATOMIC_LOAD(&voice->position_fraction, almemory_order_relaxed);
  2910. }
  2911. ATOMIC_THREAD_FENCE(almemory_order_acquire);
  2912. } while(refcount != ATOMIC_LOAD(&device->MixCount, almemory_order_relaxed));
  2913. offset = 0.0;
  2914. if(voice)
  2915. {
  2916. const ALbufferlistitem *BufferList = Source->queue;
  2917. const ALbuffer *BufferFmt = NULL;
  2918. ALboolean readFin = AL_FALSE;
  2919. ALuint totalBufferLen = 0;
  2920. while(BufferList != NULL)
  2921. {
  2922. ALsizei i = 0;
  2923. while(!BufferFmt && i < BufferList->num_buffers)
  2924. BufferFmt = BufferList->buffers[i++];
  2925. readFin |= (BufferList == Current);
  2926. totalBufferLen += BufferList->max_samples;
  2927. if(!readFin) readPos += BufferList->max_samples;
  2928. BufferList = ATOMIC_LOAD(&CONST_CAST(ALbufferlistitem*,BufferList)->next,
  2929. almemory_order_relaxed);
  2930. }
  2931. assert(BufferFmt != NULL);
  2932. if(Source->Looping)
  2933. readPos %= totalBufferLen;
  2934. else
  2935. {
  2936. /* Wrap back to 0 */
  2937. if(readPos >= totalBufferLen)
  2938. readPos = readPosFrac = 0;
  2939. }
  2940. offset = 0.0;
  2941. switch(name)
  2942. {
  2943. case AL_SEC_OFFSET:
  2944. offset = (readPos + (ALdouble)readPosFrac/FRACTIONONE) / BufferFmt->Frequency;
  2945. break;
  2946. case AL_SAMPLE_OFFSET:
  2947. offset = readPos + (ALdouble)readPosFrac/FRACTIONONE;
  2948. break;
  2949. case AL_BYTE_OFFSET:
  2950. if(BufferFmt->OriginalType == UserFmtIMA4)
  2951. {
  2952. ALsizei align = (BufferFmt->OriginalAlign-1)/2 + 4;
  2953. ALuint BlockSize = align * ChannelsFromFmt(BufferFmt->FmtChannels);
  2954. ALuint FrameBlockSize = BufferFmt->OriginalAlign;
  2955. /* Round down to nearest ADPCM block */
  2956. offset = (ALdouble)(readPos / FrameBlockSize * BlockSize);
  2957. }
  2958. else if(BufferFmt->OriginalType == UserFmtMSADPCM)
  2959. {
  2960. ALsizei align = (BufferFmt->OriginalAlign-2)/2 + 7;
  2961. ALuint BlockSize = align * ChannelsFromFmt(BufferFmt->FmtChannels);
  2962. ALuint FrameBlockSize = BufferFmt->OriginalAlign;
  2963. /* Round down to nearest ADPCM block */
  2964. offset = (ALdouble)(readPos / FrameBlockSize * BlockSize);
  2965. }
  2966. else
  2967. {
  2968. ALuint FrameSize = FrameSizeFromFmt(BufferFmt->FmtChannels,
  2969. BufferFmt->FmtType);
  2970. offset = (ALdouble)(readPos * FrameSize);
  2971. }
  2972. break;
  2973. }
  2974. }
  2975. return offset;
  2976. }
  2977. /* ApplyOffset
  2978. *
  2979. * Apply the stored playback offset to the Source. This function will update
  2980. * the number of buffers "played" given the stored offset.
  2981. */
  2982. static ALboolean ApplyOffset(ALsource *Source, ALvoice *voice)
  2983. {
  2984. ALbufferlistitem *BufferList;
  2985. ALuint totalBufferLen;
  2986. ALuint offset = 0;
  2987. ALsizei frac = 0;
  2988. /* Get sample frame offset */
  2989. if(!GetSampleOffset(Source, &offset, &frac))
  2990. return AL_FALSE;
  2991. totalBufferLen = 0;
  2992. BufferList = Source->queue;
  2993. while(BufferList && totalBufferLen <= offset)
  2994. {
  2995. if((ALuint)BufferList->max_samples > offset-totalBufferLen)
  2996. {
  2997. /* Offset is in this buffer */
  2998. ATOMIC_STORE(&voice->position, offset - totalBufferLen, almemory_order_relaxed);
  2999. ATOMIC_STORE(&voice->position_fraction, frac, almemory_order_relaxed);
  3000. ATOMIC_STORE(&voice->current_buffer, BufferList, almemory_order_release);
  3001. return AL_TRUE;
  3002. }
  3003. totalBufferLen += BufferList->max_samples;
  3004. BufferList = ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed);
  3005. }
  3006. /* Offset is out of range of the queue */
  3007. return AL_FALSE;
  3008. }
  3009. /* GetSampleOffset
  3010. *
  3011. * Retrieves the sample offset into the Source's queue (from the Sample, Byte
  3012. * or Second offset supplied by the application). This takes into account the
  3013. * fact that the buffer format may have been modifed since.
  3014. */
  3015. static ALboolean GetSampleOffset(ALsource *Source, ALuint *offset, ALsizei *frac)
  3016. {
  3017. const ALbuffer *BufferFmt = NULL;
  3018. const ALbufferlistitem *BufferList;
  3019. ALdouble dbloff, dblfrac;
  3020. /* Find the first valid Buffer in the Queue */
  3021. BufferList = Source->queue;
  3022. while(BufferList)
  3023. {
  3024. ALsizei i;
  3025. for(i = 0;i < BufferList->num_buffers && !BufferFmt;i++)
  3026. BufferFmt = BufferList->buffers[i];
  3027. if(BufferFmt) break;
  3028. BufferList = ATOMIC_LOAD(&CONST_CAST(ALbufferlistitem*,BufferList)->next,
  3029. almemory_order_relaxed);
  3030. }
  3031. if(!BufferFmt)
  3032. {
  3033. Source->OffsetType = AL_NONE;
  3034. Source->Offset = 0.0;
  3035. return AL_FALSE;
  3036. }
  3037. switch(Source->OffsetType)
  3038. {
  3039. case AL_BYTE_OFFSET:
  3040. /* Determine the ByteOffset (and ensure it is block aligned) */
  3041. *offset = (ALuint)Source->Offset;
  3042. if(BufferFmt->OriginalType == UserFmtIMA4)
  3043. {
  3044. ALsizei align = (BufferFmt->OriginalAlign-1)/2 + 4;
  3045. *offset /= align * ChannelsFromFmt(BufferFmt->FmtChannels);
  3046. *offset *= BufferFmt->OriginalAlign;
  3047. }
  3048. else if(BufferFmt->OriginalType == UserFmtMSADPCM)
  3049. {
  3050. ALsizei align = (BufferFmt->OriginalAlign-2)/2 + 7;
  3051. *offset /= align * ChannelsFromFmt(BufferFmt->FmtChannels);
  3052. *offset *= BufferFmt->OriginalAlign;
  3053. }
  3054. else
  3055. *offset /= FrameSizeFromFmt(BufferFmt->FmtChannels, BufferFmt->FmtType);
  3056. *frac = 0;
  3057. break;
  3058. case AL_SAMPLE_OFFSET:
  3059. dblfrac = modf(Source->Offset, &dbloff);
  3060. *offset = (ALuint)mind(dbloff, UINT_MAX);
  3061. *frac = (ALsizei)mind(dblfrac*FRACTIONONE, FRACTIONONE-1.0);
  3062. break;
  3063. case AL_SEC_OFFSET:
  3064. dblfrac = modf(Source->Offset*BufferFmt->Frequency, &dbloff);
  3065. *offset = (ALuint)mind(dbloff, UINT_MAX);
  3066. *frac = (ALsizei)mind(dblfrac*FRACTIONONE, FRACTIONONE-1.0);
  3067. break;
  3068. }
  3069. Source->OffsetType = AL_NONE;
  3070. Source->Offset = 0.0;
  3071. return AL_TRUE;
  3072. }
  3073. static ALsource *AllocSource(ALCcontext *context)
  3074. {
  3075. ALCdevice *device = context->Device;
  3076. SourceSubList *sublist, *subend;
  3077. ALsource *source = NULL;
  3078. ALsizei lidx = 0;
  3079. ALsizei slidx;
  3080. almtx_lock(&context->SourceLock);
  3081. if(context->NumSources >= device->SourcesMax)
  3082. {
  3083. almtx_unlock(&context->SourceLock);
  3084. alSetError(context, AL_OUT_OF_MEMORY, "Exceeding %u source limit", device->SourcesMax);
  3085. return NULL;
  3086. }
  3087. sublist = VECTOR_BEGIN(context->SourceList);
  3088. subend = VECTOR_END(context->SourceList);
  3089. for(;sublist != subend;++sublist)
  3090. {
  3091. if(sublist->FreeMask)
  3092. {
  3093. slidx = CTZ64(sublist->FreeMask);
  3094. source = sublist->Sources + slidx;
  3095. break;
  3096. }
  3097. ++lidx;
  3098. }
  3099. if(UNLIKELY(!source))
  3100. {
  3101. const SourceSubList empty_sublist = { 0, NULL };
  3102. /* Don't allocate so many list entries that the 32-bit ID could
  3103. * overflow...
  3104. */
  3105. if(UNLIKELY(VECTOR_SIZE(context->SourceList) >= 1<<25))
  3106. {
  3107. almtx_unlock(&device->BufferLock);
  3108. alSetError(context, AL_OUT_OF_MEMORY, "Too many sources allocated");
  3109. return NULL;
  3110. }
  3111. lidx = (ALsizei)VECTOR_SIZE(context->SourceList);
  3112. VECTOR_PUSH_BACK(context->SourceList, empty_sublist);
  3113. sublist = &VECTOR_BACK(context->SourceList);
  3114. sublist->FreeMask = ~U64(0);
  3115. sublist->Sources = al_calloc(16, sizeof(ALsource)*64);
  3116. if(UNLIKELY(!sublist->Sources))
  3117. {
  3118. VECTOR_POP_BACK(context->SourceList);
  3119. almtx_unlock(&context->SourceLock);
  3120. alSetError(context, AL_OUT_OF_MEMORY, "Failed to allocate source batch");
  3121. return NULL;
  3122. }
  3123. slidx = 0;
  3124. source = sublist->Sources + slidx;
  3125. }
  3126. memset(source, 0, sizeof(*source));
  3127. InitSourceParams(source, device->NumAuxSends);
  3128. /* Add 1 to avoid source ID 0. */
  3129. source->id = ((lidx<<6) | slidx) + 1;
  3130. context->NumSources++;
  3131. sublist->FreeMask &= ~(U64(1)<<slidx);
  3132. almtx_unlock(&context->SourceLock);
  3133. return source;
  3134. }
  3135. static void FreeSource(ALCcontext *context, ALsource *source)
  3136. {
  3137. ALCdevice *device = context->Device;
  3138. ALuint id = source->id - 1;
  3139. ALsizei lidx = id >> 6;
  3140. ALsizei slidx = id & 0x3f;
  3141. ALvoice *voice;
  3142. ALCdevice_Lock(device);
  3143. if((voice=GetSourceVoice(source, context)) != NULL)
  3144. {
  3145. ATOMIC_STORE(&voice->Source, NULL, almemory_order_relaxed);
  3146. ATOMIC_STORE(&voice->Playing, false, almemory_order_release);
  3147. }
  3148. ALCdevice_Unlock(device);
  3149. DeinitSource(source, device->NumAuxSends);
  3150. memset(source, 0, sizeof(*source));
  3151. VECTOR_ELEM(context->SourceList, lidx).FreeMask |= U64(1) << slidx;
  3152. context->NumSources--;
  3153. }
  3154. /* ReleaseALSources
  3155. *
  3156. * Destroys all sources in the source map.
  3157. */
  3158. ALvoid ReleaseALSources(ALCcontext *context)
  3159. {
  3160. ALCdevice *device = context->Device;
  3161. SourceSubList *sublist = VECTOR_BEGIN(context->SourceList);
  3162. SourceSubList *subend = VECTOR_END(context->SourceList);
  3163. size_t leftover = 0;
  3164. for(;sublist != subend;++sublist)
  3165. {
  3166. ALuint64 usemask = ~sublist->FreeMask;
  3167. while(usemask)
  3168. {
  3169. ALsizei idx = CTZ64(usemask);
  3170. ALsource *source = sublist->Sources + idx;
  3171. DeinitSource(source, device->NumAuxSends);
  3172. memset(source, 0, sizeof(*source));
  3173. ++leftover;
  3174. usemask &= ~(U64(1) << idx);
  3175. }
  3176. sublist->FreeMask = ~usemask;
  3177. }
  3178. if(leftover > 0)
  3179. WARN("(%p) Deleted "SZFMT" Source%s\n", device, leftover, (leftover==1)?"":"s");
  3180. }