~ubuntu-branches/ubuntu/wily/openal-soft/wily-proposed

« back to all changes in this revision

Viewing changes to Alc/mixer.c

  • Committer: Package Import Robot
  • Author(s): Bret Curtis
  • Date: 2014-07-16 08:35:25 UTC
  • mfrom: (0.2.10)
  • Revision ID: package-import@ubuntu.com-20140716083525-5rldbuk4mo211l1a
Tags: 1:1.15.1-1
* Added openal-info binary. (Closes: 659198)
* Added makehrtf binary.
* Added 'audio' to short description. (Closes: 598064) 
* Added FLAGS fixes for cmake in rules for hardening.
* Added man pages for the two binaries.
* New upstream release. (Closes: 731159)
* Removed libsndio-dlopen-change.patch, no longer required.
* Removed no-fpuextended.patch, macros no longer used.
* Removed need for lintian overrides.

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
#include "bs2b.h"
38
38
 
39
39
 
40
 
static __inline ALfloat point32(const ALfloat *vals, ALint step, ALint frac)
41
 
{ return vals[0]; (void)step; (void)frac; }
42
 
static __inline ALfloat lerp32(const ALfloat *vals, ALint step, ALint frac)
43
 
{ return lerp(vals[0], vals[step], frac * (1.0f/FRACTIONONE)); }
44
 
static __inline ALfloat cubic32(const ALfloat *vals, ALint step, ALint frac)
45
 
{ return cubic(vals[-step], vals[0], vals[step], vals[step+step],
46
 
               frac * (1.0f/FRACTIONONE)); }
47
 
 
48
 
#ifdef __GNUC__
49
 
#define LIKELY(x) __builtin_expect(!!(x), 1)
50
 
#define UNLIKELY(x) __builtin_expect(!!(x), 0)
51
 
#else
52
 
#define LIKELY(x) (x)
53
 
#define UNLIKELY(x) (x)
54
 
#endif
55
 
 
56
 
#if defined(__ARM_NEON__) && defined(HAVE_ARM_NEON_H)
57
 
#include <arm_neon.h>
58
 
 
59
 
static __inline void ApplyCoeffs(ALuint Offset, ALfloat (*RESTRICT Values)[2],
60
 
                                 ALfloat (*RESTRICT Coeffs)[2],
61
 
                                 ALfloat left, ALfloat right)
62
 
{
63
 
    ALuint c;
64
 
    float32x4_t leftright4;
65
 
    {
66
 
        float32x2_t leftright2 = vdup_n_f32(0.0);
67
 
        leftright2 = vset_lane_f32(left, leftright2, 0);
68
 
        leftright2 = vset_lane_f32(right, leftright2, 1);
69
 
        leftright4 = vcombine_f32(leftright2, leftright2);
70
 
    }
71
 
    for(c = 0;c < HRIR_LENGTH;c += 2)
72
 
    {
73
 
        const ALuint o0 = (Offset+c)&HRIR_MASK;
74
 
        const ALuint o1 = (o0+1)&HRIR_MASK;
75
 
        float32x4_t vals = vcombine_f32(vld1_f32((float32_t*)&Values[o0][0]),
76
 
                                        vld1_f32((float32_t*)&Values[o1][0]));
77
 
        float32x4_t coefs = vld1q_f32((float32_t*)&Coeffs[c][0]);
78
 
 
79
 
        vals = vmlaq_f32(vals, coefs, leftright4);
80
 
 
81
 
        vst1_f32((float32_t*)&Values[o0][0], vget_low_f32(vals));
82
 
        vst1_f32((float32_t*)&Values[o1][0], vget_high_f32(vals));
83
 
    }
84
 
}
85
 
 
86
 
#else
87
 
 
88
 
static __inline void ApplyCoeffs(ALuint Offset, ALfloat (*RESTRICT Values)[2],
89
 
                                 ALfloat (*RESTRICT Coeffs)[2],
90
 
                                 ALfloat left, ALfloat right)
91
 
{
92
 
    ALuint c;
93
 
    for(c = 0;c < HRIR_LENGTH;c++)
94
 
    {
95
 
        const ALuint off = (Offset+c)&HRIR_MASK;
96
 
        Values[off][0] += Coeffs[c][0] * left;
97
 
        Values[off][1] += Coeffs[c][1] * right;
98
 
    }
99
 
}
100
 
 
101
 
#endif
102
 
 
103
 
#define DECL_TEMPLATE(T, sampler)                                             \
104
 
static void Mix_Hrtf_##T##_##sampler(ALsource *Source, ALCdevice *Device,     \
105
 
  const ALvoid *srcdata, ALuint *DataPosInt, ALuint *DataPosFrac,             \
106
 
  ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)                       \
107
 
