2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2010 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
34 static void SetSpeakerArrangement(const char *name
, ALfloat SpeakerAngle
[MAXCHANNELS
],
35 Channel Speaker2Chan
[MAXCHANNELS
], ALint chans
)
43 strncpy(layout_str
, GetConfigValue(NULL
, name
, ""), sizeof(layout_str
));
44 layout_str
[sizeof(layout_str
)-1] = 0;
49 next
= confkey
= layout_str
;
53 next
= strchr(confkey
, ',');
59 } while(isspace(*next
) || *next
== ',');
62 sep
= strchr(confkey
, '=');
63 if(!sep
|| confkey
== sep
)
67 while(isspace(*end
) && end
!= confkey
)
71 if(strcmp(confkey
, "fl") == 0 || strcmp(confkey
, "front-left") == 0)
73 else if(strcmp(confkey
, "fr") == 0 || strcmp(confkey
, "front-right") == 0)
75 else if(strcmp(confkey
, "fc") == 0 || strcmp(confkey
, "front-center") == 0)
77 else if(strcmp(confkey
, "bl") == 0 || strcmp(confkey
, "back-left") == 0)
79 else if(strcmp(confkey
, "br") == 0 || strcmp(confkey
, "back-right") == 0)
81 else if(strcmp(confkey
, "bc") == 0 || strcmp(confkey
, "back-center") == 0)
83 else if(strcmp(confkey
, "sl") == 0 || strcmp(confkey
, "side-left") == 0)
85 else if(strcmp(confkey
, "sr") == 0 || strcmp(confkey
, "side-right") == 0)
89 AL_PRINT("Unknown speaker for %s: \"%s\"\n", name
, confkey
);
97 for(i
= 0;i
< chans
;i
++)
99 if(Speaker2Chan
[i
] == val
)
101 long angle
= strtol(sep
, NULL
, 10);
102 if(angle
>= -180 && angle
<= 180)
103 SpeakerAngle
[i
] = angle
* M_PI
/180.0f
;
105 AL_PRINT("Invalid angle for speaker \"%s\": %ld\n", confkey
, angle
);
111 for(i
= 0;i
< chans
;i
++)
116 for(i2
= i
+1;i2
< chans
;i2
++)
118 if(SpeakerAngle
[i2
] < SpeakerAngle
[min
])
127 tmpf
= SpeakerAngle
[i
];
128 SpeakerAngle
[i
] = SpeakerAngle
[min
];
129 SpeakerAngle
[min
] = tmpf
;
131 tmpc
= Speaker2Chan
[i
];
132 Speaker2Chan
[i
] = Speaker2Chan
[min
];
133 Speaker2Chan
[min
] = tmpc
;
138 static ALfloat
aluLUTpos2Angle(ALint pos
)
140 if(pos
< QUADRANT_NUM
)
141 return aluAtan((ALfloat
)pos
/ (ALfloat
)(QUADRANT_NUM
- pos
));
142 if(pos
< 2 * QUADRANT_NUM
)
143 return M_PI_2
+ aluAtan((ALfloat
)(pos
- QUADRANT_NUM
) / (ALfloat
)(2 * QUADRANT_NUM
- pos
));
144 if(pos
< 3 * QUADRANT_NUM
)
145 return aluAtan((ALfloat
)(pos
- 2 * QUADRANT_NUM
) / (ALfloat
)(3 * QUADRANT_NUM
- pos
)) - M_PI
;
146 return aluAtan((ALfloat
)(pos
- 3 * QUADRANT_NUM
) / (ALfloat
)(4 * QUADRANT_NUM
- pos
)) - M_PI_2
;
149 ALint
aluCart2LUTpos(ALfloat re
, ALfloat im
)
152 ALfloat denom
= aluFabs(re
) + aluFabs(im
);
154 pos
= (ALint
)(QUADRANT_NUM
*aluFabs(im
) / denom
+ 0.5);
157 pos
= 2 * QUADRANT_NUM
- pos
;
163 ALvoid
aluInitPanning(ALCdevice
*Device
)
165 ALfloat SpeakerAngle
[MAXCHANNELS
];
166 ALfloat (*Matrix
)[MAXCHANNELS
];
167 Channel
*Speaker2Chan
;
168 ALfloat Alpha
, Theta
;
173 for(s
= 0;s
< MAXCHANNELS
;s
++)
175 for(s2
= 0;s2
< MAXCHANNELS
;s2
++)
176 Device
->ChannelMatrix
[s
][s2
] = ((s
==s2
) ? 1.0f
: 0.0f
);
179 Speaker2Chan
= Device
->Speaker2Chan
;
180 Matrix
= Device
->ChannelMatrix
;
181 switch(Device
->Format
)
183 case AL_FORMAT_MONO8
:
184 case AL_FORMAT_MONO16
:
185 case AL_FORMAT_MONO_FLOAT32
:
186 Matrix
[FRONT_LEFT
][FRONT_CENTER
] = aluSqrt(0.5);
187 Matrix
[FRONT_RIGHT
][FRONT_CENTER
] = aluSqrt(0.5);
188 Matrix
[SIDE_LEFT
][FRONT_CENTER
] = aluSqrt(0.5);
189 Matrix
[SIDE_RIGHT
][FRONT_CENTER
] = aluSqrt(0.5);
190 Matrix
[BACK_LEFT
][FRONT_CENTER
] = aluSqrt(0.5);
191 Matrix
[BACK_RIGHT
][FRONT_CENTER
] = aluSqrt(0.5);
192 Matrix
[BACK_CENTER
][FRONT_CENTER
] = 1.0f
;
194 Speaker2Chan
[0] = FRONT_CENTER
;
195 SpeakerAngle
[0] = 0.0f
* M_PI
/180.0f
;
198 case AL_FORMAT_STEREO8
:
199 case AL_FORMAT_STEREO16
:
200 case AL_FORMAT_STEREO_FLOAT32
:
201 Matrix
[FRONT_CENTER
][FRONT_LEFT
] = aluSqrt(0.5);
202 Matrix
[FRONT_CENTER
][FRONT_RIGHT
] = aluSqrt(0.5);
203 Matrix
[SIDE_LEFT
][FRONT_LEFT
] = 1.0f
;
204 Matrix
[SIDE_RIGHT
][FRONT_RIGHT
] = 1.0f
;
205 Matrix
[BACK_LEFT
][FRONT_LEFT
] = 1.0f
;
206 Matrix
[BACK_RIGHT
][FRONT_RIGHT
] = 1.0f
;
207 Matrix
[BACK_CENTER
][FRONT_LEFT
] = aluSqrt(0.5);
208 Matrix
[BACK_CENTER
][FRONT_RIGHT
] = aluSqrt(0.5);
210 Speaker2Chan
[0] = FRONT_LEFT
;
211 Speaker2Chan
[1] = FRONT_RIGHT
;
212 SpeakerAngle
[0] = -90.0f
* M_PI
/180.0f
;
213 SpeakerAngle
[1] = 90.0f
* M_PI
/180.0f
;
214 SetSpeakerArrangement("layout", SpeakerAngle
, Speaker2Chan
, Device
->NumChan
);
217 case AL_FORMAT_QUAD8
:
218 case AL_FORMAT_QUAD16
:
219 case AL_FORMAT_QUAD32
:
220 Matrix
[FRONT_CENTER
][FRONT_LEFT
] = aluSqrt(0.5);
221 Matrix
[FRONT_CENTER
][FRONT_RIGHT
] = aluSqrt(0.5);
222 Matrix
[SIDE_LEFT
][FRONT_LEFT
] = aluSqrt(0.5);
223 Matrix
[SIDE_LEFT
][BACK_LEFT
] = aluSqrt(0.5);
224 Matrix
[SIDE_RIGHT
][FRONT_RIGHT
] = aluSqrt(0.5);
225 Matrix
[SIDE_RIGHT
][BACK_RIGHT
] = aluSqrt(0.5);
226 Matrix
[BACK_CENTER
][BACK_LEFT
] = aluSqrt(0.5);
227 Matrix
[BACK_CENTER
][BACK_RIGHT
] = aluSqrt(0.5);
229 Speaker2Chan
[0] = BACK_LEFT
;
230 Speaker2Chan
[1] = FRONT_LEFT
;
231 Speaker2Chan
[2] = FRONT_RIGHT
;
232 Speaker2Chan
[3] = BACK_RIGHT
;
233 SpeakerAngle
[0] = -135.0f
* M_PI
/180.0f
;
234 SpeakerAngle
[1] = -45.0f
* M_PI
/180.0f
;
235 SpeakerAngle
[2] = 45.0f
* M_PI
/180.0f
;
236 SpeakerAngle
[3] = 135.0f
* M_PI
/180.0f
;
237 SetSpeakerArrangement("layout", SpeakerAngle
, Speaker2Chan
, Device
->NumChan
);
240 case AL_FORMAT_51CHN8
:
241 case AL_FORMAT_51CHN16
:
242 case AL_FORMAT_51CHN32
:
243 Matrix
[SIDE_LEFT
][FRONT_LEFT
] = aluSqrt(0.5);
244 Matrix
[SIDE_LEFT
][BACK_LEFT
] = aluSqrt(0.5);
245 Matrix
[SIDE_RIGHT
][FRONT_RIGHT
] = aluSqrt(0.5);
246 Matrix
[SIDE_RIGHT
][BACK_RIGHT
] = aluSqrt(0.5);
247 Matrix
[BACK_CENTER
][BACK_LEFT
] = aluSqrt(0.5);
248 Matrix
[BACK_CENTER
][BACK_RIGHT
] = aluSqrt(0.5);
250 Speaker2Chan
[0] = BACK_LEFT
;
251 Speaker2Chan
[1] = FRONT_LEFT
;
252 Speaker2Chan
[2] = FRONT_CENTER
;
253 Speaker2Chan
[3] = FRONT_RIGHT
;
254 Speaker2Chan
[4] = BACK_RIGHT
;
255 SpeakerAngle
[0] = -110.0f
* M_PI
/180.0f
;
256 SpeakerAngle
[1] = -30.0f
* M_PI
/180.0f
;
257 SpeakerAngle
[2] = 0.0f
* M_PI
/180.0f
;
258 SpeakerAngle
[3] = 30.0f
* M_PI
/180.0f
;
259 SpeakerAngle
[4] = 110.0f
* M_PI
/180.0f
;
260 SetSpeakerArrangement("layout", SpeakerAngle
, Speaker2Chan
, Device
->NumChan
);
263 case AL_FORMAT_61CHN8
:
264 case AL_FORMAT_61CHN16
:
265 case AL_FORMAT_61CHN32
:
266 Matrix
[BACK_LEFT
][BACK_CENTER
] = aluSqrt(0.5);
267 Matrix
[BACK_LEFT
][SIDE_LEFT
] = aluSqrt(0.5);
268 Matrix
[BACK_RIGHT
][BACK_CENTER
] = aluSqrt(0.5);
269 Matrix
[BACK_RIGHT
][SIDE_RIGHT
] = aluSqrt(0.5);
271 Speaker2Chan
[0] = SIDE_LEFT
;
272 Speaker2Chan
[1] = FRONT_LEFT
;
273 Speaker2Chan
[2] = FRONT_CENTER
;
274 Speaker2Chan
[3] = FRONT_RIGHT
;
275 Speaker2Chan
[4] = SIDE_RIGHT
;
276 Speaker2Chan
[5] = BACK_CENTER
;
277 SpeakerAngle
[0] = -90.0f
* M_PI
/180.0f
;
278 SpeakerAngle
[1] = -30.0f
* M_PI
/180.0f
;
279 SpeakerAngle
[2] = 0.0f
* M_PI
/180.0f
;
280 SpeakerAngle
[3] = 30.0f
* M_PI
/180.0f
;
281 SpeakerAngle
[4] = 90.0f
* M_PI
/180.0f
;
282 SpeakerAngle
[5] = 180.0f
* M_PI
/180.0f
;
283 SetSpeakerArrangement("layout", SpeakerAngle
, Speaker2Chan
, Device
->NumChan
);
286 case AL_FORMAT_71CHN8
:
287 case AL_FORMAT_71CHN16
:
288 case AL_FORMAT_71CHN32
:
289 Matrix
[BACK_CENTER
][BACK_LEFT
] = aluSqrt(0.5);
290 Matrix
[BACK_CENTER
][BACK_RIGHT
] = aluSqrt(0.5);
292 Speaker2Chan
[0] = BACK_LEFT
;
293 Speaker2Chan
[1] = SIDE_LEFT
;
294 Speaker2Chan
[2] = FRONT_LEFT
;
295 Speaker2Chan
[3] = FRONT_CENTER
;
296 Speaker2Chan
[4] = FRONT_RIGHT
;
297 Speaker2Chan
[5] = SIDE_RIGHT
;
298 Speaker2Chan
[6] = BACK_RIGHT
;
299 SpeakerAngle
[0] = -150.0f
* M_PI
/180.0f
;
300 SpeakerAngle
[1] = -90.0f
* M_PI
/180.0f
;
301 SpeakerAngle
[2] = -30.0f
* M_PI
/180.0f
;
302 SpeakerAngle
[3] = 0.0f
* M_PI
/180.0f
;
303 SpeakerAngle
[4] = 30.0f
* M_PI
/180.0f
;
304 SpeakerAngle
[5] = 90.0f
* M_PI
/180.0f
;
305 SpeakerAngle
[6] = 150.0f
* M_PI
/180.0f
;
306 SetSpeakerArrangement("layout", SpeakerAngle
, Speaker2Chan
, Device
->NumChan
);
313 if(GetConfigValueBool(NULL
, "scalemix", 0))
315 ALfloat maxout
= 1.0f
;
316 for(s
= 0;s
< MAXCHANNELS
;s
++)
319 for(s2
= 0;s2
< MAXCHANNELS
;s2
++)
320 out
+= Device
->ChannelMatrix
[s2
][s
];
321 maxout
= __max(maxout
, out
);
324 maxout
= 1.0f
/maxout
;
325 for(s
= 0;s
< MAXCHANNELS
;s
++)
327 for(s2
= 0;s2
< MAXCHANNELS
;s2
++)
328 Device
->ChannelMatrix
[s2
][s
] *= maxout
;
332 PanningLUT
= Device
->PanningLUT
;
333 for(pos
= 0; pos
< LUT_NUM
; pos
++)
335 /* clear all values */
336 offset
= MAXCHANNELS
* pos
;
337 for(s
= 0; s
< MAXCHANNELS
; s
++)
338 PanningLUT
[offset
+s
] = 0.0f
;
340 if(Device
->NumChan
== 1)
342 PanningLUT
[offset
+ Speaker2Chan
[0]] = 1.0f
;
347 Theta
= aluLUTpos2Angle(pos
);
349 /* set panning values */
350 for(s
= 0; s
< Device
->NumChan
- 1; s
++)
352 if(Theta
>= SpeakerAngle
[s
] && Theta
< SpeakerAngle
[s
+1])
354 /* source between speaker s and speaker s+1 */
355 Alpha
= M_PI_2
* (Theta
-SpeakerAngle
[s
]) /
356 (SpeakerAngle
[s
+1]-SpeakerAngle
[s
]);
357 PanningLUT
[offset
+ Speaker2Chan
[s
]] = cos(Alpha
);
358 PanningLUT
[offset
+ Speaker2Chan
[s
+1]] = sin(Alpha
);
362 if(s
== Device
->NumChan
- 1)
364 /* source between last and first speaker */
365 if(Theta
< SpeakerAngle
[0])
366 Theta
+= 2.0f
* M_PI
;
367 Alpha
= M_PI_2
* (Theta
-SpeakerAngle
[s
]) /
368 (2.0f
* M_PI
+ SpeakerAngle
[0]-SpeakerAngle
[s
]);
369 PanningLUT
[offset
+ Speaker2Chan
[s
]] = cos(Alpha
);
370 PanningLUT
[offset
+ Speaker2Chan
[0]] = sin(Alpha
);