Don't try to use the non-standard alloca.h
[openal-soft.git] / Alc / mixer.c
blob0d52b9e37343f3823744f98f9dc1af35a500e6e9
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"
40 static inline ALfloat Sample_ALbyte(ALbyte val)
41 { return val * (1.0f/127.0f); }
43 static inline ALfloat Sample_ALshort(ALshort val)
44 { return val * (1.0f/32767.0f); }
46 static inline ALfloat Sample_ALfloat(ALfloat val)
47 { return val; }
49 #define DECL_TEMPLATE(T) \
50 static void Load_##T(ALfloat *dst, const T *src, ALuint srcstep, ALuint samples)\
51 { \
52 ALuint i; \
53 for(i = 0;i < samples;i++) \
54 dst[i] = Sample_##T(src[i*srcstep]); \
57 DECL_TEMPLATE(ALbyte)
58 DECL_TEMPLATE(ALshort)
59 DECL_TEMPLATE(ALfloat)
61 #undef DECL_TEMPLATE
63 static void LoadData(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum FmtType srctype, ALuint samples)
65 switch(srctype)
67 case FmtByte:
68 Load_ALbyte(dst, src, srcstep, samples);
69 break;
70 case FmtShort:
71 Load_ALshort(dst, src, srcstep, samples);
72 break;
73 case FmtFloat:
74 Load_ALfloat(dst, src, srcstep, samples);
75 break;
79 static void SilenceData(ALfloat *dst, ALuint samples)
81 ALuint i;
82 for(i = 0;i < samples;i++)
83 dst[i] = 0.0f;
87 static const ALfloat *DoFilters(ALfilterState *lpfilter, ALfilterState *hpfilter,
88 ALfloat *restrict dst, const ALfloat *restrict src,
89 ALuint numsamples, enum ActiveFilters type)
91 ALuint i;
92 switch(type)
94 case AF_None:
95 break;
97 case AF_LowPass:
98 ALfilterState_process(lpfilter, dst, src, numsamples);
99 return dst;
100 case AF_HighPass:
101 ALfilterState_process(hpfilter, dst, src, numsamples);
102 return dst;
104 case AF_BandPass:
105 for(i = 0;i < numsamples;)
107 ALfloat temp[64];
108 ALuint todo = minu(64, numsamples-i);
110 ALfilterState_process(lpfilter, temp, src+i, todo);
111 ALfilterState_process(hpfilter, dst+i, temp, todo);
112 i += todo;
114 return dst;
116 return src;
120 ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
122 ALsource *Source = src->Source;
123 ALbufferlistitem *BufferListItem;
124 ALuint DataPosInt, DataPosFrac;
125 ALboolean Looping;
126 ALuint increment;
127 enum Resampler Resampler;
128 ALenum State;
129 ALuint OutPos;
130 ALuint NumChannels;
131 ALuint SampleSize;
132 ALint64 DataSize64;
133 ALuint chan, j;
135 /* Get source info */
136 State = Source->state;
137 BufferListItem = Source->current_buffer;
138 DataPosInt = Source->position;
139 DataPosFrac = Source->position_fraction;
140 Looping = Source->Looping;
141 increment = src->Step;
142 Resampler = (increment==FRACTIONONE) ? PointResampler : Source->Resampler;
143 NumChannels = Source->NumChannels;
144 SampleSize = Source->SampleSize;
146 /* Get current buffer queue item */
148 OutPos = 0;
149 do {
150 const ALuint BufferPrePadding = ResamplerPrePadding[Resampler];
151 const ALuint BufferPadding = ResamplerPadding[Resampler];
152 ALuint SrcBufferSize, DstBufferSize;
154 /* Figure out how many buffer samples will be needed */
155 DataSize64 = SamplesToDo-OutPos;
156 DataSize64 *= increment;
157 DataSize64 += DataPosFrac+FRACTIONMASK;
158 DataSize64 >>= FRACTIONBITS;
159 DataSize64 += BufferPadding+BufferPrePadding;
161 SrcBufferSize = (ALuint)mini64(DataSize64, BUFFERSIZE);
163 /* Figure out how many samples we can actually mix from this. */
164 DataSize64 = SrcBufferSize;
165 DataSize64 -= BufferPadding+BufferPrePadding;
166 DataSize64 <<= FRACTIONBITS;
167 DataSize64 -= DataPosFrac;
169 DstBufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
170 DstBufferSize = minu(DstBufferSize, (SamplesToDo-OutPos));
172 /* Some mixers like having a multiple of 4, so try to give that unless
173 * this is the last update. */
174 if(OutPos+DstBufferSize < SamplesToDo)
175 DstBufferSize &= ~3;
177 for(chan = 0;chan < NumChannels;chan++)
179 const ALfloat *ResampledData;
180 ALfloat *SrcData = Device->SourceData;
181 ALuint SrcDataSize = 0;
183 if(Source->SourceType == AL_STATIC)
185 const ALbuffer *ALBuffer = BufferListItem->buffer;
186 const ALubyte *Data = ALBuffer->data;
187 ALuint DataSize;
188 ALuint pos;
190 /* If current pos is beyond the loop range, do not loop */
191 if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
193 Looping = AL_FALSE;
195 if(DataPosInt >= BufferPrePadding)
196 pos = DataPosInt - BufferPrePadding;
197 else
199 DataSize = BufferPrePadding - DataPosInt;
200 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
202 SilenceData(&SrcData[SrcDataSize], DataSize);
203 SrcDataSize += DataSize;
205 pos = 0;
208 /* Copy what's left to play in the source buffer, and clear the
209 * rest of the temp buffer */
210 DataSize = minu(SrcBufferSize - SrcDataSize, ALBuffer->SampleLen - pos);
212 LoadData(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
213 NumChannels, ALBuffer->FmtType, DataSize);
214 SrcDataSize += DataSize;
216 SilenceData(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
217 SrcDataSize += SrcBufferSize - SrcDataSize;
219 else
221 ALuint LoopStart = ALBuffer->LoopStart;
222 ALuint LoopEnd = ALBuffer->LoopEnd;
224 if(DataPosInt >= LoopStart)
226 pos = DataPosInt-LoopStart;
227 while(pos < BufferPrePadding)
228 pos += LoopEnd-LoopStart;
229 pos -= BufferPrePadding;
230 pos += LoopStart;
232 else if(DataPosInt >= BufferPrePadding)
233 pos = DataPosInt - BufferPrePadding;
234 else
236 DataSize = BufferPrePadding - DataPosInt;
237 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
239 SilenceData(&SrcData[SrcDataSize], DataSize);
240 SrcDataSize += DataSize;
242 pos = 0;
245 /* Copy what's left of this loop iteration, then copy repeats
246 * of the loop section */
247 DataSize = LoopEnd - pos;
248 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
250 LoadData(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
251 NumChannels, ALBuffer->FmtType, DataSize);
252 SrcDataSize += DataSize;
254 DataSize = LoopEnd-LoopStart;
255 while(SrcBufferSize > SrcDataSize)
257 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
259 LoadData(&SrcData[SrcDataSize], &Data[(LoopStart*NumChannels + chan)*SampleSize],
260 NumChannels, ALBuffer->FmtType, DataSize);
261 SrcDataSize += DataSize;
265 else
267 /* Crawl the buffer queue to fill in the temp buffer */
268 ALbufferlistitem *tmpiter = BufferListItem;
269 ALuint pos;
271 if(DataPosInt >= BufferPrePadding)
272 pos = DataPosInt - BufferPrePadding;
273 else
275 pos = BufferPrePadding - DataPosInt;
276 while(pos > 0)
278 ALbufferlistitem *prev;
279 if((prev=tmpiter->prev) != NULL)
280 tmpiter = prev;
281 else if(Looping)
283 while(tmpiter->next)
284 tmpiter = tmpiter->next;
286 else
288 ALuint DataSize = minu(SrcBufferSize - SrcDataSize, pos);
290 SilenceData(&SrcData[SrcDataSize], DataSize);
291 SrcDataSize += DataSize;
293 pos = 0;
294 break;
297 if(tmpiter->buffer)
299 if((ALuint)tmpiter->buffer->SampleLen > pos)
301 pos = tmpiter->buffer->SampleLen - pos;
302 break;
304 pos -= tmpiter->buffer->SampleLen;
309 while(tmpiter && SrcBufferSize > SrcDataSize)
311 const ALbuffer *ALBuffer;
312 if((ALBuffer=tmpiter->buffer) != NULL)
314 const ALubyte *Data = ALBuffer->data;
315 ALuint DataSize = ALBuffer->SampleLen;
317 /* Skip the data already played */
318 if(DataSize <= pos)
319 pos -= DataSize;
320 else
322 Data += (pos*NumChannels + chan)*SampleSize;
323 DataSize -= pos;
324 pos -= pos;
326 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
327 LoadData(&SrcData[SrcDataSize], Data, NumChannels,
328 ALBuffer->FmtType, DataSize);
329 SrcDataSize += DataSize;
332 tmpiter = tmpiter->next;
333 if(!tmpiter && Looping)
334 tmpiter = Source->queue;
335 else if(!tmpiter)
337 SilenceData(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
338 SrcDataSize += SrcBufferSize - SrcDataSize;
343 /* Now resample, then filter and mix to the appropriate outputs. */
344 ResampledData = src->Resample(
345 &SrcData[BufferPrePadding], DataPosFrac, increment,
346 Device->ResampledData, DstBufferSize
349 DirectParams *parms = &src->Direct;
350 const ALfloat *samples;
352 samples = DoFilters(
353 &parms->Filters[chan].LowPass, &parms->Filters[chan].HighPass,
354 Device->FilteredData, ResampledData, DstBufferSize,
355 parms->Filters[chan].ActiveType
357 if(!src->IsHrtf)
358 src->Dry.Mix(parms->OutBuffer, samples, &parms->Mix.Gains[chan],
359 parms->Counter, OutPos, DstBufferSize);
360 else
361 src->Dry.HrtfMix(
362 parms->OutBuffer, samples, parms->Counter, parms->Offset,
363 OutPos, parms->Mix.Hrtf.IrSize, &parms->Mix.Hrtf.Params[chan],
364 &parms->Mix.Hrtf.State[chan], DstBufferSize
368 for(j = 0;j < Device->NumAuxSends;j++)
370 SendParams *parms = &src->Send[j];
371 const ALfloat *samples;
373 if(!parms->OutBuffer)
374 continue;
376 samples = DoFilters(
377 &parms->Filters[chan].LowPass, &parms->Filters[chan].HighPass,
378 Device->FilteredData, ResampledData, DstBufferSize,
379 parms->Filters[chan].ActiveType
381 src->WetMix(parms->OutBuffer, samples, &parms->Gain,
382 parms->Counter, OutPos, DstBufferSize);
385 /* Update positions */
386 for(j = 0;j < DstBufferSize;j++)
388 DataPosFrac += increment;
389 DataPosInt += DataPosFrac>>FRACTIONBITS;
390 DataPosFrac &= FRACTIONMASK;
392 OutPos += DstBufferSize;
393 src->Direct.Offset += DstBufferSize;
394 src->Direct.Counter = maxu(src->Direct.Counter, DstBufferSize) - DstBufferSize;
395 for(j = 0;j < Device->NumAuxSends;j++)
396 src->Send[j].Counter = maxu(src->Send[j].Counter, DstBufferSize) - DstBufferSize;
398 /* Handle looping sources */
399 while(1)
401 const ALbuffer *ALBuffer;
402 ALuint DataSize = 0;
403 ALuint LoopStart = 0;
404 ALuint LoopEnd = 0;
406 if((ALBuffer=BufferListItem->buffer) != NULL)
408 DataSize = ALBuffer->SampleLen;
409 LoopStart = ALBuffer->LoopStart;
410 LoopEnd = ALBuffer->LoopEnd;
411 if(LoopEnd > DataPosInt)
412 break;
415 if(Looping && Source->SourceType == AL_STATIC)
417 assert(LoopEnd > LoopStart);
418 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
419 break;
422 if(DataSize > DataPosInt)
423 break;
425 if(BufferListItem->next)
426 BufferListItem = BufferListItem->next;
427 else if(Looping)
428 BufferListItem = Source->queue;
429 else
431 State = AL_STOPPED;
432 BufferListItem = NULL;
433 DataPosInt = 0;
434 DataPosFrac = 0;
435 break;
438 DataPosInt -= DataSize;
440 } while(State == AL_PLAYING && OutPos < SamplesToDo);
442 /* Update source info */
443 Source->state = State;
444 Source->current_buffer = BufferListItem;
445 Source->position = DataPosInt;
446 Source->position_fraction = DataPosFrac;