Use logging macros in the sndio backend
[openal-soft/android.git] / Alc / hrtf.c
blob15b597633dd2fab9f485864089ce5371eb3e5b89
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 2011 by Chris Robinson
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 "AL/al.h"
24 #include "AL/alc.h"
25 #include "alMain.h"
26 #include "alSource.h"
28 #define HRIR_COUNT 828
30 static const ALuint sampleRate = 44100;
31 static const ALubyte evCount = 19;
32 static const ALushort evOffset[19] = { 0, 1, 13, 37, 73, 118, 174, 234, 306, 378, 450, 522, 594, 654, 710, 755, 791, 815, 827 };
33 static const ALubyte azCount[19] = { 1, 12, 24, 36, 45, 56, 60, 72, 72, 72, 72, 72, 60, 56, 45, 36, 24, 12, 1 };
35 static struct HRTF {
36 ALshort coeffs[HRIR_COUNT][HRIR_LENGTH];
37 ALubyte delays[HRIR_COUNT];
38 } Hrtf = {
39 #include "hrtf_tables.inc"
42 // Calculate the elevation indices given the polar elevation in radians.
43 // This will return two indices between 0 and (evCount - 1) and an
44 // interpolation factor between 0.0 and 1.0.
45 static void CalcEvIndices(ALfloat ev, ALuint *evidx, ALfloat *evmu)
47 ev = (M_PI/2.0f + ev) * (evCount-1) / M_PI;
48 evidx[0] = (ALuint)ev;
49 evidx[1] = __min(evidx[0] + 1, evCount - 1);
50 *evmu = ev - evidx[0];
53 // Calculate the azimuth indices given the polar azimuth in radians. This
54 // will return two indices between 0 and (azCount [ei] - 1) and an
55 // interpolation factor between 0.0 and 1.0.
56 static void CalcAzIndices(ALuint evidx, ALfloat az, ALuint *azidx, ALfloat *azmu)
58 az = (M_PI*2.0f + az) * azCount[evidx] / (M_PI*2.0f);
59 azidx[0] = (ALuint)az % azCount[evidx];
60 azidx[1] = (azidx[0] + 1) % azCount[evidx];
61 *azmu = az - (ALuint)az;
64 // Calculates static HRIR coefficients and delays for the given polar
65 // elevation and azimuth in radians. Linear interpolation is used to
66 // increase the apparent resolution of the HRIR dataset. The coefficients
67 // are also normalized and attenuated by the specified gain.
68 void GetLerpedHrtfCoeffs(ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays)
70 ALuint evidx[2], azidx[2];
71 ALfloat mu[3];
72 ALuint lidx[4], ridx[4];
73 ALuint i;
75 // Claculate elevation indices and interpolation factor.
76 CalcEvIndices(elevation, evidx, &mu[2]);
78 // Calculate azimuth indices and interpolation factor for the first
79 // elevation.
80 CalcAzIndices(evidx[0], azimuth, azidx, &mu[0]);
82 // Calculate the first set of linear HRIR indices for left and right
83 // channels.
84 lidx[0] = evOffset[evidx[0]] + azidx[0];
85 lidx[1] = evOffset[evidx[0]] + azidx[1];
86 ridx[0] = evOffset[evidx[0]] + ((azCount[evidx[0]]-azidx[0]) % azCount[evidx[0]]);
87 ridx[1] = evOffset[evidx[0]] + ((azCount[evidx[0]]-azidx[1]) % azCount[evidx[0]]);
89 // Calculate azimuth indices and interpolation factor for the second
90 // elevation.
91 CalcAzIndices (evidx[1], azimuth, azidx, &mu[1]);
93 // Calculate the second set of linear HRIR indices for left and right
94 // channels.
95 lidx[2] = evOffset[evidx[1]] + azidx[0];
96 lidx[3] = evOffset[evidx[1]] + azidx[1];
97 ridx[2] = evOffset[evidx[1]] + ((azCount[evidx[1]]-azidx[0]) % azCount[evidx[1]]);
98 ridx[3] = evOffset[evidx[1]] + ((azCount[evidx[1]]-azidx[1]) % azCount[evidx[1]]);
100 // Calculate the normalized and attenuated HRIR coefficients using linear
101 // interpolation when there is enough gain to warrant it. Zero the
102 // coefficients if gain is too low.
103 if(gain > 0.0001f)
105 ALdouble scale = gain * (1.0/32767.0);
106 for(i = 0;i < HRIR_LENGTH;i++)
108 coeffs[i][0] = lerp(lerp(Hrtf.coeffs[lidx[0]][i], Hrtf.coeffs[lidx[1]][i], mu[0]),
109 lerp(Hrtf.coeffs[lidx[2]][i], Hrtf.coeffs[lidx[3]][i], mu[1]),
110 mu[2]) * scale;
111 coeffs[i][1] = lerp(lerp(Hrtf.coeffs[ridx[0]][i], Hrtf.coeffs[ridx[1]][i], mu[0]),
112 lerp(Hrtf.coeffs[ridx[2]][i], Hrtf.coeffs[ridx[3]][i], mu[1]),
113 mu[2]) * scale;
116 else
118 for(i = 0;i < HRIR_LENGTH;i++)
120 coeffs[i][0] = 0.0f;
121 coeffs[i][1] = 0.0f;
125 // Calculate the HRIR delays using linear interpolation.
126 delays[0] = (ALuint)(lerp(lerp(Hrtf.delays[lidx[0]], Hrtf.delays[lidx[1]], mu[0]),
127 lerp(Hrtf.delays[lidx[2]], Hrtf.delays[lidx[3]], mu[1]),
128 mu[2]) + 0.5f);
129 delays[1] = (ALuint)(lerp(lerp(Hrtf.delays[ridx[0]], Hrtf.delays[ridx[1]], mu[0]),
130 lerp(Hrtf.delays[ridx[2]], Hrtf.delays[ridx[3]], mu[1]),
131 mu[2]) + 0.5f);
134 ALCboolean IsHrtfCompatible(ALCdevice *device)
136 if(device->FmtChans == DevFmtStereo && device->Frequency == sampleRate)
137 return ALC_TRUE;
138 return ALC_FALSE;
141 void InitHrtf(void)
143 const char *str;
144 FILE *f = NULL;
146 str = GetConfigValue(NULL, "hrtf_tables", "");
147 if(str[0] != '\0')
149 f = fopen(str, "rb");
150 if(f == NULL)
151 AL_PRINT("Could not open %s\n", str);
153 if(f != NULL)
155 const ALubyte maxDelay = SRC_HISTORY_LENGTH;
156 ALboolean failed = AL_FALSE;
157 struct HRTF newdata;
158 size_t i, j;
160 for(i = 0;i < HRIR_COUNT;i++)
162 for(j = 0;j < HRIR_LENGTH;j++)
164 ALshort val;
165 val = fgetc(f);
166 val |= fgetc(f)<<8;
167 newdata.coeffs[i][j] = val;
170 for(i = 0;i < HRIR_COUNT;i++)
172 ALubyte val;
173 val = fgetc(f);
174 newdata.delays[i] = val;
175 if(val > maxDelay)
177 AL_PRINT("Invalid delay at idx %zu: %u (max: %u), in %s\n", i, val, maxDelay, str);
178 failed = AL_TRUE;
181 if(feof(f))
183 AL_PRINT("Premature end of data while reading %s\n", str);
184 failed = AL_TRUE;
187 fclose(f);
188 f = NULL;
190 if(!failed)
191 Hrtf = newdata;