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