FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 "internal.h"
39 #include "audio.h"
40 
41 #define TIME_DOMAIN 0
42 #define FREQUENCY_DOMAIN 1
43 
44 typedef struct MySofa { /* contains data of one SOFA file */
45  struct MYSOFA_HRTF *hrtf;
46  struct MYSOFA_LOOKUP *lookup;
47  struct MYSOFA_NEIGHBORHOOD *neighborhood;
48  int ir_samples; /* length of one impulse response (IR) */
49  int n_samples; /* ir_samples to next power of 2 */
50  float *lir, *rir; /* IRs (time-domain) */
51  float *fir;
52  int max_delay;
53 } MySofa;
54 
55 typedef struct VirtualSpeaker {
57  float azim;
58  float elev;
60 
61 typedef struct SOFAlizerContext {
62  const AVClass *class;
63 
64  char *filename; /* name of SOFA file */
65  MySofa sofa; /* contains data of the SOFA file */
66 
67  int sample_rate; /* sample rate from SOFA file */
68  float *speaker_azim; /* azimuth of the virtual loudspeakers */
69  float *speaker_elev; /* elevation of the virtual loudspeakers */
70  char *speakers_pos; /* custom positions of the virtual loudspeakers */
71  float lfe_gain; /* initial gain for the LFE channel */
72  float gain_lfe; /* gain applied to LFE channel */
73  int lfe_channel; /* LFE channel position in channel layout */
74 
75  int n_conv; /* number of channels to convolute */
76 
77  /* buffer variables (for convolution) */
78  float *ringbuffer[2]; /* buffers input samples, length of one buffer: */
79  /* no. input ch. (incl. LFE) x buffer_length */
80  int write[2]; /* current write position to ringbuffer */
81  int buffer_length; /* is: longest IR plus max. delay in all SOFA files */
82  /* then choose next power of 2 */
83  int n_fft; /* number of samples in one FFT block */
84 
85  /* netCDF variables */
86  int *delay[2]; /* broadband delay for each channel/IR to be convolved */
87 
88  float *data_ir[2]; /* IRs for all channels to be convolved */
89  /* (this excludes the LFE) */
90  float *temp_src[2];
91  FFTComplex *temp_fft[2]; /* Array to hold FFT values */
92  FFTComplex *temp_afft[2]; /* Array to accumulate FFT values prior to IFFT */
93 
94  /* control variables */
95  float gain; /* filter gain (in dB) */
96  float rotation; /* rotation of virtual loudspeakers (in degrees) */
97  float elevation; /* elevation of virtual loudspeakers (in deg.) */
98  float radius; /* distance virtual loudspeakers to listener (in metres) */
99  int type; /* processing type */
100  int framesize; /* size of buffer */
101  int normalize; /* should all IRs be normalized upon import ? */
102  int interpolate; /* should wanted IRs be interpolated from neighbors ? */
103  int minphase; /* should all IRs be minphased upon import ? */
104  float anglestep; /* neighbor search angle step, in agles */
105  float radstep; /* neighbor search radius step, in meters */
106 
108 
109  FFTContext *fft[2], *ifft[2];
111 
114 
115 static int close_sofa(struct MySofa *sofa)
116 {
117  if (sofa->neighborhood)
118  mysofa_neighborhood_free(sofa->neighborhood);
119  sofa->neighborhood = NULL;
120  if (sofa->lookup)
121  mysofa_lookup_free(sofa->lookup);
122  sofa->lookup = NULL;
123  if (sofa->hrtf)
124  mysofa_free(sofa->hrtf);
125  sofa->hrtf = NULL;
126  av_freep(&sofa->fir);
127 
128  return 0;
129 }
130 
131 static int preload_sofa(AVFilterContext *ctx, char *filename, int *samplingrate)
132 {
133  struct SOFAlizerContext *s = ctx->priv;
134  struct MYSOFA_HRTF *mysofa;
135  char *license;
136  int ret;
137 
138  mysofa = mysofa_load(filename, &ret);
139  s->sofa.hrtf = mysofa;
140  if (ret || !mysofa) {
141  av_log(ctx, AV_LOG_ERROR, "Can't find SOFA-file '%s'\n", filename);
142  return AVERROR(EINVAL);
143  }
144 
145  ret = mysofa_check(mysofa);
146  if (ret != MYSOFA_OK) {
147  av_log(ctx, AV_LOG_ERROR, "Selected SOFA file is invalid. Please select valid SOFA file.\n");
148  return ret;
149  }
150 
151  if (s->normalize)
152  mysofa_loudness(s->sofa.hrtf);
153 
154  if (s->minphase)
155  mysofa_minphase(s->sofa.hrtf, 0.01f);
156 
157  mysofa_tocartesian(s->sofa.hrtf);
158 
159  s->sofa.lookup = mysofa_lookup_init(s->sofa.hrtf);
160  if (s->sofa.lookup == NULL)
161  return AVERROR(EINVAL);
162 
163  if (s->interpolate)
164  s->sofa.neighborhood = mysofa_neighborhood_init_withstepdefine(s->sofa.hrtf,
165  s->sofa.lookup,
166  s->anglestep,
167  s->radstep);
168 
169  s->sofa.fir = av_calloc(s->sofa.hrtf->N * s->sofa.hrtf->R, sizeof(*s->sofa.fir));
170  if (!s->sofa.fir)
171  return AVERROR(ENOMEM);
172 
173  if (mysofa->DataSamplingRate.elements != 1)
174  return AVERROR(EINVAL);
175  av_log(ctx, AV_LOG_DEBUG, "Original IR length: %d.\n", mysofa->N);
176  *samplingrate = mysofa->DataSamplingRate.values[0];
177  license = mysofa_getAttribute(mysofa->attributes, (char *)"License");
178  if (license)
179  av_log(ctx, AV_LOG_INFO, "SOFA license: %s\n", license);
180 
181  return 0;
182 }
183 
184 static int parse_channel_name(char **arg, int *rchannel, char *buf)
185 {
186  int len, i, channel_id = 0;
187  int64_t layout, layout0;
188 
189  /* try to parse a channel name, e.g. "FL" */
190  if (av_sscanf(*arg, "%7[A-Z]%n", buf, &len)) {
191  layout0 = layout = av_get_channel_layout(buf);
192  /* channel_id <- first set bit in layout */
193  for (i = 32; i > 0; i >>= 1) {
194  if (layout >= 1LL << i) {
195  channel_id += i;
196  layout >>= i;
197  }
198  }
199  /* reject layouts that are not a single channel */
200  if (channel_id >= 64 || layout0 != 1LL << channel_id)
201  return AVERROR(EINVAL);
202  *rchannel = channel_id;
203  *arg += len;
204  return 0;
205  }
206  return AVERROR(EINVAL);
207 }
208 
209 static void parse_speaker_pos(AVFilterContext *ctx, int64_t in_channel_layout)
210 {
211  SOFAlizerContext *s = ctx->priv;
212  char *arg, *tokenizer, *p, *args = av_strdup(s->speakers_pos);
213 
214  if (!args)
215  return;
216  p = args;
217 
218  while ((arg = av_strtok(p, "|", &tokenizer))) {
219  char buf[8];
220  float azim, elev;
221  int out_ch_id;
222 
223  p = NULL;
224  if (parse_channel_name(&arg, &out_ch_id, buf)) {
225  av_log(ctx, AV_LOG_WARNING, "Failed to parse \'%s\' as channel name.\n", buf);
226  continue;
227  }
228  if (av_sscanf(arg, "%f %f", &azim, &elev) == 2) {
229  s->vspkrpos[out_ch_id].set = 1;
230  s->vspkrpos[out_ch_id].azim = azim;
231  s->vspkrpos[out_ch_id].elev = elev;
232  } else if (av_sscanf(arg, "%f", &azim) == 1) {
233  s->vspkrpos[out_ch_id].set = 1;
234  s->vspkrpos[out_ch_id].azim = azim;
235  s->vspkrpos[out_ch_id].elev = 0;
236  }
237  }
238 
239  av_free(args);
240 }
241 
243  float *speaker_azim, float *speaker_elev)
244 {
245  struct SOFAlizerContext *s = ctx->priv;
246  uint64_t channels_layout = ctx->inputs[0]->channel_layout;
247  float azim[16] = { 0 };
248  float elev[16] = { 0 };
249  int m, ch, n_conv = ctx->inputs[0]->channels; /* get no. input channels */
250 
251  if (n_conv > 16)
252  return AVERROR(EINVAL);
253 
254  s->lfe_channel = -1;
255 
256  if (s->speakers_pos)
257  parse_speaker_pos(ctx, channels_layout);
258 
259  /* set speaker positions according to input channel configuration: */
260  for (m = 0, ch = 0; ch < n_conv && m < 64; m++) {
261  uint64_t mask = channels_layout & (1ULL << m);
262 
263  switch (mask) {
264  case AV_CH_FRONT_LEFT: azim[ch] = 30; break;
265  case AV_CH_FRONT_RIGHT: azim[ch] = 330; break;
266  case AV_CH_FRONT_CENTER: azim[ch] = 0; break;
267  case AV_CH_LOW_FREQUENCY:
268  case AV_CH_LOW_FREQUENCY_2: s->lfe_channel = ch; break;
269  case AV_CH_BACK_LEFT: azim[ch] = 150; break;
270  case AV_CH_BACK_RIGHT: azim[ch] = 210; break;
271  case AV_CH_BACK_CENTER: azim[ch] = 180; break;
272  case AV_CH_SIDE_LEFT: azim[ch] = 90; break;
273  case AV_CH_SIDE_RIGHT: azim[ch] = 270; break;
274  case AV_CH_FRONT_LEFT_OF_CENTER: azim[ch] = 15; break;
275  case AV_CH_FRONT_RIGHT_OF_CENTER: azim[ch] = 345; break;
276  case AV_CH_TOP_CENTER: azim[ch] = 0;
277  elev[ch] = 90; break;
278  case AV_CH_TOP_FRONT_LEFT: azim[ch] = 30;
279  elev[ch] = 45; break;
280  case AV_CH_TOP_FRONT_CENTER: azim[ch] = 0;
281  elev[ch] = 45; break;
282  case AV_CH_TOP_FRONT_RIGHT: azim[ch] = 330;
283  elev[ch] = 45; break;
284  case AV_CH_TOP_BACK_LEFT: azim[ch] = 150;
285  elev[ch] = 45; break;
286  case AV_CH_TOP_BACK_RIGHT: azim[ch] = 210;
287  elev[ch] = 45; break;
288  case AV_CH_TOP_BACK_CENTER: azim[ch] = 180;
289  elev[ch] = 45; break;
290  case AV_CH_WIDE_LEFT: azim[ch] = 90; break;
291  case AV_CH_WIDE_RIGHT: azim[ch] = 270; break;
292  case AV_CH_SURROUND_DIRECT_LEFT: azim[ch] = 90; break;
293  case AV_CH_SURROUND_DIRECT_RIGHT: azim[ch] = 270; break;
294  case AV_CH_STEREO_LEFT: azim[ch] = 90; break;
295  case AV_CH_STEREO_RIGHT: azim[ch] = 270; break;
296  case 0: break;
297  default:
298  return AVERROR(EINVAL);
299  }
300 
301  if (s->vspkrpos[m].set) {
302  azim[ch] = s->vspkrpos[m].azim;
303  elev[ch] = s->vspkrpos[m].elev;
304  }
305 
306  if (mask)
307  ch++;
308  }
309 
310  memcpy(speaker_azim, azim, n_conv * sizeof(float));
311  memcpy(speaker_elev, elev, n_conv * sizeof(float));
312 
313  return 0;
314 
315 }
316 
317 typedef struct ThreadData {
318  AVFrame *in, *out;
319  int *write;
320  int **delay;
321  float **ir;
322  int *n_clippings;
323  float **ringbuffer;
324  float **temp_src;
327 } ThreadData;
328 
329 static int sofalizer_convolute(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
330 {
331  SOFAlizerContext *s = ctx->priv;
332  ThreadData *td = arg;
333  AVFrame *in = td->in, *out = td->out;
334  int offset = jobnr;
335  int *write = &td->write[jobnr];
336  const int *const delay = td->delay[jobnr];
337  const float *const ir = td->ir[jobnr];
338  int *n_clippings = &td->n_clippings[jobnr];
339  float *ringbuffer = td->ringbuffer[jobnr];
340  float *temp_src = td->temp_src[jobnr];
341  const int ir_samples = s->sofa.ir_samples; /* length of one IR */
342  const int n_samples = s->sofa.n_samples;
343  const int planar = in->format == AV_SAMPLE_FMT_FLTP;
344  const int mult = 1 + !planar;
345  const float *src = (const float *)in->extended_data[0]; /* get pointer to audio input buffer */
346  float *dst = (float *)out->extended_data[jobnr * planar]; /* get pointer to audio output buffer */
347  const int in_channels = s->n_conv; /* number of input channels */
348  /* ring buffer length is: longest IR plus max. delay -> next power of 2 */
349  const int buffer_length = s->buffer_length;
350  /* -1 for AND instead of MODULO (applied to powers of 2): */
351  const uint32_t modulo = (uint32_t)buffer_length - 1;
352  float *buffer[16]; /* holds ringbuffer for each input channel */
353  int wr = *write;
354  int read;
355  int i, l;
356 
357  if (!planar)
358  dst += offset;
359 
360  for (l = 0; l < in_channels; l++) {
361  /* get starting address of ringbuffer for each input channel */
362  buffer[l] = ringbuffer + l * buffer_length;
363  }
364 
365  for (i = 0; i < in->nb_samples; i++) {
366  const float *temp_ir = ir; /* using same set of IRs for each sample */
367 
368  dst[0] = 0;
369  if (planar) {
370  for (l = 0; l < in_channels; l++) {
371  const float *srcp = (const float *)in->extended_data[l];
372 
373  /* write current input sample to ringbuffer (for each channel) */
374  buffer[l][wr] = srcp[i];
375  }
376  } else {
377  for (l = 0; l < in_channels; l++) {
378  /* write current input sample to ringbuffer (for each channel) */
379  buffer[l][wr] = src[l];
380  }
381  }
382 
383  /* loop goes through all channels to be convolved */
384  for (l = 0; l < in_channels; l++) {
385  const float *const bptr = buffer[l];
386 
387  if (l == s->lfe_channel) {
388  /* LFE is an input channel but requires no convolution */
389  /* apply gain to LFE signal and add to output buffer */
390  dst[0] += *(buffer[s->lfe_channel] + wr) * s->gain_lfe;
391  temp_ir += n_samples;
392  continue;
393  }
394 
395  /* current read position in ringbuffer: input sample write position
396  * - delay for l-th ch. + diff. betw. IR length and buffer length
397  * (mod buffer length) */
398  read = (wr - delay[l] - (ir_samples - 1) + buffer_length) & modulo;
399 
400  if (read + ir_samples < buffer_length) {
401  memmove(temp_src, bptr + read, ir_samples * sizeof(*temp_src));
402  } else {
403  int len = FFMIN(n_samples - (read % ir_samples), buffer_length - read);
404 
405  memmove(temp_src, bptr + read, len * sizeof(*temp_src));
406  memmove(temp_src + len, bptr, (n_samples - len) * sizeof(*temp_src));
407  }
408 
409  /* multiply signal and IR, and add up the results */
410  dst[0] += s->fdsp->scalarproduct_float(temp_ir, temp_src, FFALIGN(ir_samples, 32));
411  temp_ir += n_samples;
412  }
413 
414  /* clippings counter */
415  if (fabsf(dst[0]) > 1)
416  n_clippings[0]++;
417 
418  /* move output buffer pointer by +2 to get to next sample of processed channel: */
419  dst += mult;
420  src += in_channels;
421  wr = (wr + 1) & modulo; /* update ringbuffer write position */
422  }
423 
424  *write = wr; /* remember write position in ringbuffer for next call */
425 
426  return 0;
427 }
428 
429 static int sofalizer_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
430 {
431  SOFAlizerContext *s = ctx->priv;
432  ThreadData *td = arg;
433  AVFrame *in = td->in, *out = td->out;
434  int offset = jobnr;
435  int *write = &td->write[jobnr];
436  FFTComplex *hrtf = s->data_hrtf[jobnr]; /* get pointers to current HRTF data */
437  int *n_clippings = &td->n_clippings[jobnr];
438  float *ringbuffer = td->ringbuffer[jobnr];
439  const int ir_samples = s->sofa.ir_samples; /* length of one IR */
440  const int planar = in->format == AV_SAMPLE_FMT_FLTP;
441  const int mult = 1 + !planar;
442  float *dst = (float *)out->extended_data[jobnr * planar]; /* get pointer to audio output buffer */
443  const int in_channels = s->n_conv; /* number of input channels */
444  /* ring buffer length is: longest IR plus max. delay -> next power of 2 */
445  const int buffer_length = s->buffer_length;
446  /* -1 for AND instead of MODULO (applied to powers of 2): */
447  const uint32_t modulo = (uint32_t)buffer_length - 1;
448  FFTComplex *fft_in = s->temp_fft[jobnr]; /* temporary array for FFT input/output data */
449  FFTComplex *fft_acc = s->temp_afft[jobnr];
450  FFTContext *ifft = s->ifft[jobnr];
451  FFTContext *fft = s->fft[jobnr];
452  const int n_conv = s->n_conv;
453  const int n_fft = s->n_fft;
454  const float fft_scale = 1.0f / s->n_fft;
455  FFTComplex *hrtf_offset;
456  int wr = *write;
457  int n_read;
458  int i, j;
459 
460  if (!planar)
461  dst += offset;
462 
463  /* find minimum between number of samples and output buffer length:
464  * (important, if one IR is longer than the output buffer) */
465  n_read = FFMIN(ir_samples, in->nb_samples);
466  for (j = 0; j < n_read; j++) {
467  /* initialize output buf with saved signal from overflow buf */
468  dst[mult * j] = ringbuffer[wr];
469  ringbuffer[wr] = 0.0f; /* re-set read samples to zero */
470  /* update ringbuffer read/write position */
471  wr = (wr + 1) & modulo;
472  }
473 
474  /* initialize rest of output buffer with 0 */
475  for (j = n_read; j < in->nb_samples; j++) {
476  dst[mult * j] = 0;
477  }
478 
479  /* fill FFT accumulation with 0 */
480  memset(fft_acc, 0, sizeof(FFTComplex) * n_fft);
481 
482  for (i = 0; i < n_conv; i++) {
483  const float *src = (const float *)in->extended_data[i * planar]; /* get pointer to audio input buffer */
484 
485  if (i == s->lfe_channel) { /* LFE */
486  if (in->format == AV_SAMPLE_FMT_FLT) {
487  for (j = 0; j < in->nb_samples; j++) {
488  /* apply gain to LFE signal and add to output buffer */
489  dst[2 * j] += src[i + j * in_channels] * s->gain_lfe;
490  }
491  } else {
492  for (j = 0; j < in->nb_samples; j++) {
493  /* apply gain to LFE signal and add to output buffer */
494  dst[j] += src[j] * s->gain_lfe;
495  }
496  }
497  continue;
498  }
499 
500  /* outer loop: go through all input channels to be convolved */
501  offset = i * n_fft; /* no. samples already processed */
502  hrtf_offset = hrtf + offset;
503 
504  /* fill FFT input with 0 (we want to zero-pad) */
505  memset(fft_in, 0, sizeof(FFTComplex) * n_fft);
506 
507  if (in->format == AV_SAMPLE_FMT_FLT) {
508  for (j = 0; j < in->nb_samples; j++) {
509  /* prepare input for FFT */
510  /* write all samples of current input channel to FFT input array */
511  fft_in[j].re = src[j * in_channels + i];
512  }
513  } else {
514  for (j = 0; j < in->nb_samples; j++) {
515  /* prepare input for FFT */
516  /* write all samples of current input channel to FFT input array */
517  fft_in[j].re = src[j];
518  }
519  }
520 
521  /* transform input signal of current channel to frequency domain */
522  av_fft_permute(fft, fft_in);
523  av_fft_calc(fft, fft_in);
524  for (j = 0; j < n_fft; j++) {
525  const FFTComplex *hcomplex = hrtf_offset + j;
526  const float re = fft_in[j].re;
527  const float im = fft_in[j].im;
528 
529  /* complex multiplication of input signal and HRTFs */
530  /* output channel (real): */
531  fft_acc[j].re += re * hcomplex->re - im * hcomplex->im;
532  /* output channel (imag): */
533  fft_acc[j].im += re * hcomplex->im + im * hcomplex->re;
534  }
535  }
536 
537  /* transform output signal of current channel back to time domain */
538  av_fft_permute(ifft, fft_acc);
539  av_fft_calc(ifft, fft_acc);
540 
541  for (j = 0; j < in->nb_samples; j++) {
542  /* write output signal of current channel to output buffer */
543  dst[mult * j] += fft_acc[j].re * fft_scale;
544  }
545 
546  for (j = 0; j < ir_samples - 1; j++) { /* overflow length is IR length - 1 */
547  /* write the rest of output signal to overflow buffer */
548  int write_pos = (wr + j) & modulo;
549 
550  *(ringbuffer + write_pos) += fft_acc[in->nb_samples + j].re * fft_scale;
551  }
552 
553  /* go through all samples of current output buffer: count clippings */
554  for (i = 0; i < out->nb_samples; i++) {
555  /* clippings counter */
556  if (fabsf(dst[i * mult]) > 1) { /* if current output sample > 1 */
557  n_clippings[0]++;
558  }
559  }
560 
561  /* remember read/write position in ringbuffer for next call */
562  *write = wr;
563 
564  return 0;
565 }
566 
567 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
568 {
569  AVFilterContext *ctx = inlink->dst;
570  SOFAlizerContext *s = ctx->priv;
571  AVFilterLink *outlink = ctx->outputs[0];
572  int n_clippings[2] = { 0 };
573  ThreadData td;
574  AVFrame *out;
575 
576  out = ff_get_audio_buffer(outlink, in->nb_samples);
577  if (!out) {
578  av_frame_free(&in);
579  return AVERROR(ENOMEM);
580  }
581  av_frame_copy_props(out, in);
582 
583  td.in = in; td.out = out; td.write = s->write;
584  td.delay = s->delay; td.ir = s->data_ir; td.n_clippings = n_clippings;
585  td.ringbuffer = s->ringbuffer; td.temp_src = s->temp_src;
586  td.temp_fft = s->temp_fft;
587  td.temp_afft = s->temp_afft;
588 
589  if (s->type == TIME_DOMAIN) {
590  ctx->internal->execute(ctx, sofalizer_convolute, &td, NULL, 2);
591  } else if (s->type == FREQUENCY_DOMAIN) {
592  ctx->internal->execute(ctx, sofalizer_fast_convolute, &td, NULL, 2);
593  }
594  emms_c();
595 
596  /* display error message if clipping occurred */
597  if (n_clippings[0] + n_clippings[1] > 0) {
598  av_log(ctx, AV_LOG_WARNING, "%d of %d samples clipped. Please reduce gain.\n",
599  n_clippings[0] + n_clippings[1], out->nb_samples * 2);
600  }
601 
602  av_frame_free(&in);
603  return ff_filter_frame(outlink, out);
604 }
605 
607 {
608  struct SOFAlizerContext *s = ctx->priv;
611  int ret, sample_rates[] = { 48000, -1 };
612  static const enum AVSampleFormat sample_fmts[] = {
615  };
616 
617  formats = ff_make_format_list(sample_fmts);
618  if (!formats)
619  return AVERROR(ENOMEM);
620  ret = ff_set_common_formats(ctx, formats);
621  if (ret)
622  return ret;
623 
624  layouts = ff_all_channel_layouts();
625  if (!layouts)
626  return AVERROR(ENOMEM);
627 
628  ret = ff_channel_layouts_ref(layouts, &ctx->inputs[0]->out_channel_layouts);
629  if (ret)
630  return ret;
631 
632  layouts = NULL;
634  if (ret)
635  return ret;
636 
637  ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->in_channel_layouts);
638  if (ret)
639  return ret;
640 
641  sample_rates[0] = s->sample_rate;
642  formats = ff_make_format_list(sample_rates);
643  if (!formats)
644  return AVERROR(ENOMEM);
645  return ff_set_common_samplerates(ctx, formats);
646 }
647 
648 static int getfilter_float(AVFilterContext *ctx, float x, float y, float z,
649  float *left, float *right,
650  float *delay_left, float *delay_right)
651 {
652  struct SOFAlizerContext *s = ctx->priv;
653  float c[3], delays[2];
654  float *fl, *fr;
655  int nearest;
656  int *neighbors;
657  float *res;
658 
659  c[0] = x, c[1] = y, c[2] = z;
660  nearest = mysofa_lookup(s->sofa.lookup, c);
661  if (nearest < 0)
662  return AVERROR(EINVAL);
663 
664  if (s->interpolate) {
665  neighbors = mysofa_neighborhood(s->sofa.neighborhood, nearest);
666  res = mysofa_interpolate(s->sofa.hrtf, c,
667  nearest, neighbors,
668  s->sofa.fir, delays);
669  } else {
670  if (s->sofa.hrtf->DataDelay.elements > s->sofa.hrtf->R) {
671  delays[0] = s->sofa.hrtf->DataDelay.values[nearest * s->sofa.hrtf->R];
672  delays[1] = s->sofa.hrtf->DataDelay.values[nearest * s->sofa.hrtf->R + 1];
673  } else {
674  delays[0] = s->sofa.hrtf->DataDelay.values[0];
675  delays[1] = s->sofa.hrtf->DataDelay.values[1];
676  }
677  res = s->sofa.hrtf->DataIR.values + nearest * s->sofa.hrtf->N * s->sofa.hrtf->R;
678  }
679 
680  *delay_left = delays[0];
681  *delay_right = delays[1];
682 
683  fl = res;
684  fr = res + s->sofa.hrtf->N;
685 
686  memcpy(left, fl, sizeof(float) * s->sofa.hrtf->N);
687  memcpy(right, fr, sizeof(float) * s->sofa.hrtf->N);
688 
689  return 0;
690 }
691 
692 static int load_data(AVFilterContext *ctx, int azim, int elev, float radius, int sample_rate)
693 {
694  struct SOFAlizerContext *s = ctx->priv;
695  int n_samples;
696  int ir_samples;
697  int n_conv = s->n_conv; /* no. channels to convolve */
698  int n_fft;
699  float delay_l; /* broadband delay for each IR */
700  float delay_r;
701  int nb_input_channels = ctx->inputs[0]->channels; /* no. input channels */
702  float gain_lin = expf((s->gain - 3 * nb_input_channels) / 20 * M_LN10); /* gain - 3dB/channel */
703  FFTComplex *data_hrtf_l = NULL;
704  FFTComplex *data_hrtf_r = NULL;
705  FFTComplex *fft_in_l = NULL;
706  FFTComplex *fft_in_r = NULL;
707  float *data_ir_l = NULL;
708  float *data_ir_r = NULL;
709  int offset = 0; /* used for faster pointer arithmetics in for-loop */
710  int i, j, azim_orig = azim, elev_orig = elev;
711  int ret = 0;
712  int n_current;
713  int n_max = 0;
714 
715  av_log(ctx, AV_LOG_DEBUG, "IR length: %d.\n", s->sofa.hrtf->N);
716  s->sofa.ir_samples = s->sofa.hrtf->N;
717  s->sofa.n_samples = 1 << (32 - ff_clz(s->sofa.ir_samples));
718 
719  n_samples = s->sofa.n_samples;
720  ir_samples = s->sofa.ir_samples;
721 
722  if (s->type == TIME_DOMAIN) {
723  s->data_ir[0] = av_calloc(n_samples, sizeof(float) * s->n_conv);
724  s->data_ir[1] = av_calloc(n_samples, sizeof(float) * s->n_conv);
725 
726  if (!s->data_ir[0] || !s->data_ir[1]) {
727  ret = AVERROR(ENOMEM);
728  goto fail;
729  }
730  }
731 
732  s->delay[0] = av_calloc(s->n_conv, sizeof(int));
733  s->delay[1] = av_calloc(s->n_conv, sizeof(int));
734 
735  if (!s->delay[0] || !s->delay[1]) {
736  ret = AVERROR(ENOMEM);
737  goto fail;
738  }
739 
740  /* get temporary IR for L and R channel */
741  data_ir_l = av_calloc(n_conv * n_samples, sizeof(*data_ir_l));
742  data_ir_r = av_calloc(n_conv * n_samples, sizeof(*data_ir_r));
743  if (!data_ir_r || !data_ir_l) {
744  ret = AVERROR(ENOMEM);
745  goto fail;
746  }
747 
748  if (s->type == TIME_DOMAIN) {
749  s->temp_src[0] = av_calloc(n_samples, sizeof(float));
750  s->temp_src[1] = av_calloc(n_samples, sizeof(float));
751  if (!s->temp_src[0] || !s->temp_src[1]) {
752  ret = AVERROR(ENOMEM);
753  goto fail;
754  }
755  }
756 
757  s->speaker_azim = av_calloc(s->n_conv, sizeof(*s->speaker_azim));
758  s->speaker_elev = av_calloc(s->n_conv, sizeof(*s->speaker_elev));
759  if (!s->speaker_azim || !s->speaker_elev) {
760  ret = AVERROR(ENOMEM);
761  goto fail;
762  }
763 
764  /* get speaker positions */
765  if ((ret = get_speaker_pos(ctx, s->speaker_azim, s->speaker_elev)) < 0) {
766  av_log(ctx, AV_LOG_ERROR, "Couldn't get speaker positions. Input channel configuration not supported.\n");
767  goto fail;
768  }
769 
770  for (i = 0; i < s->n_conv; i++) {
771  float coordinates[3];
772 
773  /* load and store IRs and corresponding delays */
774  azim = (int)(s->speaker_azim[i] + azim_orig) % 360;
775  elev = (int)(s->speaker_elev[i] + elev_orig) % 90;
776 
777  coordinates[0] = azim;
778  coordinates[1] = elev;
779  coordinates[2] = radius;
780 
781  mysofa_s2c(coordinates);
782 
783  /* get id of IR closest to desired position */
784  ret = getfilter_float(ctx, coordinates[0], coordinates[1], coordinates[2],
785  data_ir_l + n_samples * i,
786  data_ir_r + n_samples * i,
787  &delay_l, &delay_r);
788  if (ret < 0)
789  goto fail;
790 
791  s->delay[0][i] = delay_l * sample_rate;
792  s->delay[1][i] = delay_r * sample_rate;
793 
794  s->sofa.max_delay = FFMAX3(s->sofa.max_delay, s->delay[0][i], s->delay[1][i]);
795  }
796 
797  /* get size of ringbuffer (longest IR plus max. delay) */
798  /* then choose next power of 2 for performance optimization */
799  n_current = n_samples + s->sofa.max_delay;
800  /* length of longest IR plus max. delay */
801  n_max = FFMAX(n_max, n_current);
802 
803  /* buffer length is longest IR plus max. delay -> next power of 2
804  (32 - count leading zeros gives required exponent) */
805  s->buffer_length = 1 << (32 - ff_clz(n_max));
806  s->n_fft = n_fft = 1 << (32 - ff_clz(n_max + s->framesize));
807 
808  if (s->type == FREQUENCY_DOMAIN) {
809  av_fft_end(s->fft[0]);
810  av_fft_end(s->fft[1]);
811  s->fft[0] = av_fft_init(av_log2(s->n_fft), 0);
812  s->fft[1] = av_fft_init(av_log2(s->n_fft), 0);
813  av_fft_end(s->ifft[0]);
814  av_fft_end(s->ifft[1]);
815  s->ifft[0] = av_fft_init(av_log2(s->n_fft), 1);
816  s->ifft[1] = av_fft_init(av_log2(s->n_fft), 1);
817 
818  if (!s->fft[0] || !s->fft[1] || !s->ifft[0] || !s->ifft[1]) {
819  av_log(ctx, AV_LOG_ERROR, "Unable to create FFT contexts of size %d.\n", s->n_fft);
820  ret = AVERROR(ENOMEM);
821  goto fail;
822  }
823  }
824 
825  if (s->type == TIME_DOMAIN) {
826  s->ringbuffer[0] = av_calloc(s->buffer_length, sizeof(float) * nb_input_channels);
827  s->ringbuffer[1] = av_calloc(s->buffer_length, sizeof(float) * nb_input_channels);
828  } else if (s->type == FREQUENCY_DOMAIN) {
829  /* get temporary HRTF memory for L and R channel */
830  data_hrtf_l = av_malloc_array(n_fft, sizeof(*data_hrtf_l) * n_conv);
831  data_hrtf_r = av_malloc_array(n_fft, sizeof(*data_hrtf_r) * n_conv);
832  if (!data_hrtf_r || !data_hrtf_l) {
833  ret = AVERROR(ENOMEM);
834  goto fail;
835  }
836 
837  s->ringbuffer[0] = av_calloc(s->buffer_length, sizeof(float));
838  s->ringbuffer[1] = av_calloc(s->buffer_length, sizeof(float));
839  s->temp_fft[0] = av_malloc_array(s->n_fft, sizeof(FFTComplex));
840  s->temp_fft[1] = av_malloc_array(s->n_fft, sizeof(FFTComplex));
841  s->temp_afft[0] = av_malloc_array(s->n_fft, sizeof(FFTComplex));
842  s->temp_afft[1] = av_malloc_array(s->n_fft, sizeof(FFTComplex));
843  if (!s->temp_fft[0] || !s->temp_fft[1] ||
844  !s->temp_afft[0] || !s->temp_afft[1]) {
845  ret = AVERROR(ENOMEM);
846  goto fail;
847  }
848  }
849 
850  if (!s->ringbuffer[0] || !s->ringbuffer[1]) {
851  ret = AVERROR(ENOMEM);
852  goto fail;
853  }
854 
855  if (s->type == FREQUENCY_DOMAIN) {
856  fft_in_l = av_calloc(n_fft, sizeof(*fft_in_l));
857  fft_in_r = av_calloc(n_fft, sizeof(*fft_in_r));
858  if (!fft_in_l || !fft_in_r) {
859  ret = AVERROR(ENOMEM);
860  goto fail;
861  }
862  }
863 
864  for (i = 0; i < s->n_conv; i++) {
865  float *lir, *rir;
866 
867  offset = i * n_samples; /* no. samples already written */
868 
869  lir = data_ir_l + offset;
870  rir = data_ir_r + offset;
871 
872  if (s->type == TIME_DOMAIN) {
873  for (j = 0; j < ir_samples; j++) {
874  /* load reversed IRs of the specified source position
875  * sample-by-sample for left and right ear; and apply gain */
876  s->data_ir[0][offset + j] = lir[ir_samples - 1 - j] * gain_lin;
877  s->data_ir[1][offset + j] = rir[ir_samples - 1 - j] * gain_lin;
878  }
879  } else if (s->type == FREQUENCY_DOMAIN) {
880  memset(fft_in_l, 0, n_fft * sizeof(*fft_in_l));
881  memset(fft_in_r, 0, n_fft * sizeof(*fft_in_r));
882 
883  offset = i * n_fft; /* no. samples already written */
884  for (j = 0; j < ir_samples; j++) {
885  /* load non-reversed IRs of the specified source position
886  * sample-by-sample and apply gain,
887  * L channel is loaded to real part, R channel to imag part,
888  * IRs are shifted by L and R delay */
889  fft_in_l[s->delay[0][i] + j].re = lir[j] * gain_lin;
890  fft_in_r[s->delay[1][i] + j].re = rir[j] * gain_lin;
891  }
892 
893  /* actually transform to frequency domain (IRs -> HRTFs) */
894  av_fft_permute(s->fft[0], fft_in_l);
895  av_fft_calc(s->fft[0], fft_in_l);
896  memcpy(data_hrtf_l + offset, fft_in_l, n_fft * sizeof(*fft_in_l));
897  av_fft_permute(s->fft[0], fft_in_r);
898  av_fft_calc(s->fft[0], fft_in_r);
899  memcpy(data_hrtf_r + offset, fft_in_r, n_fft * sizeof(*fft_in_r));
900  }
901  }
902 
903  if (s->type == FREQUENCY_DOMAIN) {
904  s->data_hrtf[0] = av_malloc_array(n_fft * s->n_conv, sizeof(FFTComplex));
905  s->data_hrtf[1] = av_malloc_array(n_fft * s->n_conv, sizeof(FFTComplex));
906  if (!s->data_hrtf[0] || !s->data_hrtf[1]) {
907  ret = AVERROR(ENOMEM);
908  goto fail;
909  }
910 
911  memcpy(s->data_hrtf[0], data_hrtf_l, /* copy HRTF data to */
912  sizeof(FFTComplex) * n_conv * n_fft); /* filter struct */
913  memcpy(s->data_hrtf[1], data_hrtf_r,
914  sizeof(FFTComplex) * n_conv * n_fft);
915  }
916 
917 fail:
918  av_freep(&data_hrtf_l); /* free temporary HRTF memory */
919  av_freep(&data_hrtf_r);
920 
921  av_freep(&data_ir_l); /* free temprary IR memory */
922  av_freep(&data_ir_r);
923 
924  av_freep(&fft_in_l); /* free temporary FFT memory */
925  av_freep(&fft_in_r);
926 
927  return ret;
928 }
929 
931 {
932  SOFAlizerContext *s = ctx->priv;
933  int ret;
934 
935  if (!s->filename) {
936  av_log(ctx, AV_LOG_ERROR, "Valid SOFA filename must be set.\n");
937  return AVERROR(EINVAL);
938  }
939 
940  /* preload SOFA file, */
941  ret = preload_sofa(ctx, s->filename, &s->sample_rate);
942  if (ret) {
943  /* file loading error */
944  av_log(ctx, AV_LOG_ERROR, "Error while loading SOFA file: '%s'\n", s->filename);
945  } else { /* no file loading error, resampling not required */
946  av_log(ctx, AV_LOG_DEBUG, "File '%s' loaded.\n", s->filename);
947  }
948 
949  if (ret) {
950  av_log(ctx, AV_LOG_ERROR, "No valid SOFA file could be loaded. Please specify valid SOFA file.\n");
951  return ret;
952  }
953 
955  if (!s->fdsp)
956  return AVERROR(ENOMEM);
957 
958  return 0;
959 }
960 
961 static int config_input(AVFilterLink *inlink)
962 {
963  AVFilterContext *ctx = inlink->dst;
964  SOFAlizerContext *s = ctx->priv;
965  int ret;
966 
967  if (s->type == FREQUENCY_DOMAIN) {
968  inlink->partial_buf_size =
969  inlink->min_samples =
970  inlink->max_samples = s->framesize;
971  }
972 
973  /* gain -3 dB per channel */
974  s->gain_lfe = expf((s->gain - 3 * inlink->channels + s->lfe_gain) / 20 * M_LN10);
975 
976  s->n_conv = inlink->channels;
977 
978  /* load IRs to data_ir[0] and data_ir[1] for required directions */
979  if ((ret = load_data(ctx, s->rotation, s->elevation, s->radius, inlink->sample_rate)) < 0)
980  return ret;
981 
982  av_log(ctx, AV_LOG_DEBUG, "Samplerate: %d Channels to convolute: %d, Length of ringbuffer: %d x %d\n",
983  inlink->sample_rate, s->n_conv, inlink->channels, s->buffer_length);
984 
985  return 0;
986 }
987 
989 {
990  SOFAlizerContext *s = ctx->priv;
991 
992  close_sofa(&s->sofa);
993  av_fft_end(s->ifft[0]);
994  av_fft_end(s->ifft[1]);
995  av_fft_end(s->fft[0]);
996  av_fft_end(s->fft[1]);
997  s->ifft[0] = NULL;
998  s->ifft[1] = NULL;
999  s->fft[0] = NULL;
1000  s->fft[1] = NULL;
1001  av_freep(&s->delay[0]);
1002  av_freep(&s->delay[1]);
1003  av_freep(&s->data_ir[0]);
1004  av_freep(&s->data_ir[1]);
1005  av_freep(&s->ringbuffer[0]);
1006  av_freep(&s->ringbuffer[1]);
1007  av_freep(&s->speaker_azim);
1008  av_freep(&s->speaker_elev);
1009  av_freep(&s->temp_src[0]);
1010  av_freep(&s->temp_src[1]);
1011  av_freep(&s->temp_afft[0]);
1012  av_freep(&s->temp_afft[1]);
1013  av_freep(&s->temp_fft[0]);
1014  av_freep(&s->temp_fft[1]);
1015  av_freep(&s->data_hrtf[0]);
1016  av_freep(&s->data_hrtf[1]);
1017  av_freep(&s->fdsp);
1018 }
1019 
1020 #define OFFSET(x) offsetof(SOFAlizerContext, x)
1021 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
1022 
1023 static const AVOption sofalizer_options[] = {
1024  { "sofa", "sofa filename", OFFSET(filename), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
1025  { "gain", "set gain in dB", OFFSET(gain), AV_OPT_TYPE_FLOAT, {.dbl=0}, -20, 40, .flags = FLAGS },
1026  { "rotation", "set rotation" , OFFSET(rotation), AV_OPT_TYPE_FLOAT, {.dbl=0}, -360, 360, .flags = FLAGS },
1027  { "elevation", "set elevation", OFFSET(elevation), AV_OPT_TYPE_FLOAT, {.dbl=0}, -90, 90, .flags = FLAGS },
1028  { "radius", "set radius", OFFSET(radius), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 5, .flags = FLAGS },
1029  { "type", "set processing", OFFSET(type), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, .flags = FLAGS, "type" },
1030  { "time", "time domain", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, .flags = FLAGS, "type" },
1031  { "freq", "frequency domain", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, .flags = FLAGS, "type" },
1032  { "speakers", "set speaker custom positions", OFFSET(speakers_pos), AV_OPT_TYPE_STRING, {.str=0}, 0, 0, .flags = FLAGS },
1033  { "lfegain", "set lfe gain", OFFSET(lfe_gain), AV_OPT_TYPE_FLOAT, {.dbl=0}, -20,40, .flags = FLAGS },
1034  { "framesize", "set frame size", OFFSET(framesize), AV_OPT_TYPE_INT, {.i64=1024},1024,96000, .flags = FLAGS },
1035  { "normalize", "normalize IRs", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, .flags = FLAGS },
1036  { "interpolate","interpolate IRs from neighbors", OFFSET(interpolate),AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags = FLAGS },
1037  { "minphase", "minphase IRs", OFFSET(minphase), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags = FLAGS },
1038  { "anglestep", "set neighbor search angle step", OFFSET(anglestep), AV_OPT_TYPE_FLOAT, {.dbl=.5}, 0.01, 10, .flags = FLAGS },
1039  { "radstep", "set neighbor search radius step", OFFSET(radstep), AV_OPT_TYPE_FLOAT, {.dbl=.01}, 0.01, 1, .flags = FLAGS },
1040  { NULL }
1041 };
1042 
1043 AVFILTER_DEFINE_CLASS(sofalizer);
1044 
1045 static const AVFilterPad inputs[] = {
1046  {
1047  .name = "default",
1048  .type = AVMEDIA_TYPE_AUDIO,
1049  .config_props = config_input,
1050  .filter_frame = filter_frame,
1051  },
1052  { NULL }
1053 };
1054 
1055 static const AVFilterPad outputs[] = {
1056  {
1057  .name = "default",
1058  .type = AVMEDIA_TYPE_AUDIO,
1059  },
1060  { NULL }
1061 };
1062 
1064  .name = "sofalizer",
1065  .description = NULL_IF_CONFIG_SMALL("SOFAlizer (Spatially Oriented Format for Acoustics)."),
1066  .priv_size = sizeof(SOFAlizerContext),
1067  .priv_class = &sofalizer_class,
1068  .init = init,
1069  .uninit = uninit,
1071  .inputs = inputs,
1072  .outputs = outputs,
1074 };
static int sofalizer_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: af_sofalizer.c:429
float, planar
Definition: samplefmt.h:69
#define NULL
Definition: coverity.c:32
FFTComplex * data_hrtf[2]
Definition: af_sofalizer.c:110
AVFrame * out
Definition: af_adeclick.c:485
This structure describes decoded (raw) audio or video data.
Definition: frame.h:268
#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:109
#define AV_CH_TOP_FRONT_CENTER
#define AV_CH_LOW_FREQUENCY_2
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 av_log2(unsigned v)
Definition: intmath.c:26
struct MYSOFA_HRTF * hrtf
Definition: af_sofalizer.c:45
FFTSample re
Definition: avfft.h:38
FFTComplex * temp_afft[2]
Definition: af_sofalizer.c:92
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:51
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:115
BYTE int const BYTE * srcp
Definition: avisynth_c.h:813
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
AVFrame * in
Definition: af_afftdn.c:1082
#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:46
#define AV_CH_WIDE_RIGHT
#define AV_CH_TOP_BACK_CENTER
#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:50
#define FFALIGN(x, a)
Definition: macros.h:48
#define av_log(a,...)
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:112
#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:242
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: af_sofalizer.c:567
#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:606
#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:88
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:118
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 AV_CH_TOP_CENTER
float * ringbuffer[2]
Definition: af_sofalizer.c:78
float * speaker_azim
Definition: af_sofalizer.c:68
Definition: fft.h:88
static int load_data(AVFilterContext *ctx, int azim, int elev, float radius, int sample_rate)
Definition: af_sofalizer.c:692
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
AVS_Value args
Definition: avisynth_c.h:699
AVFormatContext * ctx
Definition: movenc.c:48
#define TIME_DOMAIN
Definition: af_sofalizer.c:41
#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[]
AVFilterChannelLayouts * ff_all_channel_layouts(void)
Construct an empty AVFilterChannelLayouts/AVFilterFormats struct – representing any channel layout (w...
Definition: formats.c:401
#define AV_CH_FRONT_RIGHT_OF_CENTER
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:341
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:131
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:52
Used for passing data between threads.
Definition: af_adeclick.c:484
FFT functions.
static int config_input(AVFilterLink *inlink)
Definition: af_sofalizer.c:961
#define AV_CH_FRONT_LEFT
uint8_t pi<< 24) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_U8,(uint64_t)((*(constuint8_t *) pi-0x80U))<< 56) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8,(*(constuint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8,(*(constuint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16,(*(constint16_t *) pi >>8)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S16,(uint64_t)(*(constint16_t *) pi)<< 48) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16,*(constint16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16,*(constint16_t *) pi *(1.0/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32,(*(constint32_t *) pi >>24)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S32,(uint64_t)(*(constint32_t *) pi)<< 32) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32,*(constint32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32,*(constint32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S64,(*(constint64_t *) pi >>56)+0x80) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S64,*(constint64_t *) pi *(1.0f/(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S64,*(constint64_t *) pi *(1.0/(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8(lrintf(*(constfloat *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16(lrintf(*(constfloat *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(constfloat *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_FLT, llrintf(*(constfloat *) pi *(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8(lrint(*(constdouble *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16(lrint(*(constdouble *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(constdouble *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_DBL, llrint(*(constdouble *) pi *(INT64_C(1)<< 63)))#defineFMT_PAIR_FUNC(out, in) staticconv_func_type *constfmt_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),};staticvoidcpy1(uint8_t **dst, constuint8_t **src, intlen){memcpy(*dst,*src, len);}staticvoidcpy2(uint8_t **dst, constuint8_t **src, intlen){memcpy(*dst,*src, 2 *len);}staticvoidcpy4(uint8_t **dst, constuint8_t **src, intlen){memcpy(*dst,*src, 4 *len);}staticvoidcpy8(uint8_t **dst, constuint8_t **src, intlen){memcpy(*dst,*src, 8 *len);}AudioConvert *swri_audio_convert_alloc(enumAVSampleFormatout_fmt, enumAVSampleFormatin_fmt, intchannels, constint *ch_map, intflags){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) returnNULL;ctx=av_mallocz(sizeof(*ctx));if(!ctx) returnNULL;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)){case1:ctx->simd_f=cpy1;break;case2:ctx->simd_f=cpy2;break;case4:ctx->simd_f=cpy4;break;case8:ctx->simd_f=cpy8;break;}}if(HAVE_X86ASM &&1) 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);returnctx;}voidswri_audio_convert_free(AudioConvert **ctx){av_freep(ctx);}intswri_audio_convert(AudioConvert *ctx, AudioData *out, AudioData *in, intlen){intch;intoff=0;constintos=(out->planar?1:out->ch_count)*out->bps;unsignedmisaligned=0;av_assert0(ctx->channels==out->ch_count);if(ctx->in_simd_align_mask){intplanes=in->planar?in->ch_count:1;unsignedm=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){intplanes=out->planar?out->ch_count:1;unsignedm=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){intplanes=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
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(constint16_t *) pi >>8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(constint32_t *) pi >>24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(constfloat *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(constfloat *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(constfloat *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(constdouble *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(constdouble *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(constdouble *) pi *(1U<< 31))))#defineSET_CONV_FUNC_GROUP(ofmt, ifmt) staticvoidset_generic_function(AudioConvert *ac){}voidff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enumAVSampleFormatout_fmt, enumAVSampleFormatin_fmt, intchannels, intsample_rate, intapply_map){AudioConvert *ac;intin_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) returnNULL;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);returnNULL;}returnac;}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;}elseif(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;elseac->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);returnac;}intff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){intuse_generic=1;intlen=in->nb_samples;intp;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%dsamples-audio_convert:%sto%s(dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));returnff_convert_dither(ac-> in
void * buf
Definition: avisynth_c.h:690
GLint GLenum type
Definition: opengl_enc.c:105
#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
static void normalize(NormalizeContext *s, AVFrame *in, AVFrame *out)
Definition: vf_normalize.c:124
const char * name
Filter name.
Definition: avfilter.h:148
float * speaker_elev
Definition: af_sofalizer.c:69
static const AVFilterPad inputs[]
int ir_samples
Definition: af_sofalizer.c:48
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:350
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:434
float ** ir
Definition: af_headphone.c:157
#define flags(name, subs,...)
Definition: cbs_av1.c:606
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:329
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:50
FFTContext * ifft[2]
Definition: af_sofalizer.c:109
int
static int parse_channel_name(char **arg, int *rchannel, char *buf)
Definition: af_sofalizer.c:184
sample_rates
FFTSample im
Definition: avfft.h:38
if(ret< 0)
Definition: vf_mcdeint.c:279
static double c[64]
#define FREQUENCY_DOMAIN
Definition: af_sofalizer.c:42
avfilter_execute_func * execute
Definition: internal.h:155
static av_cold int init(AVFilterContext *ctx)
Definition: af_sofalizer.c:930
#define av_free(p)
int len
static void parse_speaker_pos(AVFilterContext *ctx, int64_t in_channel_layout)
Definition: af_sofalizer.c:209
float * temp_src[2]
Definition: af_sofalizer.c:90
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:49
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:107
FILE * out
Definition: movenc.c:54
#define av_freep(p)
#define OFFSET(x)
#define av_malloc_array(a, b)
formats
Definition: signature.h:48
#define AV_CH_SIDE_LEFT
internal API functions
FFTComplex * temp_fft[2]
Definition: af_sofalizer.c:91
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:315
static av_cold void uninit(AVFilterContext *ctx)
Definition: af_sofalizer.c:988
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:47
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:334
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
GLuint buffer
Definition: opengl_enc.c:102
#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:648
uint8_t pi<< 24) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_U8,(uint64_t)((*(constuint8_t *) pi-0x80U))<< 56) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8,(*(constuint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8,(*(constuint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16,(*(constint16_t *) pi >>8)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S16,(uint64_t)(*(constint16_t *) pi)<< 48) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16,*(constint16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16,*(constint16_t *) pi *(1.0/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32,(*(constint32_t *) pi >>24)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S32,(uint64_t)(*(constint32_t *) pi)<< 32) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32,*(constint32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32,*(constint32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S64,(*(constint64_t *) pi >>56)+0x80) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S64,*(constint64_t *) pi *(1.0f/(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S64,*(constint64_t *) pi *(1.0/(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8(lrintf(*(constfloat *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16(lrintf(*(constfloat *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(constfloat *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_FLT, llrintf(*(constfloat *) pi *(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8(lrint(*(constdouble *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16(lrint(*(constdouble *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(constdouble *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_DBL, llrint(*(constdouble *) pi *(INT64_C(1)<< 63)))#defineFMT_PAIR_FUNC(out, in) staticconv_func_type *constfmt_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),};staticvoidcpy1(uint8_t **dst, constuint8_t **src, intlen){memcpy(*dst,*src, len);}staticvoidcpy2(uint8_t **dst, constuint8_t **src, intlen){memcpy(*dst,*src, 2 *len);}staticvoidcpy4(uint8_t **dst, constuint8_t **src, intlen){memcpy(*dst,*src, 4 *len);}staticvoidcpy8(uint8_t **dst, constuint8_t **src, intlen){memcpy(*dst,*src, 8 *len);}AudioConvert *swri_audio_convert_alloc(enumAVSampleFormatout_fmt, enumAVSampleFormatin_fmt, intchannels, constint *ch_map, intflags){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) returnNULL;ctx=av_mallocz(sizeof(*ctx));if(!ctx) returnNULL;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)){case1:ctx->simd_f=cpy1;break;case2:ctx->simd_f=cpy2;break;case4:ctx->simd_f=cpy4;break;case8:ctx->simd_f=cpy8;break;}}if(HAVE_X86ASM &&1) 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);returnctx;}voidswri_audio_convert_free(AudioConvert **ctx){av_freep(ctx);}intswri_audio_convert(AudioConvert *ctx, AudioData *out, AudioData *in, intlen){intch;intoff=0;constintos=(out->planar?1:out->ch_count)*out->bps;unsignedmisaligned=0;av_assert0(ctx->channels==out->ch_count);if(ctx->in_simd_align_mask){intplanes=in->planar?in->ch_count:1;unsignedm=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){intplanes=out->planar?out->ch_count:1;unsignedm=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){intplanes=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_STEREO_LEFT
Stereo downmix.