mixer.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  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 <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 "mixer_defs.h"
  35. static_assert((INT_MAX>>FRACTIONBITS)/MAX_PITCH > BUFFERSIZE,
  36. "MAX_PITCH and/or BUFFERSIZE are too large for FRACTIONBITS!");
  37. extern inline void InitiatePositionArrays(ALuint frac, ALuint increment, ALuint *frac_arr, ALuint *pos_arr, ALuint size);
  38. alignas(16) union ResamplerCoeffs ResampleCoeffs;
  39. enum Resampler {
  40. PointResampler,
  41. LinearResampler,
  42. FIR4Resampler,
  43. FIR8Resampler,
  44. BSincResampler,
  45. ResamplerDefault = LinearResampler
  46. };
  47. /* FIR8 requires 3 extra samples before the current position, and 4 after. */
  48. static_assert(MAX_PRE_SAMPLES >= 3, "MAX_PRE_SAMPLES must be at least 3!");
  49. static_assert(MAX_POST_SAMPLES >= 4, "MAX_POST_SAMPLES must be at least 4!");
  50. static HrtfMixerFunc MixHrtfSamples = MixHrtf_C;
  51. static MixerFunc MixSamples = Mix_C;
  52. static ResamplerFunc ResampleSamples = Resample_point32_C;
  53. static inline HrtfMixerFunc SelectHrtfMixer(void)
  54. {
  55. #ifdef HAVE_SSE
  56. if((CPUCapFlags&CPU_CAP_SSE))
  57. return MixHrtf_SSE;
  58. #endif
  59. #ifdef HAVE_NEON
  60. if((CPUCapFlags&CPU_CAP_NEON))
  61. return MixHrtf_Neon;
  62. #endif
  63. return MixHrtf_C;
  64. }
  65. static inline MixerFunc SelectMixer(void)
  66. {
  67. #ifdef HAVE_SSE
  68. if((CPUCapFlags&CPU_CAP_SSE))
  69. return Mix_SSE;
  70. #endif
  71. #ifdef HAVE_NEON
  72. if((CPUCapFlags&CPU_CAP_NEON))
  73. return Mix_Neon;
  74. #endif
  75. return Mix_C;
  76. }
  77. static inline ResamplerFunc SelectResampler(enum Resampler resampler)
  78. {
  79. switch(resampler)
  80. {
  81. case PointResampler:
  82. return Resample_point32_C;
  83. case LinearResampler:
  84. #ifdef HAVE_SSE4_1
  85. if((CPUCapFlags&CPU_CAP_SSE4_1))
  86. return Resample_lerp32_SSE41;
  87. #endif
  88. #ifdef HAVE_SSE2
  89. if((CPUCapFlags&CPU_CAP_SSE2))
  90. return Resample_lerp32_SSE2;
  91. #endif
  92. return Resample_lerp32_C;
  93. case FIR4Resampler:
  94. #ifdef HAVE_SSE4_1
  95. if((CPUCapFlags&CPU_CAP_SSE4_1))
  96. return Resample_fir4_32_SSE41;
  97. #endif
  98. #ifdef HAVE_SSE3
  99. if((CPUCapFlags&CPU_CAP_SSE3))
  100. return Resample_fir4_32_SSE3;
  101. #endif
  102. return Resample_fir4_32_C;
  103. case FIR8Resampler:
  104. #ifdef HAVE_SSE4_1
  105. if((CPUCapFlags&CPU_CAP_SSE4_1))
  106. return Resample_fir8_32_SSE41;
  107. #endif
  108. #ifdef HAVE_SSE3
  109. if((CPUCapFlags&CPU_CAP_SSE3))
  110. return Resample_fir8_32_SSE3;
  111. #endif
  112. return Resample_fir8_32_C;
  113. case BSincResampler:
  114. #ifdef HAVE_SSE
  115. if((CPUCapFlags&CPU_CAP_SSE))
  116. return Resample_bsinc32_SSE;
  117. #endif
  118. return Resample_bsinc32_C;
  119. }
  120. return Resample_point32_C;
  121. }
  122. /* The sinc resampler makes use of a Kaiser window to limit the needed sample
  123. * points to 4 and 8, respectively.
  124. */
  125. #ifndef M_PI
  126. #define M_PI (3.14159265358979323846)
  127. #endif
  128. static inline double Sinc(double x)
  129. {
  130. if(x == 0.0) return 1.0;
  131. return sin(x*M_PI) / (x*M_PI);
  132. }
  133. /* The zero-order modified Bessel function of the first kind, used for the
  134. * Kaiser window.
  135. *
  136. * I_0(x) = sum_{k=0}^inf (1 / k!)^2 (x / 2)^(2 k)
  137. * = sum_{k=0}^inf ((x / 2)^k / k!)^2
  138. */
  139. static double BesselI_0(double x)
  140. {
  141. double term, sum, x2, y, last_sum;
  142. int k;
  143. /* Start at k=1 since k=0 is trivial. */
  144. term = 1.0;
  145. sum = 1.0;
  146. x2 = x / 2.0;
  147. k = 1;
  148. /* Let the integration converge until the term of the sum is no longer
  149. * significant.
  150. */
  151. do {
  152. y = x2 / k;
  153. k ++;
  154. last_sum = sum;
  155. term *= y * y;
  156. sum += term;
  157. } while(sum != last_sum);
  158. return sum;
  159. }
  160. /* Calculate a Kaiser window from the given beta value and a normalized k
  161. * [-1, 1].
  162. *
  163. * w(k) = { I_0(B sqrt(1 - k^2)) / I_0(B), -1 <= k <= 1
  164. * { 0, elsewhere.
  165. *
  166. * Where k can be calculated as:
  167. *
  168. * k = i / l, where -l <= i <= l.
  169. *
  170. * or:
  171. *
  172. * k = 2 i / M - 1, where 0 <= i <= M.
  173. */
  174. static inline double Kaiser(double b, double k)
  175. {
  176. if(k <= -1.0 || k >= 1.0) return 0.0;
  177. return BesselI_0(b * sqrt(1.0 - (k*k))) / BesselI_0(b);
  178. }
  179. static inline double CalcKaiserBeta(double rejection)
  180. {
  181. if(rejection > 50.0)
  182. return 0.1102 * (rejection - 8.7);
  183. if(rejection >= 21.0)
  184. return (0.5842 * pow(rejection - 21.0, 0.4)) +
  185. (0.07886 * (rejection - 21.0));
  186. return 0.0;
  187. }
  188. static float SincKaiser(double r, double x)
  189. {
  190. /* Limit rippling to -60dB. */
  191. return (float)(Kaiser(CalcKaiserBeta(60.0), x / r) * Sinc(x));
  192. }
  193. void aluInitMixer(void)
  194. {
  195. enum Resampler resampler = ResamplerDefault;
  196. const char *str;
  197. ALuint i;
  198. if(ConfigValueStr(NULL, NULL, "resampler", &str))
  199. {
  200. if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
  201. resampler = PointResampler;
  202. else if(strcasecmp(str, "linear") == 0)
  203. resampler = LinearResampler;
  204. else if(strcasecmp(str, "sinc4") == 0)
  205. resampler = FIR4Resampler;
  206. else if(strcasecmp(str, "sinc8") == 0)
  207. resampler = FIR8Resampler;
  208. else if(strcasecmp(str, "bsinc") == 0)
  209. resampler = BSincResampler;
  210. else if(strcasecmp(str, "cubic") == 0)
  211. {
  212. WARN("Resampler option \"cubic\" is deprecated, using sinc4\n");
  213. resampler = FIR4Resampler;
  214. }
  215. else
  216. {
  217. char *end;
  218. long n = strtol(str, &end, 0);
  219. if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == FIR4Resampler))
  220. resampler = n;
  221. else
  222. WARN("Invalid resampler: %s\n", str);
  223. }
  224. }
  225. if(resampler == FIR8Resampler)
  226. for(i = 0;i < FRACTIONONE;i++)
  227. {
  228. ALdouble mu = (ALdouble)i / FRACTIONONE;
  229. ResampleCoeffs.FIR8[i][0] = SincKaiser(4.0, mu - -3.0);
  230. ResampleCoeffs.FIR8[i][1] = SincKaiser(4.0, mu - -2.0);
  231. ResampleCoeffs.FIR8[i][2] = SincKaiser(4.0, mu - -1.0);
  232. ResampleCoeffs.FIR8[i][3] = SincKaiser(4.0, mu - 0.0);
  233. ResampleCoeffs.FIR8[i][4] = SincKaiser(4.0, mu - 1.0);
  234. ResampleCoeffs.FIR8[i][5] = SincKaiser(4.0, mu - 2.0);
  235. ResampleCoeffs.FIR8[i][6] = SincKaiser(4.0, mu - 3.0);
  236. ResampleCoeffs.FIR8[i][7] = SincKaiser(4.0, mu - 4.0);
  237. }
  238. else if(resampler == FIR4Resampler)
  239. for(i = 0;i < FRACTIONONE;i++)
  240. {
  241. ALdouble mu = (ALdouble)i / FRACTIONONE;
  242. ResampleCoeffs.FIR4[i][0] = SincKaiser(2.0, mu - -1.0);
  243. ResampleCoeffs.FIR4[i][1] = SincKaiser(2.0, mu - 0.0);
  244. ResampleCoeffs.FIR4[i][2] = SincKaiser(2.0, mu - 1.0);
  245. ResampleCoeffs.FIR4[i][3] = SincKaiser(2.0, mu - 2.0);
  246. }
  247. MixHrtfSamples = SelectHrtfMixer();
  248. MixSamples = SelectMixer();
  249. ResampleSamples = SelectResampler(resampler);
  250. }
  251. static inline ALfloat Sample_ALbyte(ALbyte val)
  252. { return val * (1.0f/127.0f); }
  253. static inline ALfloat Sample_ALshort(ALshort val)
  254. { return val * (1.0f/32767.0f); }
  255. static inline ALfloat Sample_ALfloat(ALfloat val)
  256. { return val; }
  257. #define DECL_TEMPLATE(T) \
  258. static inline void Load_##T(ALfloat *dst, const T *src, ALuint srcstep, ALuint samples)\
  259. { \
  260. ALuint i; \
  261. for(i = 0;i < samples;i++) \
  262. dst[i] = Sample_##T(src[i*srcstep]); \
  263. }
  264. DECL_TEMPLATE(ALbyte)
  265. DECL_TEMPLATE(ALshort)
  266. DECL_TEMPLATE(ALfloat)
  267. #undef DECL_TEMPLATE
  268. static void LoadSamples(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum FmtType srctype, ALuint samples)
  269. {
  270. switch(srctype)
  271. {
  272. case FmtByte:
  273. Load_ALbyte(dst, src, srcstep, samples);
  274. break;
  275. case FmtShort:
  276. Load_ALshort(dst, src, srcstep, samples);
  277. break;
  278. case FmtFloat:
  279. Load_ALfloat(dst, src, srcstep, samples);
  280. break;
  281. }
  282. }
  283. static inline void SilenceSamples(ALfloat *dst, ALuint samples)
  284. {
  285. ALuint i;
  286. for(i = 0;i < samples;i++)
  287. dst[i] = 0.0f;
  288. }
  289. static const ALfloat *DoFilters(ALfilterState *lpfilter, ALfilterState *hpfilter,
  290. ALfloat *restrict dst, const ALfloat *restrict src,
  291. ALuint numsamples, enum ActiveFilters type)
  292. {
  293. ALuint i;
  294. switch(type)
  295. {
  296. case AF_None:
  297. ALfilterState_processPassthru(lpfilter, src, numsamples);
  298. ALfilterState_processPassthru(hpfilter, src, numsamples);
  299. break;
  300. case AF_LowPass:
  301. ALfilterState_process(lpfilter, dst, src, numsamples);
  302. ALfilterState_processPassthru(hpfilter, dst, numsamples);
  303. return dst;
  304. case AF_HighPass:
  305. ALfilterState_processPassthru(lpfilter, src, numsamples);
  306. ALfilterState_process(hpfilter, dst, src, numsamples);
  307. return dst;
  308. case AF_BandPass:
  309. for(i = 0;i < numsamples;)
  310. {
  311. ALfloat temp[256];
  312. ALuint todo = minu(256, numsamples-i);
  313. ALfilterState_process(lpfilter, temp, src+i, todo);
  314. ALfilterState_process(hpfilter, dst+i, temp, todo);
  315. i += todo;
  316. }
  317. return dst;
  318. }
  319. return src;
  320. }
  321. ALvoid MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
  322. {
  323. ResamplerFunc Resample;
  324. ALbufferlistitem *BufferListItem;
  325. ALuint DataPosInt, DataPosFrac;
  326. ALboolean Looping;
  327. ALuint increment;
  328. ALenum State;
  329. ALuint OutPos;
  330. ALuint NumChannels;
  331. ALuint SampleSize;
  332. ALint64 DataSize64;
  333. ALuint IrSize;
  334. ALuint chan, j;
  335. /* Get source info */
  336. State = Source->state;
  337. BufferListItem = ATOMIC_LOAD(&Source->current_buffer);
  338. DataPosInt = Source->position;
  339. DataPosFrac = Source->position_fraction;
  340. Looping = Source->Looping;
  341. NumChannels = Source->NumChannels;
  342. SampleSize = Source->SampleSize;
  343. increment = voice->Step;
  344. IrSize = (Device->Hrtf ? GetHrtfIrSize(Device->Hrtf) : 0);
  345. Resample = ((increment == FRACTIONONE && DataPosFrac == 0) ?
  346. Resample_copy32_C : ResampleSamples);
  347. OutPos = 0;
  348. do {
  349. ALuint SrcBufferSize, DstBufferSize;
  350. /* Figure out how many buffer samples will be needed */
  351. DataSize64 = SamplesToDo-OutPos;
  352. DataSize64 *= increment;
  353. DataSize64 += DataPosFrac+FRACTIONMASK;
  354. DataSize64 >>= FRACTIONBITS;
  355. DataSize64 += MAX_POST_SAMPLES+MAX_PRE_SAMPLES;
  356. SrcBufferSize = (ALuint)mini64(DataSize64, BUFFERSIZE);
  357. /* Figure out how many samples we can actually mix from this. */
  358. DataSize64 = SrcBufferSize;
  359. DataSize64 -= MAX_POST_SAMPLES+MAX_PRE_SAMPLES;
  360. DataSize64 <<= FRACTIONBITS;
  361. DataSize64 -= DataPosFrac;
  362. DstBufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
  363. DstBufferSize = minu(DstBufferSize, (SamplesToDo-OutPos));
  364. /* Some mixers like having a multiple of 4, so try to give that unless
  365. * this is the last update. */
  366. if(OutPos+DstBufferSize < SamplesToDo)
  367. DstBufferSize &= ~3;
  368. for(chan = 0;chan < NumChannels;chan++)
  369. {
  370. const ALfloat *ResampledData;
  371. ALfloat *SrcData = Device->SourceData;
  372. ALuint SrcDataSize;
  373. /* Load the previous samples into the source data first. */
  374. memcpy(SrcData, voice->PrevSamples[chan], MAX_PRE_SAMPLES*sizeof(ALfloat));
  375. SrcDataSize = MAX_PRE_SAMPLES;
  376. if(Source->SourceType == AL_STATIC)
  377. {
  378. const ALbuffer *ALBuffer = BufferListItem->buffer;
  379. const ALubyte *Data = ALBuffer->data;
  380. ALuint DataSize;
  381. ALuint pos;
  382. /* Offset buffer data to current channel */
  383. Data += chan*SampleSize;
  384. /* If current pos is beyond the loop range, do not loop */
  385. if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
  386. {
  387. Looping = AL_FALSE;
  388. /* Load what's left to play from the source buffer, and
  389. * clear the rest of the temp buffer */
  390. pos = DataPosInt;
  391. DataSize = minu(SrcBufferSize - SrcDataSize, ALBuffer->SampleLen - pos);
  392. LoadSamples(&SrcData[SrcDataSize], &Data[pos * NumChannels*SampleSize],
  393. NumChannels, ALBuffer->FmtType, DataSize);
  394. SrcDataSize += DataSize;
  395. SilenceSamples(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
  396. SrcDataSize += SrcBufferSize - SrcDataSize;
  397. }
  398. else
  399. {
  400. ALuint LoopStart = ALBuffer->LoopStart;
  401. ALuint LoopEnd = ALBuffer->LoopEnd;
  402. /* Load what's left of this loop iteration, then load
  403. * repeats of the loop section */
  404. pos = DataPosInt;
  405. DataSize = LoopEnd - pos;
  406. DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
  407. LoadSamples(&SrcData[SrcDataSize], &Data[pos * NumChannels*SampleSize],
  408. NumChannels, ALBuffer->FmtType, DataSize);
  409. SrcDataSize += DataSize;
  410. DataSize = LoopEnd-LoopStart;
  411. while(SrcBufferSize > SrcDataSize)
  412. {
  413. DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
  414. LoadSamples(&SrcData[SrcDataSize], &Data[LoopStart * NumChannels*SampleSize],
  415. NumChannels, ALBuffer->FmtType, DataSize);
  416. SrcDataSize += DataSize;
  417. }
  418. }
  419. }
  420. else
  421. {
  422. /* Crawl the buffer queue to fill in the temp buffer */
  423. ALbufferlistitem *tmpiter = BufferListItem;
  424. ALuint pos = DataPosInt;
  425. while(tmpiter && SrcBufferSize > SrcDataSize)
  426. {
  427. const ALbuffer *ALBuffer;
  428. if((ALBuffer=tmpiter->buffer) != NULL)
  429. {
  430. const ALubyte *Data = ALBuffer->data;
  431. ALuint DataSize = ALBuffer->SampleLen;
  432. /* Skip the data already played */
  433. if(DataSize <= pos)
  434. pos -= DataSize;
  435. else
  436. {
  437. Data += (pos*NumChannels + chan)*SampleSize;
  438. DataSize -= pos;
  439. pos -= pos;
  440. DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
  441. LoadSamples(&SrcData[SrcDataSize], Data, NumChannels,
  442. ALBuffer->FmtType, DataSize);
  443. SrcDataSize += DataSize;
  444. }
  445. }
  446. tmpiter = tmpiter->next;
  447. if(!tmpiter && Looping)
  448. tmpiter = ATOMIC_LOAD(&Source->queue);
  449. else if(!tmpiter)
  450. {
  451. SilenceSamples(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
  452. SrcDataSize += SrcBufferSize - SrcDataSize;
  453. }
  454. }
  455. }
  456. /* Store the last source samples used for next time. */
  457. memcpy(voice->PrevSamples[chan],
  458. &SrcData[(increment*DstBufferSize + DataPosFrac)>>FRACTIONBITS],
  459. MAX_PRE_SAMPLES*sizeof(ALfloat)
  460. );
  461. /* Now resample, then filter and mix to the appropriate outputs. */
  462. ResampledData = Resample(&voice->SincState,
  463. &SrcData[MAX_PRE_SAMPLES], DataPosFrac, increment,
  464. Device->ResampledData, DstBufferSize
  465. );
  466. {
  467. DirectParams *parms = &voice->Direct;
  468. const ALfloat *samples;
  469. samples = DoFilters(
  470. &parms->Filters[chan].LowPass, &parms->Filters[chan].HighPass,
  471. Device->FilteredData, ResampledData, DstBufferSize,
  472. parms->Filters[chan].ActiveType
  473. );
  474. if(!voice->IsHrtf)
  475. MixSamples(samples, parms->OutChannels, parms->OutBuffer, parms->Gains[chan],
  476. parms->Counter, OutPos, DstBufferSize);
  477. else
  478. MixHrtfSamples(parms->OutBuffer, samples, parms->Counter, voice->Offset,
  479. OutPos, IrSize, &parms->Hrtf[chan].Params,
  480. &parms->Hrtf[chan].State, DstBufferSize);
  481. }
  482. for(j = 0;j < Device->NumAuxSends;j++)
  483. {
  484. SendParams *parms = &voice->Send[j];
  485. const ALfloat *samples;
  486. if(!parms->OutBuffer)
  487. continue;
  488. samples = DoFilters(
  489. &parms->Filters[chan].LowPass, &parms->Filters[chan].HighPass,
  490. Device->FilteredData, ResampledData, DstBufferSize,
  491. parms->Filters[chan].ActiveType
  492. );
  493. MixSamples(samples, 1, parms->OutBuffer, &parms->Gains[chan],
  494. parms->Counter, OutPos, DstBufferSize);
  495. }
  496. }
  497. /* Update positions */
  498. DataPosFrac += increment*DstBufferSize;
  499. DataPosInt += DataPosFrac>>FRACTIONBITS;
  500. DataPosFrac &= FRACTIONMASK;
  501. OutPos += DstBufferSize;
  502. voice->Offset += DstBufferSize;
  503. voice->Direct.Counter = maxu(voice->Direct.Counter, DstBufferSize) - DstBufferSize;
  504. for(j = 0;j < Device->NumAuxSends;j++)
  505. voice->Send[j].Counter = maxu(voice->Send[j].Counter, DstBufferSize) - DstBufferSize;
  506. /* Handle looping sources */
  507. while(1)
  508. {
  509. const ALbuffer *ALBuffer;
  510. ALuint DataSize = 0;
  511. ALuint LoopStart = 0;
  512. ALuint LoopEnd = 0;
  513. if((ALBuffer=BufferListItem->buffer) != NULL)
  514. {
  515. DataSize = ALBuffer->SampleLen;
  516. LoopStart = ALBuffer->LoopStart;
  517. LoopEnd = ALBuffer->LoopEnd;
  518. if(LoopEnd > DataPosInt)
  519. break;
  520. }
  521. if(Looping && Source->SourceType == AL_STATIC)
  522. {
  523. assert(LoopEnd > LoopStart);
  524. DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
  525. break;
  526. }
  527. if(DataSize > DataPosInt)
  528. break;
  529. if(!(BufferListItem=BufferListItem->next))
  530. {
  531. if(Looping)
  532. BufferListItem = ATOMIC_LOAD(&Source->queue);
  533. else
  534. {
  535. State = AL_STOPPED;
  536. BufferListItem = NULL;
  537. DataPosInt = 0;
  538. DataPosFrac = 0;
  539. break;
  540. }
  541. }
  542. DataPosInt -= DataSize;
  543. }
  544. } while(State == AL_PLAYING && OutPos < SamplesToDo);
  545. /* Update source info */
  546. Source->state = State;
  547. ATOMIC_STORE(&Source->current_buffer, BufferListItem);
  548. Source->position = DataPosInt;
  549. Source->position_fraction = DataPosFrac;
  550. }