SAF
Loading...
Searching...
No Matches
saf_utility_decor.c
Go to the documentation of this file.
1/*
2 * Copyright 2018 Leo McCormack
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
27#include "saf_utilities.h"
28#include "saf_externals.h"
29
32typedef struct _latticeAPF{
33 int order;
34 int filterLength;
35 float** coeffs;
36 float_complex* buffer;
37
39
42typedef struct _latticeDecor_data{
43 int nCH;
44 int nCutoffs;
45 int nBands;
46 int maxBufferLen;
47 int* orders;
48 int* TF_delays;
49 latticeAPF** lttc_apf;
50 float enComp_coeff;
51
52 /* run-time */
53 float** in_energy;
54 float** decor_energy;
55 float_complex*** delayBuffers;
56 int* wIdx;
57 int* rIdx;
58
60
63typedef struct _transientDucker_data{
64 int nCH;
65 int nBands;
66 float** transientDetector1;
67 float** transientDetector2;
68
70
72(
73 int nChannels, /* number of channels */
74 float* freqs, /* centre frequencies */
75 int nFreqs, /* number of elements in frequency vector */
76 float fs, /* host fs */
77 int maxTFdelay, /* max number of time-slots to delay */
78 int hopSize, /* STFT hop size */
79 int* delayTF /* nFreq x nChannels */
80)
81{
82 int band, ch;
83 int* randperm_nCH;
84 float maxMilliseconds, nChannelsf;
85 float* delayRangeMax, *delayRangeMin, *tmp_delays, *delays;
86
87 nChannelsf = (float)nChannels;
88 randperm_nCH = malloc1d(nChannels*sizeof(int));
89 delayRangeMax = malloc1d(nFreqs*sizeof(float));
90 delayRangeMin = malloc1d(nFreqs*sizeof(float));
91 tmp_delays = malloc1d(nChannels*sizeof(float));
92 delays = malloc1d(nFreqs*nChannels*sizeof(float));
93 maxMilliseconds = SAF_MIN(80.0f, (maxTFdelay-1.0f)*(float)hopSize/fs*1000.0f);
94 for(band=0; band<nFreqs; band++){
95 delayRangeMax[band] = SAF_MAX(7.0f, SAF_MIN(maxMilliseconds, 50.0f*1000.0f/(freqs[band]+2.23e-9f)));
96 delayRangeMin[band] = SAF_MAX(3.0f, SAF_MIN(20.0f, 10.0f*1000.0f/(freqs[band]+2.23e-9f)));
97 }
98 for(band=0; band<nFreqs; band++)
99 for(ch=0; ch<nChannels; ch++)
100 delays[band*nChannels+ch] = (float)ch/nChannelsf + ((float)rand()/(float)RAND_MAX)/nChannelsf;
101 for(band=0; band<nFreqs; band++){
102 randperm(nChannels, randperm_nCH);
103 memcpy(tmp_delays, &delays[band*nChannels], nChannels*sizeof(float));
104 for(ch=0; ch<nChannels; ch++)
105 delays[band*nChannels+ch] = tmp_delays[randperm_nCH[ch]];
106 }
107 for(band=0; band<nFreqs; band++){
108 for(ch=0; ch<nChannels; ch++){
109 delays[band*nChannels+ch] = delays[band*nChannels+ch]*(delayRangeMax[band]-delayRangeMin[band])+delayRangeMin[band];
110 delayTF[band*nChannels+ch] = SAF_MAX((int)(delays[band*nChannels+ch]/1000.0f*fs/(float)hopSize + 0.5f)-1,0);
111 }
112 }
113
114 free(randperm_nCH);
115 free(delayRangeMax);
116 free(delayRangeMin);
117 free(tmp_delays);
118 free(delays);
119}
120
122(
123 int nCH,
124 float fs,
125 float* t60,
126 float* fcen_oct,
127 int nBands,
128 int flattenFLAG,
129 float** rir_filt,
130 int* rir_len
131)
132{
133 int i, j, k, rir_filt_len, rir_filt_lout, filterOrder;
134 float alpha, max_t60, t;
135 float *rir, *fcut, *h_filt, *rir_filt_tmp;
136
137 filterOrder = 800;
138
139 /* find rir length */
140 max_t60 = 0.0f;
141 for(i=0; i<nBands; i++)
142 max_t60 = max_t60 < t60[i] ? t60[i] : max_t60;
143 rir_filt_len = (int)(max_t60*fs+0.5f); /* length of RIRs */
144 rir_filt_lout = rir_filt_len + filterOrder/2; /* truncated output length */
145
146 /* Generate noise and shape with exponentially decaying envelopes */
147 rir = calloc1d(nCH*nBands*rir_filt_lout, sizeof(float));
148 for(i=0; i<nCH; i++){
149 for(j=0; j<nBands; j++){
150 /* decay constants for t60 */
151 alpha = 3.0f*logf(10.0f)/t60[j];
152 for(k=0, t=0.0f; k<rir_filt_len; k++, t+=1.0f/fs)
153 rir[i*nBands*rir_filt_lout + j*rir_filt_lout + k] = expf(-t*alpha) * /* envelope */
154 2.0f * ((float)rand()/(float)RAND_MAX-0.5f); /* whitenoise */
155 }
156 }
157
158 /* get bank of FIRs filters - octave bands */
159 fcut = malloc1d((nBands-1)*sizeof(float));
160 h_filt = malloc1d(nBands*(filterOrder+1)*sizeof(float));
161 getOctaveBandCutoffFreqs(fcen_oct, nBands, fcut);
162 FIRFilterbank(filterOrder, fcut, (nBands-1), fs, WINDOWING_FUNCTION_HAMMING, 1, h_filt);
163
164 /* filter RIRs with filterbank */
165 (*rir_filt) = realloc1d((*rir_filt), nCH*rir_filt_lout*sizeof(float));
166 memset((*rir_filt), 0, nCH*rir_filt_lout*sizeof(float));
167 rir_filt_tmp = malloc1d(nBands*rir_filt_lout*sizeof(float));
168 for(i=0; i<nCH; i++){
169 fftfilt(&rir[i*nBands*rir_filt_lout], h_filt, rir_filt_lout, filterOrder+1, nBands, rir_filt_tmp);
170 /* sum over bands */
171 for(j=0; j<nBands; j++){
172 for(k=0; k<rir_filt_lout; k++)
173 (*rir_filt)[i*rir_filt_lout+k] += rir_filt_tmp[j*rir_filt_lout+k];
174 }
175 }
176
177 /* equalise, to force flat magnitude response */
178 if(flattenFLAG)
179 for(i=0; i<nCH; i++)
180 flattenMinphase(&((*rir_filt)[i*rir_filt_lout]), rir_filt_lout);
181
182 /* remove filterbank delay */
183 for(i=0; i<nCH; i++)
184 memcpy(&((*rir_filt)[i*rir_filt_len]), &((*rir_filt)[i*rir_filt_lout + filterOrder/2]), rir_filt_len*sizeof(float));
185 (*rir_len) = rir_filt_len;
186
187 /* clean-up */
188 free(rir);
189 free(fcut);
190 free(h_filt);
191 free(rir_filt_tmp);
192}
193
195(
196 void** phDecor,
197 float fs,
198 int hopsize,
199 float* freqVector,
200 int nBands,
201 int nCH,
202 int* orders,
203 float* freqCutoffs,
204 int nCutoffs,
205 int maxDelay,
206 int lookupOffset,
207 float enComp_coeff
208)
209{
210 *phDecor = malloc1d(sizeof(latticeDecor_data));
211 latticeDecor_data *h = (latticeDecor_data*)(*phDecor);
212 int i, band, ch, o, filterIdx;
213
214 h->nCH = nCH;
215 h->nCutoffs = nCutoffs;
216 h->nBands = nBands;
217
218 /* alloc */
219 h->orders = malloc1d(nCutoffs*sizeof(int));
220 memcpy(h->orders, orders, nCutoffs*sizeof(int));
221 h->TF_delays = malloc1d(nBands * nCH * sizeof(int));
222 h->lttc_apf = (latticeAPF**)malloc2d(nBands, nCH, sizeof(latticeAPF));
223 h->enComp_coeff = enComp_coeff;
224 h->in_energy = (float**)calloc2d(nBands, nCH, sizeof(float));
225 h->decor_energy = (float**)calloc2d(nBands, nCH, sizeof(float));
226
227 /* Static delays */
228 getDecorrelationDelays(h->nCH, freqVector, h->nBands, fs, maxDelay, hopsize, h->TF_delays);
229
230 /* Find true max delay */
231 maxDelay = 0;
232 for(i=0; i<nBands*nCH; i++)
233 maxDelay = h->TF_delays[i] > maxDelay ? h->TF_delays[i] : maxDelay;
234
235 /* set-up allpass filters per band and channel */
236 for(band=0; band<nBands; band++){
237 filterIdx = -1;
238
239 /* Find filter index for this band: */
240 for(o=0; o<nCutoffs; o++){
241 if(freqVector[band]<freqCutoffs[o]){
242 filterIdx = o;
243 break;
244 }
245 }
246
247 /* Pull lattice allpass filter coefficients from database */
248 for(ch=0; ch<nCH; ch++){
249 if(filterIdx == -1){
250 /* Not needed... */
251 h->lttc_apf[band][ch].order = -1;
252 h->lttc_apf[band][ch].filterLength = 0;
253 h->lttc_apf[band][ch].coeffs = NULL;
254 h->lttc_apf[band][ch].buffer = NULL;
255 }
256 else{
257 h->lttc_apf[band][ch].order = h->orders[filterIdx];
258 h->lttc_apf[band][ch].coeffs = (float**)malloc2d(2, h->orders[filterIdx], sizeof(float));
259 h->lttc_apf[band][ch].buffer = calloc1d(h->lttc_apf[band][ch].order, sizeof(float_complex));
260
261 /* numerator coefficients */
262 switch(orders[filterIdx]){
263 case 20: memcpy(h->lttc_apf[band][ch].coeffs[0], __lattice_coeffs_o20[ch+lookupOffset], (h->orders[filterIdx])*sizeof(float)); break;
264 case 18: memcpy(h->lttc_apf[band][ch].coeffs[0], __lattice_coeffs_o18[ch+lookupOffset], (h->orders[filterIdx])*sizeof(float)); break;
265 case 16: memcpy(h->lttc_apf[band][ch].coeffs[0], __lattice_coeffs_o16[ch+lookupOffset], (h->orders[filterIdx])*sizeof(float)); break;
266 case 15: memcpy(h->lttc_apf[band][ch].coeffs[0], __lattice_coeffs_o15[ch+lookupOffset], (h->orders[filterIdx])*sizeof(float)); break;
267 case 14: memcpy(h->lttc_apf[band][ch].coeffs[0], __lattice_coeffs_o14[ch+lookupOffset], (h->orders[filterIdx])*sizeof(float)); break;
268 case 12: memcpy(h->lttc_apf[band][ch].coeffs[0], __lattice_coeffs_o12[ch+lookupOffset], (h->orders[filterIdx])*sizeof(float)); break;
269 case 10: memcpy(h->lttc_apf[band][ch].coeffs[0], __lattice_coeffs_o10[ch+lookupOffset], (h->orders[filterIdx])*sizeof(float)); break;
270 case 8: memcpy(h->lttc_apf[band][ch].coeffs[0], __lattice_coeffs_o8[ch+lookupOffset], (h->orders[filterIdx])*sizeof(float)); break;
271 case 6: memcpy(h->lttc_apf[band][ch].coeffs[0], __lattice_coeffs_o6[ch+lookupOffset], (h->orders[filterIdx])*sizeof(float)); break;
272 case 4: memcpy(h->lttc_apf[band][ch].coeffs[0], __lattice_coeffs_o4[ch+lookupOffset], (h->orders[filterIdx])*sizeof(float)); break;
273 case 3: memcpy(h->lttc_apf[band][ch].coeffs[0], __lattice_coeffs_o3[ch+lookupOffset], (h->orders[filterIdx])*sizeof(float)); break;
274 case 2: memcpy(h->lttc_apf[band][ch].coeffs[0], __lattice_coeffs_o2[ch+lookupOffset], (h->orders[filterIdx])*sizeof(float)); break;
275 default: saf_print_error("Unsupported filter order was specified"); break;
276 }
277
278 /* denominator coefficients */
279 for(i=0; i<orders[filterIdx]; i++)
280 h->lttc_apf[band][ch].coeffs[1][i] = h->lttc_apf[band][ch].coeffs[0][orders[filterIdx]-i-1];
281 }
282 }
283 }
284
285 /* Run-time */
286 h->maxBufferLen = maxDelay+1;
287 h->delayBuffers = (float_complex***)calloc3d(nBands, nCH, h->maxBufferLen, sizeof(float_complex));
288 h->wIdx = malloc1d(nBands*nCH*sizeof(int));
289 for(band=0; band<nBands; band++)
290 for(ch=0; ch<nCH; ch++)
291 h->wIdx[band*nCH+ch] = h->TF_delays[band*nCH+ch];
292 h->rIdx = calloc1d(nBands*nCH,sizeof(int));
293}
294
296(
297 void** phDecor
298)
299{
300 latticeDecor_data *h = (latticeDecor_data*)(*phDecor);
301 int band, ch;
302
303 if(h!=NULL){
304 free(h->orders);
305 free(h->TF_delays);
306 for(band=0; band <h->nBands; band++){
307 for(ch=0; ch<h->nCH; ch++){
308 free(h->lttc_apf[band][ch].buffer);
309 free(h->lttc_apf[band][ch].coeffs);
310 }
311 }
312 free(h->lttc_apf);
313
314 free(h->delayBuffers);
315 free(h->wIdx);
316 free(h->rIdx);
317 free(h);
318 h=NULL;
319 *phDecor = NULL;
320 }
321}
322
324(
325 void* hDecor
326)
327{
328 latticeDecor_data *h = (latticeDecor_data*)(hDecor);
329 int band, ch;
330
331 memset(FLATTEN3D(h->delayBuffers), 0, h->nBands * h->nCH * h->maxBufferLen * sizeof(float_complex));
332 for(band=0; band<h->nBands; band++)
333 for(ch=0; ch<h->nCH; ch++)
334 if(h->lttc_apf[band][ch].buffer!=NULL)
335 memset(h->lttc_apf[band][ch].buffer, 0, h->lttc_apf[band][ch].order * sizeof(float_complex));
336 memset(FLATTEN2D(h->in_energy), 0, h->nBands*h->nCH*sizeof(float));
337 memset(FLATTEN2D(h->decor_energy), 0, h->nBands*h->nCH*sizeof(float));
338}
339
341(
342 void* hDecor,
343 float_complex*** inFrame,
344 int nTimeSlots,
345 float_complex*** decorFrame
346)
347{
348 latticeDecor_data *h = (latticeDecor_data*)(hDecor);
349 int band, ch, t, i;
350 float_complex ytmp, xtmp;
351
352 for(t=0; t<nTimeSlots; t++){
353 for(band=0; band <h->nBands; band++){
354 for(ch=0; ch<h->nCH; ch++){
355 /* Apply fixed delay */
356 h->delayBuffers[band][ch][h->wIdx[band*(h->nCH) + ch]] = inFrame[band][ch][t];
357 decorFrame[band][ch][t] = h->delayBuffers[band][ch][h->rIdx[band*(h->nCH) + ch]];
358
359 /* increment and wrap-around as needed */
360 h->rIdx[band*(h->nCH) + ch]++;
361 h->wIdx[band*(h->nCH) + ch]++;
362 if( h->rIdx[band*(h->nCH) + ch] > h->TF_delays[band*(h->nCH) + ch] )
363 h->rIdx[band*(h->nCH) + ch] = 0;
364 if( h->wIdx[band*(h->nCH) + ch] > h->TF_delays[band*(h->nCH) + ch] )
365 h->wIdx[band*(h->nCH) + ch] = 0;
366 }
367 }
368 }
369
370 /* Apply lattice allpass filters */
371#if _MSC_VER >= 1900
372 for(band=0; band <h->nBands; band++){
373 for(ch=0; ch<h->nCH; ch++){
374 if(h->lttc_apf[band][ch].buffer!=NULL){ /* only if filter is defined... */
375 for(t=0; t<nTimeSlots; t++){
376 /* Compute energy of the input */
377 h->in_energy[band][ch] = (1.0f-h->enComp_coeff)*powf(cabsf(inFrame[band][ch][t]),2.0f) + (h->enComp_coeff)*h->in_energy[band][ch];
378
379 /* First tap in filter */
380 xtmp = decorFrame[band][ch][t];
381 ytmp = ccaddf(h->lttc_apf[band][ch].buffer[0], crmulf(xtmp, (h->lttc_apf[band][ch].coeffs[0][0])));
382 decorFrame[band][ch][t] = ytmp;
383
384 /* Energy compensation */
385 h->decor_energy[band][ch] = (1.0f-h->enComp_coeff)*powf(cabsf(decorFrame[band][ch][t]),2.0f) + (h->enComp_coeff)*h->decor_energy[band][ch];
386 decorFrame[band][ch][t] = crmulf(decorFrame[band][ch][t], SAF_MIN(sqrtf(h->in_energy[band][ch]/(h->decor_energy[band][ch]+2.23e-9f)), 1.0f));
387
388 /* propagate through the rest of the lattice filter structure */
389 for(i=0; i<h->lttc_apf[band][ch].order-1; i++){
390 h->lttc_apf[band][ch].buffer[i] = ccaddf(h->lttc_apf[band][ch].buffer[i+1],
391 ccsubf(crmulf(xtmp, h->lttc_apf[band][ch].coeffs[0][i+1]), /* numerator */
392 crmulf(ytmp, h->lttc_apf[band][ch].coeffs[1][i+1]))); /* denominator */
393 }
394 }
395 }
396 }
397 }
398#else
399 for(band=0; band <h->nBands; band++){
400 for(ch=0; ch<h->nCH; ch++){
401 if(h->lttc_apf[band][ch].buffer!=NULL){ /* only if filter is defined */
402 for(t=0; t<nTimeSlots; t++){
403 /* Compute energy of the input */
404 h->in_energy[band][ch] = (1.0f-h->enComp_coeff)*powf(cabsf(inFrame[band][ch][t]),2.0f) + (h->enComp_coeff)*h->in_energy[band][ch];
405
406 /* First tap in filter */
407 xtmp = decorFrame[band][ch][t];
408 ytmp = xtmp * (h->lttc_apf[band][ch].coeffs[0][0]) + h->lttc_apf[band][ch].buffer[0];
409 decorFrame[band][ch][t] = ytmp;
410
411 /* Energy compensation */
412 h->decor_energy[band][ch] = (1.0f-h->enComp_coeff)*powf(cabsf(decorFrame[band][ch][t]), 2.0f) + (h->enComp_coeff)*(h->decor_energy[band][ch]);
413 decorFrame[band][ch][t] *= SAF_MIN(sqrtf(h->in_energy[band][ch]/(h->decor_energy[band][ch]+2.23e-9f)), 1.0f);
414
415 /* propagate through the rest of the lattice filter structure */
416 for(i=0; i<h->lttc_apf[band][ch].order-1; i++){
417 h->lttc_apf[band][ch].buffer[i] = h->lttc_apf[band][ch].buffer[i+1] +
418 h->lttc_apf[band][ch].coeffs[0][i+1] * xtmp - /* numerator */
419 h->lttc_apf[band][ch].coeffs[1][i+1] * ytmp; /* denominator */
420 }
421 }
422 }
423 }
424 }
425#endif
426}
427
429(
430 void** phDucker,
431 int nCH,
432 int nBands
433)
434{
435 *phDucker = malloc1d(sizeof(transientDucker_data));
437
438 h->nCH = nCH;
439 h->nBands = nBands;
440 h->transientDetector1 = (float**)calloc2d(nBands, nCH, sizeof(float));
441 h->transientDetector2 = (float**)calloc2d(nBands, nCH, sizeof(float));
442}
443
445(
446 void** phDucker
447)
448{
450
451 if(h!=NULL){
452 free(h->transientDetector1);
453 free(h->transientDetector2);
454 free(h);
455 h=NULL;
456 *phDucker = NULL;
457 }
458}
459
461(
462 void* hDucker,
463 float_complex*** inFrame,
464 int nTimeSlots,
465 float alpha,
466 float beta,
467 float_complex*** residualFrame,
468 float_complex*** transientFrame
469)
470{
472 int band, i, t;
473 float detectorEne, transientEQ;
474 //const float alpha = 0.95f;
475 //const float beta = 0.995f;
476
477 for(band=0; band<h->nBands; band++){
478 for(i=0; i<h->nCH; i++){
479 for(t=0; t<nTimeSlots; t++){
480 detectorEne = cabsf(inFrame[band][i][t]);
481 detectorEne = detectorEne*detectorEne;
482 h->transientDetector1[band][i] *= alpha;
483 if(h->transientDetector1[band][i]<detectorEne)
484 h->transientDetector1[band][i] = detectorEne;
485 h->transientDetector2[band][i] = h->transientDetector2[band][i]*beta + (1.0f-beta)*(h->transientDetector1[band][i]);
486 if(h->transientDetector2[band][i] > h->transientDetector1[band][i])
487 h->transientDetector2[band][i] = h->transientDetector1[band][i];
488 transientEQ = SAF_MIN(1.0f, 4.0f * (h->transientDetector2[band][i])/(h->transientDetector1[band][i]+2.23e-9f));
489#ifdef _MSC_VER
490 if(residualFrame!=NULL)
491 residualFrame[band][i][t] = crmulf(inFrame[band][i][t], transientEQ);
492 if(transientFrame!=NULL)
493 transientFrame[band][i][t] = crmulf(inFrame[band][i][t], 1.0f-transientEQ);
494#else
495 if(residualFrame!=NULL)
496 residualFrame[band][i][t] = inFrame[band][i][t] * transientEQ;
497 if(transientFrame!=NULL)
498 transientFrame[band][i][t] = inFrame[band][i][t] * (1.0f-transientEQ);
499#endif
500 }
501 }
502 }
503}
#define saf_print_error(message)
Macro to print a error message along with the filename and line number.
void fftfilt(float *x, float *h, int x_len, int h_len, int nCH, float *y)
FFT-based convolution for FIR filters.
void transientDucker_destroy(void **phDucker)
Destroys an instance of the transient ducker.
#define SAF_MAX(a, b)
Returns the maximum of the two values.
const float __lattice_coeffs_o3[256][3]
Lattice all-pass filter coeffs (numerator) for 256 channels, 3rd order.
void transientDucker_apply(void *hDucker, float_complex ***inFrame, int nTimeSlots, float alpha, float beta, float_complex ***residualFrame, float_complex ***transientFrame)
Applies the transient ducker, returning either the "ducked" input frame, or the transient part of the...
const float __lattice_coeffs_o14[256][14]
Lattice all-pass filter coeffs (numerator) for 256 channels, 14th order.
void FIRFilterbank(int order, float *fc, int nCutoffFreq, float sampleRate, WINDOWING_FUNCTION_TYPES windowType, int scalingFLAG, float *filterbank)
Computes a bank of FIR filter coefficients required to divide a signal into frequency bands.
const float __lattice_coeffs_o20[256][20]
Lattice all-pass filter coeffs (numerator) for 256 channels, 20th order.
const float __lattice_coeffs_o8[256][8]
Lattice all-pass filter coeffs (numerator) for 256 channels, 8th order.
void flattenMinphase(float *x, int len)
Equalises input sequence by its minimum phase form, in order to bring its magnitude response to unity...
void randperm(int len, int *randperm)
Returns the indices required to randomly permute a vector of length 'len'.
const float __lattice_coeffs_o4[256][4]
Lattice all-pass filter coeffs (numerator) for 256 channels, 4th order.
const float __lattice_coeffs_o15[256][15]
Lattice all-pass filter coeffs (numerator) for 256 channels, 15th order.
const float __lattice_coeffs_o16[256][16]
Lattice all-pass filter coeffs (numerator) for 256 channels, 16th order.
void latticeDecorrelator_reset(void *hDecor)
Sets the internal buffers to zero.
void latticeDecorrelator_apply(void *hDecor, float_complex ***inFrame, int nTimeSlots, float_complex ***decorFrame)
Applies the lattice all-pass-filter-based multi-channel signal decorrelator.
#define SAF_MIN(a, b)
Returns the minimum of the two values.
const float __lattice_coeffs_o10[256][10]
Lattice all-pass filter coeffs (numerator) for 256 channels, 10th order.
const float __lattice_coeffs_o18[256][18]
Lattice all-pass filter coeffs (numerator) for 256 channels, 18th order.
void latticeDecorrelator_create(void **phDecor, float fs, int hopsize, float *freqVector, int nBands, int nCH, int *orders, float *freqCutoffs, int nCutoffs, int maxDelay, int lookupOffset, float enComp_coeff)
Creates an instance of the lattice all-pass-filter-based multi-channel signal decorrelator.
const float __lattice_coeffs_o2[256][2]
Lattice all-pass filter coeffs (numerator) for 256 channels, 2nd order.
void latticeDecorrelator_destroy(void **phDecor)
Destroys an instance of the lattice all-pass-filter-based multi-channel signal decorrelator.
const float __lattice_coeffs_o12[256][12]
Lattice all-pass filter coeffs (numerator) for 256 channels, 12th order.
void synthesiseNoiseReverb(int nCH, float fs, float *t60, float *fcen_oct, int nBands, int flattenFLAG, float **rir_filt, int *rir_len)
Returns quick and dirty exponentially decaying noise bursts.
const float __lattice_coeffs_o6[256][6]
Lattice all-pass filter coeffs (numerator) for 256 channels, 6th order.
void transientDucker_create(void **phDucker, int nCH, int nBands)
Creates an instance of the transient ducker/extractor.
void getDecorrelationDelays(int nChannels, float *freqs, int nFreqs, float fs, int maxTFdelay, int hopSize, int *delayTF)
Returns delay values for multiple channels per frequency, such that once applied to an input signal (...
void getOctaveBandCutoffFreqs(float *centreFreqs, int nCentreFreqs, float *cutoffFreqs)
Converts octave band CENTRE frequencies into CUTOFF frequencies.
@ WINDOWING_FUNCTION_HAMMING
Hamming.
void ** malloc2d(size_t dim1, size_t dim2, size_t data_size)
2-D malloc (contiguously allocated, so use free() as usual to deallocate)
Definition md_malloc.c:89
void * malloc1d(size_t dim1_data_size)
1-D malloc (same as malloc, but with error checking)
Definition md_malloc.c:59
void * calloc1d(size_t dim1, size_t data_size)
1-D calloc (same as calloc, but with error checking)
Definition md_malloc.c:69
void * realloc1d(void *ptr, size_t dim1_data_size)
1-D realloc (same as realloc, but with error checking)
Definition md_malloc.c:79
void ** calloc2d(size_t dim1, size_t dim2, size_t data_size)
2-D calloc (contiguously allocated, so use free() as usual to deallocate)
Definition md_malloc.c:102
void *** calloc3d(size_t dim1, size_t dim2, size_t dim3, size_t data_size)
3-D calloc (contiguously allocated, so use free() as usual to deallocate)
Definition md_malloc.c:170
#define FLATTEN2D(A)
Use this macro when passing a 2-D dynamic multi-dimensional array to memset, memcpy or any other func...
Definition md_malloc.h:65
#define FLATTEN3D(A)
Use this macro when passing a 3-D dynamic multi-dimensional array to memset, memcpy or any other func...
Definition md_malloc.h:72
Include header for SAF externals.
Main header for the utilities module (SAF_UTILITIES_MODULE)
Internal Lattice all-pass filter structure.
Internal Lattice all-pass filter based decorrelator structure.
Internal structure used by the transient Ducker.