{                                                                             \
108
 
    const ALuint NumChannels = Source->NumChannels;                           \
109
 
    const T *RESTRICT data = srcdata;                                         \
110
 
    const ALint *RESTRICT DelayStep = Source->Params.HrtfDelayStep;           \
111
 
    ALfloat (*RESTRICT DryBuffer)[MAXCHANNELS];                               \
112
 
    ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks;                  \
113
 
    ALfloat (*RESTRICT CoeffStep)[2] = Source->Params.HrtfCoeffStep;          \
114
 
    ALuint pos, frac;                                                         \
115
 
    FILTER *DryFilter;                                                        \
116
 
    ALuint BufferIdx;                                                         \
117
 
    ALuint increment;                                                         \
118
 
    ALuint i, out, c;                                                         \
119
 
    ALfloat value;                                                            \
120
 
                                                                              \
121
 
    increment = Source->Params.Step;                                          \
122
 
                                                                              \
123
 
    DryBuffer = Device->DryBuffer;                                            \
124
 
    ClickRemoval = Device->ClickRemoval;                                      \
125
 
    PendingClicks = Device->PendingClicks;                                    \
126
 
    DryFilter = &Source->Params.iirFilter;                                    \
127
 
                                                                              \
128
 
    pos = 0;                                                                  \
129
 
    frac = *DataPosFrac;                                                      \
130
 
                                                                              \
131
 
    for(i = 0;i < NumChannels;i++)                                            \
132
 
    {                                                                         \
133
 
        ALfloat (*RESTRICT TargetCoeffs)[2] = Source->Params.HrtfCoeffs[i];   \
134
 
        ALuint *RESTRICT TargetDelay = Source->Params.HrtfDelay[i];           \
135
 
        ALfloat *RESTRICT History = Source->HrtfHistory[i];                   \
136
 
        ALfloat (*RESTRICT Values)[2] = Source->HrtfValues[i];                \
137
 
        ALint Counter = maxu(Source->HrtfCounter, OutPos) - OutPos;           \
138
 
        ALuint Offset = Source->HrtfOffset + OutPos;                          \
139
 
        ALfloat Coeffs[HRIR_LENGTH][2];                                       \
140
 
        ALuint Delay[2];                                                      \
141
 
        ALfloat left, right;                                                  \
142
 
                                                                              \
143
 
        pos = 0;                                                              \
144
 
        frac = *DataPosFrac;                                                  \
145
 
                                                                              \
146
 
        for(c = 0;c < HRIR_LENGTH;c++)                                        \
147
 
        {                                                                     \
148
 
            Coeffs[c][0] = TargetCoeffs[c][0] - (CoeffStep[c][0]*Counter);    \
149
 
            Coeffs[c][1] = TargetCoeffs[c][1] - (CoeffStep[c][1]*Counter);    \
150
 
        }                                                                     \
151
 
                                                                              \
152
 
        Delay[0] = TargetDelay[0] - (DelayStep[0]*Counter) + 32768;           \
153
 
        Delay[1] = TargetDelay[1] - (DelayStep[1]*Counter) + 32768;           \
154
 
                                                                              \
155
 
        if(LIKELY(OutPos == 0))                                               \
156
 
        {                                                                     \
157
 
            value = sampler(data + pos*NumChannels + i, NumChannels, frac);   \
158
 
            value = lpFilter2PC(DryFilter, i, value);                         \
159
 
                                                                              \
160
 
            History[Offset&SRC_HISTORY_MASK] = value;                         \
161
 
            left = History[(Offset-(Delay[0]>>16))&SRC_HISTORY_MASK];         \
162
 
            right = History[(Offset-(Delay[1]>>16))&SRC_HISTORY_MASK];        \
163
 
                                                                              \
164
 
            ClickRemoval[FRONT_LEFT]  -= Values[(Offset+1)&HRIR_MASK][0] +    \
165
 
                                         Coeffs[0][0] * left;                 \
166
 
            ClickRemoval[FRONT_RIGHT] -= Values[(Offset+1)&HRIR_MASK][1] +    \
167
 
                                         Coeffs[0][1] * right;                \
168
 
        }                                                                     \
169
 
        for(BufferIdx = 0;BufferIdx < BufferSize && Counter > 0;BufferIdx++)  \
170
 
        {                                                                     \
171
 
            value = sampler(data + pos*NumChannels + i, NumChannels, frac);   \
172
 
            value = lpFilter2P(DryFilter, i, value);                          \
173
 
                                                                              \
174
 
            History[Offset&SRC_HISTORY_MASK] = value;                         \
175
 
            left = History[(Offset-(Delay[0]>>16))&SRC_HISTORY_MASK];         \
176
 
            right = History[(Offset-(Delay[1]>>16))&SRC_HISTORY_MASK];        \
177
 
                                                                              \
178
 
            Delay[0] += DelayStep[0];                                         \
179
 
            Delay[1] += DelayStep[1];                                         \
180
 
                                                                              \
181
 
            Values[Offset&HRIR_MASK][0] = 0.0f;                               \
182
 
            Values[Offset&HRIR_MASK][1] = 0.0f;                               \
183
 
            Offset++;                                                         \
184
 
                                                                              \
185
 
            for(c = 0;c < HRIR_LENGTH;c++)                                    \
186
 
            {                                                                 \
187
 
                const ALuint off = (Offset+c)&HRIR_MASK;                      \
188
 
                Values[off][0] += Coeffs[c][0] * left;                        \
189
 
                Values[off][1] += Coeffs[c][1] * right;                       \
190
 
                Coeffs[c][0] += CoeffStep[c][0];                              \
191
 
                Coeffs[c][1] += CoeffStep[c][1];                              \
192
 
            }                                                                 \
193
 
                                                                              \
194
 
            DryBuffer[OutPos][FRONT_LEFT]  += Values[Offset&HRIR_MASK][0];    \
195
 
            DryBuffer[OutPos][FRONT_RIGHT] += Values[Offset&HRIR_MASK][1];    \
196
 
                                                                              \
197
 
            frac += increment;                                                \
198
 
            pos  += frac>>FRACTIONBITS;                                       \
199
 
            frac &= FRACTIONMASK;                                             \
200
 
            OutPos++;                                                         \
201
 
            Counter--;                                                        \
202
 
        }                                                                     \
203
 
                                                                              \
204
 
        Delay[0] >>= 16;                                                      \
205
 
        Delay[1] >>= 16;                                                      \
206
 
        for(;BufferIdx < BufferSize;BufferIdx++)                              \
207
 
        {                                                                     \
208
 
            value = sampler(data + pos*NumChannels + i, NumChannels, frac);   \
209
 
            value = lpFilter2P(DryFilter, i, value);                          \
210
 
                                                                              \
211
 
            History[Offset&SRC_HISTORY_MASK] = value;                         \
212
 
            left = History[(Offset-Delay[0])&SRC_HISTORY_MASK];               \
213
 
            right = History[(Offset-Delay[1])&SRC_HISTORY_MASK];              \
214
 
                                                                              \
215
 
            Values[Offset&HRIR_MASK][0] = 0.0f;                               \
216
 
            Values[Offset&HRIR_MASK][1] = 0.0f;                               \
217
 
            Offset++;                                                         \
218
 
                                                                              \
219
 
            ApplyCoeffs(Offset, Values, Coeffs, left, right);                 \
220
 
            DryBuffer[OutPos][FRONT_LEFT]  += Values[Offset&HRIR_MASK][0];    \
221
 
            DryBuffer[OutPos][FRONT_RIGHT] += Values[Offset&HRIR_MASK][1];    \
222
 
                                                                              \
223
 
            frac += increment;                                                \
224
 
            pos  += frac>>FRACTIONBITS;                                       \
225
 
            frac &= FRACTIONMASK;                                             \
226
 
            OutPos++;                                                         \
227
 
        }                                                                     \
228
 
        if(LIKELY(OutPos == SamplesToDo))                                     \
229
 
        {                                                                     \
230
 
            value = sampler(data + pos*NumChannels + i, NumChannels, frac);   \
231
 
            value = lpFilter2PC(DryFilter, i, value);                         \
232
 
                                                                              \
233
 
            History[Offset&SRC_HISTORY_MASK] = value;                         \
234
 
            left = History[(Offset-Delay[0])&SRC_HISTORY_MASK];               \
235
 
            right = History[(Offset-Delay[1])&SRC_HISTORY_MASK];              \
236
 
                                                                              \
237
 
            PendingClicks[FRONT_LEFT]  += Values[(Offset+1)&HRIR_MASK][0] +   \
238
 
                                          Coeffs[0][0] * left;                \
239
 
            PendingClicks[FRONT_RIGHT] += Values[(Offset+1)&HRIR_MASK][1] +   \
240
 
                                          Coeffs[0][1] * right;               \
241
 
        }                                                                     \
242
 
        OutPos -= BufferSize;                                                 \
243
 
    }                                                                         \
244
 
                                                                              \
245
 
    for(out = 0;out < Device->NumAuxSends;out++)                              \
246
 
    {                                                                         \
247
 
        ALeffectslot *Slot = Source->Params.Send[out].Slot;                   \
248
 
        ALfloat  WetSend;                                                     \
249
 
        ALfloat *RESTRICT WetBuffer;                                          \
250
 
        ALfloat *RESTRICT WetClickRemoval;                                    \
251
 
        ALfloat *RESTRICT WetPendingClicks;                                   \
252
 
        FILTER  *WetFilter;                                                   \
253
 
                                                                              \
254
 
        if(Slot == NULL)                                                      \
255
 
            continue;                                                         \
256
 
                                                                              \
257
 
        WetBuffer = Slot->WetBuffer;                                          \
258
 
        WetClickRemoval = Slot->ClickRemoval;                                 \
259
 
        WetPendingClicks = Slot->PendingClicks;                               \
260
 
        WetFilter = &Source->Params.Send[out].iirFilter;                      \
261
 
        WetSend = Source->Params.Send[out].WetGain;                           \
262
 
                                                                              \
263
 
        for(i = 0;i < NumChannels;i++)                                        \
264
 
        {                                                                     \
265
 
            pos = 0;                                                          \
266
 
            frac = *DataPosFrac;                                              \
267
 
                                                                              \
268
 
            if(LIKELY(OutPos == 0))                                           \
269
 
            {                                                                 \
270
 
                value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
271
 
                value = lpFilter1PC(WetFilter, i, value);                     \
272
 
                                                                              \
273
 
                WetClickRemoval[0] -= value * WetSend;                        \
274
 
            }                                                                 \
275
 
            for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++)             \
276
 
            {                                                                 \
277
 
                value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
278
 
                value = lpFilter1P(WetFilter, i, value);                      \
279
 
                                                                              \
280
 
                WetBuffer[OutPos] += value * WetSend;                         \
281
 
                                                                              \
282
 
                frac += increment;                                            \
283
 
                pos  += frac>>FRACTIONBITS;                                   \
284
 
                frac &= FRACTIONMASK;                                         \
285
 
                OutPos++;                                                     \
286
 
            }                                                                 \
287
 
            if(LIKELY(OutPos == SamplesToDo))                                 \
288
 
            {                                                                 \
289
 
                value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
290
 
                value = lpFilter1PC(WetFilter, i, value);                     \
291
 
                                                                              \
292
 
                WetPendingClicks[0] += value * WetSend;                       \
293
 
            }                                                                 \
294
 
            OutPos -= BufferSize;                                             \
295
 
        }                                                                     \
296
 
    }                                                                         \
