alSource.c 109 KB

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