Make the sample rate part of the HRTF struct
[openal-soft/android.git] / Alc / hrtf.c
blobcc3831636eee44b536b4e83a292133d42c66dc01
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 ALubyte evCount = 19;
31 static const ALushort evOffset[19] = { 0, 1, 13, 37, 73, 118, 174, 234, 306, 378, 450, 522, 594, 654, 710, 755, 791, 815, 827 };
32 static const ALubyte azCount[19] = { 1, 12, 24, 36, 45, 56, 60, 72, 72, 72, 72, 72, 60, 56, 45, 36, 24, 12, 1 };
34 static struct Hrtf {
35 ALuint sampleRate;
36 ALshort coeffs[HRIR_COUNT][HRIR_LENGTH];
37 ALubyte delays[HRIR_COUNT];
38 } Hrtf = {
39 44100,
40 #include "hrtf_tables.inc"
43 // Calculate the elevation indices given the polar elevation in radians.
44 // This will return two indices between 0 and (evCount - 1) and an
45 // interpolation factor between 0.0 and 1.0.
46 static void CalcEvIndices(ALfloat ev, ALuint *evidx, ALfloat *evmu)
48 ev = (M_PI/2.0f + ev) * (evCount-1) / M_PI;
49 evidx[0] = (ALuint)ev;
50 evidx[1] = __min(evidx[0] + 1, evCount - 1);
51 *evmu = ev - evidx[0];
54 // Calculate the azimuth indices given the polar azimuth in radians. This
55 // will return two indices between 0 and (azCount [ei] - 1) and an
56 // interpolation factor between 0.0 and 1.0.
57 static void CalcAzIndices(ALuint evidx, ALfloat az, ALuint *azidx, ALfloat *azmu)
59 az = (M_PI*2.0f + az) * azCount[evidx] / (M_PI*2.0f);
60 azidx[0] = (ALuint)az % azCount[evidx];
61 azidx[1] = (azidx[0] + 1) % azCount[evidx];
62 *azmu = az - (ALuint)az;
65 // Calculates static HRIR coefficients and delays for the given polar
66 // elevation and azimuth in radians. Linear interpolation is used to
67 // increase the apparent resolution of the HRIR dataset. The coefficients
68 // are also normalized and attenuated by the specified gain.
69 void GetLerpedHrtfCoeffs(ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays)
71 ALuint evidx[2], azidx[2];
72 ALfloat mu[3];
73 ALuint lidx[4], ridx[4];
74 ALuint i;
76 // Claculate elevation indices and interpolation factor.
77 CalcEvIndices(elevation, evidx, &mu[2]);
79 // Calculate azimuth indices and interpolation factor for the first
80 // elevation.
81 CalcAzIndices(evidx[0], azimuth, azidx, &mu[0]);
83 // Calculate the first set of linear HRIR indices for left and right
84 // channels.
85 lidx[0] = evOffset[evidx[0]] + azidx[0];
86 lidx[1] = evOffset[evidx[0]] + azidx[1];
87 ridx[0] = evOffset[evidx[0]] + ((azCount[evidx[0]]-azidx[0]) % azCount[evidx[0]]);
88 ridx[1] = evOffset[evidx[0]] + ((azCount[evidx[0]]-azidx[1]) % azCount[evidx[0]]);
90 // Calculate azimuth indices and interpolation factor for the second
91 // elevation.
92 CalcAzIndices(evidx[1], azimuth, azidx, &mu[1]);
94 // Calculate the second set of linear HRIR indices for left and right
95 // channels.
96 lidx[2] = evOffset[evidx[1]] + azidx[0];
97 lidx[3] = evOffset[evidx[1]] + azidx[1];
98 ridx[2] = evOffset[evidx[1]] + ((azCount[evidx[1]]-azidx[0]) % azCount[evidx[1]]);
99 ridx[3] = evOffset[evidx[1]] + ((azCount[evidx[1]]-azidx[1]) % azCount[evidx[1]]);
101 // Calculate the normalized and attenuated HRIR coefficients using linear
102 // interpolation when there is enough gain to warrant it. Zero the
103 // coefficients if gain is too low.
104 if(gain > 0.0001f)
106 ALdouble scale = gain * (1.0/32767.0);
107 for(i = 0;i < HRIR_LENGTH;i++)
109 coeffs[i][0] = lerp(lerp(Hrtf.coeffs[lidx[0]][i], Hrtf.coeffs[lidx[1]][i], mu[0]),
110 lerp(Hrtf.coeffs[lidx[2]][i], Hrtf.coeffs[lidx[3]][i], mu[1]),
111 mu[2]) * scale;
112 coeffs[i][1] = lerp(lerp(Hrtf.coeffs[ridx[0]][i], Hrtf.coeffs[ridx[1]][i], mu[0]),
113 lerp(Hrtf.coeffs[ridx[2]][i], Hrtf.coeffs[ridx[3]][i], mu[1]),
114 mu[2]) * scale;
117 else
119 for(i = 0;i < HRIR_LENGTH;i++)
121 coeffs[i][0] = 0.0f;
122 coeffs[i][1] = 0.0f;
126 // Calculate the HRIR delays using linear interpolation.
127 delays[0] = (ALuint)(lerp(lerp(Hrtf.delays[lidx[0]], Hrtf.delays[lidx[1]], mu[0]),
128 lerp(Hrtf.delays[lidx[2]], Hrtf.delays[lidx[3]], mu[1]),
129 mu[2]) + 0.5f);
130 delays[1] = (ALuint)(lerp(lerp(Hrtf.delays[ridx[0]], Hrtf.delays[ridx[1]], mu[0]),
131 lerp(Hrtf.delays[ridx[2]], Hrtf.delays[ridx[3]], mu[1]),
132 mu[2]) + 0.5f);
135 ALCboolean IsHrtfCompatible(ALCdevice *device)
137 if(device->FmtChans == DevFmtStereo && device->Frequency == Hrtf.sampleRate)
138 return ALC_TRUE;
139 return ALC_FALSE;
142 void InitHrtf(void)
144 const char *str;
145 FILE *f = NULL;
147 str = GetConfigValue(NULL, "hrtf_tables", "");
148 if(str[0] != '\0')
150 f = fopen(str, "rb");
151 if(f == NULL)
152 ERR("Could not open %s\n", str);
154 if(f != NULL)
156 const ALubyte maxDelay = SRC_HISTORY_LENGTH;
157 ALboolean failed = AL_FALSE;
158 struct Hrtf newdata;
159 size_t i, j;
161 newdata.sampleRate = 44100;
162 for(i = 0;i < HRIR_COUNT;i++)
164 for(j = 0;j < HRIR_LENGTH;j++)
166 ALshort val;
167 val = fgetc(f);
168 val |= fgetc(f)<<8;
169 newdata.coeffs[i][j] = val;
172 for(i = 0;i < HRIR_COUNT;i++)
174 ALubyte val;
175 val = fgetc(f);
176 newdata.delays[i] = val;
177 if(val > maxDelay)
179 ERR("Invalid delay at idx %zu: %u (max: %u), in %s\n", i, val, maxDelay, str);
180 failed = AL_TRUE;
183 if(feof(f))
185 ERR("Premature end of data while reading %s\n", str);
186 failed = AL_TRUE;
189 fclose(f);
190 f = NULL;
192 if(!failed)
193 Hrtf = newdata;