zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
mixer.c
Go to the documentation of this file.
1 
21 #include "config.h"
22 
23 #include <math.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <assert.h>
28 
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"
38 
39 
40 static __inline ALfloat Sample_ALbyte(ALbyte val)
41 { return val * (1.0f/127.0f); }
42 
44 { return val * (1.0f/32767.0f); }
45 
47 { return val; }
48 
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]); \
55 }
56 
60 
61 #undef DECL_TEMPLATE
62 
63 static void LoadData(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum FmtType srctype, ALuint samples)
64 {
65  switch(srctype)
66  {
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;
76  }
77 }
78 
80 {
81  ALuint i;
82  for(i = 0;i < samples;i++)
83  dst[i] = 0.0f;
84 }
85 
86 
87 static void Filter2P(FILTER *filter, ALuint chan, ALfloat *RESTRICT dst,
88  const ALfloat *RESTRICT src, ALuint numsamples)
89 {
90  ALuint i;
91  for(i = 0;i < numsamples;i++)
92  dst[i] = lpFilter2P(filter, chan, src[i]);
93  dst[i] = lpFilter2PC(filter, chan, src[i]);
94 }
95 
96 
97 ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
98 {
99  ALbufferlistitem *BufferListItem;
100  ALuint DataPosInt, DataPosFrac;
101  ALuint BuffersPlayed;
102  ALboolean Looping;
103  ALuint increment;
104  enum Resampler Resampler;
105  ALenum State;
106  ALuint OutPos;
107  ALuint NumChannels;
108  ALuint SampleSize;
109  ALint64 DataSize64;
110  ALuint chan, j;
111 
112  /* Get source info */
113  State = Source->state;
114  BuffersPlayed = Source->BuffersPlayed;
115  DataPosInt = Source->position;
116  DataPosFrac = Source->position_fraction;
117  Looping = Source->Looping;
118  increment = Source->Params.Step;
119  Resampler = (increment==FRACTIONONE) ? PointResampler : Source->Resampler;
120  NumChannels = Source->NumChannels;
121  SampleSize = Source->SampleSize;
122 
123  /* Get current buffer queue item */
124  BufferListItem = Source->queue;
125  for(j = 0;j < BuffersPlayed;j++)
126  BufferListItem = BufferListItem->next;
127 
128  OutPos = 0;
129  do {
130  const ALuint BufferPrePadding = ResamplerPrePadding[Resampler];
131  const ALuint BufferPadding = ResamplerPadding[Resampler];
132  ALuint SrcBufferSize, DstBufferSize;
133 
134  /* Figure out how many buffer bytes will be needed */
135  DataSize64 = SamplesToDo-OutPos+1;
136  DataSize64 *= increment;
137  DataSize64 += DataPosFrac+FRACTIONMASK;
138  DataSize64 >>= FRACTIONBITS;
139  DataSize64 += BufferPadding+BufferPrePadding;
140 
141  SrcBufferSize = (ALuint)mini64(DataSize64, BUFFERSIZE);
142 
143  /* Figure out how many samples we can actually mix from this. */
144  DataSize64 = SrcBufferSize;
145  DataSize64 -= BufferPadding+BufferPrePadding;
146  DataSize64 <<= FRACTIONBITS;
147  DataSize64 -= increment;
148  DataSize64 -= DataPosFrac;
149 
150  DstBufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
151  DstBufferSize = minu(DstBufferSize, (SamplesToDo-OutPos));
152 
153  /* Some mixers like having a multiple of 4, so try to give that unless
154  * this is the last update. */
155  if(OutPos+DstBufferSize < SamplesToDo)
156  DstBufferSize &= ~3;
157 
158  for(chan = 0;chan < NumChannels;chan++)
159  {
160  ALfloat *SrcData = Device->SampleData1;
161  ALfloat *ResampledData = Device->SampleData2;
162  ALuint SrcDataSize = 0;
163 
164  if(Source->SourceType == AL_STATIC)
165  {
166  const ALbuffer *ALBuffer = Source->queue->buffer;
167  const ALubyte *Data = ALBuffer->data;
168  ALuint DataSize;
169  ALuint pos;
170 
171  /* If current pos is beyond the loop range, do not loop */
172  if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
173  {
174  Looping = AL_FALSE;
175 
176  if(DataPosInt >= BufferPrePadding)
177  pos = DataPosInt - BufferPrePadding;
178  else
179  {
180  DataSize = BufferPrePadding - DataPosInt;
181  DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
182 
183  SilenceData(&SrcData[SrcDataSize], DataSize);
184  SrcDataSize += DataSize;
185 
186  pos = 0;
187  }
188 
189  /* Copy what's left to play in the source buffer, and clear the
190  * rest of the temp buffer */
191  DataSize = minu(SrcBufferSize - SrcDataSize, ALBuffer->SampleLen - pos);
192 
193  LoadData(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
194  NumChannels, ALBuffer->FmtType, DataSize);
195  SrcDataSize += DataSize;
196 
197  SilenceData(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
198  SrcDataSize += SrcBufferSize - SrcDataSize;
199  }
200  else
201  {
202  ALuint LoopStart = ALBuffer->LoopStart;
203  ALuint LoopEnd = ALBuffer->LoopEnd;
204 
205  if(DataPosInt >= LoopStart)
206  {
207  pos = DataPosInt-LoopStart;
208  while(pos < BufferPrePadding)
209  pos += LoopEnd-LoopStart;
210  pos -= BufferPrePadding;
211  pos += LoopStart;
212  }
213  else if(DataPosInt >= BufferPrePadding)
214  pos = DataPosInt - BufferPrePadding;
215  else
216  {
217  DataSize = BufferPrePadding - DataPosInt;
218  DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
219 
220  SilenceData(&SrcData[SrcDataSize], DataSize);
221  SrcDataSize += DataSize;
222 
223  pos = 0;
224  }
225 
226  /* Copy what's left of this loop iteration, then copy repeats
227  * of the loop section */
228  DataSize = LoopEnd - pos;
229  DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
230 
231  LoadData(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
232  NumChannels, ALBuffer->FmtType, DataSize);
233  SrcDataSize += DataSize;
234 
235  DataSize = LoopEnd-LoopStart;
236  while(SrcBufferSize > SrcDataSize)
237  {
238  DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
239 
240  LoadData(&SrcData[SrcDataSize], &Data[(LoopStart*NumChannels + chan)*SampleSize],
241  NumChannels, ALBuffer->FmtType, DataSize);
242  SrcDataSize += DataSize;
243  }
244  }
245  }
246  else
247  {
248  /* Crawl the buffer queue to fill in the temp buffer */
249  ALbufferlistitem *tmpiter = BufferListItem;
250  ALuint pos;
251 
252  if(DataPosInt >= BufferPrePadding)
253  pos = DataPosInt - BufferPrePadding;
254  else
255  {
256  pos = BufferPrePadding - DataPosInt;
257  while(pos > 0)
258  {
259  if(!tmpiter->prev && !Looping)
260  {
261  ALuint DataSize = minu(SrcBufferSize - SrcDataSize, pos);
262 
263  SilenceData(&SrcData[SrcDataSize], DataSize);
264  SrcDataSize += DataSize;
265 
266  pos = 0;
267  break;
268  }
269 
270  if(tmpiter->prev)
271  tmpiter = tmpiter->prev;
272  else
273  {
274  while(tmpiter->next)
275  tmpiter = tmpiter->next;
276  }
277 
278  if(tmpiter->buffer)
279  {
280  if((ALuint)tmpiter->buffer->SampleLen > pos)
281  {
282  pos = tmpiter->buffer->SampleLen - pos;
283  break;
284  }
285  pos -= tmpiter->buffer->SampleLen;
286  }
287  }
288  }
289 
290  while(tmpiter && SrcBufferSize > SrcDataSize)
291  {
292  const ALbuffer *ALBuffer;
293  if((ALBuffer=tmpiter->buffer) != NULL)
294  {
295  const ALubyte *Data = ALBuffer->data;
296  ALuint DataSize = ALBuffer->SampleLen;
297 
298  /* Skip the data already played */
299  if(DataSize <= pos)
300  pos -= DataSize;
301  else
302  {
303  Data += (pos*NumChannels + chan)*SampleSize;
304  DataSize -= pos;
305  pos -= pos;
306 
307  DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
308  LoadData(&SrcData[SrcDataSize], Data, NumChannels,
309  ALBuffer->FmtType, DataSize);
310  SrcDataSize += DataSize;
311  }
312  }
313  tmpiter = tmpiter->next;
314  if(!tmpiter && Looping)
315  tmpiter = Source->queue;
316  else if(!tmpiter)
317  {
318  SilenceData(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
319  SrcDataSize += SrcBufferSize - SrcDataSize;
320  }
321  }
322  }
323 
324  /* Now resample, then filter and mix to the appropriate outputs. */
325  Source->Params.Resample(&SrcData[BufferPrePadding], DataPosFrac,
326  increment, ResampledData, DstBufferSize);
327 
328  {
329  DirectParams *directparms = &Source->Params.Direct;
330 
331  Filter2P(&directparms->iirFilter, chan, SrcData, ResampledData,
332  DstBufferSize);
333  Source->Params.DryMix(directparms, SrcData, chan, OutPos,
334  SamplesToDo, DstBufferSize);
335  }
336 
337  for(j = 0;j < Device->NumAuxSends;j++)
338  {
339  SendParams *sendparms = &Source->Params.Send[j];
340  if(!sendparms->Slot)
341  continue;
342 
343  Filter2P(&sendparms->iirFilter, chan, SrcData, ResampledData,
344  DstBufferSize);
345  Source->Params.WetMix(sendparms, SrcData, OutPos,
346  SamplesToDo, DstBufferSize);
347  }
348  }
349  /* Update positions */
350  for(j = 0;j < DstBufferSize;j++)
351  {
352  DataPosFrac += increment;
353  DataPosInt += DataPosFrac>>FRACTIONBITS;
354  DataPosFrac &= FRACTIONMASK;
355  }
356  OutPos += DstBufferSize;
357 
358  /* Handle looping sources */
359  while(1)
360  {
361  const ALbuffer *ALBuffer;
362  ALuint DataSize = 0;
363  ALuint LoopStart = 0;
364  ALuint LoopEnd = 0;
365 
366  if((ALBuffer=BufferListItem->buffer) != NULL)
367  {
368  DataSize = ALBuffer->SampleLen;
369  LoopStart = ALBuffer->LoopStart;
370  LoopEnd = ALBuffer->LoopEnd;
371  if(LoopEnd > DataPosInt)
372  break;
373  }
374 
375  if(Looping && Source->SourceType == AL_STATIC)
376  {
377  DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
378  break;
379  }
380 
381  if(DataSize > DataPosInt)
382  break;
383 
384  if(BufferListItem->next)
385  {
386  BufferListItem = BufferListItem->next;
387  BuffersPlayed++;
388  }
389  else if(Looping)
390  {
391  BufferListItem = Source->queue;
392  BuffersPlayed = 0;
393  }
394  else
395  {
396  State = AL_STOPPED;
397  BufferListItem = Source->queue;
398  BuffersPlayed = Source->BuffersInQueue;
399  DataPosInt = 0;
400  DataPosFrac = 0;
401  break;
402  }
403 
404  DataPosInt -= DataSize;
405  }
406  } while(State == AL_PLAYING && OutPos < SamplesToDo);
407 
408  /* Update source info */
409  Source->state = State;
410  Source->BuffersPlayed = BuffersPlayed;
411  Source->position = DataPosInt;
412  Source->position_fraction = DataPosFrac;
413  Source->Hrtf.Offset += OutPos;
414  if(State == AL_PLAYING)
415  Source->Hrtf.Counter = maxu(Source->Hrtf.Counter, OutPos) - OutPos;
416  else
417  {
418  Source->Hrtf.Counter = 0;
419  Source->Hrtf.Moving = AL_FALSE;
420  }
421 }
ALvoid * data
Definition: alBuffer.h:71
unsigned char ALubyte
Definition: al.h:47
GLuint const GLfloat * val
Definition: glew.h:2715
void ALvoid
Definition: al.h:74
#define AL_STOPPED
Definition: al.h:241
enum FmtType FmtType
Definition: alBuffer.h:78
volatile ALenum state
Definition: alSource.h:125
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: gl2ext.h:961
#define NULL
Definition: ftobjs.h:61
GLclampf f
Definition: glew.h:3390
ALuint position
Definition: alSource.h:133
FILTER iirFilter
Definition: alSource.h:77
const ALsizei ResamplerPadding[ResamplerMax]
Definition: alSource.c:38
ALuint NumAuxSends
Definition: alMain.h:586
static void Filter2P(FILTER *filter, ALuint chan, ALfloat *RESTRICT dst, const ALfloat *RESTRICT src, ALuint numsamples)
Definition: mixer.c:87
int32_t j
Definition: e_log.c:102
#define AL_FALSE
Definition: al.h:83
#define FRACTIONONE
Definition: alu.h:50
short ALshort
Definition: al.h:50
static __inline ALint64 mini64(ALint64 a, ALint64 b)
Definition: alu.h:75
float ALfloat
Definition: al.h:68
ALsizei SampleLen
Definition: alBuffer.h:75
DryMixerFunc DryMix
Definition: alSource.h:161
signed char ALbyte
Definition: al.h:44
FILTER iirFilter
Definition: alSource.h:65
static __inline ALfloat lpFilter2P(FILTER *iir, ALuint offset, ALfloat input)
Definition: alFilter.h:21
ALint Step
Definition: alSource.h:164
ALsizei LoopStart
Definition: alBuffer.h:84
enum Resampler Resampler
Definition: alSource.h:112
ALuint position_fraction
Definition: alSource.h:134
#define AL_PLAYING
Definition: al.h:239
FmtType
Definition: alBuffer.h:46
GLenum GLenum dst
Definition: glew.h:2396
struct ALeffectslot * Slot
Definition: alSource.h:70
static __inline ALfloat Sample_ALfloat(ALfloat val)
Definition: mixer.c:46
static __inline ALfloat Sample_ALbyte(ALbyte val)
Definition: mixer.c:40
ALuint SampleSize
Definition: alSource.h:143
ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
Definition: mixer.c:97
WetMixerFunc WetMix
Definition: alSource.h:162
const ALsizei ResamplerPrePadding[ResamplerMax]
Definition: alSource.c:43
GLsizei samples
Definition: gl2ext.h:970
static __inline ALfloat Sample_ALshort(ALshort val)
Definition: mixer.c:43
ResamplerFunc Resample
Definition: alSource.h:160
int ALenum
Definition: al.h:65
#define DECL_TEMPLATE(T)
Definition: mixer.c:49
static void LoadData(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum FmtType srctype, ALuint samples)
Definition: mixer.c:63
unsigned int ALuint
Definition: al.h:59
enum State_ State
DirectParams Direct
Definition: alSource.h:166
static __inline ALuint minu(ALuint a, ALuint b)
Definition: alu.h:61
#define AL_STATIC
Definition: al.h:334
ALuint NumChannels
Definition: alSource.h:142
struct ALbuffer * buffer
Definition: alSource.h:26
#define FRACTIONMASK
Definition: alu.h:51
ALboolean Moving
Definition: alSource.h:32
volatile ALboolean Looping
Definition: alSource.h:99
#define FRACTIONBITS
Definition: alu.h:49
Resampler
Definition: alMain.h:472
struct ALbufferlistitem * next
Definition: alSource.h:27
struct ALsource::@62 Params
ALuint Counter
Definition: alSource.h:33
char ALboolean
Definition: al.h:38
static void SilenceData(ALfloat *dst, ALuint samples)
Definition: mixer.c:79
ALuint BuffersInQueue
Definition: alSource.h:138
GLenum src
Definition: glew.h:2396
struct ALbufferlistitem * prev
Definition: alSource.h:28
int i
Definition: pngrutil.c:1377
volatile ALint SourceType
Definition: alSource.h:122
struct ALsource::@61 Send[MAX_SENDS]
#define BUFFERSIZE
Definition: alMain.h:556
static __inline ALfloat lpFilter2PC(const FILTER *iir, ALuint offset, ALfloat input)
Definition: alFilter.h:35
ALuint BuffersPlayed
Definition: alSource.h:139
ALsizei LoopEnd
Definition: alBuffer.h:85
static __inline ALuint maxu(ALuint a, ALuint b)
Definition: alu.h:63
ALbufferlistitem * queue
Definition: alSource.h:137
HrtfState Hrtf
Definition: alSource.h:156
ALuint Offset
Definition: alSource.h:36