297
 
    *DataPosInt += pos;                                                       \
298
 
    *DataPosFrac = frac;                                                      \
299
 
}
300
 
 
301
 
DECL_TEMPLATE(ALfloat, point32)
302
 
DECL_TEMPLATE(ALfloat, lerp32)
303
 
DECL_TEMPLATE(ALfloat, cubic32)
304
 
 
305
 
#undef DECL_TEMPLATE
306
 
 
307
 
 
308
 
#define DECL_TEMPLATE(T, sampler)                                             \
309
 
static void Mix_##T##_##sampler(ALsource *Source, ALCdevice *Device,          \
310
 
  const ALvoid *srcdata, ALuint *DataPosInt, ALuint *DataPosFrac,             \
311
 
  ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)                       \
312
 
{                                                                             \
313
 
    const ALuint NumChannels = Source->NumChannels;                           \
314
 
    const T *RESTRICT data = srcdata;                                         \
315
 
    ALfloat (*RESTRICT DryBuffer)[MAXCHANNELS];                               \
316
 
    ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks;                  \
317
 
    ALfloat DrySend[MAXCHANNELS];                                             \
318
 
    FILTER *DryFilter;                                                        \
319
 
    ALuint pos, frac;                                                         \
320
 
    ALuint BufferIdx;                                                         \
321
 
    ALuint increment;                                                         \
322
 
    ALuint i, out, c;                                                         \
323
 
    ALfloat value;                                                            \
324
 
                                                                              \
325
 
    increment = Source->Params.Step;                                          \
326
 
                                                                              \
327
 
    DryBuffer = Device->DryBuffer;                                            \
328
 
    ClickRemoval = Device->ClickRemoval;                                      \
329
 
    PendingClicks = Device->PendingClicks;                                    \
330
 
    DryFilter = &Source->Params.iirFilter;                                    \
331
 
                                                                              \
332
 
    pos = 0;                                                                  \
333
 
    frac = *DataPosFrac;                                                      \
334
 
                                                                              \
335
 
    for(i = 0;i < NumChannels;i++)                                            \
336
 
    {                                                                         \
337
 
        for(c = 0;c < MAXCHANNELS;c++)                                        \
338
 
            DrySend[c] = Source->Params.DryGains[i][c];                       \
339
 
                                                                              \
340
 
        pos = 0;                                                              \
341
 
        frac = *DataPosFrac;                                                  \
342
 
                                                                              \
343
 
        if(OutPos == 0)                                                       \
344
 
        {                                                                     \
345
 
            value = sampler(data + pos*NumChannels + i, NumChannels, frac);   \
346
 
                                                                              \
347
 
            value = lpFilter2PC(DryFilter, i, value);                         \
348
 
            for(c = 0;c < MAXCHANNELS;c++)                                    \
349
 
                ClickRemoval[c] -= value*DrySend[c];                          \
350
 
        }                                                                     \
351
 
        for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++)                 \
352
 
        {                                                                     \
353
 
            value = sampler(data + pos*NumChannels + i, NumChannels, frac);   \
354
 
                                                                              \
355
 
            value = lpFilter2P(DryFilter, i, value);                          \
356
 
            for(c = 0;c < MAXCHANNELS;c++)                                    \
357
 
                DryBuffer[OutPos][c] += value*DrySend[c];                     \
358
 
                                                                              \
359
 
            frac += increment;                                                \
360
 
            pos  += frac>>FRACTIONBITS;                                       \
361
 
            frac &= FRACTIONMASK;                                             \
362
 
            OutPos++;                                                         \
363
 
        }                                                                     \
364
 
        if(OutPos == SamplesToDo)                                             \
365
 
        {                                                                     \
366
 
            value = sampler(data + pos*NumChannels + i, NumChannels, frac);   \
367
 
                                                                              \
368
 
            value = lpFilter2PC(DryFilter, i, value);                         \
369
 
            for(c = 0;c < MAXCHANNELS;c++)                                    \
370
 
                PendingClicks[c] += value*DrySend[c];                         \
371
 
        }                                                                     \
372
 
        OutPos -= BufferSize;                                                 \
373
 
    }                                                                         \
