ALu.c 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259
  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 "alSource.h"
  28. #include "alBuffer.h"
  29. #include "alListener.h"
  30. #include "alAuxEffectSlot.h"
  31. #include "alu.h"
  32. #include "bs2b.h"
  33. #include "mixer_defs.h"
  34. #include "midi/base.h"
  35. struct ChanMap {
  36. enum Channel channel;
  37. ALfloat angle;
  38. };
  39. /* Cone scalar */
  40. ALfloat ConeScale = 1.0f;
  41. /* Localized Z scalar for mono sources */
  42. ALfloat ZScale = 1.0f;
  43. extern inline ALfloat minf(ALfloat a, ALfloat b);
  44. extern inline ALfloat maxf(ALfloat a, ALfloat b);
  45. extern inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max);
  46. extern inline ALdouble mind(ALdouble a, ALdouble b);
  47. extern inline ALdouble maxd(ALdouble a, ALdouble b);
  48. extern inline ALdouble clampd(ALdouble val, ALdouble min, ALdouble max);
  49. extern inline ALuint minu(ALuint a, ALuint b);
  50. extern inline ALuint maxu(ALuint a, ALuint b);
  51. extern inline ALuint clampu(ALuint val, ALuint min, ALuint max);
  52. extern inline ALint mini(ALint a, ALint b);
  53. extern inline ALint maxi(ALint a, ALint b);
  54. extern inline ALint clampi(ALint val, ALint min, ALint max);
  55. extern inline ALint64 mini64(ALint64 a, ALint64 b);
  56. extern inline ALint64 maxi64(ALint64 a, ALint64 b);
  57. extern inline ALint64 clampi64(ALint64 val, ALint64 min, ALint64 max);
  58. extern inline ALuint64 minu64(ALuint64 a, ALuint64 b);
  59. extern inline ALuint64 maxu64(ALuint64 a, ALuint64 b);
  60. extern inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max);
  61. extern inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu);
  62. extern inline ALfloat cubic(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALfloat mu);
  63. static ResamplerFunc SelectResampler(enum Resampler Resampler, ALuint increment)
  64. {
  65. if(increment == FRACTIONONE)
  66. return Resample_copy32_C;
  67. switch(Resampler)
  68. {
  69. case PointResampler:
  70. return Resample_point32_C;
  71. case LinearResampler:
  72. return Resample_lerp32_C;
  73. case CubicResampler:
  74. return Resample_cubic32_C;
  75. case ResamplerMax:
  76. /* Shouldn't happen */
  77. break;
  78. }
  79. return Resample_point32_C;
  80. }
  81. static DryMixerFunc SelectHrtfMixer(void)
  82. {
  83. #ifdef HAVE_SSE
  84. if((CPUCapFlags&CPU_CAP_SSE))
  85. return MixDirect_Hrtf_SSE;
  86. #endif
  87. #ifdef HAVE_NEON
  88. if((CPUCapFlags&CPU_CAP_NEON))
  89. return MixDirect_Hrtf_Neon;
  90. #endif
  91. return MixDirect_Hrtf_C;
  92. }
  93. static DryMixerFunc SelectDirectMixer(void)
  94. {
  95. #ifdef HAVE_SSE
  96. if((CPUCapFlags&CPU_CAP_SSE))
  97. return MixDirect_SSE;
  98. #endif
  99. #ifdef HAVE_NEON
  100. if((CPUCapFlags&CPU_CAP_NEON))
  101. return MixDirect_Neon;
  102. #endif
  103. return MixDirect_C;
  104. }
  105. static WetMixerFunc SelectSendMixer(void)
  106. {
  107. #ifdef HAVE_SSE
  108. if((CPUCapFlags&CPU_CAP_SSE))
  109. return MixSend_SSE;
  110. #endif
  111. #ifdef HAVE_NEON
  112. if((CPUCapFlags&CPU_CAP_NEON))
  113. return MixSend_Neon;
  114. #endif
  115. return MixSend_C;
  116. }
  117. static inline void aluCrossproduct(const ALfloat *inVector1, const ALfloat *inVector2, ALfloat *outVector)
  118. {
  119. outVector[0] = inVector1[1]*inVector2[2] - inVector1[2]*inVector2[1];
  120. outVector[1] = inVector1[2]*inVector2[0] - inVector1[0]*inVector2[2];
  121. outVector[2] = inVector1[0]*inVector2[1] - inVector1[1]*inVector2[0];
  122. }
  123. static inline ALfloat aluDotproduct(const ALfloat *inVector1, const ALfloat *inVector2)
  124. {
  125. return inVector1[0]*inVector2[0] + inVector1[1]*inVector2[1] +
  126. inVector1[2]*inVector2[2];
  127. }
  128. static inline void aluNormalize(ALfloat *inVector)
  129. {
  130. ALfloat lengthsqr = aluDotproduct(inVector, inVector);
  131. if(lengthsqr > 0.0f)
  132. {
  133. ALfloat inv_length = 1.0f/sqrtf(lengthsqr);
  134. inVector[0] *= inv_length;
  135. inVector[1] *= inv_length;
  136. inVector[2] *= inv_length;
  137. }
  138. }
  139. static inline ALvoid aluMatrixVector(ALfloat *vector, ALfloat w, ALfloat (*restrict matrix)[4])
  140. {
  141. ALfloat temp[4] = {
  142. vector[0], vector[1], vector[2], w
  143. };
  144. vector[0] = temp[0]*matrix[0][0] + temp[1]*matrix[1][0] + temp[2]*matrix[2][0] + temp[3]*matrix[3][0];
  145. vector[1] = temp[0]*matrix[0][1] + temp[1]*matrix[1][1] + temp[2]*matrix[2][1] + temp[3]*matrix[3][1];
  146. vector[2] = temp[0]*matrix[0][2] + temp[1]*matrix[1][2] + temp[2]*matrix[2][2] + temp[3]*matrix[3][2];
  147. }
  148. static ALvoid CalcListenerParams(ALlistener *Listener)
  149. {
  150. ALfloat N[3], V[3], U[3], P[3];
  151. /* AT then UP */
  152. N[0] = Listener->Forward[0];
  153. N[1] = Listener->Forward[1];
  154. N[2] = Listener->Forward[2];
  155. aluNormalize(N);
  156. V[0] = Listener->Up[0];
  157. V[1] = Listener->Up[1];
  158. V[2] = Listener->Up[2];
  159. aluNormalize(V);
  160. /* Build and normalize right-vector */
  161. aluCrossproduct(N, V, U);
  162. aluNormalize(U);
  163. Listener->Params.Matrix[0][0] = U[0];
  164. Listener->Params.Matrix[0][1] = V[0];
  165. Listener->Params.Matrix[0][2] = -N[0];
  166. Listener->Params.Matrix[0][3] = 0.0f;
  167. Listener->Params.Matrix[1][0] = U[1];
  168. Listener->Params.Matrix[1][1] = V[1];
  169. Listener->Params.Matrix[1][2] = -N[1];
  170. Listener->Params.Matrix[1][3] = 0.0f;
  171. Listener->Params.Matrix[2][0] = U[2];
  172. Listener->Params.Matrix[2][1] = V[2];
  173. Listener->Params.Matrix[2][2] = -N[2];
  174. Listener->Params.Matrix[2][3] = 0.0f;
  175. Listener->Params.Matrix[3][0] = 0.0f;
  176. Listener->Params.Matrix[3][1] = 0.0f;
  177. Listener->Params.Matrix[3][2] = 0.0f;
  178. Listener->Params.Matrix[3][3] = 1.0f;
  179. P[0] = Listener->Position[0];
  180. P[1] = Listener->Position[1];
  181. P[2] = Listener->Position[2];
  182. aluMatrixVector(P, 1.0f, Listener->Params.Matrix);
  183. Listener->Params.Matrix[3][0] = -P[0];
  184. Listener->Params.Matrix[3][1] = -P[1];
  185. Listener->Params.Matrix[3][2] = -P[2];
  186. Listener->Params.Velocity[0] = Listener->Velocity[0];
  187. Listener->Params.Velocity[1] = Listener->Velocity[1];
  188. Listener->Params.Velocity[2] = Listener->Velocity[2];
  189. aluMatrixVector(Listener->Params.Velocity, 0.0f, Listener->Params.Matrix);
  190. }
  191. ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
  192. {
  193. static const struct ChanMap MonoMap[1] = { { FrontCenter, 0.0f } };
  194. static const struct ChanMap StereoMap[2] = {
  195. { FrontLeft, DEG2RAD(-30.0f) },
  196. { FrontRight, DEG2RAD( 30.0f) }
  197. };
  198. static const struct ChanMap StereoWideMap[2] = {
  199. { FrontLeft, DEG2RAD(-90.0f) },
  200. { FrontRight, DEG2RAD( 90.0f) }
  201. };
  202. static const struct ChanMap RearMap[2] = {
  203. { BackLeft, DEG2RAD(-150.0f) },
  204. { BackRight, DEG2RAD( 150.0f) }
  205. };
  206. static const struct ChanMap QuadMap[4] = {
  207. { FrontLeft, DEG2RAD( -45.0f) },
  208. { FrontRight, DEG2RAD( 45.0f) },
  209. { BackLeft, DEG2RAD(-135.0f) },
  210. { BackRight, DEG2RAD( 135.0f) }
  211. };
  212. static const struct ChanMap X51Map[6] = {
  213. { FrontLeft, DEG2RAD( -30.0f) },
  214. { FrontRight, DEG2RAD( 30.0f) },
  215. { FrontCenter, DEG2RAD( 0.0f) },
  216. { LFE, 0.0f },
  217. { BackLeft, DEG2RAD(-110.0f) },
  218. { BackRight, DEG2RAD( 110.0f) }
  219. };
  220. static const struct ChanMap X61Map[7] = {
  221. { FrontLeft, DEG2RAD(-30.0f) },
  222. { FrontRight, DEG2RAD( 30.0f) },
  223. { FrontCenter, DEG2RAD( 0.0f) },
  224. { LFE, 0.0f },
  225. { BackCenter, DEG2RAD(180.0f) },
  226. { SideLeft, DEG2RAD(-90.0f) },
  227. { SideRight, DEG2RAD( 90.0f) }
  228. };
  229. static const struct ChanMap X71Map[8] = {
  230. { FrontLeft, DEG2RAD( -30.0f) },
  231. { FrontRight, DEG2RAD( 30.0f) },
  232. { FrontCenter, DEG2RAD( 0.0f) },
  233. { LFE, 0.0f },
  234. { BackLeft, DEG2RAD(-150.0f) },
  235. { BackRight, DEG2RAD( 150.0f) },
  236. { SideLeft, DEG2RAD( -90.0f) },
  237. { SideRight, DEG2RAD( 90.0f) }
  238. };
  239. ALCdevice *Device = ALContext->Device;
  240. ALfloat SourceVolume,ListenerGain,MinVolume,MaxVolume;
  241. ALbufferlistitem *BufferListItem;
  242. enum FmtChannels Channels;
  243. ALfloat (*SrcMatrix)[MaxChannels];
  244. ALfloat DryGain, DryGainHF;
  245. ALfloat WetGain[MAX_SENDS];
  246. ALfloat WetGainHF[MAX_SENDS];
  247. ALint NumSends, Frequency;
  248. const struct ChanMap *chans = NULL;
  249. enum Resampler Resampler;
  250. ALint num_channels = 0;
  251. ALboolean DirectChannels;
  252. ALfloat hwidth = 0.0f;
  253. ALfloat Pitch;
  254. ALint i, c;
  255. /* Get device properties */
  256. NumSends = Device->NumAuxSends;
  257. Frequency = Device->Frequency;
  258. /* Get listener properties */
  259. ListenerGain = ALContext->Listener->Gain;
  260. /* Get source properties */
  261. SourceVolume = ALSource->Gain;
  262. MinVolume = ALSource->MinGain;
  263. MaxVolume = ALSource->MaxGain;
  264. Pitch = ALSource->Pitch;
  265. Resampler = ALSource->Resampler;
  266. DirectChannels = ALSource->DirectChannels;
  267. /* Calculate the stepping value */
  268. Channels = FmtMono;
  269. BufferListItem = ALSource->queue;
  270. while(BufferListItem != NULL)
  271. {
  272. ALbuffer *ALBuffer;
  273. if((ALBuffer=BufferListItem->buffer) != NULL)
  274. {
  275. Pitch = Pitch * ALBuffer->Frequency / Frequency;
  276. if(Pitch > 10.0f)
  277. ALSource->Params.Step = 10<<FRACTIONBITS;
  278. else
  279. {
  280. ALSource->Params.Step = fastf2i(Pitch*FRACTIONONE);
  281. if(ALSource->Params.Step == 0)
  282. ALSource->Params.Step = 1;
  283. }
  284. ALSource->Params.Resample = SelectResampler(Resampler, ALSource->Params.Step);
  285. Channels = ALBuffer->FmtChannels;
  286. break;
  287. }
  288. BufferListItem = BufferListItem->next;
  289. }
  290. if(!DirectChannels && Device->Hrtf)
  291. ALSource->Params.DryMix = SelectHrtfMixer();
  292. else
  293. ALSource->Params.DryMix = SelectDirectMixer();
  294. ALSource->Params.WetMix = SelectSendMixer();
  295. /* Calculate gains */
  296. DryGain = clampf(SourceVolume, MinVolume, MaxVolume);
  297. DryGain *= ALSource->DirectGain * ListenerGain;
  298. DryGainHF = ALSource->DirectGainHF;
  299. for(i = 0;i < NumSends;i++)
  300. {
  301. WetGain[i] = clampf(SourceVolume, MinVolume, MaxVolume);
  302. WetGain[i] *= ALSource->Send[i].Gain * ListenerGain;
  303. WetGainHF[i] = ALSource->Send[i].GainHF;
  304. }
  305. SrcMatrix = ALSource->Params.Direct.Gains;
  306. for(i = 0;i < MAX_INPUT_CHANNELS;i++)
  307. {
  308. for(c = 0;c < MaxChannels;c++)
  309. SrcMatrix[i][c] = 0.0f;
  310. }
  311. switch(Channels)
  312. {
  313. case FmtMono:
  314. chans = MonoMap;
  315. num_channels = 1;
  316. break;
  317. case FmtStereo:
  318. if(!(Device->Flags&DEVICE_WIDE_STEREO))
  319. {
  320. /* HACK: Place the stereo channels at +/-90 degrees when using non-
  321. * HRTF stereo output. This helps reduce the "monoization" caused
  322. * by them panning towards the center. */
  323. if(Device->FmtChans == DevFmtStereo && !Device->Hrtf)
  324. chans = StereoWideMap;
  325. else
  326. chans = StereoMap;
  327. }
  328. else
  329. {
  330. chans = StereoWideMap;
  331. hwidth = DEG2RAD(60.0f);
  332. }
  333. num_channels = 2;
  334. break;
  335. case FmtRear:
  336. chans = RearMap;
  337. num_channels = 2;
  338. break;
  339. case FmtQuad:
  340. chans = QuadMap;
  341. num_channels = 4;
  342. break;
  343. case FmtX51:
  344. chans = X51Map;
  345. num_channels = 6;
  346. break;
  347. case FmtX61:
  348. chans = X61Map;
  349. num_channels = 7;
  350. break;
  351. case FmtX71:
  352. chans = X71Map;
  353. num_channels = 8;
  354. break;
  355. }
  356. if(DirectChannels != AL_FALSE)
  357. {
  358. for(c = 0;c < num_channels;c++)
  359. {
  360. for(i = 0;i < (ALint)Device->NumChan;i++)
  361. {
  362. enum Channel chan = Device->Speaker2Chan[i];
  363. if(chan == chans[c].channel)
  364. {
  365. SrcMatrix[c][chan] = DryGain;
  366. break;
  367. }
  368. }
  369. }
  370. }
  371. else if(Device->Hrtf)
  372. {
  373. for(c = 0;c < num_channels;c++)
  374. {
  375. if(chans[c].channel == LFE)
  376. {
  377. /* Skip LFE */
  378. ALSource->Params.Direct.Hrtf.Params.Delay[c][0] = 0;
  379. ALSource->Params.Direct.Hrtf.Params.Delay[c][1] = 0;
  380. for(i = 0;i < HRIR_LENGTH;i++)
  381. {
  382. ALSource->Params.Direct.Hrtf.Params.Coeffs[c][i][0] = 0.0f;
  383. ALSource->Params.Direct.Hrtf.Params.Coeffs[c][i][1] = 0.0f;
  384. }
  385. }
  386. else
  387. {
  388. /* Get the static HRIR coefficients and delays for this
  389. * channel. */
  390. GetLerpedHrtfCoeffs(Device->Hrtf,
  391. 0.0f, chans[c].angle, DryGain,
  392. ALSource->Params.Direct.Hrtf.Params.Coeffs[c],
  393. ALSource->Params.Direct.Hrtf.Params.Delay[c]);
  394. }
  395. }
  396. ALSource->Hrtf.Counter = 0;
  397. ALSource->Params.Direct.Hrtf.Params.IrSize = GetHrtfIrSize(Device->Hrtf);
  398. ALSource->Params.Direct.Hrtf.State = &ALSource->Hrtf;
  399. }
  400. else
  401. {
  402. DryGain *= lerp(1.0f, 1.0f/sqrtf((float)Device->NumChan), hwidth/F_PI);
  403. for(c = 0;c < num_channels;c++)
  404. {
  405. /* Special-case LFE */
  406. if(chans[c].channel == LFE)
  407. {
  408. SrcMatrix[c][chans[c].channel] = DryGain;
  409. continue;
  410. }
  411. ComputeAngleGains(Device, chans[c].angle, hwidth, DryGain,
  412. SrcMatrix[c]);
  413. }
  414. }
  415. ALSource->Params.Direct.OutBuffer = Device->DryBuffer;
  416. ALSource->Params.Direct.ClickRemoval = Device->ClickRemoval;
  417. ALSource->Params.Direct.PendingClicks = Device->PendingClicks;
  418. for(i = 0;i < NumSends;i++)
  419. {
  420. ALeffectslot *Slot = ALSource->Send[i].Slot;
  421. if(!Slot && i == 0)
  422. Slot = Device->DefaultSlot;
  423. if(!Slot || Slot->EffectType == AL_EFFECT_NULL)
  424. {
  425. ALSource->Params.Send[i].OutBuffer = NULL;
  426. ALSource->Params.Send[i].ClickRemoval = NULL;
  427. ALSource->Params.Send[i].PendingClicks = NULL;
  428. }
  429. else
  430. {
  431. ALSource->Params.Send[i].OutBuffer = Slot->WetBuffer;
  432. ALSource->Params.Send[i].ClickRemoval = Slot->ClickRemoval;
  433. ALSource->Params.Send[i].PendingClicks = Slot->PendingClicks;
  434. }
  435. ALSource->Params.Send[i].Gain = WetGain[i];
  436. }
  437. {
  438. ALfloat gain = maxf(0.01f, DryGainHF);
  439. for(c = 0;c < num_channels;c++)
  440. ALfilterState_setParams(&ALSource->Params.Direct.LpFilter[c],
  441. ALfilterType_HighShelf, gain,
  442. (ALfloat)LOWPASSFREQREF/Frequency, 0.0f);
  443. }
  444. for(i = 0;i < NumSends;i++)
  445. {
  446. ALfloat gain = maxf(0.01f, WetGainHF[i]);
  447. for(c = 0;c < num_channels;c++)
  448. ALfilterState_setParams(&ALSource->Params.Send[i].LpFilter[c],
  449. ALfilterType_HighShelf, gain,
  450. (ALfloat)LOWPASSFREQREF/Frequency, 0.0f);
  451. }
  452. }
  453. ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
  454. {
  455. ALCdevice *Device = ALContext->Device;
  456. ALfloat Velocity[3],Direction[3],Position[3],SourceToListener[3];
  457. ALfloat InnerAngle,OuterAngle,Angle,Distance,ClampedDist;
  458. ALfloat MinVolume,MaxVolume,MinDist,MaxDist,Rolloff;
  459. ALfloat ConeVolume,ConeHF,SourceVolume,ListenerGain;
  460. ALfloat DopplerFactor, SpeedOfSound;
  461. ALfloat AirAbsorptionFactor;
  462. ALfloat RoomAirAbsorption[MAX_SENDS];
  463. ALbufferlistitem *BufferListItem;
  464. ALfloat Attenuation;
  465. ALfloat RoomAttenuation[MAX_SENDS];
  466. ALfloat MetersPerUnit;
  467. ALfloat RoomRolloffBase;
  468. ALfloat RoomRolloff[MAX_SENDS];
  469. ALfloat DecayDistance[MAX_SENDS];
  470. ALfloat DryGain;
  471. ALfloat DryGainHF;
  472. ALboolean DryGainHFAuto;
  473. ALfloat WetGain[MAX_SENDS];
  474. ALfloat WetGainHF[MAX_SENDS];
  475. ALboolean WetGainAuto;
  476. ALboolean WetGainHFAuto;
  477. enum Resampler Resampler;
  478. ALfloat Pitch;
  479. ALuint Frequency;
  480. ALint NumSends;
  481. ALint i, j;
  482. DryGainHF = 1.0f;
  483. for(i = 0;i < MAX_SENDS;i++)
  484. WetGainHF[i] = 1.0f;
  485. /* Get context/device properties */
  486. DopplerFactor = ALContext->DopplerFactor * ALSource->DopplerFactor;
  487. SpeedOfSound = ALContext->SpeedOfSound * ALContext->DopplerVelocity;
  488. NumSends = Device->NumAuxSends;
  489. Frequency = Device->Frequency;
  490. /* Get listener properties */
  491. ListenerGain = ALContext->Listener->Gain;
  492. MetersPerUnit = ALContext->Listener->MetersPerUnit;
  493. /* Get source properties */
  494. SourceVolume = ALSource->Gain;
  495. MinVolume = ALSource->MinGain;
  496. MaxVolume = ALSource->MaxGain;
  497. Pitch = ALSource->Pitch;
  498. Resampler = ALSource->Resampler;
  499. Position[0] = ALSource->Position[0];
  500. Position[1] = ALSource->Position[1];
  501. Position[2] = ALSource->Position[2];
  502. Direction[0] = ALSource->Orientation[0];
  503. Direction[1] = ALSource->Orientation[1];
  504. Direction[2] = ALSource->Orientation[2];
  505. Velocity[0] = ALSource->Velocity[0];
  506. Velocity[1] = ALSource->Velocity[1];
  507. Velocity[2] = ALSource->Velocity[2];
  508. MinDist = ALSource->RefDistance;
  509. MaxDist = ALSource->MaxDistance;
  510. Rolloff = ALSource->RollOffFactor;
  511. InnerAngle = ALSource->InnerAngle;
  512. OuterAngle = ALSource->OuterAngle;
  513. AirAbsorptionFactor = ALSource->AirAbsorptionFactor;
  514. DryGainHFAuto = ALSource->DryGainHFAuto;
  515. WetGainAuto = ALSource->WetGainAuto;
  516. WetGainHFAuto = ALSource->WetGainHFAuto;
  517. RoomRolloffBase = ALSource->RoomRolloffFactor;
  518. ALSource->Params.Direct.OutBuffer = Device->DryBuffer;
  519. ALSource->Params.Direct.ClickRemoval = Device->ClickRemoval;
  520. ALSource->Params.Direct.PendingClicks = Device->PendingClicks;
  521. for(i = 0;i < NumSends;i++)
  522. {
  523. ALeffectslot *Slot = ALSource->Send[i].Slot;
  524. if(!Slot && i == 0)
  525. Slot = Device->DefaultSlot;
  526. if(!Slot || Slot->EffectType == AL_EFFECT_NULL)
  527. {
  528. Slot = NULL;
  529. RoomRolloff[i] = 0.0f;
  530. DecayDistance[i] = 0.0f;
  531. RoomAirAbsorption[i] = 1.0f;
  532. }
  533. else if(Slot->AuxSendAuto)
  534. {
  535. RoomRolloff[i] = RoomRolloffBase;
  536. if(IsReverbEffect(Slot->EffectType))
  537. {
  538. RoomRolloff[i] += Slot->EffectProps.Reverb.RoomRolloffFactor;
  539. DecayDistance[i] = Slot->EffectProps.Reverb.DecayTime *
  540. SPEEDOFSOUNDMETRESPERSEC;
  541. RoomAirAbsorption[i] = Slot->EffectProps.Reverb.AirAbsorptionGainHF;
  542. }
  543. else
  544. {
  545. DecayDistance[i] = 0.0f;
  546. RoomAirAbsorption[i] = 1.0f;
  547. }
  548. }
  549. else
  550. {
  551. /* If the slot's auxiliary send auto is off, the data sent to the
  552. * effect slot is the same as the dry path, sans filter effects */
  553. RoomRolloff[i] = Rolloff;
  554. DecayDistance[i] = 0.0f;
  555. RoomAirAbsorption[i] = AIRABSORBGAINHF;
  556. }
  557. if(!Slot || Slot->EffectType == AL_EFFECT_NULL)
  558. {
  559. ALSource->Params.Send[i].OutBuffer = NULL;
  560. ALSource->Params.Send[i].ClickRemoval = NULL;
  561. ALSource->Params.Send[i].PendingClicks = NULL;
  562. }
  563. else
  564. {
  565. ALSource->Params.Send[i].OutBuffer = Slot->WetBuffer;
  566. ALSource->Params.Send[i].ClickRemoval = Slot->ClickRemoval;
  567. ALSource->Params.Send[i].PendingClicks = Slot->PendingClicks;
  568. }
  569. }
  570. /* Transform source to listener space (convert to head relative) */
  571. if(ALSource->HeadRelative == AL_FALSE)
  572. {
  573. ALfloat (*restrict Matrix)[4] = ALContext->Listener->Params.Matrix;
  574. /* Transform source vectors */
  575. aluMatrixVector(Position, 1.0f, Matrix);
  576. aluMatrixVector(Direction, 0.0f, Matrix);
  577. aluMatrixVector(Velocity, 0.0f, Matrix);
  578. }
  579. else
  580. {
  581. const ALfloat *ListenerVel = ALContext->Listener->Params.Velocity;
  582. /* Offset the source velocity to be relative of the listener velocity */
  583. Velocity[0] += ListenerVel[0];
  584. Velocity[1] += ListenerVel[1];
  585. Velocity[2] += ListenerVel[2];
  586. }
  587. SourceToListener[0] = -Position[0];
  588. SourceToListener[1] = -Position[1];
  589. SourceToListener[2] = -Position[2];
  590. aluNormalize(SourceToListener);
  591. aluNormalize(Direction);
  592. /* Calculate distance attenuation */
  593. Distance = sqrtf(aluDotproduct(Position, Position));
  594. ClampedDist = Distance;
  595. Attenuation = 1.0f;
  596. for(i = 0;i < NumSends;i++)
  597. RoomAttenuation[i] = 1.0f;
  598. switch(ALContext->SourceDistanceModel ? ALSource->DistanceModel :
  599. ALContext->DistanceModel)
  600. {
  601. case InverseDistanceClamped:
  602. ClampedDist = clampf(ClampedDist, MinDist, MaxDist);
  603. if(MaxDist < MinDist)
  604. break;
  605. /*fall-through*/
  606. case InverseDistance:
  607. if(MinDist > 0.0f)
  608. {
  609. if((MinDist + (Rolloff * (ClampedDist - MinDist))) > 0.0f)
  610. Attenuation = MinDist / (MinDist + (Rolloff * (ClampedDist - MinDist)));
  611. for(i = 0;i < NumSends;i++)
  612. {
  613. if((MinDist + (RoomRolloff[i] * (ClampedDist - MinDist))) > 0.0f)
  614. RoomAttenuation[i] = MinDist / (MinDist + (RoomRolloff[i] * (ClampedDist - MinDist)));
  615. }
  616. }
  617. break;
  618. case LinearDistanceClamped:
  619. ClampedDist = clampf(ClampedDist, MinDist, MaxDist);
  620. if(MaxDist < MinDist)
  621. break;
  622. /*fall-through*/
  623. case LinearDistance:
  624. if(MaxDist != MinDist)
  625. {
  626. Attenuation = 1.0f - (Rolloff*(ClampedDist-MinDist)/(MaxDist - MinDist));
  627. Attenuation = maxf(Attenuation, 0.0f);
  628. for(i = 0;i < NumSends;i++)
  629. {
  630. RoomAttenuation[i] = 1.0f - (RoomRolloff[i]*(ClampedDist-MinDist)/(MaxDist - MinDist));
  631. RoomAttenuation[i] = maxf(RoomAttenuation[i], 0.0f);
  632. }
  633. }
  634. break;
  635. case ExponentDistanceClamped:
  636. ClampedDist = clampf(ClampedDist, MinDist, MaxDist);
  637. if(MaxDist < MinDist)
  638. break;
  639. /*fall-through*/
  640. case ExponentDistance:
  641. if(ClampedDist > 0.0f && MinDist > 0.0f)
  642. {
  643. Attenuation = powf(ClampedDist/MinDist, -Rolloff);
  644. for(i = 0;i < NumSends;i++)
  645. RoomAttenuation[i] = powf(ClampedDist/MinDist, -RoomRolloff[i]);
  646. }
  647. break;
  648. case DisableDistance:
  649. ClampedDist = MinDist;
  650. break;
  651. }
  652. /* Source Gain + Attenuation */
  653. DryGain = SourceVolume * Attenuation;
  654. for(i = 0;i < NumSends;i++)
  655. WetGain[i] = SourceVolume * RoomAttenuation[i];
  656. /* Distance-based air absorption */
  657. if(AirAbsorptionFactor > 0.0f && ClampedDist > MinDist)
  658. {
  659. ALfloat meters = maxf(ClampedDist-MinDist, 0.0f) * MetersPerUnit;
  660. DryGainHF *= powf(AIRABSORBGAINHF, AirAbsorptionFactor*meters);
  661. for(i = 0;i < NumSends;i++)
  662. WetGainHF[i] *= powf(RoomAirAbsorption[i], AirAbsorptionFactor*meters);
  663. }
  664. if(WetGainAuto)
  665. {
  666. ALfloat ApparentDist = 1.0f/maxf(Attenuation, 0.00001f) - 1.0f;
  667. /* Apply a decay-time transformation to the wet path, based on the
  668. * attenuation of the dry path.
  669. *
  670. * Using the apparent distance, based on the distance attenuation, the
  671. * initial decay of the reverb effect is calculated and applied to the
  672. * wet path.
  673. */
  674. for(i = 0;i < NumSends;i++)
  675. {
  676. if(DecayDistance[i] > 0.0f)
  677. WetGain[i] *= powf(0.001f/*-60dB*/, ApparentDist/DecayDistance[i]);
  678. }
  679. }
  680. /* Calculate directional soundcones */
  681. Angle = RAD2DEG(acosf(aluDotproduct(Direction,SourceToListener)) * ConeScale) * 2.0f;
  682. if(Angle > InnerAngle && Angle <= OuterAngle)
  683. {
  684. ALfloat scale = (Angle-InnerAngle) / (OuterAngle-InnerAngle);
  685. ConeVolume = lerp(1.0f, ALSource->OuterGain, scale);
  686. ConeHF = lerp(1.0f, ALSource->OuterGainHF, scale);
  687. }
  688. else if(Angle > OuterAngle)
  689. {
  690. ConeVolume = ALSource->OuterGain;
  691. ConeHF = ALSource->OuterGainHF;
  692. }
  693. else
  694. {
  695. ConeVolume = 1.0f;
  696. ConeHF = 1.0f;
  697. }
  698. DryGain *= ConeVolume;
  699. if(WetGainAuto)
  700. {
  701. for(i = 0;i < NumSends;i++)
  702. WetGain[i] *= ConeVolume;
  703. }
  704. if(DryGainHFAuto)
  705. DryGainHF *= ConeHF;
  706. if(WetGainHFAuto)
  707. {
  708. for(i = 0;i < NumSends;i++)
  709. WetGainHF[i] *= ConeHF;
  710. }
  711. /* Clamp to Min/Max Gain */
  712. DryGain = clampf(DryGain, MinVolume, MaxVolume);
  713. for(i = 0;i < NumSends;i++)
  714. WetGain[i] = clampf(WetGain[i], MinVolume, MaxVolume);
  715. /* Apply gain and frequency filters */
  716. DryGain *= ALSource->DirectGain * ListenerGain;
  717. DryGainHF *= ALSource->DirectGainHF;
  718. for(i = 0;i < NumSends;i++)
  719. {
  720. WetGain[i] *= ALSource->Send[i].Gain * ListenerGain;
  721. WetGainHF[i] *= ALSource->Send[i].GainHF;
  722. }
  723. /* Calculate velocity-based doppler effect */
  724. if(DopplerFactor > 0.0f)
  725. {
  726. const ALfloat *ListenerVel = ALContext->Listener->Params.Velocity;
  727. ALfloat VSS, VLS;
  728. if(SpeedOfSound < 1.0f)
  729. {
  730. DopplerFactor *= 1.0f/SpeedOfSound;
  731. SpeedOfSound = 1.0f;
  732. }
  733. VSS = aluDotproduct(Velocity, SourceToListener) * DopplerFactor;
  734. VLS = aluDotproduct(ListenerVel, SourceToListener) * DopplerFactor;
  735. Pitch *= clampf(SpeedOfSound-VLS, 1.0f, SpeedOfSound*2.0f - 1.0f) /
  736. clampf(SpeedOfSound-VSS, 1.0f, SpeedOfSound*2.0f - 1.0f);
  737. }
  738. BufferListItem = ALSource->queue;
  739. while(BufferListItem != NULL)
  740. {
  741. ALbuffer *ALBuffer;
  742. if((ALBuffer=BufferListItem->buffer) != NULL)
  743. {
  744. /* Calculate fixed-point stepping value, based on the pitch, buffer
  745. * frequency, and output frequency. */
  746. Pitch = Pitch * ALBuffer->Frequency / Frequency;
  747. if(Pitch > 10.0f)
  748. ALSource->Params.Step = 10<<FRACTIONBITS;
  749. else
  750. {
  751. ALSource->Params.Step = fastf2i(Pitch*FRACTIONONE);
  752. if(ALSource->Params.Step == 0)
  753. ALSource->Params.Step = 1;
  754. }
  755. ALSource->Params.Resample = SelectResampler(Resampler, ALSource->Params.Step);
  756. break;
  757. }
  758. BufferListItem = BufferListItem->next;
  759. }
  760. if(Device->Hrtf)
  761. ALSource->Params.DryMix = SelectHrtfMixer();
  762. else
  763. ALSource->Params.DryMix = SelectDirectMixer();
  764. ALSource->Params.WetMix = SelectSendMixer();
  765. if(Device->Hrtf)
  766. {
  767. /* Use a binaural HRTF algorithm for stereo headphone playback */
  768. ALfloat delta, ev = 0.0f, az = 0.0f;
  769. if(Distance > FLT_EPSILON)
  770. {
  771. ALfloat invlen = 1.0f/Distance;
  772. Position[0] *= invlen;
  773. Position[1] *= invlen;
  774. Position[2] *= invlen;
  775. /* Calculate elevation and azimuth only when the source is not at
  776. * the listener. This prevents +0 and -0 Z from producing
  777. * inconsistent panning. Also, clamp Y in case FP precision errors
  778. * cause it to land outside of -1..+1. */
  779. ev = asinf(clampf(Position[1], -1.0f, 1.0f));
  780. az = atan2f(Position[0], -Position[2]*ZScale);
  781. }
  782. /* Check to see if the HRIR is already moving. */
  783. if(ALSource->Hrtf.Moving)
  784. {
  785. /* Calculate the normalized HRTF transition factor (delta). */
  786. delta = CalcHrtfDelta(ALSource->Params.Direct.Hrtf.Params.Gain, DryGain,
  787. ALSource->Params.Direct.Hrtf.Params.Dir, Position);
  788. /* If the delta is large enough, get the moving HRIR target
  789. * coefficients, target delays, steppping values, and counter. */
  790. if(delta > 0.001f)
  791. {
  792. ALSource->Hrtf.Counter = GetMovingHrtfCoeffs(Device->Hrtf,
  793. ev, az, DryGain, delta,
  794. ALSource->Hrtf.Counter,
  795. ALSource->Params.Direct.Hrtf.Params.Coeffs[0],
  796. ALSource->Params.Direct.Hrtf.Params.Delay[0],
  797. ALSource->Params.Direct.Hrtf.Params.CoeffStep,
  798. ALSource->Params.Direct.Hrtf.Params.DelayStep);
  799. ALSource->Params.Direct.Hrtf.Params.Gain = DryGain;
  800. ALSource->Params.Direct.Hrtf.Params.Dir[0] = Position[0];
  801. ALSource->Params.Direct.Hrtf.Params.Dir[1] = Position[1];
  802. ALSource->Params.Direct.Hrtf.Params.Dir[2] = Position[2];
  803. }
  804. }
  805. else
  806. {
  807. /* Get the initial (static) HRIR coefficients and delays. */
  808. GetLerpedHrtfCoeffs(Device->Hrtf, ev, az, DryGain,
  809. ALSource->Params.Direct.Hrtf.Params.Coeffs[0],
  810. ALSource->Params.Direct.Hrtf.Params.Delay[0]);
  811. ALSource->Hrtf.Counter = 0;
  812. ALSource->Hrtf.Moving = AL_TRUE;
  813. ALSource->Params.Direct.Hrtf.Params.Gain = DryGain;
  814. ALSource->Params.Direct.Hrtf.Params.Dir[0] = Position[0];
  815. ALSource->Params.Direct.Hrtf.Params.Dir[1] = Position[1];
  816. ALSource->Params.Direct.Hrtf.Params.Dir[2] = Position[2];
  817. }
  818. ALSource->Params.Direct.Hrtf.Params.IrSize = GetHrtfIrSize(Device->Hrtf);
  819. ALSource->Params.Direct.Hrtf.State = &ALSource->Hrtf;
  820. }
  821. else
  822. {
  823. ALfloat (*Matrix)[MaxChannels] = ALSource->Params.Direct.Gains;
  824. ALfloat DirGain = 0.0f;
  825. ALfloat AmbientGain;
  826. for(i = 0;i < MAX_INPUT_CHANNELS;i++)
  827. {
  828. for(j = 0;j < MaxChannels;j++)
  829. Matrix[i][j] = 0.0f;
  830. }
  831. /* Normalize the length, and compute panned gains. */
  832. if(Distance > FLT_EPSILON)
  833. {
  834. ALfloat invlen = 1.0f/Distance;
  835. Position[0] *= invlen;
  836. Position[1] *= invlen;
  837. Position[2] *= invlen;
  838. DirGain = sqrtf(Position[0]*Position[0] + Position[2]*Position[2]);
  839. ComputeAngleGains(Device, atan2f(Position[0], -Position[2]*ZScale), 0.0f,
  840. DryGain*DirGain, Matrix[0]);
  841. }
  842. /* Adjustment for vertical offsets. Not the greatest, but simple
  843. * enough. */
  844. AmbientGain = DryGain * sqrtf(1.0f/Device->NumChan) * (1.0f-DirGain);
  845. for(i = 0;i < (ALint)Device->NumChan;i++)
  846. {
  847. enum Channel chan = Device->Speaker2Chan[i];
  848. Matrix[0][chan] = maxf(Matrix[0][chan], AmbientGain);
  849. }
  850. }
  851. for(i = 0;i < NumSends;i++)
  852. ALSource->Params.Send[i].Gain = WetGain[i];
  853. {
  854. ALfloat gain = maxf(0.01f, DryGainHF);
  855. ALfilterState_setParams(&ALSource->Params.Direct.LpFilter[0],
  856. ALfilterType_HighShelf, gain,
  857. (ALfloat)LOWPASSFREQREF/Frequency, 0.0f);
  858. }
  859. for(i = 0;i < NumSends;i++)
  860. {
  861. ALfloat gain = maxf(0.01f, WetGainHF[i]);
  862. ALfilterState_setParams(&ALSource->Params.Send[i].LpFilter[0],
  863. ALfilterType_HighShelf, gain,
  864. (ALfloat)LOWPASSFREQREF/Frequency, 0.0f);
  865. }
  866. }
  867. static inline ALint aluF2I25(ALfloat val)
  868. {
  869. /* Clamp the value between -1 and +1. This handles that with only a single branch. */
  870. if(fabsf(val) > 1.0f)
  871. val = (ALfloat)((0.0f < val) - (val < 0.0f));
  872. /* Convert to a signed integer, between -16777215 and +16777215. */
  873. return fastf2i(val*16777215.0f);
  874. }
  875. static inline ALfloat aluF2F(ALfloat val)
  876. { return val; }
  877. static inline ALint aluF2I(ALfloat val)
  878. { return aluF2I25(val)<<7; }
  879. static inline ALuint aluF2UI(ALfloat val)
  880. { return aluF2I(val)+2147483648u; }
  881. static inline ALshort aluF2S(ALfloat val)
  882. { return aluF2I25(val)>>9; }
  883. static inline ALushort aluF2US(ALfloat val)
  884. { return aluF2S(val)+32768; }
  885. static inline ALbyte aluF2B(ALfloat val)
  886. { return aluF2I25(val)>>17; }
  887. static inline ALubyte aluF2UB(ALfloat val)
  888. { return aluF2B(val)+128; }
  889. #define DECL_TEMPLATE(T, func) \
  890. static int Write_##T(ALCdevice *device, T *restrict buffer, \
  891. ALuint SamplesToDo) \
  892. { \
  893. ALfloat (*restrict DryBuffer)[BUFFERSIZE] = device->DryBuffer; \
  894. ALuint numchans = ChannelsFromDevFmt(device->FmtChans); \
  895. const ALuint *offsets = device->ChannelOffsets; \
  896. ALuint i, j; \
  897. \
  898. for(j = 0;j < MaxChannels;j++) \
  899. { \
  900. T *restrict out; \
  901. \
  902. if(offsets[j] == INVALID_OFFSET) \
  903. continue; \
  904. \
  905. out = buffer + offsets[j]; \
  906. for(i = 0;i < SamplesToDo;i++) \
  907. out[i*numchans] = func(DryBuffer[j][i]); \
  908. } \
  909. return SamplesToDo*numchans*sizeof(T); \
  910. }
  911. DECL_TEMPLATE(ALfloat, aluF2F)
  912. DECL_TEMPLATE(ALuint, aluF2UI)
  913. DECL_TEMPLATE(ALint, aluF2I)
  914. DECL_TEMPLATE(ALushort, aluF2US)
  915. DECL_TEMPLATE(ALshort, aluF2S)
  916. DECL_TEMPLATE(ALubyte, aluF2UB)
  917. DECL_TEMPLATE(ALbyte, aluF2B)
  918. #undef DECL_TEMPLATE
  919. ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
  920. {
  921. ALuint SamplesToDo;
  922. ALeffectslot **slot, **slot_end;
  923. ALsource **src, **src_end;
  924. ALCcontext *ctx;
  925. FPUCtl oldMode;
  926. ALuint i, c;
  927. SetMixerFPUMode(&oldMode);
  928. while(size > 0)
  929. {
  930. SamplesToDo = minu(size, BUFFERSIZE);
  931. for(c = 0;c < MaxChannels;c++)
  932. memset(device->DryBuffer[c], 0, SamplesToDo*sizeof(ALfloat));
  933. ALCdevice_Lock(device);
  934. V(device->Synth,process)(SamplesToDo, device->DryBuffer);
  935. ctx = device->ContextList;
  936. while(ctx)
  937. {
  938. ALenum DeferUpdates = ctx->DeferUpdates;
  939. ALenum UpdateSources = AL_FALSE;
  940. if(!DeferUpdates)
  941. UpdateSources = ExchangeInt(&ctx->UpdateSources, AL_FALSE);
  942. if(UpdateSources)
  943. CalcListenerParams(ctx->Listener);
  944. /* source processing */
  945. src = ctx->ActiveSources;
  946. src_end = src + ctx->ActiveSourceCount;
  947. while(src != src_end)
  948. {
  949. if((*src)->state != AL_PLAYING)
  950. {
  951. --(ctx->ActiveSourceCount);
  952. *src = *(--src_end);
  953. continue;
  954. }
  955. if(!DeferUpdates && (ExchangeInt(&(*src)->NeedsUpdate, AL_FALSE) ||
  956. UpdateSources))
  957. ALsource_Update(*src, ctx);
  958. MixSource(*src, device, SamplesToDo);
  959. src++;
  960. }
  961. /* effect slot processing */
  962. slot = ctx->ActiveEffectSlots;
  963. slot_end = slot + ctx->ActiveEffectSlotCount;
  964. while(slot != slot_end)
  965. {
  966. ALfloat offset = (*slot)->ClickRemoval[0];
  967. if(offset < (1.0f/32768.0f))
  968. offset = 0.0f;
  969. else for(i = 0;i < SamplesToDo;i++)
  970. {
  971. (*slot)->WetBuffer[0][i] += offset;
  972. offset -= offset * (1.0f/256.0f);
  973. }
  974. (*slot)->ClickRemoval[0] = offset + (*slot)->PendingClicks[0];
  975. (*slot)->PendingClicks[0] = 0.0f;
  976. if(!DeferUpdates && ExchangeInt(&(*slot)->NeedsUpdate, AL_FALSE))
  977. V((*slot)->EffectState,update)(device, *slot);
  978. V((*slot)->EffectState,process)(SamplesToDo, (*slot)->WetBuffer[0],
  979. device->DryBuffer);
  980. for(i = 0;i < SamplesToDo;i++)
  981. (*slot)->WetBuffer[0][i] = 0.0f;
  982. slot++;
  983. }
  984. ctx = ctx->next;
  985. }
  986. slot = &device->DefaultSlot;
  987. if(*slot != NULL)
  988. {
  989. ALfloat offset = (*slot)->ClickRemoval[0];
  990. if(offset < (1.0f/32768.0f))
  991. offset = 0.0f;
  992. else for(i = 0;i < SamplesToDo;i++)
  993. {
  994. (*slot)->WetBuffer[0][i] += offset;
  995. offset -= offset * (1.0f/256.0f);
  996. }
  997. (*slot)->ClickRemoval[0] = offset + (*slot)->PendingClicks[0];
  998. (*slot)->PendingClicks[0] = 0.0f;
  999. if(ExchangeInt(&(*slot)->NeedsUpdate, AL_FALSE))
  1000. V((*slot)->EffectState,update)(device, *slot);
  1001. V((*slot)->EffectState,process)(SamplesToDo, (*slot)->WetBuffer[0],
  1002. device->DryBuffer);
  1003. for(i = 0;i < SamplesToDo;i++)
  1004. (*slot)->WetBuffer[0][i] = 0.0f;
  1005. }
  1006. ALCdevice_Unlock(device);
  1007. /* Click-removal. Could do better; this only really handles immediate
  1008. * changes between updates where a predictive sample could be
  1009. * generated. Delays caused by effects and HRTF aren't caught. */
  1010. if(device->FmtChans == DevFmtMono)
  1011. {
  1012. ALfloat offset = device->ClickRemoval[FrontCenter];
  1013. if(offset < (1.0f/32768.0f))
  1014. offset = 0.0f;
  1015. else for(i = 0;i < SamplesToDo;i++)
  1016. {
  1017. device->DryBuffer[FrontCenter][i] += offset;
  1018. offset -= offset * (1.0f/256.0f);
  1019. }
  1020. device->ClickRemoval[FrontCenter] = offset + device->PendingClicks[FrontCenter];
  1021. device->PendingClicks[FrontCenter] = 0.0f;
  1022. }
  1023. else if(device->FmtChans == DevFmtStereo)
  1024. {
  1025. /* Assumes the first two channels are FrontLeft and FrontRight */
  1026. for(c = 0;c < 2;c++)
  1027. {
  1028. ALfloat offset = device->ClickRemoval[c];
  1029. if(offset < (1.0f/32768.0f))
  1030. offset = 0.0f;
  1031. else for(i = 0;i < SamplesToDo;i++)
  1032. {
  1033. device->DryBuffer[c][i] += offset;
  1034. offset -= offset * (1.0f/256.0f);
  1035. }
  1036. device->ClickRemoval[c] = offset + device->PendingClicks[c];
  1037. device->PendingClicks[c] = 0.0f;
  1038. }
  1039. if(device->Bs2b)
  1040. {
  1041. float samples[2];
  1042. for(i = 0;i < SamplesToDo;i++)
  1043. {
  1044. samples[0] = device->DryBuffer[FrontLeft][i];
  1045. samples[1] = device->DryBuffer[FrontRight][i];
  1046. bs2b_cross_feed(device->Bs2b, samples);
  1047. device->DryBuffer[FrontLeft][i] = samples[0];
  1048. device->DryBuffer[FrontRight][i] = samples[1];
  1049. }
  1050. }
  1051. }
  1052. else
  1053. {
  1054. for(c = 0;c < MaxChannels;c++)
  1055. {
  1056. ALfloat offset = device->ClickRemoval[c];
  1057. if(offset < (1.0f/32768.0f))
  1058. offset = 0.0f;
  1059. else for(i = 0;i < SamplesToDo;i++)
  1060. {
  1061. device->DryBuffer[c][i] += offset;
  1062. offset -= offset * (1.0f/256.0f);
  1063. }
  1064. device->ClickRemoval[c] = offset + device->PendingClicks[c];
  1065. device->PendingClicks[c] = 0.0f;
  1066. }
  1067. }
  1068. if(buffer)
  1069. {
  1070. int bytes = 0;
  1071. switch(device->FmtType)
  1072. {
  1073. case DevFmtByte:
  1074. bytes = Write_ALbyte(device, buffer, SamplesToDo);
  1075. break;
  1076. case DevFmtUByte:
  1077. bytes = Write_ALubyte(device, buffer, SamplesToDo);
  1078. break;
  1079. case DevFmtShort:
  1080. bytes = Write_ALshort(device, buffer, SamplesToDo);
  1081. break;
  1082. case DevFmtUShort:
  1083. bytes = Write_ALushort(device, buffer, SamplesToDo);
  1084. break;
  1085. case DevFmtInt:
  1086. bytes = Write_ALint(device, buffer, SamplesToDo);
  1087. break;
  1088. case DevFmtUInt:
  1089. bytes = Write_ALuint(device, buffer, SamplesToDo);
  1090. break;
  1091. case DevFmtFloat:
  1092. bytes = Write_ALfloat(device, buffer, SamplesToDo);
  1093. break;
  1094. }
  1095. buffer = (ALubyte*)buffer + bytes;
  1096. }
  1097. size -= SamplesToDo;
  1098. }
  1099. RestoreFPUMode(&oldMode);
  1100. }
  1101. ALvoid aluHandleDisconnect(ALCdevice *device)
  1102. {
  1103. ALCcontext *Context;
  1104. device->Connected = ALC_FALSE;
  1105. Context = device->ContextList;
  1106. while(Context)
  1107. {
  1108. ALsource **src, **src_end;
  1109. src = Context->ActiveSources;
  1110. src_end = src + Context->ActiveSourceCount;
  1111. while(src != src_end)
  1112. {
  1113. if((*src)->state == AL_PLAYING)
  1114. {
  1115. (*src)->state = AL_STOPPED;
  1116. (*src)->BuffersPlayed = (*src)->BuffersInQueue;
  1117. (*src)->position = 0;
  1118. (*src)->position_fraction = 0;
  1119. }
  1120. src++;
  1121. }
  1122. Context->ActiveSourceCount = 0;
  1123. Context = Context->next;
  1124. }
  1125. }