Assert that there's a buffer for mixing
[openal-soft.git] / Alc / mixer.c
blobbce9b14fb541fb9b2dd13b29bbadd40bc91e35d1
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.
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.
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
21 #include "config.h"
23 #include <math.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <assert.h>
29 #include "alMain.h"
30 #include "AL/al.h"
31 #include "AL/alc.h"
32 #include "alSource.h"
33 #include "alBuffer.h"
34 #include "alListener.h"
35 #include "alAuxEffectSlot.h"
36 #include "alu.h"
38 #include "mixer_defs.h"
41 extern inline void InitiatePositionArrays(ALuint frac, ALuint increment, ALuint *frac_arr, ALuint *pos_arr, ALuint size);
43 alignas(16) ALfloat CubicLUT[FRACTIONONE][4];
46 void aluInitResamplers(void)
48 ALuint i;
49 for(i = 0;i < FRACTIONONE;i++)
51 ALfloat mu = (ALfloat)i / FRACTIONONE;
52 ALfloat mu2 = mu*mu, mu3 = mu*mu*mu;
53 CubicLUT[i][0] = -0.5f*mu3 + mu2 + -0.5f*mu;
54 CubicLUT[i][1] = 1.5f*mu3 + -2.5f*mu2 + 1.0f;
55 CubicLUT[i][2] = -1.5f*mu3 + 2.0f*mu2 + 0.5f*mu;
56 CubicLUT[i][3] = 0.5f*mu3 + -0.5f*mu2;
61 static inline HrtfMixerFunc SelectHrtfMixer(void)
63 #ifdef HAVE_SSE
64 if((CPUCapFlags&CPU_CAP_SSE))
65 return MixHrtf_SSE;
66 #endif
67 #ifdef HAVE_NEON
68 if((CPUCapFlags&CPU_CAP_NEON))
69 return MixHrtf_Neon;
70 #endif
72 return MixHrtf_C;
75 static inline MixerFunc SelectMixer(void)
77 #ifdef HAVE_SSE
78 if((CPUCapFlags&CPU_CAP_SSE))
79 return Mix_SSE;
80 #endif
81 #ifdef HAVE_NEON
82 if((CPUCapFlags&CPU_CAP_NEON))
83 return Mix_Neon;
84 #endif
86 return Mix_C;
89 static inline ResamplerFunc SelectResampler(enum Resampler resampler)
91 switch(resampler)
93 case PointResampler:
94 return Resample_point32_C;
95 case LinearResampler:
96 #ifdef HAVE_SSE4_1
97 if((CPUCapFlags&CPU_CAP_SSE4_1))
98 return Resample_lerp32_SSE41;
99 #endif
100 #ifdef HAVE_SSE2
101 if((CPUCapFlags&CPU_CAP_SSE2))
102 return Resample_lerp32_SSE2;
103 #endif
104 return Resample_lerp32_C;
105 case CubicResampler:
106 #ifdef HAVE_SSE4_1
107 if((CPUCapFlags&CPU_CAP_SSE4_1))
108 return Resample_cubic32_SSE41;
109 #endif
110 #ifdef HAVE_SSE2
111 if((CPUCapFlags&CPU_CAP_SSE2))
112 return Resample_cubic32_SSE2;
113 #endif
114 return Resample_cubic32_C;
115 case ResamplerMax:
116 /* Shouldn't happen */
117 break;
120 return Resample_point32_C;
124 static inline ALfloat Sample_ALbyte(ALbyte val)
125 { return val * (1.0f/127.0f); }
127 static inline ALfloat Sample_ALshort(ALshort val)
128 { return val * (1.0f/32767.0f); }
130 static inline ALfloat Sample_ALfloat(ALfloat val)
131 { return val; }
133 #define DECL_TEMPLATE(T) \
134 static void Load_##T(ALfloat *dst, const T *src, ALuint srcstep, ALuint samples)\
136 ALuint i; \
137 for(i = 0;i < samples;i++) \
138 dst[i] = Sample_##T(src[i*srcstep]); \
141 DECL_TEMPLATE(ALbyte)
142 DECL_TEMPLATE(ALshort)
143 DECL_TEMPLATE(ALfloat)
145 #undef DECL_TEMPLATE
147 static void LoadSamples(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum FmtType srctype, ALuint samples)
149 switch(srctype)
151 case FmtByte:
152 Load_ALbyte(dst, src, srcstep, samples);
153 break;
154 case FmtShort:
155 Load_ALshort(dst, src, srcstep, samples);
156 break;
157 case FmtFloat:
158 Load_ALfloat(dst, src, srcstep, samples);
159 break;
163 static void SilenceSamples(ALfloat *dst, ALuint samples)
165 ALuint i;
166 for(i = 0;i < samples;i++)
167 dst[i] = 0.0f;
171 static const ALfloat *DoFilters(ALfilterState *lpfilter, ALfilterState *hpfilter,
172 ALfloat *restrict dst, const ALfloat *restrict src,
173 ALuint numsamples, enum ActiveFilters type)
175 ALuint i;
176 switch(type)
178 case AF_None:
179 break;
181 case AF_LowPass:
182 ALfilterState_process(lpfilter, dst, src, numsamples);
183 return dst;
184 case AF_HighPass:
185 ALfilterState_process(hpfilter, dst, src, numsamples);
186 return dst;
188 case AF_BandPass:
189 for(i = 0;i < numsamples;)
191 ALfloat temp[64];
192 ALuint todo = minu(64, numsamples-i);
194 ALfilterState_process(lpfilter, temp, src+i, todo);
195 ALfilterState_process(hpfilter, dst+i, temp, todo);
196 i += todo;
198 return dst;
200 return src;
204 ALvoid MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
206 MixerFunc Mix;
207 HrtfMixerFunc HrtfMix;
208 ResamplerFunc Resample;
209 ALbufferlistitem *BufferListItem;
210 ALuint DataPosInt, DataPosFrac;
211 ALboolean isbformat = AL_FALSE;
212 ALboolean Looping;
213 ALuint increment;
214 enum Resampler Resampler;
215 ALenum State;
216 ALuint OutPos;
217 ALuint NumChannels;
218 ALuint SampleSize;
219 ALint64 DataSize64;
220 ALuint IrSize;
221 ALuint chan, j;
223 /* Get source info */
224 State = Source->state;
225 BufferListItem = ATOMIC_LOAD(&Source->current_buffer);
226 DataPosInt = Source->position;
227 DataPosFrac = Source->position_fraction;
228 Looping = Source->Looping;
229 Resampler = Source->Resampler;
230 NumChannels = Source->NumChannels;
231 SampleSize = Source->SampleSize;
232 increment = voice->Step;
234 while(BufferListItem)
236 ALbuffer *buffer;
237 if((buffer=BufferListItem->buffer) != NULL)
239 isbformat = (buffer->FmtChannels == FmtBFormat2D ||
240 buffer->FmtChannels == FmtBFormat3D);
241 break;
243 BufferListItem = BufferListItem->next;
245 assert(BufferListItem != NULL);
247 IrSize = (Device->Hrtf ? GetHrtfIrSize(Device->Hrtf) : 0);
249 Mix = SelectMixer();
250 HrtfMix = SelectHrtfMixer();
251 Resample = ((increment == FRACTIONONE && DataPosFrac == 0) ?
252 Resample_copy32_C : SelectResampler(Resampler));
254 OutPos = 0;
255 do {
256 const ALuint BufferPrePadding = ResamplerPrePadding[Resampler];
257 const ALuint BufferPadding = ResamplerPadding[Resampler];
258 ALuint SrcBufferSize, DstBufferSize;
260 /* Figure out how many buffer samples will be needed */
261 DataSize64 = SamplesToDo-OutPos;
262 DataSize64 *= increment;
263 DataSize64 += DataPosFrac+FRACTIONMASK;
264 DataSize64 >>= FRACTIONBITS;
265 DataSize64 += BufferPadding+BufferPrePadding;
267 SrcBufferSize = (ALuint)mini64(DataSize64, BUFFERSIZE);
269 /* Figure out how many samples we can actually mix from this. */
270 DataSize64 = SrcBufferSize;
271 DataSize64 -= BufferPadding+BufferPrePadding;
272 DataSize64 <<= FRACTIONBITS;
273 DataSize64 -= DataPosFrac;
275 DstBufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
276 DstBufferSize = minu(DstBufferSize, (SamplesToDo-OutPos));
278 /* Some mixers like having a multiple of 4, so try to give that unless
279 * this is the last update. */
280 if(OutPos+DstBufferSize < SamplesToDo)
281 DstBufferSize &= ~3;
283 for(chan = 0;chan < NumChannels;chan++)
285 const ALfloat *ResampledData;
286 ALfloat *SrcData = Device->SourceData;
287 ALuint SrcDataSize = 0;
289 if(Source->SourceType == AL_STATIC)
291 const ALbuffer *ALBuffer = BufferListItem->buffer;
292 const ALubyte *Data = ALBuffer->data;
293 ALuint DataSize;
294 ALuint pos;
296 /* If current pos is beyond the loop range, do not loop */
297 if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
299 Looping = AL_FALSE;
301 if(DataPosInt >= BufferPrePadding)
302 pos = DataPosInt - BufferPrePadding;
303 else
305 DataSize = BufferPrePadding - DataPosInt;
306 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
308 SilenceSamples(&SrcData[SrcDataSize], DataSize);
309 SrcDataSize += DataSize;
311 pos = 0;
314 /* Copy what's left to play in the source buffer, and clear the
315 * rest of the temp buffer */
316 DataSize = minu(SrcBufferSize - SrcDataSize, ALBuffer->SampleLen - pos);
318 LoadSamples(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
319 NumChannels, ALBuffer->FmtType, DataSize);
320 SrcDataSize += DataSize;
322 SilenceSamples(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
323 SrcDataSize += SrcBufferSize - SrcDataSize;
325 else
327 ALuint LoopStart = ALBuffer->LoopStart;
328 ALuint LoopEnd = ALBuffer->LoopEnd;
330 if(DataPosInt >= LoopStart)
332 pos = DataPosInt-LoopStart;
333 while(pos < BufferPrePadding)
334 pos += LoopEnd-LoopStart;
335 pos -= BufferPrePadding;
336 pos += LoopStart;
338 else if(DataPosInt >= BufferPrePadding)
339 pos = DataPosInt - BufferPrePadding;
340 else
342 DataSize = BufferPrePadding - DataPosInt;
343 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
345 SilenceSamples(&SrcData[SrcDataSize], DataSize);
346 SrcDataSize += DataSize;
348 pos = 0;
351 /* Copy what's left of this loop iteration, then copy repeats
352 * of the loop section */
353 DataSize = LoopEnd - pos;
354 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
356 LoadSamples(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
357 NumChannels, ALBuffer->FmtType, DataSize);
358 SrcDataSize += DataSize;
360 DataSize = LoopEnd-LoopStart;
361 while(SrcBufferSize > SrcDataSize)
363 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
365 LoadSamples(&SrcData[SrcDataSize], &Data[(LoopStart*NumChannels + chan)*SampleSize],
366 NumChannels, ALBuffer->FmtType, DataSize);
367 SrcDataSize += DataSize;
371 else
373 /* Crawl the buffer queue to fill in the temp buffer */
374 ALbufferlistitem *tmpiter = BufferListItem;
375 ALuint pos;
377 if(DataPosInt >= BufferPrePadding)
378 pos = DataPosInt - BufferPrePadding;
379 else
381 pos = BufferPrePadding - DataPosInt;
382 while(pos > 0)
384 ALbufferlistitem *prev;
385 if((prev=tmpiter->prev) != NULL)
386 tmpiter = prev;
387 else if(Looping)
389 while(tmpiter->next)
390 tmpiter = tmpiter->next;
392 else
394 ALuint DataSize = minu(SrcBufferSize - SrcDataSize, pos);
396 SilenceSamples(&SrcData[SrcDataSize], DataSize);
397 SrcDataSize += DataSize;
399 pos = 0;
400 break;
403 if(tmpiter->buffer)
405 if((ALuint)tmpiter->buffer->SampleLen > pos)
407 pos = tmpiter->buffer->SampleLen - pos;
408 break;
410 pos -= tmpiter->buffer->SampleLen;
415 while(tmpiter && SrcBufferSize > SrcDataSize)
417 const ALbuffer *ALBuffer;
418 if((ALBuffer=tmpiter->buffer) != NULL)
420 const ALubyte *Data = ALBuffer->data;
421 ALuint DataSize = ALBuffer->SampleLen;
423 /* Skip the data already played */
424 if(DataSize <= pos)
425 pos -= DataSize;
426 else
428 Data += (pos*NumChannels + chan)*SampleSize;
429 DataSize -= pos;
430 pos -= pos;
432 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
433 LoadSamples(&SrcData[SrcDataSize], Data, NumChannels,
434 ALBuffer->FmtType, DataSize);
435 SrcDataSize += DataSize;
438 tmpiter = tmpiter->next;
439 if(!tmpiter && Looping)
440 tmpiter = ATOMIC_LOAD(&Source->queue);
441 else if(!tmpiter)
443 SilenceSamples(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
444 SrcDataSize += SrcBufferSize - SrcDataSize;
449 /* Now resample, then filter and mix to the appropriate outputs. */
450 ResampledData = Resample(
451 &SrcData[BufferPrePadding], DataPosFrac, increment,
452 Device->ResampledData, DstBufferSize
455 DirectParams *parms = &voice->Direct;
456 const ALfloat *samples;
458 samples = DoFilters(
459 &parms->Filters[chan].LowPass, &parms->Filters[chan].HighPass,
460 Device->FilteredData, ResampledData, DstBufferSize,
461 parms->Filters[chan].ActiveType
463 if(!voice->IsHrtf)
464 Mix(samples, parms->OutChannels, parms->OutBuffer, parms->Gains[chan],
465 parms->Counter, OutPos, DstBufferSize);
466 else
467 HrtfMix(parms->OutBuffer, samples, parms->Counter, voice->Offset,
468 OutPos, IrSize, &parms->Hrtf.Params[chan],
469 &parms->Hrtf.State[chan], DstBufferSize);
472 /* Only the first channel for B-Format buffers (W channel) goes to
473 * the send paths. */
474 if(chan > 0 && isbformat)
475 continue;
476 for(j = 0;j < Device->NumAuxSends;j++)
478 SendParams *parms = &voice->Send[j];
479 const ALfloat *samples;
481 if(!parms->OutBuffer)
482 continue;
484 samples = DoFilters(
485 &parms->Filters[chan].LowPass, &parms->Filters[chan].HighPass,
486 Device->FilteredData, ResampledData, DstBufferSize,
487 parms->Filters[chan].ActiveType
489 Mix(samples, 1, parms->OutBuffer, &parms->Gain,
490 parms->Counter, OutPos, DstBufferSize);
493 /* Update positions */
494 DataPosFrac += increment*DstBufferSize;
495 DataPosInt += DataPosFrac>>FRACTIONBITS;
496 DataPosFrac &= FRACTIONMASK;
498 OutPos += DstBufferSize;
499 voice->Offset += DstBufferSize;
500 voice->Direct.Counter = maxu(voice->Direct.Counter, DstBufferSize) - DstBufferSize;
501 for(j = 0;j < Device->NumAuxSends;j++)
502 voice->Send[j].Counter = maxu(voice->Send[j].Counter, DstBufferSize) - DstBufferSize;
504 /* Handle looping sources */
505 while(1)
507 const ALbuffer *ALBuffer;
508 ALuint DataSize = 0;
509 ALuint LoopStart = 0;
510 ALuint LoopEnd = 0;
512 if((ALBuffer=BufferListItem->buffer) != NULL)
514 DataSize = ALBuffer->SampleLen;
515 LoopStart = ALBuffer->LoopStart;
516 LoopEnd = ALBuffer->LoopEnd;
517 if(LoopEnd > DataPosInt)
518 break;
521 if(Looping && Source->SourceType == AL_STATIC)
523 assert(LoopEnd > LoopStart);
524 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
525 break;
528 if(DataSize > DataPosInt)
529 break;
531 if(!(BufferListItem=BufferListItem->next))
533 if(Looping)
534 BufferListItem = ATOMIC_LOAD(&Source->queue);
535 else
537 State = AL_STOPPED;
538 BufferListItem = NULL;
539 DataPosInt = 0;
540 DataPosFrac = 0;
541 break;
545 DataPosInt -= DataSize;
547 } while(State == AL_PLAYING && OutPos < SamplesToDo);
549 /* Update source info */
550 Source->state = State;
551 ATOMIC_STORE(&Source->current_buffer, BufferListItem);
552 Source->position = DataPosInt;
553 Source->position_fraction = DataPosFrac;