374
 
                                                                              \
375
 
    for(out = 0;out < Device->NumAuxSends;out++)                              \
376
 
    {                                                                         \
377
 
        ALeffectslot *Slot = Source->Params.Send[out].Slot;                   \
378
 
        ALfloat  WetSend;                                                     \
379
 
        ALfloat *WetBuffer;                                                   \
380
 
        ALfloat *WetClickRemoval;                                             \
381
 
        ALfloat *WetPendingClicks;                                            \
382
 
        FILTER  *WetFilter;                                                   \
383
 
                                                                              \
384
 
        if(Slot == NULL)                                                      \
385
 
            continue;                                                         \
386
 
                                                                              \
387
 
        WetBuffer = Slot->WetBuffer;                                          \
388
 
        WetClickRemoval = Slot->ClickRemoval;                                 \
389
 
        WetPendingClicks = Slot->PendingClicks;                               \
390
 
        WetFilter = &Source->Params.Send[out].iirFilter;                      \
391
 
        WetSend = Source->Params.Send[out].WetGain;                           \
392
 
                                                                              \
393
 
        for(i = 0;i < NumChannels;i++)                                        \
394
 
        {                                                                     \
395
 
            pos = 0;                                                          \
396
 
            frac = *DataPosFrac;                                              \
397
 
                                                                              \
398
 
            if(OutPos == 0)                                                   \
399
 
            {                                                                 \
400
 
                value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
401
 
                                                                              \
402
 
                value = lpFilter1PC(WetFilter, i, value);                     \
403
 
                WetClickRemoval[0] -= value * WetSend;                        \
404
 
            }                                                                 \
405
 
            for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++)             \
406
 
            {                                                                 \
407
 
                value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
408
 
                                                                              \
409
 
                value = lpFilter1P(WetFilter, i, value);                      \
410
 
                WetBuffer[OutPos] += value * WetSend;                         \
411
 
                                                                              \
412
 
                frac += increment;                                            \
413
 
                pos  += frac>>FRACTIONBITS;                                   \
414
 
                frac &= FRACTIONMASK;                                         \
415
 
                OutPos++;                                                     \
416
 
            }                                                                 \
417
 
            if(OutPos == SamplesToDo)                                         \
418
 
            {                                                                 \
419
 
                value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
420
 
                                                                              \
421
 
                value = lpFilter1PC(WetFilter, i, value);                     \
422
 
                WetPendingClicks[0] += value * WetSend;                       \
423
 
            }                                                                 \
424
 
            OutPos -= BufferSize;                                             \
425
 
        }                                                                     \
