Do the filtering separately from the mixing
[openal-soft.git] / Alc / mixer.c
blob41eba4aef089345a2bcf5ce2086c3a18c748dc6c
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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, 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"
37 #include "bs2b.h"
39 #include "mixer_defs.h"
42 DryMixerFunc SelectDirectMixer(void)
44 #ifdef HAVE_SSE
45 if((CPUCapFlags&CPU_CAP_SSE))
46 return MixDirect_SSE;
47 #endif
48 #ifdef HAVE_NEON
49 if((CPUCapFlags&CPU_CAP_NEON))
50 return MixDirect_Neon;
51 #endif
53 return MixDirect_C;
56 DryMixerFunc SelectHrtfMixer(void)
58 #ifdef HAVE_SSE
59 if((CPUCapFlags&CPU_CAP_SSE))
60 return MixDirect_Hrtf_SSE;
61 #endif
62 #ifdef HAVE_NEON
63 if((CPUCapFlags&CPU_CAP_NEON))
64 return MixDirect_Hrtf_Neon;
65 #endif
67 return MixDirect_Hrtf_C;
70 WetMixerFunc SelectSendMixer(void)
72 #ifdef HAVE_SSE
73 if((CPUCapFlags&CPU_CAP_SSE))
74 return MixSend_SSE;
75 #endif
76 #ifdef HAVE_NEON
77 if((CPUCapFlags&CPU_CAP_NEON))
78 return MixSend_Neon;
79 #endif
81 return MixSend_C;
85 static __inline ALfloat Sample_ALbyte(ALbyte val)
86 { return val * (1.0f/127.0f); }
88 static __inline ALfloat Sample_ALshort(ALshort val)
89 { return val * (1.0f/32767.0f); }
91 static __inline ALfloat Sample_ALfloat(ALfloat val)
92 { return val; }
94 #define DECL_TEMPLATE(T) \
95 static void Load_##T(ALfloat *dst, const T *src, ALuint samples) \
96 { \
97 ALuint i; \
98 for(i = 0;i < samples;i++) \
99 dst[i] = Sample_##T(src[i]); \
102 DECL_TEMPLATE(ALbyte)
103 DECL_TEMPLATE(ALshort)
104 DECL_TEMPLATE(ALfloat)
106 #undef DECL_TEMPLATE
108 static void LoadStack(ALfloat *dst, const ALvoid *src, enum FmtType srctype, ALuint samples)
110 switch(srctype)
112 case FmtByte:
113 Load_ALbyte(dst, src, samples);
114 break;
115 case FmtShort:
116 Load_ALshort(dst, src, samples);
117 break;
118 case FmtFloat:
119 Load_ALfloat(dst, src, samples);
120 break;
124 static void SilenceStack(ALfloat *dst, ALuint samples)
126 ALuint i;
127 for(i = 0;i < samples;i++)
128 dst[i] = 0.0f;
132 static __inline ALfloat point32(const ALfloat *vals, ALint step, ALint frac)
133 { return vals[0]; (void)step; (void)frac; }
134 static __inline ALfloat lerp32(const ALfloat *vals, ALint step, ALint frac)
135 { return lerp(vals[0], vals[step], frac * (1.0f/FRACTIONONE)); }
136 static __inline ALfloat cubic32(const ALfloat *vals, ALint step, ALint frac)
137 { return cubic(vals[-step], vals[0], vals[step], vals[step+step],
138 frac * (1.0f/FRACTIONONE)); }
140 #define DECL_TEMPLATE(Sampler) \
141 static void Resample_##Sampler(const ALfloat *data, ALuint frac, \
142 ALuint increment, ALuint NumChannels, ALfloat *RESTRICT OutBuffer, \
143 ALuint BufferSize) \
145 ALuint pos = 0; \
146 ALfloat value; \
147 ALuint i; \
149 for(i = 0;i < BufferSize+1;i++) \
151 value = Sampler(data + pos*NumChannels, NumChannels, frac); \
152 OutBuffer[i] = value; \
154 frac += increment; \
155 pos += frac>>FRACTIONBITS; \
156 frac &= FRACTIONMASK; \
160 DECL_TEMPLATE(point32)
161 DECL_TEMPLATE(lerp32)
162 DECL_TEMPLATE(cubic32)
164 #undef DECL_TEMPLATE
166 static void Resample(enum Resampler Resampler, const ALfloat *data, ALuint frac,
167 ALuint increment, ALuint NumChannels,
168 ALfloat *RESTRICT OutBuffer, ALuint BufferSize)
170 if(increment == FRACTIONONE)
171 goto do_point;
172 switch(Resampler)
174 case PointResampler:
175 do_point:
176 Resample_point32(data, frac, increment, NumChannels,
177 OutBuffer, BufferSize);
178 break;
179 case LinearResampler:
180 Resample_lerp32(data, frac, increment, NumChannels,
181 OutBuffer, BufferSize);
182 break;
183 case CubicResampler:
184 Resample_cubic32(data, frac, increment, NumChannels,
185 OutBuffer, BufferSize);
186 break;
187 case ResamplerMax:
188 /* Shouldn't happen */
189 break;
194 static void Filter2P(FILTER *filter, ALuint chan, ALfloat *RESTRICT dst,
195 const ALfloat *RESTRICT src, ALuint numsamples)
197 ALuint i;
198 for(i = 0;i < numsamples;i++)
199 dst[i] = lpFilter2P(filter, chan, src[i]);
200 dst[i] = lpFilter2PC(filter, chan, src[i]);
204 ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
206 ALbufferlistitem *BufferListItem;
207 ALuint DataPosInt, DataPosFrac;
208 ALuint BuffersPlayed;
209 ALboolean Looping;
210 ALuint increment;
211 enum Resampler Resampler;
212 ALenum State;
213 ALuint OutPos;
214 ALuint NumChannels;
215 ALuint FrameSize;
216 ALint64 DataSize64;
217 ALuint i, j;
219 /* Get source info */
220 State = Source->state;
221 BuffersPlayed = Source->BuffersPlayed;
222 DataPosInt = Source->position;
223 DataPosFrac = Source->position_fraction;
224 Looping = Source->Looping;
225 increment = Source->Params.Step;
226 Resampler = Source->Resampler;
227 NumChannels = Source->NumChannels;
228 FrameSize = NumChannels * Source->SampleSize;
230 /* Get current buffer queue item */
231 BufferListItem = Source->queue;
232 for(i = 0;i < BuffersPlayed;i++)
233 BufferListItem = BufferListItem->next;
235 OutPos = 0;
236 do {
237 const ALuint BufferPrePadding = ResamplerPrePadding[Resampler];
238 const ALuint BufferPadding = ResamplerPadding[Resampler];
239 ALfloat StackData[BUFFERSIZE];
240 ALfloat *SrcData = StackData;
241 ALuint SrcDataSize = 0;
242 ALuint BufferSize;
244 /* Figure out how many buffer bytes will be needed */
245 DataSize64 = SamplesToDo-OutPos+1;
246 DataSize64 *= increment;
247 DataSize64 += DataPosFrac+FRACTIONMASK;
248 DataSize64 >>= FRACTIONBITS;
249 DataSize64 += BufferPadding+BufferPrePadding;
250 DataSize64 *= NumChannels;
252 BufferSize = (ALuint)mini64(DataSize64, BUFFERSIZE);
253 BufferSize /= NumChannels;
255 if(Source->SourceType == AL_STATIC)
257 const ALbuffer *ALBuffer = Source->queue->buffer;
258 const ALubyte *Data = ALBuffer->data;
259 ALuint DataSize;
260 ALuint pos;
262 /* If current pos is beyond the loop range, do not loop */
263 if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
265 Looping = AL_FALSE;
267 if(DataPosInt >= BufferPrePadding)
268 pos = DataPosInt - BufferPrePadding;
269 else
271 DataSize = BufferPrePadding - DataPosInt;
272 DataSize = minu(BufferSize, DataSize);
274 SilenceStack(&SrcData[SrcDataSize*NumChannels],
275 DataSize*NumChannels);
276 SrcDataSize += DataSize;
277 BufferSize -= DataSize;
279 pos = 0;
282 /* Copy what's left to play in the source buffer, and clear the
283 * rest of the temp buffer */
284 DataSize = ALBuffer->SampleLen - pos;
285 DataSize = minu(BufferSize, DataSize);
287 LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[pos*FrameSize],
288 ALBuffer->FmtType, DataSize*NumChannels);
289 SrcDataSize += DataSize;
290 BufferSize -= DataSize;
292 SilenceStack(&SrcData[SrcDataSize*NumChannels],
293 BufferSize*NumChannels);
294 SrcDataSize += BufferSize;
295 BufferSize -= BufferSize;
297 else
299 ALuint LoopStart = ALBuffer->LoopStart;
300 ALuint LoopEnd = ALBuffer->LoopEnd;
302 if(DataPosInt >= LoopStart)
304 pos = DataPosInt-LoopStart;
305 while(pos < BufferPrePadding)
306 pos += LoopEnd-LoopStart;
307 pos -= BufferPrePadding;
308 pos += LoopStart;
310 else if(DataPosInt >= BufferPrePadding)
311 pos = DataPosInt - BufferPrePadding;
312 else
314 DataSize = BufferPrePadding - DataPosInt;
315 DataSize = minu(BufferSize, DataSize);
317 SilenceStack(&SrcData[SrcDataSize*NumChannels], DataSize*NumChannels);
318 SrcDataSize += DataSize;
319 BufferSize -= DataSize;
321 pos = 0;
324 /* Copy what's left of this loop iteration, then copy repeats
325 * of the loop section */
326 DataSize = LoopEnd - pos;
327 DataSize = minu(BufferSize, DataSize);
329 LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[pos*FrameSize],
330 ALBuffer->FmtType, DataSize*NumChannels);
331 SrcDataSize += DataSize;
332 BufferSize -= DataSize;
334 DataSize = LoopEnd-LoopStart;
335 while(BufferSize > 0)
337 DataSize = minu(BufferSize, DataSize);
339 LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[LoopStart*FrameSize],
340 ALBuffer->FmtType, DataSize*NumChannels);
341 SrcDataSize += DataSize;
342 BufferSize -= DataSize;
346 else
348 /* Crawl the buffer queue to fill in the temp buffer */
349 ALbufferlistitem *tmpiter = BufferListItem;
350 ALuint pos;
352 if(DataPosInt >= BufferPrePadding)
353 pos = DataPosInt - BufferPrePadding;
354 else
356 pos = BufferPrePadding - DataPosInt;
357 while(pos > 0)
359 if(!tmpiter->prev && !Looping)
361 ALuint DataSize = minu(BufferSize, pos);
363 SilenceStack(&SrcData[SrcDataSize*NumChannels], DataSize*NumChannels);
364 SrcDataSize += DataSize;
365 BufferSize -= DataSize;
367 pos = 0;
368 break;
371 if(tmpiter->prev)
372 tmpiter = tmpiter->prev;
373 else
375 while(tmpiter->next)
376 tmpiter = tmpiter->next;
379 if(tmpiter->buffer)
381 if((ALuint)tmpiter->buffer->SampleLen > pos)
383 pos = tmpiter->buffer->SampleLen - pos;
384 break;
386 pos -= tmpiter->buffer->SampleLen;
391 while(tmpiter && BufferSize > 0)
393 const ALbuffer *ALBuffer;
394 if((ALBuffer=tmpiter->buffer) != NULL)
396 const ALubyte *Data = ALBuffer->data;
397 ALuint DataSize = ALBuffer->SampleLen;
399 /* Skip the data already played */
400 if(DataSize <= pos)
401 pos -= DataSize;
402 else
404 Data += pos*FrameSize;
405 DataSize -= pos;
406 pos -= pos;
408 DataSize = minu(BufferSize, DataSize);
409 LoadStack(&SrcData[SrcDataSize*NumChannels], Data,
410 ALBuffer->FmtType, DataSize*NumChannels);
411 SrcDataSize += DataSize;
412 BufferSize -= DataSize;
415 tmpiter = tmpiter->next;
416 if(!tmpiter && Looping)
417 tmpiter = Source->queue;
418 else if(!tmpiter)
420 SilenceStack(&SrcData[SrcDataSize*NumChannels], BufferSize*NumChannels);
421 SrcDataSize += BufferSize;
422 BufferSize -= BufferSize;
427 /* Figure out how many samples we can mix. */
428 DataSize64 = SrcDataSize;
429 DataSize64 -= BufferPadding+BufferPrePadding;
430 DataSize64 <<= FRACTIONBITS;
431 DataSize64 -= increment;
432 DataSize64 -= DataPosFrac;
434 BufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
435 BufferSize = minu(BufferSize, (SamplesToDo-OutPos));
437 /* Some mixers like having a multiple of 4, so try to give that unless
438 * this is the last update. */
439 if(OutPos+BufferSize < SamplesToDo)
440 BufferSize &= ~3;
442 SrcData += BufferPrePadding*NumChannels;
443 for(i = 0;i < NumChannels;i++)
445 DirectParams *directparms = &Source->Params.Direct;
446 ALIGN(16) ALfloat FilteredData[BUFFERSIZE];
447 ALfloat ResampledData[BUFFERSIZE];
449 Resample(Resampler, SrcData+i, DataPosFrac, increment,
450 NumChannels, ResampledData, BufferSize);
452 Filter2P(&directparms->iirFilter, i, FilteredData, ResampledData,
453 BufferSize);
454 Source->Params.DryMix(Source, Device, directparms,
455 FilteredData, i, OutPos, SamplesToDo,
456 BufferSize);
458 for(j = 0;j < Device->NumAuxSends;j++)
460 SendParams *sendparms = &Source->Params.Send[j];
461 if(!sendparms->Slot)
462 continue;
464 Filter2P(&sendparms->iirFilter, i, FilteredData, ResampledData,
465 BufferSize);
466 Source->Params.WetMix(sendparms, FilteredData, OutPos,
467 SamplesToDo, BufferSize);
470 for(i = 0;i < BufferSize;i++)
472 DataPosFrac += increment;
473 DataPosInt += DataPosFrac>>FRACTIONBITS;
474 DataPosFrac &= FRACTIONMASK;
475 OutPos++;
478 /* Handle looping sources */
479 while(1)
481 const ALbuffer *ALBuffer;
482 ALuint DataSize = 0;
483 ALuint LoopStart = 0;
484 ALuint LoopEnd = 0;
486 if((ALBuffer=BufferListItem->buffer) != NULL)
488 DataSize = ALBuffer->SampleLen;
489 LoopStart = ALBuffer->LoopStart;
490 LoopEnd = ALBuffer->LoopEnd;
491 if(LoopEnd > DataPosInt)
492 break;
495 if(Looping && Source->SourceType == AL_STATIC)
497 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
498 break;
501 if(DataSize > DataPosInt)
502 break;
504 if(BufferListItem->next)
506 BufferListItem = BufferListItem->next;
507 BuffersPlayed++;
509 else if(Looping)
511 BufferListItem = Source->queue;
512 BuffersPlayed = 0;
514 else
516 State = AL_STOPPED;
517 BufferListItem = Source->queue;
518 BuffersPlayed = Source->BuffersInQueue;
519 DataPosInt = 0;
520 DataPosFrac = 0;
521 break;
524 DataPosInt -= DataSize;
526 } while(State == AL_PLAYING && OutPos < SamplesToDo);
528 /* Update source info */
529 Source->state = State;
530 Source->BuffersPlayed = BuffersPlayed;
531 Source->position = DataPosInt;
532 Source->position_fraction = DataPosFrac;
533 Source->Hrtf.Offset += OutPos;
534 if(State == AL_PLAYING)
536 Source->Hrtf.Counter = maxu(Source->Hrtf.Counter, OutPos) - OutPos;
537 Source->Hrtf.Moving = AL_TRUE;
539 else
541 Source->Hrtf.Counter = 0;
542 Source->Hrtf.Moving = AL_FALSE;