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 if(!ConfigValueExists(NULL
, name
))
46 strncpy(layout_str
, GetConfigValue(NULL
, name
, ""), sizeof(layout_str
));
47 layout_str
[sizeof(layout_str
)-1] = 0;
52 next
= confkey
= layout_str
;
56 next
= strchr(confkey
, ',');
62 } while(isspace(*next
) || *next
== ',');
65 sep
= strchr(confkey
, '=');
66 if(!sep
|| confkey
== sep
)
70 while(isspace(*end
) && end
!= confkey
)
74 if(strcmp(confkey
, "fl") == 0 || strcmp(confkey
, "front-left") == 0)
76 else if(strcmp(confkey
, "fr") == 0 || strcmp(confkey
, "front-right") == 0)
78 else if(strcmp(confkey
, "fc") == 0 || strcmp(confkey
, "front-center") == 0)
80 else if(strcmp(confkey
, "bl") == 0 || strcmp(confkey
, "back-left") == 0)
82 else if(strcmp(confkey
, "br") == 0 || strcmp(confkey
, "back-right") == 0)
84 else if(strcmp(confkey
, "bc") == 0 || strcmp(confkey
, "back-center") == 0)
86 else if(strcmp(confkey
, "sl") == 0 || strcmp(confkey
, "side-left") == 0)
88 else if(strcmp(confkey
, "sr") == 0 || strcmp(confkey
, "side-right") == 0)
92 AL_PRINT("Unknown speaker for %s: \"%s\"\n", name
, confkey
);
100 for(i
= 0;i
< chans
;i
++)
102 if(Speaker2Chan
[i
] == val
)
104 long angle
= strtol(sep
, NULL
, 10);
105 if(angle
>= -180 && angle
<= 180)
106 SpeakerAngle
[i
] = angle
* M_PI
/180.0f
;
108 AL_PRINT("Invalid angle for speaker \"%s\": %ld\n", confkey
, angle
);
114 for(i
= 0;i
< chans
;i
++)
119 for(i2
= i
+1;i2
< chans
;i2
++)
121 if(SpeakerAngle
[i2
] < SpeakerAngle
[min
])
130 tmpf
= SpeakerAngle
[i
];
131 SpeakerAngle
[i
] = SpeakerAngle
[min
];
132 SpeakerAngle
[min
] = tmpf
;
134 tmpc
= Speaker2Chan
[i
];
135 Speaker2Chan
[i
] = Speaker2Chan
[min
];
136 Speaker2Chan
[min
] = tmpc
;
141 static ALfloat
aluLUTpos2Angle(ALint pos
)
143 if(pos
< QUADRANT_NUM
)
144 return aluAtan((ALfloat
)pos
/ (ALfloat
)(QUADRANT_NUM
- pos
));
145 if(pos
< 2 * QUADRANT_NUM
)
146 return M_PI_2
+ aluAtan((ALfloat
)(pos
- QUADRANT_NUM
) / (ALfloat
)(2 * QUADRANT_NUM
- pos
));
147 if(pos
< 3 * QUADRANT_NUM
)
148 return aluAtan((ALfloat
)(pos
- 2 * QUADRANT_NUM
) / (ALfloat
)(3 * QUADRANT_NUM
- pos
)) - M_PI
;
149 return aluAtan((ALfloat
)(pos
- 3 * QUADRANT_NUM
) / (ALfloat
)(4 * QUADRANT_NUM
- pos
)) - M_PI_2
;
152 ALint
aluCart2LUTpos(ALfloat re
, ALfloat im
)
155 ALfloat denom
= aluFabs(re
) + aluFabs(im
);
157 pos
= (ALint
)(QUADRANT_NUM
*aluFabs(im
) / denom
+ 0.5);
160 pos
= 2 * QUADRANT_NUM
- pos
;
166 ALvoid
aluInitPanning(ALCdevice
*Device
)
168 ALfloat SpeakerAngle
[MAXCHANNELS
];
169 ALfloat (*Matrix
)[MAXCHANNELS
];
170 Channel
*Speaker2Chan
;
171 ALfloat Alpha
, Theta
;
176 for(s
= 0;s
< MAXCHANNELS
;s
++)
178 for(s2
= 0;s2
< MAXCHANNELS
;s2
++)
179 Device
->ChannelMatrix
[s
][s2
] = ((s
==s2
) ? 1.0f
: 0.0f
);
182 Speaker2Chan
= Device
->Speaker2Chan
;
183 Matrix
= Device
->ChannelMatrix
;
184 switch(Device
->FmtChans
)
187 Matrix
[FRONT_LEFT
][FRONT_CENTER
] = aluSqrt(0.5);
188 Matrix
[FRONT_RIGHT
][FRONT_CENTER
] = aluSqrt(0.5);
189 Matrix
[SIDE_LEFT
][FRONT_CENTER
] = aluSqrt(0.5);
190 Matrix
[SIDE_RIGHT
][FRONT_CENTER
] = aluSqrt(0.5);
191 Matrix
[BACK_LEFT
][FRONT_CENTER
] = aluSqrt(0.5);
192 Matrix
[BACK_RIGHT
][FRONT_CENTER
] = aluSqrt(0.5);
193 Matrix
[BACK_CENTER
][FRONT_CENTER
] = 1.0f
;
195 Speaker2Chan
[0] = FRONT_CENTER
;
196 SpeakerAngle
[0] = 0.0f
* M_PI
/180.0f
;
200 Matrix
[FRONT_CENTER
][FRONT_LEFT
] = aluSqrt(0.5);
201 Matrix
[FRONT_CENTER
][FRONT_RIGHT
] = aluSqrt(0.5);
202 Matrix
[SIDE_LEFT
][FRONT_LEFT
] = 1.0f
;
203 Matrix
[SIDE_RIGHT
][FRONT_RIGHT
] = 1.0f
;
204 Matrix
[BACK_LEFT
][FRONT_LEFT
] = 1.0f
;
205 Matrix
[BACK_RIGHT
][FRONT_RIGHT
] = 1.0f
;
206 Matrix
[BACK_CENTER
][FRONT_LEFT
] = aluSqrt(0.5);
207 Matrix
[BACK_CENTER
][FRONT_RIGHT
] = aluSqrt(0.5);
209 Speaker2Chan
[0] = FRONT_LEFT
;
210 Speaker2Chan
[1] = FRONT_RIGHT
;
211 SpeakerAngle
[0] = -90.0f
* M_PI
/180.0f
;
212 SpeakerAngle
[1] = 90.0f
* M_PI
/180.0f
;
213 SetSpeakerArrangement("layout_STEREO", SpeakerAngle
, Speaker2Chan
, Device
->NumChan
);
217 Matrix
[FRONT_CENTER
][FRONT_LEFT
] = aluSqrt(0.5);
218 Matrix
[FRONT_CENTER
][FRONT_RIGHT
] = aluSqrt(0.5);
219 Matrix
[SIDE_LEFT
][FRONT_LEFT
] = aluSqrt(0.5);
220 Matrix
[SIDE_LEFT
][BACK_LEFT
] = aluSqrt(0.5);
221 Matrix
[SIDE_RIGHT
][FRONT_RIGHT
] = aluSqrt(0.5);
222 Matrix
[SIDE_RIGHT
][BACK_RIGHT
] = aluSqrt(0.5);
223 Matrix
[BACK_CENTER
][BACK_LEFT
] = aluSqrt(0.5);
224 Matrix
[BACK_CENTER
][BACK_RIGHT
] = aluSqrt(0.5);
226 Speaker2Chan
[0] = BACK_LEFT
;
227 Speaker2Chan
[1] = FRONT_LEFT
;
228 Speaker2Chan
[2] = FRONT_RIGHT
;
229 Speaker2Chan
[3] = BACK_RIGHT
;
230 SpeakerAngle
[0] = -135.0f
* M_PI
/180.0f
;
231 SpeakerAngle
[1] = -45.0f
* M_PI
/180.0f
;
232 SpeakerAngle
[2] = 45.0f
* M_PI
/180.0f
;
233 SpeakerAngle
[3] = 135.0f
* M_PI
/180.0f
;
234 SetSpeakerArrangement("layout_QUAD", SpeakerAngle
, Speaker2Chan
, Device
->NumChan
);
238 Matrix
[SIDE_LEFT
][FRONT_LEFT
] = aluSqrt(0.5);
239 Matrix
[SIDE_LEFT
][BACK_LEFT
] = aluSqrt(0.5);
240 Matrix
[SIDE_RIGHT
][FRONT_RIGHT
] = aluSqrt(0.5);
241 Matrix
[SIDE_RIGHT
][BACK_RIGHT
] = aluSqrt(0.5);
242 Matrix
[BACK_CENTER
][BACK_LEFT
] = aluSqrt(0.5);
243 Matrix
[BACK_CENTER
][BACK_RIGHT
] = aluSqrt(0.5);
245 Speaker2Chan
[0] = BACK_LEFT
;
246 Speaker2Chan
[1] = FRONT_LEFT
;
247 Speaker2Chan
[2] = FRONT_CENTER
;
248 Speaker2Chan
[3] = FRONT_RIGHT
;
249 Speaker2Chan
[4] = BACK_RIGHT
;
250 SpeakerAngle
[0] = -110.0f
* M_PI
/180.0f
;
251 SpeakerAngle
[1] = -30.0f
* M_PI
/180.0f
;
252 SpeakerAngle
[2] = 0.0f
* M_PI
/180.0f
;
253 SpeakerAngle
[3] = 30.0f
* M_PI
/180.0f
;
254 SpeakerAngle
[4] = 110.0f
* M_PI
/180.0f
;
255 SetSpeakerArrangement("layout_51CHN", SpeakerAngle
, Speaker2Chan
, Device
->NumChan
);
259 Matrix
[BACK_LEFT
][BACK_CENTER
] = aluSqrt(0.5);
260 Matrix
[BACK_LEFT
][SIDE_LEFT
] = aluSqrt(0.5);
261 Matrix
[BACK_RIGHT
][BACK_CENTER
] = aluSqrt(0.5);
262 Matrix
[BACK_RIGHT
][SIDE_RIGHT
] = aluSqrt(0.5);
264 Speaker2Chan
[0] = SIDE_LEFT
;
265 Speaker2Chan
[1] = FRONT_LEFT
;
266 Speaker2Chan
[2] = FRONT_CENTER
;
267 Speaker2Chan
[3] = FRONT_RIGHT
;
268 Speaker2Chan
[4] = SIDE_RIGHT
;
269 Speaker2Chan
[5] = BACK_CENTER
;
270 SpeakerAngle
[0] = -90.0f
* M_PI
/180.0f
;
271 SpeakerAngle
[1] = -30.0f
* M_PI
/180.0f
;
272 SpeakerAngle
[2] = 0.0f
* M_PI
/180.0f
;
273 SpeakerAngle
[3] = 30.0f
* M_PI
/180.0f
;
274 SpeakerAngle
[4] = 90.0f
* M_PI
/180.0f
;
275 SpeakerAngle
[5] = 180.0f
* M_PI
/180.0f
;
276 SetSpeakerArrangement("layout_61CHN", SpeakerAngle
, Speaker2Chan
, Device
->NumChan
);
280 Matrix
[BACK_CENTER
][BACK_LEFT
] = aluSqrt(0.5);
281 Matrix
[BACK_CENTER
][BACK_RIGHT
] = aluSqrt(0.5);
283 Speaker2Chan
[0] = BACK_LEFT
;
284 Speaker2Chan
[1] = SIDE_LEFT
;
285 Speaker2Chan
[2] = FRONT_LEFT
;
286 Speaker2Chan
[3] = FRONT_CENTER
;
287 Speaker2Chan
[4] = FRONT_RIGHT
;
288 Speaker2Chan
[5] = SIDE_RIGHT
;
289 Speaker2Chan
[6] = BACK_RIGHT
;
290 SpeakerAngle
[0] = -150.0f
* M_PI
/180.0f
;
291 SpeakerAngle
[1] = -90.0f
* M_PI
/180.0f
;
292 SpeakerAngle
[2] = -30.0f
* M_PI
/180.0f
;
293 SpeakerAngle
[3] = 0.0f
* M_PI
/180.0f
;
294 SpeakerAngle
[4] = 30.0f
* M_PI
/180.0f
;
295 SpeakerAngle
[5] = 90.0f
* M_PI
/180.0f
;
296 SpeakerAngle
[6] = 150.0f
* M_PI
/180.0f
;
297 SetSpeakerArrangement("layout_71CHN", SpeakerAngle
, Speaker2Chan
, Device
->NumChan
);
301 if(GetConfigValueBool(NULL
, "scalemix", 0))
303 ALfloat maxout
= 1.0f
;
304 for(s
= 0;s
< MAXCHANNELS
;s
++)
307 for(s2
= 0;s2
< MAXCHANNELS
;s2
++)
308 out
+= Device
->ChannelMatrix
[s2
][s
];
309 maxout
= __max(maxout
, out
);
312 maxout
= 1.0f
/maxout
;
313 for(s
= 0;s
< MAXCHANNELS
;s
++)
315 for(s2
= 0;s2
< MAXCHANNELS
;s2
++)
316 Device
->ChannelMatrix
[s2
][s
] *= maxout
;
320 PanningLUT
= Device
->PanningLUT
;
321 for(pos
= 0; pos
< LUT_NUM
; pos
++)
323 /* clear all values */
324 offset
= MAXCHANNELS
* pos
;
325 for(s
= 0; s
< MAXCHANNELS
; s
++)
326 PanningLUT
[offset
+s
] = 0.0f
;
328 if(Device
->NumChan
== 1)
330 PanningLUT
[offset
+ Speaker2Chan
[0]] = 1.0f
;
335 Theta
= aluLUTpos2Angle(pos
);
337 /* set panning values */
338 for(s
= 0; s
< Device
->NumChan
- 1; s
++)
340 if(Theta
>= SpeakerAngle
[s
] && Theta
< SpeakerAngle
[s
+1])
342 /* source between speaker s and speaker s+1 */
343 Alpha
= M_PI_2
* (Theta
-SpeakerAngle
[s
]) /
344 (SpeakerAngle
[s
+1]-SpeakerAngle
[s
]);
345 PanningLUT
[offset
+ Speaker2Chan
[s
]] = cos(Alpha
);
346 PanningLUT
[offset
+ Speaker2Chan
[s
+1]] = sin(Alpha
);
350 if(s
== Device
->NumChan
- 1)
352 /* source between last and first speaker */
353 if(Theta
< SpeakerAngle
[0])
354 Theta
+= 2.0f
* M_PI
;
355 Alpha
= M_PI_2
* (Theta
-SpeakerAngle
[s
]) /
356 (2.0f
* M_PI
+ SpeakerAngle
[0]-SpeakerAngle
[s
]);
357 PanningLUT
[offset
+ Speaker2Chan
[s
]] = cos(Alpha
);
358 PanningLUT
[offset
+ Speaker2Chan
[0]] = sin(Alpha
);