426
 
    }                                                                         \
427
 
    *DataPosInt += pos;                                                       \
428
 
    *DataPosFrac = frac;                                                      \
429
 
}
430
 
 
431
 
DECL_TEMPLATE(ALfloat, point32)
432
 
DECL_TEMPLATE(ALfloat, lerp32)
433
 
DECL_TEMPLATE(ALfloat, cubic32)
434
 
 
435
 
#undef DECL_TEMPLATE
436
 
 
437
 
 
438
 
MixerFunc SelectMixer(enum Resampler Resampler)
439
 
{
440
 
    switch(Resampler)
441
 
    {
442
 
        case PointResampler:
443
 
            return Mix_ALfloat_point32;
444
 
        case LinearResampler:
445
 
            return Mix_ALfloat_lerp32;
446
 
        case CubicResampler:
447
 
            return Mix_ALfloat_cubic32;
448
 
        case ResamplerMax:
449
 
            break;
450
 
    }
451
 
    return NULL;
452
 
}
453
 
 
454
 
MixerFunc SelectHrtfMixer(enum Resampler Resampler)
455
 
{
456
 
    switch(Resampler)
457
 
    {
458
 
        case PointResampler:
459
 
            return Mix_Hrtf_ALfloat_point32;
460
 
        case LinearResampler:
461
 
            return Mix_Hrtf_ALfloat_lerp32;
462
 
        case CubicResampler:
463
 
            return Mix_Hrtf_ALfloat_cubic32;
464
 
        case ResamplerMax:
465
 
            break;
466
 
    }
467
 
    return NULL;
468
 
}
469
 
 
470
 
 
471
40
static __inline ALfloat Sample_ALbyte(ALbyte val)
472
41
{ return val * (1.0f/127.0f); }
473
42
 
