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

« back to all changes in this revision

Viewing changes to Alc/panning.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:
31
31
#include "AL/alc.h"
32
32
#include "alu.h"
33
33
 
34
 
static void SetSpeakerArrangement(const char *name, ALfloat SpeakerAngle[MAXCHANNELS],
35
 
                                  enum Channel Speaker2Chan[MAXCHANNELS], ALint chans)
 
34
static void SetSpeakerArrangement(const char *name, ALfloat SpeakerAngle[MaxChannels],
 
35
                                  enum Channel Speaker2Chan[MaxChannels], ALint chans)
36
36
{
37
37
    char *confkey, *next;
38
38
    char *layout_str;
71
71
        *(++end) = 0;
72
72
 
73
73
        if(strcmp(confkey, "fl") == 0 || strcmp(confkey, "front-left") == 0)
74
 
            val = FRONT_LEFT;
 
74
            val = FrontLeft;
75
75
        else if(strcmp(confkey, "fr") == 0 || strcmp(confkey, "front-right") == 0)
76
 
            val = FRONT_RIGHT;
 
76
            val = FrontRight;
77
77
        else if(strcmp(confkey, "fc") == 0 || strcmp(confkey, "front-center") == 0)
78
 
            val = FRONT_CENTER;
 
78
            val = FrontCenter;
79
79
        else if(strcmp(confkey, "bl") == 0 || strcmp(confkey, "back-left") == 0)
80
 
            val = BACK_LEFT;
 
80
            val = BackLeft;
81
81
        else if(strcmp(confkey, "br") == 0 || strcmp(confkey, "back-right") == 0)
82
 
            val = BACK_RIGHT;
 
82
            val = BackRight;
83
83
        else if(strcmp(confkey, "bc") == 0 || strcmp(confkey, "back-center") == 0)
84
 
            val = BACK_CENTER;
 
84
            val = BackCenter;
85
85
        else if(strcmp(confkey, "sl") == 0 || strcmp(confkey, "side-left") == 0)
86
 
            val = SIDE_LEFT;
 
86
            val = SideLeft;
87
87
        else if(strcmp(confkey, "sr") == 0 || strcmp(confkey, "side-right") == 0)
88
 
            val = SIDE_RIGHT;
 
88
            val = SideRight;
89
89
        else
90
90
        {
91
91
            ERR("Unknown speaker for %s: \"%s\"\n", name, confkey);
139
139
    }
140
140
}
141
141
 
142
 
static ALfloat aluLUTpos2Angle(ALint pos)
143
 
{
144
 
    if(pos < QUADRANT_NUM)
145
 
        return aluAtan((ALfloat)pos / (ALfloat)(QUADRANT_NUM - pos));
146
 
    if(pos < 2 * QUADRANT_NUM)
147
 
        return F_PI_2 + aluAtan((ALfloat)(pos - QUADRANT_NUM) / (ALfloat)(2 * QUADRANT_NUM - pos));
148
 
    if(pos < 3 * QUADRANT_NUM)
149
 
        return aluAtan((ALfloat)(pos - 2 * QUADRANT_NUM) / (ALfloat)(3 * QUADRANT_NUM - pos)) - F_PI;
150
 
    return aluAtan((ALfloat)(pos - 3 * QUADRANT_NUM) / (ALfloat)(4 * QUADRANT_NUM - pos)) - F_PI_2;
151
 
}
152
 
 
153
 
ALint aluCart2LUTpos(ALfloat re, ALfloat im)
154
 
{
155
 
    ALint pos = 0;
156
 
    ALfloat denom = aluFabs(re) + aluFabs(im);
157
 
    if(denom > 0.0f)
158
 
        pos = (ALint)(QUADRANT_NUM*aluFabs(im) / denom + 0.5);
159
 
 
160
 
    if(re < 0.0f)
161
 
        pos = 2 * QUADRANT_NUM - pos;
162
 
    if(im < 0.0f)
163
 
        pos = LUT_NUM - pos;
164
 
    return pos%LUT_NUM;
165
 
}
 
142
 
 
143
/**
 
144
 * ComputeAngleGains
 
145
 *
 
146
 * Sets channel gains based on a given source's angle and its half-width. The
 
147
 * angle and hwidth parameters are in radians.
 
148
 */
 
149
ALvoid ComputeAngleGains(const ALCdevice *device, ALfloat angle, ALfloat hwidth, ALfloat ingain, ALfloat *gains)
 
