Document the different filter types, and combine some split lines
[openal-soft.git] / Alc / mixer.c
blobfc3fecbdc5c34153cd149265dd663ed12a13a36b
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 void DoFilter(ALfilterState *filter, ALfloat *restrict dst, const ALfloat *restrict src,
88 ALuint numsamples)
90 ALuint i;
91 for(i = 0;i < numsamples;i++)
92 dst[i] = ALfilterState_processSingle(filter, src[i]);
96 ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
98 ALsource *Source = src->Source;
99 ALbufferlistitem *BufferListItem;
100 ALuint DataPosInt, DataPosFrac;
101 ALboolean Looping;
102 ALuint increment;
103 enum Resampler Resampler;
104 ALenum State;
105 ALuint OutPos;
106 ALuint NumChannels;
107 ALuint SampleSize;
108 ALint64 DataSize64;
109 ALuint chan, j;
111 /* Get source info */
112 State = Source->state;
113 BufferListItem = Source->current_buffer;
114 DataPosInt = Source->position;
115 DataPosFrac = Source->position_fraction;
116 Looping = Source->Looping;
117 increment = src->Step;
118 Resampler = (increment==FRACTIONONE) ? PointResampler : Source->Resampler;
119 NumChannels = Source->NumChannels;
120 SampleSize = Source->SampleSize;
122 /* Get current buffer queue item */
124 OutPos = 0;
125 do {
126 const ALuint BufferPrePadding = ResamplerPrePadding[Resampler];
127 const ALuint BufferPadding = ResamplerPadding[Resampler];
128 ALuint SrcBufferSize, DstBufferSize;
130 /* Figure out how many buffer samples will be needed */
131 DataSize64 = SamplesToDo-OutPos;
132 DataSize64 *= increment;
133 DataSize64 += DataPosFrac+FRACTIONMASK;
134 DataSize64 >>= FRACTIONBITS;
135 DataSize64 += BufferPadding+BufferPrePadding;
137 SrcBufferSize = (ALuint)mini64(DataSize64, BUFFERSIZE);
139 /* Figure out how many samples we can actually mix from this. */
140 DataSize64 = SrcBufferSize;
141 DataSize64 -= BufferPadding+BufferPrePadding;
142 DataSize64 <<= FRACTIONBITS;
143 DataSize64 -= DataPosFrac;
145 DstBufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
146 DstBufferSize = minu(DstBufferSize, (SamplesToDo-OutPos));
148 /* Some mixers like having a multiple of 4, so try to give that unless
149 * this is the last update. */
150 if(OutPos+DstBufferSize < SamplesToDo)
151 DstBufferSize &= ~3;
153 for(chan = 0;chan < NumChannels;chan++)
155 ALfloat *SrcData = Device->SampleData1;
156 ALfloat *ResampledData = Device->SampleData2;
157 ALuint SrcDataSize = 0;
159 if(Source->SourceType == AL_STATIC)
161 const ALbuffer *ALBuffer = Source->queue->buffer;
162 const ALubyte *Data = ALBuffer->data;
163 ALuint DataSize;
164 ALuint pos;
166 /* If current pos is beyond the loop range, do not loop */
167 if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
169 Looping = AL_FALSE;
171 if(DataPosInt >= BufferPrePadding)
172 pos = DataPosInt - BufferPrePadding;
173 else
175 DataSize = BufferPrePadding - DataPosInt;
176 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
178 SilenceData(&SrcData[SrcDataSize], DataSize);
179 SrcDataSize += DataSize;
181 pos = 0;
184 /* Copy what's left to play in the source buffer, and clear the
185 * rest of the temp buffer */
186 DataSize = minu(SrcBufferSize - SrcDataSize, ALBuffer->SampleLen - pos);
188 LoadData(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
189 NumChannels, ALBuffer->FmtType, DataSize);
190 SrcDataSize += DataSize;
192 SilenceData(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
193 SrcDataSize += SrcBufferSize - SrcDataSize;
195 else
197 ALuint LoopStart = ALBuffer->LoopStart;
198 ALuint LoopEnd = ALBuffer->LoopEnd;
200 if(DataPosInt >= LoopStart)
202 pos = DataPosInt-LoopStart;
203 while(pos < BufferPrePadding)
204 pos += LoopEnd-LoopStart;
205 pos -= BufferPrePadding;
206 pos += LoopStart;
208 else if(DataPosInt >= BufferPrePadding)
209 pos = DataPosInt - BufferPrePadding;
210 else
212 DataSize = BufferPrePadding - DataPosInt;
213 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
215 SilenceData(&SrcData[SrcDataSize], DataSize);
216 SrcDataSize += DataSize;
218 pos = 0;
221 /* Copy what's left of this loop iteration, then copy repeats
222 * of the loop section */
223 DataSize = LoopEnd - pos;
224 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
226 LoadData(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
227 NumChannels, ALBuffer->FmtType, DataSize);
228 SrcDataSize += DataSize;
230 DataSize = LoopEnd-LoopStart;
231 while(SrcBufferSize > SrcDataSize)
233 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
235 LoadData(&SrcData[SrcDataSize], &Data[(LoopStart*NumChannels + chan)*SampleSize],
236 NumChannels, ALBuffer->FmtType, DataSize);
237 SrcDataSize += DataSize;
241 else
243 /* Crawl the buffer queue to fill in the temp buffer */
244 ALbufferlistitem *tmpiter = BufferListItem;
245 ALuint pos;
247 if(DataPosInt >= BufferPrePadding)
248 pos = DataPosInt - BufferPrePadding;
249 else
251 pos = BufferPrePadding - DataPosInt;
252 while(pos > 0)
254 ALbufferlistitem *prev;
255 if((prev=tmpiter->prev) != NULL)
256 tmpiter = prev;
257 else if(Looping)
259 while(tmpiter->next)
260 tmpiter = tmpiter->next;
262 else
264 ALuint DataSize = minu(SrcBufferSize - SrcDataSize, pos);
266 SilenceData(&SrcData[SrcDataSize], DataSize);
267 SrcDataSize += DataSize;
269 pos = 0;
270 break;
273 if(tmpiter->buffer)
275 if((ALuint)tmpiter->buffer->SampleLen > pos)
277 pos = tmpiter->buffer->SampleLen - pos;
278 break;
280 pos -= tmpiter->buffer->SampleLen;
285 while(tmpiter && SrcBufferSize > SrcDataSize)
287 const ALbuffer *ALBuffer;
288 if((ALBuffer=tmpiter->buffer) != NULL)
290 const ALubyte *Data = ALBuffer->data;
291 ALuint DataSize = ALBuffer->SampleLen;
293 /* Skip the data already played */
294 if(DataSize <= pos)
295 pos -= DataSize;
296 else
298 Data += (pos*NumChannels + chan)*SampleSize;
299 DataSize -= pos;
300 pos -= pos;
302 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
303 LoadData(&SrcData[SrcDataSize], Data, NumChannels,
304 ALBuffer->FmtType, DataSize);
305 SrcDataSize += DataSize;
308 tmpiter = tmpiter->next;
309 if(!tmpiter && Looping)
310 tmpiter = Source->queue;
311 else if(!tmpiter)
313 SilenceData(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
314 SrcDataSize += SrcBufferSize - SrcDataSize;
319 /* Now resample, then filter and mix to the appropriate outputs. */
320 src->Resample(&SrcData[BufferPrePadding], DataPosFrac,
321 increment, ResampledData, DstBufferSize);
324 DirectParams *directparms = &src->Direct;
326 DoFilter(&directparms->LpFilter[chan], SrcData, ResampledData,
327 DstBufferSize);
328 src->DryMix(directparms, SrcData, chan, OutPos, DstBufferSize);
331 for(j = 0;j < Device->NumAuxSends;j++)
333 SendParams *sendparms = &src->Send[j];
334 if(!sendparms->OutBuffer)
335 continue;
337 DoFilter(&sendparms->LpFilter[chan], SrcData, ResampledData,
338 DstBufferSize);
339 src->WetMix(sendparms, SrcData, OutPos, DstBufferSize);
342 /* Update positions */
343 for(j = 0;j < DstBufferSize;j++)
345 DataPosFrac += increment;
346 DataPosInt += DataPosFrac>>FRACTIONBITS;
347 DataPosFrac &= FRACTIONMASK;
349 OutPos += DstBufferSize;
351 /* Handle looping sources */
352 while(1)
354 const ALbuffer *ALBuffer;
355 ALuint DataSize = 0;
356 ALuint LoopStart = 0;
357 ALuint LoopEnd = 0;
359 if((ALBuffer=BufferListItem->buffer) != NULL)
361 DataSize = ALBuffer->SampleLen;
362 LoopStart = ALBuffer->LoopStart;
363 LoopEnd = ALBuffer->LoopEnd;
364 if(LoopEnd > DataPosInt)
365 break;
368 if(Looping && Source->SourceType == AL_STATIC)
370 assert(LoopEnd > LoopStart);
371 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
372 break;
375 if(DataSize > DataPosInt)
376 break;
378 if(BufferListItem->next)
379 BufferListItem = BufferListItem->next;
380 else if(Looping)
381 BufferListItem = Source->queue;
382 else
384 State = AL_STOPPED;
385 BufferListItem = NULL;
386 DataPosInt = 0;
387 DataPosFrac = 0;
388 break;
391 DataPosInt -= DataSize;
393 } while(State == AL_PLAYING && OutPos < SamplesToDo);
395 /* Update source info */
396 Source->state = State;
397 Source->current_buffer = BufferListItem;
398 Source->position = DataPosInt;
399 Source->position_fraction = DataPosFrac;
400 src->Direct.Offset += OutPos;
401 src->Direct.Counter = maxu(src->Direct.Counter, OutPos) - OutPos;