Free the global ALSA config after opening capture devices too
[openal-soft.git] / Alc / mixer.c
blob10e3d4e2345733126b114e916949bd806ec304be
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(enum Resampler Resampler)
44 #ifdef HAVE_SSE
45 if((CPUCapFlags&CPU_CAP_SSE))
47 switch(Resampler)
49 case PointResampler:
50 return MixDirect_point32_SSE;
51 case LinearResampler:
52 return MixDirect_lerp32_SSE;
53 case CubicResampler:
54 return MixDirect_cubic32_SSE;
55 case ResamplerMax:
56 break;
59 #endif
60 #ifdef HAVE_NEON
61 if((CPUCapFlags&CPU_CAP_NEON))
63 switch(Resampler)
65 case PointResampler:
66 return MixDirect_point32_Neon;
67 case LinearResampler:
68 return MixDirect_lerp32_Neon;
69 case CubicResampler:
70 return MixDirect_cubic32_Neon;
71 case ResamplerMax:
72 break;
75 #endif
77 switch(Resampler)
79 case PointResampler:
80 return MixDirect_point32_C;
81 case LinearResampler:
82 return MixDirect_lerp32_C;
83 case CubicResampler:
84 return MixDirect_cubic32_C;
85 case ResamplerMax:
86 break;
88 return NULL;
91 DryMixerFunc SelectHrtfMixer(enum Resampler Resampler)
93 #ifdef HAVE_SSE
94 if((CPUCapFlags&CPU_CAP_SSE))
96 switch(Resampler)
98 case PointResampler:
99 return MixDirect_Hrtf_point32_SSE;
100 case LinearResampler:
101 return MixDirect_Hrtf_lerp32_SSE;
102 case CubicResampler:
103 return MixDirect_Hrtf_cubic32_SSE;
104 case ResamplerMax:
105 break;
108 #endif
109 #ifdef HAVE_NEON
110 if((CPUCapFlags&CPU_CAP_NEON))
112 switch(Resampler)
114 case PointResampler:
115 return MixDirect_Hrtf_point32_Neon;
116 case LinearResampler:
117 return MixDirect_Hrtf_lerp32_Neon;
118 case CubicResampler:
119 return MixDirect_Hrtf_cubic32_Neon;
120 case ResamplerMax:
121 break;
124 #endif
126 switch(Resampler)
128 case PointResampler:
129 return MixDirect_Hrtf_point32_C;
130 case LinearResampler:
131 return MixDirect_Hrtf_lerp32_C;
132 case CubicResampler:
133 return MixDirect_Hrtf_cubic32_C;
134 case ResamplerMax:
135 break;
137 return NULL;
140 WetMixerFunc SelectSendMixer(enum Resampler Resampler)
142 #ifdef HAVE_SSE
143 if((CPUCapFlags&CPU_CAP_SSE))
145 switch(Resampler)
147 case PointResampler:
148 return MixSend_point32_SSE;
149 case LinearResampler:
150 return MixSend_lerp32_SSE;
151 case CubicResampler:
152 return MixSend_cubic32_SSE;
153 case ResamplerMax:
154 break;
157 #endif
158 #ifdef HAVE_NEON
159 if((CPUCapFlags&CPU_CAP_NEON))
161 switch(Resampler)
163 case PointResampler:
164 return MixSend_point32_Neon;
165 case LinearResampler:
166 return MixSend_lerp32_Neon;
167 case CubicResampler:
168 return MixSend_cubic32_Neon;
169 case ResamplerMax:
170 break;
173 #endif
175 switch(Resampler)
177 case PointResampler:
178 return MixSend_point32_C;
179 case LinearResampler:
180 return MixSend_lerp32_C;
181 case CubicResampler:
182 return MixSend_cubic32_C;
183 case ResamplerMax:
184 break;
186 return NULL;
190 static __inline ALfloat Sample_ALbyte(ALbyte val)
191 { return val * (1.0f/127.0f); }
193 static __inline ALfloat Sample_ALshort(ALshort val)
194 { return val * (1.0f/32767.0f); }
196 static __inline ALfloat Sample_ALfloat(ALfloat val)
197 { return val; }
199 #define DECL_TEMPLATE(T) \
200 static void Load_##T(ALfloat *dst, const T *src, ALuint samples) \
202 ALuint i; \
203 for(i = 0;i < samples;i++) \
204 dst[i] = Sample_##T(src[i]); \
207 DECL_TEMPLATE(ALbyte)
208 DECL_TEMPLATE(ALshort)
209 DECL_TEMPLATE(ALfloat)
211 #undef DECL_TEMPLATE
213 static void LoadStack(ALfloat *dst, const ALvoid *src, enum FmtType srctype, ALuint samples)
215 switch(srctype)
217 case FmtByte:
218 Load_ALbyte(dst, src, samples);
219 break;
220 case FmtShort:
221 Load_ALshort(dst, src, samples);
222 break;
223 case FmtFloat:
224 Load_ALfloat(dst, src, samples);
225 break;
229 static void SilenceStack(ALfloat *dst, ALuint samples)
231 ALuint i;
232 for(i = 0;i < samples;i++)
233 dst[i] = 0.0f;
237 ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
239 ALbufferlistitem *BufferListItem;
240 ALuint DataPosInt, DataPosFrac;
241 ALuint BuffersPlayed;
242 ALboolean Looping;
243 ALuint increment;
244 enum Resampler Resampler;
245 ALenum State;
246 ALuint OutPos;
247 ALuint NumChannels;
248 ALuint FrameSize;
249 ALint64 DataSize64;
250 ALuint i;
252 /* Get source info */
253 State = Source->state;
254 BuffersPlayed = Source->BuffersPlayed;
255 DataPosInt = Source->position;
256 DataPosFrac = Source->position_fraction;
257 Looping = Source->Looping;
258 increment = Source->Params.Step;
259 Resampler = Source->Resampler;
260 NumChannels = Source->NumChannels;
261 FrameSize = NumChannels * Source->SampleSize;
263 /* Get current buffer queue item */
264 BufferListItem = Source->queue;
265 for(i = 0;i < BuffersPlayed;i++)
266 BufferListItem = BufferListItem->next;
268 OutPos = 0;
269 do {
270 const ALuint BufferPrePadding = ResamplerPrePadding[Resampler];
271 const ALuint BufferPadding = ResamplerPadding[Resampler];
272 ALfloat StackData[STACK_DATA_SIZE/sizeof(ALfloat)];
273 ALfloat *SrcData = StackData;
274 ALuint SrcDataSize = 0;
275 ALuint BufferSize;
277 /* Figure out how many buffer bytes will be needed */
278 DataSize64 = SamplesToDo-OutPos+1;
279 DataSize64 *= increment;
280 DataSize64 += DataPosFrac+FRACTIONMASK;
281 DataSize64 >>= FRACTIONBITS;
282 DataSize64 += BufferPadding+BufferPrePadding;
283 DataSize64 *= NumChannels;
285 BufferSize = (ALuint)mini64(DataSize64, STACK_DATA_SIZE/sizeof(ALfloat));
286 BufferSize /= NumChannels;
288 if(Source->SourceType == AL_STATIC)
290 const ALbuffer *ALBuffer = Source->queue->buffer;
291 const ALubyte *Data = ALBuffer->data;
292 ALuint DataSize;
293 ALuint pos;
295 /* If current pos is beyond the loop range, do not loop */
296 if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
298 Looping = AL_FALSE;
300 if(DataPosInt >= BufferPrePadding)
301 pos = DataPosInt - BufferPrePadding;
302 else
304 DataSize = BufferPrePadding - DataPosInt;
305 DataSize = minu(BufferSize, DataSize);
307 SilenceStack(&SrcData[SrcDataSize*NumChannels],
308 DataSize*NumChannels);
309 SrcDataSize += DataSize;
310 BufferSize -= DataSize;
312 pos = 0;
315 /* Copy what's left to play in the source buffer, and clear the
316 * rest of the temp buffer */
317 DataSize = ALBuffer->SampleLen - pos;
318 DataSize = minu(BufferSize, DataSize);
320 LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[pos*FrameSize],
321 ALBuffer->FmtType, DataSize*NumChannels);
322 SrcDataSize += DataSize;
323 BufferSize -= DataSize;
325 SilenceStack(&SrcData[SrcDataSize*NumChannels],
326 BufferSize*NumChannels);
327 SrcDataSize += BufferSize;
328 BufferSize -= BufferSize;
330 else
332 ALuint LoopStart = ALBuffer->LoopStart;
333 ALuint LoopEnd = ALBuffer->LoopEnd;
335 if(DataPosInt >= LoopStart)
337 pos = DataPosInt-LoopStart;
338 while(pos < BufferPrePadding)
339 pos += LoopEnd-LoopStart;
340 pos -= BufferPrePadding;
341 pos += LoopStart;
343 else if(DataPosInt >= BufferPrePadding)
344 pos = DataPosInt - BufferPrePadding;
345 else
347 DataSize = BufferPrePadding - DataPosInt;
348 DataSize = minu(BufferSize, DataSize);
350 SilenceStack(&SrcData[SrcDataSize*NumChannels], DataSize*NumChannels);
351 SrcDataSize += DataSize;
352 BufferSize -= DataSize;
354 pos = 0;
357 /* Copy what's left of this loop iteration, then copy repeats
358 * of the loop section */
359 DataSize = LoopEnd - pos;
360 DataSize = minu(BufferSize, DataSize);
362 LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[pos*FrameSize],
363 ALBuffer->FmtType, DataSize*NumChannels);
364 SrcDataSize += DataSize;
365 BufferSize -= DataSize;
367 DataSize = LoopEnd-LoopStart;
368 while(BufferSize > 0)
370 DataSize = minu(BufferSize, DataSize);
372 LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[LoopStart*FrameSize],
373 ALBuffer->FmtType, DataSize*NumChannels);
374 SrcDataSize += DataSize;
375 BufferSize -= DataSize;
379 else
381 /* Crawl the buffer queue to fill in the temp buffer */
382 ALbufferlistitem *tmpiter = BufferListItem;
383 ALuint pos;
385 if(DataPosInt >= BufferPrePadding)
386 pos = DataPosInt - BufferPrePadding;
387 else
389 pos = BufferPrePadding - DataPosInt;
390 while(pos > 0)
392 if(!tmpiter->prev && !Looping)
394 ALuint DataSize = minu(BufferSize, pos);
396 SilenceStack(&SrcData[SrcDataSize*NumChannels], DataSize*NumChannels);
397 SrcDataSize += DataSize;
398 BufferSize -= DataSize;
400 pos = 0;
401 break;
404 if(tmpiter->prev)
405 tmpiter = tmpiter->prev;
406 else
408 while(tmpiter->next)
409 tmpiter = tmpiter->next;
412 if(tmpiter->buffer)
414 if((ALuint)tmpiter->buffer->SampleLen > pos)
416 pos = tmpiter->buffer->SampleLen - pos;
417 break;
419 pos -= tmpiter->buffer->SampleLen;
424 while(tmpiter && BufferSize > 0)
426 const ALbuffer *ALBuffer;
427 if((ALBuffer=tmpiter->buffer) != NULL)
429 const ALubyte *Data = ALBuffer->data;
430 ALuint DataSize = ALBuffer->SampleLen;
432 /* Skip the data already played */
433 if(DataSize <= pos)
434 pos -= DataSize;
435 else
437 Data += pos*FrameSize;
438 DataSize -= pos;
439 pos -= pos;
441 DataSize = minu(BufferSize, DataSize);
442 LoadStack(&SrcData[SrcDataSize*NumChannels], Data,
443 ALBuffer->FmtType, DataSize*NumChannels);
444 SrcDataSize += DataSize;
445 BufferSize -= DataSize;
448 tmpiter = tmpiter->next;
449 if(!tmpiter && Looping)
450 tmpiter = Source->queue;
451 else if(!tmpiter)
453 SilenceStack(&SrcData[SrcDataSize*NumChannels], BufferSize*NumChannels);
454 SrcDataSize += BufferSize;
455 BufferSize -= BufferSize;
460 /* Figure out how many samples we can mix. */
461 DataSize64 = SrcDataSize;
462 DataSize64 -= BufferPadding+BufferPrePadding;
463 DataSize64 <<= FRACTIONBITS;
464 DataSize64 -= increment;
465 DataSize64 -= DataPosFrac;
467 BufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
468 BufferSize = minu(BufferSize, (SamplesToDo-OutPos));
470 SrcData += BufferPrePadding*NumChannels;
471 Source->Params.DryMix(Source, Device, &Source->Params.Direct,
472 SrcData, DataPosFrac,
473 OutPos, SamplesToDo, BufferSize);
474 for(i = 0;i < Device->NumAuxSends;i++)
476 if(!Source->Params.Slot[i])
477 continue;
478 Source->Params.WetMix(Source, i, &Source->Params.Send[i],
479 SrcData, DataPosFrac,
480 OutPos, SamplesToDo, BufferSize);
482 for(i = 0;i < BufferSize;i++)
484 DataPosFrac += increment;
485 DataPosInt += DataPosFrac>>FRACTIONBITS;
486 DataPosFrac &= FRACTIONMASK;
487 OutPos++;
490 /* Handle looping sources */
491 while(1)
493 const ALbuffer *ALBuffer;
494 ALuint DataSize = 0;
495 ALuint LoopStart = 0;
496 ALuint LoopEnd = 0;
498 if((ALBuffer=BufferListItem->buffer) != NULL)
500 DataSize = ALBuffer->SampleLen;
501 LoopStart = ALBuffer->LoopStart;
502 LoopEnd = ALBuffer->LoopEnd;
503 if(LoopEnd > DataPosInt)
504 break;
507 if(Looping && Source->SourceType == AL_STATIC)
509 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
510 break;
513 if(DataSize > DataPosInt)
514 break;
516 if(BufferListItem->next)
518 BufferListItem = BufferListItem->next;
519 BuffersPlayed++;
521 else if(Looping)
523 BufferListItem = Source->queue;
524 BuffersPlayed = 0;
526 else
528 State = AL_STOPPED;
529 BufferListItem = Source->queue;
530 BuffersPlayed = Source->BuffersInQueue;
531 DataPosInt = 0;
532 DataPosFrac = 0;
533 break;
536 DataPosInt -= DataSize;
538 } while(State == AL_PLAYING && OutPos < SamplesToDo);
540 /* Update source info */
541 Source->state = State;
542 Source->BuffersPlayed = BuffersPlayed;
543 Source->position = DataPosInt;
544 Source->position_fraction = DataPosFrac;
545 Source->Hrtf.Offset += OutPos;
546 if(State == AL_PLAYING)
548 Source->Hrtf.Counter = maxu(Source->Hrtf.Counter, OutPos) - OutPos;
549 Source->Hrtf.Moving = AL_TRUE;
551 else
553 Source->Hrtf.Counter = 0;
554 Source->Hrtf.Moving = AL_FALSE;