Signed-off-by: Paul B Mahol <one...@gmail.com> --- doc/filters.texi | 24 ++ libavfilter/Makefile | 1 + libavfilter/af_hrtf.c | 554 +++++++++++++++++++++++++++++++++++++++++++++++ libavfilter/af_hrtf.h | 550 ++++++++++++++++++++++++++++++++++++++++++++++ libavfilter/allfilters.c | 1 + 5 files changed, 1130 insertions(+) create mode 100644 libavfilter/af_hrtf.c create mode 100644 libavfilter/af_hrtf.h
diff --git a/doc/filters.texi b/doc/filters.texi index c6fef0c..0f9aa9a 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1527,6 +1527,30 @@ Applies only to double-pole filter. The default is 0.707q and gives a Butterworth response. @end table +@section hrtf + +Head-related transfer function: Converts multichannel audio to 2 channel output +for headphones, preserving the spatiality of the sound. + +It accepts the following parameters: + +@table @option +@item mode +Set operating mode. + +It accepts the following values: +@table @option +@end table +@item m +Set matrix decoding of the rear channel + +@item s +Set 2-channel matrix decoding + +@item 0 +No matrix decoding. +@end table + @section join Join multiple input streams into one multi-channel stream. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 75d19dc..76381be 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -70,6 +70,7 @@ OBJS-$(CONFIG_EBUR128_FILTER) += f_ebur128.o OBJS-$(CONFIG_EQUALIZER_FILTER) += af_biquads.o OBJS-$(CONFIG_FLANGER_FILTER) += af_flanger.o generate_wave_table.o OBJS-$(CONFIG_HIGHPASS_FILTER) += af_biquads.o +OBJS-$(CONFIG_HRTF_FILTER) += af_hrtf.o OBJS-$(CONFIG_JOIN_FILTER) += af_join.o OBJS-$(CONFIG_LADSPA_FILTER) += af_ladspa.o OBJS-$(CONFIG_LOWPASS_FILTER) += af_biquads.o diff --git a/libavfilter/af_hrtf.c b/libavfilter/af_hrtf.c new file mode 100644 index 0000000..4243475 --- /dev/null +++ b/libavfilter/af_hrtf.c @@ -0,0 +1,554 @@ +/* + * Copyright (c) 2004 Yue Shi Lai + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/** + * @file + * Experimental audio filter that mixes 5.1 and 5.0 with matrix encoded + * rear channels into headphone signal using FIR filtering with HRTF. + */ + +#include "libavutil/channel_layout.h" +#include "libavutil/opt.h" +#include "libavutil/samplefmt.h" +#include "libavutil/avassert.h" +#include "avfilter.h" +#include "audio.h" +#include "internal.h" + +/* HRTF filter coefficients and adjustable parameters */ +#include "af_hrtf.h" + +typedef struct HRTFContext { + const AVClass *class; + int mode; + int dlbuflen, hrflen, basslen; + + float lf[DELAYBUFLEN], rf[DELAYBUFLEN], + lr[DELAYBUFLEN], rr[DELAYBUFLEN], + cf[DELAYBUFLEN], cr[DELAYBUFLEN]; + + const float *cf_ir, *cr_ir, + *af_ir, *ar_ir, + *of_ir, *or_ir; + + int cf_o, cr_o, + af_o, ar_o, + of_o, or_o; + + float ba_l[DELAYBUFLEN], ba_r[DELAYBUFLEN]; + + int matrix_mode; // Whether to matrix decode the rear center channel + int decode_mode; // How to decode the input + + float l_fwr, r_fwr, // Full wave rectified (FWR) amplitudes and gain used + lpr_fwr, lmr_fwr; // to steer the active matrix decoding of front channels + // (variable names lpr/lmr means Lt + Rt, Lt - Rt) + + float adapt_l_gain, adapt_r_gain, + adapt_lpr_gain, adapt_lmr_gain; + + float fwrbuf_l[DELAYBUFLEN], // Matrix input decoding require special FWR + fwrbuf_r[DELAYBUFLEN], // buffer, since the decoding is done in place + fwrbuf_lr[DELAYBUFLEN], + fwrbuf_rr[DELAYBUFLEN]; + + float lr_fwr, rr_fwr, // Full wave rectified amplitude and gain used to + lrprr_fwr, lrmrr_fwr; // steer the active matrix decoding of center + // rear channel + + float adapt_lr_gain, adapt_rr_gain, + adapt_lrprr_gain, adapt_lrmrr_gain; + + int cyc_pos; /* Cyclic position on the ring buffer */ +} HRTFContext; + +#define OFFSET(x) offsetof(HRTFContext, x) +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption hrtf_options[] = { + { "mode", "set the matrix mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, A, "mode" }, + { "m", "set matrix decoding of the rear channel", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, A, "mode" }, + { "s", "2-channel matrix decoding", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, A, "mode" }, + { "0", "no matrix decoding", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, A, "mode" }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(hrtf); + +/* + * Detect when the impulse response starts (significantly) + */ +static int pulse_detect(const float *sx) +{ + /* nmax must be the reference impulse response length (128) minus + s->hrflen */ + const int nmax = 128 - HRTFFILTLEN; + const float thresh = IRTHRESH; + int i; + + for (i = 0; i < nmax; i++) + if (fabs(sx[i]) > thresh) + return i; + return 0; +} + +static av_cold int init(AVFilterContext *ctx) +{ + HRTFContext *s = ctx->priv; + + s->dlbuflen = DELAYBUFLEN; + s->hrflen = HRTFFILTLEN; + s->basslen = BASSFILTLEN; + + s->cyc_pos = s->dlbuflen - 1; + + s->matrix_mode = 0; + s->decode_mode = HRTF_MIX_51; + + switch (s->mode) { + case 0: /* Use matrix rear decoding. */ + s->matrix_mode = 1; + break; + case 1: /* Input needs matrix decoding. */ + s->decode_mode = HRTF_MIX_MATRIX2CH; + break; + case 2: + s->matrix_mode = 0; + break; + } + + s->cf_ir = cf_filt + (s->cf_o = pulse_detect(cf_filt)); + s->af_ir = af_filt + (s->af_o = pulse_detect(af_filt)); + s->of_ir = of_filt + (s->of_o = pulse_detect(of_filt)); + s->ar_ir = ar_filt + (s->ar_o = pulse_detect(ar_filt)); + s->or_ir = or_filt + (s->or_o = pulse_detect(or_filt)); + s->cr_ir = cr_filt + (s->cr_o = pulse_detect(cr_filt)); + + return 0; +} + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats = NULL; + AVFilterChannelLayouts *layouts = NULL; + static int sample_rates[] = { 48000, -1 }; + + ff_add_format(&formats, AV_SAMPLE_FMT_S16); + ff_set_common_formats(ctx, formats); + ff_set_common_samplerates(ctx, ff_make_format_list(sample_rates)); + + ff_add_channel_layout(&layouts, AV_CH_LAYOUT_STEREO); + ff_add_channel_layout(&layouts, AV_CH_LAYOUT_5POINT1); + ff_channel_layouts_ref(layouts, &ctx->inputs[0]->out_channel_layouts); + + layouts = NULL; + ff_add_channel_layout(&layouts, AV_CH_LAYOUT_STEREO); + ff_channel_layouts_ref(layouts, &ctx->outputs[0]->in_channel_layouts); + + return 0; +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + HRTFContext *s = ctx->priv; + + if (inlink->channel_layout == AV_CH_LAYOUT_STEREO) { + s->matrix_mode = 0; + if (s->decode_mode != HRTF_MIX_MATRIX2CH) + s->decode_mode = HRTF_MIX_STEREO; + } + + return 0; +} + +/* + * Fuzzy matrix coefficient transfer function to "lock" the matrix on + * a effectively passive mode if the gain is approximately 1. + */ +static inline float passive_lock(float x) +{ + const float x1 = x - 1; + const float ax1s = fabs(x - 1) * (1.0 / MATAGCLOCK); + + return x1 - x1 / (1 + ax1s * ax1s) + 1; +} + +/* + * Unified active matrix decoder for 2 channel matrix encoded surround + * sources. + */ +static void matrix_decode(int16_t *in, const int k, const int il, + const int ir, const int decode_rear, + const int dlbuflen, + float l_fwr, float r_fwr, + float lpr_fwr, float lmr_fwr, + float *adapt_l_gain, float *adapt_r_gain, + float *adapt_lpr_gain, float *adapt_lmr_gain, + float *lf, float *rf, float *lr, + float *rr, float *cf) +{ + const int kr = (k + MATREARDELAY) % dlbuflen; + float l_gain = (l_fwr + r_fwr) / (1 + l_fwr + l_fwr); + float r_gain = (l_fwr + r_fwr) / (1 + r_fwr + r_fwr); + /* The 2nd axis has strong gain fluctuations, and therefore require + limits. The factor corresponds to the 1 / amplification of (Lt + - Rt) when (Lt, Rt) is strongly correlated. (e.g. during + dialogues). It should be bigger than -12 dB to prevent + distortion. */ + float lmr_lim_fwr = lmr_fwr > M9_03DB * lpr_fwr ? lmr_fwr : M9_03DB * lpr_fwr; + float lpr_gain = (lpr_fwr + lmr_lim_fwr) / (1 + lpr_fwr + lpr_fwr); + float lmr_gain = (lpr_fwr + lmr_lim_fwr) / (1 + lmr_lim_fwr + lmr_lim_fwr); + float lmr_unlim_gain = (lpr_fwr + lmr_fwr) / (1 + lmr_fwr + lmr_fwr); + float lpr, lmr; + float l_agc, r_agc, lpr_agc, lmr_agc; + float f, d_gain, c_gain, c_agc_cfk; + + /*** AXIS NO. 1: (Lt, Rt) -> (C, Ls, Rs) ***/ + /* AGC adaption */ + d_gain = (fabs(l_gain - *adapt_l_gain) + + fabs(r_gain - *adapt_r_gain)) * 0.5; + f = d_gain * (1.0 / MATAGCTRIG); + f = MATAGCDECAY - MATAGCDECAY / (1 + f * f); + *adapt_l_gain = (1 - f) * *adapt_l_gain + f * l_gain; + *adapt_r_gain = (1 - f) * *adapt_r_gain + f * r_gain; + + /* Matrix */ + l_agc = in[il] * passive_lock(*adapt_l_gain); + r_agc = in[ir] * passive_lock(*adapt_r_gain); + cf[k] = (l_agc + r_agc) * M_SQRT1_2; + + if (decode_rear) { + lr[kr] = rr[kr] = (l_agc - r_agc) * M_SQRT1_2; + /* + * Stereo rear channel is steered with the same AGC steering as + * the decoding matrix. Note this requires a fast updating AGC + * at the order of 20 ms (which is the case here). + */ + lr[kr] *= (l_fwr + l_fwr) / (1 + l_fwr + r_fwr); + rr[kr] *= (r_fwr + r_fwr) / (1 + l_fwr + r_fwr); + } + + /*** AXIS NO. 2: (Lt + Rt, Lt - Rt) -> (L, R) ***/ + lpr = (in[il] + in[ir]) * M_SQRT1_2; + lmr = (in[il] - in[ir]) * M_SQRT1_2; + + /* AGC adaption */ + d_gain = fabs(lmr_unlim_gain - *adapt_lmr_gain); + f = d_gain * (1.0 / MATAGCTRIG); + f = MATAGCDECAY - MATAGCDECAY / (1 + f * f); + + *adapt_lpr_gain = (1 - f) * *adapt_lpr_gain + f * lpr_gain; + *adapt_lmr_gain = (1 - f) * *adapt_lmr_gain + f * lmr_gain; + + /* Matrix */ + lpr_agc = lpr * passive_lock(*adapt_lpr_gain); + lmr_agc = lmr * passive_lock(*adapt_lmr_gain); + lf[k] = (lpr_agc + lmr_agc) * M_SQRT1_2; + rf[k] = (lpr_agc - lmr_agc) * M_SQRT1_2; + + /*** CENTER FRONT CANCELLATION ***/ + /* A heuristic approach exploits that Lt + Rt gain contains the + information about Lt, Rt correlation. This effectively reshapes + the front and rear "cones" to concentrate Lt + Rt to C and + introduce Lt - Rt in L, R. */ + /* 0.67677 is the empirical lower bound for lpr_gain. */ + c_gain = 8 * (*adapt_lpr_gain - 0.67677); + c_gain = c_gain > 0 ? c_gain : 0; + + /* c_gain should not be too high, not even reaching full + cancellation (~ 0.50 - 0.55 at current AGC implementation), or + the center will sound too narrow. */ + c_gain = MATCOMPGAIN / (1 + c_gain * c_gain); + c_agc_cfk = c_gain * cf[k]; + + lf[k] -= c_agc_cfk; + rf[k] -= c_agc_cfk; + cf[k] += c_agc_cfk + c_agc_cfk; +} + +static void update_channel(HRTFContext *s, int16_t *in, const int k) +{ + const int fwr_pos = (k + FWRDURATION) % s->dlbuflen; + + /* Update the full wave rectified total amplitude */ + /* Input matrix decoder */ + if (s->decode_mode == HRTF_MIX_MATRIX2CH) { + s->l_fwr += abs(in[0]) - fabs(s->fwrbuf_l[fwr_pos]); + s->r_fwr += abs(in[1]) - fabs(s->fwrbuf_r[fwr_pos]); + s->lpr_fwr += abs(in[0] + in[1]) - + fabs(s->fwrbuf_l[fwr_pos] + s->fwrbuf_r[fwr_pos]); + s->lmr_fwr += abs(in[0] - in[1]) - + fabs(s->fwrbuf_l[fwr_pos] - s->fwrbuf_r[fwr_pos]); + } + + /* Rear matrix decoder */ + if (s->matrix_mode) { + s->lr_fwr += abs(in[4]) - fabs(s->fwrbuf_lr[fwr_pos]); + s->rr_fwr += abs(in[5]) - fabs(s->fwrbuf_rr[fwr_pos]); + s->lrprr_fwr += abs(in[4] + in[5]) - fabs(s->fwrbuf_lr[fwr_pos] + + s->fwrbuf_rr[fwr_pos]); + s->lrmrr_fwr += abs(in[4] - in[5]) - fabs(s->fwrbuf_lr[fwr_pos] - + s->fwrbuf_rr[fwr_pos]); + } + + switch (s->decode_mode) { + case HRTF_MIX_51: + /* 5/5+1 channel sources */ + s->lf[k] = in[0]; + s->cf[k] = in[2]; + s->rf[k] = in[1]; + s->fwrbuf_lr[k] = s->lr[k] = in[4]; + s->fwrbuf_rr[k] = s->rr[k] = in[5]; + break; + case HRTF_MIX_MATRIX2CH: + /* Matrix encoded 2 channel sources */ + s->fwrbuf_l[k] = in[0]; + s->fwrbuf_r[k] = in[1]; + matrix_decode(in, k, 0, 1, 1, s->dlbuflen, s->l_fwr, s->r_fwr, + s->lpr_fwr, s->lmr_fwr, &(s->adapt_l_gain), + &(s->adapt_r_gain), &(s->adapt_lpr_gain), + &(s->adapt_lmr_gain), s->lf, s->rf, s->lr, s->rr, s->cf); + break; + case HRTF_MIX_STEREO: + /* Stereo sources */ + s->lf[k] = in[0]; + s->rf[k] = in[1]; + s->cf[k] = s->lr[k] = s->rr[k] = 0; + break; + } + + /* We need to update the bass compensation delay line, too. */ + s->ba_l[k] = in[0]; + s->ba_r[k] = in[1]; + if (s->decode_mode == HRTF_MIX_51) { + s->ba_l[k] += in[2] + in[4]; + s->ba_r[k] += in[2] + in[5]; + } +} + +static inline float filter_fir(register unsigned int n, const float* w, + const float* x) +{ + register float y; // Output + + y = 0.0; + do { + n--; + y += w[n] * x[n]; + } while (n != 0); + + return y; +} + +/* + * Convolution on a ring buffer + * nx: length of the ring buffer + * nk: length of the convolution kernel + * sx: ring buffer + * sk: convolution kernel + * offset: offset on the ring buffer, can be + */ +static float conv(const int nx, const int nk, const float *sx, const float *sk, + const int offset) +{ + /* k = reminder of offset / nx */ + int k = offset >= 0 ? offset % nx : nx + (offset % nx); + + if (nk + k <= nx) + return filter_fir(nk, sx + k, sk); + else + return filter_fir(nk + k - nx, sx, sk + nx - k) + + filter_fir(nx - k, sx + k, sk); +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + HRTFContext *s = ctx->priv; + AVFrame *out; + int16_t *src = (int16_t *)in->data[0]; + int16_t *dst; + int16_t *end = src + in->nb_samples * inlink->channels; + const int dblen = s->dlbuflen, hlen = s->hrflen, blen = s->basslen; + float common, left, right, diff, left_b, right_b; + + out = ff_get_audio_buffer(outlink, in->nb_samples); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + + dst = (int16_t *)out->data[0]; + + while (src < end) { + const int k = s->cyc_pos; + + update_channel(s, src, k); + + /* + * Simulate a 7.5 ms -20 dB echo of the center channel in the + * front channels (like reflection from a room wall) - a kind of + * psycho-acoustically "cheating" to focus the center front + * channel, which is normally hard to be perceived as front + */ + s->lf[k] += CFECHOAMPL * s->cf[(k + CFECHODELAY) % s->dlbuflen]; + s->rf[k] += CFECHOAMPL * s->cf[(k + CFECHODELAY) % s->dlbuflen]; + + switch (s->decode_mode) { + case HRTF_MIX_51: + case HRTF_MIX_MATRIX2CH: + /* Mixer filter matrix */ + common = conv(dblen, hlen, s->cf, s->cf_ir, k + s->cf_o); + if (s->matrix_mode) { + /* In matrix decoding mode, the rear channel gain must be + renormalized, as there is an additional channel. */ + matrix_decode(src, k, 4, 5, 0, s->dlbuflen, + s->lr_fwr, s->rr_fwr, + s->lrprr_fwr, s->lrmrr_fwr, + &(s->adapt_lr_gain), &(s->adapt_rr_gain), + &(s->adapt_lrprr_gain), &(s->adapt_lrmrr_gain), + s->lr, s->rr, NULL, NULL, s->cr); + common += conv(dblen, hlen, s->cr, s->cr_ir, k + s->cr_o) * M1_76DB; + left = + ( conv(dblen, hlen, s->lf, s->af_ir, k + s->af_o) + + conv(dblen, hlen, s->rf, s->of_ir, k + s->of_o) + + (conv(dblen, hlen, s->lr, s->ar_ir, k + s->ar_o) + + conv(dblen, hlen, s->rr, s->or_ir, k + s->or_o)) * + M1_76DB + common); + right = + ( conv(dblen, hlen, s->rf, s->af_ir, k + s->af_o) + + conv(dblen, hlen, s->lf, s->of_ir, k + s->of_o) + + (conv(dblen, hlen, s->rr, s->ar_ir, k + s->ar_o) + + conv(dblen, hlen, s->lr, s->or_ir, k + s->or_o)) * + M1_76DB + common); + } else { + left = + ( conv(dblen, hlen, s->lf, s->af_ir, k + s->af_o) + + conv(dblen, hlen, s->rf, s->of_ir, k + s->of_o) + + conv(dblen, hlen, s->lr, s->ar_ir, k + s->ar_o) + + conv(dblen, hlen, s->rr, s->or_ir, k + s->or_o) + + common); + right = + ( conv(dblen, hlen, s->rf, s->af_ir, k + s->af_o) + + conv(dblen, hlen, s->lf, s->of_ir, k + s->of_o) + + conv(dblen, hlen, s->rr, s->ar_ir, k + s->ar_o) + + conv(dblen, hlen, s->lr, s->or_ir, k + s->or_o) + + common); + } + break; + case HRTF_MIX_STEREO: + left = + ( conv(dblen, hlen, s->lf, s->af_ir, k + s->af_o) + + conv(dblen, hlen, s->rf, s->of_ir, k + s->of_o)); + right = + ( conv(dblen, hlen, s->rf, s->af_ir, k + s->af_o) + + conv(dblen, hlen, s->lf, s->of_ir, k + s->of_o)); + break; + default: + break; + } + + /* + * Bass compensation for the lower frequency cut of the HRTF. + * A cross talk of the left and right channel is introduced to + * match the directional characteristics of higher frequencies. + * The bass will not have any real 3D perception, but that is + * OK (note at 180 Hz, the wavelength is about 2 m, and any + * spatial perception is impossible). + */ + left_b = conv(dblen, blen, s->ba_l, ba_ir, k); + right_b = conv(dblen, blen, s->ba_r, ba_ir, k); + left += (1 - BASSCROSS) * left_b + BASSCROSS * right_b; + right += (1 - BASSCROSS) * right_b + BASSCROSS * left_b; + /* Also mix the LFE channel (if available) */ + if (inlink->channels >= 6) { + left += src[3] * M3_01DB; + right += src[3] * M3_01DB; + } + + /* Amplitude renormalization. */ + left *= AMPLNORM; + right *= AMPLNORM; + + switch (s->decode_mode) { + case HRTF_MIX_51: + case HRTF_MIX_STEREO: + /* "Cheating": linear stereo expansion to amplify the 3D + perception. Note: Too much will destroy the acoustic space + and may even result in headaches. */ + diff = STEXPAND2 * (left - right); + dst[0] = av_clip_int16(left + diff); + dst[1] = av_clip_int16(right - diff); + break; + case HRTF_MIX_MATRIX2CH: + /* Do attempt any stereo expansion with matrix encoded + sources. The L, R channels are already stereo expanded + by the steering, any further stereo expansion will sound + very unnatural. */ + dst[0] = av_clip_int16(left); + dst[1] = av_clip_int16(right); + break; + } + + /* Next sample... */ + src += inlink->channels; + dst += outlink->channels; + + s->cyc_pos--; + if (s->cyc_pos < 0) + s->cyc_pos += dblen; + } + + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static const AVFilterPad hrtf_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = filter_frame, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad hrtf_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, + { NULL } +}; + +AVFilter ff_af_hrtf = { + .name = "hrtf", + .description = NULL_IF_CONFIG_SMALL("Head-related transfer function (HRTF)."), + .init = init, + .query_formats = query_formats, + .priv_size = sizeof(HRTFContext), + .priv_class = &hrtf_class, + .inputs = hrtf_inputs, + .outputs = hrtf_outputs, +}; diff --git a/libavfilter/af_hrtf.h b/libavfilter/af_hrtf.h new file mode 100644 index 0000000..c810e66 --- /dev/null +++ b/libavfilter/af_hrtf.h @@ -0,0 +1,550 @@ +/* + * Copyright (c) 2004 Yue Shi Lai + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef AVFILTER_AF_HRTF_H +#define AVFILTER_AF_HRTF_H + +#define HRTF_MIX_51 0 +#define HRTF_MIX_STEREO 1 +#define HRTF_MIX_MATRIX2CH 2 + +/* Amplitude scaling factors */ +#define M17_0DB 0.1414213562 +#define M9_03DB 0.3535533906 +#define M6_99DB 0.4472135955 +#define M4_77DB 0.5773502692 +#define M3_01DB 0.7071067812 +#define M1_76DB 0.8164965809 + +#define DELAYBUFLEN 1024 /* Length of the delay buffer */ +#define HRTFFILTLEN 64 /* HRTF filter length */ +#define IRTHRESH 0.001 /* Impulse response pruning thresh. */ + +#define AMPLNORM M6_99DB /* Overall amplitude renormalization */ + +#define BASSFILTFREQ 180 /* Bass compensation filter cut (Hz) */ +#define BASSFILTLEN 193 /* Bass compensation filter length */ +#define BASSGAIN M_SQRT2 /* Bass compensation gain */ +#define BASSCROSS 0.35 /* Bass cross talk */ + +#define FWRDURATION 240 /* FWR average duration (samples) */ +#define MATREARDELAY 720 /* Matrix mode rear delay (samples) */ + +#define MATAGCTRIG 8.0 /* (Fuzzy) AGC trigger */ +#define MATAGCDECAY 1.0 /* AGC baseline decay rate (1/samp.) */ +#define MATAGCLOCK 0.2 /* AGC range (around 1) where the + matrix behaves passively */ +#define MATCOMPGAIN 0.37 /* Cross talk compensation gain, + 0.50 - 0.55 is full cancellation. */ + +#define CFECHODELAY 360 /* Center front echo delay (samples) */ +#define CFECHOAMPL M17_0DB /* Center front echo amplitude */ + +#define STEXPAND2 0.07 /* Stereo expansion / 2 */ + +/* Head related impulse response (HRIR) derived from KEMAR measurement + data by Bill Gardner <bi...@media.mit.edu> and Keith Martin + <k...@media.mit.edu> + + URL: http://sound.media.mit.edu/KEMAR.html + + Distributed under GPL with authors' permission +*/ + +/* EQUALIZED KEMAR HRIR + +How to generate these data: + +1. You need the MIT Media Lab's KEMAR data, read it into an software + capable of signal/time series analysis (like Mathematica, Matlab, + ...) + +2. Construct an equalizing FIR inverse filter by calculating the + transfer function of the front, same side impulse response, then + take 1 over the absolute magnitude. + +3. Cut the poles in the inverse filter's transfer function + specification by limiting the amplification to 2.5 (note, this + number assumes that you have correct signal processing + normalization of the Fourier transform). + +4. Design the FIR inverse filter by calculating the inverse Fourier + transform, then chopping the coefficients down to a reasonable + number (N = 15 is used here), apply the Kaiser-Bessel window (alpha + = 2 is used here). Note the objective is remove the color bias + only (as if you are using an equalizer), _not_ to do a full inverse + filtering. (Note: beta = pi*alpha in other notation.) + + For N = 15, alpha = 2, you should get the following impulse + response: + + 0.001001558668605168, 0.00698457265741865, 0.040453643039829436, + 0.012230541722147855, -0.11939760844854072, 0.16468099899755967, + -0.30297563073747436, 1.3140211791355982, -0.30297563073747436, + 0.16468099899755967, -0.11939760844854072, 0.012230541722147855, + 0.040453643039829436, 0.00698457265741865, 0.001001558668605168 + +5. Linearly convolve all KEMAR HRIR with this inverse filter. + +6. Resample from 44.1 kHz sampling frequency to 48 kHz. + +*/ + +/* Center front (-5 degree) - not 0 degree in order to create a clear + front image from a finite distance */ +static const float cf_filt[128] = { + -0.00008638082319075036, 0.0003198059946385229, + -0.0005010631339162132, 0.0011424741331126876, + -0.001584220794688753, 0.001742715363246275, + -0.0011080796626780694, 0.0001651829990860167, + 0.005235028337314985, 0.0035223828473357776, + 0.010057681388431303, -0.033469432129545514, + 0.013391253316233523, 0.004858462839827063, + 0.08172161220103627, 0.26158596134500023, + -0.12420314583323326, -0.14298458356097565, + 0.14421897280453896, -0.1635792507629016, + -0.02187136722480014, 0.2426863044711817, + 0.07229814207917194, 0.0942742651913879, + 0.29856830878076834, 0.2944146162057754, + -0.12122157003421209, -0.19640092165631157, + 0.11623836502034968, -0.05794027397995521, + -0.34313138341973776, -0.19487516249168105, + 0.010118993953802401, -0.09460218797710966, + -0.16761521117359582, 0.004154461610153861, + 0.052768641758969316, -0.00041823982226147407, + 0.021634960445143514, 0.07562793486871108, + 0.08895407129506479, 0.039857755093416214, + 0.044257936180422945, 0.061557584906101664, + 0.015547268541895703, -0.023908191934932484, + 0.009498030443468223, 0.03816269003221337, + -0.009820500607303615, -0.042003975527908084, + -0.03335447117311547, -0.029294510859746596, + -0.05212623136198511, -0.073427547153205, + -0.061190797824958836, -0.04620925059966413, + -0.04204619420702159, -0.02331915902615157, + 0.00211481411477094, 0.00852563995740107, + 0.008766809731743399, 0.008666632180812078, + 0.018279202191625352, 0.02924332751289675, + 0.022293148257836494, 0.012362146008584188, + 0.008572582458807008, 0.006491370763597344, + -0.0019366944997535774, -0.006318669309634434, + -0.006457921690218669, -0.015050265524669974, + -0.02110660282616213, -0.017027809096377904, + -0.01651052305334348, -0.022770064150046673, + -0.01999875754219472, -0.012294792027337775, + -0.011506057031057188, -0.011448970577312903, + -0.004823572302580925, 0.0022451134042777883, + 0.004145473526859826, 0.005629030064546135, + 0.008588029213398785, 0.010092048834844231, + 0.007182013245552008, 0.0014600979508720656, + -0.0038314646272511756, -0.003443901997881347, + -0.0029483418254804047, -0.007609357112679647, + -0.006518368948030822, -0.004495803701497202, + -0.007109113004849672, -0.008346237278084265, + -0.005560847336252453, -0.002993453167553188, + -0.005122897816824269, -0.004389782626604215, + -0.0010912633695218108, -0.0019712029474458835, + -0.005870162265802235, -0.005626159534954128, + -0.00027254977910844407, 0.0013794425431633785, + -0.0005919083190430062, -0.0007861203545416682, + -0.0007049560240893946, -0.0032720188494468868, + -0.004460645567968504, -0.0032018528193571696, + -0.0030579229375062105, -0.003593998902656612, + -0.0038032977997776445, -0.004613776010454773, + -0.0059796549143736845, -0.00420126194319768, + -0.0012374419948287222, 0.0008572699213050608, + 0.0021490971020081094, 0.00047295283198381995, + -0.0009670277915884887, -0.001354440866080231, + -0.002962902746547851, -0.00533935813338141, + -0.005469203016468759, -0.004355784273189485 +}; + +/* Front, same side (30 degree) */ +static const float af_filt[128] = { + -0.004140580614755493, 0.005790934614385445, + 0.003318916682081112, 0.014257145544366063, + 0.007328442487127339, -0.06550381777876194, + 0.03502225818161845, -0.013090579770708259, + 0.2517776798694195, 0.420770489950659, + -0.3418854608834852, -0.24371032493696737, + 0.04901356150030018, -0.1778083521632833, + 0.26448004245714163, 0.23245199964546834, + 0.033053145803936305, 0.46811222821062415, + 0.5359265986255611, -0.011912195468533787, + -0.39763432601411647, -0.034482864386898314, + 0.029445398240649626, -0.3850940407863262, + -0.3272328478175581, -0.14701421403616477, + -0.08522137400169517, -0.14936851633336035, + -0.09432605283433723, 0.0991200405937827, + 0.011075012089917331, -0.0051036489980274685, + 0.0933903289749412, 0.1344189369609565, + 0.10507466913017807, 0.04240159324684365, + 0.06559270110638656, 0.026984119875617524, + -0.03359846103238096, -0.018000197099174275, + 0.042031818548178244, 0.03849039666888434, + -0.02450829674011345, -0.03407882403088576, + -0.029230189282961977, -0.046964865291761734, + -0.09458258700116245, -0.1527349330901158, + -0.15411577687826097, -0.08761679790956928, + -0.033623549089171874, -0.007204768531481949, + 0.008273425020444852, 0.021368717994908505, + 0.04366608267875025, 0.05660907333076205, + 0.06775726495503939, 0.05621881735271431, + 0.03576231950669927, 0.02500825834889175, + 0.015423811076054601, 0.007903258334503761, + -0.0053873014137761945, -0.006987955469434698, + -0.012027972007598602, -0.025228281243816594, + -0.026225091797257318, -0.023809293997344882, + -0.03250172017712295, -0.03195696301067249, + -0.01784813952189948, -0.01663267233760342, + -0.016184530450468065, -0.011659883749357463, + -0.0035378511240219163, -0.0005485800790443406, + 0.0018432660108168625, 0.011634844139907534, + 0.018333603402051105, 0.020447379185133056, + 0.00850783664147828, 0.0004694148911037838, + -0.0017047130409786676, -0.0022409152834483997, + -0.000860472174892845, -0.004111075059198666, + -0.003527843382056666, -0.009640160874903018, + -0.01750044574231376, -0.015613389403672443, + -0.010790028120953001, -0.0095313499955768, + -0.007469721416726809, -0.0019186578145117315, + -0.00014977322572890802, -0.0029803838028179728, + -0.006520567233727221, 0.000035015132033882596, + 0.009245098100543752, 0.009896930052308656, + 0.008316744929565786, 0.004575207140193997, + -0.0000647420103997081, -0.004502916832871627, + -0.004225962213251224, -0.002886014126381486, + -0.006416834142585976, -0.007156609995423569, + -0.008840274447579472, -0.01441763751386817, + -0.015435817484659574, -0.00924487254924743, + -0.0021571721940235205, 0.0028540722992305453, + 0.00273577475088536, -0.000788412365513805, + -0.0032650029728365907, -0.003880217646231338, + -0.0035302087299613778, -0.0038531436176586246, + -0.0011921632190514074, -0.0020722967099011938, + -0.004985351145629344, -0.0042375588844648735, + -0.003030360463006021, -0.0014161075428041471, + -0.0005083025643192044, 0.00035096963769606926 +}; + +/* Front, opposite (-30 degree) */ +static const float of_filt[128] = { + -0.000013472538374193126, -0.00008048061877079751, + 0.000043927265781258155, -0.000017931700794858892, + -0.000034774602476112886, -0.00009576223008735474, + 0.0001557797638630691, -0.00018742885883751094, + 0.00026512448626705716, -0.0001451040203319678, + -0.00008263233117758043, 0.0006486245853639179, + -0.0010631408451846698, 0.0026571994100746143, + 0.0014179177997092787, 0.0062326502956616256, + -0.008194149324545333, -0.006568029415878379, + 0.009538759710818582, 0.012309193558632693, + 0.12336638055838955, 0.046164307101829005, + -0.10228706407884815, 0.04047687260345798, + -0.00296595313977046, -0.07057949208414134, + 0.08172114840714612, 0.08736490764127891, + 0.05105250431333021, 0.11627179512747428, + 0.20717888490340705, 0.09375052213570291, + -0.09784374168330194, -0.010493571845901443, + 0.053131894303891716, -0.10157443971694806, + -0.16264032634244974, -0.05402369511361273, + -0.0274403608654217, -0.09860277022495063, + -0.06841875821090282, -0.004434574400066223, + -0.0005222661652743502, -0.006231881259827263, + 0.014410397820340159, 0.04885649512730243, + 0.04361962569042684, 0.03399214029009391, + 0.04961073933475931, 0.04067325604132289, + 0.007850647519227257, 0.004564440466905299, + 0.02257107958021618, 0.008183791928884486, + -0.014913479343180557, -0.018685938460856224, + -0.01745737397226911, -0.02327177054233603, + -0.03723048632685227, -0.044739390162299685, + -0.042651220125613766, -0.03730017561004743, + -0.029039465434276192, -0.01885087458914294, + -0.01207127752277769, -0.006779800724164512, + -0.001930416967444157, 0.000029454577995528385, + 0.0013822760965755472, 0.0014799128583230202, + 0.0002068200609199832, 0.0022254295286201083, + 0.005143858159434566, 0.0018580542060917013, + -0.0019426046325146259, -0.0014464042108543495, + -0.0034430083560735582, -0.009692758426099499, + -0.011840035292593485, -0.010716508855893968, + -0.012939889036853034, -0.0121846427935653, + -0.006198503315630782, -0.0023186723099380305, + -0.002679872498314837, -0.003086020446226295, + -0.0015709623347698936, -0.0008147490468332398, + -0.0012384575726770983, -0.0005212877089109362, + 0.0017707578744906142, 0.001324932723905786, + -0.0017023653780617696, -0.0045108927752919425, + -0.005422155613096912, -0.0039489323837623835, + -0.005295995750506547, -0.00629706566356189, + -0.004685732198036754, -0.0048076735568143, + -0.005978864279217503, -0.005928999306332966, + -0.004187703549017582, -0.003213999896976475, + -0.0028068699816073414, -0.0010889703907593833, + 0.0003276714243495386, -0.0013015007040186994, + -0.003208050402434782, -0.0025115319088208545, + -0.0013787553006401076, -0.0018279087370218635, + -0.0025904836507747754, -0.002071221947222004, + -0.0026424212922485594, -0.0039837031817577, + -0.0041635566057380965, -0.004355223489150822, + -0.004350395332709937, -0.0036693292471930263, + -0.003386384394185026, -0.003972568655001128, + -0.004332336840023821, -0.002648767912111827, + -0.001384410080218114, -0.0011353792711849466, + -0.0013726264946164232, -0.0020075119315034313 +}; + +/* Rear, same side (135 degree) */ +static const float ar_filt[128] = { + 0.004573315040810066, 0.0013592578059426913, + 0.01553271930902704, -0.0002356117224941317, + -0.05746098219774702, 0.03430688963370445, + 0.00808371687447385, 0.21893535841158596, + 0.2984357591724814, -0.3302799746504719, + -0.3194029149806245, 0.21633225051331056, + 0.24371260938097083, -0.08843705549751085, + 0.03939684701343366, 0.45386926431114494, + 0.07599118140753386, -0.18114706160474578, + 0.285640624686038, 0.4049515236666218, + -0.05347890222071792, -0.31464359045319074, + -0.1033502246468194, -0.04553593949283157, + -0.1880747731157464, -0.13629090230626037, + -0.10435789106123239, -0.19818232801888755, + -0.16701805476330397, -0.022793111199284, + 0.058049696762683685, 0.007048321372693906, + -0.002966419183225961, 0.10140569697797763, + 0.11648999956673124, 0.05218347182779882, + 0.028427001212735392, 0.04151900310166159, + -0.0006960604221423734, -0.05898623212226975, + -0.03801934531173312, -0.029306970535287986, + -0.04549125782835908, -0.0599222718506552, + -0.058299618975430116, -0.03765579129720727, + -0.03559302657499581, -0.020647901025903054, + -0.005720957338744348, -0.0041915732688915545, + -0.0011470880098346143, 0.008737404798553, + 0.023444168098121512, 0.024204226042172663, + 0.01894897166475026, 0.020807655257479588, + 0.021570431128040954, 0.006800556178576289, + -0.009000089216921362, -0.010969824547067934, + -0.0033653428332822374, -0.012676936164668659, + -0.026739938673413587, -0.023427869194287573, + -0.023302007105117244, -0.023647155590533712, + -0.021289317515613106, -0.009120487305069884, + 0.0009251551667728967, 0.00004285344125653763, + -0.00009042365479456271, 0.00022573242339446494, + 0.00720168491586098, 0.007111875505402431, + 0.003186514817683482, 0.00810087718334745, + 0.012619557025922575, 0.007854726400013397, + -0.0024013592881066267, -0.001452457473161119, + -0.0025535188366093945, -0.012428911627809337, + -0.013729251536694145, -0.0070099675146427344, + -0.007165284278706593, -0.01639289295622301, + -0.015831795079778305, -0.007305768485523729, + -0.003608863157004021, -0.0032640528878698084, + 0.0030901263998481944, 0.00749497566124848, + 0.002515185532327241, 0.00004840875738621367, + 0.0017596043486043966, 0.0046229941553338144, + 0.0034259167322926096, 0.003707347634186093, + 0.0035584806528586328, -0.0019078936035275198, + -0.006057343815214898, -0.0069262470468817, + -0.004345020728618624, -0.004177623355574794, + -0.005373506556122508, -0.006624933928893836, + -0.008679541408588839, -0.010718719681595322, + -0.011392246979594496, -0.007893917064389902, + -0.0027572935365832536, -0.00006064707149834412, + -0.0012512537319656323, -0.0024501501002409786, + -0.0022106788572895998, -0.00234124933370301, + -0.0008953445167066823, 0.0005393670625637734, + -0.00033175600142209297, -0.004023994309351289, + -0.008655472335784443, -0.009899957354849682, + -0.008664952919996412, -0.00553483124503576, + -0.003735336089277662, -0.002754824348643885, + -0.0026884314856593368, -0.004084181815125924 +}; + +/* Rear, opposite (-135 degree) */ +static const float or_filt[128] = { + 0.0001220944028243897, -0.000021785381808441314, + 5.823057988603169e-6, -0.00001217768176447613, + -0.00006123604397345513, 5.574117262531134e-6, + -0.00004935331914366778, 1.1771577934768211e-6, + -0.000059236211621095756, 9.503536190497286e-6, + -0.0001494445696103564, 0.00012248858284145305, + -0.0000963975321456313, 6.017905197665205e-6, + 0.00003353395360402643, -0.0001931511015359506, + 0.0005113536523931485, -0.0005676652619386114, + 0.0012057159755477467, 0.0009370492250339692, + 0.004596472288877981, -0.0018831773384237068, + -0.008208535225621212, 0.0038178646400751056, + 0.008726517739105965, 0.06664363898418262, + 0.06788684221502142, -0.04492315162807267, + -0.04019906311255255, 0.026203059677375153, + 0.013678129114847544, -0.014334962223993527, + 0.010141709596167392, 0.11559131576945537, + 0.1586402064538425, 0.059975334707967023, + 0.004671725963777715, 0.031498678282775874, + 0.014338626006524587, -0.014749719448472231, + -0.02055508237941379, -0.05407690143992048, + -0.07767559836886143, -0.05029091786216801, + -0.030808335706574427, -0.03401958135442541, + -0.030520368430288967, -0.014168302104259355, + 0.011907621259989802, 0.014286081013069, + 0.006377467879613449, 0.018546823568277478, + 0.028297012771618273, 0.025222339408338186, + 0.021931611353415138, 0.019708894333646355, + 0.01729258494072014, 0.017468204169564034, + 0.009729094845051928, -0.002976992018531901, + -0.00956986166277019, -0.016125733548332074, + -0.02934094241442545, -0.04133767871051455, + -0.043536981145416466, -0.0385966307108608, + -0.02784453599342459, -0.018995135307247116, + -0.012849534096536747, -0.004437491064613308, + 0.00028385411598204655, 0.003776874988516643, + 0.008069432041547833, 0.008764754183751848, + 0.008020908861878062, 0.006830351461360802, + 0.002218330884267235, -0.0020478725582339444, + -0.003997428121462543, -0.007066287373515421, + -0.00940847412544698, -0.010938998446237963, + -0.011775483016151306, -0.011391103919484287, + -0.010586061195163017, -0.009842793078929053, + -0.007753202010139829, -0.00569213732353025, + -0.006506783349722073, -0.005346134281903736, + -0.003913089814898934, -0.0036091443854759727, + -0.0020328564301266287, 0.00017932870773467683, + 0.0032779786679056357, 0.003969695813293966, + 0.0020339334412434987, -0.00011345940675415259, + -0.0018344103399567666, -0.003556764701666365, + -0.004263523639408391, -0.002940568582022133, + -0.0034341188272627556, -0.006023399920020824, + -0.0077456903203677865, -0.007912219312377842, + -0.00625202770436523, -0.00530785086116117, + -0.005569722659634311, -0.004664448462594344, + -0.0037747773914077747, -0.004175649656985592, + -0.004659601521384289, -0.005008602967819641, + -0.004730625079902729, -0.0034039554356604146, + -0.0017110333873406587, -0.0006091938771510242, + -0.0016051679050678297, -0.003312864664007262, + -0.004505512715977288, -0.004152222189861692, + -0.003218596419678823, -0.0027277806209877343, + -0.001715005444317267, -0.0012589960071233749, + -0.001852908777923165, -0.002540339553144362 +}; + +/* Center rear (180 degree) */ +static const float cr_filt[128] = { + -0.00005989110716536726, -0.00022790291829128702, + 0.0002659166098971966, -0.0003774772716776257, + 0.0004540309551867803, -0.000420238187386368, + 0.00025518536450885686, 0.00028285526288953955, + -0.001016391007574093, 0.0028634984299063795, + 0.0021574799687976045, 0.01035121276682072, + -0.010481720917298163, -0.013197198495899292, + 0.0031928225328717195, 0.02903137843618603, + 0.1632429772511569, 0.1047487989875262, + -0.10464685060623742, -0.09260196288035998, + -0.007514241993554443, 0.013596249226741712, + -0.019876166508450258, 0.1255626123599804, + 0.3648170359521724, 0.19458249753223478, + -0.04434070930031298, 0.046582528121935265, + 0.09484427347230277, -0.03137795311969644, + -0.10297437925363695, -0.09351091015917065, + -0.1129521092162064, -0.14925322995658827, + -0.1231466295584665, -0.06356719756705227, + -0.05442277895126282, -0.07568433015661316, + -0.023314932828602003, 0.04260950721318558, + 0.02249026315598923, 0.02048195669571197, + 0.05651342117268278, 0.05885038917623213, + 0.03797102097397795, 0.011767394419953451, + 0.00560502503429481, 0.005051125343961189, + -0.012925933188033823, -0.023918884651306566, + -0.013251659441678816, -0.010694772488866284, + -0.03080486448617846, -0.03661278237783158, + -0.0379227303416262, -0.042189005718490775, + -0.026595666344596286, -0.009759025956801257, + -0.002064986663513004, -0.002420117028098389, + -0.006629991977552491, 0.004619970897631026, + 0.019450642967537877, 0.0173521119057514, + 0.017641425439988062, 0.02270029598048491, + 0.018976431925275348, 0.009299852902290885, + -0.001695039371619912, -0.00675162574265618, + -0.009380968871003034, -0.011208396125485165, + -0.01308640049201482, -0.0165636375633249, + -0.022004099870933345, -0.025173458684139286, + -0.016918759559175375, -0.00865150653575917, + -0.006999929082792643, -0.005454830010518988, + -0.0021129521131095317, 0.00018717090054046307, + -0.0002864344788569993, 0.0017615225381095569, + 0.006985907557802283, 0.010577308310476465, + 0.006466104789306027, -0.0014988738575948326, + -0.0039669755229277195, -0.0065156971200080235, + -0.009343206924192169, -0.0076430644693577495, + -0.004395214976600924, -0.003052735340422483, + -0.007019103043066595, -0.00974109267696527, + -0.007968015032797376, -0.007801513845528344, + -0.007535748903681969, -0.003543341967287925, + 0.0015083125553729722, 0.0023345972556147025, + -0.0010043623069557037, -0.0025295765105203746, + -0.0023701840891643634, -0.0005908186035024362, + 0.0029826252289082847, 0.004829048542117764, + 0.004488360022902081, 0.00002643748103005408, + -0.0042100779212597295, -0.006170600558114495, + -0.007267149164680168, -0.006825522903494639, + -0.006899834372739123, -0.0073493916110062675, + -0.009554351265163382, -0.011790297433830197, + -0.010645796603734424, -0.0064661575394022106, + -0.002026743466524137, -0.0004337034584909932, + -0.0011172647031654614, -0.0017947816283674731, + -0.00255615052036616, -0.0017721562881944813, + -0.0002379619297227554, 0.0007130120121089036 +}; + +static const float ba_ir[193] = { + 0.000000, -0.000000, -0.000000, 0.000001, 0.000000, -0.000002, -0.000000, + 0.000003, 0.000000, -0.000006, -0.000000, 0.000009, 0.000000, -0.000015, + -0.000000, 0.000023, 0.000000, -0.000034, -0.000000, 0.000048, 0.000000, + -0.000068, -0.000000, 0.000094, 0.000000, -0.000128, -0.000000, 0.000171, + 0.000000, -0.000225, -0.000000, 0.000293, 0.000000, -0.000378, -0.000000, + 0.000481, 0.000000, -0.000607, -0.000000, 0.000758, 0.000000, -0.000939, + -0.000000, 0.001155, 0.000000, -0.001409, -0.000000, 0.001707, 0.000000, + -0.002056, -0.000000, 0.002460, 0.000000, -0.002929, -0.000000, 0.003469, + 0.000000, -0.004090, -0.000000, 0.004802, 0.000000, -0.005617, -0.000000, + 0.006550, 0.000000, -0.007618, -0.000000, 0.008843, 0.000000, -0.010253, + -0.000000, 0.011883, 0.000000, -0.013780, -0.000000, 0.016011, 0.000000, + -0.018668, -0.000000, 0.021888, 0.000000, -0.025881, -0.000000, 0.030989, + 0.000000, -0.037800, -0.000000, 0.047431, 0.000000, -0.062277, -0.000000, + 0.088571, 0.000000, -0.149172, -0.000000, 0.449864, 0.707107, 0.449864, + -0.000000, -0.149172, 0.000000, 0.088571, -0.000000, -0.062277, 0.000000, + 0.047431, -0.000000, -0.037800, 0.000000, 0.030989, -0.000000, -0.025881, + 0.000000, 0.021888, -0.000000, -0.018668, 0.000000, 0.016011, -0.000000, + -0.013780, 0.000000, 0.011883, -0.000000, -0.010253, 0.000000, 0.008843, + -0.000000, -0.007618, 0.000000, 0.006550, -0.000000, -0.005617, 0.000000, + 0.004802, -0.000000, -0.004090, 0.000000, 0.003469, -0.000000, -0.002929, + 0.000000, 0.002460, -0.000000, -0.002056, 0.000000, 0.001707, -0.000000, + -0.001409, 0.000000, 0.001155, -0.000000, -0.000939, 0.000000, 0.000758, + -0.000000, -0.000607, 0.000000, 0.000481, -0.000000, -0.000378, 0.000000, + 0.000293, -0.000000, -0.000225, 0.000000, 0.000171, -0.000000, -0.000128, + 0.000000, 0.000094, -0.000000, -0.000068, 0.000000, 0.000048, -0.000000, + -0.000034, 0.000000, 0.000023, -0.000000, -0.000015, 0.000000, 0.000009, + -0.000000, -0.000006, 0.000000, 0.000003, -0.000000, -0.000002, 0.000000, + 0.000001, -0.000000, -0.000000, 0.000000, +}; +#endif /* AVFILTER_AF_HRTF_H */ diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 3b13ed7..e76775e 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -86,6 +86,7 @@ void avfilter_register_all(void) REGISTER_FILTER(EQUALIZER, equalizer, af); REGISTER_FILTER(FLANGER, flanger, af); REGISTER_FILTER(HIGHPASS, highpass, af); + REGISTER_FILTER(HRTF, hrtf, af); REGISTER_FILTER(JOIN, join, af); REGISTER_FILTER(LADSPA, ladspa, af); REGISTER_FILTER(LOWPASS, lowpass, af); -- 1.7.11.2 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel