37typedef struct _safMatConv_data {
38 int hopSize, fftSize, nBins;
39 int length_h, nCHin, nCHout;
40 int numFilterBlocks, numOvrlpAddBlocks;
43 float* x_pad, *y_pad, *hx_n, *z_n, *ovrlpAddBuffer, *y_n_overlap;
44 float_complex* H_f, *X_n, *HX_n;
45 float_complex** Hpart_f;
63 float* h_pad, *h_pad_2hops;
66 h->length_h = length_h;
69 h->usePartFLAG = usePartFLAG;
73 h->numOvrlpAddBlocks = (int)(ceilf((
float)(hopSize+length_h-1)/(
float)hopSize)+0.1f);
75 h->fftSize = (h->numOvrlpAddBlocks)*hopSize;
76 h->nBins = h->fftSize/2 + 1;
79 h->ovrlpAddBuffer =
calloc1d(nCHout*(h->fftSize),
sizeof(
float));
80 h->x_pad =
calloc1d((h->nCHin)*(h->fftSize),
sizeof(
float));
81 h->y_pad =
malloc1d((h->nCHout)*(h->fftSize)*
sizeof(
float));
82 h->hx_n =
malloc1d((h->fftSize) *
sizeof(
float));
83 h->H_f =
malloc1d((h->nCHout)*(h->nCHin)*(h->nBins)*
sizeof(float_complex));
84 h->X_n =
malloc1d((h->nCHout)*(h->nCHin)*(h->nBins)*
sizeof(float_complex));
85 h->HX_n =
malloc1d((h->nCHout)*(h->nCHin)*(h->nBins)*
sizeof(float_complex));
86 h->z_n =
malloc1d((h->fftSize) *
sizeof(
float));
88 h_pad =
calloc1d(h->fftSize,
sizeof(
float));
89 for(no=0; no<nCHout; no++){
90 for(ni=0; ni<nCHin; ni++){
91 memcpy(h_pad, &(H[no*nCHin*length_h+ni*length_h]), length_h*
sizeof(
float));
92 saf_rfft_forward(h->hFFT, h_pad, &(h->H_f[no*nCHin*(h->nBins)+ni*(h->nBins)]));
99 h->length_h = length_h;
100 h->fftSize = 2*(h->hopSize);
101 h->nBins = hopSize+1;
102 h->numFilterBlocks = (int)ceilf((
float)length_h/(float)hopSize);
103 saf_assert(h->numFilterBlocks>=1,
"Number of filter blocks/partitions must be at least 1");
106 h_pad =
calloc1d(h->numFilterBlocks * hopSize,
sizeof(
float));
107 h_pad_2hops =
calloc1d(2 * hopSize,
sizeof(
float));
108 h->Hpart_f =
malloc1d(nCHout*
sizeof(float_complex*));
109 h->X_n =
calloc1d(h->numFilterBlocks * nCHin * (h->nBins),
sizeof(float_complex));
110 h->HX_n =
malloc1d(h->numFilterBlocks * nCHin * (h->nBins) *
sizeof(float_complex));
111 h->x_pad =
calloc1d(2 * hopSize,
sizeof(
float));
112 h->hx_n =
malloc1d(h->numFilterBlocks*nCHin*(h->fftSize)*
sizeof(
float));
113 h->y_n_overlap =
calloc1d(nCHout*hopSize,
sizeof(
float));
114 h->z_n =
malloc1d((h->fftSize) *
sizeof(
float));
116 for(no=0; no<nCHout; no++){
117 h->Hpart_f[no] =
malloc1d(h->numFilterBlocks*nCHin*(h->nBins)*
sizeof(float_complex));
118 for(ni=0; ni<nCHin; ni++){
119 memcpy(h_pad, &H[no*nCHin*length_h+ni*length_h], length_h*
sizeof(
float));
120 for (nb=0; nb<h->numFilterBlocks; nb++){
121 memcpy(h_pad_2hops, &(h_pad[nb*hopSize]), hopSize*
sizeof(
float));
122 saf_rfft_forward(h->hFFT, h_pad_2hops, &(h->Hpart_f[no][nb*nCHin*(h->nBins)+ni*(h->nBins)]));
148 free(h->ovrlpAddBuffer);
153 free(h->y_n_overlap);
154 for(no=0; no<h->nCHout; no++)
155 free(h->Hpart_f[no]);
172 memset(h->ovrlpAddBuffer, 0, h->nCHout*(h->fftSize)*
sizeof(
float));
174 memset(h->y_n_overlap, 0, h->nCHout*h->hopSize*
sizeof(
float));
190 for(ni=0; ni<h->nCHin; ni++){
191 cblas_scopy(h->hopSize, &inputSig[ni*(h->hopSize)], 1, &(h->x_pad[ni*(h->fftSize)]), 1);
192 saf_rfft_forward(h->hFFT, &(h->x_pad[ni*(h->fftSize)]), &(h->X_n[ni*(h->nBins)]));
196 for(no=1; no<h->nCHout; no++)
197 cblas_ccopy(h->nCHin*(h->nBins), h->X_n, 1, &(h->X_n[no*ni*(h->nBins)]), 1);
200 utility_cvvmul(h->H_f, h->X_n, (h->nCHout)*(h->nCHin)*h->nBins, h->HX_n);
203 for(no=0; no<h->nCHout; no++){
205 memset(h->z_n, 0, (h->fftSize) *
sizeof(
float));
206 for(ni=0; ni<h->nCHin; ni++){
207 saf_rfft_backward(h->hFFT, &(h->HX_n[no*(h->nCHin)*(h->nBins)+ni*(h->nBins)]), h->hx_n);
208 cblas_saxpy(h->fftSize, 1.0f, h->hx_n, 1, h->z_n, 1);
212 memmove(&(h->ovrlpAddBuffer[no*(h->fftSize)]), &(h->ovrlpAddBuffer[no*(h->fftSize)+(h->hopSize)]), (h->numOvrlpAddBlocks-1)*(h->hopSize)*
sizeof(
float));
213 memset(&(h->ovrlpAddBuffer[no*(h->fftSize)+(h->numOvrlpAddBlocks-1)*(h->hopSize)]), 0, (h->hopSize)*
sizeof(
float));
216 cblas_saxpy(h->fftSize, 1.0f, h->z_n, 1, &(h->ovrlpAddBuffer[no*(h->fftSize)]), 1);
219 cblas_scopy(h->hopSize, &(h->ovrlpAddBuffer[no*(h->fftSize)]), 1, &(outputSig[no*(h->hopSize)]), 1);
225 memmove(&(h->X_n[1*(h->nCHin)*(h->nBins)]), h->X_n, (h->numFilterBlocks-1)*(h->nCHin)*(h->nBins)*
sizeof(float_complex));
226 for(ni=0; ni<h->nCHin; ni++){
227 cblas_scopy(h->hopSize, &(inputSig[ni*(h->hopSize)]), 1, h->x_pad, 1);
228 saf_rfft_forward(h->hFFT, h->x_pad, &(h->X_n[0*(h->nCHin)*(h->nBins)+ni*(h->nBins)]));
232 for(no=0; no<h->nCHout; no++){
233 utility_cvvmul(h->Hpart_f[no], h->X_n, h->numFilterBlocks * (h->nCHin) * (h->nBins), h->HX_n);
234 for(nb=0; nb<h->numFilterBlocks; nb++)
235 for(ni=0; ni<h->nCHin; ni++)
236 saf_rfft_backward(h->hFFT, &(h->HX_n[nb*(h->nCHin)*(h->nBins)+ni*(h->nBins)]), &(h->hx_n[nb*(h->nCHin)*(h->fftSize)+ni*(h->fftSize)]));
239 memset(h->z_n, 0, (h->fftSize) *
sizeof(
float));
240 for(nb=0; nb<h->numFilterBlocks*(h->nCHin); nb++)
241 cblas_saxpy(h->fftSize, 1.0f, &(h->hx_n[nb*(h->fftSize)]), 1, h->z_n, 1);
244 utility_svvadd(h->z_n, (
const float*)&(h->y_n_overlap[no*(h->hopSize)]), h->hopSize, &(outputSig[no*(h->hopSize)]));
247 cblas_scopy(h->hopSize, &(h->z_n[h->hopSize]), 1, &(h->y_n_overlap[no*(h->hopSize)]), 1);
260typedef struct _safMulConv_data {
261 int hopSize, fftSize, nBins;
263 int numOvrlpAddBlocks, numFilterBlocks;
266 float* x_pad, *z_n, *ovrlpAddBuffer, *hx_n, *y_n_overlap;
267 float_complex* X_n, *HX_n, *Z_n, *H_f, *Hpart_f;
284 float* h_pad, *h_pad_2hops;
286 h->hopSize = hopSize;
287 h->length_h = length_h;
289 h->usePartFLAG = usePartFLAG;
293 h->numOvrlpAddBlocks = (int)(ceilf((
float)(hopSize+length_h-1)/(
float)hopSize)+0.1f);
294 h->fftSize = (h->numOvrlpAddBlocks*hopSize);
295 h->nBins = h->fftSize/2 + 1;
298 h->ovrlpAddBuffer =
calloc1d(nCH*h->fftSize,
sizeof(
float));
299 h_pad =
calloc1d(h->fftSize,
sizeof(
float));
300 h->H_f =
malloc1d(nCH*(h->nBins)*
sizeof(float_complex));
301 h->X_n =
calloc1d(nCH * (h->nBins),
sizeof(float_complex));
302 h->Z_n =
malloc1d(nCH * (h->nBins) *
sizeof(float_complex));
303 h->x_pad =
calloc1d(h->fftSize,
sizeof(
float));
304 h->z_n =
malloc1d(nCH*(h->fftSize)*
sizeof(
float));
306 for(nc=0; nc<nCH; nc++){
307 memcpy(h_pad, &H[nc*length_h], length_h*
sizeof(
float));
315 h->fftSize = 2*(h->hopSize);
316 h->nBins = hopSize+1;
317 h->numFilterBlocks = (int)ceilf((
float)length_h/(float)hopSize);
318 saf_assert(h->numFilterBlocks>=1,
"Number of filter blocks/partitions must be at least 1");
321 h_pad =
calloc1d(h->numFilterBlocks * hopSize,
sizeof(
float));
322 h_pad_2hops =
calloc1d(2 * hopSize,
sizeof(
float));
323 h->Hpart_f =
malloc1d(h->numFilterBlocks*nCH*(h->nBins)*
sizeof(float_complex));
324 h->X_n =
calloc1d(h->numFilterBlocks * nCH * (h->nBins),
sizeof(float_complex));
325 h->HX_n =
calloc1d(h->numFilterBlocks * nCH * (h->nBins),
sizeof(float_complex));
326 h->x_pad =
calloc1d(2 * hopSize,
sizeof(
float));
327 h->hx_n =
malloc1d(h->numFilterBlocks*nCH*(h->fftSize)*
sizeof(
float));
328 h->z_n =
calloc1d(h->fftSize,
sizeof(
float));
329 h->y_n_overlap =
calloc1d(nCH*hopSize,
sizeof(
float));
331 for(nc=0; nc<nCH; nc++){
332 memcpy(h_pad, &H[nc*length_h], length_h*
sizeof(
float));
333 for (nb=0; nb<h->numFilterBlocks; nb++){
334 memcpy(h_pad_2hops, &(h_pad[nb*hopSize]), hopSize*
sizeof(
float));
335 saf_rfft_forward(h->hFFT, h_pad_2hops, &(h->Hpart_f[nb*nCH*(h->nBins)+nc*(h->nBins)]));
363 free(h->y_n_overlap);
380 memset(h->ovrlpAddBuffer, 0, h->nCH*h->fftSize*
sizeof(
float));
382 memset(h->y_n_overlap, 0, h->nCH*h->hopSize*
sizeof(
float));
398 for(nc=0; nc<h->nCH; nc++){
399 memcpy(h->x_pad, &(inputSig[nc*(h->hopSize)]), h->hopSize *
sizeof(
float));
405 for(nc=0; nc<h->nCH; nc++){
406 saf_rfft_backward(h->hFFT, &(h->Z_n[nc*(h->nBins)]), &(h->z_n[nc*(h->fftSize)]));
409 utility_svvcopy(&(h->ovrlpAddBuffer[nc*(h->fftSize)+(h->hopSize)]), (h->numOvrlpAddBlocks-1)*(h->hopSize), &(h->ovrlpAddBuffer[nc*(h->fftSize)]));
410 memset(&(h->ovrlpAddBuffer[nc*(h->fftSize)+(h->numOvrlpAddBlocks-1)*(h->hopSize)]), 0, (h->hopSize)*
sizeof(
float));
411 cblas_saxpy(h->fftSize, 1.0f, &(h->z_n[nc*(h->fftSize)]), 1, &(h->ovrlpAddBuffer[nc*(h->fftSize)]), 1);
412 utility_svvcopy(&(h->ovrlpAddBuffer[nc*(h->fftSize)]), h->hopSize, &(outputSig[nc*(h->hopSize)]));
418 memmove(&(h->X_n[1*(h->nCH)*(h->nBins)]), h->X_n, (h->numFilterBlocks-1)*(h->nCH)*(h->nBins)*
sizeof(float_complex));
419 for(nc=0; nc<h->nCH; nc++){
420 memcpy(h->x_pad, &(inputSig[nc*(h->hopSize)]), h->hopSize *
sizeof(
float));
421 saf_rfft_forward(h->hFFT, h->x_pad, &(h->X_n[0*(h->nCH)*(h->nBins)+nc*(h->nBins)]));
425 utility_cvvmul(h->Hpart_f, h->X_n, h->numFilterBlocks * (h->nCH) * (h->nBins), h->HX_n);
426 for(nc=0; nc<h->nCH; nc++){
427 for(nb=0; nb<h->numFilterBlocks; nb++)
428 saf_rfft_backward(h->hFFT, &(h->HX_n[nb*(h->nCH)*(h->nBins)+nc*(h->nBins)]), &(h->hx_n[nb*(h->nCH)*(h->fftSize)+nc*(h->fftSize)]));
431 memset(h->z_n, 0, h->fftSize*
sizeof(
float));
432 for(nb=0; nb<h->numFilterBlocks; nb++)
433 cblas_saxpy(h->fftSize, 1.0f, (
const float*)&(h->hx_n[nb*(h->nCH)*(h->fftSize)+nc*(h->fftSize)]), 1, h->z_n, 1);
436 utility_svvadd(h->z_n, (
const float*)&(h->y_n_overlap[nc*(h->hopSize)]), h->hopSize, &(outputSig[nc* (h->hopSize)]));
439 memcpy(&(h->y_n_overlap[nc*(h->hopSize)]), &(h->z_n[h->hopSize]), h->hopSize*
sizeof(
float));
451typedef struct _safTVConv_data {
452 int hopSize, fftSize, nBins;
453 int length_h, nIRs, nCHout;
457 *z_n, *z_n_last, *z_n_last2,
458 *y_n_overlap, *y_n_overlap_last,
461 *outFadeIn, *outFadeOut;
462 float_complex* X_n, *HX_n;
463 float_complex*** Hpart_f;
464 int posIdx_last, posIdx_last2;
481 float* h_pad, *h_pad_2hops;
483 h->hopSize = hopSize;
484 h->length_h = length_h;
488 h->posIdx_last = initIdx;
489 h->posIdx_last2 = initIdx;
496 h->length_h = length_h;
497 h->fftSize = 2*(h->hopSize);
498 h->nBins = hopSize+1;
499 h->numFilterBlocks = (int)ceilf((
float)length_h/(float)hopSize);
500 saf_assert(h->numFilterBlocks>=1,
"Number of filter blocks/partitions must be at least 1");
503 h_pad =
calloc1d(h->numFilterBlocks * hopSize,
sizeof(
float));
504 h_pad_2hops =
calloc1d(2 * hopSize,
sizeof(
float));
505 h->Hpart_f = (float_complex***)
malloc2d(nIRs, nCHout,
sizeof(float_complex*));
506 h->X_n =
calloc1d(h->numFilterBlocks * (h->nBins),
sizeof(float_complex));
507 h->HX_n =
malloc1d(h->numFilterBlocks * (h->nBins) *
sizeof(float_complex));
508 h->x_pad =
calloc1d(2 * hopSize,
sizeof(
float));
509 h->hx_n =
malloc1d(h->numFilterBlocks*(h->fftSize)*
sizeof(
float));
510 h->y_n_overlap =
calloc1d(nCHout*hopSize,
sizeof(
float));
511 h->y_n_overlap_last =
calloc1d(nCHout*hopSize,
sizeof(
float));
512 h->z_n =
malloc1d((h->fftSize) *
sizeof(
float));
513 h->z_n_last =
malloc1d((h->fftSize) *
sizeof(
float));
514 h->z_n_last2 =
malloc1d((h->fftSize) *
sizeof(
float));
515 h->out1 =
malloc1d(hopSize *
sizeof(
float));
516 h->out2 =
malloc1d(hopSize *
sizeof(
float));
517 h->fadeIn =
malloc1d(hopSize *
sizeof(
float));
518 h->fadeOut =
malloc1d(hopSize *
sizeof(
float));
519 h->outFadeIn =
malloc1d(hopSize *
sizeof(
float));
520 h->outFadeOut =
malloc1d(hopSize *
sizeof(
float));
521 for(n=0; n<hopSize; n++){
522 h->fadeIn[n] = (float) n / (
float) (hopSize-1);
523 h->fadeOut[n] = (float) (hopSize-1-n) / (float) (hopSize-1);
526 for(np=0; np<nIRs; np++){
527 for(no=0; no<nCHout; no++){
528 h->Hpart_f[np][no] =
malloc1d(h->numFilterBlocks*(h->nBins)*
sizeof(float_complex));
529 memcpy(h_pad, &H[np][no*length_h], length_h*
sizeof(
float));
530 for (nb=0; nb<h->numFilterBlocks; nb++){
531 memcpy(h_pad_2hops, &(h_pad[nb*hopSize]), hopSize*
sizeof(
float));
532 saf_rfft_forward(h->hFFT, h_pad_2hops, &(h->Hpart_f[np][no][nb*(h->nBins)]));
558 free(h->y_n_overlap);
559 free(h->y_n_overlap_last);
566 for(np=0; np<h->nIRs; np++){
567 for(no=0; no<h->nCHout; no++)
568 free(h->Hpart_f[np][no]);
589 memmove(&(h->X_n[1*(h->nBins)]), h->X_n, (h->numFilterBlocks-1)*(h->nBins)*
sizeof(float_complex));
591 cblas_scopy(h->hopSize, inputSig, 1, h->x_pad, 1);
595 for(no=0; no<h->nCHout; no++){
596 utility_cvvmul(h->Hpart_f[irIdx][no], h->X_n, h->numFilterBlocks * (h->nBins), h->HX_n);
597 for(nb=0; nb<h->numFilterBlocks; nb++)
598 saf_rfft_backward(h->hFFT, &(h->HX_n[nb*(h->nBins)]), &(h->hx_n[nb*(h->fftSize)]));
601 memset(h->z_n, 0, (h->fftSize) *
sizeof(
float));
602 for(nb=0; nb<h->numFilterBlocks; nb++)
603 cblas_saxpy(h->fftSize, 1.0f, &(h->hx_n[nb*(h->fftSize)]), 1, h->z_n, 1);
606 if(irIdx != h->posIdx_last){
607 utility_cvvmul(h->Hpart_f[h->posIdx_last][no], h->X_n, h->numFilterBlocks * (h->nBins), h->HX_n);
608 for(nb=0; nb<h->numFilterBlocks; nb++)
609 saf_rfft_backward(h->hFFT, &(h->HX_n[nb*(h->nBins)]), &(h->hx_n[nb*(h->fftSize)]));
612 memset(h->z_n_last, 0, (h->fftSize) *
sizeof(
float));
613 for(nb=0; nb<h->numFilterBlocks; nb++)
614 cblas_saxpy(h->fftSize, 1.0f, &(h->hx_n[nb*(h->fftSize)]), 1, h->z_n_last, 1);
619 if(h->posIdx_last != h->posIdx_last2){
620 utility_cvvmul(h->Hpart_f[h->posIdx_last2][no], h->X_n, h->numFilterBlocks * (h->nBins), h->HX_n);
621 for(nb=0; nb<h->numFilterBlocks; nb++)
622 saf_rfft_backward(h->hFFT, &(h->HX_n[nb*(h->nBins)]), &(h->hx_n[nb*(h->fftSize)]));
625 memset(h->z_n_last2, 0, (h->fftSize) *
sizeof(
float));
626 for(nb=0; nb<h->numFilterBlocks; nb++)
627 cblas_saxpy(h->fftSize, 1.0f, &(h->hx_n[nb*(h->fftSize)]), 1, h->z_n_last2, 1);
634 utility_svvadd(h->z_n_last, (
const float*)&(h->y_n_overlap[no*(h->hopSize)]), h->hopSize, h->out1);
635 utility_svvadd(h->z_n_last2, (
const float*)&(h->y_n_overlap_last[no*(h->hopSize)]), h->hopSize, h->out2);
637 utility_svvmul(h->out1, (
const float*)h->fadeIn, h->hopSize, h->outFadeIn);
638 utility_svvmul(h->out2, (
const float*)h->fadeOut, h->hopSize, h->outFadeOut);
640 utility_svvadd(h->outFadeIn, (
const float*)h->outFadeOut, h->hopSize, &(outputSig[no*(h->hopSize)]));
643 cblas_scopy(h->hopSize, &(h->z_n[h->hopSize]), 1, &(h->y_n_overlap[no*(h->hopSize)]), 1);
644 cblas_scopy(h->hopSize, &(h->z_n_last[h->hopSize]), 1, &(h->y_n_overlap_last[no*(h->hopSize)]), 1);
647 h->posIdx_last2 = h->posIdx_last;
648 h->posIdx_last = irIdx;
void saf_multiConv_destroy(void **const phMC)
Destroys an instance of multiConv.
void saf_matrixConv_apply(void *const hMC, float *inputSig, float *outputSig)
Performs the matrix convolution.
#define saf_assert(x, message)
Macro to make an assertion, along with a string explaining its purpose.
void saf_TVConv_apply(void *const hTVC, float *inputSig, float *outputSig, int irIdx)
Performs the matrix convolution.
void utility_cvvmul(const float_complex *a, const float_complex *b, const int len, float_complex *c)
Single-precision, complex, element-wise vector-vector multiplication i.e.
void utility_svvmul(const float *a, const float *b, const int len, float *c)
Single-precision, element-wise vector-vector multiplication i.e.
void saf_multiConv_apply(void *const hMC, float *inputSig, float *outputSig)
Performs the multi-channel convolution.
void saf_multiConv_reset(void *const hMC)
Flushes internal buffers with zeros.
void saf_matrixConv_create(void **const phMC, int hopSize, float *H, int length_h, int nCHin, int nCHout, int usePartFLAG)
Creates an instance of matrixConv.
void saf_TVConv_create(void **const phTVC, int hopSize, float **H, int length_h, int nIRs, int nCHout, int initIdx)
Creates an instance of TVConv.
void utility_svvcopy(const float *a, const int len, float *c)
Single-precision, vector-vector copy, i.e.
void saf_rfft_create(void **const phFFT, int N)
Creates an instance of saf_rfft; real<->half-complex (conjugate-symmetric) FFT.
void saf_multiConv_create(void **const phMC, int hopSize, float *H, int length_h, int nCH, int usePartFLAG)
Creates an instance of multiConv.
void saf_TVConv_destroy(void **const phTVC)
Destroys an instance of matrixConv.
void saf_matrixConv_destroy(void **const phMC)
Destroys an instance of matrixConv.
void saf_rfft_forward(void *const hFFT, float *inputTD, float_complex *outputFD)
Performs the forward-FFT operation; use for real to complex (conjugate symmetric) transformations.
void saf_rfft_backward(void *const hFFT, float_complex *inputFD, float *outputTD)
Performs the backward-FFT operation; use for complex (conjugate symmetric) to real transformations.
void saf_rfft_destroy(void **const phFFT)
Destroys an instance of saf_rfft.
void utility_svvadd(const float *a, const float *b, const int len, float *c)
Single-precision, vector-vector addition, i.e.
void saf_matrixConv_reset(void *const hMC)
Flushes internal buffers with zeros.
void ** malloc2d(size_t dim1, size_t dim2, size_t data_size)
2-D malloc (contiguously allocated, so use free() as usual to deallocate)
void * malloc1d(size_t dim1_data_size)
1-D malloc (same as malloc, but with error checking)
void * calloc1d(size_t dim1, size_t data_size)
1-D calloc (same as calloc, but with error checking)
Include header for SAF externals.
Main header for the utilities module (SAF_UTILITIES_MODULE)
Data structure for the matrix convolver.
Data structure for the multi-channel convolver.
Data structure for the time-varying convolver.