13996
|
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 };
|