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
[OUTPUTCHANNELS
],
35 Channel Speaker2Chan
[OUTPUTCHANNELS
], 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 ALvoid
aluInitPanning(ALCdevice
*Device
)
151 ALfloat SpeakerAngle
[OUTPUTCHANNELS
];
152 ALfloat (*Matrix
)[OUTPUTCHANNELS
];
153 Channel
*Speaker2Chan
;
154 ALfloat Alpha
, Theta
;
159 for(s
= 0;s
< OUTPUTCHANNELS
;s
++)
161 for(s2
= 0;s2
< OUTPUTCHANNELS
;s2
++)
162 Device
->ChannelMatrix
[s
][s2
] = ((s
==s2
) ? 1.0f
: 0.0f
);
165 Speaker2Chan
= Device
->Speaker2Chan
;
166 Matrix
= Device
->ChannelMatrix
;
167 switch(Device
->Format
)
169 case AL_FORMAT_MONO8
:
170 case AL_FORMAT_MONO16
:
171 case AL_FORMAT_MONO_FLOAT32
:
172 Matrix
[FRONT_LEFT
][FRONT_CENTER
] = aluSqrt(0.5);
173 Matrix
[FRONT_RIGHT
][FRONT_CENTER
] = aluSqrt(0.5);
174 Matrix
[SIDE_LEFT
][FRONT_CENTER
] = aluSqrt(0.5);
175 Matrix
[SIDE_RIGHT
][FRONT_CENTER
] = aluSqrt(0.5);
176 Matrix
[BACK_LEFT
][FRONT_CENTER
] = aluSqrt(0.5);
177 Matrix
[BACK_RIGHT
][FRONT_CENTER
] = aluSqrt(0.5);
178 Matrix
[BACK_CENTER
][FRONT_CENTER
] = 1.0f
;
180 Speaker2Chan
[0] = FRONT_CENTER
;
181 SpeakerAngle
[0] = 0.0f
* M_PI
/180.0f
;
184 case AL_FORMAT_STEREO8
:
185 case AL_FORMAT_STEREO16
:
186 case AL_FORMAT_STEREO_FLOAT32
:
187 Matrix
[FRONT_CENTER
][FRONT_LEFT
] = aluSqrt(0.5);
188 Matrix
[FRONT_CENTER
][FRONT_RIGHT
] = aluSqrt(0.5);
189 Matrix
[SIDE_LEFT
][FRONT_LEFT
] = 1.0f
;
190 Matrix
[SIDE_RIGHT
][FRONT_RIGHT
] = 1.0f
;
191 Matrix
[BACK_LEFT
][FRONT_LEFT
] = 1.0f
;
192 Matrix
[BACK_RIGHT
][FRONT_RIGHT
] = 1.0f
;
193 Matrix
[BACK_CENTER
][FRONT_LEFT
] = aluSqrt(0.5);
194 Matrix
[BACK_CENTER
][FRONT_RIGHT
] = aluSqrt(0.5);
196 Speaker2Chan
[0] = FRONT_LEFT
;
197 Speaker2Chan
[1] = FRONT_RIGHT
;
198 SpeakerAngle
[0] = -90.0f
* M_PI
/180.0f
;
199 SpeakerAngle
[1] = 90.0f
* M_PI
/180.0f
;
200 SetSpeakerArrangement("layout", SpeakerAngle
, Speaker2Chan
, Device
->NumChan
);
203 case AL_FORMAT_QUAD8
:
204 case AL_FORMAT_QUAD16
:
205 case AL_FORMAT_QUAD32
:
206 Matrix
[FRONT_CENTER
][FRONT_LEFT
] = aluSqrt(0.5);
207 Matrix
[FRONT_CENTER
][FRONT_RIGHT
] = aluSqrt(0.5);
208 Matrix
[SIDE_LEFT
][FRONT_LEFT
] = aluSqrt(0.5);
209 Matrix
[SIDE_LEFT
][BACK_LEFT
] = aluSqrt(0.5);
210 Matrix
[SIDE_RIGHT
][FRONT_RIGHT
] = aluSqrt(0.5);
211 Matrix
[SIDE_RIGHT
][BACK_RIGHT
] = aluSqrt(0.5);
212 Matrix
[BACK_CENTER
][BACK_LEFT
] = aluSqrt(0.5);
213 Matrix
[BACK_CENTER
][BACK_RIGHT
] = aluSqrt(0.5);
215 Speaker2Chan
[0] = BACK_LEFT
;
216 Speaker2Chan
[1] = FRONT_LEFT
;
217 Speaker2Chan
[2] = FRONT_RIGHT
;
218 Speaker2Chan
[3] = BACK_RIGHT
;
219 SpeakerAngle
[0] = -135.0f
* M_PI
/180.0f
;
220 SpeakerAngle
[1] = -45.0f
* M_PI
/180.0f
;
221 SpeakerAngle
[2] = 45.0f
* M_PI
/180.0f
;
222 SpeakerAngle
[3] = 135.0f
* M_PI
/180.0f
;
223 SetSpeakerArrangement("layout", SpeakerAngle
, Speaker2Chan
, Device
->NumChan
);
226 case AL_FORMAT_51CHN8
:
227 case AL_FORMAT_51CHN16
:
228 case AL_FORMAT_51CHN32
:
229 Matrix
[SIDE_LEFT
][FRONT_LEFT
] = aluSqrt(0.5);
230 Matrix
[SIDE_LEFT
][BACK_LEFT
] = aluSqrt(0.5);
231 Matrix
[SIDE_RIGHT
][FRONT_RIGHT
] = aluSqrt(0.5);
232 Matrix
[SIDE_RIGHT
][BACK_RIGHT
] = aluSqrt(0.5);
233 Matrix
[BACK_CENTER
][BACK_LEFT
] = aluSqrt(0.5);
234 Matrix
[BACK_CENTER
][BACK_RIGHT
] = aluSqrt(0.5);
236 Speaker2Chan
[0] = BACK_LEFT
;
237 Speaker2Chan
[1] = FRONT_LEFT
;
238 Speaker2Chan
[2] = FRONT_CENTER
;
239 Speaker2Chan
[3] = FRONT_RIGHT
;
240 Speaker2Chan
[4] = BACK_RIGHT
;
241 SpeakerAngle
[0] = -110.0f
* M_PI
/180.0f
;
242 SpeakerAngle
[1] = -30.0f
* M_PI
/180.0f
;
243 SpeakerAngle
[2] = 0.0f
* M_PI
/180.0f
;
244 SpeakerAngle
[3] = 30.0f
* M_PI
/180.0f
;
245 SpeakerAngle
[4] = 110.0f
* M_PI
/180.0f
;
246 SetSpeakerArrangement("layout", SpeakerAngle
, Speaker2Chan
, Device
->NumChan
);
249 case AL_FORMAT_61CHN8
:
250 case AL_FORMAT_61CHN16
:
251 case AL_FORMAT_61CHN32
:
252 Matrix
[BACK_LEFT
][BACK_CENTER
] = aluSqrt(0.5);
253 Matrix
[BACK_LEFT
][SIDE_LEFT
] = aluSqrt(0.5);
254 Matrix
[BACK_RIGHT
][BACK_CENTER
] = aluSqrt(0.5);
255 Matrix
[BACK_RIGHT
][SIDE_RIGHT
] = aluSqrt(0.5);
257 Speaker2Chan
[0] = SIDE_LEFT
;
258 Speaker2Chan
[1] = FRONT_LEFT
;
259 Speaker2Chan
[2] = FRONT_CENTER
;
260 Speaker2Chan
[3] = FRONT_RIGHT
;
261 Speaker2Chan
[4] = SIDE_RIGHT
;
262 Speaker2Chan
[5] = BACK_CENTER
;
263 SpeakerAngle
[0] = -90.0f
* M_PI
/180.0f
;
264 SpeakerAngle
[1] = -30.0f
* M_PI
/180.0f
;
265 SpeakerAngle
[2] = 0.0f
* M_PI
/180.0f
;
266 SpeakerAngle
[3] = 30.0f
* M_PI
/180.0f
;
267 SpeakerAngle
[4] = 90.0f
* M_PI
/180.0f
;
268 SpeakerAngle
[5] = 180.0f
* M_PI
/180.0f
;
269 SetSpeakerArrangement("layout", SpeakerAngle
, Speaker2Chan
, Device
->NumChan
);
272 case AL_FORMAT_71CHN8
:
273 case AL_FORMAT_71CHN16
:
274 case AL_FORMAT_71CHN32
:
275 Matrix
[BACK_CENTER
][BACK_LEFT
] = aluSqrt(0.5);
276 Matrix
[BACK_CENTER
][BACK_RIGHT
] = aluSqrt(0.5);
278 Speaker2Chan
[0] = BACK_LEFT
;
279 Speaker2Chan
[1] = SIDE_LEFT
;
280 Speaker2Chan
[2] = FRONT_LEFT
;
281 Speaker2Chan
[3] = FRONT_CENTER
;
282 Speaker2Chan
[4] = FRONT_RIGHT
;
283 Speaker2Chan
[5] = SIDE_RIGHT
;
284 Speaker2Chan
[6] = BACK_RIGHT
;
285 SpeakerAngle
[0] = -150.0f
* M_PI
/180.0f
;
286 SpeakerAngle
[1] = -90.0f
* M_PI
/180.0f
;
287 SpeakerAngle
[2] = -30.0f
* M_PI
/180.0f
;
288 SpeakerAngle
[3] = 0.0f
* M_PI
/180.0f
;
289 SpeakerAngle
[4] = 30.0f
* M_PI
/180.0f
;
290 SpeakerAngle
[5] = 90.0f
* M_PI
/180.0f
;
291 SpeakerAngle
[6] = 150.0f
* M_PI
/180.0f
;
292 SetSpeakerArrangement("layout", SpeakerAngle
, Speaker2Chan
, Device
->NumChan
);
299 if(GetConfigValueBool(NULL
, "scalemix", 0))
301 ALfloat maxout
= 1.0f
;
302 for(s
= 0;s
< OUTPUTCHANNELS
;s
++)
305 for(s2
= 0;s2
< OUTPUTCHANNELS
;s2
++)
306 out
+= Device
->ChannelMatrix
[s2
][s
];
307 maxout
= __max(maxout
, out
);
310 maxout
= 1.0f
/maxout
;
311 for(s
= 0;s
< OUTPUTCHANNELS
;s
++)
313 for(s2
= 0;s2
< OUTPUTCHANNELS
;s2
++)
314 Device
->ChannelMatrix
[s2
][s
] *= maxout
;
318 PanningLUT
= Device
->PanningLUT
;
319 for(pos
= 0; pos
< LUT_NUM
; pos
++)
321 /* clear all values */
322 offset
= OUTPUTCHANNELS
* pos
;
323 for(s
= 0; s
< OUTPUTCHANNELS
; s
++)
324 PanningLUT
[offset
+s
] = 0.0f
;
326 if(Device
->NumChan
== 1)
328 PanningLUT
[offset
+ Speaker2Chan
[0]] = 1.0f
;
333 Theta
= aluLUTpos2Angle(pos
);
335 /* set panning values */
336 for(s
= 0; s
< Device
->NumChan
- 1; s
++)
338 if(Theta
>= SpeakerAngle
[s
] && Theta
< SpeakerAngle
[s
+1])
340 /* source between speaker s and speaker s+1 */
341 Alpha
= M_PI_2
* (Theta
-SpeakerAngle
[s
]) /
342 (SpeakerAngle
[s
+1]-SpeakerAngle
[s
]);
343 PanningLUT
[offset
+ Speaker2Chan
[s
]] = cos(Alpha
);
344 PanningLUT
[offset
+ Speaker2Chan
[s
+1]] = sin(Alpha
);
348 if(s
== Device
->NumChan
- 1)
350 /* source between last and first speaker */
351 if(Theta
< SpeakerAngle
[0])
352 Theta
+= 2.0f
* M_PI
;
353 Alpha
= M_PI_2
* (Theta
-SpeakerAngle
[s
]) /
354 (2.0f
* M_PI
+ SpeakerAngle
[0]-SpeakerAngle
[s
]);
355 PanningLUT
[offset
+ Speaker2Chan
[s
]] = cos(Alpha
);
356 PanningLUT
[offset
+ Speaker2Chan
[0]] = sin(Alpha
);