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/mem.h"
32 #include "libavutil/tx.h"
33 #include "libavutil/avstring.h"
35 #include "libavutil/float_dsp.h"
36 #include "libavutil/intmath.h"
37 #include "libavutil/opt.h"
38 #include "avfilter.h"
39 #include "filters.h"
40 #include "formats.h"
41 #include "audio.h"
42 
43 #define TIME_DOMAIN 0
44 #define FREQUENCY_DOMAIN 1
45 
46 typedef struct MySofa { /* contains data of one SOFA file */
47  struct MYSOFA_HRTF *hrtf;
48  struct MYSOFA_LOOKUP *lookup;
49  struct MYSOFA_NEIGHBORHOOD *neighborhood;
50  int ir_samples; /* length of one impulse response (IR) */
51  int n_samples; /* ir_samples to next power of 2 */
52  float *lir, *rir; /* IRs (time-domain) */
53  float *fir;
54  int max_delay;
55 } MySofa;
56 
57 typedef struct VirtualSpeaker {
58  uint8_t set;
59  float azim;
60  float elev;
62 
63 typedef struct SOFAlizerContext {
64  const AVClass *class;
65 
66  char *filename; /* name of SOFA file */
67  MySofa sofa; /* contains data of the SOFA file */
68 
69  int sample_rate; /* sample rate from SOFA file */
70  float *speaker_azim; /* azimuth of the virtual loudspeakers */
71  float *speaker_elev; /* elevation of the virtual loudspeakers */
72  char *speakers_pos; /* custom positions of the virtual loudspeakers */
73  float lfe_gain; /* initial gain for the LFE channel */
74  float gain_lfe; /* gain applied to LFE channel */
75  int lfe_channel; /* LFE channel position in channel layout */
76 
77  int n_conv; /* number of channels to convolute */
78 
79  /* buffer variables (for convolution) */
80  float *ringbuffer[2]; /* buffers input samples, length of one buffer: */
81  /* no. input ch. (incl. LFE) x buffer_length */
82  int write[2]; /* current write position to ringbuffer */
83  int buffer_length; /* is: longest IR plus max. delay in all SOFA files */
84  /* then choose next power of 2 */
85  int n_fft; /* number of samples in one FFT block */
87 
88  /* netCDF variables */
89  int *delay[2]; /* broadband delay for each channel/IR to be convolved */
90 
91  float *data_ir[2]; /* IRs for all channels to be convolved */
92  /* (this excludes the LFE) */
93  float *temp_src[2];
94  AVComplexFloat *in_fft[2]; /* Array to hold input FFT values */
95  AVComplexFloat *out_fft[2]; /* Array to hold output FFT values */
96  AVComplexFloat *temp_afft[2]; /* Array to accumulate FFT values prior to IFFT */
97 
98  /* control variables */
99  float gain; /* filter gain (in dB) */
100  float rotation; /* rotation of virtual loudspeakers (in degrees) */
101  float elevation; /* elevation of virtual loudspeakers (in deg.) */
102  float radius; /* distance virtual loudspeakers to listener (in metres) */
103  int type; /* processing type */
104  int framesize; /* size of buffer */
105  int normalize; /* should all IRs be normalized upon import ? */
106  int interpolate; /* should wanted IRs be interpolated from neighbors ? */
107  int minphase; /* should all IRs be minphased upon import ? */
108  float anglestep; /* neighbor search angle step, in agles */
109  float radstep; /* neighbor search radius step, in meters */
110 
112 
113  AVTXContext *fft[2], *ifft[2];
116 
119 
120 static int close_sofa(struct MySofa *sofa)
121 {
122  if (sofa->neighborhood)
123  mysofa_neighborhood_free(sofa->neighborhood);
124  sofa->neighborhood = NULL;
125  if (sofa->lookup)
126  mysofa_lookup_free(sofa->lookup);
127  sofa->lookup = NULL;
128  if (sofa->hrtf)
129  mysofa_free(sofa->hrtf);
130  sofa->hrtf = NULL;
131  av_freep(&sofa->fir);
132 
133  return 0;
134 }
135 
136 static int preload_sofa(AVFilterContext *ctx, char *filename, int *samplingrate)
137 {
138  struct SOFAlizerContext *s = ctx->priv;
139  struct MYSOFA_HRTF *mysofa;
140  char *license;
141  int ret;
142 
143  mysofa = mysofa_load(filename, &ret);
144  s->sofa.hrtf = mysofa;
145  if (ret || !mysofa) {
146  av_log(ctx, AV_LOG_ERROR, "Can't find SOFA-file '%s'\n", filename);
147  return AVERROR(EINVAL);
148  }
149 
150  ret = mysofa_check(mysofa);
151  if (ret != MYSOFA_OK) {
152  av_log(ctx, AV_LOG_ERROR, "Selected SOFA file is invalid. Please select valid SOFA file.\n");
153  return ret;
154  }
155 
156  if (s->normalize)
157  mysofa_loudness(s->sofa.hrtf);
158 
159  if (s->minphase)
160  mysofa_minphase(s->sofa.hrtf, 0.01f);
161 
162  mysofa_tocartesian(s->sofa.hrtf);
163 
164  s->sofa.lookup = mysofa_lookup_init(s->sofa.hrtf);
165  if (s->sofa.lookup == NULL)
166  return AVERROR(EINVAL);
167 
168  if (s->interpolate)
169  s->sofa.neighborhood = mysofa_neighborhood_init_withstepdefine(s->sofa.hrtf,
170  s->sofa.lookup,
171  s->anglestep,
172  s->radstep);
173 
174  s->sofa.fir = av_calloc(s->sofa.hrtf->N * s->sofa.hrtf->R, sizeof(*s->sofa.fir));
175  if (!s->sofa.fir)
176  return AVERROR(ENOMEM);
177 
178  if (mysofa->DataSamplingRate.elements != 1)
179  return AVERROR(EINVAL);
180  av_log(ctx, AV_LOG_DEBUG, "Original IR length: %d.\n", mysofa->N);
181  *samplingrate = mysofa->DataSamplingRate.values[0];
182  license = mysofa_getAttribute(mysofa->attributes, (char *)"License");
183  if (license)
184  av_log(ctx, AV_LOG_INFO, "SOFA license: %s\n", license);
185 
186  return 0;
187 }
188 
189 static int parse_channel_name(AVFilterContext *ctx, char **arg, int *rchannel)
190 {
191  int len;
192  enum AVChannel channel_id = 0;
193  char buf[8] = {0};
194 
195  /* try to parse a channel name, e.g. "FL" */
196  if (av_sscanf(*arg, "%7[A-Z]%n", buf, &len)) {
197  channel_id = av_channel_from_string(buf);
198  if (channel_id < 0 || channel_id >= 64) {
199  av_log(ctx, AV_LOG_WARNING, "Failed to parse \'%s\' as channel name.\n", buf);
200  return AVERROR(EINVAL);
201  }
202 
203  *rchannel = channel_id;
204  *arg += len;
205  return 0;
206  } else if (av_sscanf(*arg, "%d%n", &channel_id, &len) == 1) {
207  if (channel_id < 0 || channel_id >= 64) {
208  av_log(ctx, AV_LOG_WARNING, "Failed to parse \'%d\' as channel number.\n", channel_id);
209  return AVERROR(EINVAL);
210  }
211  *rchannel = channel_id;
212  *arg += len;
213  return 0;
214  }
215  return AVERROR(EINVAL);
216 }
217 
219 {
220  SOFAlizerContext *s = ctx->priv;
221  char *arg, *tokenizer, *p, *args = av_strdup(s->speakers_pos);
222 
223  if (!args)
224  return;
225  p = args;
226 
227  while ((arg = av_strtok(p, "|", &tokenizer))) {
228  float azim, elev;
229  int out_ch_id;
230 
231  p = NULL;
232  if (parse_channel_name(ctx, &arg, &out_ch_id)) {
233  continue;
234  }
235  if (av_sscanf(arg, "%f %f", &azim, &elev) == 2) {
236  s->vspkrpos[out_ch_id].set = 1;
237  s->vspkrpos[out_ch_id].azim = azim;
238  s->vspkrpos[out_ch_id].elev = elev;
239  } else if (av_sscanf(arg, "%f", &azim) == 1) {
240  s->vspkrpos[out_ch_id].set = 1;
241  s->vspkrpos[out_ch_id].azim = azim;
242  s->vspkrpos[out_ch_id].elev = 0;
243  }
244  }
245 
246  av_free(args);
247 }
248 
250  float *speaker_azim, float *speaker_elev)
251 {
252  struct SOFAlizerContext *s = ctx->priv;
253  AVChannelLayout *channel_layout = &ctx->inputs[0]->ch_layout;
254  float azim[64] = { 0 };
255  float elev[64] = { 0 };
256  int ch, n_conv = ctx->inputs[0]->ch_layout.nb_channels; /* get no. input channels */
257 
258  if (n_conv < 0 || n_conv > 64)
259  return AVERROR(EINVAL);
260 
261  s->lfe_channel = -1;
262 
263  if (s->speakers_pos)
265 
266  /* set speaker positions according to input channel configuration: */
267  for (ch = 0; ch < n_conv; ch++) {
268  int chan = av_channel_layout_channel_from_index(channel_layout, ch);
269 
270  switch (chan) {
271  case AV_CHAN_FRONT_LEFT: azim[ch] = 30; break;
272  case AV_CHAN_FRONT_RIGHT: azim[ch] = 330; break;
273  case AV_CHAN_FRONT_CENTER: azim[ch] = 0; break;
275  case AV_CHAN_LOW_FREQUENCY_2: s->lfe_channel = ch; break;
276  case AV_CHAN_BACK_LEFT: azim[ch] = 150; break;
277  case AV_CHAN_BACK_RIGHT: azim[ch] = 210; break;
278  case AV_CHAN_BACK_CENTER: azim[ch] = 180; break;
279  case AV_CHAN_SIDE_LEFT: azim[ch] = 90; break;
280  case AV_CHAN_SIDE_RIGHT: azim[ch] = 270; break;
281  case AV_CHAN_FRONT_LEFT_OF_CENTER: azim[ch] = 15; break;
282  case AV_CHAN_FRONT_RIGHT_OF_CENTER: azim[ch] = 345; break;
283  case AV_CHAN_TOP_CENTER: azim[ch] = 0;
284  elev[ch] = 90; break;
285  case AV_CHAN_TOP_FRONT_LEFT: azim[ch] = 30;
286  elev[ch] = 45; break;
287  case AV_CHAN_TOP_FRONT_CENTER: azim[ch] = 0;
288  elev[ch] = 45; break;
289  case AV_CHAN_TOP_FRONT_RIGHT: azim[ch] = 330;
290  elev[ch] = 45; break;
291  case AV_CHAN_TOP_BACK_LEFT: azim[ch] = 150;
292  elev[ch] = 45; break;
293  case AV_CHAN_TOP_BACK_RIGHT: azim[ch] = 210;
294  elev[ch] = 45; break;
295  case AV_CHAN_TOP_BACK_CENTER: azim[ch] = 180;
296  elev[ch] = 45; break;
297  case AV_CHAN_WIDE_LEFT: azim[ch] = 90; break;
298  case AV_CHAN_WIDE_RIGHT: azim[ch] = 270; break;
299  case AV_CHAN_SURROUND_DIRECT_LEFT: azim[ch] = 90; break;
300  case AV_CHAN_SURROUND_DIRECT_RIGHT: azim[ch] = 270; break;
301  case AV_CHAN_STEREO_LEFT: azim[ch] = 90; break;
302  case AV_CHAN_STEREO_RIGHT: azim[ch] = 270; break;
303  default:
304  return AVERROR(EINVAL);
305  }
306 
307  if (s->vspkrpos[ch].set) {
308  azim[ch] = s->vspkrpos[ch].azim;
309  elev[ch] = s->vspkrpos[ch].elev;
310  }
311  }
312 
313  memcpy(speaker_azim, azim, n_conv * sizeof(float));
314  memcpy(speaker_elev, elev, n_conv * sizeof(float));
315 
316  return 0;
317 
318 }
319 
320 typedef struct ThreadData {
321  AVFrame *in, *out;
322  int *write;
323  int **delay;
324  float **ir;
325  int *n_clippings;
326  float **ringbuffer;
327  float **temp_src;
331 } ThreadData;
332 
333 static int sofalizer_convolute(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
334 {
335  SOFAlizerContext *s = ctx->priv;
336  ThreadData *td = arg;
337  AVFrame *in = td->in, *out = td->out;
338  int offset = jobnr;
339  int *write = &td->write[jobnr];
340  const int *const delay = td->delay[jobnr];
341  const float *const ir = td->ir[jobnr];
342  int *n_clippings = &td->n_clippings[jobnr];
343  float *ringbuffer = td->ringbuffer[jobnr];
344  float *temp_src = td->temp_src[jobnr];
345  const int ir_samples = s->sofa.ir_samples; /* length of one IR */
346  const int n_samples = s->sofa.n_samples;
347  const int planar = in->format == AV_SAMPLE_FMT_FLTP;
348  const int mult = 1 + !planar;
349  const float *src = (const float *)in->extended_data[0]; /* get pointer to audio input buffer */
350  float *dst = (float *)out->extended_data[jobnr * planar]; /* get pointer to audio output buffer */
351  const int in_channels = s->n_conv; /* number of input channels */
352  /* ring buffer length is: longest IR plus max. delay -> next power of 2 */
353  const int buffer_length = s->buffer_length;
354  /* -1 for AND instead of MODULO (applied to powers of 2): */
355  const uint32_t modulo = (uint32_t)buffer_length - 1;
356  float *buffer[64]; /* holds ringbuffer for each input channel */
357  int wr = *write;
358  int read;
359  int i, l;
360 
361  if (!planar)
362  dst += offset;
363 
364  for (l = 0; l < in_channels; l++) {
365  /* get starting address of ringbuffer for each input channel */
366  buffer[l] = ringbuffer + l * buffer_length;
367  }
368 
369  for (i = 0; i < in->nb_samples; i++) {
370  const float *temp_ir = ir; /* using same set of IRs for each sample */
371 
372  dst[0] = 0;
373  if (planar) {
374  for (l = 0; l < in_channels; l++) {
375  const float *srcp = (const float *)in->extended_data[l];
376 
377  /* write current input sample to ringbuffer (for each channel) */
378  buffer[l][wr] = srcp[i];
379  }
380  } else {
381  for (l = 0; l < in_channels; l++) {
382  /* write current input sample to ringbuffer (for each channel) */
383  buffer[l][wr] = src[l];
384  }
385  }
386 
387  /* loop goes through all channels to be convolved */
388  for (l = 0; l < in_channels; l++) {
389  const float *const bptr = buffer[l];
390 
391  if (l == s->lfe_channel) {
392  /* LFE is an input channel but requires no convolution */
393  /* apply gain to LFE signal and add to output buffer */
394  dst[0] += *(buffer[s->lfe_channel] + wr) * s->gain_lfe;
395  temp_ir += n_samples;
396  continue;
397  }
398 
399  /* current read position in ringbuffer: input sample write position
400  * - delay for l-th ch. + diff. betw. IR length and buffer length
401  * (mod buffer length) */
402  read = (wr - delay[l] - (ir_samples - 1) + buffer_length) & modulo;
403 
404  if (read + ir_samples < buffer_length) {
405  memmove(temp_src, bptr + read, ir_samples * sizeof(*temp_src));
406  } else {
407  int len = FFMIN(n_samples - (read % ir_samples), buffer_length - read);
408 
409  memmove(temp_src, bptr + read, len * sizeof(*temp_src));
410  memmove(temp_src + len, bptr, (n_samples - len) * sizeof(*temp_src));
411  }
412 
413  /* multiply signal and IR, and add up the results */
414  dst[0] += s->fdsp->scalarproduct_float(temp_ir, temp_src, FFALIGN(ir_samples, 32));
415  temp_ir += n_samples;
416  }
417 
418  /* clippings counter */
419  if (fabsf(dst[0]) > 1)
420  n_clippings[0]++;
421 
422  /* move output buffer pointer by +2 to get to next sample of processed channel: */
423  dst += mult;
424  src += in_channels;
425  wr = (wr + 1) & modulo; /* update ringbuffer write position */
426  }
427 
428  *write = wr; /* remember write position in ringbuffer for next call */
429 
430  return 0;
431 }
432 
433 static int sofalizer_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
434 {
435  SOFAlizerContext *s = ctx->priv;
436  ThreadData *td = arg;
437  AVFrame *in = td->in, *out = td->out;
438  int offset = jobnr;
439  int *write = &td->write[jobnr];
440  AVComplexFloat *hrtf = s->data_hrtf[jobnr]; /* get pointers to current HRTF data */
441  int *n_clippings = &td->n_clippings[jobnr];
442  float *ringbuffer = td->ringbuffer[jobnr];
443  const int ir_samples = s->sofa.ir_samples; /* length of one IR */
444  const int planar = in->format == AV_SAMPLE_FMT_FLTP;
445  const int mult = 1 + !planar;
446  float *dst = (float *)out->extended_data[jobnr * planar]; /* get pointer to audio output buffer */
447  const int in_channels = s->n_conv; /* number of input channels */
448  /* ring buffer length is: longest IR plus max. delay -> next power of 2 */
449  const int buffer_length = s->buffer_length;
450  /* -1 for AND instead of MODULO (applied to powers of 2): */
451  const uint32_t modulo = (uint32_t)buffer_length - 1;
452  AVComplexFloat *fft_in = s->in_fft[jobnr]; /* temporary array for FFT input data */
453  AVComplexFloat *fft_out = s->out_fft[jobnr]; /* temporary array for FFT output data */
454  AVComplexFloat *fft_acc = s->temp_afft[jobnr];
455  AVTXContext *ifft = s->ifft[jobnr];
456  av_tx_fn itx_fn = s->itx_fn[jobnr];
457  AVTXContext *fft = s->fft[jobnr];
458  av_tx_fn tx_fn = s->tx_fn[jobnr];
459  const int n_conv = s->n_conv;
460  const int n_fft = s->n_fft;
461  const float fft_scale = 1.0f / s->n_fft;
462  AVComplexFloat *hrtf_offset;
463  int wr = *write;
464  int n_read;
465  int i, j;
466 
467  if (!planar)
468  dst += offset;
469 
470  /* find minimum between number of samples and output buffer length:
471  * (important, if one IR is longer than the output buffer) */
472  n_read = FFMIN(ir_samples, in->nb_samples);
473  for (j = 0; j < n_read; j++) {
474  /* initialize output buf with saved signal from overflow buf */
475  dst[mult * j] = ringbuffer[wr];
476  ringbuffer[wr] = 0.0f; /* re-set read samples to zero */
477  /* update ringbuffer read/write position */
478  wr = (wr + 1) & modulo;
479  }
480 
481  /* initialize rest of output buffer with 0 */
482  for (j = n_read; j < in->nb_samples; j++) {
483  dst[mult * j] = 0;
484  }
485 
486  /* fill FFT accumulation with 0 */
487  memset(fft_acc, 0, sizeof(AVComplexFloat) * n_fft);
488 
489  for (i = 0; i < n_conv; i++) {
490  const float *src = (const float *)in->extended_data[i * planar]; /* get pointer to audio input buffer */
491 
492  if (i == s->lfe_channel) { /* LFE */
493  if (in->format == AV_SAMPLE_FMT_FLT) {
494  for (j = 0; j < in->nb_samples; j++) {
495  /* apply gain to LFE signal and add to output buffer */
496  dst[2 * j] += src[i + j * in_channels] * s->gain_lfe;
497  }
498  } else {
499  for (j = 0; j < in->nb_samples; j++) {
500  /* apply gain to LFE signal and add to output buffer */
501  dst[j] += src[j] * s->gain_lfe;
502  }
503  }
504  continue;
505  }
506 
507  /* outer loop: go through all input channels to be convolved */
508  offset = i * n_fft; /* no. samples already processed */
509  hrtf_offset = hrtf + offset;
510 
511  /* fill FFT input with 0 (we want to zero-pad) */
512  memset(fft_in, 0, sizeof(AVComplexFloat) * n_fft);
513 
514  if (in->format == AV_SAMPLE_FMT_FLT) {
515  for (j = 0; j < in->nb_samples; j++) {
516  /* prepare input for FFT */
517  /* write all samples of current input channel to FFT input array */
518  fft_in[j].re = src[j * in_channels + i];
519  }
520  } else {
521  for (j = 0; j < in->nb_samples; j++) {
522  /* prepare input for FFT */
523  /* write all samples of current input channel to FFT input array */
524  fft_in[j].re = src[j];
525  }
526  }
527 
528  /* transform input signal of current channel to frequency domain */
529  tx_fn(fft, fft_out, fft_in, sizeof(*fft_in));
530 
531  for (j = 0; j < n_fft; j++) {
532  const AVComplexFloat *hcomplex = hrtf_offset + j;
533  const float re = fft_out[j].re;
534  const float im = fft_out[j].im;
535 
536  /* complex multiplication of input signal and HRTFs */
537  /* output channel (real): */
538  fft_acc[j].re += re * hcomplex->re - im * hcomplex->im;
539  /* output channel (imag): */
540  fft_acc[j].im += re * hcomplex->im + im * hcomplex->re;
541  }
542  }
543 
544  /* transform output signal of current channel back to time domain */
545  itx_fn(ifft, fft_out, fft_acc, sizeof(*fft_acc));
546 
547  for (j = 0; j < in->nb_samples; j++) {
548  /* write output signal of current channel to output buffer */
549  dst[mult * j] += fft_out[j].re * fft_scale;
550  }
551 
552  for (j = 0; j < ir_samples - 1; j++) { /* overflow length is IR length - 1 */
553  /* write the rest of output signal to overflow buffer */
554  int write_pos = (wr + j) & modulo;
555 
556  *(ringbuffer + write_pos) += fft_out[in->nb_samples + j].re * fft_scale;
557  }
558 
559  /* go through all samples of current output buffer: count clippings */
560  for (i = 0; i < out->nb_samples; i++) {
561  /* clippings counter */
562  if (fabsf(dst[i * mult]) > 1) { /* if current output sample > 1 */
563  n_clippings[0]++;
564  }
565  }
566 
567  /* remember read/write position in ringbuffer for next call */
568  *write = wr;
569 
570  return 0;
571 }
572 
574 {
575  AVFilterContext *ctx = inlink->dst;
576  SOFAlizerContext *s = ctx->priv;
577  AVFilterLink *outlink = ctx->outputs[0];
578  int n_clippings[2] = { 0 };
579  ThreadData td;
580  AVFrame *out;
581 
582  out = ff_get_audio_buffer(outlink, in->nb_samples);
583  if (!out) {
584  av_frame_free(&in);
585  return AVERROR(ENOMEM);
586  }
588 
589  td.in = in; td.out = out; td.write = s->write;
590  td.delay = s->delay; td.ir = s->data_ir; td.n_clippings = n_clippings;
591  td.ringbuffer = s->ringbuffer; td.temp_src = s->temp_src;
592  td.in_fft = s->in_fft;
593  td.out_fft = s->out_fft;
594  td.temp_afft = s->temp_afft;
595 
596  if (s->type == TIME_DOMAIN) {
598  } else if (s->type == FREQUENCY_DOMAIN) {
600  }
601 
602  /* display error message if clipping occurred */
603  if (n_clippings[0] + n_clippings[1] > 0) {
604  av_log(ctx, AV_LOG_WARNING, "%d of %d samples clipped. Please reduce gain.\n",
605  n_clippings[0] + n_clippings[1], out->nb_samples * 2);
606  }
607 
608  av_frame_free(&in);
609  return ff_filter_frame(outlink, out);
610 }
611 
613 {
614  AVFilterLink *inlink = ctx->inputs[0];
615  AVFilterLink *outlink = ctx->outputs[0];
616  SOFAlizerContext *s = ctx->priv;
617  AVFrame *in;
618  int ret;
619 
621 
622  if (s->nb_samples)
623  ret = ff_inlink_consume_samples(inlink, s->nb_samples, s->nb_samples, &in);
624  else
626  if (ret < 0)
627  return ret;
628  if (ret > 0)
629  return filter_frame(inlink, in);
630 
633 
634  return FFERROR_NOT_READY;
635 }
636 
638  AVFilterFormatsConfig **cfg_in,
639  AVFilterFormatsConfig **cfg_out)
640 {
641  const SOFAlizerContext *s = ctx->priv;
643  int ret, sample_rates[] = { 48000, -1 };
644  static const enum AVSampleFormat sample_fmts[] = {
647  };
648 
650  if (ret)
651  return ret;
652 
654  if (!layouts)
655  return AVERROR(ENOMEM);
656 
658  if (ret)
659  return ret;
660 
661  layouts = NULL;
663  if (ret)
664  return ret;
665 
667  if (ret)
668  return ret;
669 
670  sample_rates[0] = s->sample_rate;
671  return ff_set_common_samplerates_from_list2(ctx, cfg_in, cfg_out, sample_rates);
672 }
673 
674 static int getfilter_float(AVFilterContext *ctx, float x, float y, float z,
675  float *left, float *right,
676  float *delay_left, float *delay_right)
677 {
678  struct SOFAlizerContext *s = ctx->priv;
679  float c[3], delays[2];
680  float *fl, *fr;
681  int nearest;
682  int *neighbors;
683  float *res;
684 
685  c[0] = x, c[1] = y, c[2] = z;
686  nearest = mysofa_lookup(s->sofa.lookup, c);
687  if (nearest < 0)
688  return AVERROR(EINVAL);
689 
690  if (s->interpolate) {
691  neighbors = mysofa_neighborhood(s->sofa.neighborhood, nearest);
692  res = mysofa_interpolate(s->sofa.hrtf, c,
693  nearest, neighbors,
694  s->sofa.fir, delays);
695  } else {
696  if (s->sofa.hrtf->DataDelay.elements > s->sofa.hrtf->R) {
697  delays[0] = s->sofa.hrtf->DataDelay.values[nearest * s->sofa.hrtf->R];
698  delays[1] = s->sofa.hrtf->DataDelay.values[nearest * s->sofa.hrtf->R + 1];
699  } else {
700  delays[0] = s->sofa.hrtf->DataDelay.values[0];
701  delays[1] = s->sofa.hrtf->DataDelay.values[1];
702  }
703  res = s->sofa.hrtf->DataIR.values + nearest * s->sofa.hrtf->N * s->sofa.hrtf->R;
704  }
705 
706  *delay_left = delays[0];
707  *delay_right = delays[1];
708 
709  fl = res;
710  fr = res + s->sofa.hrtf->N;
711 
712  memcpy(left, fl, sizeof(float) * s->sofa.hrtf->N);
713  memcpy(right, fr, sizeof(float) * s->sofa.hrtf->N);
714 
715  return 0;
716 }
717 
718 static int load_data(AVFilterContext *ctx, int azim, int elev, float radius, int sample_rate)
719 {
720  struct SOFAlizerContext *s = ctx->priv;
721  int n_samples;
722  int ir_samples;
723  int n_conv = s->n_conv; /* no. channels to convolve */
724  int n_fft;
725  float delay_l; /* broadband delay for each IR */
726  float delay_r;
727  int nb_input_channels = ctx->inputs[0]->ch_layout.nb_channels; /* no. input channels */
728  float gain_lin = expf((s->gain - 3 * nb_input_channels) / 20 * M_LN10); /* gain - 3dB/channel */
729  AVComplexFloat *data_hrtf_l = NULL;
730  AVComplexFloat *data_hrtf_r = NULL;
731  AVComplexFloat *fft_out_l = NULL;
732  AVComplexFloat *fft_out_r = NULL;
733  AVComplexFloat *fft_in_l = NULL;
734  AVComplexFloat *fft_in_r = NULL;
735  float *data_ir_l = NULL;
736  float *data_ir_r = NULL;
737  int offset = 0; /* used for faster pointer arithmetics in for-loop */
738  int i, j, azim_orig = azim, elev_orig = elev;
739  int ret = 0;
740  int n_current;
741  int n_max = 0;
742 
743  av_log(ctx, AV_LOG_DEBUG, "IR length: %d.\n", s->sofa.hrtf->N);
744  s->sofa.ir_samples = s->sofa.hrtf->N;
745  s->sofa.n_samples = 1 << (32 - ff_clz(s->sofa.ir_samples));
746 
747  n_samples = s->sofa.n_samples;
748  ir_samples = s->sofa.ir_samples;
749 
750  if (s->type == TIME_DOMAIN) {
751  s->data_ir[0] = av_calloc(n_samples, sizeof(float) * s->n_conv);
752  s->data_ir[1] = av_calloc(n_samples, sizeof(float) * s->n_conv);
753 
754  if (!s->data_ir[0] || !s->data_ir[1]) {
755  ret = AVERROR(ENOMEM);
756  goto fail;
757  }
758  }
759 
760  s->delay[0] = av_calloc(s->n_conv, sizeof(int));
761  s->delay[1] = av_calloc(s->n_conv, sizeof(int));
762 
763  if (!s->delay[0] || !s->delay[1]) {
764  ret = AVERROR(ENOMEM);
765  goto fail;
766  }
767 
768  /* get temporary IR for L and R channel */
769  data_ir_l = av_calloc(n_conv * n_samples, sizeof(*data_ir_l));
770  data_ir_r = av_calloc(n_conv * n_samples, sizeof(*data_ir_r));
771  if (!data_ir_r || !data_ir_l) {
772  ret = AVERROR(ENOMEM);
773  goto fail;
774  }
775 
776  if (s->type == TIME_DOMAIN) {
777  s->temp_src[0] = av_calloc(n_samples, sizeof(float));
778  s->temp_src[1] = av_calloc(n_samples, sizeof(float));
779  if (!s->temp_src[0] || !s->temp_src[1]) {
780  ret = AVERROR(ENOMEM);
781  goto fail;
782  }
783  }
784 
785  s->speaker_azim = av_calloc(s->n_conv, sizeof(*s->speaker_azim));
786  s->speaker_elev = av_calloc(s->n_conv, sizeof(*s->speaker_elev));
787  if (!s->speaker_azim || !s->speaker_elev) {
788  ret = AVERROR(ENOMEM);
789  goto fail;
790  }
791 
792  /* get speaker positions */
793  if ((ret = get_speaker_pos(ctx, s->speaker_azim, s->speaker_elev)) < 0) {
794  av_log(ctx, AV_LOG_ERROR, "Couldn't get speaker positions. Input channel configuration not supported.\n");
795  goto fail;
796  }
797 
798  for (i = 0; i < s->n_conv; i++) {
799  float coordinates[3];
800 
801  /* load and store IRs and corresponding delays */
802  azim = (int)(s->speaker_azim[i] + azim_orig) % 360;
803  elev = (int)(s->speaker_elev[i] + elev_orig) % 90;
804 
805  coordinates[0] = azim;
806  coordinates[1] = elev;
807  coordinates[2] = radius;
808 
809  mysofa_s2c(coordinates);
810 
811  /* get id of IR closest to desired position */
812  ret = getfilter_float(ctx, coordinates[0], coordinates[1], coordinates[2],
813  data_ir_l + n_samples * i,
814  data_ir_r + n_samples * i,
815  &delay_l, &delay_r);
816  if (ret < 0)
817  goto fail;
818 
819  s->delay[0][i] = delay_l * sample_rate;
820  s->delay[1][i] = delay_r * sample_rate;
821 
822  s->sofa.max_delay = FFMAX3(s->sofa.max_delay, s->delay[0][i], s->delay[1][i]);
823  }
824 
825  /* get size of ringbuffer (longest IR plus max. delay) */
826  /* then choose next power of 2 for performance optimization */
827  n_current = n_samples + s->sofa.max_delay;
828  /* length of longest IR plus max. delay */
829  n_max = FFMAX(n_max, n_current);
830 
831  /* buffer length is longest IR plus max. delay -> next power of 2
832  (32 - count leading zeros gives required exponent) */
833  s->buffer_length = 1 << (32 - ff_clz(n_max));
834  s->n_fft = n_fft = 1 << (32 - ff_clz(n_max + s->framesize));
835 
836  if (s->type == FREQUENCY_DOMAIN) {
837  float scale = 1.f;
838 
839  av_tx_uninit(&s->fft[0]);
840  av_tx_uninit(&s->fft[1]);
841  ret = av_tx_init(&s->fft[0], &s->tx_fn[0], AV_TX_FLOAT_FFT, 0, s->n_fft, &scale, 0);
842  if (ret < 0)
843  goto fail;
844  ret = av_tx_init(&s->fft[1], &s->tx_fn[1], AV_TX_FLOAT_FFT, 0, s->n_fft, &scale, 0);
845  if (ret < 0)
846  goto fail;
847  av_tx_uninit(&s->ifft[0]);
848  av_tx_uninit(&s->ifft[1]);
849  ret = av_tx_init(&s->ifft[0], &s->itx_fn[0], AV_TX_FLOAT_FFT, 1, s->n_fft, &scale, 0);
850  if (ret < 0)
851  goto fail;
852  ret = av_tx_init(&s->ifft[1], &s->itx_fn[1], AV_TX_FLOAT_FFT, 1, s->n_fft, &scale, 0);
853  if (ret < 0)
854  goto fail;
855  }
856 
857  if (s->type == TIME_DOMAIN) {
858  s->ringbuffer[0] = av_calloc(s->buffer_length, sizeof(float) * nb_input_channels);
859  s->ringbuffer[1] = av_calloc(s->buffer_length, sizeof(float) * nb_input_channels);
860  } else if (s->type == FREQUENCY_DOMAIN) {
861  /* get temporary HRTF memory for L and R channel */
862  data_hrtf_l = av_malloc_array(n_fft, sizeof(*data_hrtf_l) * n_conv);
863  data_hrtf_r = av_malloc_array(n_fft, sizeof(*data_hrtf_r) * n_conv);
864  if (!data_hrtf_r || !data_hrtf_l) {
865  ret = AVERROR(ENOMEM);
866  goto fail;
867  }
868 
869  s->ringbuffer[0] = av_calloc(s->buffer_length, sizeof(float));
870  s->ringbuffer[1] = av_calloc(s->buffer_length, sizeof(float));
871  s->in_fft[0] = av_malloc_array(s->n_fft, sizeof(AVComplexFloat));
872  s->in_fft[1] = av_malloc_array(s->n_fft, sizeof(AVComplexFloat));
873  s->out_fft[0] = av_malloc_array(s->n_fft, sizeof(AVComplexFloat));
874  s->out_fft[1] = av_malloc_array(s->n_fft, sizeof(AVComplexFloat));
875  s->temp_afft[0] = av_malloc_array(s->n_fft, sizeof(AVComplexFloat));
876  s->temp_afft[1] = av_malloc_array(s->n_fft, sizeof(AVComplexFloat));
877  if (!s->in_fft[0] || !s->in_fft[1] ||
878  !s->out_fft[0] || !s->out_fft[1] ||
879  !s->temp_afft[0] || !s->temp_afft[1]) {
880  ret = AVERROR(ENOMEM);
881  goto fail;
882  }
883  }
884 
885  if (!s->ringbuffer[0] || !s->ringbuffer[1]) {
886  ret = AVERROR(ENOMEM);
887  goto fail;
888  }
889 
890  if (s->type == FREQUENCY_DOMAIN) {
891  fft_out_l = av_calloc(n_fft, sizeof(*fft_out_l));
892  fft_out_r = av_calloc(n_fft, sizeof(*fft_out_r));
893  fft_in_l = av_calloc(n_fft, sizeof(*fft_in_l));
894  fft_in_r = av_calloc(n_fft, sizeof(*fft_in_r));
895  if (!fft_in_l || !fft_in_r ||
896  !fft_out_l || !fft_out_r) {
897  ret = AVERROR(ENOMEM);
898  goto fail;
899  }
900  }
901 
902  for (i = 0; i < s->n_conv; i++) {
903  float *lir, *rir;
904 
905  offset = i * n_samples; /* no. samples already written */
906 
907  lir = data_ir_l + offset;
908  rir = data_ir_r + offset;
909 
910  if (s->type == TIME_DOMAIN) {
911  for (j = 0; j < ir_samples; j++) {
912  /* load reversed IRs of the specified source position
913  * sample-by-sample for left and right ear; and apply gain */
914  s->data_ir[0][offset + j] = lir[ir_samples - 1 - j] * gain_lin;
915  s->data_ir[1][offset + j] = rir[ir_samples - 1 - j] * gain_lin;
916  }
917  } else if (s->type == FREQUENCY_DOMAIN) {
918  memset(fft_in_l, 0, n_fft * sizeof(*fft_in_l));
919  memset(fft_in_r, 0, n_fft * sizeof(*fft_in_r));
920 
921  offset = i * n_fft; /* no. samples already written */
922  for (j = 0; j < ir_samples; j++) {
923  /* load non-reversed IRs of the specified source position
924  * sample-by-sample and apply gain,
925  * L channel is loaded to real part, R channel to imag part,
926  * IRs are shifted by L and R delay */
927  fft_in_l[s->delay[0][i] + j].re = lir[j] * gain_lin;
928  fft_in_r[s->delay[1][i] + j].re = rir[j] * gain_lin;
929  }
930 
931  /* actually transform to frequency domain (IRs -> HRTFs) */
932  s->tx_fn[0](s->fft[0], fft_out_l, fft_in_l, sizeof(*fft_in_l));
933  memcpy(data_hrtf_l + offset, fft_out_l, n_fft * sizeof(*fft_out_l));
934  s->tx_fn[1](s->fft[1], fft_out_r, fft_in_r, sizeof(*fft_in_r));
935  memcpy(data_hrtf_r + offset, fft_out_r, n_fft * sizeof(*fft_out_r));
936  }
937  }
938 
939  if (s->type == FREQUENCY_DOMAIN) {
940  s->data_hrtf[0] = av_malloc_array(n_fft * s->n_conv, sizeof(AVComplexFloat));
941  s->data_hrtf[1] = av_malloc_array(n_fft * s->n_conv, sizeof(AVComplexFloat));
942  if (!s->data_hrtf[0] || !s->data_hrtf[1]) {
943  ret = AVERROR(ENOMEM);
944  goto fail;
945  }
946 
947  memcpy(s->data_hrtf[0], data_hrtf_l, /* copy HRTF data to */
948  sizeof(AVComplexFloat) * n_conv * n_fft); /* filter struct */
949  memcpy(s->data_hrtf[1], data_hrtf_r,
950  sizeof(AVComplexFloat) * n_conv * n_fft);
951  }
952 
953 fail:
954  av_freep(&data_hrtf_l); /* free temporary HRTF memory */
955  av_freep(&data_hrtf_r);
956 
957  av_freep(&data_ir_l); /* free temprary IR memory */
958  av_freep(&data_ir_r);
959 
960  av_freep(&fft_out_l); /* free temporary FFT memory */
961  av_freep(&fft_out_r);
962 
963  av_freep(&fft_in_l); /* free temporary FFT memory */
964  av_freep(&fft_in_r);
965 
966  return ret;
967 }
968 
970 {
971  SOFAlizerContext *s = ctx->priv;
972  int ret;
973 
974  if (!s->filename) {
975  av_log(ctx, AV_LOG_ERROR, "Valid SOFA filename must be set.\n");
976  return AVERROR(EINVAL);
977  }
978 
979  /* preload SOFA file, */
980  ret = preload_sofa(ctx, s->filename, &s->sample_rate);
981  if (ret) {
982  /* file loading error */
983  av_log(ctx, AV_LOG_ERROR, "Error while loading SOFA file: '%s'\n", s->filename);
984  } else { /* no file loading error, resampling not required */
985  av_log(ctx, AV_LOG_DEBUG, "File '%s' loaded.\n", s->filename);
986  }
987 
988  if (ret) {
989  av_log(ctx, AV_LOG_ERROR, "No valid SOFA file could be loaded. Please specify valid SOFA file.\n");
990  return ret;
991  }
992 
993  s->fdsp = avpriv_float_dsp_alloc(0);
994  if (!s->fdsp)
995  return AVERROR(ENOMEM);
996 
997  return 0;
998 }
999 
1001 {
1002  AVFilterContext *ctx = inlink->dst;
1003  SOFAlizerContext *s = ctx->priv;
1004  int ret;
1005 
1006  if (s->type == FREQUENCY_DOMAIN)
1007  s->nb_samples = s->framesize;
1008 
1009  /* gain -3 dB per channel */
1010  s->gain_lfe = expf((s->gain - 3 * inlink->ch_layout.nb_channels + s->lfe_gain) / 20 * M_LN10);
1011 
1012  s->n_conv = inlink->ch_layout.nb_channels;
1013 
1014  /* load IRs to data_ir[0] and data_ir[1] for required directions */
1015  if ((ret = load_data(ctx, s->rotation, s->elevation, s->radius, inlink->sample_rate)) < 0)
1016  return ret;
1017 
1018  av_log(ctx, AV_LOG_DEBUG, "Samplerate: %d Channels to convolute: %d, Length of ringbuffer: %d x %d\n",
1019  inlink->sample_rate, s->n_conv, inlink->ch_layout.nb_channels, s->buffer_length);
1020 
1021  return 0;
1022 }
1023 
1025 {
1026  SOFAlizerContext *s = ctx->priv;
1027 
1028  close_sofa(&s->sofa);
1029  av_tx_uninit(&s->ifft[0]);
1030  av_tx_uninit(&s->ifft[1]);
1031  av_tx_uninit(&s->fft[0]);
1032  av_tx_uninit(&s->fft[1]);
1033  s->ifft[0] = NULL;
1034  s->ifft[1] = NULL;
1035  s->fft[0] = NULL;
1036  s->fft[1] = NULL;
1037  av_freep(&s->delay[0]);
1038  av_freep(&s->delay[1]);
1039  av_freep(&s->data_ir[0]);
1040  av_freep(&s->data_ir[1]);
1041  av_freep(&s->ringbuffer[0]);
1042  av_freep(&s->ringbuffer[1]);
1043  av_freep(&s->speaker_azim);
1044  av_freep(&s->speaker_elev);
1045  av_freep(&s->temp_src[0]);
1046  av_freep(&s->temp_src[1]);
1047  av_freep(&s->temp_afft[0]);
1048  av_freep(&s->temp_afft[1]);
1049  av_freep(&s->in_fft[0]);
1050  av_freep(&s->in_fft[1]);
1051  av_freep(&s->out_fft[0]);
1052  av_freep(&s->out_fft[1]);
1053  av_freep(&s->data_hrtf[0]);
1054  av_freep(&s->data_hrtf[1]);
1055  av_freep(&s->fdsp);
1056 }
1057 
1058 #define OFFSET(x) offsetof(SOFAlizerContext, x)
1059 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
1060 
1061 static const AVOption sofalizer_options[] = {
1062  { "sofa", "sofa filename", OFFSET(filename), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
1063  { "gain", "set gain in dB", OFFSET(gain), AV_OPT_TYPE_FLOAT, {.dbl=0}, -20, 40, .flags = FLAGS },
1064  { "rotation", "set rotation" , OFFSET(rotation), AV_OPT_TYPE_FLOAT, {.dbl=0}, -360, 360, .flags = FLAGS },
1065  { "elevation", "set elevation", OFFSET(elevation), AV_OPT_TYPE_FLOAT, {.dbl=0}, -90, 90, .flags = FLAGS },
1066  { "radius", "set radius", OFFSET(radius), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 5, .flags = FLAGS },
1067  { "type", "set processing", OFFSET(type), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, .flags = FLAGS, .unit = "type" },
1068  { "time", "time domain", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, .flags = FLAGS, .unit = "type" },
1069  { "freq", "frequency domain", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, .flags = FLAGS, .unit = "type" },
1070  { "speakers", "set speaker custom positions", OFFSET(speakers_pos), AV_OPT_TYPE_STRING, {.str=0}, 0, 0, .flags = FLAGS },
1071  { "lfegain", "set lfe gain", OFFSET(lfe_gain), AV_OPT_TYPE_FLOAT, {.dbl=0}, -20,40, .flags = FLAGS },
1072  { "framesize", "set frame size", OFFSET(framesize), AV_OPT_TYPE_INT, {.i64=1024},1024,96000, .flags = FLAGS },
1073  { "normalize", "normalize IRs", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, .flags = FLAGS },
1074  { "interpolate","interpolate IRs from neighbors", OFFSET(interpolate),AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags = FLAGS },
1075  { "minphase", "minphase IRs", OFFSET(minphase), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags = FLAGS },
1076  { "anglestep", "set neighbor search angle step", OFFSET(anglestep), AV_OPT_TYPE_FLOAT, {.dbl=.5}, 0.01, 10, .flags = FLAGS },
1077  { "radstep", "set neighbor search radius step", OFFSET(radstep), AV_OPT_TYPE_FLOAT, {.dbl=.01}, 0.01, 1, .flags = FLAGS },
1078  { NULL }
1079 };
1080 
1081 AVFILTER_DEFINE_CLASS(sofalizer);
1082 
1083 static const AVFilterPad inputs[] = {
1084  {
1085  .name = "default",
1086  .type = AVMEDIA_TYPE_AUDIO,
1087  .config_props = config_input,
1088  },
1089 };
1090 
1092  .name = "sofalizer",
1093  .description = NULL_IF_CONFIG_SMALL("SOFAlizer (Spatially Oriented Format for Acoustics)."),
1094  .priv_size = sizeof(SOFAlizerContext),
1095  .priv_class = &sofalizer_class,
1096  .init = init,
1097  .activate = activate,
1098  .uninit = uninit,
1102  .flags = AVFILTER_FLAG_SLICE_THREADS,
1103 };
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:98
AV_SAMPLE_FMT_FLTP
@ AV_SAMPLE_FMT_FLTP
float, planar
Definition: samplefmt.h:66
AVFilterChannelLayouts
A list of supported channel layouts.
Definition: formats.h:85
SOFAlizerContext::write
int write[2]
Definition: af_sofalizer.c:82
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
TIME_DOMAIN
#define TIME_DOMAIN
Definition: af_sofalizer.c:43
SOFAlizerContext::filename
char * filename
Definition: af_sofalizer.c:66
SOFAlizerContext::nb_samples
int nb_samples
Definition: af_sofalizer.c:86
SOFAlizerContext::speakers_pos
char * speakers_pos
Definition: af_sofalizer.c:72
SOFAlizerContext::radstep
float radstep
Definition: af_sofalizer.c:109
SOFAlizerContext
Definition: af_sofalizer.c:63
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:139
SOFAlizerContext::vspkrpos
VirtualSpeaker vspkrpos[64]
Definition: af_sofalizer.c:111
out
FILE * out
Definition: movenc.c:55
parse_channel_name
static int parse_channel_name(AVFilterContext *ctx, char **arg, int *rchannel)
Definition: af_sofalizer.c:189
AV_CHANNEL_LAYOUT_STEREO
#define AV_CHANNEL_LAYOUT_STEREO
Definition: channel_layout.h:387
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1023
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:673
layouts
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:335
FFERROR_NOT_READY
return FFERROR_NOT_READY
Definition: filter_design.txt:204
AV_CHAN_WIDE_LEFT
@ AV_CHAN_WIDE_LEFT
Definition: channel_layout.h:72
AVTXContext
Definition: tx_priv.h:235
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:143
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:161
SOFAlizerContext::in_fft
AVComplexFloat * in_fft[2]
Definition: af_sofalizer.c:94
SOFAlizerContext::lfe_channel
int lfe_channel
Definition: af_sofalizer.c:75
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: filters.h:262
sample_rates
static const int sample_rates[]
Definition: dcaenc.h:34
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:380
av_channel_layout_channel_from_index
enum AVChannel av_channel_layout_channel_from_index(const AVChannelLayout *channel_layout, unsigned int idx)
Get the channel with the given index in a channel layout.
Definition: channel_layout.c:668
AVOption
AVOption.
Definition: opt.h:429
expf
#define expf(x)
Definition: libm.h:283
AVComplexFloat
Definition: tx.h:27
SOFAlizerContext::type
int type
Definition: af_sofalizer.c:103
SOFAlizerContext::anglestep
float anglestep
Definition: af_sofalizer.c:108
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:205
ThreadData::out
AVFrame * out
Definition: af_adeclick.c:526
ThreadData::in
AVFrame * in
Definition: af_adecorrelate.c:155
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:434
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:903
ThreadData::temp_src
float ** temp_src
Definition: af_headphone.c:138
SOFAlizerContext::gain_lfe
float gain_lfe
Definition: af_sofalizer.c:74
SOFAlizerContext::n_conv
int n_conv
Definition: af_sofalizer.c:77
formats.h
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:1451
AV_CHAN_SURROUND_DIRECT_LEFT
@ AV_CHAN_SURROUND_DIRECT_LEFT
Definition: channel_layout.h:74
AVComplexFloat::im
float im
Definition: tx.h:28
AV_CHAN_TOP_BACK_RIGHT
@ AV_CHAN_TOP_BACK_RIGHT
Definition: channel_layout.h:67
fail
#define fail()
Definition: checkasm.h:188
VirtualSpeaker::elev
float elev
Definition: af_sofalizer.c:60
ThreadData::ringbuffer
float ** ringbuffer
Definition: af_headphone.c:137
parse_speaker_pos
static void parse_speaker_pos(AVFilterContext *ctx)
Definition: af_sofalizer.c:218
SOFAlizerContext::sofa
MySofa sofa
Definition: af_sofalizer.c:67
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
SOFAlizerContext::sample_rate
int sample_rate
Definition: af_sofalizer.c:69
fabsf
static __device__ float fabsf(float a)
Definition: cuda_runtime.h:181
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;} } 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
AVFilterPad
A filter pad used for either input or output.
Definition: filters.h:38
MySofa::lir
float * lir
Definition: af_sofalizer.c:52
AV_CHAN_STEREO_RIGHT
@ AV_CHAN_STEREO_RIGHT
See above.
Definition: channel_layout.h:71
MySofa::n_samples
int n_samples
Definition: af_sofalizer.c:51
mult
static int16_t mult(Float11 *f1, Float11 *f2)
Definition: g726.c:60
SOFAlizerContext::interpolate
int interpolate
Definition: af_sofalizer.c:106
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:151
FREQUENCY_DOMAIN
#define FREQUENCY_DOMAIN
Definition: af_sofalizer.c:44
s
#define s(width, name)
Definition: cbs_vp9.c:198
config_input
static int config_input(AVFilterLink *inlink)
Definition: af_sofalizer.c:1000
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:178
AV_CHAN_SIDE_RIGHT
@ AV_CHAN_SIDE_RIGHT
Definition: channel_layout.h:60
get_speaker_pos
static int get_speaker_pos(AVFilterContext *ctx, float *speaker_azim, float *speaker_elev)
Definition: af_sofalizer.c:249
filters.h
AV_TX_FLOAT_FFT
@ AV_TX_FLOAT_FFT
Standard complex to complex FFT with sample data type of AVComplexFloat, AVComplexDouble or AVComplex...
Definition: tx.h:47
load_data
static int load_data(AVFilterContext *ctx, int azim, int elev, float radius, int sample_rate)
Definition: af_sofalizer.c:718
ff_set_common_samplerates_from_list2
int ff_set_common_samplerates_from_list2(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out, const int *samplerates)
Definition: formats.c:944
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:49
SOFAlizerContext::data_hrtf
AVComplexFloat * data_hrtf[2]
Definition: af_sofalizer.c:115
SOFAlizerContext::data_ir
float * data_ir[2]
Definition: af_sofalizer.c:91
init
static av_cold int init(AVFilterContext *ctx)
Definition: af_sofalizer.c:969
SOFAlizerContext::framesize
int framesize
Definition: af_sofalizer.c:104
sofalizer_fast_convolute
static int sofalizer_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: af_sofalizer.c:433
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: filters.h:263
MySofa::lookup
struct MYSOFA_LOOKUP * lookup
Definition: af_sofalizer.c:48
MySofa::ir_samples
int ir_samples
Definition: af_sofalizer.c:50
SOFAlizerContext::fdsp
AVFloatDSPContext * fdsp
Definition: af_sofalizer.c:117
arg
const char * arg
Definition: jacosubdec.c:67
if
if(ret)
Definition: filter_design.txt:179
activate
static int activate(AVFilterContext *ctx)
Definition: af_sofalizer.c:612
SOFAlizerContext::ringbuffer
float * ringbuffer[2]
Definition: af_sofalizer.c:80
av_sscanf
int av_sscanf(const char *string, const char *format,...)
See libc sscanf manual for more information.
Definition: avsscanf.c:961
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
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:1471
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:712
SOFAlizerContext::delay
int * delay[2]
Definition: af_sofalizer.c:89
SOFAlizerContext::buffer_length
int buffer_length
Definition: af_sofalizer.c:83
MySofa::rir
float * rir
Definition: af_sofalizer.c:52
AV_CHAN_TOP_BACK_CENTER
@ AV_CHAN_TOP_BACK_CENTER
Definition: channel_layout.h:66
MySofa::max_delay
int max_delay
Definition: af_sofalizer.c:54
ff_audio_default_filterpad
const AVFilterPad ff_audio_default_filterpad[1]
An AVFilterPad array whose only entry has name "default" and is of type AVMEDIA_TYPE_AUDIO.
Definition: audio.c:34
AV_CHAN_TOP_CENTER
@ AV_CHAN_TOP_CENTER
Definition: channel_layout.h:61
query_formats
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
Definition: af_sofalizer.c:637
ThreadData::in_fft
AVComplexFloat ** in_fft
Definition: af_headphone.c:140
ff_add_channel_layout
int ff_add_channel_layout(AVFilterChannelLayouts **l, const AVChannelLayout *channel_layout)
Definition: formats.c:521
filter_frame
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: af_sofalizer.c:573
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
AVFilterFormatsConfig
Lists of formats / etc.
Definition: avfilter.h:111
AV_CHAN_FRONT_RIGHT_OF_CENTER
@ AV_CHAN_FRONT_RIGHT_OF_CENTER
Definition: channel_layout.h:57
float_dsp.h
AV_CHAN_FRONT_RIGHT
@ AV_CHAN_FRONT_RIGHT
Definition: channel_layout.h:51
AV_CHAN_FRONT_CENTER
@ AV_CHAN_FRONT_CENTER
Definition: channel_layout.h:52
inputs
static const AVFilterPad inputs[]
Definition: af_sofalizer.c:1083
SOFAlizerContext::speaker_azim
float * speaker_azim
Definition: af_sofalizer.c:70
SOFAlizerContext::temp_afft
AVComplexFloat * temp_afft[2]
Definition: af_sofalizer.c:96
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:94
AVChannelLayout
An AVChannelLayout holds information about the channel layout of audio data.
Definition: channel_layout.h:311
VirtualSpeaker
Definition: af_sofalizer.c:57
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:83
SOFAlizerContext::n_fft
int n_fft
Definition: af_sofalizer.c:85
AV_SAMPLE_FMT_NONE
@ AV_SAMPLE_FMT_NONE
Definition: samplefmt.h:56
SOFAlizerContext::rotation
float rotation
Definition: af_sofalizer.c:100
AV_CHAN_LOW_FREQUENCY
@ AV_CHAN_LOW_FREQUENCY
Definition: channel_layout.h:53
AV_CHAN_BACK_RIGHT
@ AV_CHAN_BACK_RIGHT
Definition: channel_layout.h:55
AVComplexFloat::re
float re
Definition: tx.h:28
AV_CHAN_SIDE_LEFT
@ AV_CHAN_SIDE_LEFT
Definition: channel_layout.h:59
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:467
OFFSET
#define OFFSET(x)
Definition: af_sofalizer.c:1058
AV_CHAN_TOP_FRONT_RIGHT
@ AV_CHAN_TOP_FRONT_RIGHT
Definition: channel_layout.h:64
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_CHAN_FRONT_LEFT_OF_CENTER
@ AV_CHAN_FRONT_LEFT_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:612
preload_sofa
static int preload_sofa(AVFilterContext *ctx, char *filename, int *samplingrate)
Definition: af_sofalizer.c:136
SOFAlizerContext::radius
float radius
Definition: af_sofalizer.c:102
interpolate
static void interpolate(float *out, float v1, float v2, int size)
Definition: twinvq.c:85
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:295
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:191
AV_OPT_TYPE_FLOAT
@ AV_OPT_TYPE_FLOAT
Underlying C type is float.
Definition: opt.h:271
SOFAlizerContext::tx_fn
av_tx_fn tx_fn[2]
Definition: af_sofalizer.c:114
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:674
AVChannel
AVChannel
Definition: channel_layout.h:47
normalize
Definition: normalize.py:1
AVFrame::nb_samples
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:460
AV_CHAN_SURROUND_DIRECT_RIGHT
@ AV_CHAN_SURROUND_DIRECT_RIGHT
Definition: channel_layout.h:75
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
FLAGS
#define FLAGS
Definition: af_sofalizer.c:1059
AVFrame::extended_data
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:441
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:31
sofalizer_options
static const AVOption sofalizer_options[]
Definition: af_sofalizer.c:1061
AVSampleFormat
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:55
ThreadData
Used for passing data between threads.
Definition: dsddec.c:71
FILTER_QUERY_FUNC2
#define FILTER_QUERY_FUNC2(func)
Definition: filters.h:239
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
ThreadData::n_clippings
int * n_clippings
Definition: af_headphone.c:136
ThreadData::delay
int ** delay
Definition: af_sofalizer.c:323
len
int len
Definition: vorbis_enc_data.h:426
AVFilterPad::name
const char * name
Pad name.
Definition: filters.h:44
MySofa
Definition: af_sofalizer.c:46
AV_CHAN_STEREO_LEFT
@ AV_CHAN_STEREO_LEFT
Stereo downmix.
Definition: channel_layout.h:69
SOFAlizerContext::lfe_gain
float lfe_gain
Definition: af_sofalizer.c:73
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
AVFilter
Filter definition.
Definition: avfilter.h:201
SOFAlizerContext::fft
AVTXContext * fft[2]
Definition: af_sofalizer.c:113
ret
ret
Definition: filter_design.txt:187
ThreadData::write
int * write
Definition: af_headphone.c:134
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: af_sofalizer.c:1024
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
AV_CHAN_BACK_CENTER
@ AV_CHAN_BACK_CENTER
Definition: channel_layout.h:58
av_channel_from_string
enum AVChannel av_channel_from_string(const char *str)
This is the inverse function of av_channel_name().
Definition: channel_layout.c:150
ThreadData::temp_afft
AVComplexFloat ** temp_afft
Definition: af_headphone.c:141
SOFAlizerContext::out_fft
AVComplexFloat * out_fft[2]
Definition: af_sofalizer.c:95
sofalizer_convolute
static int sofalizer_convolute(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: af_sofalizer.c:333
ff_set_common_formats_from_list2
int ff_set_common_formats_from_list2(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out, const int *fmts)
Definition: formats.c:1016
channel_layout.h
AV_CHAN_LOW_FREQUENCY_2
@ AV_CHAN_LOW_FREQUENCY_2
Definition: channel_layout.h:76
AV_CHAN_TOP_BACK_LEFT
@ AV_CHAN_TOP_BACK_LEFT
Definition: channel_layout.h:65
ff_filter_execute
int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
Definition: avfilter.c:1651
SOFAlizerContext::minphase
int minphase
Definition: af_sofalizer.c:107
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:47
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition: opt.h:259
avfilter.h
VirtualSpeaker::set
uint8_t set
Definition: af_sofalizer.c:58
AV_CHAN_BACK_LEFT
@ AV_CHAN_BACK_LEFT
Definition: channel_layout.h:54
AVFilterContext
An instance of a filter.
Definition: avfilter.h:457
MySofa::neighborhood
struct MYSOFA_NEIGHBORHOOD * neighborhood
Definition: af_sofalizer.c:49
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:152
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:272
AV_CHAN_TOP_FRONT_CENTER
@ AV_CHAN_TOP_FRONT_CENTER
Definition: channel_layout.h:63
mem.h
audio.h
ff_af_sofalizer
const AVFilter ff_af_sofalizer
Definition: af_sofalizer.c:1091
AV_CHAN_WIDE_RIGHT
@ AV_CHAN_WIDE_RIGHT
Definition: channel_layout.h:73
M_LN10
#define M_LN10
Definition: mathematics.h:49
VirtualSpeaker::azim
float azim
Definition: af_sofalizer.c:59
SOFAlizerContext::speaker_elev
float * speaker_elev
Definition: af_sofalizer.c:71
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
scale
static void scale(int *out, const int *in, const int w, const int h, const int shift)
Definition: intra.c:291
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
Underlying C type is int.
Definition: opt.h:327
channel_layouts
static const uint16_t channel_layouts[7]
Definition: dca_lbr.c:112
SOFAlizerContext::ifft
AVTXContext * ifft[2]
Definition: af_sofalizer.c:113
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
avpriv_float_dsp_alloc
av_cold AVFloatDSPContext * avpriv_float_dsp_alloc(int bit_exact)
Allocate a float DSP context.
Definition: float_dsp.c:146
AV_CHAN_TOP_FRONT_LEFT
@ AV_CHAN_TOP_FRONT_LEFT
Definition: channel_layout.h:62
FFMAX3
#define FFMAX3(a, b, c)
Definition: macros.h:48
SOFAlizerContext::gain
float gain
Definition: af_sofalizer.c:99
ThreadData::ir
float ** ir
Definition: af_headphone.c:135
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
SOFAlizerContext::temp_src
float * temp_src[2]
Definition: af_sofalizer.c:93
AV_CHAN_FRONT_LEFT
@ AV_CHAN_FRONT_LEFT
Definition: channel_layout.h:50
MySofa::fir
float * fir
Definition: af_sofalizer.c:53
avstring.h
SOFAlizerContext::itx_fn
av_tx_fn itx_fn[2]
Definition: af_sofalizer.c:114
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition: opt.h:276
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition: opt.h:299
SOFAlizerContext::normalize
int normalize
Definition: af_sofalizer.c:105
AV_SAMPLE_FMT_FLT
@ AV_SAMPLE_FMT_FLT
float
Definition: samplefmt.h:60
SOFAlizerContext::elevation
float elevation
Definition: af_sofalizer.c:101
src
#define src
Definition: vp8dsp.c:248
read
static uint32_t BS_FUNC() read(BSCTX *bc, unsigned int n)
Return n bits from the buffer, n has to be in the 0-32 range.
Definition: bitstream_template.h:231
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(sofalizer)
tx.h
close_sofa
static int close_sofa(struct MySofa *sofa)
Definition: af_sofalizer.c:120
intmath.h