Move an HRTF mixer parameter and shorten a couple variable names
[openal-soft.git] / Alc / mixer.c
blob7b0b9d308b3fe87afd13e37e88b0d49be934b54d
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, 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 memcpy(dst, src, numsamples * sizeof(ALfloat));
96 break;
98 case AF_LowPass:
99 ALfilterState_process(lpfilter, dst, src, numsamples);
100 break;
101 case AF_HighPass:
102 ALfilterState_process(hpfilter, dst, src, numsamples);
103 break;
105 case AF_BandPass:
106 for(i = 0;i < numsamples;)
108 ALfloat temp[64];
109 ALuint todo = minu(64, numsamples-i);
111 ALfilterState_process(lpfilter, temp, src, todo);
112 ALfilterState_process(hpfilter, dst, temp, todo);
113 i += todo;
115 break;
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 ALfloat *SrcData = Device->SampleData1;
180 ALfloat *ResampledData = Device->SampleData2;
181 ALuint SrcDataSize = 0;
183 if(Source->SourceType == AL_STATIC)
185 const ALbuffer *ALBuffer = Source->queue->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 src->Resample(&SrcData[BufferPrePadding], DataPosFrac,
345 increment, ResampledData, DstBufferSize);
348 DirectParams *parms = &src->Direct;
350 DoFilters(&parms->LpFilter[chan], &parms->HpFilter[chan], SrcData,
351 ResampledData, DstBufferSize, parms->Filters[chan]);
352 if(!src->IsHrtf)
353 src->Dry.Mix(parms->OutBuffer, SrcData, &parms->Mix.Gains[chan],
354 maxu(parms->Counter, OutPos) - OutPos, OutPos,
355 DstBufferSize);
356 else
357 src->Dry.HrtfMix(parms->OutBuffer, SrcData,
358 maxu(parms->Counter, OutPos) - OutPos,
359 parms->Offset + OutPos, OutPos,
360 parms->Mix.Hrtf.IrSize, &parms->Mix.Hrtf.Params[chan],
361 &parms->Mix.Hrtf.State[chan], DstBufferSize);
364 for(j = 0;j < Device->NumAuxSends;j++)
366 SendParams *parms = &src->Send[j];
367 if(!parms->OutBuffer)
368 continue;
370 DoFilters(&parms->LpFilter[chan], &parms->HpFilter[chan],
371 SrcData, ResampledData, DstBufferSize,
372 parms->Filters[chan]);
373 src->WetMix(parms->OutBuffer, SrcData, &parms->Gain,
374 maxu(parms->Counter, OutPos) - OutPos,
375 OutPos, DstBufferSize);
378 /* Update positions */
379 for(j = 0;j < DstBufferSize;j++)
381 DataPosFrac += increment;
382 DataPosInt += DataPosFrac>>FRACTIONBITS;
383 DataPosFrac &= FRACTIONMASK;
385 OutPos += DstBufferSize;
387 /* Handle looping sources */
388 while(1)
390 const ALbuffer *ALBuffer;
391 ALuint DataSize = 0;
392 ALuint LoopStart = 0;
393 ALuint LoopEnd = 0;
395 if((ALBuffer=BufferListItem->buffer) != NULL)
397 DataSize = ALBuffer->SampleLen;
398 LoopStart = ALBuffer->LoopStart;
399 LoopEnd = ALBuffer->LoopEnd;
400 if(LoopEnd > DataPosInt)
401 break;
404 if(Looping && Source->SourceType == AL_STATIC)
406 assert(LoopEnd > LoopStart);
407 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
408 break;
411 if(DataSize > DataPosInt)
412 break;
414 if(BufferListItem->next)
415 BufferListItem = BufferListItem->next;
416 else if(Looping)
417 BufferListItem = Source->queue;
418 else
420 State = AL_STOPPED;
421 BufferListItem = NULL;
422 DataPosInt = 0;
423 DataPosFrac = 0;
424 break;
427 DataPosInt -= DataSize;
429 } while(State == AL_PLAYING && OutPos < SamplesToDo);
431 /* Update source info */
432 Source->state = State;
433 Source->current_buffer = BufferListItem;
434 Source->position = DataPosInt;
435 Source->position_fraction = DataPosFrac;
436 src->Direct.Offset += OutPos;
437 src->Direct.Counter = maxu(src->Direct.Counter, OutPos) - OutPos;