FFmpeg  4.2.2
af_sofalizer.c
Go to the documentation of this file.
1 /*****************************************************************************
2  * sofalizer.c : SOFAlizer filter for virtual binaural acoustics
3  *****************************************************************************
4  * Copyright (C) 2013-2015 Andreas Fuchs, Wolfgang Hrauda,
5  * Acoustics Research Institute (ARI), Vienna, Austria
6  *
7  * Authors: Andreas Fuchs <andi.fuchs.mail@gmail.com>
8  * Wolfgang Hrauda <wolfgang.hrauda@gmx.at>
9  *
10  * SOFAlizer project coordinator at ARI, main developer of SOFA:
11  * Piotr Majdak <piotr@majdak.at>
12  *
13  * This program is free software; you can redistribute it and/or modify it
14  * under the terms of the GNU Lesser General Public License as published by
15  * the Free Software Foundation; either version 2.1 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU Lesser General Public License for more details.
22  *
23  * You should have received a copy of the GNU Lesser General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26  *****************************************************************************/
27 
28 #include <math.h>
29 #include <mysofa.h>
30 
31 #include "libavcodec/avfft.h"
32 #include "libavutil/avstring.h"
34 #include "libavutil/float_dsp.h"
35 #include "libavutil/intmath.h"
36 #include "libavutil/opt.h"
37 #include "avfilter.h"
38 #include "filters.h"
39 #include "internal.h"
40 #include "audio.h"
41 
42 #define TIME_DOMAIN 0
43 #define FREQUENCY_DOMAIN 1
44 
45 typedef struct MySofa { /* contains data of one SOFA file */
46  struct MYSOFA_HRTF *hrtf;
47  struct MYSOFA_LOOKUP *lookup;
48  struct MYSOFA_NEIGHBORHOOD *neighborhood;
49  int ir_samples; /* length of one impulse response (IR) */
50  int n_samples; /* ir_samples to next power of 2 */
51  float *lir, *rir; /* IRs (time-domain) */
52  float *fir;
53  int max_delay;
54 } MySofa;
55 
56 typedef struct VirtualSpeaker {
57  uint8_t set;
58  float azim;
59  float elev;
61 
62 typedef struct SOFAlizerContext {
63  const AVClass *class;
64 
65  char *filename; /* name of SOFA file */
66  MySofa sofa; /* contains data of the SOFA file */
67 
68  int sample_rate; /* sample rate from SOFA file */
69  float *speaker_azim; /* azimuth of the virtual loudspeakers */
70  float *speaker_elev; /* elevation of the virtual loudspeakers */
71  char *speakers_pos; /* custom positions of the virtual loudspeakers */
72  float lfe_gain; /* initial gain for the LFE channel */
73  float gain_lfe; /* gain applied to LFE channel */
74  int lfe_channel; /* LFE channel position in channel layout */
75 
76  int n_conv; /* number of channels to convolute */
77 
78  /* buffer variables (for convolution) */
79  float *ringbuffer[2]; /* buffers input samples, length of one buffer: */
80  /* no. input ch. (incl. LFE) x buffer_length */
81  int write[2]; /* current write position to ringbuffer */
82  int buffer_length; /* is: longest IR plus max. delay in all SOFA files */
83  /* then choose next power of 2 */
84  int n_fft; /* number of samples in one FFT block */
86 
87  /* netCDF variables */
88  int *delay[2]; /* broadband delay for each channel/IR to be convolved */
89 
90  float *data_ir[2]; /* IRs for all channels to be convolved */
91  /* (this excludes the LFE) */
92  float *temp_src[2];
93  FFTComplex *temp_fft[2]; /* Array to hold FFT values */
94  FFTComplex *temp_afft[2]; /* Array to accumulate FFT values prior to IFFT */
95 
96  /* control variables */
97  float gain; /* filter gain (in dB) */
98  float rotation; /* rotation of virtual loudspeakers (in degrees) */
99  float elevation; /* elevation of virtual loudspeakers (in deg.) */
100  float radius; /* distance virtual loudspeakers to listener (in metres) */
101  int type; /* processing type */
102  int framesize; /* size of buffer */
103  int normalize; /* should all IRs be normalized upon import ? */
104  int interpolate; /* should wanted IRs be interpolated from neighbors ? */
105  int minphase; /* should all IRs be minphased upon import ? */
106  float anglestep; /* neighbor search angle step, in agles */
107  float radstep; /* neighbor search radius step, in meters */
108 
109  VirtualSpeaker vspkrpos[64];
110 
111  FFTContext *fft[2], *ifft[2];
112  FFTComplex *data_hrtf[2];
113 
116 
117 static int close_sofa(struct MySofa *sofa)
118 {
119  if (sofa->neighborhood)
120  mysofa_neighborhood_free(sofa->neighborhood);
121  sofa->neighborhood = NULL;
122  if (sofa->lookup)
123  mysofa_lookup_free(sofa->lookup);
124  sofa->lookup = NULL;
125  if (sofa->hrtf)
126  mysofa_free(sofa->hrtf);
127  sofa->hrtf = NULL;
128  av_freep(&sofa->fir);
129 
130  return 0;
131 }
132 
133 static int preload_sofa(AVFilterContext *ctx, char *filename, int *samplingrate)
134 {
135  struct SOFAlizerContext *s = ctx->priv;
136  struct MYSOFA_HRTF *mysofa;
137  char *license;
138  int ret;
139 
140  mysofa = mysofa_load(filename, &ret);
141  s->sofa.hrtf = mysofa;
142  if (ret || !mysofa) {
143  av_log(ctx, AV_LOG_ERROR, "Can't find SOFA-file '%s'\n", filename);
144  return AVERROR(EINVAL);
145  }
146 
147  ret = mysofa_check(mysofa);
148  if (ret != MYSOFA_OK) {
149  av_log(ctx, AV_LOG_ERROR, "Selected SOFA file is invalid. Please select valid SOFA file.\n");
150  return ret;
151  }
152 
153  if (s->normalize)
154  mysofa_loudness(s->sofa.hrtf);
155 
156  if (s->minphase)
157  mysofa_minphase(s->sofa.hrtf, 0.01f);
158 
159  mysofa_tocartesian(s->sofa.hrtf);
160 
161  s->sofa.lookup = mysofa_lookup_init(s->sofa.hrtf);
162  if (s->sofa.lookup == NULL)
163  return AVERROR(EINVAL);
164 
165  if (s->interpolate)
166  s->sofa.neighborhood = mysofa_neighborhood_init_withstepdefine(s->sofa.hrtf,
167  s->sofa.lookup,
168  s->anglestep,
169  s->radstep);
170 
171  s->sofa.fir = av_calloc(s->sofa.hrtf->N * s->sofa.hrtf->R, sizeof(*s->sofa.fir));
172  if (!s->sofa.fir)
173  return AVERROR(ENOMEM);
174 
175  if (mysofa->DataSamplingRate.elements != 1)
176  return AVERROR(EINVAL);
177  av_log(ctx, AV_LOG_DEBUG, "Original IR length: %d.\n", mysofa->N);
178  *samplingrate = mysofa->DataSamplingRate.values[0];
179  license = mysofa_getAttribute(mysofa->attributes, (char *)"License");
180  if (license)
181  av_log(ctx, AV_LOG_INFO, "SOFA license: %s\n", license);
182 
183  return 0;
184 }
185 
186 static int parse_channel_name(char **arg, int *rchannel, char *buf)
187 {
188  int len, i, channel_id = 0;
189  int64_t layout, layout0;
190 
191  /* try to parse a channel name, e.g. "FL" */
192  if (av_sscanf(*arg, "%7[A-Z]%n", buf, &len)) {
193  layout0 = layout = av_get_channel_layout(buf);
194  /* channel_id <- first set bit in layout */
195  for (i = 32; i > 0; i >>= 1) {
196  if (layout >= 1LL << i) {
197  channel_id += i;
198  layout >>= i;
199  }
200  }
201  /* reject layouts that are not a single channel */
202  if (channel_id >= 64 || layout0 != 1LL << channel_id)
203  return AVERROR(EINVAL);
204  *rchannel = channel_id;
205  *arg += len;
206  return 0;
207  }
208  return AVERROR(EINVAL);
209 }
210 
211 static void parse_speaker_pos(AVFilterContext *ctx, int64_t in_channel_layout)
212 {
213  SOFAlizerContext *s = ctx->priv;
214  char *arg, *tokenizer, *p, *args = av_strdup(s->speakers_pos);
215 
216  if (!args)
217  return;
218  p = args;
219 
220  while ((arg = av_strtok(p, "|", &tokenizer))) {
221  char buf[8];
222  float azim, elev;
223  int out_ch_id;
224 
225  p = NULL;
226  if (parse_channel_name(&arg, &out_ch_id, buf)) {
227  av_log(ctx, AV_LOG_WARNING, "Failed to parse \'%s\' as channel name.\n", buf);
228  continue;
229  }
230  if (av_sscanf(arg, "%f %f", &azim, &elev) == 2) {
231  s->vspkrpos[out_ch_id].set = 1;
232  s->vspkrpos[out_ch_id].azim = azim;
233  s->vspkrpos[out_ch_id].elev = elev;
234  } else if (av_sscanf(arg, "%f", &azim) == 1) {
235  s->vspkrpos[out_ch_id].set = 1;
236  s->vspkrpos[out_ch_id].azim = azim;
237  s->vspkrpos[out_ch_id].elev = 0;
238  }
239  }
240 
241  av_free(args);
242 }
243 
245  float *speaker_azim, float *speaker_elev)
246 {
247  struct SOFAlizerContext *s = ctx->priv;
248  uint64_t channels_layout = ctx->inputs[0]->channel_layout;
249  float azim[16] = { 0 };
250  float elev[16] = { 0 };
251  int m, ch, n_conv = ctx->inputs[0]->channels; /* get no. input channels */
252 
253  if (n_conv > 16)
254  return AVERROR(EINVAL);
255 
256  s->lfe_channel = -1;
257 
258  if (s->speakers_pos)
259  parse_speaker_pos(ctx, channels_layout);
260 
261  /* set speaker positions according to input channel configuration: */
262  for (m = 0, ch = 0; ch < n_conv && m < 64; m++) {
263  uint64_t mask = channels_layout & (1ULL << m);
264 
265  switch (mask) {
266  case AV_CH_FRONT_LEFT: azim[ch] = 30; break;
267  case AV_CH_FRONT_RIGHT: azim[ch] = 330; break;
268  case AV_CH_FRONT_CENTER: azim[ch] = 0; break;
269  case AV_CH_LOW_FREQUENCY:
270  case AV_CH_LOW_FREQUENCY_2: s->lfe_channel = ch; break;
271  case AV_CH_BACK_LEFT: azim[ch] = 150; break;
272  case AV_CH_BACK_RIGHT: azim[ch] = 210; break;
273  case AV_CH_BACK_CENTER: azim[ch] = 180; break;
274  case AV_CH_SIDE_LEFT: azim[ch] = 90; break;
275  case AV_CH_SIDE_RIGHT: azim[ch] = 270; break;
276  case AV_CH_FRONT_LEFT_OF_CENTER: azim[ch] = 15; break;
277  case AV_CH_FRONT_RIGHT_OF_CENTER: azim[ch] = 345; break;
278  case AV_CH_TOP_CENTER: azim[ch] = 0;
279  elev[ch] = 90; break;
280  case AV_CH_TOP_FRONT_LEFT: azim[ch] = 30;
281  elev[ch] = 45; break;
282  case AV_CH_TOP_FRONT_CENTER: azim[ch] = 0;
283  elev[ch] = 45; break;
284  case AV_CH_TOP_FRONT_RIGHT: azim[ch] = 330;
285  elev[ch] = 45; break;
286  case AV_CH_TOP_BACK_LEFT: azim[ch] = 150;
287  elev[ch] = 45; break;
288  case AV_CH_TOP_BACK_RIGHT: azim[ch] = 210;
289  elev[ch] = 45; break;
290  case AV_CH_TOP_BACK_CENTER: azim[ch] = 180;
291  elev[ch] = 45; break;
292  case AV_CH_WIDE_LEFT: azim[ch] = 90; break;
293  case AV_CH_WIDE_RIGHT: azim[ch] = 270; break;
294  case AV_CH_SURROUND_DIRECT_LEFT: azim[ch] = 90; break;
295  case AV_CH_SURROUND_DIRECT_RIGHT: azim[ch] = 270; break;
296  case AV_CH_STEREO_LEFT: azim[ch] = 90; break;
297  case AV_CH_STEREO_RIGHT: azim[ch] = 270; break;
298  case 0: break;
299  default:
300  return AVERROR(EINVAL);
301  }
302 
303  if (s->vspkrpos[m].set) {
304  azim[ch] = s->vspkrpos[m].azim;
305  elev[ch] = s->vspkrpos[m].elev;
306  }
307 
308  if (mask)
309  ch++;
310  }
311 
312  memcpy(speaker_azim, azim, n_conv * sizeof(float));
313  memcpy(speaker_elev, elev, n_conv * sizeof(float));
314 
315  return 0;
316 
317 }
318 
319 typedef struct ThreadData {
320  AVFrame *in, *out;
321  int *write;
322  int **delay;
323  float **ir;
324  int *n_clippings;
325  float **ringbuffer;
326  float **temp_src;
327  FFTComplex **temp_fft;
328  FFTComplex **temp_afft;
329 } ThreadData;
330 
331 static int sofalizer_convolute(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
332 {
333  SOFAlizerContext *s = ctx->priv;
334  ThreadData *td = arg;
335  AVFrame *in = td->in, *out = td->out;
336  int offset = jobnr;
337  int *write = &td->write[jobnr];
338  const int *const delay = td->delay[jobnr];
339  const float *const ir = td->ir[jobnr];
340  int *n_clippings = &td->n_clippings[jobnr];
341  float *ringbuffer = td->ringbuffer[jobnr];
342  float *temp_src = td->temp_src[jobnr];
343  const int ir_samples = s->sofa.ir_samples; /* length of one IR */
344  const int n_samples = s->sofa.n_samples;
345  const int planar = in->format == AV_SAMPLE_FMT_FLTP;
346  const int mult = 1 + !planar;
347  const float *src = (const float *)in->extended_data[0]; /* get pointer to audio input buffer */
348  float *dst = (float *)out->extended_data[jobnr * planar]; /* get pointer to audio output buffer */
349  const int in_channels = s->n_conv; /* number of input channels */
350  /* ring buffer length is: longest IR plus max. delay -> next power of 2 */
351  const int buffer_length = s->buffer_length;
352  /* -1 for AND instead of MODULO (applied to powers of 2): */
353  const uint32_t modulo = (uint32_t)buffer_length - 1;
354  float *buffer[16]; /* holds ringbuffer for each input channel */
355  int wr = *write;
356  int read;
357  int i, l;
358 
359  if (!planar)
360  dst += offset;
361 
362  for (l = 0; l < in_channels; l++) {
363  /* get starting address of ringbuffer for each input channel */
364  buffer[l] = ringbuffer + l * buffer_length;
365  }
366 
367  for (i = 0; i < in->nb_samples; i++) {
368  const float *temp_ir = ir; /* using same set of IRs for each sample */
369 
370  dst[0] = 0;
371  if (planar) {
372  for (l = 0; l < in_channels; l++) {
373  const float *srcp = (const float *)in->extended_data[l];
374 
375  /* write current input sample to ringbuffer (for each channel) */
376  buffer[l][wr] = srcp[i];
377  }
378  } else {
379  for (l = 0; l < in_channels; l++) {
380  /* write current input sample to ringbuffer (for each channel) */
381  buffer[l][wr] = src[l];
382  }
383  }
384 
385  /* loop goes through all channels to be convolved */
386  for (l = 0; l < in_channels; l++) {
387  const float *const bptr = buffer[l];
388 
389  if (l == s->lfe_channel) {
390  /* LFE is an input channel but requires no convolution */
391  /* apply gain to LFE signal and add to output buffer */
392  dst[0] += *(buffer[s->lfe_channel] + wr) * s->gain_lfe;
393  temp_ir += n_samples;
394  continue;
395  }
396 
397  /* current read position in ringbuffer: input sample write position
398  * - delay for l-th ch. + diff. betw. IR length and buffer length
399  * (mod buffer length) */
400  read = (wr - delay[l] - (ir_samples - 1) + buffer_length) & modulo;
401 
402  if (read + ir_samples < buffer_length) {
403  memmove(temp_src, bptr + read, ir_samples * sizeof(*temp_src));
404  } else {
405  int len = FFMIN(n_samples - (read % ir_samples), buffer_length - read);
406 
407  memmove(temp_src, bptr + read, len * sizeof(*temp_src));
408  memmove(temp_src + len, bptr, (n_samples - len) * sizeof(*temp_src));
409  }
410 
411  /* multiply signal and IR, and add up the results */
412  dst[0] += s->fdsp->scalarproduct_float(temp_ir, temp_src, FFALIGN(ir_samples, 32));
413  temp_ir += n_samples;
414  }
415 
416  /* clippings counter */
417  if (fabsf(dst[0]) > 1)
418  n_clippings[0]++;
419 
420  /* move output buffer pointer by +2 to get to next sample of processed channel: */
421  dst += mult;
422  src += in_channels;
423  wr = (wr + 1) & modulo; /* update ringbuffer write position */
424  }
425 
426  *write = wr; /* remember write position in ringbuffer for next call */
427 
428  return 0;
429 }
430 
431 static int sofalizer_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
432 {
433  SOFAlizerContext *s = ctx->priv;
434  ThreadData *td = arg;
435  AVFrame *in = td->in, *out = td->out;
436  int offset = jobnr;
437  int *write = &td->write[jobnr];
438  FFTComplex *hrtf = s->data_hrtf[jobnr]; /* get pointers to current HRTF data */
439  int *n_clippings = &td->n_clippings[jobnr];
440  float *ringbuffer = td->ringbuffer[jobnr];
441  const int ir_samples = s->sofa.ir_samples; /* length of one IR */
442  const int planar = in->format == AV_SAMPLE_FMT_FLTP;
443  const int mult = 1 + !planar;
444  float *dst = (float *)out->extended_data[jobnr * planar]; /* get pointer to audio output buffer */
445  const int in_channels = s->n_conv; /* number of input channels */
446  /* ring buffer length is: longest IR plus max. delay -> next power of 2 */
447  const int buffer_length = s->buffer_length;
448  /* -1 for AND instead of MODULO (applied to powers of 2): */
449  const uint32_t modulo = (uint32_t)buffer_length - 1;
450  FFTComplex *fft_in = s->temp_fft[jobnr]; /* temporary array for FFT input/output data */
451  FFTComplex *fft_acc = s->temp_afft[jobnr];
452  FFTContext *ifft = s->ifft[jobnr];
453  FFTContext *fft = s->fft[jobnr];
454  const int n_conv = s->n_conv;
455  const int n_fft = s->n_fft;
456  const float fft_scale = 1.0f / s->n_fft;
457  FFTComplex *hrtf_offset;
458  int wr = *write;
459  int n_read;
460  int i, j;
461 
462  if (!planar)
463  dst += offset;
464 
465  /* find minimum between number of samples and output buffer length:
466  * (important, if one IR is longer than the output buffer) */
467  n_read = FFMIN(ir_samples, in->nb_samples);
468  for (j = 0; j < n_read; j++) {
469  /* initialize output buf with saved signal from overflow buf */
470  dst[mult * j] = ringbuffer[wr];
471  ringbuffer[wr] = 0.0f; /* re-set read samples to zero */
472  /* update ringbuffer read/write position */
473  wr = (wr + 1) & modulo;
474  }
475 
476  /* initialize rest of output buffer with 0 */
477  for (j = n_read; j < in->nb_samples; j++) {
478  dst[mult * j] = 0;
479  }
480 
481  /* fill FFT accumulation with 0 */
482  memset(fft_acc, 0, sizeof(FFTComplex) * n_fft);
483 
484  for (i = 0; i < n_conv; i++) {
485  const float *src = (const float *)in->extended_data[i * planar]; /* get pointer to audio input buffer */
486 
487  if (i == s->lfe_channel) { /* LFE */
488  if (in->format == AV_SAMPLE_FMT_FLT) {
489  for (j = 0; j < in->nb_samples; j++) {
490  /* apply gain to LFE signal and add to output buffer */
491  dst[2 * j] += src[i + j * in_channels] * s->gain_lfe;
492  }
493  } else {
494  for (j = 0; j < in->nb_samples; j++) {
495  /* apply gain to LFE signal and add to output buffer */
496  dst[j] += src[j] * s->gain_lfe;
497  }
498  }
499  continue;
500  }
501 
502  /* outer loop: go through all input channels to be convolved */
503  offset = i * n_fft; /* no. samples already processed */
504  hrtf_offset = hrtf + offset;
505 
506  /* fill FFT input with 0 (we want to zero-pad) */
507  memset(fft_in, 0, sizeof(FFTComplex) * n_fft);
508 
509  if (in->format == AV_SAMPLE_FMT_FLT) {
510  for (j = 0; j < in->nb_samples; j++) {
511  /* prepare input for FFT */
512  /* write all samples of current input channel to FFT input array */
513  fft_in[j].re = src[j * in_channels + i];
514  }
515  } else {
516  for (j = 0; j < in->nb_samples; j++) {
517  /* prepare input for FFT */
518  /* write all samples of current input channel to FFT input array */
519  fft_in[j].re = src[j];
520  }
521  }
522 
523  /* transform input signal of current channel to frequency domain */
524  av_fft_permute(fft, fft_in);
525  av_fft_calc(fft, fft_in);
526  for (j = 0; j < n_fft; j++) {
527  const FFTComplex *hcomplex = hrtf_offset + j;
528  const float re = fft_in[j].re;
529  const float im = fft_in[j].im;
530 
531  /* complex multiplication of input signal and HRTFs */
532  /* output channel (real): */
533  fft_acc[j].re += re * hcomplex->re - im * hcomplex->im;
534  /* output channel (imag): */
535  fft_acc[j].im += re * hcomplex->im + im * hcomplex->re;
536  }
537  }
538 
539  /* transform output signal of current channel back to time domain */
540  av_fft_permute(ifft, fft_acc);
541  av_fft_calc(ifft, fft_acc);
542 
543  for (j = 0; j < in->nb_samples; j++) {
544  /* write output signal of current channel to output buffer */
545  dst[mult * j] += fft_acc[j].re * fft_scale;
546  }
547 
548  for (j = 0; j < ir_samples - 1; j++) { /* overflow length is IR length - 1 */
549  /* write the rest of output signal to overflow buffer */
550  int write_pos = (wr + j) & modulo;
551 
552  *(ringbuffer + write_pos) += fft_acc[in->nb_samples + j].re * fft_scale;
553  }
554 
555  /* go through all samples of current output buffer: count clippings */
556  for (i = 0; i < out->nb_samples; i++) {
557  /* clippings counter */
558  if (fabsf(dst[i * mult]) > 1) { /* if current output sample > 1 */
559  n_clippings[0]++;
560  }
561  }
562 
563  /* remember read/write position in ringbuffer for next call */
564  *write = wr;
565 
566  return 0;
567 }
568 
569 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
570 {
571  AVFilterContext *ctx = inlink->dst;
572  SOFAlizerContext *s = ctx->priv;
573  AVFilterLink *outlink = ctx->outputs[0];
574  int n_clippings[2] = { 0 };
575  ThreadData td;
576  AVFrame *out;
577 
578  out = ff_get_audio_buffer(outlink, in->nb_samples);
579  if (!out) {
580  av_frame_free(&in);
581  return AVERROR(ENOMEM);
582  }
583  av_frame_copy_props(out, in);
584 
585  td.in = in; td.out = out; td.write = s->write;
586  td.delay = s->delay; td.ir = s->data_ir; td.n_clippings = n_clippings;
587  td.ringbuffer = s->ringbuffer; td.temp_src = s->temp_src;
588  td.temp_fft = s->temp_fft;
589  td.temp_afft = s->temp_afft;
590 
591  if (s->type == TIME_DOMAIN) {
592  ctx->internal->execute(ctx, sofalizer_convolute, &td, NULL, 2);
593  } else if (s->type == FREQUENCY_DOMAIN) {
594  ctx->internal->execute(ctx, sofalizer_fast_convolute, &td, NULL, 2);
595  }
596  emms_c();
597 
598  /* display error message if clipping occurred */
599  if (n_clippings[0] + n_clippings[1] > 0) {
600  av_log(ctx, AV_LOG_WARNING, "%d of %d samples clipped. Please reduce gain.\n",
601  n_clippings[0] + n_clippings[1], out->nb_samples * 2);
602  }
603 
604  av_frame_free(&in);
605  return ff_filter_frame(outlink, out);
606 }
607 
609 {
610  AVFilterLink *inlink = ctx->inputs[0];
611  AVFilterLink *outlink = ctx->outputs[0];
612  SOFAlizerContext *s = ctx->priv;
613  AVFrame *in;
614  int ret;
615 
616  FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
617 
618  if (s->nb_samples)
619  ret = ff_inlink_consume_samples(inlink, s->nb_samples, s->nb_samples, &in);
620  else
621  ret = ff_inlink_consume_frame(inlink, &in);
622  if (ret < 0)
623  return ret;
624  if (ret > 0)
625  return filter_frame(inlink, in);
626 
627  FF_FILTER_FORWARD_STATUS(inlink, outlink);
628  FF_FILTER_FORWARD_WANTED(outlink, inlink);
629 
630  return FFERROR_NOT_READY;
631 }
632 
634 {
635  struct SOFAlizerContext *s = ctx->priv;
638  int ret, sample_rates[] = { 48000, -1 };
639  static const enum AVSampleFormat sample_fmts[] = {
642  };
643 
644  formats = ff_make_format_list(sample_fmts);
645  if (!formats)
646  return AVERROR(ENOMEM);
647  ret = ff_set_common_formats(ctx, formats);
648  if (ret)
649  return ret;
650 
651  layouts = ff_all_channel_layouts();
652  if (!layouts)
653  return AVERROR(ENOMEM);
654 
655  ret = ff_channel_layouts_ref(layouts, &ctx->inputs[0]->out_channel_layouts);
656  if (ret)
657  return ret;
658 
659  layouts = NULL;
661  if (ret)
662  return ret;
663 
664  ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->in_channel_layouts);
665  if (ret)
666  return ret;
667 
668  sample_rates[0] = s->sample_rate;
669  formats = ff_make_format_list(sample_rates);
670  if (!formats)
671  return AVERROR(ENOMEM);
672  return ff_set_common_samplerates(ctx, formats);
673 }
674 
675 static int getfilter_float(AVFilterContext *ctx, float x, float y, float z,
676  float *left, float *right,
677  float *delay_left, float *delay_right)
678 {
679  struct SOFAlizerContext *s = ctx->priv;
680  float c[3], delays[2];
681  float *fl, *fr;
682  int nearest;
683  int *neighbors;
684  float *res;
685 
686  c[0] = x, c[1] = y, c[2] = z;
687  nearest = mysofa_lookup(s->sofa.lookup, c);
688  if (nearest < 0)
689  return AVERROR(EINVAL);
690 
691  if (s->interpolate) {
692  neighbors = mysofa_neighborhood(s->sofa.neighborhood, nearest);
693  res = mysofa_interpolate(s->sofa.hrtf, c,
694  nearest, neighbors,
695  s->sofa.fir, delays);
696  } else {
697  if (s->sofa.hrtf->DataDelay.elements > s->sofa.hrtf->R) {
698  delays[0] = s->sofa.hrtf->DataDelay.values[nearest * s->sofa.hrtf->R];
699  delays[1] = s->sofa.hrtf->DataDelay.values[nearest * s->sofa.hrtf->R + 1];
700  } else {
701  delays[0] = s->sofa.hrtf->DataDelay.values[0];
702  delays[1] = s->sofa.hrtf->DataDelay.values[1];
703  }
704  res = s->sofa.hrtf->DataIR.values + nearest * s->sofa.hrtf->N * s->sofa.hrtf->R;
705  }
706 
707  *delay_left = delays[0];
708  *delay_right = delays[1];
709 
710  fl = res;
711  fr = res + s->sofa.hrtf->N;
712 
713  memcpy(left, fl, sizeof(float) * s->sofa.hrtf->N);
714  memcpy(right, fr, sizeof(float) * s->sofa.hrtf->N);
715 
716  return 0;
717 }
718 
719 static int load_data(AVFilterContext *ctx, int azim, int elev, float radius, int sample_rate)
720 {
721  struct SOFAlizerContext *s = ctx->priv;
722  int n_samples;
723  int ir_samples;
724  int n_conv = s->n_conv; /* no. channels to convolve */
725  int n_fft;
726  float delay_l; /* broadband delay for each IR */
727  float delay_r;
728  int nb_input_channels = ctx->inputs[0]->channels; /* no. input channels */
729  float gain_lin = expf((s->gain - 3 * nb_input_channels) / 20 * M_LN10); /* gain - 3dB/channel */
730  FFTComplex *data_hrtf_l = NULL;
731  FFTComplex *data_hrtf_r = NULL;
732  FFTComplex *fft_in_l = NULL;
733  FFTComplex *fft_in_r = NULL;
734  float *data_ir_l = NULL;
735  float *data_ir_r = NULL;
736  int offset = 0; /* used for faster pointer arithmetics in for-loop */
737  int i, j, azim_orig = azim, elev_orig = elev;
738  int ret = 0;
739  int n_current;
740  int n_max = 0;
741 
742  av_log(ctx, AV_LOG_DEBUG, "IR length: %d.\n", s->sofa.hrtf->N);
743  s->sofa.ir_samples = s->sofa.hrtf->N;
744  s->sofa.n_samples = 1 << (32 - ff_clz(s->sofa.ir_samples));
745 
746  n_samples = s->sofa.n_samples;
747  ir_samples = s->sofa.ir_samples;
748 
749  if (s->type == TIME_DOMAIN) {
750  s->data_ir[0] = av_calloc(n_samples, sizeof(float) * s->n_conv);
751  s->data_ir[1] = av_calloc(n_samples, sizeof(float) * s->n_conv);
752 
753  if (!s->data_ir[0] || !s->data_ir[1]) {
754  ret = AVERROR(ENOMEM);
755  goto fail;
756  }
757  }
758 
759  s->delay[0] = av_calloc(s->n_conv, sizeof(int));
760  s->delay[1] = av_calloc(s->n_conv, sizeof(int));
761 
762  if (!s->delay[0] || !s->delay[1]) {
763  ret = AVERROR(ENOMEM);
764  goto fail;
765  }
766 
767  /* get temporary IR for L and R channel */
768  data_ir_l = av_calloc(n_conv * n_samples, sizeof(*data_ir_l));
769  data_ir_r = av_calloc(n_conv * n_samples, sizeof(*data_ir_r));
770  if (!data_ir_r || !data_ir_l) {
771  ret = AVERROR(ENOMEM);
772  goto fail;
773  }
774 
775  if (s->type == TIME_DOMAIN) {
776  s->temp_src[0] = av_calloc(n_samples, sizeof(float));
777  s->temp_src[1] = av_calloc(n_samples, sizeof(float));
778  if (!s->temp_src[0] || !s->temp_src[1]) {
779  ret = AVERROR(ENOMEM);
780  goto fail;
781  }
782  }
783 
784  s->speaker_azim = av_calloc(s->n_conv, sizeof(*s->speaker_azim));
785  s->speaker_elev = av_calloc(s->n_conv, sizeof(*s->speaker_elev));
786  if (!s->speaker_azim || !s->speaker_elev) {
787  ret = AVERROR(ENOMEM);
788  goto fail;
789  }
790 
791  /* get speaker positions */
792  if ((ret = get_speaker_pos(ctx, s->speaker_azim, s->speaker_elev)) < 0) {
793  av_log(ctx, AV_LOG_ERROR, "Couldn't get speaker positions. Input channel configuration not supported.\n");
794  goto fail;
795  }
796 
797  for (i = 0; i < s->n_conv; i++) {
798  float coordinates[3];
799 
800  /* load and store IRs and corresponding delays */
801  azim = (int)(s->speaker_azim[i] + azim_orig) % 360;
802  elev = (int)(s->speaker_elev[i] + elev_orig) % 90;
803 
804  coordinates[0] = azim;
805  coordinates[1] = elev;
806  coordinates[2] = radius;
807 
808  mysofa_s2c(coordinates);
809 
810  /* get id of IR closest to desired position */
811  ret = getfilter_float(ctx, coordinates[0], coordinates[1], coordinates[2],
812  data_ir_l + n_samples * i,
813  data_ir_r + n_samples * i,
814  &delay_l, &delay_r);
815  if (ret < 0)
816  goto fail;
817 
818  s->delay[0][i] = delay_l * sample_rate;
819  s->delay[1][i] = delay_r * sample_rate;
820 
821  s->sofa.max_delay = FFMAX3(s->sofa.max_delay, s->delay[0][i], s->delay[1][i]);
822  }
823 
824  /* get size of ringbuffer (longest IR plus max. delay) */
825  /* then choose next power of 2 for performance optimization */
826  n_current = n_samples + s->sofa.max_delay;
827  /* length of longest IR plus max. delay */
828  n_max = FFMAX(n_max, n_current);
829 
830  /* buffer length is longest IR plus max. delay -> next power of 2
831  (32 - count leading zeros gives required exponent) */
832  s->buffer_length = 1 << (32 - ff_clz(n_max));
833  s->n_fft = n_fft = 1 << (32 - ff_clz(n_max + s->framesize));
834 
835  if (s->type == FREQUENCY_DOMAIN) {
836  av_fft_end(s->fft[0]);
837  av_fft_end(s->fft[1]);
838  s->fft[0] = av_fft_init(av_log2(s->n_fft), 0);
839  s->fft[1] = av_fft_init(av_log2(s->n_fft), 0);
840  av_fft_end(s->ifft[0]);
841  av_fft_end(s->ifft[1]);
842  s->ifft[0] = av_fft_init(av_log2(s->n_fft), 1);
843  s->ifft[1] = av_fft_init(av_log2(s->n_fft), 1);
844 
845  if (!s->fft[0] || !s->fft[1] || !s->ifft[0] || !s->ifft[1]) {
846  av_log(ctx, AV_LOG_ERROR, "Unable to create FFT contexts of size %d.\n", s->n_fft);
847  ret = AVERROR(ENOMEM);
848  goto fail;
849  }
850  }
851 
852  if (s->type == TIME_DOMAIN) {
853  s->ringbuffer[0] = av_calloc(s->buffer_length, sizeof(float) * nb_input_channels);
854  s->ringbuffer[1] = av_calloc(s->buffer_length, sizeof(float) * nb_input_channels);
855  } else if (s->type == FREQUENCY_DOMAIN) {
856  /* get temporary HRTF memory for L and R channel */
857  data_hrtf_l = av_malloc_array(n_fft, sizeof(*data_hrtf_l) * n_conv);
858  data_hrtf_r = av_malloc_array(n_fft, sizeof(*data_hrtf_r) * n_conv);
859  if (!data_hrtf_r || !data_hrtf_l) {
860  ret = AVERROR(ENOMEM);
861  goto fail;
862  }
863 
864  s->ringbuffer[0] = av_calloc(s->buffer_length, sizeof(float));
865  s->ringbuffer[1] = av_calloc(s->buffer_length, sizeof(float));
866  s->temp_fft[0] = av_malloc_array(s->n_fft, sizeof(FFTComplex));
867  s->temp_fft[1] = av_malloc_array(s->n_fft, sizeof(FFTComplex));
868  s->temp_afft[0] = av_malloc_array(s->n_fft, sizeof(FFTComplex));
869  s->temp_afft[1] = av_malloc_array(s->n_fft, sizeof(FFTComplex));
870  if (!s->temp_fft[0] || !s->temp_fft[1] ||
871  !s->temp_afft[0] || !s->temp_afft[1]) {
872  ret = AVERROR(ENOMEM);
873  goto fail;
874  }
875  }
876 
877  if (!s->ringbuffer[0] || !s->ringbuffer[1]) {
878  ret = AVERROR(ENOMEM);
879  goto fail;
880  }
881 
882  if (s->type == FREQUENCY_DOMAIN) {
883  fft_in_l = av_calloc(n_fft, sizeof(*fft_in_l));
884  fft_in_r = av_calloc(n_fft, sizeof(*fft_in_r));
885  if (!fft_in_l || !fft_in_r) {
886  ret = AVERROR(ENOMEM);
887  goto fail;
888  }
889  }
890 
891  for (i = 0; i < s->n_conv; i++) {
892  float *lir, *rir;
893 
894  offset = i * n_samples; /* no. samples already written */
895 
896  lir = data_ir_l + offset;
897  rir = data_ir_r + offset;
898 
899  if (s->type == TIME_DOMAIN) {
900  for (j = 0; j < ir_samples; j++) {
901  /* load reversed IRs of the specified source position
902  * sample-by-sample for left and right ear; and apply gain */
903  s->data_ir[0][offset + j] = lir[ir_samples - 1 - j] * gain_lin;
904  s->data_ir[1][offset + j] = rir[ir_samples - 1 - j] * gain_lin;
905  }
906  } else if (s->type == FREQUENCY_DOMAIN) {
907  memset(fft_in_l, 0, n_fft * sizeof(*fft_in_l));
908  memset(fft_in_r, 0, n_fft * sizeof(*fft_in_r));
909 
910  offset = i * n_fft; /* no. samples already written */
911  for (j = 0; j < ir_samples; j++) {
912  /* load non-reversed IRs of the specified source position
913  * sample-by-sample and apply gain,
914  * L channel is loaded to real part, R channel to imag part,
915  * IRs are shifted by L and R delay */
916  fft_in_l[s->delay[0][i] + j].re = lir[j] * gain_lin;
917  fft_in_r[s->delay[1][i] + j].re = rir[j] * gain_lin;
918  }
919 
920  /* actually transform to frequency domain (IRs -> HRTFs) */
921  av_fft_permute(s->fft[0], fft_in_l);
922  av_fft_calc(s->fft[0], fft_in_l);
923  memcpy(data_hrtf_l + offset, fft_in_l, n_fft * sizeof(*fft_in_l));
924  av_fft_permute(s->fft[0], fft_in_r);
925  av_fft_calc(s->fft[0], fft_in_r);
926  memcpy(data_hrtf_r + offset, fft_in_r, n_fft * sizeof(*fft_in_r));
927  }
928  }
929 
930  if (s->type == FREQUENCY_DOMAIN) {
931  s->data_hrtf[0] = av_malloc_array(n_fft * s->n_conv, sizeof(FFTComplex));
932  s->data_hrtf[1] = av_malloc_array(n_fft * s->n_conv, sizeof(FFTComplex));
933  if (!s->data_hrtf[0] || !s->data_hrtf[1]) {
934  ret = AVERROR(ENOMEM);
935  goto fail;
936  }
937 
938  memcpy(s->data_hrtf[0], data_hrtf_l, /* copy HRTF data to */
939  sizeof(FFTComplex) * n_conv * n_fft); /* filter struct */
940  memcpy(s->data_hrtf[1], data_hrtf_r,
941  sizeof(FFTComplex) * n_conv * n_fft);
942  }
943 
944 fail:
945  av_freep(&data_hrtf_l); /* free temporary HRTF memory */
946  av_freep(&data_hrtf_r);
947 
948  av_freep(&data_ir_l); /* free temprary IR memory */
949  av_freep(&data_ir_r);
950 
951  av_freep(&fft_in_l); /* free temporary FFT memory */
952  av_freep(&fft_in_r);
953 
954  return ret;
955 }
956 
958 {
959  SOFAlizerContext *s = ctx->priv;
960  int ret;
961 
962  if (!s->filename) {
963  av_log(ctx, AV_LOG_ERROR, "Valid SOFA filename must be set.\n");
964  return AVERROR(EINVAL);
965  }
966 
967  /* preload SOFA file, */
968  ret = preload_sofa(ctx, s->filename, &s->sample_rate);
969  if (ret) {
970  /* file loading error */
971  av_log(ctx, AV_LOG_ERROR, "Error while loading SOFA file: '%s'\n", s->filename);
972  } else { /* no file loading error, resampling not required */
973  av_log(ctx, AV_LOG_DEBUG, "File '%s' loaded.\n", s->filename);
974  }
975 
976  if (ret) {
977  av_log(ctx, AV_LOG_ERROR, "No valid SOFA file could be loaded. Please specify valid SOFA file.\n");
978  return ret;
979  }
980 
982  if (!s->fdsp)
983  return AVERROR(ENOMEM);
984 
985  return 0;
986 }
987 
988 static int config_input(AVFilterLink *inlink)
989 {
990  AVFilterContext *ctx = inlink->dst;
991  SOFAlizerContext *s = ctx->priv;
992  int ret;
993 
994  if (s->type == FREQUENCY_DOMAIN)
995  s->nb_samples = s->framesize;
996 
997  /* gain -3 dB per channel */
998  s->gain_lfe = expf((s->gain - 3 * inlink->channels + s->lfe_gain) / 20 * M_LN10);
999 
1000  s->n_conv = inlink->channels;
1001 
1002  /* load IRs to data_ir[0] and data_ir[1] for required directions */
1003  if ((ret = load_data(ctx, s->rotation, s->elevation, s->radius, inlink->sample_rate)) < 0)
1004  return ret;
1005 
1006  av_log(ctx, AV_LOG_DEBUG, "Samplerate: %d Channels to convolute: %d, Length of ringbuffer: %d x %d\n",
1007  inlink->sample_rate, s->n_conv, inlink->channels, s->buffer_length);
1008 
1009  return 0;
1010 }
1011 
1013 {
1014  SOFAlizerContext *s = ctx->priv;
1015 
1016  close_sofa(&s->sofa);
1017  av_fft_end(s->ifft[0]);
1018  av_fft_end(s->ifft[1]);
1019  av_fft_end(s->fft[0]);
1020  av_fft_end(s->fft[1]);
1021  s->ifft[0] = NULL;
1022  s->ifft[1] = NULL;
1023  s->fft[0] = NULL;
1024  s->fft[1] = NULL;
1025  av_freep(&s->delay[0]);
1026  av_freep(&s->delay[1]);
1027  av_freep(&s->data_ir[0]);
1028  av_freep(&s->data_ir[1]);
1029  av_freep(&s->ringbuffer[0]);
1030  av_freep(&s->ringbuffer[1]);
1031  av_freep(&s->speaker_azim);
1032  av_freep(&s->speaker_elev);
1033  av_freep(&s->temp_src[0]);
1034  av_freep(&s->temp_src[1]);
1035  av_freep(&s->temp_afft[0]);
1036  av_freep(&s->temp_afft[1]);
1037  av_freep(&s->temp_fft[0]);
1038  av_freep(&s->temp_fft[1]);
1039  av_freep(&s->data_hrtf[0]);
1040  av_freep(&s->data_hrtf[1]);
1041  av_freep(&s->fdsp);
1042 }
1043 
1044 #define OFFSET(x) offsetof(SOFAlizerContext, x)
1045 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
1046 
1047 static const AVOption sofalizer_options[] = {
1048  { "sofa", "sofa filename", OFFSET(filename), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
1049  { "gain", "set gain in dB", OFFSET(gain), AV_OPT_TYPE_FLOAT, {.dbl=0}, -20, 40, .flags = FLAGS },
1050  { "rotation", "set rotation" , OFFSET(rotation), AV_OPT_TYPE_FLOAT, {.dbl=0}, -360, 360, .flags = FLAGS },
1051  { "elevation", "set elevation", OFFSET(elevation), AV_OPT_TYPE_FLOAT, {.dbl=0}, -90, 90, .flags = FLAGS },
1052  { "radius", "set radius", OFFSET(radius), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 5, .flags = FLAGS },
1053  { "type", "set processing", OFFSET(type), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, .flags = FLAGS, "type" },
1054  { "time", "time domain", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, .flags = FLAGS, "type" },
1055  { "freq", "frequency domain", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, .flags = FLAGS, "type" },
1056  { "speakers", "set speaker custom positions", OFFSET(speakers_pos), AV_OPT_TYPE_STRING, {.str=0}, 0, 0, .flags = FLAGS },
1057  { "lfegain", "set lfe gain", OFFSET(lfe_gain), AV_OPT_TYPE_FLOAT, {.dbl=0}, -20,40, .flags = FLAGS },
1058  { "framesize", "set frame size", OFFSET(framesize), AV_OPT_TYPE_INT, {.i64=1024},1024,96000, .flags = FLAGS },
1059  { "normalize", "normalize IRs", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, .flags = FLAGS },
1060  { "interpolate","interpolate IRs from neighbors", OFFSET(interpolate),AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags = FLAGS },
1061  { "minphase", "minphase IRs", OFFSET(minphase), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags = FLAGS },
1062  { "anglestep", "set neighbor search angle step", OFFSET(anglestep), AV_OPT_TYPE_FLOAT, {.dbl=.5}, 0.01, 10, .flags = FLAGS },
1063  { "radstep", "set neighbor search radius step", OFFSET(radstep), AV_OPT_TYPE_FLOAT, {.dbl=.01}, 0.01, 1, .flags = FLAGS },
1064  { NULL }
1065 };
1066 
1067 AVFILTER_DEFINE_CLASS(sofalizer);
1068 
1069 static const AVFilterPad inputs[] = {
1070  {
1071  .name = "default",
1072  .type = AVMEDIA_TYPE_AUDIO,
1073  .config_props = config_input,
1074  },
1075  { NULL }
1076 };
1077 
1078 static const AVFilterPad outputs[] = {
1079  {
1080  .name = "default",
1081  .type = AVMEDIA_TYPE_AUDIO,
1082  },
1083  { NULL }
1084 };
1085 
1087  .name = "sofalizer",
1088  .description = NULL_IF_CONFIG_SMALL("SOFAlizer (Spatially Oriented Format for Acoustics)."),
1089  .priv_size = sizeof(SOFAlizerContext),
1090  .priv_class = &sofalizer_class,
1091  .init = init,
1092  .activate = activate,
1093  .uninit = uninit,
1095  .inputs = inputs,
1096  .outputs = outputs,
1098 };
static int sofalizer_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: af_sofalizer.c:431
float, planar
Definition: samplefmt.h:69
float(* scalarproduct_float)(const float *v1, const float *v2, int len)
Calculate the scalar product of two vectors of floats.
Definition: float_dsp.h:175
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link&#39;s FIFO and update the link&#39;s stats.
Definition: avfilter.c:1481
#define NULL
Definition: coverity.c:32
FFTComplex * data_hrtf[2]
Definition: af_sofalizer.c:112
AVFrame * out
Definition: af_adeclick.c:488
This structure describes decoded (raw) audio or video data.
Definition: frame.h:295
#define AV_CH_TOP_FRONT_RIGHT
AVOption.
Definition: opt.h:246
av_cold void av_fft_end(FFTContext *s)
Definition: avfft.c:48
float re
Definition: fft.c:82
float ** temp_src
Definition: af_headphone.c:160
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
Main libavfilter public API header.
AVFILTER_DEFINE_CLASS(sofalizer)
#define AV_CH_TOP_FRONT_LEFT
FFTContext * fft[2]
Definition: af_sofalizer.c:111
#define AV_CH_TOP_FRONT_CENTER
uint8_t pi<< 24) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_U8,(uint64_t)((*(const uint8_t *) pi - 0x80U))<< 56) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi - 0x80) *(1.0f/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi - 0x80) *(1.0/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16,(*(const int16_t *) pi >>8)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S16,(uint64_t)(*(const int16_t *) pi)<< 48) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, *(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, *(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32,(*(const int32_t *) pi >>24)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S32,(uint64_t)(*(const int32_t *) pi)<< 32) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, *(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, *(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S64,(*(const int64_t *) pi >>56)+0x80) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S64, *(const int64_t *) pi *(1.0f/(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S64, *(const int64_t *) pi *(1.0/(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_FLT, llrintf(*(const float *) pi *(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_DBL, llrint(*(const double *) pi *(INT64_C(1)<< 63))) #define FMT_PAIR_FUNC(out, in) static conv_func_type *const fmt_pair_to_conv_functions[AV_SAMPLE_FMT_NB *AV_SAMPLE_FMT_NB]={ FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64), };static void cpy1(uint8_t **dst, const uint8_t **src, int len){ memcpy(*dst, *src, len);} static void cpy2(uint8_t **dst, const uint8_t **src, int len){ memcpy(*dst, *src, 2 *len);} static void cpy4(uint8_t **dst, const uint8_t **src, int len){ memcpy(*dst, *src, 4 *len);} static void cpy8(uint8_t **dst, const uint8_t **src, int len){ memcpy(*dst, *src, 8 *len);} AudioConvert *swri_audio_convert_alloc(enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, const int *ch_map, int flags) { AudioConvert *ctx;conv_func_type *f=fmt_pair_to_conv_functions[av_get_packed_sample_fmt(out_fmt)+AV_SAMPLE_FMT_NB *av_get_packed_sample_fmt(in_fmt)];if(!f) return NULL;ctx=av_mallocz(sizeof(*ctx));if(!ctx) return NULL;if(channels==1){ in_fmt=av_get_planar_sample_fmt(in_fmt);out_fmt=av_get_planar_sample_fmt(out_fmt);} ctx->channels=channels;ctx->conv_f=f;ctx->ch_map=ch_map;if(in_fmt==AV_SAMPLE_FMT_U8||in_fmt==AV_SAMPLE_FMT_U8P) memset(ctx->silence, 0x80, sizeof(ctx->silence));if(out_fmt==in_fmt &&!ch_map) { switch(av_get_bytes_per_sample(in_fmt)){ case 1:ctx->simd_f=cpy1;break;case 2:ctx->simd_f=cpy2;break;case 4:ctx->simd_f=cpy4;break;case 8:ctx->simd_f=cpy8;break;} } if(HAVE_X86ASM &&HAVE_MMX) swri_audio_convert_init_x86(ctx, out_fmt, in_fmt, channels);if(ARCH_ARM) swri_audio_convert_init_arm(ctx, out_fmt, in_fmt, channels);if(ARCH_AARCH64) swri_audio_convert_init_aarch64(ctx, out_fmt, in_fmt, channels);return ctx;} void swri_audio_convert_free(AudioConvert **ctx) { av_freep(ctx);} int swri_audio_convert(AudioConvert *ctx, AudioData *out, AudioData *in, int len) { int ch;int off=0;const int os=(out->planar ? 1 :out->ch_count) *out->bps;unsigned misaligned=0;av_assert0(ctx->channels==out->ch_count);if(ctx->in_simd_align_mask) { int planes=in->planar ? in->ch_count :1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) in->ch[ch];misaligned|=m &ctx->in_simd_align_mask;} if(ctx->out_simd_align_mask) { int planes=out->planar ? out->ch_count :1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) out->ch[ch];misaligned|=m &ctx->out_simd_align_mask;} if(ctx->simd_f &&!ctx->ch_map &&!misaligned){ off=len &~15;av_assert1(off >=0);av_assert1(off<=len);av_assert2(ctx->channels==SWR_CH_MAX||!in->ch[ctx->channels]);if(off >0){ if(out->planar==in->planar){ int planes=out->planar ? out->ch_count :1;for(ch=0;ch< planes;ch++){ ctx->simd_f(out-> ch ch
Definition: audioconvert.c:56
#define AV_CH_LOW_FREQUENCY_2
struct MYSOFA_HRTF * hrtf
Definition: af_sofalizer.c:46
#define FFERROR_NOT_READY
Filters implementation helper functions.
Definition: filters.h:34
FFTSample re
Definition: avfft.h:38
FFTComplex * temp_afft[2]
Definition: af_sofalizer.c:94
void av_fft_permute(FFTContext *s, FFTComplex *z)
Do the permutation needed BEFORE calling ff_fft_calc().
Definition: avfft.c:38
FFTComplex ** temp_afft
Definition: af_headphone.c:162
#define AV_CH_SURROUND_DIRECT_RIGHT
#define AV_CH_LAYOUT_STEREO
AVFilter ff_af_sofalizer
#define src
Definition: vp8dsp.c:254
float * fir
Definition: af_sofalizer.c:52
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:244
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:283
static int close_sofa(struct MySofa *sofa)
Definition: af_sofalizer.c:117
BYTE int const BYTE * srcp
Definition: avisynth_c.h:908
const char * name
Pad name.
Definition: internal.h:60
uint64_t av_get_channel_layout(const char *name)
Return a channel layout id that matches name, or 0 if no match is found.
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:346
int ff_channel_layouts_ref(AVFilterChannelLayouts *f, AVFilterChannelLayouts **ref)
Add *ref as a new reference to f.
Definition: formats.c:435
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1080
float ** ringbuffer
Definition: af_headphone.c:159
uint8_t pi<< 24) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_U8,(uint64_t)((*(const uint8_t *) pi - 0x80U))<< 56) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi - 0x80) *(1.0f/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi - 0x80) *(1.0/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16,(*(const int16_t *) pi >>8)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S16,(uint64_t)(*(const int16_t *) pi)<< 48) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, *(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, *(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32,(*(const int32_t *) pi >>24)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S32,(uint64_t)(*(const int32_t *) pi)<< 32) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, *(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, *(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S64,(*(const int64_t *) pi >>56)+0x80) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S64, *(const int64_t *) pi *(1.0f/(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S64, *(const int64_t *) pi *(1.0/(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_FLT, llrintf(*(const float *) pi *(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_DBL, llrint(*(const double *) pi *(INT64_C(1)<< 63))) #define FMT_PAIR_FUNC(out, in) static conv_func_type *const fmt_pair_to_conv_functions[AV_SAMPLE_FMT_NB *AV_SAMPLE_FMT_NB]={ FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64), };static void cpy1(uint8_t **dst, const uint8_t **src, int len){ memcpy(*dst, *src, len);} static void cpy2(uint8_t **dst, const uint8_t **src, int len){ memcpy(*dst, *src, 2 *len);} static void cpy4(uint8_t **dst, const uint8_t **src, int len){ memcpy(*dst, *src, 4 *len);} static void cpy8(uint8_t **dst, const uint8_t **src, int len){ memcpy(*dst, *src, 8 *len);} AudioConvert *swri_audio_convert_alloc(enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, const int *ch_map, int flags) { AudioConvert *ctx;conv_func_type *f=fmt_pair_to_conv_functions[av_get_packed_sample_fmt(out_fmt)+AV_SAMPLE_FMT_NB *av_get_packed_sample_fmt(in_fmt)];if(!f) return NULL;ctx=av_mallocz(sizeof(*ctx));if(!ctx) return NULL;if(channels==1){ in_fmt=av_get_planar_sample_fmt(in_fmt);out_fmt=av_get_planar_sample_fmt(out_fmt);} ctx->channels=channels;ctx->conv_f=f;ctx->ch_map=ch_map;if(in_fmt==AV_SAMPLE_FMT_U8||in_fmt==AV_SAMPLE_FMT_U8P) memset(ctx->silence, 0x80, sizeof(ctx->silence));if(out_fmt==in_fmt &&!ch_map) { switch(av_get_bytes_per_sample(in_fmt)){ case 1:ctx->simd_f=cpy1;break;case 2:ctx->simd_f=cpy2;break;case 4:ctx->simd_f=cpy4;break;case 8:ctx->simd_f=cpy8;break;} } if(HAVE_X86ASM &&HAVE_MMX) swri_audio_convert_init_x86(ctx, out_fmt, in_fmt, channels);if(ARCH_ARM) swri_audio_convert_init_arm(ctx, out_fmt, in_fmt, channels);if(ARCH_AARCH64) swri_audio_convert_init_aarch64(ctx, out_fmt, in_fmt, channels);return ctx;} void swri_audio_convert_free(AudioConvert **ctx) { av_freep(ctx);} int swri_audio_convert(AudioConvert *ctx, AudioData *out, AudioData *in, int len) { int ch;int off=0;const int os=(out->planar ? 1 :out->ch_count) *out->bps;unsigned misaligned=0;av_assert0(ctx->channels==out->ch_count);if(ctx->in_simd_align_mask) { int planes=in->planar ? in->ch_count :1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) in->ch[ch];misaligned|=m &ctx->in_simd_align_mask;} if(ctx->out_simd_align_mask) { int planes=out->planar ? out->ch_count :1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) out->ch[ch];misaligned|=m &ctx->out_simd_align_mask;} if(ctx->simd_f &&!ctx->ch_map &&!misaligned){ off=len &~15;av_assert1(off >=0);av_assert1(off<=len);av_assert2(ctx->channels==SWR_CH_MAX||!in->ch[ctx->channels]);if(off >0){ if(out->planar==in->planar){ int planes=out->planar ? out->ch_count :1;for(ch=0;ch< planes;ch++){ ctx->simd_f(out-> ch const uint8_t **in ch off *out planar
Definition: audioconvert.c:56
static char buffer[20]
Definition: seek.c:32
#define AV_CH_WIDE_LEFT
uint8_t
#define av_cold
Definition: attributes.h:82
AVOptions.
int ** delay
Definition: af_headphone.c:156
#define AV_CH_TOP_BACK_LEFT
struct MYSOFA_LOOKUP * lookup
Definition: af_sofalizer.c:47
#define AV_CH_WIDE_RIGHT
#define AV_CH_TOP_BACK_CENTER
#define emms_c()
Definition: internal.h:55
#define AV_CH_LOW_FREQUENCY
#define FLAGS
static void interpolate(float *out, float v1, float v2, int size)
Definition: twinvq.c:84
#define AV_CH_BACK_LEFT
float * rir
Definition: af_sofalizer.c:51
#define FFALIGN(x, a)
Definition: macros.h:48
#define av_log(a,...)
#define FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink)
Forward the status on an output link to an input link.
Definition: filters.h:199
A filter pad used for either input or output.
Definition: internal.h:54
#define expf(x)
Definition: libm.h:283
AVFloatDSPContext * fdsp
Definition: af_sofalizer.c:114
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:568
#define td
Definition: regdef.h:70
av_cold AVFloatDSPContext * avpriv_float_dsp_alloc(int bit_exact)
Allocate a float DSP context.
Definition: float_dsp.c:135
int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout)
Definition: formats.c:343
AVFrame * ff_get_audio_buffer(AVFilterLink *link, int nb_samples)
Request an audio samples buffer with a specific set of permissions.
Definition: audio.c:86
static const uint16_t mask[17]
Definition: lzw.c:38
static int get_speaker_pos(AVFilterContext *ctx, float *speaker_azim, float *speaker_elev)
Definition: af_sofalizer.c:244
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: af_sofalizer.c:569
#define AVERROR(e)
Definition: error.h:43
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:202
static int query_formats(AVFilterContext *ctx)
Definition: af_sofalizer.c:633
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
void * priv
private data for use by the filter
Definition: avfilter.h:353
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:116
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
const char * arg
Definition: jacosubdec.c:66
float * data_ir[2]
Definition: af_sofalizer.c:90
FFTContext * av_fft_init(int nbits, int inverse)
Set up a complex FFT.
Definition: avfft.c:28
static const uint8_t offset[127][2]
Definition: vf_spp.c:92
#define FFMAX(a, b)
Definition: common.h:94
#define fail()
Definition: checkasm.h:120
int av_sscanf(const char *string, const char *format,...)
See libc sscanf manual for more information.
Definition: avsscanf.c:962
#define AV_CH_STEREO_RIGHT
See AV_CH_STEREO_LEFT.
#define FF_FILTER_FORWARD_WANTED(outlink, inlink)
Forward the frame_wanted_out flag from an output link to an input link.
Definition: filters.h:254
#define AV_CH_TOP_CENTER
float * ringbuffer[2]
Definition: af_sofalizer.c:79
float * speaker_azim
Definition: af_sofalizer.c:69
Definition: fft.h:88
static int load_data(AVFilterContext *ctx, int azim, int elev, float radius, int sample_rate)
Definition: af_sofalizer.c:719
audio channel layout utility functions
static int16_t mult(Float11 *f1, Float11 *f2)
Definition: g726.c:55
#define FFMIN(a, b)
Definition: common.h:96
#define ff_clz
Definition: intmath.h:142
const char AVS_Value args
Definition: avisynth_c.h:872
AVFormatContext * ctx
Definition: movenc.c:48
#define TIME_DOMAIN
Definition: af_sofalizer.c:42
#define s(width, name)
Definition: cbs_vp9.c:257
int * n_clippings
Definition: af_headphone.c:158
#define AV_CH_FRONT_LEFT_OF_CENTER
#define AV_CH_FRONT_CENTER
static const AVFilterPad outputs[]
if(ret< 0)
Definition: vf_mcdeint.c:279
AVFilterChannelLayouts * ff_all_channel_layouts(void)
Construct an empty AVFilterChannelLayouts/AVFilterFormats struct – representing any channel layout (...
Definition: formats.c:401
#define AV_CH_FRONT_RIGHT_OF_CENTER
#define av_log2
Definition: intmath.h:83
A list of supported channel layouts.
Definition: formats.h:85
static const AVOption sofalizer_options[]
FFTComplex ** temp_fft
Definition: af_headphone.c:161
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:368
sample_rate
#define AV_LOG_INFO
Standard information.
Definition: log.h:187
static int preload_sofa(AVFilterContext *ctx, char *filename, int *samplingrate)
Definition: af_sofalizer.c:133
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:251
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:58
int max_delay
Definition: af_sofalizer.c:53
Used for passing data between threads.
Definition: af_adeclick.c:487
static int activate(AVFilterContext *ctx)
Definition: af_sofalizer.c:608
int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max, AVFrame **rframe)
Take samples from the link&#39;s FIFO and update the link&#39;s stats.
Definition: avfilter.c:1500
FFT functions.
static int config_input(AVFilterLink *inlink)
Definition: af_sofalizer.c:988
#define AV_CH_FRONT_LEFT
void * buf
Definition: avisynth_c.h:766
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) #define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac) { } void ff_audio_convert_free(AudioConvert **ac) { if(! *ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);} AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map) { AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method !=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2) { ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc) { av_free(ac);return NULL;} return ac;} in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar) { ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar ? ac->channels :1;} else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;} int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in) { int use_generic=1;int len=in->nb_samples;int p;if(ac->dc) { av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (dithered)\", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
#define AV_CH_TOP_BACK_RIGHT
Describe the class of an AVClass context structure.
Definition: log.h:67
Filter definition.
Definition: avfilter.h:144
float im
Definition: fft.c:82
cl_device_type type
const char * name
Filter name.
Definition: avfilter.h:148
float * speaker_elev
Definition: af_sofalizer.c:70
static const AVFilterPad inputs[]
int ir_samples
Definition: af_sofalizer.c:49
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:350
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:434
#define FF_FILTER_FORWARD_STATUS(inlink, outlink)
Acknowledge the status on an input link and forward it to an output link.
Definition: filters.h:226
float ** ir
Definition: af_headphone.c:157
#define flags(name, subs,...)
Definition: cbs_av1.c:561
AVFilterInternal * internal
An opaque struct for libavfilter internal use.
Definition: avfilter.h:378
#define AV_CH_BACK_CENTER
#define AV_CH_SIDE_RIGHT
static int sofalizer_convolute(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: af_sofalizer.c:331
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok()...
Definition: avstring.c:184
#define M_LN10
Definition: mathematics.h:43
float * lir
Definition: af_sofalizer.c:51
FFTContext * ifft[2]
Definition: af_sofalizer.c:111
int
static int parse_channel_name(char **arg, int *rchannel, char *buf)
Definition: af_sofalizer.c:186
sample_rates
FFTSample im
Definition: avfft.h:38
static double c[64]
#define FREQUENCY_DOMAIN
Definition: af_sofalizer.c:43
avfilter_execute_func * execute
Definition: internal.h:155
static av_cold int init(AVFilterContext *ctx)
Definition: af_sofalizer.c:957
#define av_free(p)
int len
static void parse_speaker_pos(AVFilterContext *ctx, int64_t in_channel_layout)
Definition: af_sofalizer.c:211
float * temp_src[2]
Definition: af_sofalizer.c:92
A list of supported formats for one end of a filter link.
Definition: formats.h:64
uint64_t layout
#define AV_CH_SURROUND_DIRECT_LEFT
int n_samples
Definition: af_sofalizer.c:50
An instance of a filter.
Definition: avfilter.h:338
#define AV_CH_FRONT_RIGHT
static enum AVSampleFormat sample_fmts[]
Definition: adpcmenc.c:701
VirtualSpeaker vspkrpos[64]
Definition: af_sofalizer.c:109
FILE * out
Definition: movenc.c:54
#define av_freep(p)
#define OFFSET(x)
#define av_malloc_array(a, b)
AVFrame * in
Definition: af_afftdn.c:1082
formats
Definition: signature.h:48
#define AV_CH_SIDE_LEFT
internal API functions
FFTComplex * temp_fft[2]
Definition: af_sofalizer.c:93
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:342
static av_cold void uninit(AVFilterContext *ctx)
void av_fft_calc(FFTContext *s, FFTComplex *z)
Do a complex FFT with the parameters defined in av_fft_init().
Definition: avfft.c:43
struct MYSOFA_NEIGHBORHOOD * neighborhood
Definition: af_sofalizer.c:48
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:361
int ff_set_common_samplerates(AVFilterContext *ctx, AVFilterFormats *samplerates)
Definition: formats.c:556
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:654
#define FFMAX3(a, b, c)
Definition: common.h:95
#define AV_CH_BACK_RIGHT
static int getfilter_float(AVFilterContext *ctx, float x, float y, float z, float *left, float *right, float *delay_left, float *delay_right)
Definition: af_sofalizer.c:675
#define AV_CH_STEREO_LEFT
Stereo downmix.