Add a flag to specify when the low-pass filter needs to apply
[openal-soft.git] / Alc / mixer.c
blobac433e3522814b233553619fa526ba36f5d6ca3f
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 DoFilters(ALfilterState *lpfilter, ALfloat *restrict dst, const ALfloat *restrict src,
88 ALuint numsamples, enum ActiveFilters type)
90 ALuint i;
91 switch(type)
93 case AF_None:
94 memcpy(dst, src, numsamples * sizeof(ALfloat));
95 break;
97 case AF_LowPass:
98 for(i = 0;i < numsamples;i++)
99 dst[i] = ALfilterState_processSingle(lpfilter, src[i]);
100 break;
105 ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
107 ALsource *Source = src->Source;
108 ALbufferlistitem *BufferListItem;
109 ALuint DataPosInt, DataPosFrac;
110 ALboolean Looping;
111 ALuint increment;
112 enum Resampler Resampler;
113 ALenum State;
114 ALuint OutPos;
115 ALuint NumChannels;
116 ALuint SampleSize;
117 ALint64 DataSize64;
118 ALuint chan, j;
120 /* Get source info */
121 State = Source->state;
122 BufferListItem = Source->current_buffer;
123 DataPosInt = Source->position;
124 DataPosFrac = Source->position_fraction;
125 Looping = Source->Looping;
126 increment = src->Step;
127 Resampler = (increment==FRACTIONONE) ? PointResampler : Source->Resampler;
128 NumChannels = Source->NumChannels;
129 SampleSize = Source->SampleSize;
131 /* Get current buffer queue item */
133 OutPos = 0;
134 do {
135 const ALuint BufferPrePadding = ResamplerPrePadding[Resampler];
136 const ALuint BufferPadding = ResamplerPadding[Resampler];
137 ALuint SrcBufferSize, DstBufferSize;
139 /* Figure out how many buffer samples will be needed */
140 DataSize64 = SamplesToDo-OutPos;
141 DataSize64 *= increment;
142 DataSize64 += DataPosFrac+FRACTIONMASK;
143 DataSize64 >>= FRACTIONBITS;
144 DataSize64 += BufferPadding+BufferPrePadding;
146 SrcBufferSize = (ALuint)mini64(DataSize64, BUFFERSIZE);
148 /* Figure out how many samples we can actually mix from this. */
149 DataSize64 = SrcBufferSize;
150 DataSize64 -= BufferPadding+BufferPrePadding;
151 DataSize64 <<= FRACTIONBITS;
152 DataSize64 -= DataPosFrac;
154 DstBufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
155 DstBufferSize = minu(DstBufferSize, (SamplesToDo-OutPos));
157 /* Some mixers like having a multiple of 4, so try to give that unless
158 * this is the last update. */
159 if(OutPos+DstBufferSize < SamplesToDo)
160 DstBufferSize &= ~3;
162 for(chan = 0;chan < NumChannels;chan++)
164 ALfloat *SrcData = Device->SampleData1;
165 ALfloat *ResampledData = Device->SampleData2;
166 ALuint SrcDataSize = 0;
168 if(Source->SourceType == AL_STATIC)
170 const ALbuffer *ALBuffer = Source->queue->buffer;
171 const ALubyte *Data = ALBuffer->data;
172 ALuint DataSize;
173 ALuint pos;
175 /* If current pos is beyond the loop range, do not loop */
176 if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
178 Looping = AL_FALSE;
180 if(DataPosInt >= BufferPrePadding)
181 pos = DataPosInt - BufferPrePadding;
182 else
184 DataSize = BufferPrePadding - DataPosInt;
185 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
187 SilenceData(&SrcData[SrcDataSize], DataSize);
188 SrcDataSize += DataSize;
190 pos = 0;
193 /* Copy what's left to play in the source buffer, and clear the
194 * rest of the temp buffer */
195 DataSize = minu(SrcBufferSize - SrcDataSize, ALBuffer->SampleLen - pos);
197 LoadData(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
198 NumChannels, ALBuffer->FmtType, DataSize);
199 SrcDataSize += DataSize;
201 SilenceData(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
202 SrcDataSize += SrcBufferSize - SrcDataSize;
204 else
206 ALuint LoopStart = ALBuffer->LoopStart;
207 ALuint LoopEnd = ALBuffer->LoopEnd;
209 if(DataPosInt >= LoopStart)
211 pos = DataPosInt-LoopStart;
212 while(pos < BufferPrePadding)
213 pos += LoopEnd-LoopStart;
214 pos -= BufferPrePadding;
215 pos += LoopStart;
217 else if(DataPosInt >= BufferPrePadding)
218 pos = DataPosInt - BufferPrePadding;
219 else
221 DataSize = BufferPrePadding - DataPosInt;
222 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
224 SilenceData(&SrcData[SrcDataSize], DataSize);
225 SrcDataSize += DataSize;
227 pos = 0;
230 /* Copy what's left of this loop iteration, then copy repeats
231 * of the loop section */
232 DataSize = LoopEnd - pos;
233 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
235 LoadData(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
236 NumChannels, ALBuffer->FmtType, DataSize);
237 SrcDataSize += DataSize;
239 DataSize = LoopEnd-LoopStart;
240 while(SrcBufferSize > SrcDataSize)
242 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
244 LoadData(&SrcData[SrcDataSize], &Data[(LoopStart*NumChannels + chan)*SampleSize],
245 NumChannels, ALBuffer->FmtType, DataSize);
246 SrcDataSize += DataSize;
250 else
252 /* Crawl the buffer queue to fill in the temp buffer */
253 ALbufferlistitem *tmpiter = BufferListItem;
254 ALuint pos;
256 if(DataPosInt >= BufferPrePadding)
257 pos = DataPosInt - BufferPrePadding;
258 else
260 pos = BufferPrePadding - DataPosInt;
261 while(pos > 0)
263 ALbufferlistitem *prev;
264 if((prev=tmpiter->prev) != NULL)
265 tmpiter = prev;
266 else if(Looping)
268 while(tmpiter->next)
269 tmpiter = tmpiter->next;
271 else
273 ALuint DataSize = minu(SrcBufferSize - SrcDataSize, pos);
275 SilenceData(&SrcData[SrcDataSize], DataSize);
276 SrcDataSize += DataSize;
278 pos = 0;
279 break;
282 if(tmpiter->buffer)
284 if((ALuint)tmpiter->buffer->SampleLen > pos)
286 pos = tmpiter->buffer->SampleLen - pos;
287 break;
289 pos -= tmpiter->buffer->SampleLen;
294 while(tmpiter && SrcBufferSize > SrcDataSize)
296 const ALbuffer *ALBuffer;
297 if((ALBuffer=tmpiter->buffer) != NULL)
299 const ALubyte *Data = ALBuffer->data;
300 ALuint DataSize = ALBuffer->SampleLen;
302 /* Skip the data already played */
303 if(DataSize <= pos)
304 pos -= DataSize;
305 else
307 Data += (pos*NumChannels + chan)*SampleSize;
308 DataSize -= pos;
309 pos -= pos;
311 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
312 LoadData(&SrcData[SrcDataSize], Data, NumChannels,
313 ALBuffer->FmtType, DataSize);
314 SrcDataSize += DataSize;
317 tmpiter = tmpiter->next;
318 if(!tmpiter && Looping)
319 tmpiter = Source->queue;
320 else if(!tmpiter)
322 SilenceData(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
323 SrcDataSize += SrcBufferSize - SrcDataSize;
328 /* Now resample, then filter and mix to the appropriate outputs. */
329 src->Resample(&SrcData[BufferPrePadding], DataPosFrac,
330 increment, ResampledData, DstBufferSize);
333 DirectParams *directparms = &src->Direct;
335 DoFilters(&directparms->LpFilter[chan], SrcData, ResampledData,
336 DstBufferSize, directparms->Filters[chan]);
337 src->DryMix(directparms, SrcData, chan, OutPos, DstBufferSize);
340 for(j = 0;j < Device->NumAuxSends;j++)
342 SendParams *sendparms = &src->Send[j];
343 if(!sendparms->OutBuffer)
344 continue;
346 DoFilters(&sendparms->LpFilter[chan], SrcData, ResampledData,
347 DstBufferSize, sendparms->Filters[chan]);
348 src->WetMix(sendparms, SrcData, OutPos, DstBufferSize);
351 /* Update positions */
352 for(j = 0;j < DstBufferSize;j++)
354 DataPosFrac += increment;
355 DataPosInt += DataPosFrac>>FRACTIONBITS;
356 DataPosFrac &= FRACTIONMASK;
358 OutPos += DstBufferSize;
360 /* Handle looping sources */
361 while(1)
363 const ALbuffer *ALBuffer;
364 ALuint DataSize = 0;
365 ALuint LoopStart = 0;
366 ALuint LoopEnd = 0;
368 if((ALBuffer=BufferListItem->buffer) != NULL)
370 DataSize = ALBuffer->SampleLen;
371 LoopStart = ALBuffer->LoopStart;
372 LoopEnd = ALBuffer->LoopEnd;
373 if(LoopEnd > DataPosInt)
374 break;
377 if(Looping && Source->SourceType == AL_STATIC)
379 assert(LoopEnd > LoopStart);
380 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
381 break;
384 if(DataSize > DataPosInt)
385 break;
387 if(BufferListItem->next)
388 BufferListItem = BufferListItem->next;
389 else if(Looping)
390 BufferListItem = Source->queue;
391 else
393 State = AL_STOPPED;
394 BufferListItem = NULL;
395 DataPosInt = 0;
396 DataPosFrac = 0;
397 break;
400 DataPosInt -= DataSize;
402 } while(State == AL_PLAYING && OutPos < SamplesToDo);
404 /* Update source info */
405 Source->state = State;
406 Source->current_buffer = BufferListItem;
407 Source->position = DataPosInt;
408 Source->position_fraction = DataPosFrac;
409 src->Direct.Offset += OutPos;
410 src->Direct.Counter = maxu(src->Direct.Counter, OutPos) - OutPos;