From 530fc345ec73390f20e40738192acfb5633800bd Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 25 Dec 2018 22:32:05 +0100 Subject: [PATCH] avfilter/af_sofalizer: add fltp sample format support --- libavfilter/af_sofalizer.c | 89 ++++++++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 28 deletions(-) diff --git a/libavfilter/af_sofalizer.c b/libavfilter/af_sofalizer.c index b09c6e024b..3b60969d68 100644 --- a/libavfilter/af_sofalizer.c +++ b/libavfilter/af_sofalizer.c @@ -340,8 +340,10 @@ static int sofalizer_convolute(AVFilterContext *ctx, void *arg, int jobnr, int n float *temp_src = td->temp_src[jobnr]; const int ir_samples = s->sofa.ir_samples; /* length of one IR */ const int n_samples = s->sofa.n_samples; - const float *src = (const float *)in->data[0]; /* get pointer to audio input buffer */ - float *dst = (float *)out->data[0]; /* get pointer to audio output buffer */ + const int planar = in->format == AV_SAMPLE_FMT_FLTP; + const int mult = 1 + !planar; + const float *src = (const float *)in->extended_data[0]; /* get pointer to audio input buffer */ + float *dst = (float *)out->extended_data[jobnr * planar]; /* get pointer to audio output buffer */ const int in_channels = s->n_conv; /* number of input channels */ /* ring buffer length is: longest IR plus max. delay -> next power of 2 */ const int buffer_length = s->buffer_length; @@ -352,7 +354,9 @@ static int sofalizer_convolute(AVFilterContext *ctx, void *arg, int jobnr, int n int read; int i, l; - dst += offset; + if (!planar) + dst += offset; + for (l = 0; l < in_channels; l++) { /* get starting address of ringbuffer for each input channel */ buffer[l] = ringbuffer + l * buffer_length; @@ -362,9 +366,18 @@ static int sofalizer_convolute(AVFilterContext *ctx, void *arg, int jobnr, int n const float *temp_ir = ir; /* using same set of IRs for each sample */ dst[0] = 0; - for (l = 0; l < in_channels; l++) { - /* write current input sample to ringbuffer (for each channel) */ - buffer[l][wr] = src[l]; + if (planar) { + for (l = 0; l < in_channels; l++) { + const float *srcp = (const float *)in->extended_data[l]; + + /* write current input sample to ringbuffer (for each channel) */ + buffer[l][wr] = srcp[i]; + } + } else { + for (l = 0; l < in_channels; l++) { + /* write current input sample to ringbuffer (for each channel) */ + buffer[l][wr] = src[l]; + } } /* loop goes through all channels to be convolved */ @@ -374,7 +387,7 @@ static int sofalizer_convolute(AVFilterContext *ctx, void *arg, int jobnr, int n if (l == s->lfe_channel) { /* LFE is an input channel but requires no convolution */ /* apply gain to LFE signal and add to output buffer */ - *dst += *(buffer[s->lfe_channel] + wr) * s->gain_lfe; + dst[0] += *(buffer[s->lfe_channel] + wr) * s->gain_lfe; temp_ir += n_samples; continue; } @@ -403,7 +416,7 @@ static int sofalizer_convolute(AVFilterContext *ctx, void *arg, int jobnr, int n n_clippings[0]++; /* move output buffer pointer by +2 to get to next sample of processed channel: */ - dst += 2; + dst += mult; src += in_channels; wr = (wr + 1) & modulo; /* update ringbuffer write position */ } @@ -424,8 +437,9 @@ static int sofalizer_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, int *n_clippings = &td->n_clippings[jobnr]; float *ringbuffer = td->ringbuffer[jobnr]; const int n_samples = s->sofa.n_samples; /* length of one IR */ - const float *src = (const float *)in->data[0]; /* get pointer to audio input buffer */ - float *dst = (float *)out->data[0]; /* get pointer to audio output buffer */ + const int planar = in->format == AV_SAMPLE_FMT_FLTP; + const int mult = 1 + !planar; + float *dst = (float *)out->extended_data[jobnr * planar]; /* get pointer to audio output buffer */ const int in_channels = s->n_conv; /* number of input channels */ /* ring buffer length is: longest IR plus max. delay -> next power of 2 */ const int buffer_length = s->buffer_length; @@ -443,14 +457,15 @@ static int sofalizer_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, int n_read; int i, j; - dst += offset; + if (!planar) + dst += offset; /* find minimum between number of samples and output buffer length: * (important, if one IR is longer than the output buffer) */ n_read = FFMIN(s->sofa.n_samples, in->nb_samples); for (j = 0; j < n_read; j++) { /* initialize output buf with saved signal from overflow buf */ - dst[2 * j] = ringbuffer[wr]; + dst[mult * j] = ringbuffer[wr]; ringbuffer[wr] = 0.0; /* re-set read samples to zero */ /* update ringbuffer read/write position */ wr = (wr + 1) & modulo; @@ -458,17 +473,26 @@ static int sofalizer_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, /* initialize rest of output buffer with 0 */ for (j = n_read; j < in->nb_samples; j++) { - dst[2 * j] = 0; + dst[mult * j] = 0; } /* fill FFT accumulation with 0 */ memset(fft_acc, 0, sizeof(FFTComplex) * n_fft); for (i = 0; i < n_conv; i++) { + const float *src = (const float *)in->extended_data[i * planar]; /* get pointer to audio input buffer */ + if (i == s->lfe_channel) { /* LFE */ - for (j = 0; j < in->nb_samples; j++) { - /* apply gain to LFE signal and add to output buffer */ - dst[2 * j] += src[i + j * in_channels] * s->gain_lfe; + if (in->format == AV_SAMPLE_FMT_FLT) { + for (j = 0; j < in->nb_samples; j++) { + /* apply gain to LFE signal and add to output buffer */ + dst[2 * j] += src[i + j * in_channels] * s->gain_lfe; + } + } else { + for (j = 0; j < in->nb_samples; j++) { + /* apply gain to LFE signal and add to output buffer */ + dst[j] += src[j] * s->gain_lfe; + } } continue; } @@ -480,10 +504,18 @@ static int sofalizer_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, /* fill FFT input with 0 (we want to zero-pad) */ memset(fft_in, 0, sizeof(FFTComplex) * n_fft); - for (j = 0; j < in->nb_samples; j++) { - /* prepare input for FFT */ - /* write all samples of current input channel to FFT input array */ - fft_in[j].re = src[j * in_channels + i]; + if (in->format == AV_SAMPLE_FMT_FLT) { + for (j = 0; j < in->nb_samples; j++) { + /* prepare input for FFT */ + /* write all samples of current input channel to FFT input array */ + fft_in[j].re = src[j * in_channels + i]; + } + } else { + for (j = 0; j < in->nb_samples; j++) { + /* prepare input for FFT */ + /* write all samples of current input channel to FFT input array */ + fft_in[j].re = src[j]; + } } /* transform input signal of current channel to frequency domain */ @@ -508,7 +540,7 @@ static int sofalizer_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, for (j = 0; j < in->nb_samples; j++) { /* write output signal of current channel to output buffer */ - dst[2 * j] += fft_acc[j].re * fft_scale; + dst[mult * j] += fft_acc[j].re * fft_scale; } for (j = 0; j < n_samples - 1; j++) { /* overflow length is IR length - 1 */ @@ -521,12 +553,9 @@ static int sofalizer_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, /* go through all samples of current output buffer: count clippings */ for (i = 0; i < out->nb_samples; i++) { /* clippings counter */ - if (fabsf(dst[0]) > 1) { /* if current output sample > 1 */ + if (fabsf(dst[i * mult]) > 1) { /* if current output sample > 1 */ n_clippings[0]++; } - - /* move output buffer pointer by +2 to get to next sample of processed channel: */ - dst += 2; } /* remember read/write position in ringbuffer for next call */ @@ -580,10 +609,14 @@ static int query_formats(AVFilterContext *ctx) AVFilterFormats *formats = NULL; AVFilterChannelLayouts *layouts = NULL; int ret, sample_rates[] = { 48000, -1 }; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE + }; - ret = ff_add_format(&formats, AV_SAMPLE_FMT_FLT); - if (ret) - return ret; + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); ret = ff_set_common_formats(ctx, formats); if (ret) return ret;