150
{
 
151
    ALfloat tmpgains[MaxChannels] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
 
152
    enum Channel Speaker2Chan[MaxChannels];
 
153
    ALfloat SpeakerAngle[MaxChannels];
 
154
    ALfloat langle, rangle;
 
155
    ALfloat a;
 
156
    ALuint i;
 
157
 
 
158
    for(i = 0;i < device->NumChan;i++)
 
159
        Speaker2Chan[i] = device->Speaker2Chan[i];
 
160
    for(i = 0;i < device->NumChan;i++)
 
161
        SpeakerAngle[i] = device->SpeakerAngle[i];
 
162
 
 
163
    /* Some easy special-cases first... */
 
164
    if(device->NumChan == 1 || hwidth >= F_PI)
 
165
    {
 
166
        /* Full coverage for all speakers. */
 
167
        for(i = 0;i < device->NumChan;i++)
 
168
        {
 
169
            enum Channel chan = Speaker2Chan[i];
 
170
            gains[chan] = ingain;
 
171
        }
 
172
        return;
 
173
    }
 
174
    if(hwidth <= 0.0f)
 
175
    {
 
176
        /* Infinitely small sound point. */
 
177
        for(i = 0;i < device->NumChan-1;i++)
 
178
        {
 
179
            if(angle >= SpeakerAngle[i] && angle < SpeakerAngle[i+1])
 
180
            {
 
181
                /* Sound is between speakers i and i+1 */
 
182
                a =             (angle-SpeakerAngle[i]) /
 
183
                    (SpeakerAngle[i+1]-SpeakerAngle[i]);
 
184
                gains[Speaker2Chan[i]]   = sqrtf(1.0f-a) * ingain;
 
185
                gains[Speaker2Chan[i+1]] = sqrtf(     a) * ingain;
 
186
                return;
 
187
            }
 
188
        }
 
189
        /* Sound is between last and first speakers */
 
190
        if(angle < SpeakerAngle[0])
 
191
            angle += F_PI*2.0f;
 
192
        a =                       (angle-SpeakerAngle[i]) /
 
193
            (F_PI*2.0f + SpeakerAngle[0]-SpeakerAngle[i]);
 
194
        gains[Speaker2Chan[i]] = sqrtf(1.0f-a) * ingain;
 
195
        gains[Speaker2Chan[0]] = sqrtf(     a) * ingain;
 
196
        return;
 
197
    }
 
198
 
 
199
    if(fabsf(angle)+hwidth > F_PI)
 
200
    {
 
201
        /* The coverage area would go outside of -pi...+pi. Instead, rotate the
 
202
         * speaker angles so it would be as if angle=0, and keep them wrapped
 
203
         * within -pi...+pi. */
 
204
        if(angle > 0.0f)
 
205
        {
 
206
            ALuint done = 0;
 
207
            ALuint i = 0;
 
208
            while(i < device->NumChan && device->SpeakerAngle[i]-angle < -F_PI)
 
209
                i++;
 
210
            for(done = 0;i < device->NumChan;done++)
 
211
            {
 
212
                SpeakerAngle[done] = device->SpeakerAngle[i]-angle;
 
213
                Speaker2Chan[done] = device->Speaker2Chan[i];
 
214
                i++;
 
215
            }
 
216
            for(i = 0;done < device->NumChan;i++)
 
217
            {
 
218
                SpeakerAngle[done] = device->SpeakerAngle[i]-angle + F_PI*2.0f;
 
219
                Speaker2Chan[done] = device->Speaker2Chan[i];
 
220
                done++;
 
221
            }
 
222
        }
 
223
        else
 
224
        {
 
225
            /* NOTE: '< device->NumChan' on the iterators is correct here since
 
226
             * we need to handle index 0. Because the iterators are unsigned,
 
227
             * they'll underflow and wrap to become 0xFFFFFFFF, which will
 
228
             * break as expected. */
 
229
            ALuint done = device->NumChan-1;
 
230
            ALuint i = device->NumChan-1;
 
231
            while(i < device->NumChan && device->SpeakerAngle[i]-angle > F_PI)
 
232
                i--;
 
233
            for(done = device->NumChan-1;i < device->NumChan;done--)
 
234
            {
 
235
                SpeakerAngle[done] = device->SpeakerAngle[i]-angle;
 
236
                Speaker2Chan[done] = device->Speaker2Chan[i];
 
237
                i--;
 
238
            }
 
239
            for(i = device->NumChan-1;done < device->NumChan;i--)
 
240
            {
 
241
                SpeakerAngle[done] = device->SpeakerAngle[i]-angle - F_PI*2.0f;
 
242
                Speaker2Chan[done] = device->Speaker2Chan[i];
 
243
                done--;
 
244
            }
 
245
        }
 
246
        angle = 0.0f;
 
247
    }
 
248
    langle = angle - hwidth;
 
249
    rangle = angle + hwidth;
 
250
 
 
251
    /* First speaker */
 
252
    i = 0;
 
253
    do {
 
254
        ALuint last = device->NumChan-1;
 
255
        enum Channel chan = Speaker2Chan[i];
 
256
 
 
257
        if(SpeakerAngle[i] >= langle && SpeakerAngle[i] <= rangle)
 
258
        {
 
259
            tmpgains[chan] = 1.0f;
 
260
            continue;
 
261
        }
 
262
 
 
263
        if(SpeakerAngle[i] < langle && SpeakerAngle[i+1] > langle)
 
264
        {
 
265
            a =            (langle-SpeakerAngle[i]) /
 
266
                (SpeakerAngle[i+1]-SpeakerAngle[i]);
 
267
            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, 1.0f-a);
 
268
        }
 
269
        if(SpeakerAngle[i] > rangle)
 
270
        {
 
271
            a =          (F_PI*2.0f + rangle-SpeakerAngle[last]) /
 
272
                (F_PI*2.0f + SpeakerAngle[i]-SpeakerAngle[last]);
 
273
            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, a);
 
274
        }
 
