FFmpeg
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 "libavutil/tx.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  AVComplexFloat *in_fft[2]; /* Array to hold input FFT values */
94  AVComplexFloat *out_fft[2]; /* Array to hold output FFT values */
95  AVComplexFloat *temp_afft[2]; /* Array to accumulate FFT values prior to IFFT */
96 
97  /* control variables */
98  float gain; /* filter gain (in dB) */
99  float rotation; /* rotation of virtual loudspeakers (in degrees) */
100  float elevation; /* elevation of virtual loudspeakers (in deg.) */
101  float radius; /* distance virtual loudspeakers to listener (in metres) */
102  int type; /* processing type */
103  int framesize; /* size of buffer */
104  int normalize; /* should all IRs be normalized upon import ? */
105  int interpolate; /* should wanted IRs be interpolated from neighbors ? */
106  int minphase; /* should all IRs be minphased upon import ? */
107  float anglestep; /* neighbor search angle step, in agles */
108  float radstep; /* neighbor search radius step, in meters */
109 
111 
112  AVTXContext *fft[2], *ifft[2];
115 
118 
119 static int close_sofa(struct MySofa *sofa)
120 {
121  if (sofa->neighborhood)
122  mysofa_neighborhood_free(sofa->neighborhood);
123  sofa->neighborhood = NULL;
124  if (sofa->lookup)
125  mysofa_lookup_free(sofa->lookup);
126  sofa->lookup = NULL;
127  if (sofa->hrtf)
128  mysofa_free(sofa->hrtf);
129  sofa->hrtf = NULL;
130  av_freep(&sofa->fir);
131 
132  return 0;
133 }
134 
135 static int preload_sofa(AVFilterContext *ctx, char *filename, int *samplingrate)
136 {
137  struct SOFAlizerContext *s = ctx->priv;
138  struct MYSOFA_HRTF *mysofa;
139  char *license;
140  int ret;
141 
142  mysofa = mysofa_load(filename, &ret);
143  s->sofa.hrtf = mysofa;
144  if (ret || !mysofa) {
145  av_log(ctx, AV_LOG_ERROR, "Can't find SOFA-file '%s'\n", filename);
146  return AVERROR(EINVAL);
147  }
148 
149  ret = mysofa_check(mysofa);
150  if (ret != MYSOFA_OK) {
151  av_log(ctx, AV_LOG_ERROR, "Selected SOFA file is invalid. Please select valid SOFA file.\n");
152  return ret;
153  }
154 
155  if (s->normalize)
156  mysofa_loudness(s->sofa.hrtf);
157 
158  if (s->minphase)
159  mysofa_minphase(s->sofa.hrtf, 0.01f);
160 
161  mysofa_tocartesian(s->sofa.hrtf);
162 
163  s->sofa.lookup = mysofa_lookup_init(s->sofa.hrtf);
164  if (s->sofa.lookup == NULL)
165  return AVERROR(EINVAL);
166 
167  if (s->interpolate)
168  s->sofa.neighborhood = mysofa_neighborhood_init_withstepdefine(s->sofa.hrtf,
169  s->sofa.lookup,
170  s->anglestep,
171  s->radstep);
172 
173  s->sofa.fir = av_calloc(s->sofa.hrtf->N * s->sofa.hrtf->R, sizeof(*s->sofa.fir));
174  if (!s->sofa.fir)
175  return AVERROR(ENOMEM);
176 
177  if (mysofa->DataSamplingRate.elements != 1)
178  return AVERROR(EINVAL);
179  av_log(ctx, AV_LOG_DEBUG, "Original IR length: %d.\n", mysofa->N);
180  *samplingrate = mysofa->DataSamplingRate.values[0];
181  license = mysofa_getAttribute(mysofa->attributes, (char *)"License");
182  if (license)
183  av_log(ctx, AV_LOG_INFO, "SOFA license: %s\n", license);
184 
185  return 0;
186 }
187 
188 static int parse_channel_name(AVFilterContext *ctx, char **arg, int *rchannel)
189 {
190  int len, i, channel_id = 0;
191  int64_t layout, layout0;
192  char buf[8] = {0};
193 
194  /* try to parse a channel name, e.g. "FL" */
195  if (av_sscanf(*arg, "%7[A-Z]%n", buf, &len)) {
196  layout0 = layout = av_get_channel_layout(buf);
197  /* channel_id <- first set bit in layout */
198  for (i = 32; i > 0; i >>= 1) {
199  if (layout >= 1LL << i) {
200  channel_id += i;
201  layout >>= i;
202  }
203  }
204  /* reject layouts that are not a single channel */
205  if (channel_id >= 64 || layout0 != 1LL << channel_id) {
206  av_log(ctx, AV_LOG_WARNING, "Failed to parse \'%s\' as channel name.\n", buf);
207  return AVERROR(EINVAL);
208  }
209  *rchannel = channel_id;
210  *arg += len;
211  return 0;
212  } else if (av_sscanf(*arg, "%d%n", &channel_id, &len) == 1) {
213  if (channel_id < 0 || channel_id >= 64) {
214  av_log(ctx, AV_LOG_WARNING, "Failed to parse \'%d\' as channel number.\n", channel_id);
215  return AVERROR(EINVAL);
216  }
217  *rchannel = channel_id;
218  *arg += len;
219  return 0;
220  }
221  return AVERROR(EINVAL);
222 }
223 
224 static void parse_speaker_pos(AVFilterContext *ctx, int64_t in_channel_layout)
225 {
226  SOFAlizerContext *s = ctx->priv;
227  char *arg, *tokenizer, *p, *args = av_strdup(s->speakers_pos);
228 
229  if (!args)
230  return;
231  p = args;
232 
233  while ((arg = av_strtok(p, "|", &tokenizer))) {
234  float azim, elev;
235  int out_ch_id;
236 
237  p = NULL;
238  if (parse_channel_name(ctx, &arg, &out_ch_id)) {
239  continue;
240  }
241  if (av_sscanf(arg, "%f %f", &azim, &elev) == 2) {
242  s->vspkrpos[out_ch_id].set = 1;
243  s->vspkrpos[out_ch_id].azim = azim;
244  s->vspkrpos[out_ch_id].elev = elev;
245  } else if (av_sscanf(arg, "%f", &azim) == 1) {
246  s->vspkrpos[out_ch_id].set = 1;
247  s->vspkrpos[out_ch_id].azim = azim;
248  s->vspkrpos[out_ch_id].elev = 0;
249  }
250  }
251 
252  av_free(args);
253 }
254 
256  float *speaker_azim, float *speaker_elev)
257 {
258  struct SOFAlizerContext *s = ctx->priv;
259  uint64_t channels_layout = ctx->inputs[0]->channel_layout;
260  float azim[64] = { 0 };
261  float elev[64] = { 0 };
262  int m, ch, n_conv = ctx->inputs[0]->channels; /* get no. input channels */
263 
264  if (n_conv < 0 || n_conv > 64)
265  return AVERROR(EINVAL);
266 
267  s->lfe_channel = -1;
268 
269  if (s->speakers_pos)
270  parse_speaker_pos(ctx, channels_layout);
271 
272  /* set speaker positions according to input channel configuration: */
273  for (m = 0, ch = 0; ch < n_conv && m < 64; m++) {
274  uint64_t mask = channels_layout & (1ULL << m);
275 
276  switch (mask) {
277  case AV_CH_FRONT_LEFT: azim[ch] = 30; break;
278  case AV_CH_FRONT_RIGHT: azim[ch] = 330; break;
279  case AV_CH_FRONT_CENTER: azim[ch] = 0; break;
280  case AV_CH_LOW_FREQUENCY:
281  case AV_CH_LOW_FREQUENCY_2: s->lfe_channel = ch; break;
282  case AV_CH_BACK_LEFT: azim[ch] = 150; break;
283  case AV_CH_BACK_RIGHT: azim[ch] = 210; break;
284  case AV_CH_BACK_CENTER: azim[ch] = 180; break;
285  case AV_CH_SIDE_LEFT: azim[ch] = 90; break;
286  case AV_CH_SIDE_RIGHT: azim[ch] = 270; break;
287  case AV_CH_FRONT_LEFT_OF_CENTER: azim[ch] = 15; break;
288  case AV_CH_FRONT_RIGHT_OF_CENTER: azim[ch] = 345; break;
289  case AV_CH_TOP_CENTER: azim[ch] = 0;
290  elev[ch] = 90; break;
291  case AV_CH_TOP_FRONT_LEFT: azim[ch] = 30;
292  elev[ch] = 45; break;
293  case AV_CH_TOP_FRONT_CENTER: azim[ch] = 0;
294  elev[ch] = 45; break;
295  case AV_CH_TOP_FRONT_RIGHT: azim[ch] = 330;
296  elev[ch] = 45; break;
297  case AV_CH_TOP_BACK_LEFT: azim[ch] = 150;
298  elev[ch] = 45; break;
299  case AV_CH_TOP_BACK_RIGHT: azim[ch] = 210;
300  elev[ch] = 45; break;
301  case AV_CH_TOP_BACK_CENTER: azim[ch] = 180;
302  elev[ch] = 45; break;
303  case AV_CH_WIDE_LEFT: azim[ch] = 90; break;
304  case AV_CH_WIDE_RIGHT: azim[ch] = 270; break;
305  case AV_CH_SURROUND_DIRECT_LEFT: azim[ch] = 90; break;
306  case AV_CH_SURROUND_DIRECT_RIGHT: azim[ch] = 270; break;
307  case AV_CH_STEREO_LEFT: azim[ch] = 90; break;
308  case AV_CH_STEREO_RIGHT: azim[ch] = 270; break;
309  case 0: break;
310  default:
311  return AVERROR(EINVAL);
312  }
313 
314  if (s->vspkrpos[m].set) {
315  azim[ch] = s->vspkrpos[m].azim;
316  elev[ch] = s->vspkrpos[m].elev;
317  }
318 
319  if (mask)
320  ch++;
321  }
322 
323  memcpy(speaker_azim, azim, n_conv * sizeof(float));
324  memcpy(speaker_elev, elev, n_conv * sizeof(float));
325 
326  return 0;
327 
328 }
329 
330 typedef struct ThreadData {
331  AVFrame *in, *out;
332  int *write;
333  int **delay;
334  float **ir;
335  int *n_clippings;
336  float **ringbuffer;
337  float **temp_src;
341 } ThreadData;
342 
343 static int sofalizer_convolute(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
344 {
345  SOFAlizerContext *s = ctx->priv;
346  ThreadData *td = arg;
347  AVFrame *in = td->in, *out = td->out;
348  int offset = jobnr;
349  int *write = &td->write[jobnr];
350  const int *const delay = td->delay[jobnr];
351  const float *const ir = td->ir[jobnr];
352  int *n_clippings = &td->n_clippings[jobnr];
353  float *ringbuffer = td->ringbuffer[jobnr];
354  float *temp_src = td->temp_src[jobnr];
355  const int ir_samples = s->sofa.ir_samples; /* length of one IR */
356  const int n_samples = s->sofa.n_samples;
357  const int planar = in->format == AV_SAMPLE_FMT_FLTP;
358  const int mult = 1 + !planar;
359  const float *src = (const float *)in->extended_data[0]; /* get pointer to audio input buffer */
360  float *dst = (float *)out->extended_data[jobnr * planar]; /* get pointer to audio output buffer */
361  const int in_channels = s->n_conv; /* number of input channels */
362  /* ring buffer length is: longest IR plus max. delay -> next power of 2 */
363  const int buffer_length = s->buffer_length;
364  /* -1 for AND instead of MODULO (applied to powers of 2): */
365  const uint32_t modulo = (uint32_t)buffer_length - 1;
366  float *buffer[64]; /* holds ringbuffer for each input channel */
367  int wr = *write;
368  int read;
369  int i, l;
370 
371  if (!planar)
372  dst += offset;
373 
374  for (l = 0; l < in_channels; l++) {
375  /* get starting address of ringbuffer for each input channel */
376  buffer[l] = ringbuffer + l * buffer_length;
377  }
378 
379  for (i = 0; i < in->nb_samples; i++) {
380  const float *temp_ir = ir; /* using same set of IRs for each sample */
381 
382  dst[0] = 0;
383  if (planar) {
384  for (l = 0; l < in_channels; l++) {
385  const float *srcp = (const float *)in->extended_data[l];
386 
387  /* write current input sample to ringbuffer (for each channel) */
388  buffer[l][wr] = srcp[i];
389  }
390  } else {
391  for (l = 0; l < in_channels; l++) {
392  /* write current input sample to ringbuffer (for each channel) */
393  buffer[l][wr] = src[l];
394  }
395  }
396 
397  /* loop goes through all channels to be convolved */
398  for (l = 0; l < in_channels; l++) {
399  const float *const bptr = buffer[l];
400 
401  if (l == s->lfe_channel) {
402  /* LFE is an input channel but requires no convolution */
403  /* apply gain to LFE signal and add to output buffer */
404  dst[0] += *(buffer[s->lfe_channel] + wr) * s->gain_lfe;
405  temp_ir += n_samples;
406  continue;
407  }
408 
409  /* current read position in ringbuffer: input sample write position
410  * - delay for l-th ch. + diff. betw. IR length and buffer length
411  * (mod buffer length) */
412  read = (wr - delay[l] - (ir_samples - 1) + buffer_length) & modulo;
413 
414  if (read + ir_samples < buffer_length) {
415  memmove(temp_src, bptr + read, ir_samples * sizeof(*temp_src));
416  } else {
417  int len = FFMIN(n_samples - (read % ir_samples), buffer_length - read);
418 
419  memmove(temp_src, bptr + read, len * sizeof(*temp_src));
420  memmove(temp_src + len, bptr, (n_samples - len) * sizeof(*temp_src));
421  }
422 
423  /* multiply signal and IR, and add up the results */
424  dst[0] += s->fdsp->scalarproduct_float(temp_ir, temp_src, FFALIGN(ir_samples, 32));
425  temp_ir += n_samples;
426  }
427 
428  /* clippings counter */
429  if (fabsf(dst[0]) > 1)
430  n_clippings[0]++;
431 
432  /* move output buffer pointer by +2 to get to next sample of processed channel: */
433  dst += mult;
434  src += in_channels;
435  wr = (wr + 1) & modulo; /* update ringbuffer write position */
436  }
437 
438  *write = wr; /* remember write position in ringbuffer for next call */
439 
440  return 0;
441 }
442 
443 static int sofalizer_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
444 {
445  SOFAlizerContext *s = ctx->priv;
446  ThreadData *td = arg;
447  AVFrame *in = td->in, *out = td->out;
448  int offset = jobnr;
449  int *write = &td->write[jobnr];
450  AVComplexFloat *hrtf = s->data_hrtf[jobnr]; /* get pointers to current HRTF data */
451  int *n_clippings = &td->n_clippings[jobnr];
452  float *ringbuffer = td->ringbuffer[jobnr];
453  const int ir_samples = s->sofa.ir_samples; /* length of one IR */
454  const int planar = in->format == AV_SAMPLE_FMT_FLTP;
455  const int mult = 1 + !planar;
456  float *dst = (float *)out->extended_data[jobnr * planar]; /* get pointer to audio output buffer */
457  const int in_channels = s->n_conv; /* number of input channels */
458  /* ring buffer length is: longest IR plus max. delay -> next power of 2 */
459  const int buffer_length = s->buffer_length;
460  /* -1 for AND instead of MODULO (applied to powers of 2): */
461  const uint32_t modulo = (uint32_t)buffer_length - 1;
462  AVComplexFloat *fft_in = s->in_fft[jobnr]; /* temporary array for FFT input data */
463  AVComplexFloat *fft_out = s->out_fft[jobnr]; /* temporary array for FFT output data */
464  AVComplexFloat *fft_acc = s->temp_afft[jobnr];
465  AVTXContext *ifft = s->ifft[jobnr];
466  av_tx_fn itx_fn = s->itx_fn[jobnr];
467  AVTXContext *fft = s->fft[jobnr];
468  av_tx_fn tx_fn = s->tx_fn[jobnr];
469  const int n_conv = s->n_conv;
470  const int n_fft = s->n_fft;
471  const float fft_scale = 1.0f / s->n_fft;
472  AVComplexFloat *hrtf_offset;
473  int wr = *write;
474  int n_read;
475  int i, j;
476 
477  if (!planar)
478  dst += offset;
479 
480  /* find minimum between number of samples and output buffer length:
481  * (important, if one IR is longer than the output buffer) */
482  n_read = FFMIN(ir_samples, in->nb_samples);
483  for (j = 0; j < n_read; j++) {
484  /* initialize output buf with saved signal from overflow buf */
485  dst[mult * j] = ringbuffer[wr];
486  ringbuffer[wr] = 0.0f; /* re-set read samples to zero */
487  /* update ringbuffer read/write position */
488  wr = (wr + 1) & modulo;
489  }
490 
491  /* initialize rest of output buffer with 0 */
492  for (j = n_read; j < in->nb_samples; j++) {
493  dst[mult * j] = 0;
494  }
495 
496  /* fill FFT accumulation with 0 */
497  memset(fft_acc, 0, sizeof(AVComplexFloat) * n_fft);
498 
499  for (i = 0; i < n_conv; i++) {
500  const float *src = (const float *)in->extended_data[i * planar]; /* get pointer to audio input buffer */
501 
502  if (i == s->lfe_channel) { /* LFE */
503  if (in->format == AV_SAMPLE_FMT_FLT) {
504  for (j = 0; j < in->nb_samples; j++) {
505  /* apply gain to LFE signal and add to output buffer */
506  dst[2 * j] += src[i + j * in_channels] * s->gain_lfe;
507  }
508  } else {
509  for (j = 0; j < in->nb_samples; j++) {
510  /* apply gain to LFE signal and add to output buffer */
511  dst[j] += src[j] * s->gain_lfe;
512  }
513  }
514  continue;
515  }
516 
517  /* outer loop: go through all input channels to be convolved */
518  offset = i * n_fft; /* no. samples already processed */
519  hrtf_offset = hrtf + offset;
520 
521  /* fill FFT input with 0 (we want to zero-pad) */
522  memset(fft_in, 0, sizeof(AVComplexFloat) * n_fft);
523 
524  if (in->format == AV_SAMPLE_FMT_FLT) {
525  for (j = 0; j < in->nb_samples; j++) {
526  /* prepare input for FFT */
527  /* write all samples of current input channel to FFT input array */
528  fft_in[j].re = src[j * in_channels + i];
529  }
530  } else {
531  for (j = 0; j < in->nb_samples; j++) {
532  /* prepare input for FFT */
533  /* write all samples of current input channel to FFT input array */
534  fft_in[j].re = src[j];
535  }
536  }
537 
538  /* transform input signal of current channel to frequency domain */
539  tx_fn(fft, fft_out, fft_in, sizeof(float));
540 
541  for (j = 0; j < n_fft; j++) {
542  const AVComplexFloat *hcomplex = hrtf_offset + j;
543  const float re = fft_out[j].re;
544  const float im = fft_out[j].im;
545 
546  /* complex multiplication of input signal and HRTFs */
547  /* output channel (real): */
548  fft_acc[j].re += re * hcomplex->re - im * hcomplex->im;
549  /* output channel (imag): */
550  fft_acc[j].im += re * hcomplex->im + im * hcomplex->re;
551  }
552  }
553 
554  /* transform output signal of current channel back to time domain */
555  itx_fn(ifft, fft_out, fft_acc, sizeof(float));
556 
557  for (j = 0; j < in->nb_samples; j++) {
558  /* write output signal of current channel to output buffer */
559  dst[mult * j] += fft_out[j].re * fft_scale;
560  }
561 
562  for (j = 0; j < ir_samples - 1; j++) { /* overflow length is IR length - 1 */
563  /* write the rest of output signal to overflow buffer */
564  int write_pos = (wr + j) & modulo;
565 
566  *(ringbuffer + write_pos) += fft_out[in->nb_samples + j].re * fft_scale;
567  }
568 
569  /* go through all samples of current output buffer: count clippings */
570  for (i = 0; i < out->nb_samples; i++) {
571  /* clippings counter */
572  if (fabsf(dst[i * mult]) > 1) { /* if current output sample > 1 */
573  n_clippings[0]++;
574  }
575  }
576 
577  /* remember read/write position in ringbuffer for next call */
578  *write = wr;
579 
580  return 0;
581 }
582 
584 {
585  AVFilterContext *ctx = inlink->dst;
586  SOFAlizerContext *s = ctx->priv;
587  AVFilterLink *outlink = ctx->outputs[0];
588  int n_clippings[2] = { 0 };
589  ThreadData td;
590  AVFrame *out;
591 
592  out = ff_get_audio_buffer(outlink, in->nb_samples);
593  if (!out) {
594  av_frame_free(&in);
595  return AVERROR(ENOMEM);
596  }
598 
599  td.in = in; td.out = out; td.write = s->write;
600  td.delay = s->delay; td.ir = s->data_ir; td.n_clippings = n_clippings;
601  td.ringbuffer = s->ringbuffer; td.temp_src = s->temp_src;
602  td.in_fft = s->in_fft;
603  td.out_fft = s->out_fft;
604  td.temp_afft = s->temp_afft;
605 
606  if (s->type == TIME_DOMAIN) {
608  } else if (s->type == FREQUENCY_DOMAIN) {
610  }
611  emms_c();
612 
613  /* display error message if clipping occurred */
614  if (n_clippings[0] + n_clippings[1] > 0) {
615  av_log(ctx, AV_LOG_WARNING, "%d of %d samples clipped. Please reduce gain.\n",
616  n_clippings[0] + n_clippings[1], out->nb_samples * 2);
617  }
618 
619  av_frame_free(&in);
620  return ff_filter_frame(outlink, out);
621 }
622 
624 {
625  AVFilterLink *inlink = ctx->inputs[0];
626  AVFilterLink *outlink = ctx->outputs[0];
627  SOFAlizerContext *s = ctx->priv;
628  AVFrame *in;
629  int ret;
630 
632 
633  if (s->nb_samples)
634  ret = ff_inlink_consume_samples(inlink, s->nb_samples, s->nb_samples, &in);
635  else
637  if (ret < 0)
638  return ret;
639  if (ret > 0)
640  return filter_frame(inlink, in);
641 
644 
645  return FFERROR_NOT_READY;
646 }
647 
649 {
650  struct SOFAlizerContext *s = ctx->priv;
652  int ret, sample_rates[] = { 48000, -1 };
653  static const enum AVSampleFormat sample_fmts[] = {
656  };
657 
659  if (ret)
660  return ret;
661 
663  if (!layouts)
664  return AVERROR(ENOMEM);
665 
666  ret = ff_channel_layouts_ref(layouts, &ctx->inputs[0]->outcfg.channel_layouts);
667  if (ret)
668  return ret;
669 
670  layouts = NULL;
672  if (ret)
673  return ret;
674 
675  ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->incfg.channel_layouts);
676  if (ret)
677  return ret;
678 
679  sample_rates[0] = s->sample_rate;
681 }
682 
683 static int getfilter_float(AVFilterContext *ctx, float x, float y, float z,
684  float *left, float *right,
685  float *delay_left, float *delay_right)
686 {
687  struct SOFAlizerContext *s = ctx->priv;
688  float c[3], delays[2];
689  float *fl, *fr;
690  int nearest;
691  int *neighbors;
692  float *res;
693 
694  c[0] = x, c[1] = y, c[2] = z;
695  nearest = mysofa_lookup(s->sofa.lookup, c);
696  if (nearest < 0)
697  return AVERROR(EINVAL);
698 
699  if (s->interpolate) {
700  neighbors = mysofa_neighborhood(s->sofa.neighborhood, nearest);
701  res = mysofa_interpolate(s->sofa.hrtf, c,
702  nearest, neighbors,
703  s->sofa.fir, delays);
704  } else {
705  if (s->sofa.hrtf->DataDelay.elements > s->sofa.hrtf->R) {
706  delays[0] = s->sofa.hrtf->DataDelay.values[nearest * s->sofa.hrtf->R];
707  delays[1] = s->sofa.hrtf->DataDelay.values[nearest * s->sofa.hrtf->R + 1];
708  } else {
709  delays[0] = s->sofa.hrtf->DataDelay.values[0];
710  delays[1] = s->sofa.hrtf->DataDelay.values[1];
711  }
712  res = s->sofa.hrtf->DataIR.values + nearest * s->sofa.hrtf->N * s->sofa.hrtf->R;
713  }
714 
715  *delay_left = delays[0];
716  *delay_right = delays[1];
717 
718  fl = res;
719  fr = res + s->sofa.hrtf->N;
720 
721  memcpy(left, fl, sizeof(float) * s->sofa.hrtf->N);
722  memcpy(right, fr, sizeof(float) * s->sofa.hrtf->N);
723 
724  return 0;
725 }
726 
727 static int load_data(AVFilterContext *ctx, int azim, int elev, float radius, int sample_rate)
728 {
729  struct SOFAlizerContext *s = ctx->priv;
730  int n_samples;
731  int ir_samples;
732  int n_conv = s->n_conv; /* no. channels to convolve */
733  int n_fft;
734  float delay_l; /* broadband delay for each IR */
735  float delay_r;
736  int nb_input_channels = ctx->inputs[0]->channels; /* no. input channels */
737  float gain_lin = expf((s->gain - 3 * nb_input_channels) / 20 * M_LN10); /* gain - 3dB/channel */
738  AVComplexFloat *data_hrtf_l = NULL;
739  AVComplexFloat *data_hrtf_r = NULL;
740  AVComplexFloat *fft_out_l = NULL;
741  AVComplexFloat *fft_out_r = NULL;
742  AVComplexFloat *fft_in_l = NULL;
743  AVComplexFloat *fft_in_r = NULL;
744  float *data_ir_l = NULL;
745  float *data_ir_r = NULL;
746  int offset = 0; /* used for faster pointer arithmetics in for-loop */
747  int i, j, azim_orig = azim, elev_orig = elev;
748  int ret = 0;
749  int n_current;
750  int n_max = 0;
751 
752  av_log(ctx, AV_LOG_DEBUG, "IR length: %d.\n", s->sofa.hrtf->N);
753  s->sofa.ir_samples = s->sofa.hrtf->N;
754  s->sofa.n_samples = 1 << (32 - ff_clz(s->sofa.ir_samples));
755 
756  n_samples = s->sofa.n_samples;
757  ir_samples = s->sofa.ir_samples;
758 
759  if (s->type == TIME_DOMAIN) {
760  s->data_ir[0] = av_calloc(n_samples, sizeof(float) * s->n_conv);
761  s->data_ir[1] = av_calloc(n_samples, sizeof(float) * s->n_conv);
762 
763  if (!s->data_ir[0] || !s->data_ir[1]) {
764  ret = AVERROR(ENOMEM);
765  goto fail;
766  }
767  }
768 
769  s->delay[0] = av_calloc(s->n_conv, sizeof(int));
770  s->delay[1] = av_calloc(s->n_conv, sizeof(int));
771 
772  if (!s->delay[0] || !s->delay[1]) {
773  ret = AVERROR(ENOMEM);
774  goto fail;
775  }
776 
777  /* get temporary IR for L and R channel */
778  data_ir_l = av_calloc(n_conv * n_samples, sizeof(*data_ir_l));
779  data_ir_r = av_calloc(n_conv * n_samples, sizeof(*data_ir_r));
780  if (!data_ir_r || !data_ir_l) {
781  ret = AVERROR(ENOMEM);
782  goto fail;
783  }
784 
785  if (s->type == TIME_DOMAIN) {
786  s->temp_src[0] = av_calloc(n_samples, sizeof(float));
787  s->temp_src[1] = av_calloc(n_samples, sizeof(float));
788  if (!s->temp_src[0] || !s->temp_src[1]) {
789  ret = AVERROR(ENOMEM);
790  goto fail;
791  }
792  }
793 
794  s->speaker_azim = av_calloc(s->n_conv, sizeof(*s->speaker_azim));
795  s->speaker_elev = av_calloc(s->n_conv, sizeof(*s->speaker_elev));
796  if (!s->speaker_azim || !s->speaker_elev) {
797  ret = AVERROR(ENOMEM);
798  goto fail;
799  }
800 
801  /* get speaker positions */
802  if ((ret = get_speaker_pos(ctx, s->speaker_azim, s->speaker_elev)) < 0) {
803  av_log(ctx, AV_LOG_ERROR, "Couldn't get speaker positions. Input channel configuration not supported.\n");
804  goto fail;
805  }
806 
807  for (i = 0; i < s->n_conv; i++) {
808  float coordinates[3];
809 
810  /* load and store IRs and corresponding delays */
811  azim = (int)(s->speaker_azim[i] + azim_orig) % 360;
812  elev = (int)(s->speaker_elev[i] + elev_orig) % 90;
813 
814  coordinates[0] = azim;
815  coordinates[1] = elev;
816  coordinates[2] = radius;
817 
818  mysofa_s2c(coordinates);
819 
820  /* get id of IR closest to desired position */
821  ret = getfilter_float(ctx, coordinates[0], coordinates[1], coordinates[2],
822  data_ir_l + n_samples * i,
823  data_ir_r + n_samples * i,
824  &delay_l, &delay_r);
825  if (ret < 0)
826  goto fail;
827 
828  s->delay[0][i] = delay_l * sample_rate;
829  s->delay[1][i] = delay_r * sample_rate;
830 
831  s->sofa.max_delay = FFMAX3(s->sofa.max_delay, s->delay[0][i], s->delay[1][i]);
832  }
833 
834  /* get size of ringbuffer (longest IR plus max. delay) */
835  /* then choose next power of 2 for performance optimization */
836  n_current = n_samples + s->sofa.max_delay;
837  /* length of longest IR plus max. delay */
838  n_max = FFMAX(n_max, n_current);
839 
840  /* buffer length is longest IR plus max. delay -> next power of 2
841  (32 - count leading zeros gives required exponent) */
842  s->buffer_length = 1 << (32 - ff_clz(n_max));
843  s->n_fft = n_fft = 1 << (32 - ff_clz(n_max + s->framesize));
844 
845  if (s->type == FREQUENCY_DOMAIN) {
846  float scale;
847 
848  av_tx_uninit(&s->fft[0]);
849  av_tx_uninit(&s->fft[1]);
850  ret = av_tx_init(&s->fft[0], &s->tx_fn[0], AV_TX_FLOAT_FFT, 0, s->n_fft, &scale, 0);
851  if (ret < 0)
852  goto fail;
853  ret = av_tx_init(&s->fft[1], &s->tx_fn[1], AV_TX_FLOAT_FFT, 0, s->n_fft, &scale, 0);
854  if (ret < 0)
855  goto fail;
856  av_tx_uninit(&s->ifft[0]);
857  av_tx_uninit(&s->ifft[1]);
858  ret = av_tx_init(&s->ifft[0], &s->itx_fn[0], AV_TX_FLOAT_FFT, 1, s->n_fft, &scale, 0);
859  if (ret < 0)
860  goto fail;
861  ret = av_tx_init(&s->ifft[1], &s->itx_fn[1], AV_TX_FLOAT_FFT, 1, s->n_fft, &scale, 0);
862  if (ret < 0)
863  goto fail;
864  }
865 
866  if (s->type == TIME_DOMAIN) {
867  s->ringbuffer[0] = av_calloc(s->buffer_length, sizeof(float) * nb_input_channels);
868  s->ringbuffer[1] = av_calloc(s->buffer_length, sizeof(float) * nb_input_channels);
869  } else if (s->type == FREQUENCY_DOMAIN) {
870  /* get temporary HRTF memory for L and R channel */
871  data_hrtf_l = av_malloc_array(n_fft, sizeof(*data_hrtf_l) * n_conv);
872  data_hrtf_r = av_malloc_array(n_fft, sizeof(*data_hrtf_r) * n_conv);
873  if (!data_hrtf_r || !data_hrtf_l) {
874  ret = AVERROR(ENOMEM);
875  goto fail;
876  }
877 
878  s->ringbuffer[0] = av_calloc(s->buffer_length, sizeof(float));
879  s->ringbuffer[1] = av_calloc(s->buffer_length, sizeof(float));
880  s->in_fft[0] = av_malloc_array(s->n_fft, sizeof(AVComplexFloat));
881  s->in_fft[1] = av_malloc_array(s->n_fft, sizeof(AVComplexFloat));
882  s->out_fft[0] = av_malloc_array(s->n_fft, sizeof(AVComplexFloat));
883  s->out_fft[1] = av_malloc_array(s->n_fft, sizeof(AVComplexFloat));
884  s->temp_afft[0] = av_malloc_array(s->n_fft, sizeof(AVComplexFloat));
885  s->temp_afft[1] = av_malloc_array(s->n_fft, sizeof(AVComplexFloat));
886  if (!s->in_fft[0] || !s->in_fft[1] ||
887  !s->out_fft[0] || !s->out_fft[1] ||
888  !s->temp_afft[0] || !s->temp_afft[1]) {
889  ret = AVERROR(ENOMEM);
890  goto fail;
891  }
892  }
893 
894  if (!s->ringbuffer[0] || !s->ringbuffer[1]) {
895  ret = AVERROR(ENOMEM);
896  goto fail;
897  }
898 
899  if (s->type == FREQUENCY_DOMAIN) {
900  fft_out_l = av_calloc(n_fft, sizeof(*fft_out_l));
901  fft_out_r = av_calloc(n_fft, sizeof(*fft_out_r));
902  fft_in_l = av_calloc(n_fft, sizeof(*fft_in_l));
903  fft_in_r = av_calloc(n_fft, sizeof(*fft_in_r));
904  if (!fft_in_l || !fft_in_r ||
905  !fft_out_l || !fft_out_r) {
906  ret = AVERROR(ENOMEM);
907  goto fail;
908  }
909  }
910 
911  for (i = 0; i < s->n_conv; i++) {
912  float *lir, *rir;
913 
914  offset = i * n_samples; /* no. samples already written */
915 
916  lir = data_ir_l + offset;
917  rir = data_ir_r + offset;
918 
919  if (s->type == TIME_DOMAIN) {
920  for (j = 0; j < ir_samples; j++) {
921  /* load reversed IRs of the specified source position
922  * sample-by-sample for left and right ear; and apply gain */
923  s->data_ir[0][offset + j] = lir[ir_samples - 1 - j] * gain_lin;
924  s->data_ir[1][offset + j] = rir[ir_samples - 1 - j] * gain_lin;
925  }
926  } else if (s->type == FREQUENCY_DOMAIN) {
927  memset(fft_in_l, 0, n_fft * sizeof(*fft_in_l));
928  memset(fft_in_r, 0, n_fft * sizeof(*fft_in_r));
929 
930  offset = i * n_fft; /* no. samples already written */
931  for (j = 0; j < ir_samples; j++) {
932  /* load non-reversed IRs of the specified source position
933  * sample-by-sample and apply gain,
934  * L channel is loaded to real part, R channel to imag part,
935  * IRs are shifted by L and R delay */
936  fft_in_l[s->delay[0][i] + j].re = lir[j] * gain_lin;
937  fft_in_r[s->delay[1][i] + j].re = rir[j] * gain_lin;
938  }
939 
940  /* actually transform to frequency domain (IRs -> HRTFs) */
941  s->tx_fn[0](s->fft[0], fft_out_l, fft_in_l, sizeof(float));
942  memcpy(data_hrtf_l + offset, fft_out_l, n_fft * sizeof(*fft_out_l));
943  s->tx_fn[1](s->fft[1], fft_out_r, fft_in_r, sizeof(float));
944  memcpy(data_hrtf_r + offset, fft_out_r, n_fft * sizeof(*fft_out_r));
945  }
946  }
947 
948  if (s->type == FREQUENCY_DOMAIN) {
949  s->data_hrtf[0] = av_malloc_array(n_fft * s->n_conv, sizeof(AVComplexFloat));
950  s->data_hrtf[1] = av_malloc_array(n_fft * s->n_conv, sizeof(AVComplexFloat));
951  if (!s->data_hrtf[0] || !s->data_hrtf[1]) {
952  ret = AVERROR(ENOMEM);
953  goto fail;
954  }
955 
956  memcpy(s->data_hrtf[0], data_hrtf_l, /* copy HRTF data to */
957  sizeof(AVComplexFloat) * n_conv * n_fft); /* filter struct */
958  memcpy(s->data_hrtf[1], data_hrtf_r,
959  sizeof(AVComplexFloat) * n_conv * n_fft);
960  }
961 
962 fail:
963  av_freep(&data_hrtf_l); /* free temporary HRTF memory */
964  av_freep(&data_hrtf_r);
965 
966  av_freep(&data_ir_l); /* free temprary IR memory */
967  av_freep(&data_ir_r);
968 
969  av_freep(&fft_out_l); /* free temporary FFT memory */
970  av_freep(&fft_out_r);
971 
972  av_freep(&fft_in_l); /* free temporary FFT memory */
973  av_freep(&fft_in_r);
974 
975  return ret;
976 }
977 
979 {
980  SOFAlizerContext *s = ctx->priv;
981  int ret;
982 
983  if (!s->filename) {
984  av_log(ctx, AV_LOG_ERROR, "Valid SOFA filename must be set.\n");
985  return AVERROR(EINVAL);
986  }
987 
988  /* preload SOFA file, */
989  ret = preload_sofa(ctx, s->filename, &s->sample_rate);
990  if (ret) {
991  /* file loading error */
992  av_log(ctx, AV_LOG_ERROR, "Error while loading SOFA file: '%s'\n", s->filename);
993  } else { /* no file loading error, resampling not required */
994  av_log(ctx, AV_LOG_DEBUG, "File '%s' loaded.\n", s->filename);
995  }
996 
997  if (ret) {
998  av_log(ctx, AV_LOG_ERROR, "No valid SOFA file could be loaded. Please specify valid SOFA file.\n");
999  return ret;
1000  }
1001 
1002  s->fdsp = avpriv_float_dsp_alloc(0);
1003  if (!s->fdsp)
1004  return AVERROR(ENOMEM);
1005 
1006  return 0;
1007 }
1008 
1010 {
1011  AVFilterContext *ctx = inlink->dst;
1012  SOFAlizerContext *s = ctx->priv;
1013  int ret;
1014 
1015  if (s->type == FREQUENCY_DOMAIN)
1016  s->nb_samples = s->framesize;
1017 
1018  /* gain -3 dB per channel */
1019  s->gain_lfe = expf((s->gain - 3 * inlink->channels + s->lfe_gain) / 20 * M_LN10);
1020 
1021  s->n_conv = inlink->channels;
1022 
1023  /* load IRs to data_ir[0] and data_ir[1] for required directions */
1024  if ((ret = load_data(ctx, s->rotation, s->elevation, s->radius, inlink->sample_rate)) < 0)
1025  return ret;
1026 
1027  av_log(ctx, AV_LOG_DEBUG, "Samplerate: %d Channels to convolute: %d, Length of ringbuffer: %d x %d\n",
1028  inlink->sample_rate, s->n_conv, inlink->channels, s->buffer_length);
1029 
1030  return 0;
1031 }
1032 
1034 {
1035  SOFAlizerContext *s = ctx->priv;
1036 
1037  close_sofa(&s->sofa);
1038  av_tx_uninit(&s->ifft[0]);
1039  av_tx_uninit(&s->ifft[1]);
1040  av_tx_uninit(&s->fft[0]);
1041  av_tx_uninit(&s->fft[1]);
1042  s->ifft[0] = NULL;
1043  s->ifft[1] = NULL;
1044  s->fft[0] = NULL;
1045  s->fft[1] = NULL;
1046  av_freep(&s->delay[0]);
1047  av_freep(&s->delay[1]);
1048  av_freep(&s->data_ir[0]);
1049  av_freep(&s->data_ir[1]);
1050  av_freep(&s->ringbuffer[0]);
1051  av_freep(&s->ringbuffer[1]);
1052  av_freep(&s->speaker_azim);
1053  av_freep(&s->speaker_elev);
1054  av_freep(&s->temp_src[0]);
1055  av_freep(&s->temp_src[1]);
1056  av_freep(&s->temp_afft[0]);
1057  av_freep(&s->temp_afft[1]);
1058  av_freep(&s->in_fft[0]);
1059  av_freep(&s->in_fft[1]);
1060  av_freep(&s->out_fft[0]);
1061  av_freep(&s->out_fft[1]);
1062  av_freep(&s->data_hrtf[0]);
1063  av_freep(&s->data_hrtf[1]);
1064  av_freep(&s->fdsp);
1065 }
1066 
1067 #define OFFSET(x) offsetof(SOFAlizerContext, x)
1068 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
1069 
1070 static const AVOption sofalizer_options[] = {
1071  { "sofa", "sofa filename", OFFSET(filename), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
1072  { "gain", "set gain in dB", OFFSET(gain), AV_OPT_TYPE_FLOAT, {.dbl=0}, -20, 40, .flags = FLAGS },
1073  { "rotation", "set rotation" , OFFSET(rotation), AV_OPT_TYPE_FLOAT, {.dbl=0}, -360, 360, .flags = FLAGS },
1074  { "elevation", "set elevation", OFFSET(elevation), AV_OPT_TYPE_FLOAT, {.dbl=0}, -90, 90, .flags = FLAGS },
1075  { "radius", "set radius", OFFSET(radius), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 5, .flags = FLAGS },
1076  { "type", "set processing", OFFSET(type), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, .flags = FLAGS, "type" },
1077  { "time", "time domain", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, .flags = FLAGS, "type" },
1078  { "freq", "frequency domain", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, .flags = FLAGS, "type" },
1079  { "speakers", "set speaker custom positions", OFFSET(speakers_pos), AV_OPT_TYPE_STRING, {.str=0}, 0, 0, .flags = FLAGS },
1080  { "lfegain", "set lfe gain", OFFSET(lfe_gain), AV_OPT_TYPE_FLOAT, {.dbl=0}, -20,40, .flags = FLAGS },
1081  { "framesize", "set frame size", OFFSET(framesize), AV_OPT_TYPE_INT, {.i64=1024},1024,96000, .flags = FLAGS },
1082  { "normalize", "normalize IRs", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, .flags = FLAGS },
1083  { "interpolate","interpolate IRs from neighbors", OFFSET(interpolate),AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags = FLAGS },
1084  { "minphase", "minphase IRs", OFFSET(minphase), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags = FLAGS },
1085  { "anglestep", "set neighbor search angle step", OFFSET(anglestep), AV_OPT_TYPE_FLOAT, {.dbl=.5}, 0.01, 10, .flags = FLAGS },
1086  { "radstep", "set neighbor search radius step", OFFSET(radstep), AV_OPT_TYPE_FLOAT, {.dbl=.01}, 0.01, 1, .flags = FLAGS },
1087  { NULL }
1088 };
1089 
1090 AVFILTER_DEFINE_CLASS(sofalizer);
1091 
1092 static const AVFilterPad inputs[] = {
1093  {
1094  .name = "default",
1095  .type = AVMEDIA_TYPE_AUDIO,
1096  .config_props = config_input,
1097  },
1098 };
1099 
1100 static const AVFilterPad outputs[] = {
1101  {
1102  .name = "default",
1103  .type = AVMEDIA_TYPE_AUDIO,
1104  },
1105 };
1106 
1108  .name = "sofalizer",
1109  .description = NULL_IF_CONFIG_SMALL("SOFAlizer (Spatially Oriented Format for Acoustics)."),
1110  .priv_size = sizeof(SOFAlizerContext),
1111  .priv_class = &sofalizer_class,
1112  .init = init,
1113  .activate = activate,
1114  .uninit = uninit,
1118  .flags = AVFILTER_FLAG_SLICE_THREADS,
1119 };
ff_get_audio_buffer
AVFrame * ff_get_audio_buffer(AVFilterLink *link, int nb_samples)
Request an audio samples buffer with a specific set of permissions.
Definition: audio.c:88
AV_SAMPLE_FMT_FLTP
@ AV_SAMPLE_FMT_FLTP
float, planar
Definition: samplefmt.h:69
AVFilterChannelLayouts
A list of supported channel layouts.
Definition: formats.h:85
SOFAlizerContext::write
int write[2]
Definition: af_sofalizer.c:81
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
td
#define td
Definition: regdef.h:70
TIME_DOMAIN
#define TIME_DOMAIN
Definition: af_sofalizer.c:42
SOFAlizerContext::filename
char * filename
Definition: af_sofalizer.c:65
SOFAlizerContext::nb_samples
int nb_samples
Definition: af_sofalizer.c:85
SOFAlizerContext::speakers_pos
char * speakers_pos
Definition: af_sofalizer.c:71
SOFAlizerContext::radstep
float radstep
Definition: af_sofalizer.c:108
SOFAlizerContext
Definition: af_sofalizer.c:62
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
ThreadData::out_fft
AVComplexFloat ** out_fft
Definition: af_headphone.c:135
SOFAlizerContext::vspkrpos
VirtualSpeaker vspkrpos[64]
Definition: af_sofalizer.c:110
AV_CH_TOP_FRONT_CENTER
#define AV_CH_TOP_FRONT_CENTER
Definition: channel_layout.h:62
out
FILE * out
Definition: movenc.c:54
parse_channel_name
static int parse_channel_name(AVFilterContext *ctx, char **arg, int *rchannel)
Definition: af_sofalizer.c:188
AV_CH_LOW_FREQUENCY_2
#define AV_CH_LOW_FREQUENCY_2
Definition: channel_layout.h:73
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1018
sample_fmts
static enum AVSampleFormat sample_fmts[]
Definition: adpcmenc.c:948
ff_channel_layouts_ref
int ff_channel_layouts_ref(AVFilterChannelLayouts *f, AVFilterChannelLayouts **ref)
Add *ref as a new reference to f.
Definition: formats.c:550
layouts
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:434
FFERROR_NOT_READY
return FFERROR_NOT_READY
Definition: filter_design.txt:204
AVTXContext
Definition: tx_priv.h:110
ff_set_common_samplerates_from_list
int ff_set_common_samplerates_from_list(AVFilterContext *ctx, const int *samplerates)
Equivalent to ff_set_common_samplerates(ctx, ff_make_format_list(samplerates))
Definition: formats.c:683
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
ff_clz
#define ff_clz
Definition: intmath.h:142
AV_CH_TOP_FRONT_RIGHT
#define AV_CH_TOP_FRONT_RIGHT
Definition: channel_layout.h:63
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:112
SOFAlizerContext::in_fft
AVComplexFloat * in_fft[2]
Definition: af_sofalizer.c:93
SOFAlizerContext::lfe_channel
int lfe_channel
Definition: af_sofalizer.c:74
im
float im
Definition: fft.c:78
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:303
AVOption
AVOption.
Definition: opt.h:247
FILTER_QUERY_FUNC
#define FILTER_QUERY_FUNC(func)
Definition: internal.h:168
expf
#define expf(x)
Definition: libm.h:283
AV_CH_TOP_FRONT_LEFT
#define AV_CH_TOP_FRONT_LEFT
Definition: channel_layout.h:61
AVComplexFloat
Definition: tx.h:27
SOFAlizerContext::type
int type
Definition: af_sofalizer.c:102
av_get_channel_layout
uint64_t av_get_channel_layout(const char *name)
Return a channel layout id that matches name, or 0 if no match is found.
Definition: channel_layout.c:145
SOFAlizerContext::anglestep
float anglestep
Definition: af_sofalizer.c:107
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:153
parse_speaker_pos
static void parse_speaker_pos(AVFilterContext *ctx, int64_t in_channel_layout)
Definition: af_sofalizer.c:224
ThreadData::out
AVFrame * out
Definition: af_adeclick.c:473
outputs
static const AVFilterPad outputs[]
Definition: af_sofalizer.c:1100
FF_FILTER_FORWARD_STATUS_BACK
#define FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink)
Forward the status on an output link to an input link.
Definition: filters.h:199
AV_CH_WIDE_LEFT
#define AV_CH_WIDE_LEFT
Definition: channel_layout.h:69
sample_rate
sample_rate
Definition: ffmpeg_filter.c:156
av_tx_init
av_cold int av_tx_init(AVTXContext **ctx, av_tx_fn *tx, enum AVTXType type, int inv, int len, const void *scale, uint64_t flags)
Initialize a transform context with the given configuration (i)MDCTs with an odd length are currently...
Definition: tx.c:228
ThreadData::temp_src
float ** temp_src
Definition: af_headphone.c:134
SOFAlizerContext::gain_lfe
float gain_lfe
Definition: af_sofalizer.c:73
AV_CH_SURROUND_DIRECT_RIGHT
#define AV_CH_SURROUND_DIRECT_RIGHT
Definition: channel_layout.h:72
SOFAlizerContext::n_conv
int n_conv
Definition: af_sofalizer.c:76
AV_CH_WIDE_RIGHT
#define AV_CH_WIDE_RIGHT
Definition: channel_layout.h:70
AV_CH_TOP_BACK_LEFT
#define AV_CH_TOP_BACK_LEFT
Definition: channel_layout.h:64
ff_inlink_consume_frame
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link's FIFO and update the link's stats.
Definition: avfilter.c:1417
AVComplexFloat::im
float im
Definition: tx.h:28
AV_CH_TOP_BACK_CENTER
#define AV_CH_TOP_BACK_CENTER
Definition: channel_layout.h:65
fail
#define fail()
Definition: checkasm.h:127
VirtualSpeaker::elev
float elev
Definition: af_sofalizer.c:59
AV_CH_BACK_LEFT
#define AV_CH_BACK_LEFT
Definition: channel_layout.h:53
ThreadData::ringbuffer
float ** ringbuffer
Definition: af_headphone.c:133
SOFAlizerContext::sofa
MySofa sofa
Definition: af_sofalizer.c:66
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
scale
static av_always_inline float scale(float x, float s)
Definition: vf_v360.c:1377
SOFAlizerContext::sample_rate
int sample_rate
Definition: af_sofalizer.c:68
fabsf
static __device__ float fabsf(float a)
Definition: cuda_runtime.h:181
AV_CH_LAYOUT_STEREO
#define AV_CH_LAYOUT_STEREO
Definition: channel_layout.h:91
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:50
MySofa::lir
float * lir
Definition: af_sofalizer.c:51
MySofa::n_samples
int n_samples
Definition: af_sofalizer.c:50
mult
static int16_t mult(Float11 *f1, Float11 *f2)
Definition: g726.c:56
SOFAlizerContext::interpolate
int interpolate
Definition: af_sofalizer.c:105
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
av_cold
#define av_cold
Definition: attributes.h:90
av_tx_fn
void(* av_tx_fn)(AVTXContext *s, void *out, void *in, ptrdiff_t stride)
Function pointer to a function to perform the transform.
Definition: tx.h:102
AV_CH_LOW_FREQUENCY
#define AV_CH_LOW_FREQUENCY
Definition: channel_layout.h:52
FREQUENCY_DOMAIN
#define FREQUENCY_DOMAIN
Definition: af_sofalizer.c:43
mask
static const uint16_t mask[17]
Definition: lzw.c:38
ff_add_channel_layout
int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout)
Definition: formats.c:426
s
#define s(width, name)
Definition: cbs_vp9.c:257
config_input
static int config_input(AVFilterLink *inlink)
Definition: af_sofalizer.c:1009
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
av_strtok
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:186
ff_set_common_formats_from_list
int ff_set_common_formats_from_list(AVFilterContext *ctx, const int *fmts)
Equivalent to ff_set_common_formats(ctx, ff_make_format_list(fmts))
Definition: formats.c:705
get_speaker_pos
static int get_speaker_pos(AVFilterContext *ctx, float *speaker_azim, float *speaker_elev)
Definition: af_sofalizer.c:255
filters.h
AV_TX_FLOAT_FFT
@ AV_TX_FLOAT_FFT
Standard complex to complex FFT with sample data type AVComplexFloat.
Definition: tx.h:45
load_data
static int load_data(AVFilterContext *ctx, int azim, int elev, float radius, int sample_rate)
Definition: af_sofalizer.c:727
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
ctx
AVFormatContext * ctx
Definition: movenc.c:48
SOFAlizerContext::data_hrtf
AVComplexFloat * data_hrtf[2]
Definition: af_sofalizer.c:114
SOFAlizerContext::data_ir
float * data_ir[2]
Definition: af_sofalizer.c:90
init
static av_cold int init(AVFilterContext *ctx)
Definition: af_sofalizer.c:978
SOFAlizerContext::framesize
int framesize
Definition: af_sofalizer.c:103
sofalizer_fast_convolute
static int sofalizer_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: af_sofalizer.c:443
MySofa::lookup
struct MYSOFA_LOOKUP * lookup
Definition: af_sofalizer.c:47
MySofa::ir_samples
int ir_samples
Definition: af_sofalizer.c:49
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: internal.h:191
SOFAlizerContext::fdsp
AVFloatDSPContext * fdsp
Definition: af_sofalizer.c:116
arg
const char * arg
Definition: jacosubdec.c:67
AV_CH_STEREO_RIGHT
#define AV_CH_STEREO_RIGHT
See AV_CH_STEREO_LEFT.
Definition: channel_layout.h:68
if
if(ret)
Definition: filter_design.txt:179
activate
static int activate(AVFilterContext *ctx)
Definition: af_sofalizer.c:623
SOFAlizerContext::ringbuffer
float * ringbuffer[2]
Definition: af_sofalizer.c:79
av_sscanf
int av_sscanf(const char *string, const char *format,...)
See libc sscanf manual for more information.
Definition: avsscanf.c:960
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
AV_CH_TOP_CENTER
#define AV_CH_TOP_CENTER
Definition: channel_layout.h:60
ff_inlink_consume_samples
int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max, AVFrame **rframe)
Take samples from the link's FIFO and update the link's stats.
Definition: avfilter.c:1436
NULL
#define NULL
Definition: coverity.c:32
av_frame_copy_props
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:537
SOFAlizerContext::delay
int * delay[2]
Definition: af_sofalizer.c:88
SOFAlizerContext::buffer_length
int buffer_length
Definition: af_sofalizer.c:82
MySofa::rir
float * rir
Definition: af_sofalizer.c:51
src
#define src
Definition: vp8dsp.c:255
MySofa::max_delay
int max_delay
Definition: af_sofalizer.c:53
AV_CH_FRONT_CENTER
#define AV_CH_FRONT_CENTER
Definition: channel_layout.h:51
ThreadData::in_fft
AVComplexFloat ** in_fft
Definition: af_headphone.c:136
filter_frame
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: af_sofalizer.c:583
AV_CH_FRONT_LEFT_OF_CENTER
#define AV_CH_FRONT_LEFT_OF_CENTER
Definition: channel_layout.h:55
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
float_dsp.h
inputs
static const AVFilterPad inputs[]
Definition: af_sofalizer.c:1092
SOFAlizerContext::speaker_azim
float * speaker_azim
Definition: af_sofalizer.c:69
SOFAlizerContext::temp_afft
AVComplexFloat * temp_afft[2]
Definition: af_sofalizer.c:95
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
VirtualSpeaker
Definition: af_sofalizer.c:56
SOFAlizerContext::n_fft
int n_fft
Definition: af_sofalizer.c:84
AV_SAMPLE_FMT_NONE
@ AV_SAMPLE_FMT_NONE
Definition: samplefmt.h:59
SOFAlizerContext::rotation
float rotation
Definition: af_sofalizer.c:99
AVComplexFloat::re
float re
Definition: tx.h:28
AVFloatDSPContext
Definition: float_dsp.h:24
AVFrame::format
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition: frame.h:376
query_formats
static int query_formats(AVFilterContext *ctx)
Definition: af_sofalizer.c:648
OFFSET
#define OFFSET(x)
Definition: af_sofalizer.c:1067
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
FF_FILTER_FORWARD_WANTED
FF_FILTER_FORWARD_WANTED(outlink, inlink)
AV_CH_TOP_BACK_RIGHT
#define AV_CH_TOP_BACK_RIGHT
Definition: channel_layout.h:66
AV_CH_FRONT_RIGHT_OF_CENTER
#define AV_CH_FRONT_RIGHT_OF_CENTER
Definition: channel_layout.h:56
ff_all_channel_layouts
AVFilterChannelLayouts * ff_all_channel_layouts(void)
Construct an empty AVFilterChannelLayouts/AVFilterFormats struct – representing any channel layout (w...
Definition: formats.c:516
preload_sofa
static int preload_sofa(AVFilterContext *ctx, char *filename, int *samplingrate)
Definition: af_sofalizer.c:135
SOFAlizerContext::radius
float radius
Definition: af_sofalizer.c:101
interpolate
static void interpolate(float *out, float v1, float v2, int size)
Definition: twinvq.c:84
av_tx_uninit
av_cold void av_tx_uninit(AVTXContext **ctx)
Frees a context and sets ctx to NULL, does nothing when ctx == NULL.
Definition: tx.c:213
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:191
sample_rates
sample_rates
Definition: ffmpeg_filter.c:156
internal.h
AV_OPT_TYPE_FLOAT
@ AV_OPT_TYPE_FLOAT
Definition: opt.h:227
SOFAlizerContext::tx_fn
av_tx_fn tx_fn[2]
Definition: af_sofalizer.c:113
layout
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel layout
Definition: filter_design.txt:18
getfilter_float
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:683
normalize
Definition: normalize.py:1
AVFrame::nb_samples
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:369
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
FLAGS
#define FLAGS
Definition: af_sofalizer.c:1068
AVFrame::extended_data
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:350
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:32
sofalizer_options
static const AVOption sofalizer_options[]
Definition: af_sofalizer.c:1070
AVSampleFormat
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:58
ThreadData
Used for passing data between threads.
Definition: dsddec.c:67
AV_CH_BACK_CENTER
#define AV_CH_BACK_CENTER
Definition: channel_layout.h:57
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
AV_CH_FRONT_LEFT
#define AV_CH_FRONT_LEFT
Definition: channel_layout.h:49
ThreadData::n_clippings
int * n_clippings
Definition: af_headphone.c:132
AV_CH_SIDE_RIGHT
#define AV_CH_SIDE_RIGHT
Definition: channel_layout.h:59
ThreadData::delay
int ** delay
Definition: af_sofalizer.c:333
len
int len
Definition: vorbis_enc_data.h:426
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:56
MySofa
Definition: af_sofalizer.c:45
SOFAlizerContext::lfe_gain
float lfe_gain
Definition: af_sofalizer.c:72
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:271
AVFilter
Filter definition.
Definition: avfilter.h:149
SOFAlizerContext::fft
AVTXContext * fft[2]
Definition: af_sofalizer.c:112
ret
ret
Definition: filter_design.txt:187
ThreadData::write
int * write
Definition: af_headphone.c:130
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: af_sofalizer.c:1033
left
Tag MUST be and< 10hcoeff half pel interpolation filter coefficients, hcoeff[0] are the 2 middle coefficients[1] are the next outer ones and so on, resulting in a filter like:...eff[2], hcoeff[1], hcoeff[0], hcoeff[0], hcoeff[1], hcoeff[2] ... the sign of the coefficients is not explicitly stored but alternates after each coeff and coeff[0] is positive, so ...,+,-,+,-,+,+,-,+,-,+,... hcoeff[0] is not explicitly stored but found by subtracting the sum of all stored coefficients with signs from 32 hcoeff[0]=32 - hcoeff[1] - hcoeff[2] - ... a good choice for hcoeff and htaps is htaps=6 hcoeff={40,-10, 2} an alternative which requires more computations at both encoder and decoder side and may or may not be better is htaps=8 hcoeff={42,-14, 6,-2}ref_frames minimum of the number of available reference frames and max_ref_frames for example the first frame after a key frame always has ref_frames=1spatial_decomposition_type wavelet type 0 is a 9/7 symmetric compact integer wavelet 1 is a 5/3 symmetric compact integer wavelet others are reserved stored as delta from last, last is reset to 0 if always_reset||keyframeqlog quality(logarithmic quantizer scale) stored as delta from last, last is reset to 0 if always_reset||keyframemv_scale stored as delta from last, last is reset to 0 if always_reset||keyframe FIXME check that everything works fine if this changes between framesqbias dequantization bias stored as delta from last, last is reset to 0 if always_reset||keyframeblock_max_depth maximum depth of the block tree stored as delta from last, last is reset to 0 if always_reset||keyframequant_table quantization tableHighlevel bitstream structure:==============================--------------------------------------------|Header|--------------------------------------------|------------------------------------|||Block0||||split?||||yes no||||......... intra?||||:Block01 :yes no||||:Block02 :....... ..........||||:Block03 ::y DC ::ref index:||||:Block04 ::cb DC ::motion x :||||......... :cr DC ::motion y :||||....... ..........|||------------------------------------||------------------------------------|||Block1|||...|--------------------------------------------|------------ ------------ ------------|||Y subbands||Cb subbands||Cr subbands||||--- ---||--- ---||--- ---|||||LL0||HL0||||LL0||HL0||||LL0||HL0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||LH0||HH0||||LH0||HH0||||LH0||HH0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HL1||LH1||||HL1||LH1||||HL1||LH1|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HH1||HL2||||HH1||HL2||||HH1||HL2|||||...||...||...|||------------ ------------ ------------|--------------------------------------------Decoding process:=================------------|||Subbands|------------||||------------|Intra DC||||LL0 subband prediction ------------|\ Dequantization ------------------- \||Reference frames|\ IDWT|------- -------|Motion \|||Frame 0||Frame 1||Compensation . OBMC v -------|------- -------|--------------. \------> Frame n output Frame Frame<----------------------------------/|...|------------------- Range Coder:============Binary Range Coder:------------------- The implemented range coder is an adapted version based upon "Range encoding: an algorithm for removing redundancy from a digitised message." by G. N. N. Martin. The symbols encoded by the Snow range coder are bits(0|1). The associated probabilities are not fix but change depending on the symbol mix seen so far. bit seen|new state ---------+----------------------------------------------- 0|256 - state_transition_table[256 - old_state];1|state_transition_table[old_state];state_transition_table={ 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 194, 194, 195, 196, 197, 198, 199, 200, 201, 202, 202, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 215, 215, 216, 217, 218, 219, 220, 220, 222, 223, 224, 225, 226, 227, 227, 229, 229, 230, 231, 232, 234, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 0, 0, 0, 0, 0, 0, 0};FIXME Range Coding of integers:------------------------- FIXME Neighboring Blocks:===================left and top are set to the respective blocks unless they are outside of the image in which case they are set to the Null block top-left is set to the top left block unless it is outside of the image in which case it is set to the left block if this block has no larger parent block or it is at the left side of its parent block and the top right block is not outside of the image then the top right block is used for top-right else the top-left block is used Null block y, cb, cr are 128 level, ref, mx and my are 0 Motion Vector Prediction:=========================1. the motion vectors of all the neighboring blocks are scaled to compensate for the difference of reference frames scaled_mv=(mv *(256 *(current_reference+1)/(mv.reference+1))+128)> the median of the scaled left
Definition: snow.txt:386
ThreadData::temp_afft
AVComplexFloat ** temp_afft
Definition: af_headphone.c:137
SOFAlizerContext::out_fft
AVComplexFloat * out_fft[2]
Definition: af_sofalizer.c:94
sofalizer_convolute
static int sofalizer_convolute(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: af_sofalizer.c:343
channel_layout.h
SOFAlizerContext::minphase
int minphase
Definition: af_sofalizer.c:106
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
MySofa::hrtf
struct MYSOFA_HRTF * hrtf
Definition: af_sofalizer.c:46
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:224
avfilter.h
VirtualSpeaker::set
uint8_t set
Definition: af_sofalizer.c:57
AV_CH_SURROUND_DIRECT_LEFT
#define AV_CH_SURROUND_DIRECT_LEFT
Definition: channel_layout.h:71
AVFilterContext
An instance of a filter.
Definition: avfilter.h:386
MySofa::neighborhood
struct MYSOFA_NEIGHBORHOOD * neighborhood
Definition: af_sofalizer.c:48
AV_CH_FRONT_RIGHT
#define AV_CH_FRONT_RIGHT
Definition: channel_layout.h:50
AVFILTER_FLAG_SLICE_THREADS
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:121
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:279
audio.h
ff_af_sofalizer
const AVFilter ff_af_sofalizer
Definition: af_sofalizer.c:1107
M_LN10
#define M_LN10
Definition: mathematics.h:43
VirtualSpeaker::azim
float azim
Definition: af_sofalizer.c:58
ThreadData::in
AVFrame * in
Definition: af_adecorrelate.c:154
SOFAlizerContext::speaker_elev
float * speaker_elev
Definition: af_sofalizer.c:70
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
FF_FILTER_FORWARD_STATUS
FF_FILTER_FORWARD_STATUS(inlink, outlink)
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:241
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:192
SOFAlizerContext::ifft
AVTXContext * ifft[2]
Definition: af_sofalizer.c:112
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
avpriv_float_dsp_alloc
av_cold AVFloatDSPContext * avpriv_float_dsp_alloc(int bit_exact)
Allocate a float DSP context.
Definition: float_dsp.c:135
FFMAX3
#define FFMAX3(a, b, c)
Definition: macros.h:48
SOFAlizerContext::gain
float gain
Definition: af_sofalizer.c:98
ThreadData::ir
float ** ir
Definition: af_headphone.c:131
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
AV_CH_BACK_RIGHT
#define AV_CH_BACK_RIGHT
Definition: channel_layout.h:54
SOFAlizerContext::temp_src
float * temp_src[2]
Definition: af_sofalizer.c:92
AV_CH_STEREO_LEFT
#define AV_CH_STEREO_LEFT
Stereo downmix.
Definition: channel_layout.h:67
MySofa::fir
float * fir
Definition: af_sofalizer.c:52
avstring.h
SOFAlizerContext::itx_fn
av_tx_fn itx_fn[2]
Definition: af_sofalizer.c:113
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:228
ff_filter_execute
static av_always_inline int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
Definition: internal.h:143
planar
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_S32, int32_t, AV_SAMPLE_FMT_S16, *(const int16_t *) pi *(1<< 16)) 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/(UINT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S64, *(const int64_t *) pi *(1.0/(UINT64_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 *(UINT64_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 *(UINT64_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 &&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);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,(const uint8_t **) in->ch+ch, off *(out-> planar
Definition: audioconvert.c:56
int
int
Definition: ffmpeg_filter.c:156
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:233
SOFAlizerContext::normalize
int normalize
Definition: af_sofalizer.c:104
AV_SAMPLE_FMT_FLT
@ AV_SAMPLE_FMT_FLT
float
Definition: samplefmt.h:63
SOFAlizerContext::elevation
float elevation
Definition: af_sofalizer.c:100
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(sofalizer)
AV_CH_SIDE_LEFT
#define AV_CH_SIDE_LEFT
Definition: channel_layout.h:58
tx.h
re
float re
Definition: fft.c:78
close_sofa
static int close_sofa(struct MySofa *sofa)
Definition: af_sofalizer.c:119
intmath.h