diff options
author | Paul B Mahol <onemda@gmail.com> | 2015-12-24 17:53:11 +0100 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2015-12-24 19:00:05 +0100 |
commit | 8cbb055760c725d0fb99fb759caabb5f4e37e340 (patch) | |
tree | d9689a88f5d40e2d34a97720c843fd162e5f0c58 /libavfilter/af_sofalizer.c | |
parent | 8dba3fb8fdcf06a51d27ae92321d713060e3c781 (diff) | |
download | ffmpeg-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.c | 225 |
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 */ |