diff options
Diffstat (limited to 'audio')
-rw-r--r-- | audio/audio.c | 7 | ||||
-rw-r--r-- | audio/audio.h | 1 | ||||
-rw-r--r-- | audio/filter/af.c | 23 | ||||
-rw-r--r-- | audio/filter/af_center.c | 104 | ||||
-rw-r--r-- | audio/filter/af_export.c | 237 | ||||
-rw-r--r-- | audio/filter/af_extrastereo.c | 132 | ||||
-rw-r--r-- | audio/filter/af_hrtf.c | 670 | ||||
-rw-r--r-- | audio/filter/af_hrtf.h | 510 | ||||
-rw-r--r-- | audio/filter/af_karaoke.c | 86 | ||||
-rw-r--r-- | audio/filter/af_ladspa.c | 851 | ||||
-rw-r--r-- | audio/filter/af_sinesuppress.c | 117 | ||||
-rw-r--r-- | audio/filter/af_sub.c | 148 | ||||
-rw-r--r-- | audio/filter/af_surround.c | 246 | ||||
-rw-r--r-- | audio/filter/af_sweep.c | 92 | ||||
-rw-r--r-- | audio/filter/dsp.h | 31 | ||||
-rw-r--r-- | audio/filter/filter.c | 359 | ||||
-rw-r--r-- | audio/filter/filter.h | 74 | ||||
-rw-r--r-- | audio/filter/window.c | 212 | ||||
-rw-r--r-- | audio/filter/window.h | 42 |
19 files changed, 0 insertions, 3942 deletions
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 <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#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;i<len;i+=nch){ - // Average left and right - a[i+ch] = (a[i]/2) + (a[i+1]/2); - } - - 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_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 <gustavo.barbieri@ic.unicamp.br> - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <inttypes.h> -#include <unistd.h> -#include "config.h" - -#include <sys/types.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#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 <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <inttypes.h> -#include <math.h> -#include <limits.h> - -#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 <http://www.gnu.org/licenses/>. - */ - -//#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <inttypes.h> - -#include <math.h> -#include <libavutil/common.h> - -#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_aud |