478
47
{ return val; }
479
48
 
480
49
#define DECL_TEMPLATE(T)                                                      \
481
 
static void Load_##T(ALfloat *dst, const T *src, ALuint samples)              \
 
50
static void Load_##T(ALfloat *dst, const T *src, ALuint srcstep, ALuint samples)\
482
51
{                                                                             \
483
52
    ALuint i;                                                                 \
484
53
    for(i = 0;i < samples;i++)                                                \
485
 
        dst[i] = Sample_##T(src[i]);                                          \
 
54
        dst[i] = Sample_##T(src[i*srcstep]);                                  \
486
55
}
487
56
 
488
57
DECL_TEMPLATE(ALbyte)
491
60
 
492
61
#undef DECL_TEMPLATE
493
62
 
494
 
static void LoadStack(ALfloat *dst, const ALvoid *src, enum FmtType srctype, ALuint samples)
 
63
static void LoadData(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum FmtType srctype, ALuint samples)
495
64
{
496
65
    switch(srctype)
497
66
    {
498
67
        case FmtByte:
499
 
            Load_ALbyte(dst, src, samples);
 
68
            Load_ALbyte(dst, src, srcstep, samples);
500
69
            break;
501
70
        case FmtShort:
502
 
            Load_ALshort(dst, src, samples);
 
71
            Load_ALshort(dst, src, srcstep, samples);
503
72
            break;
504
73
        case FmtFloat:
505
 
            Load_ALfloat(dst, src, samples);
 
74
            Load_ALfloat(dst, src, srcstep, samples);
506
75
            break;
507
76
    }
508
77
}
509
78
 
510
 
static void SilenceStack(ALfloat *dst, ALuint samples)
 
79
static void SilenceData(ALfloat *dst, ALuint samples)
511
80
{
512
81
    ALuint i;
513
82
    for(i = 0;i < samples;i++)
515
84
}
516
85
 
517
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
 
