Browse code

avfilter/af_sofalizer: switch to libmysofa

Signed-off-by: Paul B Mahol <onemda@gmail.com>

Paul B Mahol authored on 2017/06/03 08:39:04
Showing 4 changed files
... ...
@@ -17,6 +17,7 @@ version <next>:
17 17
 - remove the libnut muxer/demuxer wrappers
18 18
 - remove the libschroedinger encoder/decoder wrappers
19 19
 - surround audio filter
20
+- sofalizer filter switched to libmysofa
20 21
 
21 22
 version 3.3:
22 23
 - CrystalHD decoder moved to new decode API
... ...
@@ -277,7 +277,7 @@ External library support:
277 277
   --disable-lzma           disable lzma [autodetect]
278 278
   --enable-decklink        enable Blackmagic DeckLink I/O support [no]
279 279
   --enable-mediacodec      enable Android MediaCodec support [no]
280
-  --enable-netcdf          enable NetCDF, needed for sofalizer filter [no]
280
+  --enable-libmysofa       enable libmysofa, needed for sofalizer filter [no]
281 281
   --enable-openal          enable OpenAL 1.1 capture support [no]
282 282
   --enable-opencl          enable OpenCL code
283 283
   --enable-opengl          enable OpenGL rendering [no]
... ...
@@ -1550,6 +1550,7 @@ EXTERNAL_LIBRARY_LIST="
1550 1550
     libkvazaar
1551 1551
     libmodplug
1552 1552
     libmp3lame
1553
+    libmysofa
1553 1554
     libopencv
1554 1555
     libopenh264
1555 1556
     libopenjpeg
... ...
@@ -1576,7 +1577,6 @@ EXTERNAL_LIBRARY_LIST="
1576 1576
     libzmq
1577 1577
     libzvbi
1578 1578
     mediacodec
1579
-    netcdf
1580 1579
     openal
1581 1580
     opencl
1582 1581
     opengl
... ...
@@ -3156,7 +3156,7 @@ showspectrumpic_filter_deps="avcodec"
3156 3156
 showspectrumpic_filter_select="fft"
3157 3157
 signature_filter_deps="gpl avcodec avformat"
3158 3158
 smartblur_filter_deps="gpl swscale"
3159
-sofalizer_filter_deps="netcdf avcodec"
3159
+sofalizer_filter_deps="libmysofa avcodec"
3160 3160
 sofalizer_filter_select="fft"
3161 3161
 spectrumsynth_filter_deps="avcodec"
3162 3162
 spectrumsynth_filter_select="fft"
... ...
@@ -5822,6 +5822,7 @@ enabled libmfx            && { use_pkg_config libmfx "mfx/mfxvideo.h" MFXInit ||
5822 5822
                                { require libmfx "mfx/mfxvideo.h" MFXInit -llibmfx && warn "using libmfx without pkg-config"; } }
5823 5823
 enabled libmodplug        && require_pkg_config libmodplug libmodplug/modplug.h ModPlug_Load
5824 5824
 enabled libmp3lame        && require "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame
5825
+enabled libmysofa         && require libmysofa "mysofa.h" mysofa_load -lmysofa
5825 5826
 enabled libnpp            && require libnpp npp.h nppGetLibVersion -lnppi -lnppc
5826 5827
 enabled libopencore_amrnb && require libopencore_amrnb opencore-amrnb/interf_dec.h Decoder_Interface_init -lopencore-amrnb
5827 5828
 enabled libopencore_amrwb && require libopencore_amrwb opencore-amrwb/dec_if.h D_IF_init -lopencore-amrwb
... ...
@@ -5919,7 +5920,6 @@ enabled mmal              && { check_lib mmal interface/mmal/mmal.h mmal_port_co
5919 5919
                                  check_lib mmal interface/mmal/mmal.h mmal_port_connect -lmmal_core -lmmal_util -lmmal_vc_client -lbcm_host; } ||
5920 5920
                                die "ERROR: mmal not found" &&
5921 5921
                                check_func_headers interface/mmal/mmal.h "MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS"; }
5922
-enabled netcdf            && require_pkg_config netcdf netcdf.h nc_inq_libvers
5923 5922
 enabled openal            && { { for al_extralibs in "${OPENAL_LIBS}" "-lopenal" "-lOpenAL32"; do
5924 5923
                                check_lib openal 'AL/al.h' alGetError "${al_extralibs}" && break; done } ||
5925 5924
                                die "ERROR: openal not found"; } &&
... ...
@@ -3571,7 +3571,7 @@ SOFAlizer is developed at the Acoustics Research Institute (ARI) of the
3571 3571
 Austrian Academy of Sciences.
3572 3572
 
3573 3573
 To enable compilation of this filter you need to configure FFmpeg with
3574
-@code{--enable-netcdf}.
3574
+@code{--enable-libmysofa}.
3575 3575
 
3576 3576
 The filter accepts the following options:
3577 3577
 
... ...
@@ -26,7 +26,7 @@
26 26
  *****************************************************************************/
27 27
 
28 28
 #include <math.h>
29
-#include <netcdf.h>
29
+#include <mysofa.h>
30 30
 
31 31
 #include "libavcodec/avfft.h"
32 32
 #include "libavutil/avstring.h"
... ...
@@ -41,18 +41,12 @@
41 41
 #define TIME_DOMAIN      0
42 42
 #define FREQUENCY_DOMAIN 1
43 43
 
44
-typedef struct NCSofa {  /* contains data of one SOFA file */
45
-    int ncid;            /* netCDF ID of the opened SOFA file */
44
+typedef struct MySofa {  /* contains data of one SOFA file */
45
+    struct MYSOFA_EASY *easy;
46 46
     int n_samples;       /* length of one impulse response (IR) */
47
-    int m_dim;           /* number of measurement positions */
48
-    int *data_delay;     /* broadband delay of each IR */
49
-                         /* all measurement positions for each receiver (i.e. ear): */
50
-    float *sp_a;         /* azimuth angles */
51
-    float *sp_e;         /* elevation angles */
52
-    float *sp_r;         /* radii */
53
-                         /* data at each measurement position for each receiver: */
54
-    float *data_ir;      /* IRs (time-domain) */
55
-} NCSofa;
47
+    float *lir, *rir;    /* IRs (time-domain) */
48
+    int max_delay;
49
+} MySofa;
56 50
 