275
        else if(SpeakerAngle[last] < rangle)
 
276
        {
 
277
            a =                      (rangle-SpeakerAngle[last]) /
 
278
                (F_PI*2.0f + SpeakerAngle[i]-SpeakerAngle[last]);
 
279
            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, a);
 
280
        }
 
281
    } while(0);
 
282
 
 
283
    for(i = 1;i < device->NumChan-1;i++)
 
284
    {
 
285
        enum Channel chan = Speaker2Chan[i];
 
286
        if(SpeakerAngle[i] >= langle && SpeakerAngle[i] <= rangle)
 
287
        {
 
288
            tmpgains[chan] = 1.0f;
 
289
            continue;
 
290
        }
 
291
 
 
292
        if(SpeakerAngle[i] < langle && SpeakerAngle[i+1] > langle)
 
293
        {
 
294
            a =            (langle-SpeakerAngle[i]) /
 
295
                (SpeakerAngle[i+1]-SpeakerAngle[i]);
 
296
            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, 1.0f-a);
 
297
        }
 
298
        if(SpeakerAngle[i] > rangle && SpeakerAngle[i-1] < rangle)
 
299
        {
 
300
            a =          (rangle-SpeakerAngle[i-1]) /
 
301
                (SpeakerAngle[i]-SpeakerAngle[i-1]);
 
302
            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, a);
 
303
        }
 
304
    }
 
305
 
 
306
    /* Last speaker */
 
307
    i = device->NumChan-1;
 
308
    do {
 
309
        enum Channel chan = Speaker2Chan[i];
 
310
        if(SpeakerAngle[i] >= langle && SpeakerAngle[i] <= rangle)
 
311
        {
 
312
            tmpgains[Speaker2Chan[i]] = 1.0f;
 
313
            continue;
 
314
        }
 
315
        if(SpeakerAngle[i] > rangle && SpeakerAngle[i-1] < rangle)
 
316
        {
 
317
            a =          (rangle-SpeakerAngle[i-1]) /
 
318
                (SpeakerAngle[i]-SpeakerAngle[i-1]);
 
319
            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, a);
 
320
        }
 
321
        if(SpeakerAngle[i] < langle)
 
322
        {
 
323
            a =                      (langle-SpeakerAngle[i]) /
 
324
                (F_PI*2.0f + SpeakerAngle[0]-SpeakerAngle[i]);
 
325
            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, 1.0f-a);
 
326
        }
 
327
        else if(SpeakerAngle[0] > langle)
 
328
        {
 
329
            a =          (F_PI*2.0f + langle-SpeakerAngle[i]) /
 
330
                (F_PI*2.0f + SpeakerAngle[0]-SpeakerAngle[i]);
 
331
            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, 1.0f-a);
 
332
        }
 
333
    } while(0);
 
334
 
 
335
    for(i = 0;i < device->NumChan;i++)
 
336
    {
 
337
        enum Channel chan = device->Speaker2Chan[i];
 
338
        gains[chan] = sqrtf(tmpgains[chan]) * ingain;
 
339
    }
 
340
}
 
341
 
166
342
 