518
97
ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
519
98
{
520
99
    ALbufferlistitem *BufferListItem;
526
105
    ALenum State;
527
106
    ALuint OutPos;
528
107
    ALuint NumChannels;
529
 
    ALuint FrameSize;
 
108
    ALuint SampleSize;
530
109
    ALint64 DataSize64;
531
 
    ALuint i;
 
110
    ALuint chan, j;
532
111
 
533
112
    /* Get source info */
534
113
    State         = Source->state;
535
114
    BuffersPlayed = Source->BuffersPlayed;
536
115
    DataPosInt    = Source->position;
537
116
    DataPosFrac   = Source->position_fraction;
538
 
    Looping       = Source->bLooping;
 
117
    Looping       = Source->Looping;
539
118
    increment     = Source->Params.Step;
540
 
    Resampler     = Source->Resampler;
 
119
    Resampler     = (increment==FRACTIONONE) ? PointResampler : Source->Resampler;
541
120
    NumChannels   = Source->NumChannels;
542
 
    FrameSize     = NumChannels * Source->SampleSize;
 
121
    SampleSize    = Source->SampleSize;
543
122
 
544
123
    /* Get current buffer queue item */
545
124
    BufferListItem = Source->queue;
546
 
    for(i = 0;i < BuffersPlayed;i++)
 
125
    for(j = 0;j < BuffersPlayed;j++)
547
126
        BufferListItem = BufferListItem->next;
548
127
 
549
128
    OutPos = 0;
550
129
    do {
551
130
        const ALuint BufferPrePadding = ResamplerPrePadding[Resampler];
552
131
        const ALuint BufferPadding = ResamplerPadding[Resampler];
553
 
        ALfloat StackData[STACK_DATA_SIZE/sizeof(ALfloat)];
554
 
        ALfloat *SrcData = StackData;
555
 
        ALuint SrcDataSize = 0;
556
 
        ALuint BufferSize;
 
132
        ALuint SrcBufferSize, DstBufferSize;
557
133
 
558
134
        /* Figure out how many buffer bytes will be needed */
559
135
        DataSize64  = SamplesToDo-OutPos+1;
561
137
        DataSize64 += DataPosFrac+FRACTIONMASK;
562
138
        DataSize64 >>= FRACTIONBITS;
563
139
        DataSize64 += BufferPadding+BufferPrePadding;
564
 
        DataSize64 *= NumChannels;
565
 
 
566
 
        BufferSize  = (ALuint)mini64(DataSize64, STACK_DATA_SIZE/sizeof(ALfloat));
567
 
        BufferSize /= NumChannels;
568
 
 
569
 
        if(Source->lSourceType == AL_STATIC)
570
 
        {
571
 
            const ALbuffer *ALBuffer = Source->queue->buffer;
572
 
            const ALubyte *Data = ALBuffer->data;
573
 
            ALuint DataSize;
574
 
            ALuint pos;
575
 
 
576
 
            /* If current pos is beyond the loop range, do not loop */
577
 
            if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
578
 
            {
579
 
                Looping = AL_FALSE;
580
 
 
581
 
                if(DataPosInt >= BufferPrePadding)
582
 
                    pos = DataPosInt - BufferPrePadding;
583
 
                else
584
 
                {
585
 
                    DataSize = BufferPrePadding - DataPosInt;
586
 
                    DataSize = minu(BufferSize, DataSize);
587
 
 
588
 
                    SilenceStack(&SrcData[SrcDataSize*NumChannels],
589
 
                                 DataSize*NumChannels);
590
 
                    SrcDataSize += DataSize;
591
 
                    BufferSize -= DataSize;
592
 
 
593
 
                    pos = 0;
594
 
                }
595
 
 
596
 
                /* Copy what's left to play in the source buffer, and clear the
597
 
                 * rest of the temp buffer */
598
 
                DataSize = ALBuffer->SampleLen - pos;
599
 
                DataSize = minu(BufferSize, DataSize);
600
 
 
601
 
                LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[pos*FrameSize],
602
 
                          ALBuffer->FmtType, DataSize*NumChannels);
603
 
                SrcDataSize += DataSize;
604
 
                BufferSize -= DataSize;
605
 
 
606
 
                SilenceStack(&SrcData[SrcDataSize*NumChannels],
607
 
                             BufferSize*NumChannels);
608
 
                SrcDataSize += BufferSize;
609
 
                BufferSize -= BufferSize;
610
 
            }
611
 
            else
612
 
            {
613
 
                ALuint LoopStart = ALBuffer->LoopStart;
614
 
                ALuint LoopEnd   = ALBuffer->LoopEnd;
615
 
 
616
 
                if(DataPosInt >= LoopStart)
617
 
                {
618
 
                    pos = DataPosInt-LoopStart;
619
 
                    while(pos < BufferPrePadding)
620
 
                        pos += LoopEnd-LoopStart;
621
 
                    pos -= BufferPrePadding;
622
 
                    pos += LoopStart;
623
 
                }
624
 
                else if(DataPosInt >= BufferPrePadding)
625
 
                    pos = DataPosInt - BufferPrePadding;
626
 
                else
627
 
                {
628
 
                    DataSize = BufferPrePadding - DataPosInt;
629
 
                    DataSize = minu(BufferSize, DataSize);
630
 
 
631
 
                    SilenceStack(&SrcData[SrcDataSize*NumChannels], DataSize*NumChannels);
632
 
                    SrcDataSize += DataSize;
633
 
                    BufferSize -= DataSize;
634
 
 
635
 
                    pos = 0;
636
 
                }
637
 
 
638
 
                /* Copy what's left of this loop iteration, then copy repeats
639
 
                 * of the loop section */
640
 
                DataSize = LoopEnd - pos;
641
 
                DataSize = minu(BufferSize, DataSize);
642
 
 
643
 
                LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[pos*FrameSize],
644
 
                          ALBuffer->FmtType, DataSize*NumChannels);
645
 
                SrcDataSize += DataSize;
646
 
                BufferSize -= DataSize;
647
 
 
648
 
                DataSize = LoopEnd-LoopStart;
649
 
                while(BufferSize > 0)
650
 
                {
651
 
                    DataSize = minu(BufferSize, DataSize);
652
 
 
653
 
                    LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[LoopStart*FrameSize],
654
 
                              ALBuffer->FmtType, DataSize*NumChannels);
655
 
                    SrcDataSize += DataSize;
656
 
                    BufferSize -= DataSize;
657
 
                }
658
 
            }
659
 
        }
660
 
        else
