Fix up some more header includes
[openal-soft.git] / Alc / mixer.c
blobda3dcc200def8efbfc3e2522665bb448d2310803
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 samples) \
51 { \
52 ALuint i; \
53 for(i = 0;i < samples;i++) \
54 dst[i] = Sample_##T(src[i]); \
57 DECL_TEMPLATE(ALbyte)
58 DECL_TEMPLATE(ALshort)
59 DECL_TEMPLATE(ALfloat)
61 #undef DECL_TEMPLATE
63 static void LoadStack(ALfloat *dst, const ALvoid *src, enum FmtType srctype, ALuint samples)
65 switch(srctype)
67 case FmtByte:
68 Load_ALbyte(dst, src, samples);
69 break;
70 case FmtShort:
71 Load_ALshort(dst, src, samples);
72 break;
73 case FmtFloat:
74 Load_ALfloat(dst, src, samples);
75 break;
79 static void SilenceStack(ALfloat *dst, ALuint samples)
81 ALuint i;
82 for(i = 0;i < samples;i++)
83 dst[i] = 0.0f;
87 static __inline ALfloat point32(const ALfloat *vals, ALint step, ALint frac)
88 { return vals[0]; (void)step; (void)frac; }
89 static __inline ALfloat lerp32(const ALfloat *vals, ALint step, ALint frac)
90 { return lerp(vals[0], vals[step], frac * (1.0f/FRACTIONONE)); }
91 static __inline ALfloat cubic32(const ALfloat *vals, ALint step, ALint frac)
92 { return cubic(vals[-step], vals[0], vals[step], vals[step+step],
93 frac * (1.0f/FRACTIONONE)); }
95 #define DECL_TEMPLATE(Sampler) \
96 static void Resample_##Sampler(const ALfloat *data, ALuint frac, \
97 ALuint increment, ALuint NumChannels, ALfloat *RESTRICT OutBuffer, \
98 ALuint BufferSize) \
99 { \
100 ALuint pos = 0; \
101 ALfloat value; \
102 ALuint i; \
104 for(i = 0;i < BufferSize+1;i++) \
106 value = Sampler(data + pos*NumChannels, NumChannels, frac); \
107 OutBuffer[i] = value; \
109 frac += increment; \
110 pos += frac>>FRACTIONBITS; \
111 frac &= FRACTIONMASK; \
115 DECL_TEMPLATE(point32)
116 DECL_TEMPLATE(lerp32)
117 DECL_TEMPLATE(cubic32)
119 #undef DECL_TEMPLATE
121 static void Resample(enum Resampler Resampler, const ALfloat *data, ALuint frac,
122 ALuint increment, ALuint NumChannels,
123 ALfloat *RESTRICT OutBuffer, ALuint BufferSize)
125 if(increment == FRACTIONONE)
126 goto do_point;
127 switch(Resampler)
129 case PointResampler:
130 do_point:
131 Resample_point32(data, frac, increment, NumChannels,
132 OutBuffer, BufferSize);
133 break;
134 case LinearResampler:
135 Resample_lerp32(data, frac, increment, NumChannels,
136 OutBuffer, BufferSize);
137 break;
138 case CubicResampler:
139 Resample_cubic32(data, frac, increment, NumChannels,
140 OutBuffer, BufferSize);
141 break;
142 case ResamplerMax:
143 /* Shouldn't happen */
144 break;
149 static void Filter2P(FILTER *filter, ALuint chan, ALfloat *RESTRICT dst,
150 const ALfloat *RESTRICT src, ALuint numsamples)
152 ALuint i;
153 for(i = 0;i < numsamples;i++)
154 dst[i] = lpFilter2P(filter, chan, src[i]);
155 dst[i] = lpFilter2PC(filter, chan, src[i]);
159 ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
161 ALbufferlistitem *BufferListItem;
162 ALuint DataPosInt, DataPosFrac;
163 ALuint BuffersPlayed;
164 ALboolean Looping;
165 ALuint increment;
166 enum Resampler Resampler;
167 ALenum State;
168 ALuint OutPos;
169 ALuint NumChannels;
170 ALuint FrameSize;
171 ALint64 DataSize64;
172 ALuint i, j;
174 /* Get source info */
175 State = Source->state;
176 BuffersPlayed = Source->BuffersPlayed;
177 DataPosInt = Source->position;
178 DataPosFrac = Source->position_fraction;
179 Looping = Source->Looping;
180 increment = Source->Params.Step;
181 Resampler = Source->Resampler;
182 NumChannels = Source->NumChannels;
183 FrameSize = NumChannels * Source->SampleSize;
185 /* Get current buffer queue item */
186 BufferListItem = Source->queue;
187 for(i = 0;i < BuffersPlayed;i++)
188 BufferListItem = BufferListItem->next;
190 OutPos = 0;
191 do {
192 const ALuint BufferPrePadding = ResamplerPrePadding[Resampler];
193 const ALuint BufferPadding = ResamplerPadding[Resampler];
194 ALfloat StackData[BUFFERSIZE];
195 ALfloat *SrcData = StackData;
196 ALuint SrcDataSize = 0;
197 ALuint BufferSize;
199 /* Figure out how many buffer bytes will be needed */
200 DataSize64 = SamplesToDo-OutPos+1;
201 DataSize64 *= increment;
202 DataSize64 += DataPosFrac+FRACTIONMASK;
203 DataSize64 >>= FRACTIONBITS;
204 DataSize64 += BufferPadding+BufferPrePadding;
205 DataSize64 *= NumChannels;
207 BufferSize = (ALuint)mini64(DataSize64, BUFFERSIZE);
208 BufferSize /= NumChannels;
210 if(Source->SourceType == AL_STATIC)
212 const ALbuffer *ALBuffer = Source->queue->buffer;
213 const ALubyte *Data = ALBuffer->data;
214 ALuint DataSize;
215 ALuint pos;
217 /* If current pos is beyond the loop range, do not loop */
218 if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
220 Looping = AL_FALSE;
222 if(DataPosInt >= BufferPrePadding)
223 pos = DataPosInt - BufferPrePadding;
224 else
226 DataSize = BufferPrePadding - DataPosInt;
227 DataSize = minu(BufferSize, DataSize);
229 SilenceStack(&SrcData[SrcDataSize*NumChannels],
230 DataSize*NumChannels);
231 SrcDataSize += DataSize;
232 BufferSize -= DataSize;
234 pos = 0;
237 /* Copy what's left to play in the source buffer, and clear the
238 * rest of the temp buffer */
239 DataSize = ALBuffer->SampleLen - pos;
240 DataSize = minu(BufferSize, DataSize);
242 LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[pos*FrameSize],
243 ALBuffer->FmtType, DataSize*NumChannels);
244 SrcDataSize += DataSize;
245 BufferSize -= DataSize;
247 SilenceStack(&SrcData[SrcDataSize*NumChannels],
248 BufferSize*NumChannels);
249 SrcDataSize += BufferSize;
250 BufferSize -= BufferSize;
252 else
254 ALuint LoopStart = ALBuffer->LoopStart;
255 ALuint LoopEnd = ALBuffer->LoopEnd;
257 if(DataPosInt >= LoopStart)
259 pos = DataPosInt-LoopStart;
260 while(pos < BufferPrePadding)
261 pos += LoopEnd-LoopStart;
262 pos -= BufferPrePadding;
263 pos += LoopStart;
265 else if(DataPosInt >= BufferPrePadding)
266 pos = DataPosInt - BufferPrePadding;
267 else
269 DataSize = BufferPrePadding - DataPosInt;
270 DataSize = minu(BufferSize, DataSize);
272 SilenceStack(&SrcData[SrcDataSize*NumChannels], DataSize*NumChannels);
273 SrcDataSize += DataSize;
274 BufferSize -= DataSize;
276 pos = 0;
279 /* Copy what's left of this loop iteration, then copy repeats
280 * of the loop section */
281 DataSize = LoopEnd - pos;
282 DataSize = minu(BufferSize, DataSize);
284 LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[pos*FrameSize],
285 ALBuffer->FmtType, DataSize*NumChannels);
286 SrcDataSize += DataSize;
287 BufferSize -= DataSize;
289 DataSize = LoopEnd-LoopStart;
290 while(BufferSize > 0)
292 DataSize = minu(BufferSize, DataSize);
294 LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[LoopStart*FrameSize],
295 ALBuffer->FmtType, DataSize*NumChannels);
296 SrcDataSize += DataSize;
297 BufferSize -= DataSize;
301 else
303 /* Crawl the buffer queue to fill in the temp buffer */
304 ALbufferlistitem *tmpiter = BufferListItem;
305 ALuint pos;
307 if(DataPosInt >= BufferPrePadding)
308 pos = DataPosInt - BufferPrePadding;
309 else
311 pos = BufferPrePadding - DataPosInt;
312 while(pos > 0)
314 if(!tmpiter->prev && !Looping)
316 ALuint DataSize = minu(BufferSize, pos);
318 SilenceStack(&SrcData[SrcDataSize*NumChannels], DataSize*NumChannels);
319 SrcDataSize += DataSize;
320 BufferSize -= DataSize;
322 pos = 0;
323 break;
326 if(tmpiter->prev)
327 tmpiter = tmpiter->prev;
328 else
330 while(tmpiter->next)
331 tmpiter = tmpiter->next;
334 if(tmpiter->buffer)
336 if((ALuint)tmpiter->buffer->SampleLen > pos)
338 pos = tmpiter->buffer->SampleLen - pos;
339 break;
341 pos -= tmpiter->buffer->SampleLen;
346 while(tmpiter && BufferSize > 0)
348 const ALbuffer *ALBuffer;
349 if((ALBuffer=tmpiter->buffer) != NULL)
351 const ALubyte *Data = ALBuffer->data;
352 ALuint DataSize = ALBuffer->SampleLen;
354 /* Skip the data already played */
355 if(DataSize <= pos)
356 pos -= DataSize;
357 else
359 Data += pos*FrameSize;
360 DataSize -= pos;
361 pos -= pos;
363 DataSize = minu(BufferSize, DataSize);
364 LoadStack(&SrcData[SrcDataSize*NumChannels], Data,
365 ALBuffer->FmtType, DataSize*NumChannels);
366 SrcDataSize += DataSize;
367 BufferSize -= DataSize;
370 tmpiter = tmpiter->next;
371 if(!tmpiter && Looping)
372 tmpiter = Source->queue;
373 else if(!tmpiter)
375 SilenceStack(&SrcData[SrcDataSize*NumChannels], BufferSize*NumChannels);
376 SrcDataSize += BufferSize;
377 BufferSize -= BufferSize;
382 /* Figure out how many samples we can mix. */
383 DataSize64 = SrcDataSize;
384 DataSize64 -= BufferPadding+BufferPrePadding;
385 DataSize64 <<= FRACTIONBITS;
386 DataSize64 -= increment;
387 DataSize64 -= DataPosFrac;
389 BufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
390 BufferSize = minu(BufferSize, (SamplesToDo-OutPos));
392 /* Some mixers like having a multiple of 4, so try to give that unless
393 * this is the last update. */
394 if(OutPos+BufferSize < SamplesToDo)
395 BufferSize &= ~3;
397 SrcData += BufferPrePadding*NumChannels;
398 for(i = 0;i < NumChannels;i++)
400 DirectParams *directparms = &Source->Params.Direct;
401 ALIGN(16) ALfloat FilteredData[BUFFERSIZE];
402 ALfloat ResampledData[BUFFERSIZE];
404 Resample(Resampler, SrcData+i, DataPosFrac, increment,
405 NumChannels, ResampledData, BufferSize);
407 Filter2P(&directparms->iirFilter, i, FilteredData, ResampledData,
408 BufferSize);
409 Source->Params.DryMix(Source, Device, directparms,
410 FilteredData, i, OutPos, SamplesToDo,
411 BufferSize);
413 for(j = 0;j < Device->NumAuxSends;j++)
415 SendParams *sendparms = &Source->Params.Send[j];
416 if(!sendparms->Slot)
417 continue;
419 Filter2P(&sendparms->iirFilter, i, FilteredData, ResampledData,
420 BufferSize);
421 Source->Params.WetMix(sendparms, FilteredData, OutPos,
422 SamplesToDo, BufferSize);
425 for(i = 0;i < BufferSize;i++)
427 DataPosFrac += increment;
428 DataPosInt += DataPosFrac>>FRACTIONBITS;
429 DataPosFrac &= FRACTIONMASK;
430 OutPos++;
433 /* Handle looping sources */
434 while(1)
436 const ALbuffer *ALBuffer;
437 ALuint DataSize = 0;
438 ALuint LoopStart = 0;
439 ALuint LoopEnd = 0;
441 if((ALBuffer=BufferListItem->buffer) != NULL)
443 DataSize = ALBuffer->SampleLen;
444 LoopStart = ALBuffer->LoopStart;
445 LoopEnd = ALBuffer->LoopEnd;
446 if(LoopEnd > DataPosInt)
447 break;
450 if(Looping && Source->SourceType == AL_STATIC)
452 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
453 break;
456 if(DataSize > DataPosInt)
457 break;
459 if(BufferListItem->next)
461 BufferListItem = BufferListItem->next;
462 BuffersPlayed++;
464 else if(Looping)
466 BufferListItem = Source->queue;
467 BuffersPlayed = 0;
469 else
471 State = AL_STOPPED;
472 BufferListItem = Source->queue;
473 BuffersPlayed = Source->BuffersInQueue;
474 DataPosInt = 0;
475 DataPosFrac = 0;
476 break;
479 DataPosInt -= DataSize;
481 } while(State == AL_PLAYING && OutPos < SamplesToDo);
483 /* Update source info */
484 Source->state = State;
485 Source->BuffersPlayed = BuffersPlayed;
486 Source->position = DataPosInt;
487 Source->position_fraction = DataPosFrac;
488 Source->Hrtf.Offset += OutPos;
489 if(State == AL_PLAYING)
491 Source->Hrtf.Counter = maxu(Source->Hrtf.Counter, OutPos) - OutPos;
492 Source->Hrtf.Moving = AL_TRUE;
494 else
496 Source->Hrtf.Counter = 0;
497 Source->Hrtf.Moving = AL_FALSE;