ALu.c 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127
  1. /**
  2. * OpenAL cross platform audio library
  3. * Copyright (C) 1999-2007 by authors.
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Library General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Library General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Library General Public
  15. * License along with this library; if not, write to the
  16. * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  17. * Boston, MA 02111-1307, USA.
  18. * Or go to http://www.gnu.org/copyleft/lgpl.html
  19. */
  20. #include "config.h"
  21. #include <math.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <ctype.h>
  25. #include <assert.h>
  26. #include "alMain.h"
  27. #include "AL/al.h"
  28. #include "AL/alc.h"
  29. #include "alSource.h"
  30. #include "alBuffer.h"
  31. #include "alListener.h"
  32. #include "alAuxEffectSlot.h"
  33. #include "alu.h"
  34. #include "bs2b.h"
  35. struct ChanMap {
  36. enum Channel channel;
  37. ALfloat angle;
  38. };
  39. /* Cone scalar */
  40. ALfloat ConeScale = 0.5f;
  41. /* Localized Z scalar for mono sources */
  42. ALfloat ZScale = 1.0f;
  43. static __inline ALvoid aluMatrixVector(ALfloat *vector,ALfloat w,ALfloat matrix[4][4])
  44. {
  45. ALfloat temp[4] = {
  46. vector[0], vector[1], vector[2], w
  47. };
  48. vector[0] = temp[0]*matrix[0][0] + temp[1]*matrix[1][0] + temp[2]*matrix[2][0] + temp[3]*matrix[3][0];
  49. vector[1] = temp[0]*matrix[0][1] + temp[1]*matrix[1][1] + temp[2]*matrix[2][1] + temp[3]*matrix[3][1];
  50. vector[2] = temp[0]*matrix[0][2] + temp[1]*matrix[1][2] + temp[2]*matrix[2][2] + temp[3]*matrix[3][2];
  51. }
  52. ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
  53. {
  54. static const struct ChanMap MonoMap[1] = { { FRONT_CENTER, 0.0f } };
  55. static const struct ChanMap StereoMap[2] = {
  56. { FRONT_LEFT, -30.0f * F_PI/180.0f },
  57. { FRONT_RIGHT, 30.0f * F_PI/180.0f }
  58. };
  59. static const struct ChanMap RearMap[2] = {
  60. { BACK_LEFT, -150.0f * F_PI/180.0f },
  61. { BACK_RIGHT, 150.0f * F_PI/180.0f }
  62. };
  63. static const struct ChanMap QuadMap[4] = {
  64. { FRONT_LEFT, -45.0f * F_PI/180.0f },
  65. { FRONT_RIGHT, 45.0f * F_PI/180.0f },
  66. { BACK_LEFT, -135.0f * F_PI/180.0f },
  67. { BACK_RIGHT, 135.0f * F_PI/180.0f }
  68. };
  69. static const struct ChanMap X51Map[6] = {
  70. { FRONT_LEFT, -30.0f * F_PI/180.0f },
  71. { FRONT_RIGHT, 30.0f * F_PI/180.0f },
  72. { FRONT_CENTER, 0.0f * F_PI/180.0f },
  73. { LFE, 0.0f },
  74. { BACK_LEFT, -110.0f * F_PI/180.0f },
  75. { BACK_RIGHT, 110.0f * F_PI/180.0f }
  76. };
  77. static const struct ChanMap X61Map[7] = {
  78. { FRONT_LEFT, -30.0f * F_PI/180.0f },
  79. { FRONT_RIGHT, 30.0f * F_PI/180.0f },
  80. { FRONT_CENTER, 0.0f * F_PI/180.0f },
  81. { LFE, 0.0f },
  82. { BACK_CENTER, 180.0f * F_PI/180.0f },
  83. { SIDE_LEFT, -90.0f * F_PI/180.0f },
  84. { SIDE_RIGHT, 90.0f * F_PI/180.0f }
  85. };
  86. static const struct ChanMap X71Map[8] = {
  87. { FRONT_LEFT, -30.0f * F_PI/180.0f },
  88. { FRONT_RIGHT, 30.0f * F_PI/180.0f },
  89. { FRONT_CENTER, 0.0f * F_PI/180.0f },
  90. { LFE, 0.0f },
  91. { BACK_LEFT, -150.0f * F_PI/180.0f },
  92. { BACK_RIGHT, 150.0f * F_PI/180.0f },
  93. { SIDE_LEFT, -90.0f * F_PI/180.0f },
  94. { SIDE_RIGHT, 90.0f * F_PI/180.0f }
  95. };
  96. ALCdevice *Device = ALContext->Device;
  97. ALfloat SourceVolume,ListenerGain,MinVolume,MaxVolume;
  98. ALbufferlistitem *BufferListItem;
  99. enum FmtChannels Channels;
  100. ALfloat (*SrcMatrix)[MAXCHANNELS];
  101. ALfloat DryGain, DryGainHF;
  102. ALfloat WetGain[MAX_SENDS];
  103. ALfloat WetGainHF[MAX_SENDS];
  104. ALint NumSends, Frequency;
  105. const ALfloat *ChannelGain;
  106. const struct ChanMap *chans = NULL;
  107. enum Resampler Resampler;
  108. ALint num_channels = 0;
  109. ALboolean DirectChannels;
  110. ALfloat Pitch;
  111. ALfloat cw;
  112. ALuint pos;
  113. ALint i, c;
  114. /* Get device properties */
  115. NumSends = Device->NumAuxSends;
  116. Frequency = Device->Frequency;
  117. /* Get listener properties */
  118. ListenerGain = ALContext->Listener.Gain;
  119. /* Get source properties */
  120. SourceVolume = ALSource->flGain;
  121. MinVolume = ALSource->flMinGain;
  122. MaxVolume = ALSource->flMaxGain;
  123. Pitch = ALSource->flPitch;
  124. Resampler = ALSource->Resampler;
  125. DirectChannels = ALSource->DirectChannels;
  126. /* Calculate the stepping value */
  127. Channels = FmtMono;
  128. BufferListItem = ALSource->queue;
  129. while(BufferListItem != NULL)
  130. {
  131. ALbuffer *ALBuffer;
  132. if((ALBuffer=BufferListItem->buffer) != NULL)
  133. {
  134. ALsizei maxstep = STACK_DATA_SIZE/sizeof(ALfloat) /
  135. ALSource->NumChannels;
  136. maxstep -= ResamplerPadding[Resampler] +
  137. ResamplerPrePadding[Resampler] + 1;
  138. maxstep = mini(maxstep, INT_MAX>>FRACTIONBITS);
  139. Pitch = Pitch * ALBuffer->Frequency / Frequency;
  140. if(Pitch > (ALfloat)maxstep)
  141. ALSource->Params.Step = maxstep<<FRACTIONBITS;
  142. else
  143. {
  144. ALSource->Params.Step = fastf2i(Pitch*FRACTIONONE);
  145. if(ALSource->Params.Step == 0)
  146. ALSource->Params.Step = 1;
  147. }
  148. if(ALSource->Params.Step == FRACTIONONE)
  149. Resampler = PointResampler;
  150. Channels = ALBuffer->FmtChannels;
  151. break;
  152. }
  153. BufferListItem = BufferListItem->next;
  154. }
  155. if(!DirectChannels && Device->Hrtf)
  156. ALSource->Params.DoMix = SelectHrtfMixer(Resampler);
  157. else
  158. ALSource->Params.DoMix = SelectMixer(Resampler);
  159. /* Calculate gains */
  160. DryGain = clampf(SourceVolume, MinVolume, MaxVolume);
  161. DryGain *= ALSource->DirectGain;
  162. DryGainHF = ALSource->DirectGainHF;
  163. for(i = 0;i < NumSends;i++)
  164. {
  165. WetGain[i] = clampf(SourceVolume, MinVolume, MaxVolume);
  166. WetGain[i] *= ALSource->Send[i].WetGain;
  167. WetGainHF[i] = ALSource->Send[i].WetGainHF;
  168. }
  169. SrcMatrix = ALSource->Params.DryGains;
  170. for(i = 0;i < MAXCHANNELS;i++)
  171. {
  172. for(c = 0;c < MAXCHANNELS;c++)
  173. SrcMatrix[i][c] = 0.0f;
  174. }
  175. switch(Channels)
  176. {
  177. case FmtMono:
  178. chans = MonoMap;
  179. num_channels = 1;
  180. break;
  181. case FmtStereo:
  182. if(!DirectChannels && (Device->Flags&DEVICE_DUPLICATE_STEREO))
  183. {
  184. DryGain *= aluSqrt(2.0f/4.0f);
  185. for(c = 0;c < 2;c++)
  186. {
  187. pos = aluCart2LUTpos(aluCos(RearMap[c].angle),
  188. aluSin(RearMap[c].angle));
  189. ChannelGain = Device->PanningLUT[pos];
  190. for(i = 0;i < (ALint)Device->NumChan;i++)
  191. {
  192. enum Channel chan = Device->Speaker2Chan[i];
  193. SrcMatrix[c][chan] += DryGain * ListenerGain *
  194. ChannelGain[chan];
  195. }
  196. }
  197. }
  198. chans = StereoMap;
  199. num_channels = 2;
  200. break;
  201. case FmtRear:
  202. chans = RearMap;
  203. num_channels = 2;
  204. break;
  205. case FmtQuad:
  206. chans = QuadMap;
  207. num_channels = 4;
  208. break;
  209. case FmtX51:
  210. chans = X51Map;
  211. num_channels = 6;
  212. break;
  213. case FmtX61:
  214. chans = X61Map;
  215. num_channels = 7;
  216. break;
  217. case FmtX71:
  218. chans = X71Map;
  219. num_channels = 8;
  220. break;
  221. }
  222. if(DirectChannels != AL_FALSE)
  223. {
  224. for(c = 0;c < num_channels;c++)
  225. {
  226. for(i = 0;i < (ALint)Device->NumChan;i++)
  227. {
  228. enum Channel chan = Device->Speaker2Chan[i];
  229. if(chan == chans[c].channel)
  230. {
  231. SrcMatrix[c][chan] += DryGain * ListenerGain;
  232. break;
  233. }
  234. }
  235. }
  236. }
  237. else if(Device->Hrtf)
  238. {
  239. for(c = 0;c < num_channels;c++)
  240. {
  241. if(chans[c].channel == LFE)
  242. {
  243. /* Skip LFE */
  244. ALSource->Params.HrtfDelay[c][0] = 0;
  245. ALSource->Params.HrtfDelay[c][1] = 0;
  246. for(i = 0;i < HRIR_LENGTH;i++)
  247. {
  248. ALSource->Params.HrtfCoeffs[c][i][0] = 0.0f;
  249. ALSource->Params.HrtfCoeffs[c][i][1] = 0.0f;
  250. }
  251. }
  252. else
  253. {
  254. /* Get the static HRIR coefficients and delays for this
  255. * channel. */
  256. GetLerpedHrtfCoeffs(Device->Hrtf,
  257. 0.0f, chans[c].angle,
  258. DryGain*ListenerGain,
  259. ALSource->Params.HrtfCoeffs[c],
  260. ALSource->Params.HrtfDelay[c]);
  261. }
  262. ALSource->HrtfCounter = 0;
  263. }
  264. }
  265. else
  266. {
  267. for(c = 0;c < num_channels;c++)
  268. {
  269. if(chans[c].channel == LFE) /* Special-case LFE */
  270. {
  271. SrcMatrix[c][LFE] += DryGain * ListenerGain;
  272. continue;
  273. }
  274. pos = aluCart2LUTpos(aluCos(chans[c].angle), aluSin(chans[c].angle));
  275. ChannelGain = Device->PanningLUT[pos];
  276. for(i = 0;i < (ALint)Device->NumChan;i++)
  277. {
  278. enum Channel chan = Device->Speaker2Chan[i];
  279. SrcMatrix[c][chan] += DryGain * ListenerGain *
  280. ChannelGain[chan];
  281. }
  282. }
  283. }
  284. for(i = 0;i < NumSends;i++)
  285. {
  286. ALeffectslot *Slot = ALSource->Send[i].Slot;
  287. if(!Slot && i == 0)
  288. Slot = Device->DefaultSlot;
  289. if(Slot && Slot->effect.type == AL_EFFECT_NULL)
  290. Slot = NULL;
  291. ALSource->Params.Send[i].Slot = Slot;
  292. ALSource->Params.Send[i].WetGain = WetGain[i] * ListenerGain;
  293. }
  294. /* Update filter coefficients. Calculations based on the I3DL2
  295. * spec. */
  296. cw = aluCos(F_PI*2.0f * LOWPASSFREQREF / Frequency);
  297. /* We use two chained one-pole filters, so we need to take the
  298. * square root of the squared gain, which is the same as the base
  299. * gain. */
  300. ALSource->Params.iirFilter.coeff = lpCoeffCalc(DryGainHF, cw);
  301. for(i = 0;i < NumSends;i++)
  302. {
  303. /* We use a one-pole filter, so we need to take the squared gain */
  304. ALfloat a = lpCoeffCalc(WetGainHF[i]*WetGainHF[i], cw);
  305. ALSource->Params.Send[i].iirFilter.coeff = a;
  306. }
  307. }
  308. ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
  309. {
  310. const ALCdevice *Device = ALContext->Device;
  311. ALfloat InnerAngle,OuterAngle,Angle,Distance,ClampedDist;
  312. ALfloat Direction[3],Position[3],SourceToListener[3];
  313. ALfloat Velocity[3],ListenerVel[3];
  314. ALfloat MinVolume,MaxVolume,MinDist,MaxDist,Rolloff;
  315. ALfloat ConeVolume,ConeHF,SourceVolume,ListenerGain;
  316. ALfloat DopplerFactor, SpeedOfSound;
  317. ALfloat AirAbsorptionFactor;
  318. ALfloat RoomAirAbsorption[MAX_SENDS];
  319. ALbufferlistitem *BufferListItem;
  320. ALfloat Attenuation;
  321. ALfloat RoomAttenuation[MAX_SENDS];
  322. ALfloat MetersPerUnit;
  323. ALfloat RoomRolloffBase;
  324. ALfloat RoomRolloff[MAX_SENDS];
  325. ALfloat DecayDistance[MAX_SENDS];
  326. ALfloat DryGain;
  327. ALfloat DryGainHF;
  328. ALboolean DryGainHFAuto;
  329. ALfloat WetGain[MAX_SENDS];
  330. ALfloat WetGainHF[MAX_SENDS];
  331. ALboolean WetGainAuto;
  332. ALboolean WetGainHFAuto;
  333. enum Resampler Resampler;
  334. ALfloat Matrix[4][4];
  335. ALfloat Pitch;
  336. ALuint Frequency;
  337. ALint NumSends;
  338. ALfloat cw;
  339. ALint i, j;
  340. DryGainHF = 1.0f;
  341. for(i = 0;i < MAX_SENDS;i++)
  342. WetGainHF[i] = 1.0f;
  343. //Get context properties
  344. DopplerFactor = ALContext->DopplerFactor * ALSource->DopplerFactor;
  345. SpeedOfSound = ALContext->flSpeedOfSound * ALContext->DopplerVelocity;
  346. NumSends = Device->NumAuxSends;
  347. Frequency = Device->Frequency;
  348. //Get listener properties
  349. ListenerGain = ALContext->Listener.Gain;
  350. MetersPerUnit = ALContext->Listener.MetersPerUnit;
  351. ListenerVel[0] = ALContext->Listener.Velocity[0];
  352. ListenerVel[1] = ALContext->Listener.Velocity[1];
  353. ListenerVel[2] = ALContext->Listener.Velocity[2];
  354. //Get source properties
  355. SourceVolume = ALSource->flGain;
  356. MinVolume = ALSource->flMinGain;
  357. MaxVolume = ALSource->flMaxGain;
  358. Pitch = ALSource->flPitch;
  359. Resampler = ALSource->Resampler;
  360. Position[0] = ALSource->vPosition[0] * MetersPerUnit;
  361. Position[1] = ALSource->vPosition[1] * MetersPerUnit;
  362. Position[2] = ALSource->vPosition[2] * MetersPerUnit;
  363. Direction[0] = ALSource->vOrientation[0];
  364. Direction[1] = ALSource->vOrientation[1];
  365. Direction[2] = ALSource->vOrientation[2];
  366. Velocity[0] = ALSource->vVelocity[0];
  367. Velocity[1] = ALSource->vVelocity[1];
  368. Velocity[2] = ALSource->vVelocity[2];
  369. MinDist = ALSource->flRefDistance * MetersPerUnit;
  370. MaxDist = ALSource->flMaxDistance * MetersPerUnit;
  371. Rolloff = ALSource->flRollOffFactor;
  372. InnerAngle = ALSource->flInnerAngle * ConeScale;
  373. OuterAngle = ALSource->flOuterAngle * ConeScale;
  374. AirAbsorptionFactor = ALSource->AirAbsorptionFactor;
  375. DryGainHFAuto = ALSource->DryGainHFAuto;
  376. WetGainAuto = ALSource->WetGainAuto;
  377. WetGainHFAuto = ALSource->WetGainHFAuto;
  378. RoomRolloffBase = ALSource->RoomRolloffFactor;
  379. for(i = 0;i < NumSends;i++)
  380. {
  381. ALeffectslot *Slot = ALSource->Send[i].Slot;
  382. if(!Slot && i == 0)
  383. Slot = Device->DefaultSlot;
  384. if(!Slot || Slot->effect.type == AL_EFFECT_NULL)
  385. {
  386. Slot = NULL;
  387. RoomRolloff[i] = 0.0f;
  388. DecayDistance[i] = 0.0f;
  389. RoomAirAbsorption[i] = 1.0f;
  390. }
  391. else if(Slot->AuxSendAuto)
  392. {
  393. RoomRolloff[i] = RoomRolloffBase;
  394. if(IsReverbEffect(Slot->effect.type))
  395. {
  396. RoomRolloff[i] += Slot->effect.Reverb.RoomRolloffFactor;
  397. DecayDistance[i] = Slot->effect.Reverb.DecayTime *
  398. SPEEDOFSOUNDMETRESPERSEC;
  399. RoomAirAbsorption[i] = Slot->effect.Reverb.AirAbsorptionGainHF;
  400. }
  401. else
  402. {
  403. DecayDistance[i] = 0.0f;
  404. RoomAirAbsorption[i] = 1.0f;
  405. }
  406. }
  407. else
  408. {
  409. /* If the slot's auxiliary send auto is off, the data sent to the
  410. * effect slot is the same as the dry path, sans filter effects */
  411. RoomRolloff[i] = Rolloff;
  412. DecayDistance[i] = 0.0f;
  413. RoomAirAbsorption[i] = AIRABSORBGAINHF;
  414. }
  415. ALSource->Params.Send[i].Slot = Slot;
  416. }
  417. for(i = 0;i < 4;i++)
  418. {
  419. for(j = 0;j < 4;j++)
  420. Matrix[i][j] = ALContext->Listener.Matrix[i][j];
  421. }
  422. //1. Translate Listener to origin (convert to head relative)
  423. if(ALSource->bHeadRelative == AL_FALSE)
  424. {
  425. /* Translate position */
  426. Position[0] -= ALContext->Listener.Position[0] * MetersPerUnit;
  427. Position[1] -= ALContext->Listener.Position[1] * MetersPerUnit;
  428. Position[2] -= ALContext->Listener.Position[2] * MetersPerUnit;
  429. /* Transform source vectors into listener space */
  430. aluMatrixVector(Position, 1.0f, Matrix);
  431. aluMatrixVector(Direction, 0.0f, Matrix);
  432. aluMatrixVector(Velocity, 0.0f, Matrix);
  433. /* Transform listener velocity into listener space */
  434. aluMatrixVector(ListenerVel, 0.0f, Matrix);
  435. }
  436. else
  437. {
  438. /* Transform listener velocity into listener space */
  439. aluMatrixVector(ListenerVel, 0.0f, Matrix);
  440. /* Offset the source velocity to be relative of the listener velocity */
  441. Velocity[0] += ListenerVel[0];
  442. Velocity[1] += ListenerVel[1];
  443. Velocity[2] += ListenerVel[2];
  444. }
  445. SourceToListener[0] = -Position[0];
  446. SourceToListener[1] = -Position[1];
  447. SourceToListener[2] = -Position[2];
  448. aluNormalize(SourceToListener);
  449. aluNormalize(Direction);
  450. //2. Calculate distance attenuation
  451. Distance = aluSqrt(aluDotproduct(Position, Position));
  452. ClampedDist = Distance;
  453. Attenuation = 1.0f;
  454. for(i = 0;i < NumSends;i++)
  455. RoomAttenuation[i] = 1.0f;
  456. switch(ALContext->SourceDistanceModel ? ALSource->DistanceModel :
  457. ALContext->DistanceModel)
  458. {
  459. case InverseDistanceClamped:
  460. ClampedDist = clampf(ClampedDist, MinDist, MaxDist);
  461. if(MaxDist < MinDist)
  462. break;
  463. //fall-through
  464. case InverseDistance:
  465. if(MinDist > 0.0f)
  466. {
  467. if((MinDist + (Rolloff * (ClampedDist - MinDist))) > 0.0f)
  468. Attenuation = MinDist / (MinDist + (Rolloff * (ClampedDist - MinDist)));
  469. for(i = 0;i < NumSends;i++)
  470. {
  471. if((MinDist + (RoomRolloff[i] * (ClampedDist - MinDist))) > 0.0f)
  472. RoomAttenuation[i] = MinDist / (MinDist + (RoomRolloff[i] * (ClampedDist - MinDist)));
  473. }
  474. }
  475. break;
  476. case LinearDistanceClamped:
  477. ClampedDist = clampf(ClampedDist, MinDist, MaxDist);
  478. if(MaxDist < MinDist)
  479. break;
  480. //fall-through
  481. case LinearDistance:
  482. if(MaxDist != MinDist)
  483. {
  484. Attenuation = 1.0f - (Rolloff*(ClampedDist-MinDist)/(MaxDist - MinDist));
  485. Attenuation = maxf(Attenuation, 0.0f);
  486. for(i = 0;i < NumSends;i++)
  487. {
  488. RoomAttenuation[i] = 1.0f - (RoomRolloff[i]*(ClampedDist-MinDist)/(MaxDist - MinDist));
  489. RoomAttenuation[i] = maxf(RoomAttenuation[i], 0.0f);
  490. }
  491. }
  492. break;
  493. case ExponentDistanceClamped:
  494. ClampedDist = clampf(ClampedDist, MinDist, MaxDist);
  495. if(MaxDist < MinDist)
  496. break;
  497. //fall-through
  498. case ExponentDistance:
  499. if(ClampedDist > 0.0f && MinDist > 0.0f)
  500. {
  501. Attenuation = aluPow(ClampedDist/MinDist, -Rolloff);
  502. for(i = 0;i < NumSends;i++)
  503. RoomAttenuation[i] = aluPow(ClampedDist/MinDist, -RoomRolloff[i]);
  504. }
  505. break;
  506. case DisableDistance:
  507. ClampedDist = MinDist;
  508. break;
  509. }
  510. // Source Gain + Attenuation
  511. DryGain = SourceVolume * Attenuation;
  512. for(i = 0;i < NumSends;i++)
  513. WetGain[i] = SourceVolume * RoomAttenuation[i];
  514. // Distance-based air absorption
  515. ClampedDist = maxf(ClampedDist-MinDist, 0.0f);
  516. if(AirAbsorptionFactor > 0.0f && ClampedDist > 0.0f)
  517. {
  518. DryGainHF *= aluPow(AIRABSORBGAINHF, AirAbsorptionFactor*ClampedDist);
  519. for(i = 0;i < NumSends;i++)
  520. WetGainHF[i] *= aluPow(RoomAirAbsorption[i],
  521. AirAbsorptionFactor*ClampedDist);
  522. }
  523. if(WetGainAuto && ClampedDist > 0.0f)
  524. {
  525. /* Apply a decay-time transformation to the wet path, based on the
  526. * attenuation of the dry path.
  527. *
  528. * Using the distance from the minimum (reference) distance property,
  529. * the initial decay of the reverb effect is calculated and applied to
  530. * the wet path.
  531. */
  532. for(i = 0;i < NumSends;i++)
  533. {
  534. if(DecayDistance[i] > 0.0f)
  535. WetGain[i] *= aluPow(0.001f/*-60dB*/, ClampedDist/DecayDistance[i]);
  536. }
  537. }
  538. /* Calculate directional soundcones */
  539. Angle = aluAcos(aluDotproduct(Direction,SourceToListener)) * (180.0f/F_PI);
  540. if(Angle >= InnerAngle && Angle <= OuterAngle)
  541. {
  542. ALfloat scale = (Angle-InnerAngle) / (OuterAngle-InnerAngle);
  543. ConeVolume = lerp(1.0f, ALSource->flOuterGain, scale);
  544. ConeHF = lerp(1.0f, ALSource->OuterGainHF, scale);
  545. }
  546. else if(Angle > OuterAngle)
  547. {
  548. ConeVolume = ALSource->flOuterGain;
  549. ConeHF = ALSource->OuterGainHF;
  550. }
  551. else
  552. {
  553. ConeVolume = 1.0f;
  554. ConeHF = 1.0f;
  555. }
  556. DryGain *= ConeVolume;
  557. if(WetGainAuto)
  558. {
  559. for(i = 0;i < NumSends;i++)
  560. WetGain[i] *= ConeVolume;
  561. }
  562. if(DryGainHFAuto)
  563. DryGainHF *= ConeHF;
  564. if(WetGainHFAuto)
  565. {
  566. for(i = 0;i < NumSends;i++)
  567. WetGainHF[i] *= ConeHF;
  568. }
  569. // Clamp to Min/Max Gain
  570. DryGain = clampf(DryGain, MinVolume, MaxVolume);
  571. for(i = 0;i < NumSends;i++)
  572. WetGain[i] = clampf(WetGain[i], MinVolume, MaxVolume);
  573. // Apply filter gains and filters
  574. DryGain *= ALSource->DirectGain * ListenerGain;
  575. DryGainHF *= ALSource->DirectGainHF;
  576. for(i = 0;i < NumSends;i++)
  577. {
  578. WetGain[i] *= ALSource->Send[i].WetGain * ListenerGain;
  579. WetGainHF[i] *= ALSource->Send[i].WetGainHF;
  580. }
  581. // Calculate Velocity
  582. if(DopplerFactor > 0.0f && SpeedOfSound > 0.5f)
  583. {
  584. ALfloat VSS, VLS;
  585. VSS = aluDotproduct(Velocity, SourceToListener) * DopplerFactor;
  586. VLS = aluDotproduct(ListenerVel, SourceToListener) * DopplerFactor;
  587. Pitch *= clampf(SpeedOfSound-VLS, 1.0f, SpeedOfSound*2.0f - 1.0f) /
  588. clampf(SpeedOfSound-VSS, 1.0f, SpeedOfSound*2.0f - 1.0f);
  589. }
  590. BufferListItem = ALSource->queue;
  591. while(BufferListItem != NULL)
  592. {
  593. ALbuffer *ALBuffer;
  594. if((ALBuffer=BufferListItem->buffer) != NULL)
  595. {
  596. ALsizei maxstep = STACK_DATA_SIZE/sizeof(ALfloat) /
  597. ALSource->NumChannels;
  598. maxstep -= ResamplerPadding[Resampler] +
  599. ResamplerPrePadding[Resampler] + 1;
  600. maxstep = mini(maxstep, INT_MAX>>FRACTIONBITS);
  601. Pitch = Pitch * ALBuffer->Frequency / Frequency;
  602. if(Pitch > (ALfloat)maxstep)
  603. ALSource->Params.Step = maxstep<<FRACTIONBITS;
  604. else
  605. {
  606. ALSource->Params.Step = fastf2i(Pitch*FRACTIONONE);
  607. if(ALSource->Params.Step == 0)
  608. ALSource->Params.Step = 1;
  609. }
  610. if(ALSource->Params.Step == FRACTIONONE)
  611. Resampler = PointResampler;
  612. break;
  613. }
  614. BufferListItem = BufferListItem->next;
  615. }
  616. if(Device->Hrtf)
  617. ALSource->Params.DoMix = SelectHrtfMixer(Resampler);
  618. else
  619. ALSource->Params.DoMix = SelectMixer(Resampler);
  620. if(Device->Hrtf)
  621. {
  622. // Use a binaural HRTF algorithm for stereo headphone playback
  623. ALfloat delta, ev = 0.0f, az = 0.0f;
  624. if(Distance > 0.0f)
  625. {
  626. ALfloat invlen = 1.0f/Distance;
  627. Position[0] *= invlen;
  628. Position[1] *= invlen;
  629. Position[2] *= invlen;
  630. // Calculate elevation and azimuth only when the source is not at
  631. // the listener. This prevents +0 and -0 Z from producing
  632. // inconsistent panning.
  633. ev = aluAsin(Position[1]);
  634. az = aluAtan2(Position[0], -Position[2]*ZScale);
  635. }
  636. // Check to see if the HRIR is already moving.
  637. if(ALSource->HrtfMoving)
  638. {
  639. // Calculate the normalized HRTF transition factor (delta).
  640. delta = CalcHrtfDelta(ALSource->Params.HrtfGain, DryGain,
  641. ALSource->Params.HrtfDir, Position);
  642. // If the delta is large enough, get the moving HRIR target
  643. // coefficients, target delays, steppping values, and counter.
  644. if(delta > 0.001f)
  645. {
  646. ALSource->HrtfCounter = GetMovingHrtfCoeffs(Device->Hrtf,
  647. ev, az, DryGain, delta,
  648. ALSource->HrtfCounter,
  649. ALSource->Params.HrtfCoeffs[0],
  650. ALSource->Params.HrtfDelay[0],
  651. ALSource->Params.HrtfCoeffStep,
  652. ALSource->Params.HrtfDelayStep);
  653. ALSource->Params.HrtfGain = DryGain;
  654. ALSource->Params.HrtfDir[0] = Position[0];
  655. ALSource->Params.HrtfDir[1] = Position[1];
  656. ALSource->Params.HrtfDir[2] = Position[2];
  657. }
  658. }
  659. else
  660. {
  661. // Get the initial (static) HRIR coefficients and delays.
  662. GetLerpedHrtfCoeffs(Device->Hrtf, ev, az, DryGain,
  663. ALSource->Params.HrtfCoeffs[0],
  664. ALSource->Params.HrtfDelay[0]);
  665. ALSource->HrtfCounter = 0;
  666. ALSource->Params.HrtfGain = DryGain;
  667. ALSource->Params.HrtfDir[0] = Position[0];
  668. ALSource->Params.HrtfDir[1] = Position[1];
  669. ALSource->Params.HrtfDir[2] = Position[2];
  670. }
  671. }
  672. else
  673. {
  674. // Use energy-preserving panning algorithm for multi-speaker playback
  675. ALfloat DirGain, AmbientGain;
  676. const ALfloat *ChannelGain;
  677. ALfloat length;
  678. ALint pos;
  679. length = maxf(Distance, MinDist);
  680. if(length > 0.0f)
  681. {
  682. ALfloat invlen = 1.0f/length;
  683. Position[0] *= invlen;
  684. Position[1] *= invlen;
  685. Position[2] *= invlen;
  686. }
  687. pos = aluCart2LUTpos(-Position[2]*ZScale, Position[0]);
  688. ChannelGain = Device->PanningLUT[pos];
  689. DirGain = aluSqrt(Position[0]*Position[0] + Position[2]*Position[2]);
  690. // elevation adjustment for directional gain. this sucks, but
  691. // has low complexity
  692. AmbientGain = aluSqrt(1.0f/Device->NumChan);
  693. for(i = 0;i < MAXCHANNELS;i++)
  694. {
  695. ALuint i2;
  696. for(i2 = 0;i2 < MAXCHANNELS;i2++)
  697. ALSource->Params.DryGains[i][i2] = 0.0f;
  698. }
  699. for(i = 0;i < (ALint)Device->NumChan;i++)
  700. {
  701. enum Channel chan = Device->Speaker2Chan[i];
  702. ALfloat gain = lerp(AmbientGain, ChannelGain[chan], DirGain);
  703. ALSource->Params.DryGains[0][chan] = DryGain * gain;
  704. }
  705. }
  706. for(i = 0;i < NumSends;i++)
  707. ALSource->Params.Send[i].WetGain = WetGain[i];
  708. /* Update filter coefficients. */
  709. cw = aluCos(F_PI*2.0f * LOWPASSFREQREF / Frequency);
  710. ALSource->Params.iirFilter.coeff = lpCoeffCalc(DryGainHF, cw);
  711. for(i = 0;i < NumSends;i++)
  712. {
  713. ALfloat a = lpCoeffCalc(WetGainHF[i]*WetGainHF[i], cw);
  714. ALSource->Params.Send[i].iirFilter.coeff = a;
  715. }
  716. }
  717. static __inline ALfloat aluF2F(ALfloat val)
  718. { return val; }
  719. static __inline ALint aluF2I(ALfloat val)
  720. {
  721. if(val > 1.0f) return 2147483647;
  722. if(val < -1.0f) return -2147483647-1;
  723. return fastf2i((ALfloat)(val*2147483647.0));
  724. }
  725. static __inline ALuint aluF2UI(ALfloat val)
  726. { return aluF2I(val)+2147483648u; }
  727. static __inline ALshort aluF2S(ALfloat val)
  728. { return aluF2I(val)>>16; }
  729. static __inline ALushort aluF2US(ALfloat val)
  730. { return aluF2S(val)+32768; }
  731. static __inline ALbyte aluF2B(ALfloat val)
  732. { return aluF2I(val)>>24; }
  733. static __inline ALubyte aluF2UB(ALfloat val)
  734. { return aluF2B(val)+128; }
  735. #define DECL_TEMPLATE(T, N, func) \
  736. static void Write_##T##_##N(ALCdevice *device, T *RESTRICT buffer, \
  737. ALuint SamplesToDo) \
  738. { \
  739. ALfloat (*RESTRICT DryBuffer)[MAXCHANNELS] = device->DryBuffer; \
  740. const enum Channel *ChanMap = device->DevChannels; \
  741. ALuint i, j; \
  742. \
  743. for(j = 0;j < N;j++) \
  744. { \
  745. T *RESTRICT out = buffer + j; \
  746. enum Channel chan = ChanMap[j]; \
  747. \
  748. for(i = 0;i < SamplesToDo;i++) \
  749. out[i*N] = func(DryBuffer[i][chan]); \
  750. } \
  751. }
  752. DECL_TEMPLATE(ALfloat, 1, aluF2F)
  753. DECL_TEMPLATE(ALfloat, 2, aluF2F)
  754. DECL_TEMPLATE(ALfloat, 4, aluF2F)
  755. DECL_TEMPLATE(ALfloat, 6, aluF2F)
  756. DECL_TEMPLATE(ALfloat, 7, aluF2F)
  757. DECL_TEMPLATE(ALfloat, 8, aluF2F)
  758. DECL_TEMPLATE(ALuint, 1, aluF2UI)
  759. DECL_TEMPLATE(ALuint, 2, aluF2UI)
  760. DECL_TEMPLATE(ALuint, 4, aluF2UI)
  761. DECL_TEMPLATE(ALuint, 6, aluF2UI)
  762. DECL_TEMPLATE(ALuint, 7, aluF2UI)
  763. DECL_TEMPLATE(ALuint, 8, aluF2UI)
  764. DECL_TEMPLATE(ALint, 1, aluF2I)
  765. DECL_TEMPLATE(ALint, 2, aluF2I)
  766. DECL_TEMPLATE(ALint, 4, aluF2I)
  767. DECL_TEMPLATE(ALint, 6, aluF2I)
  768. DECL_TEMPLATE(ALint, 7, aluF2I)
  769. DECL_TEMPLATE(ALint, 8, aluF2I)
  770. DECL_TEMPLATE(ALushort, 1, aluF2US)
  771. DECL_TEMPLATE(ALushort, 2, aluF2US)
  772. DECL_TEMPLATE(ALushort, 4, aluF2US)
  773. DECL_TEMPLATE(ALushort, 6, aluF2US)
  774. DECL_TEMPLATE(ALushort, 7, aluF2US)
  775. DECL_TEMPLATE(ALushort, 8, aluF2US)
  776. DECL_TEMPLATE(ALshort, 1, aluF2S)
  777. DECL_TEMPLATE(ALshort, 2, aluF2S)
  778. DECL_TEMPLATE(ALshort, 4, aluF2S)
  779. DECL_TEMPLATE(ALshort, 6, aluF2S)
  780. DECL_TEMPLATE(ALshort, 7, aluF2S)
  781. DECL_TEMPLATE(ALshort, 8, aluF2S)
  782. DECL_TEMPLATE(ALubyte, 1, aluF2UB)
  783. DECL_TEMPLATE(ALubyte, 2, aluF2UB)
  784. DECL_TEMPLATE(ALubyte, 4, aluF2UB)
  785. DECL_TEMPLATE(ALubyte, 6, aluF2UB)
  786. DECL_TEMPLATE(ALubyte, 7, aluF2UB)
  787. DECL_TEMPLATE(ALubyte, 8, aluF2UB)
  788. DECL_TEMPLATE(ALbyte, 1, aluF2B)
  789. DECL_TEMPLATE(ALbyte, 2, aluF2B)
  790. DECL_TEMPLATE(ALbyte, 4, aluF2B)
  791. DECL_TEMPLATE(ALbyte, 6, aluF2B)
  792. DECL_TEMPLATE(ALbyte, 7, aluF2B)
  793. DECL_TEMPLATE(ALbyte, 8, aluF2B)
  794. #undef DECL_TEMPLATE
  795. #define DECL_TEMPLATE(T) \
  796. static void Write_##T(ALCdevice *device, T *buffer, ALuint SamplesToDo) \
  797. { \
  798. switch(device->FmtChans) \
  799. { \
  800. case DevFmtMono: \
  801. Write_##T##_1(device, buffer, SamplesToDo); \
  802. break; \
  803. case DevFmtStereo: \
  804. Write_##T##_2(device, buffer, SamplesToDo); \
  805. break; \
  806. case DevFmtQuad: \
  807. Write_##T##_4(device, buffer, SamplesToDo); \
  808. break; \
  809. case DevFmtX51: \
  810. case DevFmtX51Side: \
  811. Write_##T##_6(device, buffer, SamplesToDo); \
  812. break; \
  813. case DevFmtX61: \
  814. Write_##T##_7(device, buffer, SamplesToDo); \
  815. break; \
  816. case DevFmtX71: \
  817. Write_##T##_8(device, buffer, SamplesToDo); \
  818. break; \
  819. } \
  820. }
  821. DECL_TEMPLATE(ALfloat)
  822. DECL_TEMPLATE(ALuint)
  823. DECL_TEMPLATE(ALint)
  824. DECL_TEMPLATE(ALushort)
  825. DECL_TEMPLATE(ALshort)
  826. DECL_TEMPLATE(ALubyte)
  827. DECL_TEMPLATE(ALbyte)
  828. #undef DECL_TEMPLATE
  829. ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
  830. {
  831. ALuint SamplesToDo;
  832. ALeffectslot **slot, **slot_end;
  833. ALsource **src, **src_end;
  834. ALCcontext *ctx;
  835. int fpuState;
  836. ALuint i, c;
  837. fpuState = SetMixerFPUMode();
  838. while(size > 0)
  839. {
  840. /* Setup variables */
  841. SamplesToDo = minu(size, BUFFERSIZE);
  842. /* Clear mixing buffer */
  843. memset(device->DryBuffer, 0, SamplesToDo*MAXCHANNELS*sizeof(ALfloat));
  844. LockDevice(device);
  845. ctx = device->ContextList;
  846. while(ctx)
  847. {
  848. ALenum DeferUpdates = ctx->DeferUpdates;
  849. ALenum UpdateSources = AL_FALSE;
  850. if(!DeferUpdates)
  851. UpdateSources = ExchangeInt(&ctx->UpdateSources, AL_FALSE);
  852. src = ctx->ActiveSources;
  853. src_end = src + ctx->ActiveSourceCount;
  854. while(src != src_end)
  855. {
  856. if((*src)->state != AL_PLAYING)
  857. {
  858. --(ctx->ActiveSourceCount);
  859. *src = *(--src_end);
  860. continue;
  861. }
  862. if(!DeferUpdates && (ExchangeInt(&(*src)->NeedsUpdate, AL_FALSE) ||
  863. UpdateSources))
  864. ALsource_Update(*src, ctx);
  865. MixSource(*src, device, SamplesToDo);
  866. src++;
  867. }
  868. /* effect slot processing */
  869. slot = ctx->ActiveEffectSlots;
  870. slot_end = slot + ctx->ActiveEffectSlotCount;
  871. while(slot != slot_end)
  872. {
  873. for(c = 0;c < SamplesToDo;c++)
  874. {
  875. (*slot)->WetBuffer[c] += (*slot)->ClickRemoval[0];
  876. (*slot)->ClickRemoval[0] -= (*slot)->ClickRemoval[0] * (1.0f/256.0f);
  877. }
  878. (*slot)->ClickRemoval[0] += (*slot)->PendingClicks[0];
  879. (*slot)->PendingClicks[0] = 0.0f;
  880. if(!DeferUpdates && ExchangeInt(&(*slot)->NeedsUpdate, AL_FALSE))
  881. ALeffectState_Update((*slot)->EffectState, device, *slot);
  882. ALeffectState_Process((*slot)->EffectState, SamplesToDo,
  883. (*slot)->WetBuffer, device->DryBuffer);
  884. for(i = 0;i < SamplesToDo;i++)
  885. (*slot)->WetBuffer[i] = 0.0f;
  886. slot++;
  887. }
  888. ctx = ctx->next;
  889. }
  890. slot = &device->DefaultSlot;
  891. if(*slot != NULL)
  892. {
  893. for(c = 0;c < SamplesToDo;c++)
  894. {
  895. (*slot)->WetBuffer[c] += (*slot)->ClickRemoval[0];
  896. (*slot)->ClickRemoval[0] -= (*slot)->ClickRemoval[0] * (1.0f/256.0f);
  897. }
  898. (*slot)->ClickRemoval[0] += (*slot)->PendingClicks[0];
  899. (*slot)->PendingClicks[0] = 0.0f;
  900. if(ExchangeInt(&(*slot)->NeedsUpdate, AL_FALSE))
  901. ALeffectState_Update((*slot)->EffectState, device, *slot);
  902. ALeffectState_Process((*slot)->EffectState, SamplesToDo,
  903. (*slot)->WetBuffer, device->DryBuffer);
  904. for(i = 0;i < SamplesToDo;i++)
  905. (*slot)->WetBuffer[i] = 0.0f;
  906. }
  907. UnlockDevice(device);
  908. //Post processing loop
  909. if(device->FmtChans == DevFmtMono)
  910. {
  911. for(i = 0;i < SamplesToDo;i++)
  912. {
  913. device->DryBuffer[i][FRONT_CENTER] += device->ClickRemoval[FRONT_CENTER];
  914. device->ClickRemoval[FRONT_CENTER] -= device->ClickRemoval[FRONT_CENTER] * (1.0f/256.0f);
  915. }
  916. device->ClickRemoval[FRONT_CENTER] += device->PendingClicks[FRONT_CENTER];
  917. device->PendingClicks[FRONT_CENTER] = 0.0f;
  918. }
  919. else if(device->FmtChans == DevFmtStereo)
  920. {
  921. /* Assumes the first two channels are FRONT_LEFT and FRONT_RIGHT */
  922. for(i = 0;i < SamplesToDo;i++)
  923. {
  924. for(c = 0;c < 2;c++)
  925. {
  926. device->DryBuffer[i][c] += device->ClickRemoval[c];
  927. device->ClickRemoval[c] -= device->ClickRemoval[c] * (1.0f/256.0f);
  928. }
  929. }
  930. for(c = 0;c < 2;c++)
  931. {
  932. device->ClickRemoval[c] += device->PendingClicks[c];
  933. device->PendingClicks[c] = 0.0f;
  934. }
  935. if(device->Bs2b)
  936. {
  937. for(i = 0;i < SamplesToDo;i++)
  938. bs2b_cross_feed(device->Bs2b, &device->DryBuffer[i][0]);
  939. }
  940. }
  941. else
  942. {
  943. for(i = 0;i < SamplesToDo;i++)
  944. {
  945. for(c = 0;c < MAXCHANNELS;c++)
  946. {
  947. device->DryBuffer[i][c] += device->ClickRemoval[c];
  948. device->ClickRemoval[c] -= device->ClickRemoval[c] * (1.0f/256.0f);
  949. }
  950. }
  951. for(c = 0;c < MAXCHANNELS;c++)
  952. {
  953. device->ClickRemoval[c] += device->PendingClicks[c];
  954. device->PendingClicks[c] = 0.0f;
  955. }
  956. }
  957. if(buffer)
  958. {
  959. switch(device->FmtType)
  960. {
  961. case DevFmtByte:
  962. Write_ALbyte(device, buffer, SamplesToDo);
  963. break;
  964. case DevFmtUByte:
  965. Write_ALubyte(device, buffer, SamplesToDo);
  966. break;
  967. case DevFmtShort:
  968. Write_ALshort(device, buffer, SamplesToDo);
  969. break;
  970. case DevFmtUShort:
  971. Write_ALushort(device, buffer, SamplesToDo);
  972. break;
  973. case DevFmtInt:
  974. Write_ALint(device, buffer, SamplesToDo);
  975. break;
  976. case DevFmtUInt:
  977. Write_ALuint(device, buffer, SamplesToDo);
  978. break;
  979. case DevFmtFloat:
  980. Write_ALfloat(device, buffer, SamplesToDo);
  981. break;
  982. }
  983. }
  984. size -= SamplesToDo;
  985. }
  986. RestoreFPUMode(fpuState);
  987. }
  988. ALvoid aluHandleDisconnect(ALCdevice *device)
  989. {
  990. ALCcontext *Context;
  991. LockDevice(device);
  992. device->Connected = ALC_FALSE;
  993. Context = device->ContextList;
  994. while(Context)
  995. {
  996. ALsource **src, **src_end;
  997. src = Context->ActiveSources;
  998. src_end = src + Context->ActiveSourceCount;
  999. while(src != src_end)
  1000. {
  1001. if((*src)->state == AL_PLAYING)
  1002. {
  1003. (*src)->state = AL_STOPPED;
  1004. (*src)->BuffersPlayed = (*src)->BuffersInQueue;
  1005. (*src)->position = 0;
  1006. (*src)->position_fraction = 0;
  1007. }
  1008. src++;
  1009. }
  1010. Context->ActiveSourceCount = 0;
  1011. Context = Context->next;
  1012. }
  1013. UnlockDevice(device);
  1014. }