167
343
ALvoid aluInitPanning(ALCdevice *Device)
168
344
{
169
 
    ALfloat SpeakerAngle[MAXCHANNELS];
170
345
    const char *layoutname = NULL;
171
346
    enum Channel *Speaker2Chan;
172
 
    ALfloat Alpha, Theta;
173
 
    ALint pos;
174
 
    ALuint s;
 
347
    ALfloat *SpeakerAngle;
175
348
 
176
349
    Speaker2Chan = Device->Speaker2Chan;
 
350
    SpeakerAngle = Device->SpeakerAngle;
177
351
    switch(Device->FmtChans)
178
352
    {
179
353
        case DevFmtMono:
180
354
            Device->NumChan = 1;
181
 
            Speaker2Chan[0] = FRONT_CENTER;
 
355
            Speaker2Chan[0] = FrontCenter;
182
356
            SpeakerAngle[0] = F_PI/180.0f * 0.0f;
183
357
            layoutname = NULL;
184
358
            break;
185
359
 
186
360
        case DevFmtStereo:
187
361
            Device->NumChan = 2;
188
 
            Speaker2Chan[0] = FRONT_LEFT;
189
 
            Speaker2Chan[1] = FRONT_RIGHT;
 
362
            Speaker2Chan[0] = FrontLeft;
 
363
            Speaker2Chan[1] = FrontRight;
190
364
            SpeakerAngle[0] = F_PI/180.0f * -90.0f;
191
365
            SpeakerAngle[1] = F_PI/180.0f *  90.0f;
192
366
            layoutname = "layout_stereo";
194
368
 
195
369
        case DevFmtQuad:
196
370
            Device->NumChan = 4;
197
 
            Speaker2Chan[0] = BACK_LEFT;
198
 
            Speaker2Chan[1] = FRONT_LEFT;
199
 
            Speaker2Chan[2] = FRONT_RIGHT;
200
 
            Speaker2Chan[3] = BACK_RIGHT;
 
371
            Speaker2Chan[0] = BackLeft;
 
372
            Speaker2Chan[1] = FrontLeft;
 
373
            Speaker2Chan[2] = FrontRight;
 
374
            Speaker2Chan[3] = BackRight;
201
375
            SpeakerAngle[0] = F_PI/180.0f * -135.0f;
202
376
            SpeakerAngle[1] = F_PI/180.0f *  -45.0f;
203
377
            SpeakerAngle[2] = F_PI/180.0f *   45.0f;
207
381
 
208
382
        case DevFmtX51:
209
383
            Device->NumChan = 5;
210
 
            Speaker2Chan[0] = BACK_LEFT;
211
 
            Speaker2Chan[1] = FRONT_LEFT;
212
 
            Speaker2Chan[2] = FRONT_CENTER;
213
 
            Speaker2Chan[3] = FRONT_RIGHT;
214
 
            Speaker2Chan[4] = BACK_RIGHT;
 
384
            Speaker2Chan[0] = BackLeft;
 
385
            Speaker2Chan[1] = FrontLeft;
 
386
            Speaker2Chan[2] = FrontCenter;
 
387
            Speaker2Chan[3] = FrontRight;
 
388
            Speaker2Chan[4] = BackRight;
215
389
            SpeakerAngle[0] = F_PI/180.0f * -110.0f;
216
390
            SpeakerAngle[1] = F_PI/180.0f *  -30.0f;
217
391
            SpeakerAngle[2] = F_PI/180.0f *    0.0f;
222
396
 
223
397
        case DevFmtX51Side:
224
398
            Device->NumChan = 5;
225
 
            Speaker2Chan[0] = SIDE_LEFT;
226
 
            Speaker2Chan[1] = FRONT_LEFT;
227
 
            Speaker2Chan[2] = FRONT_CENTER;
228
 
            Speaker2Chan[3] = FRONT_RIGHT;
229
 
            Speaker2Chan[4] = SIDE_RIGHT;
 
399
            Speaker2Chan[0] = SideLeft;
 
400
            Speaker2Chan[1] = FrontLeft;
 
401
            Speaker2Chan[2] = FrontCenter;
 
402
            Speaker2Chan[3] = FrontRight;
 
403
            Speaker2Chan[4] = SideRight;
230
404
            SpeakerAngle[0] = F_PI/180.0f * -90.0f;
231
405
            SpeakerAngle[1] = F_PI/180.0f * -30.0f;
232
406
            SpeakerAngle[2] = F_PI/180.0f *   0.0f;
237
411
 
238
412
        case DevFmtX61:
239
413
            Device->NumChan = 6;
240
 
            Speaker2Chan[0] = SIDE_LEFT;
241
 
            Speaker2Chan[1] = FRONT_LEFT;
242
 
            Speaker2Chan[2] = FRONT_CENTER;
243
 
            Speaker2Chan[3] = FRONT_RIGHT;
244
 
            Speaker2Chan[4] = SIDE_RIGHT;
245
 
            Speaker2Chan[5] = BACK_CENTER;
 
414
            Speaker2Chan[0] = SideLeft;
 
415
            Speaker2Chan[1] = FrontLeft;
 
416
            Speaker2Chan[2] = FrontCenter;
 
417
            Speaker2Chan[3] = FrontRight;
 
418
            Speaker2Chan[4] = SideRight;
 
419
            Speaker2Chan[5] = BackCenter;
246
420
            SpeakerAngle[0] = F_PI/180.0f * -90.0f;
247
421
            SpeakerAngle[1] = F_PI/180.0f * -30.0f;
248
422
            SpeakerAngle[2] = F_PI/180.0f *   0.0f;
254
428
 
255
429
        case DevFmtX71:
256
430
            Device->NumChan = 7;
257
 
            Speaker2Chan[0] = BACK_LEFT;
258
 
            Speaker2Chan[1] = SIDE_LEFT;
259
 
            Speaker2Chan[2] = FRONT_LEFT;
260
 
            Speaker2Chan[3] = FRONT_CENTER;
261
 
            Speaker2Chan[4] = FRONT_RIGHT;
262
 
            Speaker2Chan[5] = SIDE_RIGHT;
263
 
            Speaker2Chan[6] = BACK_RIGHT;
 
431
            Speaker2Chan[0] = BackLeft;
 
432
            Speaker2Chan[1] = SideLeft;
 
433
            Speaker2Chan[2] = FrontLeft;
 
434
            Speaker2Chan[3] = FrontCenter;
 
435
            Speaker2Chan[4] = FrontRight;
 
436
            Speaker2Chan[5] = SideRight;
 
437
            Speaker2Chan[6] = BackRight;
264
438
            SpeakerAngle[0] = F_PI/180.0f * -150.0f;
265
439
            SpeakerAngle[1] = F_PI/180.0f *  -90.0f;
266
440
            SpeakerAngle[2] = F_PI/180.0f *  -30.0f;
273
447
    }
274
448
    if(layoutname && Device->Type != Loopback)
275
449
        SetSpeakerArrangement(layoutname, SpeakerAngle, Speaker2Chan, Device->NumChan);
276
 
 
277
 
    for(pos = 0; pos < LUT_NUM; pos++)
278
 
    {
279
 
        ALfloat *PanningLUT = Device->PanningLUT[pos];
280
 
 
281
 
        /* clear all values */
282
 
        for(s = 0; s < MAXCHANNELS; s++)
283
 
            PanningLUT[s] = 0.0f;
284
 
 
285
 
        if(Device->NumChan == 1)
286
 
        {
287
 
            PanningLUT[Speaker2Chan[0]] = 1.0f;
288
 
            continue;
289
 
        }
290
 
 
291
 
        /* source angle */
292
 
        Theta = aluLUTpos2Angle(pos);
293
 
 
294
 
        /* set panning values */
295
 
        for(s = 0; s < Device->NumChan - 1; s++)
296
 
        {
297
 
            if(Theta >= SpeakerAngle[s] && Theta < SpeakerAngle[s+1])
298
 
            {
299
 
                /* source between speaker s and speaker s+1 */
300
 
                Alpha = (Theta-SpeakerAngle[s]) /
301
 
                        (SpeakerAngle[s+1]-SpeakerAngle[s]);
302
 
                PanningLUT[Speaker2Chan[s]]   = aluSqrt(1.0f-Alpha);
303
 
                PanningLUT[Speaker2Chan[s+1]] = aluSqrt(     Alpha);
304
 
                break;
305
 
            }
306
 
        }
307
 
        if(s == Device->NumChan - 1)
308
 
        {
309
 
            /* source between last and first speaker */
310
 
            if(Theta < SpeakerAngle[0])
311
 
                Theta += F_PI*2.0f;
312
 
            Alpha = (Theta-SpeakerAngle[s]) /
313
 
                    (F_PI*2.0f + SpeakerAngle[0]-SpeakerAngle[s]);
314
 
            PanningLUT[Speaker2Chan[s]] = aluSqrt(1.0f-Alpha);
315
 
            PanningLUT[Speaker2Chan[0]] = aluSqrt(     Alpha);
316
 
        }
317
 
    }
318
450
}