From 091bfa3abf2f28b37fa12cca6b4c248c31d27965 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 3 Sep 2015 23:55:36 +0200 Subject: audio/filter: remove some useless filters All of these filters are considered not useful anymore by us. Some have replacements in libavfilter (useable through af_lavfi). af_center, af_extrastereo, af_karaoke, af_sinesuppress, af_sub, af_surround, af_sweep: pretty simple and useless filters which probably nobody ever wants. af_ladspa: has a replacement in libavfilter. af_hrtf: the algorithm doesn't work properly on most sources, and the implementation was buggy and complicated. (The filter was inherited from MPlayer; but even in mpv times we had to apply fixes that fixed major issues with added noise.) There is a ladspa filter if you still want to use it. af_export: I'm not even sure what this is supposed to do. Possibly it was meant for GUIs rendering audio visualizations, but it couldn't really work well. For example, the size of the audio depended on the samplerate (fixed number of samples only), and it couldn't retrieve the complete audio, only fragments. If this is really needed for GUIs, mpv should add native visualization, or a proper API for it. --- audio/audio.c | 7 - audio/audio.h | 1 - audio/filter/af.c | 23 -- audio/filter/af_center.c | 104 ----- audio/filter/af_export.c | 237 ------------ audio/filter/af_extrastereo.c | 132 ------- audio/filter/af_hrtf.c | 670 -------------------------------- audio/filter/af_hrtf.h | 510 ------------------------ audio/filter/af_karaoke.c | 86 ----- audio/filter/af_ladspa.c | 851 ----------------------------------------- audio/filter/af_sinesuppress.c | 117 ------ audio/filter/af_sub.c | 148 ------- audio/filter/af_surround.c | 246 ------------ audio/filter/af_sweep.c | 92 ----- audio/filter/dsp.h | 31 -- audio/filter/filter.c | 359 ----------------- audio/filter/filter.h | 74 ---- audio/filter/window.c | 212 ---------- audio/filter/window.h | 42 -- 19 files changed, 3942 deletions(-) delete mode 100644 audio/filter/af_center.c delete mode 100644 audio/filter/af_export.c delete mode 100644 audio/filter/af_extrastereo.c delete mode 100644 audio/filter/af_hrtf.c delete mode 100644 audio/filter/af_hrtf.h delete mode 100644 audio/filter/af_karaoke.c delete mode 100644 audio/filter/af_ladspa.c delete mode 100644 audio/filter/af_sinesuppress.c delete mode 100644 audio/filter/af_sub.c delete mode 100644 audio/filter/af_surround.c delete mode 100644 audio/filter/af_sweep.c delete mode 100644 audio/filter/dsp.h delete mode 100644 audio/filter/filter.c delete mode 100644 audio/filter/filter.h delete mode 100644 audio/filter/window.c delete mode 100644 audio/filter/window.h (limited to 'audio') diff --git a/audio/audio.c b/audio/audio.c index f84d6054bc..4b12992879 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -58,13 +58,6 @@ void mp_audio_set_num_channels(struct mp_audio *mpa, int num_channels) update_redundant_info(mpa); } -// Use old MPlayer/ALSA channel layout. -void mp_audio_set_channels_old(struct mp_audio *mpa, int num_channels) -{ - mp_chmap_from_channels_alsa(&mpa->channels, num_channels); - update_redundant_info(mpa); -} - void mp_audio_set_channels(struct mp_audio *mpa, const struct mp_chmap *chmap) { mpa->channels = *chmap; diff --git a/audio/audio.h b/audio/audio.h index a0ecb2d7bf..bf5358274a 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -46,7 +46,6 @@ struct mp_audio { void mp_audio_set_format(struct mp_audio *mpa, int format); void mp_audio_set_num_channels(struct mp_audio *mpa, int num_channels); -void mp_audio_set_channels_old(struct mp_audio *mpa, int num_channels); void mp_audio_set_channels(struct mp_audio *mpa, const struct mp_chmap *chmap); void mp_audio_copy_config(struct mp_audio *dst, const struct mp_audio *src); bool mp_audio_config_equals(const struct mp_audio *a, const struct mp_audio *b); diff --git a/audio/filter/af.c b/audio/filter/af.c index 6a5b1f42a5..b877ba7661 100644 --- a/audio/filter/af.c +++ b/audio/filter/af.c @@ -34,23 +34,12 @@ extern const struct af_info af_info_delay; extern const struct af_info af_info_channels; extern const struct af_info af_info_format; -extern const struct af_info af_info_force; extern const struct af_info af_info_volume; extern const struct af_info af_info_equalizer; extern const struct af_info af_info_pan; -extern const struct af_info af_info_surround; -extern const struct af_info af_info_sub; -extern const struct af_info af_info_export; extern const struct af_info af_info_drc; -extern const struct af_info af_info_extrastereo; extern const struct af_info af_info_lavcac3enc; extern const struct af_info af_info_lavrresample; -extern const struct af_info af_info_sweep; -extern const struct af_info af_info_hrtf; -extern const struct af_info af_info_ladspa; -extern const struct af_info af_info_center; -extern const struct af_info af_info_sinesuppress; -extern const struct af_info af_info_karaoke; extern const struct af_info af_info_scaletempo; extern const struct af_info af_info_bs2b; extern const struct af_info af_info_lavfi; @@ -63,24 +52,12 @@ static const struct af_info *const filter_list[] = { &af_info_volume, &af_info_equalizer, &af_info_pan, - &af_info_surround, - &af_info_sub, - &af_info_export, &af_info_drc, - &af_info_extrastereo, &af_info_lavcac3enc, &af_info_lavrresample, - &af_info_sweep, - &af_info_hrtf, -#if HAVE_LADSPA - &af_info_ladspa, -#endif #if HAVE_RUBBERBAND &af_info_rubberband, #endif - &af_info_center, - &af_info_sinesuppress, - &af_info_karaoke, &af_info_scaletempo, #if HAVE_LIBBS2B &af_info_bs2b, diff --git a/audio/filter/af_center.c b/audio/filter/af_center.c deleted file mode 100644 index 69e54e81c6..0000000000 --- a/audio/filter/af_center.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * This filter adds a center channel to the audio stream by - * averaging the left and right channel. - * There are two runtime controls one for setting which channel - * to insert the center-audio into called AF_CONTROL_SUB_CH. - * - * FIXME: implement a high-pass filter for better results. - * - * copyright (c) 2005 Alex Beregszaszi - * - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpv 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see . - */ - -#include -#include -#include - -#include "common/common.h" -#include "af.h" - -// Data for specific instances of this filter -typedef struct af_center_s -{ - int ch; // Channel number which to insert the filtered data -}af_center_t; - -// Initialization and runtime control -static int control(struct af_instance* af, int cmd, void* arg) -{ - af_center_t* s = af->priv; - - switch(cmd){ - case AF_CONTROL_REINIT:{ - // Sanity check - if(!arg) return AF_ERROR; - - af->data->rate = ((struct mp_audio*)arg)->rate; - mp_audio_set_channels_old(af->data, MPMAX(s->ch+1,((struct mp_audio*)arg)->nch)); - mp_audio_set_format(af->data, AF_FORMAT_FLOAT); - - return af_test_output(af,(struct mp_audio*)arg); - } - } - return AF_UNKNOWN; -} - -static int filter_frame(struct af_instance* af, struct mp_audio* data) -{ - if (!data) - return 0; - if (af_make_writeable(af, data) < 0) { - talloc_free(data); - return -1; - } - struct mp_audio* c = data; // Current working data - af_center_t* s = af->priv; // Setup for this instance - float* a = c->planes[0]; // Audio data - int nch = c->nch; // Number of channels - int len = c->samples*c->nch; // Number of samples in current audio block - int ch = s->ch; // Channel in which to insert the center audio - register int i; - - // Run filter - for(i=0;icontrol=control; - af->filter_frame = filter_frame; - return AF_OK; -} - -#define OPT_BASE_STRUCT af_center_t -const struct af_info af_info_center = { - .info = "Audio filter for adding a center channel", - .name = "center", - .flags = AF_FLAGS_NOT_REENTRANT, - .open = af_open, - .priv_size = sizeof(af_center_t), - .options = (const struct m_option[]) { - OPT_INTRANGE("channel", ch, 0, 0, AF_NCH - 1, OPTDEF_INT(1)), - {0} - }, -}; diff --git a/audio/filter/af_export.c b/audio/filter/af_export.c deleted file mode 100644 index 6020d9d98e..0000000000 --- a/audio/filter/af_export.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * This audio filter exports the incoming signal to other processes - * using memory mapping. The memory mapped area contains a header: - * int nch, - * int size, - * unsigned long long counter (updated every time the contents of - * the area changes), - * the rest is payload (non-interleaved). - * - * Authors: Anders; Gustavo Sverzut Barbieri - * - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpv 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see . - */ - -#include -#include -#include -#include -#include -#include "config.h" - -#include -#include -#include -#include - -#include "osdep/io.h" - -#include "talloc.h" -#include "af.h" -#include "options/path.h" - -#define DEF_SZ 512 // default buffer size (in samples) -#define SHARED_FILE "mpv-af_export" /* default file name - (relative to ~/.mpv/ */ - -#define SIZE_HEADER (2 * sizeof(int) + sizeof(unsigned long long)) - -// Data for specific instances of this filter -typedef struct af_export_s -{ - unsigned long long count; // Used for sync - void* buf[AF_NCH]; // Buffers for storing the data before it is exported - int sz; // Size of buffer in samples - int wi; // Write index - int fd; // File descriptor to shared memory area - char* filename; // File to export data - uint8_t *mmap_area; // MMap shared area -} af_export_t; - - -/* Initialization and runtime control - af audio filter instance - cmd control command - arg argument -*/ -static int control(struct af_instance* af, int cmd, void* arg) -{ - af_export_t* s = af->priv; - switch (cmd){ - case AF_CONTROL_REINIT:{ - int i=0; - int mapsize; - - // Free previous buffers - free(s->buf[0]); - - // unmap previous area - if(s->mmap_area) - munmap(s->mmap_area, SIZE_HEADER + (af->data->bps*s->sz*af->data->nch)); - // close previous file descriptor - if(s->fd) - close(s->fd); - - // Accept only int16_t as input format (which sucks) - mp_audio_copy_config(af->data, (struct mp_audio*)arg); - mp_audio_set_format(af->data, AF_FORMAT_S16); - - // Allocate new buffers (as one continuous block) - s->buf[0] = calloc(s->sz*af->data->nch, af->data->bps); - if(NULL == s->buf[0]) { - MP_FATAL(af, "Out of memory\n"); - return AF_ERROR; - } - for(i = 1; i < af->data->nch; i++) - s->buf[i] = (uint8_t *)s->buf[0] + i*s->sz*af->data->bps; - - if (!s->filename) { - MP_FATAL(af, "No filename set.\n"); - return AF_ERROR; - } - - // Init memory mapping - s->fd = open(s->filename, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0640); - MP_INFO(af, "Exporting to file: %s\n", s->filename); - if(s->fd < 0) { - MP_FATAL(af, "Could not open/create file: %s\n", - s->filename); - return AF_ERROR; - } - - // header + buffer - mapsize = (SIZE_HEADER + (af->data->bps * s->sz * af->data->nch)); - - // grow file to needed size - for(i = 0; i < mapsize; i++){ - char null = 0; - write(s->fd, (void*) &null, 1); - } - - // mmap size - s->mmap_area = mmap(0, mapsize, PROT_READ|PROT_WRITE,MAP_SHARED, s->fd, 0); - if(s->mmap_area == NULL) - MP_FATAL(af, "Could not mmap file %s\n", s->filename); - MP_INFO(af, "Memory mapped to file: %s (%p)\n", - s->filename, s->mmap_area); - - // Initialize header - *((int*)s->mmap_area) = af->data->nch; - *((int*)s->mmap_area + 1) = s->sz * af->data->bps * af->data->nch; - msync(s->mmap_area, mapsize, MS_ASYNC); - - // Use test_output to return FALSE if necessary - return af_test_output(af, (struct mp_audio*)arg); - } - } - return AF_UNKNOWN; -} - -/* Free allocated memory and clean up other stuff too. - af audio filter instance -*/ -static void uninit( struct af_instance* af ) -{ - af_export_t* s = af->priv; - - free(s->buf[0]); - - // Free mmaped area - if(s->mmap_area) - munmap(s->mmap_area, sizeof(af_export_t)); - - if(s->fd > -1) - close(s->fd); -} - -/* Filter data through filter - af audio filter instance - data audio data -*/ -static int filter(struct af_instance *af, struct mp_audio *data) -{ - if (!data) - return 0; - struct mp_audio* c = data; // Current working data - af_export_t* s = af->priv; // Setup for this instance - int16_t* a = c->planes[0]; // Incoming sound - int nch = c->nch; // Number of channels - int len = c->samples*c->nch; // Number of sample in data chunk - int sz = s->sz; // buffer size (in samples) - int flag = 0; // Set to 1 if buffer is filled - - int ch, i; - - // Fill all buffers - for(ch = 0; ch < nch; ch++){ - int wi = s->wi; // Reset write index - int16_t* b = s->buf[ch]; // Current buffer - - // Copy data to export buffers - for(i = ch; i < len; i += nch){ - b[wi++] = a[i]; - if(wi >= sz){ // Don't write outside the end of the buffer - flag = 1; - break; - } - } - s->wi = wi % s->sz; - } - - // Export buffer to mmaped area - if(flag){ - // update buffer in mapped area - memcpy(s->mmap_area + SIZE_HEADER, s->buf[0], sz * c->bps * nch); - s->count++; // increment counter (to sync) - memcpy(s->mmap_area + SIZE_HEADER - sizeof(s->count), - &(s->count), sizeof(s->count)); - } - - af_add_output_frame(af, data); - return 0; -} - -/* Allocate memory and set function pointers - af audio filter instance - returns AF_OK or AF_ERROR -*/ -static int af_open( struct af_instance* af ) -{ - af->control = control; - af->uninit = uninit; - af->filter_frame = filter; - af_export_t *priv = af->priv; - - if (!priv->filename || !priv->filename[0]) { - MP_FATAL(af, "no export filename given"); - return AF_ERROR; - } - - return AF_OK; -} - -#define OPT_BASE_STRUCT af_export_t -const struct af_info af_info_export = { - .info = "Sound export filter", - .name = "export", - .open = af_open, - .priv_size = sizeof(af_export_t), - .options = (const struct m_option[]) { - OPT_STRING("filename", filename, 0), - OPT_INTRANGE("buffersamples", sz, 0, 1, 2048, OPTDEF_INT(DEF_SZ)), - {0} - }, -}; diff --git a/audio/filter/af_extrastereo.c b/audio/filter/af_extrastereo.c deleted file mode 100644 index 49222ebfdc..0000000000 --- a/audio/filter/af_extrastereo.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2004 Alex Beregszaszi & Pierre Lombard - * - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpv 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see . - */ - -#include -#include -#include - -#include -#include -#include - -#include "common/common.h" -#include "af.h" - -// Data for specific instances of this filter -typedef struct af_extrastereo_s -{ - float mul; -}af_extrastereo_t; - -// Initialization and runtime control -static int control(struct af_instance* af, int cmd, void* arg) -{ - switch(cmd){ - case AF_CONTROL_REINIT:{ - // Sanity check - if(!arg) return AF_ERROR; - - mp_audio_copy_config(af->data, (struct mp_audio*)arg); - mp_audio_force_interleaved_format(af->data); - mp_audio_set_num_channels(af->data, 2); - if (af->data->format != AF_FORMAT_FLOAT) - mp_audio_set_format(af->data, AF_FORMAT_S16); - - return af_test_output(af,(struct mp_audio*)arg); - } - } - return AF_UNKNOWN; -} - -// Filter data through filter -static void play_s16(af_extrastereo_t *s, struct mp_audio* data) -{ - register int i = 0; - int16_t *a = (int16_t*)data->planes[0]; // Audio data - int len = data->samples*data->nch; // Number of samples - int avg, l, r; - - for (i = 0; i < len; i+=2) - { - avg = (a[i] + a[i + 1]) / 2; - - l = avg + (int)(s->mul * (a[i] - avg)); - r = avg + (int)(s->mul * (a[i + 1] - avg)); - - a[i] = MPCLAMP(l, SHRT_MIN, SHRT_MAX); - a[i + 1] = MPCLAMP(r, SHRT_MIN, SHRT_MAX); - } -} - -static void play_float(af_extrastereo_t *s, struct mp_audio* data) -{ - register int i = 0; - float *a = (float*)data->planes[0]; // Audio data - int len = data->samples * data->nch; // Number of samples - float avg, l, r; - - for (i = 0; i < len; i+=2) - { - avg = (a[i] + a[i + 1]) / 2; - - l = avg + (s->mul * (a[i] - avg)); - r = avg + (s->mul * (a[i + 1] - avg)); - - a[i] = af_softclip(l); - a[i + 1] = af_softclip(r); - } -} - -static int filter_frame(struct af_instance *af, struct mp_audio *data) -{ - if (!data) - return 0; - if (af_make_writeable(af, data) < 0) { - talloc_free(data); - return -1; - } - if (data->format == AF_FORMAT_FLOAT) { - play_float(af->priv, data); - } else { - play_s16(af->priv, data); - } - af_add_output_frame(af, data); - return 0; -} - -// Allocate memory and set function pointers -static int af_open(struct af_instance* af){ - af->control=control; - af->filter_frame = filter_frame; - - return AF_OK; -} - -#define OPT_BASE_STRUCT af_extrastereo_t -const struct af_info af_info_extrastereo = { - .info = "Increase difference between audio channels", - .name = "extrastereo", - .flags = AF_FLAGS_NOT_REENTRANT, - .open = af_open, - .priv_size = sizeof(af_extrastereo_t), - .options = (const struct m_option[]) { - OPT_FLOAT("mul", mul, 0, OPTDEF_FLOAT(2.5)), - {0} - }, -}; diff --git a/audio/filter/af_hrtf.c b/audio/filter/af_hrtf.c deleted file mode 100644 index 3c8a89c665..0000000000 --- a/audio/filter/af_hrtf.c +++ /dev/null @@ -1,670 +0,0 @@ -/* - * Experimental audio filter that mixes 5.1 and 5.1 with matrix - * encoded rear channels into headphone signal using FIR filtering - * with HRTF. - * - * Author: ylai - * - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpv 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see . - */ - -//#include -#include -#include -#include - -#include -#include - -#include "af.h" -#include "dsp.h" - -/* HRTF filter coefficients and adjustable parameters */ -#include "af_hrtf.h" - -typedef struct af_hrtf_s { - /* Lengths */ - int dlbuflen, hrflen, basslen; - /* L, C, R, Ls, Rs channels */ - float *lf, *rf, *lr, *rr, *cf, *cr; - const float *cf_ir, *af_ir, *of_ir, *ar_ir, *or_ir, *cr_ir; - int cf_o, af_o, of_o, ar_o, or_o, cr_o; - /* Bass */ - float *ba_l, *ba_r; - float *ba_ir; - /* Whether to matrix decode the rear center channel */ - int matrix_mode; - /* How to decode the input: - 0 = 5/5+1 channels - 1 = 2 channels - 2 = matrix encoded 2 channels */ - int decode_mode; - /* Full wave rectified (FWR) amplitudes and gain used to steer the - active matrix decoding of front channels (variable names - lpr/lmr means Lt + Rt, Lt - Rt) */ - float l_fwr, r_fwr, lpr_fwr, lmr_fwr; - float adapt_l_gain, adapt_r_gain, adapt_lpr_gain, adapt_lmr_gain; - /* Matrix input decoding require special FWR buffer, since the - decoding is done in place. */ - float *fwrbuf_l, *fwrbuf_r, *fwrbuf_lr, *fwrbuf_rr; - /* Rear channel delay buffer for matrix decoding */ - float *rear_dlbuf; - /* Full wave rectified amplitude and gain used to steer the active - matrix decoding of center rear channel */ - float lr_fwr, rr_fwr, lrprr_fwr, lrmrr_fwr; - float adapt_lr_gain, adapt_rr_gain; - float adapt_lrprr_gain, adapt_lrmrr_gain; - /* Cyclic position on the ring buffer */ - int cyc_pos; - int print_flag; - int mode; -} af_hrtf_t; - -/* 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 af_filter_fir(nk, sx + k, sk); - else - return af_filter_fir(nk + k - nx, sx, sk + nx - k) + - af_filter_fir(nx - k, sx + k, sk); -} - -/* 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; -} - -/* 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 inline void matrix_decode(short *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; - -#if 0 - static int counter = 0; - static FILE *fp_out; - - if(counter == 0) - fp_out = fopen("af_hrtf.log", "w"); - if(counter % 240 == 0) - fprintf(fp_out, "%g %g %g %g %g ", counter * (1.0 / 48000), - l_gain, r_gain, lpr_gain, lmr_gain); -#endif - - /*** 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 s0und 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; -#if 0 - if(counter % 240 == 0) - fprintf(fp_out, "%g %g %g %g %g\n", - *adapt_l_gain, *adapt_r_gain, - *adapt_lpr_gain, *adapt_lmr_gain, - c_gain); - counter++; -#endif -} - -static inline void update_ch(af_hrtf_t *s, short *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[2]) - fabs(s->fwrbuf_lr[fwr_pos]); - s->rr_fwr += abs(in[3]) - fabs(s->fwrbuf_rr[fwr_pos]); - s->lrprr_fwr += abs(in[2] + in[3]) - - fabs(s->fwrbuf_lr[fwr_pos] + s->fwrbuf_rr[fwr_pos]); - s->lrmrr_fwr += abs(in[2] - in[3]) - - 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[4]; - s->rf[k] = in[1]; - s->fwrbuf_lr[k] = s->lr[k] = in[2]; - s->fwrbuf_rr[k] = s->rr[k] = in[3]; - 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. */ - // TODO: should this use lf/cf/rf etc. instead? - s->ba_l[k] = in[0]; - s->ba_r[k] = in[1]; - if (s->decode_mode == HRTF_MIX_51) { - s->ba_l[k] += in[4] + in[2]; - s->ba_r[k] += in[4] + in[3]; - } -} - -static void clear_coeff(af_hrtf_t *s, float *c) -{ - memset(c, 0, s->dlbuflen * sizeof(float)); -} - -static void reset(af_hrtf_t *s) -{ - clear_coeff(s, s->lf); - clear_coeff(s, s->rf); - clear_coeff(s, s->lr); - clear_coeff(s, s->rr); - clear_coeff(s, s->cf); - clear_coeff(s, s->cr); - clear_coeff(s, s->ba_l); - clear_coeff(s, s->ba_r); - clear_coeff(s, s->fwrbuf_l); - clear_coeff(s, s->fwrbuf_r); - clear_coeff(s, s->fwrbuf_lr); - clear_coeff(s, s->fwrbuf_rr); -} - -/* Initialization and runtime control */ -static int control(struct af_instance *af, int cmd, void* arg) -{ - af_hrtf_t *s = af->priv; - int test_output_res; - - switch(cmd) { - case AF_CONTROL_REINIT: - reset(s); - af->data->rate = 48000; - mp_audio_set_channels_old(af->data, ((struct mp_audio*)arg)->nch); - if(af->data->nch == 2) { - /* 2 channel input */ - if(s->decode_mode != HRTF_MIX_MATRIX2CH) { - /* Default behavior is stereo mixing. */ - s->decode_mode = HRTF_MIX_STEREO; - } - } else if (af->data->nch < 5) { - mp_audio_set_channels_old(af->data, 5); - } - mp_audio_set_format(af->data, AF_FORMAT_S16); - test_output_res = af_test_output(af, (struct mp_audio*)arg); - // after testing input set the real output format - mp_audio_set_num_channels(af->data, 2); - s->print_flag = 1; - return test_output_res; - case AF_CONTROL_RESET: - reset(s); - return AF_OK; - } - - return AF_UNKNOWN; -} - -/* Deallocate memory */ -static void uninit(struct af_instance *af) -{ - af_hrtf_t *s = af->priv; - - free(s->lf); - free(s->rf); - free(s->lr); - free(s->rr); - free(s->cf); - free(s->cr); - free(s->ba_l); - free(s->ba_r); - free(s->ba_ir); - free(s->fwrbuf_l); - free(s->fwrbuf_r); - free(s->fwrbuf_lr); - free(s->fwrbuf_rr); -} - -/* Filter data through filter - -Two "tricks" are used to compensate the "color" of the KEMAR data: - -1. The KEMAR data is refiltered to ensure that the front L, R channels -on the same side of the ear are equalized (especially in the high -frequencies). - -2. A bass compensation is introduced to ensure that 0-200 Hz are not -damped (without any real 3D acoustical image, however). -*/ -static int filter(struct af_instance *af, struct mp_audio *data) -{ - af_hrtf_t *s = af->priv; - - if (!data) - return 0; - struct mp_audio *outframe = - mp_audio_pool_get(af->out_pool, &af->fmt_out, data->samples); - if (!outframe) { - talloc_free(data); - return -1; - } - mp_audio_copy_attributes(outframe, data); - - short *in = data->planes[0]; // Input audio data - short *out = outframe->planes[0]; // Output audio data - short *end = in + data->samples * data->nch; // Loop end - float common, left, right, diff, left_b, right_b; - const int dblen = s->dlbuflen, hlen = s->hrflen, blen = s->basslen; - - if(s->print_flag) { - s->print_flag = 0; - switch (s->decode_mode) { - case HRTF_MIX_51: - MP_INFO(af, "Using HRTF to mix %s discrete surround into " - "L, R channels\n", s->matrix_mode ? "5+1" : "5"); - break; - case HRTF_MIX_STEREO: - MP_INFO(af, "Using HRTF to mix stereo into " - "L, R channels\n"); - break; - case HRTF_MIX_MATRIX2CH: - MP_INFO(af, "Using active matrix to decode 2 channel " - "input, HRTF to mix %s matrix surround into " - "L, R channels\n", "3/2"); - break; - default: - MP_WARN(af, "bogus decode_mode: %d\n", s->decode_mode); - break; - } - - if(s->matrix_mode) - MP_INFO(af, "Using active matrix to decode rear center " - "channel\n"); - } - - /* MPlayer's 5 channel layout (notation for the variable): - * - * 0: L (LF), 1: R (RF), 2: Ls (LR), 3: Rs (RR), 4: C (CF), matrix - * encoded: Cs (CR) - * - * or: L = left, C = center, R = right, F = front, R = rear - * - * Filter notation: - * - * CF - * OF AF - * Ear-> - * OR AR - * CR - * - * or: C = center, A = same side, O = opposite, F = front, R = rear - */ - - while(in < end) { - const int k = s->cyc_pos; - - update_ch(s, in, 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(in, k, 2, 3, 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: - /* make gcc happy */ - left = 0.0; - right = 0.0; - 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, s->ba_ir, k); - right_b = conv(dblen, blen, s->ba_r, s->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(data->nch >= 6) { - left += in[5] * M3_01DB; - right += in[5] * 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); - out[0] = av_clip_int16(left + diff); - out[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. */ - out[0] = av_clip_int16(left); - out[1] = av_clip_int16(right); - break; - } - - /* Next sample... */ - in = &in[data->nch]; - out = &out[af->data->nch]; - (s->cyc_pos)--; - if(s->cyc_pos < 0) - s->cyc_pos += dblen; - } - - talloc_free(data); - af_add_output_frame(af, outframe); - return 0; -} - -static int allocate(af_hrtf_t *s) -{ - if ((s->lf = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1; - if ((s->rf = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1; - if ((s->lr = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1; - if ((s->rr = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1; - if ((s->cf = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1; - if ((s->cr = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1; - if ((s->ba_l = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1; - if ((s->ba_r = malloc(s->dlbuflen * sizeof(float))) == NULL) return -1; - if ((s->fwrbuf_l = - malloc(s->dlbuflen * sizeof(float))) == NULL) return -1; - if ((s->fwrbuf_r = - malloc(s->dlbuflen * sizeof(float))) == NULL) return -1; - if ((s->fwrbuf_lr = - malloc(s->dlbuflen * sizeof(float))) == NULL) return -1; - if ((s->fwrbuf_rr = - malloc(s->dlbuflen * sizeof(float))) == NULL) return -1; - return 0; -} - -/* Allocate memory and set function pointers */ -static int af_open(struct af_instance* af) -{ - int i; - af_hrtf_t *s; - float fc; - - af->control = control; - af->uninit = uninit; - af->filter_frame = filter; - - s = af->priv; - - s->dlbuflen = DELAYBUFLEN; - s->hrflen = HRTFFILTLEN; - s->basslen = BASSFILTLEN; - - s->cyc_pos = s->dlbuflen - 1; - /* With a full (two axis) steering matrix decoder, s->matrix_mode - should not be enabled lightly (it will also steer the Ls, Rs - channels). */ - 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->print_flag = 1; - - if (allocate(s) != 0) { - MP_ERR(af, "Memory allocation error.\n"); - return AF_ERROR; - } - - for(i = 0; i < s->dlbuflen; i++) - s->lf[i] = s->rf[i] = s->lr[i] = s->rr[i] = s->cf[i] = - s->cr[i] = 0; - - s->lr_fwr = - s->rr_fwr = 0; - - 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)); - - if((s->ba_ir = malloc(s->basslen * sizeof(float))) == NULL) { - MP_ERR(af, "Memory allocation error.\n"); - return AF_ERROR; - } - fc = 2.0 * BASSFILTFREQ / (float)af->data->rate; - if(af_filter_design_fir(s->basslen, s->ba_ir, &fc, LP | KAISER, 4 * M_PI) == - -1) { - MP_ERR(af, "Unable to design low-pass " - "filter.\n"); - return AF_ERROR; - } - for(i = 0; i < s->basslen; i++) - s->ba_ir[i] *= BASSGAIN; - - return AF_OK; -} - -#define OPT_BASE_STRUCT af_hrtf_t -const struct af_info af_info_hrtf = { - .info = "HRTF Headphone", - .name = "hrtf", - .open = af_open, - .priv_size = sizeof(af_hrtf_t), - .options = (const struct m_option[]) { - OPT_CHOICE("mode", mode, 0, ({"m", 0}, {"s", 1}, {"0", 2})), - {0} - }, -}; diff --git a/audio/filter/af_hrtf.h b/audio/filter/af_hrtf.h deleted file mode 100644 index 9ba9858aaf..0000000000 --- a/audio/filter/af_hrtf.h +++ /dev/null @@ -1,510 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpv 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see . - */ - -#ifndef MPLAYER_AF_HRTF_H -#define MPLAYER_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 and Keith Martin - - - 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.000255185364508856