Pass the uncompressed sample count to LoadData and ConvertData for IMA4
[openal-soft/android.git] / Alc / panning.c
blob0d83ea305a819484b1ba584e948a564dcf89fba7
1 /**
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
21 #include "config.h"
23 #include <math.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <assert.h>
29 #include "alMain.h"
30 #include "AL/al.h"
31 #include "AL/alc.h"
32 #include "alu.h"
34 static void SetSpeakerArrangement(const char *name, ALfloat SpeakerAngle[MAXCHANNELS],
35 enum Channel Speaker2Chan[MAXCHANNELS], ALint chans)
37 char *confkey, *next;
38 char *layout_str;
39 char *sep, *end;
40 enum Channel val;
41 const char *str;
42 int i;
44 if(!ConfigValueStr(NULL, name, &str) && !ConfigValueStr(NULL, "layout", &str))
45 return;
47 layout_str = strdup(str);
48 next = confkey = layout_str;
49 while(next && *next)
51 confkey = next;
52 next = strchr(confkey, ',');
53 if(next)
55 *next = 0;
56 do {
57 next++;
58 } while(isspace(*next) || *next == ',');
61 sep = strchr(confkey, '=');
62 if(!sep || confkey == sep)
64 ERR("Malformed speaker key: %s\n", confkey);
65 continue;
68 end = sep - 1;
69 while(isspace(*end) && end != confkey)
70 end--;
71 *(++end) = 0;
73 if(strcmp(confkey, "fl") == 0 || strcmp(confkey, "front-left") == 0)
74 val = FRONT_LEFT;
75 else if(strcmp(confkey, "fr") == 0 || strcmp(confkey, "front-right") == 0)
76 val = FRONT_RIGHT;
77 else if(strcmp(confkey, "fc") == 0 || strcmp(confkey, "front-center") == 0)
78 val = FRONT_CENTER;
79 else if(strcmp(confkey, "bl") == 0 || strcmp(confkey, "back-left") == 0)
80 val = BACK_LEFT;
81 else if(strcmp(confkey, "br") == 0 || strcmp(confkey, "back-right") == 0)
82 val = BACK_RIGHT;
83 else if(strcmp(confkey, "bc") == 0 || strcmp(confkey, "back-center") == 0)
84 val = BACK_CENTER;
85 else if(strcmp(confkey, "sl") == 0 || strcmp(confkey, "side-left") == 0)
86 val = SIDE_LEFT;
87 else if(strcmp(confkey, "sr") == 0 || strcmp(confkey, "side-right") == 0)
88 val = SIDE_RIGHT;
89 else
91 ERR("Unknown speaker for %s: \"%s\"\n", name, confkey);
92 continue;
95 *(sep++) = 0;
96 while(isspace(*sep))
97 sep++;
99 for(i = 0;i < chans;i++)
101 if(Speaker2Chan[i] == val)
103 long angle = strtol(sep, NULL, 10);
104 if(angle >= -180 && angle <= 180)
105 SpeakerAngle[i] = angle * F_PI/180.0f;
106 else
107 ERR("Invalid angle for speaker \"%s\": %ld\n", confkey, angle);
108 break;
112 free(layout_str);
113 layout_str = NULL;
115 for(i = 0;i < chans;i++)
117 int min = i;
118 int i2;
120 for(i2 = i+1;i2 < chans;i2++)
122 if(SpeakerAngle[i2] < SpeakerAngle[min])
123 min = i2;
126 if(min != i)
128 ALfloat tmpf;
129 enum Channel tmpc;
131 tmpf = SpeakerAngle[i];
132 SpeakerAngle[i] = SpeakerAngle[min];
133 SpeakerAngle[min] = tmpf;
135 tmpc = Speaker2Chan[i];
136 Speaker2Chan[i] = Speaker2Chan[min];
137 Speaker2Chan[min] = tmpc;
142 static ALfloat aluLUTpos2Angle(ALint pos)
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;
153 ALint aluCart2LUTpos(ALfloat re, ALfloat im)
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);
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;
167 ALvoid aluInitPanning(ALCdevice *Device)
169 ALfloat SpeakerAngle[MAXCHANNELS];
170 enum Channel *Speaker2Chan;
171 ALfloat Alpha, Theta;
172 ALint pos;
173 ALuint s;
175 Speaker2Chan = Device->Speaker2Chan;
176 switch(Device->FmtChans)
178 case DevFmtMono:
179 Device->NumChan = 1;
180 Speaker2Chan[0] = FRONT_CENTER;
181 SpeakerAngle[0] = F_PI/180.0f * 0.0f;
182 break;
184 case DevFmtStereo:
185 Device->NumChan = 2;
186 Speaker2Chan[0] = FRONT_LEFT;
187 Speaker2Chan[1] = FRONT_RIGHT;
188 SpeakerAngle[0] = F_PI/180.0f * -90.0f;
189 SpeakerAngle[1] = F_PI/180.0f * 90.0f;
190 SetSpeakerArrangement("layout_STEREO", SpeakerAngle, Speaker2Chan, Device->NumChan);
191 break;
193 case DevFmtQuad:
194 Device->NumChan = 4;
195 Speaker2Chan[0] = BACK_LEFT;
196 Speaker2Chan[1] = FRONT_LEFT;
197 Speaker2Chan[2] = FRONT_RIGHT;
198 Speaker2Chan[3] = BACK_RIGHT;
199 SpeakerAngle[0] = F_PI/180.0f * -135.0f;
200 SpeakerAngle[1] = F_PI/180.0f * -45.0f;
201 SpeakerAngle[2] = F_PI/180.0f * 45.0f;
202 SpeakerAngle[3] = F_PI/180.0f * 135.0f;
203 SetSpeakerArrangement("layout_QUAD", SpeakerAngle, Speaker2Chan, Device->NumChan);
204 break;
206 case DevFmtX51:
207 Device->NumChan = 5;
208 Speaker2Chan[0] = BACK_LEFT;
209 Speaker2Chan[1] = FRONT_LEFT;
210 Speaker2Chan[2] = FRONT_CENTER;
211 Speaker2Chan[3] = FRONT_RIGHT;
212 Speaker2Chan[4] = BACK_RIGHT;
213 SpeakerAngle[0] = F_PI/180.0f * -110.0f;
214 SpeakerAngle[1] = F_PI/180.0f * -30.0f;
215 SpeakerAngle[2] = F_PI/180.0f * 0.0f;
216 SpeakerAngle[3] = F_PI/180.0f * 30.0f;
217 SpeakerAngle[4] = F_PI/180.0f * 110.0f;
218 SetSpeakerArrangement("layout_51CHN", SpeakerAngle, Speaker2Chan, Device->NumChan);
219 break;
221 case DevFmtX51Side:
222 Device->NumChan = 5;
223 Speaker2Chan[0] = SIDE_LEFT;
224 Speaker2Chan[1] = FRONT_LEFT;
225 Speaker2Chan[2] = FRONT_CENTER;
226 Speaker2Chan[3] = FRONT_RIGHT;
227 Speaker2Chan[4] = SIDE_RIGHT;
228 SpeakerAngle[0] = F_PI/180.0f * -90.0f;
229 SpeakerAngle[1] = F_PI/180.0f * -30.0f;
230 SpeakerAngle[2] = F_PI/180.0f * 0.0f;
231 SpeakerAngle[3] = F_PI/180.0f * 30.0f;
232 SpeakerAngle[4] = F_PI/180.0f * 90.0f;
233 SetSpeakerArrangement("layout_51SIDECHN", SpeakerAngle, Speaker2Chan, Device->NumChan);
234 break;
236 case DevFmtX61:
237 Device->NumChan = 6;
238 Speaker2Chan[0] = SIDE_LEFT;
239 Speaker2Chan[1] = FRONT_LEFT;
240 Speaker2Chan[2] = FRONT_CENTER;
241 Speaker2Chan[3] = FRONT_RIGHT;
242 Speaker2Chan[4] = SIDE_RIGHT;
243 Speaker2Chan[5] = BACK_CENTER;
244 SpeakerAngle[0] = F_PI/180.0f * -90.0f;
245 SpeakerAngle[1] = F_PI/180.0f * -30.0f;
246 SpeakerAngle[2] = F_PI/180.0f * 0.0f;
247 SpeakerAngle[3] = F_PI/180.0f * 30.0f;
248 SpeakerAngle[4] = F_PI/180.0f * 90.0f;
249 SpeakerAngle[5] = F_PI/180.0f * 180.0f;
250 SetSpeakerArrangement("layout_61CHN", SpeakerAngle, Speaker2Chan, Device->NumChan);
251 break;
253 case DevFmtX71:
254 Device->NumChan = 7;
255 Speaker2Chan[0] = BACK_LEFT;
256 Speaker2Chan[1] = SIDE_LEFT;
257 Speaker2Chan[2] = FRONT_LEFT;
258 Speaker2Chan[3] = FRONT_CENTER;
259 Speaker2Chan[4] = FRONT_RIGHT;
260 Speaker2Chan[5] = SIDE_RIGHT;
261 Speaker2Chan[6] = BACK_RIGHT;
262 SpeakerAngle[0] = F_PI/180.0f * -150.0f;
263 SpeakerAngle[1] = F_PI/180.0f * -90.0f;
264 SpeakerAngle[2] = F_PI/180.0f * -30.0f;
265 SpeakerAngle[3] = F_PI/180.0f * 0.0f;
266 SpeakerAngle[4] = F_PI/180.0f * 30.0f;
267 SpeakerAngle[5] = F_PI/180.0f * 90.0f;
268 SpeakerAngle[6] = F_PI/180.0f * 150.0f;
269 SetSpeakerArrangement("layout_71CHN", SpeakerAngle, Speaker2Chan, Device->NumChan);
270 break;
273 for(pos = 0; pos < LUT_NUM; pos++)
275 ALfloat *PanningLUT = Device->PanningLUT[pos];
277 /* clear all values */
278 for(s = 0; s < MAXCHANNELS; s++)
279 PanningLUT[s] = 0.0f;
281 if(Device->NumChan == 1)
283 PanningLUT[Speaker2Chan[0]] = 1.0f;
284 continue;
287 /* source angle */
288 Theta = aluLUTpos2Angle(pos);
290 /* set panning values */
291 for(s = 0; s < Device->NumChan - 1; s++)
293 if(Theta >= SpeakerAngle[s] && Theta < SpeakerAngle[s+1])
295 /* source between speaker s and speaker s+1 */
296 Alpha = (Theta-SpeakerAngle[s]) /
297 (SpeakerAngle[s+1]-SpeakerAngle[s]);
298 PanningLUT[Speaker2Chan[s]] = aluSqrt(1.0f-Alpha);
299 PanningLUT[Speaker2Chan[s+1]] = aluSqrt( Alpha);
300 break;
303 if(s == Device->NumChan - 1)
305 /* source between last and first speaker */
306 if(Theta < SpeakerAngle[0])
307 Theta += F_PI*2.0f;
308 Alpha = (Theta-SpeakerAngle[s]) /
309 (F_PI*2.0f + SpeakerAngle[0]-SpeakerAngle[s]);
310 PanningLUT[Speaker2Chan[s]] = aluSqrt(1.0f-Alpha);
311 PanningLUT[Speaker2Chan[0]] = aluSqrt( Alpha);