comparison libaf/af_hrtf.c @ 13996:be8f4abbe960

head related transfer function
author henry
date Sat, 20 Nov 2004 14:41:51 +0000
parents
children 3c56b18bbb0c
comparison
equal deleted inserted replaced
13995:cbadd7b190b2 13996:be8f4abbe960
1 /* Experimental audio filter that mixes 5.1 and 5.1 with matrix
2 encoded rear channels into headphone signal using FIR filtering
3 with HRTF.
4 */
5 //#include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include <inttypes.h>
10
11 #include <math.h>
12
13 #include "af.h"
14 #include "dsp.h"
15
16 /* HRTF filter coefficients and adjustable parameters */
17 #include "af_hrtf.h"
18
19 typedef struct af_hrtf_s {
20 /* Lengths */
21 int dlbuflen, hrflen, basslen;
22 /* L, C, R, Ls, Rs channels */
23 float *lf, *rf, *lr, *rr, *cf, *cr;
24 float *cf_ir, *af_ir, *of_ir, *ar_ir, *or_ir, *cr_ir;
25 int cf_o, af_o, of_o, ar_o, or_o, cr_o;
26 /* Bass */
27 float *ba_l, *ba_r;
28 float *ba_ir;
29 /* Whether to matrix decode the rear center channel */
30 int matrix_mode;
31 /* Full wave rectified amplitude used to steer the active matrix
32 decoding of center rear channel */
33 float lr_fwr, rr_fwr;
34 /* Cyclic position on the ring buffer */
35 int cyc_pos;
36 } af_hrtf_t;
37
38 /* Convolution on a ring buffer
39 * nx: length of the ring buffer
40 * nk: length of the convolution kernel
41 * sx: ring buffer
42 * sk: convolution kernel
43 * offset: offset on the ring buffer, can be
44 */
45 static float conv(const int nx, const int nk, float *sx, float *sk,
46 const int offset)
47 {
48 /* k = reminder of offset / nx */
49 int k = offset >= 0 ? offset % nx : nx + (offset % nx);
50
51 if(nk + k <= nx)
52 return fir(nk, sx + k, sk);
53 else
54 return fir(nk + k - nx, sx, sk + nx - k) +
55 fir(nx - k, sx + k, sk);
56 }
57
58 /* Detect when the impulse response starts (significantly) */
59 int pulse_detect(float *sx)
60 {
61 /* nmax must be the reference impulse response length (128) minus
62 s->hrflen */
63 const int nmax = 128 - HRTFFILTLEN;
64 const float thresh = IRTHRESH;
65 int i;
66
67 for(i = 0; i < nmax; i++)
68 if(fabs(sx[i]) > thresh)
69 return i;
70 return 0;
71 }
72
73 inline void update_ch(af_hrtf_t *s, short *in, const int k)
74 {
75 /* Update the full wave rectified total amplutude */
76 s->lr_fwr += abs(in[2]) - fabs(s->lr[k]);
77 s->rr_fwr += abs(in[3]) - fabs(s->rr[k]);
78
79 s->lf[k] = in[0];
80 s->cf[k] = in[4];
81 s->rf[k] = in[1];
82 s->lr[k] = in[2];
83 s->rr[k] = in[3];
84
85 s->ba_l[k] = in[0] + in[4] + in[2];
86 s->ba_r[k] = in[4] + in[1] + in[3];
87 }
88
89 inline void matrix_decode_cr(af_hrtf_t *s, short *in, const int k)
90 {
91 /* Active matrix decoding of the center rear channel, 1 in the
92 denominator is to prevent singularity */
93 float lr_agc = in[2] * (s->lr_fwr + s->rr_fwr) /
94 (1 + s->lr_fwr + s->lr_fwr);
95 float rr_agc = in[3] * (s->lr_fwr + s->rr_fwr) /
96 (1 + s->rr_fwr + s->rr_fwr);
97
98 s->cr[k] = (lr_agc + rr_agc) * M_SQRT1_2;
99 }
100
101 /* Initialization and runtime control */
102 static int control(struct af_instance_s *af, int cmd, void* arg)
103 {
104 af_hrtf_t *s = af->setup;
105 char mode;
106
107 switch(cmd) {
108 case AF_CONTROL_REINIT:
109 af->data->rate = ((af_data_t*)arg)->rate;
110 if(af->data->rate != 48000) {
111 af_msg(AF_MSG_ERROR,
112 "[hrtf] ERROR: Sampling rate is not 48000 Hz (%d)!\n",
113 af->data->rate);
114 return AF_ERROR;
115 }
116 af->data->nch = ((af_data_t*)arg)->nch;
117 if(af->data->nch < 5) {
118 af_msg(AF_MSG_ERROR,
119 "[hrtf] ERROR: Insufficient channels (%d < 5).\n",
120 af->data->nch);
121 return AF_ERROR;
122 }
123 af->data->format = AF_FORMAT_SI | AF_FORMAT_NE;
124 af->data->bps = 2;
125 return AF_OK;
126 case AF_CONTROL_COMMAND_LINE:
127 sscanf((char*)arg, "%c", &mode);
128 switch(mode) {
129 case 'm':
130 s->matrix_mode = 1;
131 break;
132 case '0':
133 s->matrix_mode = 0;
134 break;
135 default:
136 af_msg(AF_MSG_ERROR,
137 "[hrtf] Mode is neither 'm', nor '0' (%c).\n",
138 mode);
139 return AF_ERROR;
140 }
141 return AF_OK;
142 }
143
144 af_msg(AF_MSG_INFO,
145 "[hrtf] Using HRTF to mix %s discrete surround into "
146 "L, R channels\n", s->matrix_mode ? "5" : "5+1");
147 if(s->matrix_mode)
148 af_msg(AF_MSG_INFO,
149 "[hrtf] Using active matrix to decode rear center "
150 "channel\n");
151
152 return AF_UNKNOWN;
153 }
154
155 /* Deallocate memory */
156 static void uninit(struct af_instance_s *af)
157 {
158 if(af->setup) {
159 af_hrtf_t *s = af->setup;
160
161 if(s->lf)
162 free(s->lf);
163 if(s->rf)
164 free(s->rf);
165 if(s->lr)
166 free(s->lr);
167 if(s->rr)
168 free(s->rr);
169 if(s->cf)
170 free(s->cf);
171 if(s->cr)
172 free(s->cr);
173 if(s->ba_l)
174 free(s->ba_l);
175 if(s->ba_r)
176 free(s->ba_r);
177 if(s->ba_ir)
178 free(s->ba_ir);
179 free(af->setup);
180 }
181 if(af->data)
182 free(af->data);
183 }
184
185 /* Filter data through filter
186
187 Two "tricks" are used to compensate the "color" of the KEMAR data:
188
189 1. The KEMAR data is refiltered to ensure that the front L, R channels
190 on the same side of the ear are equalized (especially in the high
191 frequencies).
192
193 2. A bass compensation is introduced to ensure that 0-200 Hz are not
194 damped (without any real 3D acoustical image, however).
195 */
196 static af_data_t* play(struct af_instance_s *af, af_data_t *data)
197 {
198 af_hrtf_t *s = af->setup;
199 short *in = data->audio; // Input audio data
200 short *out = NULL; // Output audio data
201 short *end = in + data->len / sizeof(short); // Loop end
202 float common, left, right, diff, left_b, right_b;
203 const int dblen = s->dlbuflen, hlen = s->hrflen, blen = s->basslen;
204
205 if(AF_OK != RESIZE_LOCAL_BUFFER(af, data))
206 return NULL;
207
208 out = af->data->audio;
209
210 /* MPlayer's 5 channel layout (notation for the variable):
211 *
212 * 0: L (LF), 1: R (RF), 2: Ls (LR), 3: Rs (RR), 4: C (CF), matrix
213 * encoded: Cs (CR)
214 *
215 * or: L = left, C = center, R = right, F = front, R = rear
216 *
217 * Filter notation:
218 *
219 * CF
220 * OF AF
221 * Ear->
222 * OR AR
223 * CR
224 *
225 * or: C = center, A = same side, O = opposite, F = front, R = rear
226 */
227
228 while(in < end) {
229 const int k = s->cyc_pos;
230
231 update_ch(s, in, k);
232
233 /* Simulate a 7.5 ms -20 dB echo of the center channel in the
234 front channels (like reflection from a room wall) - a kind of
235 psycho-acoustically "cheating" to focus the center front
236 channel, which is normally hard to be perceived as front */
237 s->lf[k] += CFECHOAMPL * s->cf[(k + CFECHODELAY) % s->dlbuflen];
238 s->rf[k] += CFECHOAMPL * s->cf[(k + CFECHODELAY) % s->dlbuflen];
239
240 /* Mixer filter matrix */
241 common = conv(dblen, hlen, s->cf, s->cf_ir, k + s->cf_o);
242 if(s->matrix_mode) {
243 /* In matrix decoding mode, the rear channel gain must be
244 renormalized, as there is an additional channel. */
245 matrix_decode_cr(s, in, k);
246 common +=
247 conv(dblen, hlen, s->cr, s->cr_ir, k + s->cr_o) *
248 M1_76DB;
249 left =
250 ( conv(dblen, hlen, s->lf, s->af_ir, k + s->af_o) +
251 conv(dblen, hlen, s->rf, s->of_ir, k + s->of_o) +
252 (conv(dblen, hlen, s->lr, s->ar_ir, k + s->ar_o) +
253 conv(dblen, hlen, s->rr, s->or_ir, k + s->or_o)) *
254 M1_76DB + common);
255 right =
256 ( conv(dblen, hlen, s->rf, s->af_ir, k + s->af_o) +
257 conv(dblen, hlen, s->lf, s->of_ir, k + s->of_o) +
258 (conv(dblen, hlen, s->rr, s->ar_ir, k + s->ar_o) +
259 conv(dblen, hlen, s->lr, s->or_ir, k + s->or_o)) *
260 M1_76DB + common);
261 }
262 else {
263 left =
264 ( conv(dblen, hlen, s->lf, s->af_ir, k + s->af_o) +
265 conv(dblen, hlen, s->rf, s->of_ir, k + s->of_o) +
266 conv(dblen, hlen, s->lr, s->ar_ir, k + s->ar_o) +
267 conv(dblen, hlen, s->rr, s->or_ir, k + s->or_o) +
268 common);
269 right =
270 ( conv(dblen, hlen, s->rf, s->af_ir, k + s->af_o) +
271 conv(dblen, hlen, s->lf, s->of_ir, k + s->of_o) +
272 conv(dblen, hlen, s->rr, s->ar_ir, k + s->ar_o) +
273 conv(dblen, hlen, s->lr, s->or_ir, k + s->or_o) +
274 common);
275 }
276
277 /* Bass compensation for the lower frequency cut of the HRTF. A
278 cross talk of the left and right channel is introduced to
279 match the directional characteristics of higher frequencies.
280 The bass will not have any real 3D perception, but that is
281 OK. */
282 left_b = conv(dblen, blen, s->ba_l, s->ba_ir, k);
283 right_b = conv(dblen, blen, s->ba_r, s->ba_ir, k);
284 left += (1 - BASSCROSS) * left_b + BASSCROSS * right_b;
285 right += (1 - BASSCROSS) * right_b + BASSCROSS * left_b;
286 /* Also mix the LFE channel (if available) */
287 if(af->data->nch >= 6) {
288 left += out[5] * M3_01DB;
289 right += out[5] * M3_01DB;
290 }
291
292 /* Amplitude renormalization. */
293 left *= AMPLNORM;
294 right *= AMPLNORM;
295
296 /* "Cheating": linear stereo expansion to amplify the 3D
297 perception. Note: Too much will destroy the acoustic space
298 and may even result in headaches. */
299 diff = STEXPAND2 * (left - right);
300 out[0] = (int16_t)(left + diff);
301 out[1] = (int16_t)(right - diff);
302
303 /* The remaining channels are not needed any more */
304 out[2] = out[3] = out[4] = 0;
305 if(af->data->nch >= 6)
306 out[5] = 0;
307
308 /* Next sample... */
309 in = &in[data->nch];
310 out = &out[af->data->nch];
311 (s->cyc_pos)--;
312 if(s->cyc_pos < 0)
313 s->cyc_pos += dblen;
314 }
315
316 /* Set output data */
317 data->audio = af->data->audio;
318 data->len = (data->len * af->mul.n) / af->mul.d;
319 data->nch = af->data->nch;
320
321 return data;
322 }
323
324 static int allocate(af_hrtf_t *s)
325 {
326 if ((s->lf = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1;
327 if ((s->rf = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1;
328 if ((s->lr = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1;
329 if ((s->rr = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1;
330 if ((s->cf = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1;
331 if ((s->cr = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1;
332 if ((s->ba_l = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1;
333 if ((s->ba_r = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1;
334 return 0;
335 }
336
337 /* Allocate memory and set function pointers */
338 static int open(af_instance_t* af)
339 {
340 int i;
341 af_hrtf_t *s;
342 float fc;
343
344 af_msg(AF_MSG_INFO,
345 "[hrtf] Head related impulse response (HRIR) derived from KEMAR measurement\n"
346 "[hrtf] data by Bill Gardner <billg@media.mit.edu>\n"
347 "[hrtf] and Keith Martin <kdm@media.mit.edu>.\n"
348 "[hrtf] This data is Copyright 1994 by the MIT Media Laboratory. It is\n"
349 "[hrtf] provided free with no restrictions on use, provided the authors are\n"
350 "[hrtf] cited when the data is used in any research or commercial application.\n"
351 "[hrtf] URL: http://sound.media.mit.edu/KEMAR.html\n");
352
353 af->control = control;
354 af->uninit = uninit;
355 af->play = play;
356 af->mul.n = 1;
357 af->mul.d = 1;
358 af->data = calloc(1, sizeof(af_data_t));
359 af->setup = calloc(1, sizeof(af_hrtf_t));
360 if((af->data == NULL) || (af->setup == NULL))
361 return AF_ERROR;
362
363 s = af->setup;
364
365 s->dlbuflen = DELAYBUFLEN;
366 s->hrflen = HRTFFILTLEN;
367 s->basslen = BASSFILTLEN;
368
369 s->cyc_pos = s->dlbuflen - 1;
370 s->matrix_mode = 1;
371
372 if (allocate(s) != 0) {
373 af_msg(AF_MSG_ERROR, "[hrtf] Memory allocation error.\n");
374 return AF_ERROR;
375 }
376
377 for(i = 0; i < s->dlbuflen; i++)
378 s->lf[i] = s->rf[i] = s->lr[i] = s->rr[i] = s->cf[i] =
379 s->cr[i] = 0;
380
381 s->lr_fwr =
382 s->rr_fwr = 0;
383
384 s->cf_ir = cf_filt + (s->cf_o = pulse_detect(cf_filt));
385 s->af_ir = af_filt + (s->af_o = pulse_detect(af_filt));
386 s->of_ir = of_filt + (s->of_o = pulse_detect(of_filt));
387 s->ar_ir = ar_filt + (s->ar_o = pulse_detect(ar_filt));
388 s->or_ir = or_filt + (s->or_o = pulse_detect(or_filt));
389 s->cr_ir = cr_filt + (s->cr_o = pulse_detect(cr_filt));
390
391 if((s->ba_ir = malloc(s->basslen * sizeof(float))) == NULL) {
392 af_msg(AF_MSG_ERROR, "[hrtf] Memory allocation error.\n");
393 return AF_ERROR;
394 }
395 fc = 2.0 * BASSFILTFREQ / (float)af->data->rate;
396 if(design_fir(s->basslen, s->ba_ir, &fc, LP | KAISER, 4 * M_PI) ==
397 -1) {
398 af_msg(AF_MSG_ERROR, "[hrtf] Unable to design low-pass "
399 "filter.\n");
400 return AF_ERROR;
401 }
402 for(i = 0; i < s->basslen; i++)
403 s->ba_ir[i] *= BASSGAIN;
404
405 return AF_OK;
406 }
407
408 /* Description of this filter */
409 af_info_t af_info_hrtf = {
410 "HRTF Headphone",
411 "hrtf",
412 "ylai",
413 "",
414 AF_FLAGS_REENTRANT,
415 open
416 };