57 51
 typedef struct VirtualSpeaker {
58 52
     uint8_t set;
... ...
@@ -64,7 +58,7 @@ typedef struct SOFAlizerContext {
64 64
     const AVClass *class;
65 65
 
66 66
     char *filename;             /* name of SOFA file */
67
-    NCSofa sofa;                /* contains data of the SOFA file */
67
+    MySofa sofa;                /* contains data of the SOFA file */
68 68
 
69 69
     int sample_rate;            /* sample rate from SOFA file */
70 70
     float *speaker_azim;        /* azimuth of the virtual loudspeakers */
... ...
@@ -107,271 +101,33 @@ typedef struct SOFAlizerContext {
107 107
     AVFloatDSPContext *fdsp;
108 108
 } SOFAlizerContext;
109 109
 
110
-static int close_sofa(struct NCSofa *sofa)
110
+static int close_sofa(struct MySofa *sofa)
111 111
 {
112
-    av_freep(&sofa->data_delay);
113
-    av_freep(&sofa->sp_a);
114
-    av_freep(&sofa->sp_e);
115
-    av_freep(&sofa->sp_r);
116
-    av_freep(&sofa->data_ir);
117
-    nc_close(sofa->ncid);
118
-    sofa->ncid = 0;
112
+    mysofa_close(sofa->easy);
113
+    sofa->easy = NULL;
119 114
 
120 115
     return 0;
121 116
 }
122 117
 
123
-static int load_sofa(AVFilterContext *ctx, char *filename, int *samplingrate)
118
+static int preload_sofa(AVFilterContext *ctx, char *filename, int *samplingrate)
124 119
 {
125 120
     struct SOFAlizerContext *s = ctx->priv;
126
-    /* variables associated with content of SOFA file: */
127
-    int ncid, n_dims, n_vars, n_gatts, n_unlim_dim_id, status;
128
-    char data_delay_dim_name[NC_MAX_NAME];
129
-    float *sp_a, *sp_e, *sp_r, *data_ir;
130
-    char *sofa_conventions;
131
-    char dim_name[NC_MAX_NAME];   /* names of netCDF dimensions */
132
-    size_t *dim_length;           /* lengths of netCDF dimensions */
133
-    char *text;
134
-    unsigned int sample_rate;
135
-    int data_delay_dim_id[2];
136
-    int samplingrate_id;
137
-    int data_delay_id;
138
-    int n_samples;
139
-    int m_dim_id = -1;
140
-    int n_dim_id = -1;
141
-    int data_ir_id;
142
-    size_t att_len;
143
-    int m_dim;
144
-    int *data_delay;
145
-    int sp_id;
146
-    int i, ret;
147
-
148
-    s->sofa.ncid = 0;
149
-    status = nc_open(filename, NC_NOWRITE, &ncid); /* open SOFA file read-only */
150
-    if (status != NC_NOERR) {
151
-        av_log(ctx, AV_LOG_ERROR, "Can't find SOFA-file '%s'\n", filename);
152
-        return AVERROR(EINVAL);
153
-    }
154
-
155
-    /* get number of dimensions, vars, global attributes and Id of unlimited dimensions: */
156
-    nc_inq(ncid, &n_dims, &n_vars, &n_gatts, &n_unlim_dim_id);
157
-
158
-    /* -- get number of measurements ("M") and length of one IR ("N") -- */
159
-    dim_length = av_malloc_array(n_dims, sizeof(*dim_length));
160
-    if (!dim_length) {
161
-        nc_close(ncid);
162
-        return AVERROR(ENOMEM);
163
-    }
164
-
165
-    for (i = 0; i < n_dims; i++) { /* go through all dimensions of file */
166
-        nc_inq_dim(ncid, i, (char *)&dim_name, &dim_length[i]); /* get dimensions */
167
-        if (!strncmp("M", (const char *)&dim_name, 1)) /* get ID of dimension "M" */
168
-            m_dim_id = i;
169
-        if (!strncmp("N", (const char *)&dim_name, 1)) /* get ID of dimension "N" */
170
-            n_dim_id = i;
171
-    }
172
-
173
-    if ((m_dim_id == -1) || (n_dim_id == -1)) { /* dimension "M" or "N" couldn't be found */
174
-        av_log(ctx, AV_LOG_ERROR, "Can't find required dimensions in SOFA file.\n");
175
-        av_freep(&dim_length);
176
-        nc_close(ncid);
177
-        return AVERROR(EINVAL);
178
-    }
179
-
180
-    n_samples = dim_length[n_dim_id]; /* get length of one IR */
181
-    m_dim     = dim_length[m_dim_id]; /* get number of measurements */
182
-
183
-    av_freep(&dim_length);
184
-
185
-    /* -- check file type -- */
186
-    /* get length of attritube "Conventions" */
187
-    status = nc_inq_attlen(ncid, NC_GLOBAL, "Conventions", &att_len);
188
-    if (status != NC_NOERR) {
189
-        av_log(ctx, AV_LOG_ERROR, "Can't get length of attribute \"Conventions\".\n");
190
-        nc_close(ncid);
191
-        return AVERROR_INVALIDDATA;
192
-    }
193
-
194
-    /* check whether file is SOFA file */
195
-    text = av_malloc(att_len + 1);
196
-    if (!text) {
197
-        nc_close(ncid);
198
-        return AVERROR(ENOMEM);
199
-    }
121
+    struct MYSOFA_HRTF *mysofa;
122
+    int ret;
200 123
 
201
-    nc_get_att_text(ncid, NC_GLOBAL, "Conventions", text);
202
-    *(text + att_len) = 0;
203
-    if (strncmp("SOFA", text, 4)) {
204
-        av_log(ctx, AV_LOG_ERROR, "Not a SOFA file!\n");
205
-        av_freep(&text);
206
-        nc_close(ncid);
124
+    mysofa = mysofa_load(filename, &ret);
125
+    if (ret || !mysofa) {
126
+        av_log(ctx, AV_LOG_ERROR, "Can't find SOFA-file '%s'\n", filename);
207 127
         return AVERROR(EINVAL);
208 128
     }
209
-    av_freep(&text);
210
-
211
-    status = nc_inq_attlen(ncid, NC_GLOBAL, "License", &att_len);
212
-    if (status == NC_NOERR) {
213
-        text = av_malloc(att_len + 1);
214
-        if (text) {
215
-            nc_get_att_text(ncid, NC_GLOBAL, "License", text);
216
-            *(text + att_len) = 0;
217
-            av_log(ctx, AV_LOG_INFO, "SOFA file License: %s\n", text);
218
-            av_freep(&text);
219
-        }
220
-    }
221
-
222
-    status = nc_inq_attlen(ncid, NC_GLOBAL, "SourceDescription", &att_len);
223
-    if (status == NC_NOERR) {
224
-        text = av_malloc(att_len + 1);
225
-        if (text) {
226
-            nc_get_att_text(ncid, NC_GLOBAL, "SourceDescription", text);
227
-            *(text + att_len) = 0;
228
-            av_log(ctx, AV_LOG_INFO, "SOFA file SourceDescription: %s\n", text);
229
-            av_freep(&text);
230
-        }
231
-    }
232
-
233
-    status = nc_inq_attlen(ncid, NC_GLOBAL, "Comment", &att_len);
234
-    if (status == NC_NOERR) {
235
-        text = av_malloc(att_len + 1);
236
-        if (text) {
237
-            nc_get_att_text(ncid, NC_GLOBAL, "Comment", text);
238
-            *(text + att_len) = 0;
239
-            av_log(ctx, AV_LOG_INFO, "SOFA file Comment: %s\n", text);
240
-            av_freep(&text);
241
-        }
242
-    }
243
-
244
-    status = nc_inq_attlen(ncid, NC_GLOBAL, "SOFAConventions", &att_len);
245
-    if (status != NC_NOERR) {
246
-        av_log(ctx, AV_LOG_ERROR, "Can't get length of attribute \"SOFAConventions\".\n");
247
-        nc_close(ncid);
248
-        return AVERROR_INVALIDDATA;
249
-    }
250 129
 
251
-    sofa_conventions = av_malloc(att_len + 1);
252
-    if (!sofa_conventions) {
253
-        nc_close(ncid);
254
-        return AVERROR(ENOMEM);
255
-    }
256
-
257
-    nc_get_att_text(ncid, NC_GLOBAL, "SOFAConventions", sofa_conventions);
258
-    *(sofa_conventions + att_len) = 0;
259
-    if (strncmp("SimpleFreeFieldHRIR", sofa_conventions, att_len)) {
260
-        av_log(ctx, AV_LOG_ERROR, "Not a SimpleFreeFieldHRIR file!\n");
261
-        av_freep(&sofa_conventions);
262
-        nc_close(ncid);
130
+    if (mysofa->DataSamplingRate.elements != 1)
263 131
         return AVERROR(EINVAL);
264
-    }
265
-    av_freep(&sofa_conventions);
266
-
267
-    /* -- get sampling rate of HRTFs -- */
268
-    /* read ID, then value */
269
-    status  = nc_inq_varid(ncid, "Data.SamplingRate", &samplingrate_id);
270
-    status += nc_get_var_uint(ncid, samplingrate_id, &sample_rate);
271
-    if (status != NC_NOERR) {
272
-        av_log(ctx, AV_LOG_ERROR, "Couldn't read Data.SamplingRate.\n");
273
-        nc_close(ncid);
274
-        return AVERROR(EINVAL);
275
-    }
276
-    *samplingrate = sample_rate; /* remember sampling rate */
277
-
278
-    /* -- allocate memory for one value for each measurement position: -- */
279
-    sp_a = s->sofa.sp_a = av_malloc_array(m_dim, sizeof(float));
280
-    sp_e = s->sofa.sp_e = av_malloc_array(m_dim, sizeof(float));
281
-    sp_r = s->sofa.sp_r = av_malloc_array(m_dim, sizeof(float));
282
-    /* delay and IR values required for each ear and measurement position: */
283
-    data_delay = s->sofa.data_delay = av_calloc(m_dim, 2 * sizeof(int));
284
-    data_ir = s->sofa.data_ir = av_calloc(m_dim * FFALIGN(n_samples, 16), sizeof(float) * 2);
285
-
286
-    if (!data_delay || !sp_a || !sp_e || !sp_r || !data_ir) {
287
-        /* if memory could not be allocated */
288
-        close_sofa(&s->sofa);
289
-        return AVERROR(ENOMEM);
290
-    }
291
-
292
-    /* get impulse responses (HRTFs): */
293
-    /* get corresponding ID */
294
-    status = nc_inq_varid(ncid, "Data.IR", &data_ir_id);
295
-    status += nc_get_var_float(ncid, data_ir_id, data_ir); /* read and store IRs */
296
-    if (status != NC_NOERR) {
297
-        av_log(ctx, AV_LOG_ERROR, "Couldn't read Data.IR!\n");
298
-        ret = AVERROR(EINVAL);
299
-        goto error;
300
-    }
301
-
302
-    /* get source positions of the HRTFs in the SOFA file: */
303
-    status  = nc_inq_varid(ncid, "SourcePosition", &sp_id); /* get corresponding ID */
304
-    status += nc_get_vara_float(ncid, sp_id, (size_t[2]){ 0, 0 } ,
305
-                (size_t[2]){ m_dim, 1}, sp_a); /* read & store azimuth angles */
306
-    status += nc_get_vara_float(ncid, sp_id, (size_t[2]){ 0, 1 } ,
307
-                (size_t[2]){ m_dim, 1}, sp_e); /* read & store elevation angles */
308
-    status += nc_get_vara_float(ncid, sp_id, (size_t[2]){ 0, 2 } ,
309
-                (size_t[2]){ m_dim, 1}, sp_r); /* read & store radii */
310
-    if (status != NC_NOERR) { /* if any source position variable coudn't be read */
311
-        av_log(ctx, AV_LOG_ERROR, "Couldn't read SourcePosition.\n");
312
-        ret = AVERROR(EINVAL);
313
-        goto error;
314
-    }
315
-
316
-    /* read Data.Delay, check for errors and fit it to data_delay */
317
-    status  = nc_inq_varid(ncid, "Data.Delay", &data_delay_id);
318
-    status += nc_inq_vardimid(ncid, data_delay_id, &data_delay_dim_id[0]);
319
-    status += nc_inq_dimname(ncid, data_delay_dim_id[0], data_delay_dim_name);
320
-    if (status != NC_NOERR) {
321
-        av_log(ctx, AV_LOG_ERROR, "Couldn't read Data.Delay.\n");
322
-        ret = AVERROR(EINVAL);
323
-        goto error;
324
-    }
325
-
326
-    /* Data.Delay dimension check */
327
-    /* dimension of Data.Delay is [I R]: */
328
-    if (!strncmp(data_delay_dim_name, "I", 2)) {
329
-        /* check 2 characters to assure string is 0-terminated after "I" */
330
-        int delay[2]; /* delays get from SOFA file: */
331
-        int *data_delay_r;
332
-
333
-        av_log(ctx, AV_LOG_DEBUG, "Data.Delay has dimension [I R]\n");
334
-        status = nc_get_var_int(ncid, data_delay_id, &delay[0]);
335
-        if (status != NC_NOERR) {
336
-            av_log(ctx, AV_LOG_ERROR, "Couldn't read Data.Delay\n");
337
-            ret = AVERROR(EINVAL);
338
-            goto error;
339
-        }
340
-        data_delay_r = data_delay + m_dim;
341
-        for (i = 0; i < m_dim; i++) { /* extend given dimension [I R] to [M R] */
342
-            /* assign constant delay value for all measurements to data_delay fields */
343
-            data_delay[i]   = delay[0];
344
-            data_delay_r[i] = delay[1];
345
-        }
346
-        /* dimension of Data.Delay is [M R] */
347
-    } else if (!strncmp(data_delay_dim_name, "M", 2)) {
348
-        av_log(ctx, AV_LOG_ERROR, "Data.Delay in dimension [M R]\n");
349
-        /* get delays from SOFA file: */
350
-        status = nc_get_var_int(ncid, data_delay_id, data_delay);
351
-        if (status != NC_NOERR) {
352
-            av_log(ctx, AV_LOG_ERROR, "Couldn't read Data.Delay\n");
353
-            ret = AVERROR(EINVAL);
354
-            goto error;
355
-        }
356
-    } else { /* dimension of Data.Delay is neither [I R] nor [M R] */
357
-        av_log(ctx, AV_LOG_ERROR, "Data.Delay does not have the required dimensions [I R] or [M R].\n");
358
-        ret = AVERROR(EINVAL);
359
-        goto error;
360
-    }
361
-
362
-    /* save information in SOFA struct: */
363
-    s->sofa.m_dim = m_dim; /* no. measurement positions */
364
-    s->sofa.n_samples = n_samples; /* length on one IR */
365
-    s->sofa.ncid = ncid; /* netCDF ID of SOFA file */
366
-    nc_close(ncid); /* close SOFA file */
367
-
368
-    av_log(ctx, AV_LOG_DEBUG, "m_dim: %d n_samples %d\n", m_dim, n_samples);
132
+    *samplingrate = mysofa->DataSamplingRate.values[0];
133
+    s->sofa.n_samples = mysofa->N;
134
+    mysofa_free(mysofa);
369 135
 
370 136
     return 0;
371
-
372
-error:
373
-    close_sofa(&s->sofa);
374
-    return ret;
375 137
 }
376 138
 
377 139
 static int parse_channel_name(char **arg, int *rchannel, char *buf)
... ...
@@ -507,83 +263,6 @@ static int get_speaker_pos(AVFilterContext *ctx,
507 507
 
508 508
 }
509 509
 
510
-static int max_delay(struct NCSofa *sofa)
511
-{
512
-    int i, max = 0;
513
-
514
-    for (i = 0; i < sofa->m_dim * 2; i++) {
515
-        /* search maximum delay in given SOFA file */
516
-        max = FFMAX(max, sofa->data_delay[i]);
517
-    }
518
-
519
-    return max;
520
-}
521
-
522
-static int find_m(SOFAlizerContext *s, int azim, int elev, float radius)
523
-{
524
-    /* get source positions and M of currently selected SOFA file */
525
-    float *sp_a = s->sofa.sp_a; /* azimuth angle */
526
-    float *sp_e = s->sofa.sp_e; /* elevation angle */
527
-    float *sp_r = s->sofa.sp_r; /* radius */
528
-    int m_dim = s->sofa.m_dim; /* no. measurements */
529
-    int best_id = 0; /* index m currently closest to desired source pos. */
530
-    float delta = 1000; /* offset between desired and currently best pos. */
531
-    float current;
532
-    int i;
533
-
534
-    for (i = 0; i < m_dim; i++) {
535
-        /* search through all measurements in currently selected SOFA file */
536
-        /* distance of current to desired source position: */
537
-        current = fabs(sp_a[i] - azim) +
538
-                  fabs(sp_e[i] - elev) +
539
-                  fabs(sp_r[i] - radius);
540
-        if (current <= delta) {
541
-            /* if current distance is smaller than smallest distance so far */
542
-            delta = current;
543
-            best_id = i; /* remember index */
544
-        }
545
-    }
546
-
547
-    return best_id;
548
-}
549
-
550
-static int compensate_volume(AVFilterContext *ctx)
551
-{
552
-    struct SOFAlizerContext *s = ctx->priv;
553
-    float compensate;
554
-    float energy = 0;
555
-    float *ir;
556
-    int m;
557
-
558
-    if (s->sofa.ncid) {
559
-        /* find IR at front center position in the SOFA file (IR closest to 0°,0°,1m) */
560
-        struct NCSofa *sofa = &s->sofa;
561
-        m = find_m(s, 0, 0, 1);
562
-        /* get energy of that IR and compensate volume */
563
-        ir = sofa->data_ir + 2 * m * sofa->n_samples;
564
-        if (sofa->n_samples & 31) {
565
-            energy = avpriv_scalarproduct_float_c(ir, ir, sofa->n_samples);
566
-        } else {
567
-            energy = s->fdsp->scalarproduct_float(ir, ir, sofa->n_samples);
568
-        }
569
-        compensate = 256 / (sofa->n_samples * sqrt(energy));
570
-        av_log(ctx, AV_LOG_DEBUG, "Compensate-factor: %f\n", compensate);
571
-        ir = sofa->data_ir;
572
-        /* apply volume compensation to IRs */
573
-        if (sofa->n_samples & 31) {
574
-            int i;
575
-            for (i = 0; i < sofa->n_samples * sofa->m_dim * 2; i++) {
576
-                ir[i] = ir[i] * compensate;
577
-            }
578
-        } else {
579
-            s->fdsp->vector_fmul_scalar(ir, ir, compensate, sofa->n_samples * sofa->m_dim * 2);
580
-            emms_c();
581
-        }
582
-    }
583
-
584
-    return 0;
585
-}
586
-
587 510
 typedef struct ThreadData {
588 511
     AVFrame *in, *out;
589 512
     int *write;
... ...
@@ -629,10 +308,10 @@ static int sofalizer_convolute(AVFilterContext *ctx, void *arg, int jobnr, int n
629 629
     for (i = 0; i < in->nb_samples; i++) {
630 630
         const float *temp_ir = ir; /* using same set of IRs for each sample */
631 631
 
632
-        *dst = 0;
632
+        dst[0] = 0;
633 633
         for (l = 0; l < in_channels; l++) {
634 634
             /* write current input sample to ringbuffer (for each channel) */
635
-            *(buffer[l] + wr) = src[l];
635
+            buffer[l][wr] = src[l];
636 636
         }
637 637
 
638 638
         /* loop goes through all channels to be convolved */
... ...
@@ -643,31 +322,31 @@ static int sofalizer_convolute(AVFilterContext *ctx, void *arg, int jobnr, int n
643 643
                 /* LFE is an input channel but requires no convolution */
644 644
                 /* apply gain to LFE signal and add to output buffer */
645 645
                 *dst += *(buffer[s->lfe_channel] + wr) * s->gain_lfe;
646
-                temp_ir += FFALIGN(n_samples, 16);
646
+                temp_ir += FFALIGN(n_samples, 32);
647 647
                 continue;
648 648
             }
649 649
 
650 650
             /* current read position in ringbuffer: input sample write position
651 651
              * - delay for l-th ch. + diff. betw. IR length and buffer length
652 652
              * (mod buffer length) */
653
-            read = (wr - *(delay + l) - (n_samples - 1) + buffer_length) & modulo;
653
+            read = (wr - delay[l] - (n_samples - 1) + buffer_length) & modulo;
654 654
 
655 655
             if (read + n_samples < buffer_length) {
656
-                memcpy(temp_src, bptr + read, n_samples * sizeof(*temp_src));
656
+                memmove(temp_src, bptr + read, n_samples * sizeof(*temp_src));
657 657
             } else {
658 658
                 int len = FFMIN(n_samples - (read % n_samples), buffer_length - read);
659 659
 
660
-                memcpy(temp_src, bptr + read, len * sizeof(*temp_src));
661
-                memcpy(temp_src + len, bptr, (n_samples - len) * sizeof(*temp_src));
660
+                memmove(temp_src, bptr + read, len * sizeof(*temp_src));
661
+                memmove(temp_src + len, bptr, (n_samples - len) * sizeof(*temp_src));
662 662
             }
663 663
 
664 664
             /* multiply signal and IR, and add up the results */
665 665
             dst[0] += s->fdsp->scalarproduct_float(temp_ir, temp_src, n_samples);
666
-            temp_ir += FFALIGN(n_samples, 16);
666
+            temp_ir += FFALIGN(n_samples, 32);
667 667
         }
668 668
 
669 669
         /* clippings counter */
670
-        if (fabs(*dst) > 1)
670
+        if (fabs(dst[0]) > 1)
671 671
             *n_clippings += 1;
672 672
 
673 673
         /* move output buffer pointer by +2 to get to next sample of processed channel: */
... ...
@@ -875,14 +554,14 @@ static int query_formats(AVFilterContext *ctx)
875 875
     return ff_set_common_samplerates(ctx, formats);
876 876
 }
877 877
 
878
-static int load_data(AVFilterContext *ctx, int azim, int elev, float radius)
878
+static int load_data(AVFilterContext *ctx, int azim, int elev, float radius, int sample_rate)
879 879
 {
880 880
     struct SOFAlizerContext *s = ctx->priv;
881
-    const int n_samples = s->sofa.n_samples;
881
+    int n_samples;
882 882
     int n_conv = s->n_conv; /* no. channels to convolve */
883
-    int n_fft = s->n_fft;
884
-    int delay_l[16]; /* broadband delay for each IR */
885
-    int delay_r[16];
883
+    int n_fft;
884
+    float delay_l; /* broadband delay for each IR */
885
+    float delay_r;
886 886
     int nb_input_channels = ctx->inputs[0]->channels; /* no. input channels */
887 887
     float gain_lin = expf((s->gain - 3 * nb_input_channels) / 20 * M_LN10); /* gain - 3dB/channel */
888 888
     FFTComplex *data_hrtf_l = NULL;
... ...
@@ -892,68 +571,166 @@ static int load_data(AVFilterContext *ctx, int azim, int elev, float radius)
892 892
     float *data_ir_l = NULL;
893 893
     float *data_ir_r = NULL;
894 894
     int offset = 0; /* used for faster pointer arithmetics in for-loop */
895
-    int m[16]; /* measurement index m of IR closest to required source positions */
896 895
     int i, j, azim_orig = azim, elev_orig = elev;
896
+    int filter_length, ret = 0;
897
+    int n_current;
898
+    int n_max = 0;
897 899
 
898
-    if (!s->sofa.ncid) { /* if an invalid SOFA file has been selected */
900
+    s->sofa.easy = mysofa_open(s->filename, sample_rate, &filter_length, &ret);
901
+    if (!s->sofa.easy || ret) { /* if an invalid SOFA file has been selected */
899 902
         av_log(ctx, AV_LOG_ERROR, "Selected SOFA file is invalid. Please select valid SOFA file.\n");
900 903
         return AVERROR_INVALIDDATA;
901 904
     }
902 905
 
906
+    n_samples = s->sofa.n_samples;
907
+
908
+    s->data_ir[0] = av_calloc(FFALIGN(n_samples, 32), sizeof(float) * s->n_conv);
909
+    s->data_ir[1] = av_calloc(FFALIGN(n_samples, 32), sizeof(float) * s->n_conv);
910
+    s->delay[0] = av_calloc(s->n_conv, sizeof(int));
911
+    s->delay[1] = av_calloc(s->n_conv, sizeof(int));
912
+
913
+    if (!s->data_ir[0] || !s->data_ir[1] || !s->delay[0] || !s->delay[1]) {
914
+        ret = AVERROR(ENOMEM);
915
+        goto fail;
916
+    }
917
+
918
+    /* get temporary IR for L and R channel */
919
+    data_ir_l = av_calloc(n_conv * FFALIGN(n_samples, 32), sizeof(*data_ir_l));
920
+    data_ir_r = av_calloc(n_conv * FFALIGN(n_samples, 32), sizeof(*data_ir_r));
921
+    if (!data_ir_r || !data_ir_l) {
922
+        ret = AVERROR(ENOMEM);
923
+        goto fail;
924
+    }
925
+
903 926
     if (s->type == TIME_DOMAIN) {
904
-        s->temp_src[0] = av_calloc(FFALIGN(n_samples, 16), sizeof(float));
905
-        s->temp_src[1] = av_calloc(FFALIGN(n_samples, 16), sizeof(float));
906
-
907
-        /* get temporary IR for L and R channel */
908
-        data_ir_l = av_calloc(n_conv * FFALIGN(n_samples, 16), sizeof(*data_ir_l));
909
-        data_ir_r = av_calloc(n_conv * FFALIGN(n_samples, 16), sizeof(*data_ir_r));
910
-        if (!data_ir_r || !data_ir_l || !s->temp_src[0] || !s->temp_src[1]) {
911
-            av_free(data_ir_l);
912
-            av_free(data_ir_r);
913
-            return AVERROR(ENOMEM);
927
+        s->temp_src[0] = av_calloc(FFALIGN(n_samples, 32), sizeof(float));
928
+        s->temp_src[1] = av_calloc(FFALIGN(n_samples, 32), sizeof(float));
929
+        if (!s->temp_src[0] || !s->temp_src[1]) {
930
+            ret = AVERROR(ENOMEM);
931
+            goto fail;
932
+        }
933
+    }
934
+
935
+    s->speaker_azim = av_calloc(s->n_conv, sizeof(*s->speaker_azim));
936
+    s->speaker_elev = av_calloc(s->n_conv, sizeof(*s->speaker_elev));
937
+    if (!s->speaker_azim || !s->speaker_elev) {
938
+        ret = AVERROR(ENOMEM);
939
+        goto fail;
940
+    }
941
+
942
+    /* get speaker positions */
943
+    if ((ret = get_speaker_pos(ctx, s->speaker_azim, s->speaker_elev)) < 0) {
944
+        av_log(ctx, AV_LOG_ERROR, "Couldn't get speaker positions. Input channel configuration not supported.\n");
945
+        goto fail;
946
+    }
947
+
948
+    for (i = 0; i < s->n_conv; i++) {
949
+        float coordinates[3];
950
+
951
+        /* load and store IRs and corresponding delays */
952
+        azim = (int)(s->speaker_azim[i] + azim_orig) % 360;
953
+        elev = (int)(s->speaker_elev[i] + elev_orig) % 90;
954
+
955
+        coordinates[0] = azim;
956
+        coordinates[1] = elev;
957
+        coordinates[2] = radius;
958
+
959
+        mysofa_s2c(coordinates);
960
+
961
+        /* get id of IR closest to desired position */
962
+        mysofa_getfilter_float(s->sofa.easy, coordinates[0], coordinates[1], coordinates[2],
963
+                               data_ir_l + FFALIGN(n_samples, 32) * i,
964
+                               data_ir_r + FFALIGN(n_samples, 32) * i,
965
+                               &delay_l, &delay_r);
966
+
967
+        s->delay[0][i] = delay_l * sample_rate;
968
+        s->delay[1][i] = delay_r * sample_rate;
969
+
970
+        s->sofa.max_delay = FFMAX3(s->sofa.max_delay, s->delay[0][i], s->delay[1][i]);
971
+    }
972
+
973
+    /* get size of ringbuffer (longest IR plus max. delay) */
974
+    /* then choose next power of 2 for performance optimization */
975
+    n_current = s->sofa.n_samples + s->sofa.max_delay;
976
+    /* length of longest IR plus max. delay */
977
+    n_max = FFMAX(n_max, n_current);
978
+
979
+    /* buffer length is longest IR plus max. delay -> next power of 2
980
+       (32 - count leading zeros gives required exponent)  */
981
+    s->buffer_length = 1 << (32 - ff_clz(n_max));
982
+    s->n_fft = n_fft = 1 << (32 - ff_clz(n_max + sample_rate));
983
+
984
+    if (s->type == FREQUENCY_DOMAIN) {
985
+        av_fft_end(s->fft[0]);
986
+        av_fft_end(s->fft[1]);
987
+        s->fft[0] = av_fft_init(log2(s->n_fft), 0);
988
+        s->fft[1] = av_fft_init(log2(s->n_fft), 0);
989
+        av_fft_end(s->ifft[0]);
990
+        av_fft_end(s->ifft[1]);
991
+        s->ifft[0] = av_fft_init(log2(s->n_fft), 1);
992
+        s->ifft[1] = av_fft_init(log2(s->n_fft), 1);
993
+
994
+        if (!s->fft[0] || !s->fft[1] || !s->ifft[0] || !s->ifft[1]) {
995
+            av_log(ctx, AV_LOG_ERROR, "Unable to create FFT contexts of size %d.\n", s->n_fft);
996
+            ret = AVERROR(ENOMEM);
997
+            goto fail;
914 998
         }
999
+    }
1000
+
1001
+    if (s->type == TIME_DOMAIN) {
1002
+        s->ringbuffer[0] = av_calloc(s->buffer_length, sizeof(float) * nb_input_channels);
1003
+        s->ringbuffer[1] = av_calloc(s->buffer_length, sizeof(float) * nb_input_channels);
915 1004
     } else {
916 1005
         /* get temporary HRTF memory for L and R channel */
917 1006
         data_hrtf_l = av_malloc_array(n_fft, sizeof(*data_hrtf_l) * n_conv);
918 1007
         data_hrtf_r = av_malloc_array(n_fft, sizeof(*data_hrtf_r) * n_conv);
919 1008
         if (!data_hrtf_r || !data_hrtf_l) {
920
-            av_free(data_hrtf_l);
921
-            av_free(data_hrtf_r);
922
-            return AVERROR(ENOMEM);
1009
+            ret = AVERROR(ENOMEM);
1010
+            goto fail;
1011
+        }
1012
+
1013
+        s->ringbuffer[0] = av_calloc(s->buffer_length, sizeof(float));
1014
+        s->ringbuffer[1] = av_calloc(s->buffer_length, sizeof(float));
1015
+        s->temp_fft[0] = av_malloc_array(s->n_fft, sizeof(FFTComplex));
1016
+        s->temp_fft[1] = av_malloc_array(s->n_fft, sizeof(FFTComplex));
1017
+        if (!s->temp_fft[0] || !s->temp_fft[1]) {
1018
+            ret = AVERROR(ENOMEM);
1019
+            goto fail;
1020
+        }
1021
+    }
1022
+
1023
+    if (!s->ringbuffer[0] || !s->ringbuffer[1]) {
1024
+        ret = AVERROR(ENOMEM);
1025
+        goto fail;
1026
+    }
1027
+
1028
+    if (s->type == FREQUENCY_DOMAIN) {
1029
+        fft_in_l = av_calloc(n_fft, sizeof(*fft_in_l));
1030
+        fft_in_r = av_calloc(n_fft, sizeof(*fft_in_r));
1031
+        if (!fft_in_l || !fft_in_r) {
1032
+            ret = AVERROR(ENOMEM);
1033
+            goto fail;
923 1034
         }
924 1035
     }
925 1036
 
926 1037
     for (i = 0; i < s->n_conv; i++) {
927
-        /* load and store IRs and corresponding delays */
928
-        azim = (int)(s->speaker_azim[i] + azim_orig) % 360;
929
-        elev = (int)(s->speaker_elev[i] + elev_orig) % 90;
930
-        /* get id of IR closest to desired position */
931
-        m[i] = find_m(s, azim, elev, radius);
1038
+        float *lir, *rir;
932 1039
 
933
-        /* load the delays associated with the current IRs */
934
-        delay_l[i] = *(s->sofa.data_delay + 2 * m[i]);
935
-        delay_r[i] = *(s->sofa.data_delay + 2 * m[i] + 1);
1040
+        offset = i * FFALIGN(n_samples, 32); /* no. samples already written */
1041
+
1042
+        lir = data_ir_l + offset;
1043
+        rir = data_ir_r + offset;
936 1044
 
937 1045
         if (s->type == TIME_DOMAIN) {
938
-            offset = i * FFALIGN(n_samples, 16); /* no. samples already written */
939 1046
             for (j = 0; j < n_samples; j++) {
940 1047
                 /* load reversed IRs of the specified source position
941 1048
                  * sample-by-sample for left and right ear; and apply gain */
942
-                *(data_ir_l + offset + j) = /* left channel */
943
-                *(s->sofa.data_ir + 2 * m[i] * n_samples + n_samples - 1 - j) * gain_lin;
944
-                *(data_ir_r + offset + j) = /* right channel */
945
-                *(s->sofa.data_ir + 2 * m[i] * n_samples + n_samples - 1 - j  + n_samples) * gain_lin;
1049
+                s->data_ir[0][offset + j] = lir[n_samples - 1 - j] * gain_lin;
1050
+                s->data_ir[1][offset + j] = rir[n_samples - 1 - j] * gain_lin;
946 1051
             }
947 1052
         } else {
948
-            fft_in_l = av_calloc(n_fft, sizeof(*fft_in_l));
949
-            fft_in_r = av_calloc(n_fft, sizeof(*fft_in_r));
950
-            if (!fft_in_l || !fft_in_r) {
951
-                av_free(data_hrtf_l);
952
-                av_free(data_hrtf_r);
953
-                av_free(fft_in_l);
954
-                av_free(fft_in_r);
955
-                return AVERROR(ENOMEM);
956
-            }
1053
+            memset(fft_in_l, 0, n_fft * sizeof(*fft_in_l));
1054
+            memset(fft_in_r, 0, n_fft * sizeof(*fft_in_r));
957 1055
 
958 1056
             offset = i * n_fft; /* no. samples already written */
959 1057
             for (j = 0; j < n_samples; j++) {
... ...
@@ -961,10 +738,8 @@ static int load_data(AVFilterContext *ctx, int azim, int elev, float radius)
961 961
                  * sample-by-sample and apply gain,
962 962
                  * L channel is loaded to real part, R channel to imag part,
963 963
                  * IRs ared shifted by L and R delay */
964
-                fft_in_l[delay_l[i] + j].re = /* left channel */
965
-                *(s->sofa.data_ir + 2 * m[i] * n_samples + j) * gain_lin;
966
-                fft_in_r[delay_r[i] + j].re = /* right channel */
967
-                *(s->sofa.data_ir + (2 * m[i] + 1) * n_samples + j) * gain_lin;
964
+                fft_in_l[s->delay[0][i] + j].re = lir[j] * gain_lin;
965
+                fft_in_r[s->delay[1][i] + j].re = rir[j] * gain_lin;
968 966
             }
969 967
 
970 968
             /* actually transform to frequency domain (IRs -> HRTFs) */
... ...
@@ -975,45 +750,33 @@ static int load_data(AVFilterContext *ctx, int azim, int elev, float radius)
975 975
             av_fft_calc(s->fft[0], fft_in_r);
976 976
             memcpy(data_hrtf_r + offset, fft_in_r, n_fft * sizeof(*fft_in_r));
977 977
         }
978
-
979
-        av_log(ctx, AV_LOG_DEBUG, "Index: %d, Azimuth: %f, Elevation: %f, Radius: %f of SOFA file.\n",
980
-               m[i], *(s->sofa.sp_a + m[i]), *(s->sofa.sp_e + m[i]), *(s->sofa.sp_r + m[i]));
981 978
     }
982 979
 
983
-    if (s->type == TIME_DOMAIN) {
984
-        /* copy IRs and delays to allocated memory in the SOFAlizerContext struct: */
985
-        memcpy(s->data_ir[0], data_ir_l, sizeof(float) * n_conv * FFALIGN(n_samples, 16));
986
-        memcpy(s->data_ir[1], data_ir_r, sizeof(float) * n_conv * FFALIGN(n_samples, 16));
987
-
988
-        av_freep(&data_ir_l); /* free temporary IR memory */
989
-        av_freep(&data_ir_r);
990
-    } else {
980
+    if (s->type == FREQUENCY_DOMAIN) {
991 981
         s->data_hrtf[0] = av_malloc_array(n_fft * s->n_conv, sizeof(FFTComplex));
992 982
         s->data_hrtf[1] = av_malloc_array(n_fft * s->n_conv, sizeof(FFTComplex));
993 983
         if (!s->data_hrtf[0] || !s->data_hrtf[1]) {
994
-            av_freep(&data_hrtf_l);
995
-            av_freep(&data_hrtf_r);
996
-            av_freep(&fft_in_l);
997
-            av_freep(&fft_in_r);
998
-            return AVERROR(ENOMEM); /* memory allocation failed */
984
+            ret = AVERROR(ENOMEM);
985
+            goto fail;
999 986
         }
1000 987
 
1001 988
         memcpy(s->data_hrtf[0], data_hrtf_l, /* copy HRTF data to */
1002 989
             sizeof(FFTComplex) * n_conv * n_fft); /* filter struct */
1003 990
         memcpy(s->data_hrtf[1], data_hrtf_r,
1004 991
             sizeof(FFTComplex) * n_conv * n_fft);
992
+    }
1005 993
 
1006
-        av_freep(&data_hrtf_l); /* free temporary HRTF memory */
1007
-        av_freep(&data_hrtf_r);
994
+fail:
995
+    av_freep(&data_hrtf_l); /* free temporary HRTF memory */
996
+    av_freep(&data_hrtf_r);
1008 997
 
1009
-        av_freep(&fft_in_l); /* free temporary FFT memory */
1010
-        av_freep(&fft_in_r);
1011
-    }
998
+    av_freep(&data_ir_l); /* free temprary IR memory */
999
+    av_freep(&data_ir_r);
1012 1000
 
1013
-    memcpy(s->delay[0], &delay_l[0], sizeof(int) * s->n_conv);
1014
-    memcpy(s->delay[1], &delay_r[0], sizeof(int) * s->n_conv);
1001
+    av_freep(&fft_in_l); /* free temporary FFT memory */
1002
+    av_freep(&fft_in_r);
1015 1003
 
1016
-    return 0;
1004
+    return ret;
1017 1005
 }
1018 1006
 
1019 1007
 static av_cold int init(AVFilterContext *ctx)
... ...
@@ -1026,12 +789,8 @@ static av_cold int init(AVFilterContext *ctx)
1026 1026
         return AVERROR(EINVAL);
1027 1027
     }
1028 1028
 
1029
-    /* load SOFA file, */
1030
-    /* initialize file IDs to 0 before attempting to load SOFA files,
1031
-     * this assures that in case of error, only the memory of already
1032
-     * loaded files is free'd */
1033
-    s->sofa.ncid = 0;
1034
-    ret = load_sofa(ctx, s->filename, &s->sample_rate);
1029
+    /* preload SOFA file, */
1030
+    ret = preload_sofa(ctx, s->filename, &s->sample_rate);
1035 1031
     if (ret) {
1036 1032
         /* file loading error */
1037 1033
         av_log(ctx, AV_LOG_ERROR, "Error while loading SOFA file: '%s'\n", s->filename);
... ...
@@ -1055,10 +814,6 @@ static int config_input(AVFilterLink *inlink)
1055 1055
 {
1056 1056
     AVFilterContext *ctx = inlink->dst;
1057 1057
     SOFAlizerContext *s = ctx->priv;
1058
-    int nb_input_channels = inlink->channels; /* no. input channels */
1059
-    int n_max_ir = 0;
1060
-    int n_current;
1061
-    int n_max = 0;
1062 1058
     int ret;
1063 1059
 
1064 1060
     if (s->type == FREQUENCY_DOMAIN) {
... ...
@@ -1070,85 +825,14 @@ static int config_input(AVFilterLink *inlink)
1070 1070
     /* gain -3 dB per channel, -6 dB to get LFE on a similar level */
1071 1071
     s->gain_lfe = expf((s->gain - 3 * inlink->channels - 6 + s->lfe_gain) / 20 * M_LN10);
1072 1072
 
1073
-    s->n_conv = nb_input_channels;
1074
-
1075
-    /* get size of ringbuffer (longest IR plus max. delay) */
1076
-    /* then choose next power of 2 for performance optimization */
1077
-    n_current = s->sofa.n_samples + max_delay(&s->sofa);
1078
-    if (n_current > n_max) {
1079
-        /* length of longest IR plus max. delay (in all SOFA files) */
1080
-        n_max = n_current;
1081
-        /* length of longest IR (without delay, in all SOFA files) */
1082
-        n_max_ir = s->sofa.n_samples;
1083
-    }
1084
-    /* buffer length is longest IR plus max. delay -> next power of 2
1085
-       (32 - count leading zeros gives required exponent)  */
1086
-    s->buffer_length = 1 << (32 - ff_clz(n_max));
1087
-    s->n_fft         = 1 << (32 - ff_clz(n_max + inlink->sample_rate));
1088
-
1089
-    if (s->type == FREQUENCY_DOMAIN) {
1090
-        av_fft_end(s->fft[0]);
1091
-        av_fft_end(s->fft[1]);
1092
-        s->fft[0] = av_fft_init(log2(s->n_fft), 0);
1093
-        s->fft[1] = av_fft_init(log2(s->n_fft), 0);
1094
-        av_fft_end(s->ifft[0]);
1095
-        av_fft_end(s->ifft[1]);
1096
-        s->ifft[0] = av_fft_init(log2(s->n_fft), 1);
1097
-        s->ifft[1] = av_fft_init(log2(s->n_fft), 1);
1098
-
1099
-        if (!s->fft[0] || !s->fft[1] || !s->ifft[0] || !s->ifft[1]) {
1100
-            av_log(ctx, AV_LOG_ERROR, "Unable to create FFT contexts of size %d.\n", s->n_fft);
1101
-            return AVERROR(ENOMEM);
1102
-        }
1103
-    }
1104
-
1105
-    /* Allocate memory for the impulse responses, delays and the ringbuffers */
1106
-    /* size: (longest IR) * (number of channels to convolute) */
1107
-    s->data_ir[0] = av_calloc(FFALIGN(n_max_ir, 16), sizeof(float) * s->n_conv);
1108
-    s->data_ir[1] = av_calloc(FFALIGN(n_max_ir, 16), sizeof(float) * s->n_conv);
1109
-    /* length:  number of channels to convolute */
1110
-    s->delay[0] = av_malloc_array(s->n_conv, sizeof(float));
1111
-    s->delay[1] = av_malloc_array(s->n_conv, sizeof(float));
1112
-    /* length: (buffer length) * (number of input channels),
1113
-     * OR: buffer length (if frequency domain processing)
1114
-     * calloc zero-initializes the buffer */
1115
-
1116
-    if (s->type == TIME_DOMAIN) {
1117
-        s->ringbuffer[0] = av_calloc(s->buffer_length, sizeof(float) * nb_input_channels);
1118
-        s->ringbuffer[1] = av_calloc(s->buffer_length, sizeof(float) * nb_input_channels);
1119
-    } else {
1120
-        s->ringbuffer[0] = av_calloc(s->buffer_length, sizeof(float));
1121
-        s->ringbuffer[1] = av_calloc(s->buffer_length, sizeof(float));
1122
-        s->temp_fft[0] = av_malloc_array(s->n_fft, sizeof(FFTComplex));
1123
-        s->temp_fft[1] = av_malloc_array(s->n_fft, sizeof(FFTComplex));
1124
-        if (!s->temp_fft[0] || !s->temp_fft[1])
1125
-            return AVERROR(ENOMEM);
1126
-    }
1127
-
1128
-    /* length: number of channels to convolute */
1129
-    s->speaker_azim = av_calloc(s->n_conv, sizeof(*s->speaker_azim));
1130
-    s->speaker_elev = av_calloc(s->n_conv, sizeof(*s->speaker_elev));
1131
-
1132
-    /* memory allocation failed: */
1133
-    if (!s->data_ir[0] || !s->data_ir[1] || !s->delay[1] ||
1134
-        !s->delay[0] || !s->ringbuffer[0] || !s->ringbuffer[1] ||
1135
-        !s->speaker_azim || !s->speaker_elev)
1136
-        return AVERROR(ENOMEM);
1137
-
1138
-    compensate_volume(ctx);
1139
-
1140
-    /* get speaker positions */
1141
-    if ((ret = get_speaker_pos(ctx, s->speaker_azim, s->speaker_elev)) < 0) {
1142
-        av_log(ctx, AV_LOG_ERROR, "Couldn't get speaker positions. Input channel configuration not supported.\n");
1143
-        return ret;
1144
-    }
1073
+    s->n_conv = inlink->channels;
1145 1074
 
1146 1075
     /* load IRs to data_ir[0] and data_ir[1] for required directions */
1147
-    if ((ret = load_data(ctx, s->rotation, s->elevation, s->radius)) < 0)
1076
+    if ((ret = load_data(ctx, s->rotation, s->elevation, s->radius, inlink->sample_rate)) < 0)
1148 1077
         return ret;
1149 1078
 
1150 1079
     av_log(ctx, AV_LOG_DEBUG, "Samplerate: %d Channels to convolute: %d, Length of ringbuffer: %d x %d\n",
1151
-        inlink->sample_rate, s->n_conv, nb_input_channels, s->buffer_length);
1080
+        inlink->sample_rate, s->n_conv, inlink->channels, s->buffer_length);
1152 1081
 
1153 1082
     return 0;
1154 1083
 }
... ...
@@ -1157,13 +841,7 @@ static av_cold void uninit(AVFilterContext *ctx)
1157 1157
 {
1158 1158
     SOFAlizerContext *s = ctx->priv;
1159 1159
 
1160
-    if (s->sofa.ncid) {
1161
-        av_freep(&s->sofa.sp_a);
1162
-        av_freep(&s->sofa.sp_e);
1163
-        av_freep(&s->sofa.sp_r);
1164
-        av_freep(&s->sofa.data_delay);
1165
-        av_freep(&s->sofa.data_ir);
1166
-    }
1160
+    close_sofa(&s->sofa);
1167 1161
     av_fft_end(s->ifft[0]);
1168 1162
     av_fft_end(s->ifft[1]);
1169 1163
     av_fft_end(s->fft[0]);