661
 
        {
662
 
            /* Crawl the buffer queue to fill in the temp buffer */
663
 
            ALbufferlistitem *tmpiter = BufferListItem;
664
 
            ALuint pos;
665
 
 
666
 
            if(DataPosInt >= BufferPrePadding)
667
 
                pos = DataPosInt - BufferPrePadding;
668
 
            else
669
 
            {
670
 
                pos = BufferPrePadding - DataPosInt;
671
 
                while(pos > 0)
672
 
                {
673
 
                    if(!tmpiter->prev && !Looping)
674
 
                    {
675
 
                        ALuint DataSize = minu(BufferSize, pos);
676
 
 
677
 
                        SilenceStack(&SrcData[SrcDataSize*NumChannels], DataSize*NumChannels);
678
 
                        SrcDataSize += DataSize;
679
 
                        BufferSize -= DataSize;
680
 
 
681
 
                        pos = 0;
682
 
                        break;
683
 
                    }
684
 
 
685
 
                    if(tmpiter->prev)
686
 
                        tmpiter = tmpiter->prev;
687
 
                    else
688
 
                    {
689
 
                        while(tmpiter->next)
690
 
                            tmpiter = tmpiter->next;
691
 
                    }
692
 
 
693
 
                    if(tmpiter->buffer)
694
 
                    {
695
 
                        if((ALuint)tmpiter->buffer->SampleLen > pos)
696
 
                        {
697
 
                            pos = tmpiter->buffer->SampleLen - pos;
698
 
                            break;
699
 
                        }
700
 
                        pos -= tmpiter->buffer->SampleLen;
701
 
                    }
702
 
                }
703
 
            }
704
 
 
705
 
            while(tmpiter && BufferSize > 0)
706
 
            {
707
 
                const ALbuffer *ALBuffer;
708
 
                if((ALBuffer=tmpiter->buffer) != NULL)
709
 
                {
710
 
                    const ALubyte *Data = ALBuffer->data;
711
 
                    ALuint DataSize = ALBuffer->SampleLen;
712
 
 
713
 
                    /* Skip the data already played */
714
 
                    if(DataSize <= pos)
715
 
                        pos -= DataSize;
716
 
                    else
717
 
                    {
718
 
                        Data += pos*FrameSize;
719
 
                        DataSize -= pos;
720
 
                        pos -= pos;
721
 
 
722
 
                        DataSize = minu(BufferSize, DataSize);
723
 
                        LoadStack(&SrcData[SrcDataSize*NumChannels], Data,
724
 
                                  ALBuffer->FmtType, DataSize*NumChannels);
725
 
                        SrcDataSize += DataSize;
726
 
                        BufferSize -= DataSize;
727
 
                    }
728
 
                }
729
 
                tmpiter = tmpiter->next;
730
 
                if(!tmpiter && Looping)
731
 
                    tmpiter = Source->queue;
732
 
                else if(!tmpiter)
733
 
                {
734
 
                    SilenceStack(&SrcData[SrcDataSize*NumChannels], BufferSize*NumChannels);
735
 
                    SrcDataSize += BufferSize;
736
 
                    BufferSize -= BufferSize;
737
 
                }
738
 
            }
739
 
        }
740
 
 
741
 
        /* Figure out how many samples we can mix. */
742
 
        DataSize64  = SrcDataSize;
 
140
 
 
141
        SrcBufferSize = (ALuint)mini64(DataSize64, BUFFERSIZE);
 
142
 
 
143
        /* Figure out how many samples we can actually mix from this. */
 
144
        DataSize64  = SrcBufferSize;
743
145
        DataSize64 -= BufferPadding+BufferPrePadding;
744
146
        DataSize64 <<= FRACTIONBITS;
745
147
        DataSize64 -= increment;
746
148
        DataSize64 -= DataPosFrac;
747
149
 
748
 
        BufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
749
 
        BufferSize = minu(BufferSize, (SamplesToDo-OutPos));
750
 
 
751
 
        SrcData += BufferPrePadding*NumChannels;
752
 
        Source->Params.DoMix(Source, Device, SrcData, &DataPosInt, &DataPosFrac,
753
 
                             OutPos, SamplesToDo, BufferSize);
754
 
        OutPos += BufferSize;
 
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;
755
357
 
756
358
        /* Handle looping sources */
757
359
        while(1)
770
372
                    break;
771
373
            }
772
374
 
773
 
            if(Looping && Source->lSourceType == AL_STATIC)
 
375
            if(Looping && Source->SourceType == AL_STATIC)
774
376
            {
775
377
                DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
776
378
                break;
808
410
    Source->BuffersPlayed     = BuffersPlayed;
809
411
    Source->position          = DataPosInt;
810
412
    Source->position_fraction = DataPosFrac;
811
 
    Source->HrtfOffset       += OutPos;
 
413
    Source->Hrtf.Offset      += OutPos;
812
414
    if(State == AL_PLAYING)
813
 
    {
814
 
        Source->HrtfCounter = maxu(Source->HrtfCounter, OutPos) - OutPos;
815
 
        Source->HrtfMoving  = AL_TRUE;
816
 
    }
 
415
        Source->Hrtf.Counter = maxu(Source->Hrtf.Counter, OutPos) - OutPos;
817
416
    else
818
417
    {
819
 
        Source->HrtfCounter = 0;
820
 
        Source->HrtfMoving  = AL_FALSE;
 
418
        Source->Hrtf.Counter = 0;
 
419
        Source->Hrtf.Moving  = AL_FALSE;
821
420
    }
822
421
}