alSource.c 114 KB

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