source.cpp 109 KB

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