aboutsummaryrefslogtreecommitdiffstats
path: root/libavfilter/af_sofalizer.c
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2015-12-24 17:53:11 +0100
committerPaul B Mahol <onemda@gmail.com>2015-12-24 19:00:05 +0100
commit8cbb055760c725d0fb99fb759caabb5f4e37e340 (patch)
treed9689a88f5d40e2d34a97720c843fd162e5f0c58 /libavfilter/af_sofalizer.c
parent8dba3fb8fdcf06a51d27ae92321d713060e3c781 (diff)
downloadffmpeg-8cbb055760c725d0fb99fb759caabb5f4e37e340.tar.gz
avfilter/af_sofalizer: make virtual speaker positioning supports all channel layouts
Signed-off-by: Paul B Mahol <onemda@gmail.com>
Diffstat (limited to 'libavfilter/af_sofalizer.c')
-rw-r--r--libavfilter/af_sofalizer.c225
1 files changed, 53 insertions, 172 deletions
diff --git a/libavfilter/af_sofalizer.c b/libavfilter/af_sofalizer.c
index 76bf7deea8..6a24cbced8 100644
--- a/libavfilter/af_sofalizer.c
+++ b/libavfilter/af_sofalizer.c
@@ -363,155 +363,58 @@ static int get_speaker_pos(AVFilterContext *ctx,
{
struct SOFAlizerContext *s = ctx->priv;
uint64_t channels_layout = ctx->inputs[0]->channel_layout;
- float azim[10] = { 0 };
- float elev[10] = { 0 };
- int n_conv = ctx->inputs[0]->channels; /* get no. input channels */
+ float azim[16] = { 0 };
+ float elev[16] = { 0 };
+ int m, ch, n_conv = ctx->inputs[0]->channels; /* get no. input channels */
+
+ if (n_conv > 16)
+ return AVERROR(EINVAL);
s->lfe_channel = -1;
/* set speaker positions according to input channel configuration: */
- switch (channels_layout) {
- case AV_CH_LAYOUT_MONO:
- azim[0] = 0;
- break;
- case AV_CH_LAYOUT_2POINT1:
- s->lfe_channel = 2;
- case AV_CH_LAYOUT_STEREO:
- azim[0] = 30;
- azim[1] = 330;
- break;
- case AV_CH_LAYOUT_3POINT1:
- s->lfe_channel = 3;
- case AV_CH_LAYOUT_SURROUND:
- azim[0] = 30;
- azim[1] = 330;
- azim[2] = 0;
- break;
- case AV_CH_LAYOUT_2_1:
- azim[0] = 30;
- azim[1] = 330;
- azim[2] = 180;
- break;
- case AV_CH_LAYOUT_2_2:
- azim[0] = 30;
- azim[1] = 330;
- azim[2] = 90;
- azim[3] = 270;
- break;
- case AV_CH_LAYOUT_QUAD:
- azim[0] = 30;
- azim[1] = 330;
- azim[2] = 120;
- azim[3] = 240;
- break;
- case AV_CH_LAYOUT_4POINT1:
- s->lfe_channel = 3;
- azim[0] = 30;
- azim[1] = 330;
- azim[2] = 0;
- azim[4] = 180;
- break;
- case AV_CH_LAYOUT_4POINT0:
- azim[0] = 30;
- azim[1] = 330;
- azim[2] = 0;
- azim[3] = 180;
- break;
- case AV_CH_LAYOUT_5POINT1:
- s->lfe_channel = 3;
- azim[0] = 30;
- azim[1] = 330;
- azim[2] = 0;
- azim[4] = 90;
- azim[5] = 270;
- break;
- case AV_CH_LAYOUT_5POINT0:
- azim[0] = 30;
- azim[1] = 330;
- azim[2] = 0;
- azim[3] = 90;
- azim[4] = 270;
- break;
- case AV_CH_LAYOUT_5POINT1_BACK:
- s->lfe_channel = 3;
- azim[0] = 30;
- azim[1] = 330;
- azim[2] = 0;
- azim[4] = 120;
- azim[5] = 240;
- break;
- case AV_CH_LAYOUT_5POINT0_BACK:
- azim[0] = 30;
- azim[1] = 330;
- azim[2] = 0;
- azim[3] = 120;
- azim[4] = 240;
- break;
- case AV_CH_LAYOUT_6POINT1:
- s->lfe_channel = 3;
- azim[0] = 30;
- azim[1] = 330;
- azim[2] = 0;
- azim[4] = 180;
- azim[5] = 90;
- azim[6] = 270;
- break;
- case AV_CH_LAYOUT_6POINT0:
- azim[0] = 30;
- azim[1] = 330;
- azim[2] = 0;
- azim[3] = 180;
- azim[4] = 90;
- azim[5] = 270;
- break;
- case AV_CH_LAYOUT_6POINT1_BACK:
- s->lfe_channel = 3;
- azim[0] = 30;
- azim[1] = 330;
- azim[2] = 0;
- azim[4] = 120;
- azim[5] = 240;
- azim[6] = 180;
- break;
- case AV_CH_LAYOUT_HEXAGONAL:
- azim[0] = 30;
- azim[1] = 330;
- azim[2] = 0;
- azim[3] = 120;
- azim[4] = 240;
- azim[5] = 180;
- break;
- case AV_CH_LAYOUT_7POINT1:
- s->lfe_channel = 3;
- azim[0] = 30;
- azim[1] = 330;
- azim[2] = 0;
- azim[4] = 150;
- azim[5] = 210;
- azim[6] = 90;
- azim[7] = 270;
- break;
- case AV_CH_LAYOUT_7POINT0:
- azim[0] = 30;
- azim[1] = 330;
- azim[2] = 0;
- azim[3] = 150;
- azim[4] = 210;
- azim[5] = 90;
- azim[6] = 270;
- break;
- case AV_CH_LAYOUT_OCTAGONAL:
- azim[0] = 30;
- azim[1] = 330;
- azim[2] = 0;
- azim[3] = 150;
- azim[4] = 210;
- azim[5] = 180;
- azim[6] = 90;
- azim[7] = 270;
- break;
- default:
- return -1;
+ for (m = 0, ch = 0; ch < n_conv && m < 64; m++) {
+ uint64_t mask = channels_layout & (1 << m);
+
+ switch (mask) {
+ case AV_CH_FRONT_LEFT: azim[ch] = 30; break;
+ case AV_CH_FRONT_RIGHT: azim[ch] = 330; break;
+ case AV_CH_FRONT_CENTER: azim[ch] = 0; break;
+ case AV_CH_LOW_FREQUENCY:
+ case AV_CH_LOW_FREQUENCY_2: s->lfe_channel = ch; break;
+ case AV_CH_BACK_LEFT: azim[ch] = 150; break;
+ case AV_CH_BACK_RIGHT: azim[ch] = 210; break;
+ case AV_CH_BACK_CENTER: azim[ch] = 180; break;
+ case AV_CH_SIDE_LEFT: azim[ch] = 90; break;
+ case AV_CH_SIDE_RIGHT: azim[ch] = 270; break;
+ case AV_CH_FRONT_LEFT_OF_CENTER: azim[ch] = 15; break;
+ case AV_CH_FRONT_RIGHT_OF_CENTER: azim[ch] = 345; break;
+ case AV_CH_TOP_CENTER: azim[ch] = 0;
+ elev[ch] = 90; break;
+ case AV_CH_TOP_FRONT_LEFT: azim[ch] = 30;
+ elev[ch] = 45; break;
+ case AV_CH_TOP_FRONT_CENTER: azim[ch] = 0;
+ elev[ch] = 45; break;
+ case AV_CH_TOP_FRONT_RIGHT: azim[ch] = 330;
+ elev[ch] = 45; break;
+ case AV_CH_TOP_BACK_LEFT: azim[ch] = 150;
+ elev[ch] = 45; break;
+ case AV_CH_TOP_BACK_RIGHT: azim[ch] = 210;
+ elev[ch] = 45; break;
+ case AV_CH_TOP_BACK_CENTER: azim[ch] = 180;
+ elev[ch] = 45; break;
+ case AV_CH_WIDE_LEFT: azim[ch] = 90; break;
+ case AV_CH_WIDE_RIGHT: azim[ch] = 270; break;
+ case AV_CH_SURROUND_DIRECT_LEFT: azim[ch] = 90; break;
+ case AV_CH_SURROUND_DIRECT_RIGHT: azim[ch] = 270; break;
+ case AV_CH_STEREO_LEFT: azim[ch] = 90; break;
+ case AV_CH_STEREO_RIGHT: azim[ch] = 270; break;
+ case 0: break;
+ default:
+ return AVERROR(EINVAL);
+ }
+ if (mask)
+ ch++;
}
memcpy(speaker_azim, azim, n_conv * sizeof(float));
@@ -622,7 +525,7 @@ static int sofalizer_convolute(AVFilterContext *ctx, void *arg, int jobnr, int n
const int buffer_length = s->buffer_length;
/* -1 for AND instead of MODULO (applied to powers of 2): */
const uint32_t modulo = (uint32_t)buffer_length - 1;
- float *buffer[10]; /* holds ringbuffer for each input channel */
+ float *buffer[16]; /* holds ringbuffer for each input channel */
int wr = *write;
int read;
int i, l;
@@ -846,28 +749,6 @@ static int query_formats(AVFilterContext *ctx)
AVFilterFormats *formats = NULL;
AVFilterChannelLayouts *layouts = NULL;
int ret, sample_rates[] = { 48000, -1 };
- static const uint64_t channel_layouts[] = { AV_CH_LAYOUT_MONO,
- AV_CH_LAYOUT_STEREO,
- AV_CH_LAYOUT_2POINT1,
- AV_CH_LAYOUT_SURROUND,
- AV_CH_LAYOUT_2_1,
- AV_CH_LAYOUT_4POINT0,
- AV_CH_LAYOUT_QUAD,
- AV_CH_LAYOUT_2_2,
- AV_CH_LAYOUT_3POINT1,
- AV_CH_LAYOUT_5POINT0_BACK,
- AV_CH_LAYOUT_5POINT0,
- AV_CH_LAYOUT_4POINT1,
- AV_CH_LAYOUT_5POINT1_BACK,
- AV_CH_LAYOUT_5POINT1,
- AV_CH_LAYOUT_6POINT0,
- AV_CH_LAYOUT_HEXAGONAL,
- AV_CH_LAYOUT_6POINT1,
- AV_CH_LAYOUT_6POINT1_BACK,
- AV_CH_LAYOUT_7POINT0,
- AV_CH_LAYOUT_7POINT1,
- AV_CH_LAYOUT_OCTAGONAL,
- 0, };
ret = ff_add_format(&formats, AV_SAMPLE_FMT_FLT);
if (ret)
@@ -876,7 +757,7 @@ static int query_formats(AVFilterContext *ctx)
if (ret)
return ret;
- layouts = ff_make_formatu64_list(channel_layouts);
+ layouts = ff_all_channel_layouts();
if (!layouts)
return AVERROR(ENOMEM);
@@ -906,8 +787,8 @@ static int load_data(AVFilterContext *ctx, int azim, int elev, float radius)
const int n_samples = s->sofa.n_samples;
int n_conv = s->n_conv; /* no. channels to convolve */
int n_fft = s->n_fft;
- int delay_l[10]; /* broadband delay for each IR */
- int delay_r[10];
+ int delay_l[16]; /* broadband delay for each IR */
+ int delay_r[16];
int nb_input_channels = ctx->inputs[0]->channels; /* no. input channels */
float gain_lin = expf((s->gain - 3 * nb_input_channels) / 20 * M_LN10); /* gain - 3dB/channel */
FFTComplex *data_hrtf_l = NULL;
@@ -917,7 +798,7 @@ static int load_data(AVFilterContext *ctx, int azim, int elev, float radius)
float *data_ir_l = NULL;
float *data_ir_r = NULL;
int offset = 0; /* used for faster pointer arithmetics in for-loop */
- int m[10]; /* measurement index m of IR closest to required source positions */
+ int m[16]; /* measurement index m of IR closest to required source positions */
int i, j, azim_orig = azim, elev_orig = elev;
if (!s->sofa.ncid) { /* if an invalid SOFA file has been selected */