40#if defined(SAF_USE_APPLE_ACCELERATE_LP64) || defined(SAF_USE_APPLE_ACCELERATE_ILP64)
41# include "AvailabilityVersions.h"
43# define SAF_USE_INTERLEAVED_VDSP
48typedef struct _saf_stft_data {
49 int winsize, hopsize, fftsize, nCHin, nCHout, nBands;
51 int numOvrlpAddBlocks, bufferlength, nPrevHops;
52 float* window, *insig_rect_win, *insig_win, *outsig_win;
53 float** overlapAddBuffer;
55 float_complex* tmp_fft;
61typedef struct _saf_rfft_data {
65#if defined(SAF_USE_FFTW)
70 fftwf_complex* fwd_bufferFD;
71 fftwf_complex* bwd_bufferFD;
72#elif defined(SAF_USE_INTEL_IPP)
74 int specSize, specBufferSize, bufferSize, log2n;
75 IppsDFTSpec_R_32f* hDFTspec;
76 IppsFFTSpec_R_32f* hFFTspec;
80#elif defined(SAF_USE_APPLE_ACCELERATE_LP64) || defined(SAF_USE_APPLE_ACCELERATE_ILP64)
81# ifdef SAF_USE_INTERLEAVED_VDSP
82 vDSP_DFT_Interleaved_Setup DFT_fwd;
83 vDSP_DFT_Interleaved_Setup DFT_bwd;
86 vDSP_DFT_Setup DFT_fwd;
87 vDSP_DFT_Setup DFT_bwd;
88 DSPSplitComplex VDSP_split;
89 DSPSplitComplex VDSP_split_tmp;
91#elif defined(SAF_USE_INTEL_MKL_LP64) || defined(SAF_USE_INTEL_MKL_ILP64)
92 DFTI_DESCRIPTOR_HANDLE MKL_FFT_Handle;
93 MKL_LONG input_strides[2], output_strides[2], Status;
96 kiss_fftr_cfg kissFFThandle_fwd;
97 kiss_fftr_cfg kissFFThandle_bkw;
102typedef struct _saf_fft_data {
106#if defined(SAF_USE_FFTW)
109 fftwf_complex* fwd_bufferTD;
110 fftwf_complex* bwd_bufferTD;
111 fftwf_complex* fwd_bufferFD;
112 fftwf_complex* bwd_bufferFD;
113#elif defined(SAF_USE_INTEL_IPP)
115 int specSize, specBufferSize, bufferSize, log2n;
116 IppsDFTSpec_C_32fc* hDFTspec;
117 IppsFFTSpec_C_32fc* hFFTspec;
121#elif defined(SAF_USE_APPLE_ACCELERATE_LP64) || defined(SAF_USE_APPLE_ACCELERATE_ILP64)
122# ifdef SAF_USE_INTERLEAVED_VDSP
123 vDSP_DFT_Interleaved_Setup DFT_fwd;
124 vDSP_DFT_Interleaved_Setup DFT_bwd;
126 vDSP_DFT_Setup DFT_fwd;
127 vDSP_DFT_Setup DFT_bwd;
128 DSPSplitComplex VDSP_split;
129 DSPSplitComplex VDSP_split_tmp;
131#elif defined(SAF_USE_INTEL_MKL_LP64) || defined(SAF_USE_INTEL_MKL_ILP64)
132 DFTI_DESCRIPTOR_HANDLE MKL_FFT_Handle;
136 kiss_fft_cfg kissFFThandle_fwd;
137 kiss_fft_cfg kissFFThandle_bkw;
154 for(k=0; k<fftSize/2+1; k++)
155 freqVector[k] = (
float)k * fs/(float)fftSize;
168 int i, y_len, fftSize, nBins;
170 float_complex* H, *X, *Y;
174 y_len = x_len + h_len - 1;
175 fftSize = (int)((
float)
nextpow2(y_len)+0.5f);
177 h0 =
calloc1d(fftSize,
sizeof(
float));
178 x0 =
calloc1d(fftSize,
sizeof(
float));
179 y0 =
malloc1d(fftSize *
sizeof(
float));
180 H =
malloc1d(nBins*
sizeof(float_complex));
181 X =
malloc1d(nBins*
sizeof(float_complex));
182 Y =
malloc1d(nBins*
sizeof(float_complex));
186 for(i=0; i<nCH; i++){
188 memcpy(h0, &h[i*h_len], h_len*
sizeof(
float));
189 memcpy(x0, &x[i*x_len], x_len*
sizeof(
float));
198 memcpy(&y[i*y_len], y0, y_len*
sizeof(
float));
224 y_tmp =
malloc1d(nCH*(x_len+h_len-1)*
sizeof(
float));
225 fftconv(x, h, x_len, h_len, nCH, y_tmp);
227 memcpy(&y[i*x_len], &y_tmp[i*(x_len+h_len-1)], x_len*
sizeof(
float));
238#if defined(SAF_USE_INTEL_IPP) && 0
239 IppsHilbertSpec* ippSpec;
244 saf_assert(!ippsHilbertGetSize_32f32fc(x_len, ippAlgHintNone, &ippSpecSize, &ippBufferSize),
"IPP error!");
245 ippSpec = (IppsHilbertSpec*)ippsMalloc_8u(ippSpecSize);
246 buffer = ippsMalloc_8u(ippBufferSize);
247 saf_assert(!ippsHilbertInit_32f32fc(x_len, ippAlgHintNone, ippSpec, buffer),
"IPP error!");
248 saf_assert(!ippsHilbert_32f32fc(x, (Ipp32fc*)y, ippSpec, buffer),
"IPP error!");
254 float_complex *xfft, *h, *xhfft;
258 xfft =
malloc1d(x_len*
sizeof(float_complex));
259 h =
malloc1d(x_len*
sizeof(float_complex));
260 xhfft =
malloc1d(x_len*
sizeof(float_complex));
266 memset(h, 0,
sizeof(float_complex)*x_len);
269 h[0] = cmplxf(1.0f, 0.0f);
270 h[x_len/2] = cmplxf(1.0f, 0.0f);
271 for(i=1;i<x_len/2;i++)
272 h[i] = cmplxf(2.0f, 0.0f);
275 saf_assert(x_len % 2 == 0,
"Uneven lengths are not supported by saf_fft");
277 h[0] = cmplxf(1.0f, 0.0f);
278 for(i=1;i<(x_len+1)/2;i++)
279 h[i] = cmplxf(2.0f, 0.0f);
300 void **
const phSTFT,
313 h->winsize = winsize;
314 h->hopsize = hopsize;
315 h->nBands = winsize+1;
316 h->FDformat = FDformat;
319 h->fftsize = 2*winsize;
321 h->insig_rect_win =
calloc1d(h->fftsize,
sizeof(
float));
322 h->insig_win =
calloc1d(h->fftsize,
sizeof(
float));
325 h->tmp_fft =
malloc1d(h->nBands *
sizeof(float_complex));
326 h->outsig_win =
malloc1d(h->fftsize*
sizeof(
float));
327 h->nPrevHops = winsize/hopsize-1;
329 h->prev_inhops = (
float***)
calloc3d(h->nPrevHops, nCHin, hopsize,
sizeof(
float));
331 h->prev_inhops = NULL;
337 h->window =
malloc1d(winsize*
sizeof(
float));
342 h->numOvrlpAddBlocks = winsize/hopsize;
343 h->bufferlength = h->numOvrlpAddBlocks * (h->fftsize);
344 h->overlapAddBuffer = (
float**)
calloc2d(nCHout, h->bufferlength,
sizeof(
float));
356 free(h->overlapAddBuffer);
357 free(h->insig_rect_win);
360 free(h->prev_inhops);
372 float_complex*** dataFD
377 int ch, j, nHops, t, band, idx, hIdx;
379 saf_assert(framesize % h->hopsize == 0,
"framesize must be multiple of hopsize");
380 nHops = framesize/h->hopsize;
384 if(h->winsize==h->hopsize){
385 for (t = 0; t<nHops; t++){
386 for(ch=0; ch < h->nCHin; ch++){
388 memcpy(h->insig_rect_win, &dataTD[ch][t*(h->hopsize)], h->winsize*
sizeof(
float));
398 for(band=0; band<h->nBands; band++)
399 dataFD[band][ch][t] = h->tmp_fft[band];
408 for (t = 0; t<nHops; t++){
409 for(ch=0; ch < h->nCHin; ch++){
412 while (hIdx < h->winsize){
413 memcpy(&(h->insig_rect_win[hIdx]), h->prev_inhops[0][ch], h->hopsize*
sizeof(
float));
414 for(j=0; j< h->nPrevHops-1; j++)
415 memcpy(h->prev_inhops[j][ch], h->prev_inhops[j+1][ch], h->hopsize*
sizeof(
float));
416 memcpy(h->prev_inhops[h->nPrevHops-1][ch], &dataTD[ch][idx], h->hopsize*
sizeof(
float));
419 utility_svvmul(h->insig_rect_win, h->window, h->winsize, h->insig_win);
429 for(band=0; band<h->nBands; band++)
430 dataFD[band][ch][t] = h->tmp_fft[band];
442 float_complex*** dataFD,
448 int t, ch, nHops, band;
450 saf_assert(framesize % h->hopsize == 0,
"framesize must be multiple of hopsize");
451 nHops = framesize/h->hopsize;
453 for (t = 0; t<nHops; t++){
454 for(ch=0; ch < h->nCHout; ch++){
456 memcpy(h->overlapAddBuffer[ch], h->overlapAddBuffer[ch] + h->hopsize, (h->numOvrlpAddBlocks-1)*(h->hopsize)*
sizeof(
float));
459 memset(h->overlapAddBuffer[ch] + (h->numOvrlpAddBlocks-1)*(h->hopsize), 0, h->hopsize*
sizeof(
float));
467 for(band=0; band<h->nBands; band++)
468 h->tmp_fft[band] = dataFD[band][ch][t];
474 cblas_saxpy(h->fftsize, 1.0f, h->outsig_win, 1, h->overlapAddBuffer[ch], 1);
475 memcpy(dataTD[ch] + t*(h->hopsize), h->overlapAddBuffer[ch], h->hopsize*
sizeof(
float));
487 memset(
FLATTEN3D(h->prev_inhops), 0, h->nPrevHops * (h->nCHin) * (h->hopsize) *
sizeof(
float));
488 memset(
FLATTEN2D(h->overlapAddBuffer), 0, h->nCHout * (h->bufferlength) *
sizeof(
float));
501 if(new_nCHin != h->nCHin && h->nPrevHops > 0){
504 h->prev_inhops = (
float***)
realloc3d_r((
void***)h->prev_inhops, h->nPrevHops, new_nCHin, h->hopsize,
505 h->nPrevHops, h->nCHin, h->hopsize,
sizeof(
float));
507 for(i=0; i< h->nPrevHops; i++)
508 for(ch=h->nCHin; ch<new_nCHin; ch++)
509 memset(h->prev_inhops[i][ch], 0, h->hopsize *
sizeof(
float));
511 h->nCHin = new_nCHin;
514 if(new_nCHout != h->nCHout){
517 h->overlapAddBuffer = (
float**)
realloc2d_r((
void**)h->overlapAddBuffer, new_nCHout, h->bufferlength,
518 h->nCHout, h->bufferlength,
sizeof(
float));
520 for(ch=h->nCHout; ch<new_nCHout; ch++)
521 memset(h->overlapAddBuffer[ch], 0, h->bufferlength *
sizeof(
float));
523 h->nCHout = new_nCHout;
542 h->Scale = 1.0f/(float)N;
543 saf_assert(N>=2 &&
ISEVEN(N),
"Only even (non zero) FFT sizes are supported");
544 h->useKissFFT_FLAG = 0;
545#if defined(SAF_USE_FFTW)
546 h->fwd_bufferTD =
malloc1d(h->N*
sizeof(
float));
547 h->bwd_bufferTD =
malloc1d(h->N*
sizeof(
float));
548 h->fwd_bufferFD =
malloc1d((h->N/2+1)*
sizeof(fftwf_complex));
549 h->bwd_bufferFD =
malloc1d((h->N/2+1)*
sizeof(fftwf_complex));
550 h->p_fwd = fftwf_plan_dft_r2c_1d(h->N, h->fwd_bufferTD, h->fwd_bufferFD, FFTW_ESTIMATE);
551 h->p_bwd = fftwf_plan_dft_c2r_1d(h->N, h->bwd_bufferFD, h->bwd_bufferTD, FFTW_ESTIMATE);
552#elif defined(SAF_USE_INTEL_IPP)
554 if((
int)(log2f((
float)N)+1.0f) == (
int)(log2f((
float)N))){
555 h->useIPPfft_FLAG = 1;
556 h->log2n = (int)(log2f((
float)N)+0.1f);
557 ippsFFTGetSize_R_32f(h->log2n, IPP_FFT_DIV_INV_BY_N, ippAlgHintNone, &(h->specSize), &(h->specBufferSize), &(h->bufferSize));
559 h->memSpec = (Ipp8u*) ippMalloc(h->specSize);
560 h->buffer = (Ipp8u*) ippMalloc(h->bufferSize);
561 h->memInit = (Ipp8u*) ippMalloc(h->specBufferSize);
562 ippsFFTInit_R_32f(&(h->hFFTspec), h->log2n, IPP_FFT_DIV_INV_BY_N, ippAlgHintNone, h->memSpec, h->memInit);
565 h->useIPPfft_FLAG = 0;
566 ippsDFTGetSize_R_32f(N, IPP_FFT_DIV_INV_BY_N, ippAlgHintNone, &(h->specSize), &(h->specBufferSize), &(h->bufferSize));
567 h->hDFTspec = (IppsDFTSpec_R_32f*) ippMalloc(h->specSize);
568 h->buffer = (Ipp8u*) ippMalloc(h->bufferSize);
569 h->memInit = (Ipp8u*) ippMalloc(h->specBufferSize);
570 ippsDFTInit_R_32f(N, IPP_FFT_DIV_INV_BY_N, ippAlgHintNone, h->hDFTspec, h->memInit);
574#elif defined(SAF_USE_APPLE_ACCELERATE_LP64) || defined(SAF_USE_APPLE_ACCELERATE_ILP64)
575# ifdef SAF_USE_INTERLEAVED_VDSP
576 h->DFT_fwd = vDSP_DFT_Interleaved_CreateSetup(0, N/2, vDSP_DFT_FORWARD, vDSP_DFT_Interleaved_RealtoComplex);
577 h->DFT_bwd = vDSP_DFT_Interleaved_CreateSetup(0, N/2, vDSP_DFT_INVERSE, vDSP_DFT_Interleaved_RealtoComplex);
579 h->DFT_fwd = vDSP_DFT_zrop_CreateSetup(0, N, vDSP_DFT_FORWARD);
580 h->DFT_bwd = vDSP_DFT_zrop_CreateSetup(0, N, vDSP_DFT_INVERSE);
582 if(h->DFT_fwd==0 || h->DFT_bwd==0)
583 h->useKissFFT_FLAG = 1;
586 saf_assert(h->DFT_fwd!=0 && h->DFT_bwd!=0,
"Failed to create vDSP DFT");
587# ifdef SAF_USE_INTERLEAVED_VDSP
588 h->tempBuffer =
malloc1d(2*(h->N/2+1)*
sizeof(
float));
590 h->VDSP_split_tmp.realp =
malloc1d((h->N/2)*
sizeof(
float));
591 h->VDSP_split_tmp.imagp =
malloc1d((h->N/2)*
sizeof(
float));
592 h->VDSP_split.realp =
malloc1d((h->N/2)*
sizeof(
float));
593 h->VDSP_split.imagp =
malloc1d((h->N/2)*
sizeof(
float));
596#elif defined(SAF_USE_INTEL_MKL_LP64) || defined(SAF_USE_INTEL_MKL_ILP64)
597 h->MKL_FFT_Handle = 0;
598 h->Status = DftiCreateDescriptor(&(h->MKL_FFT_Handle), DFTI_SINGLE, DFTI_REAL, 1, h->N);
599 h->Status = DftiSetValue(h->MKL_FFT_Handle, DFTI_PLACEMENT, DFTI_NOT_INPLACE);
603 h->Status = DftiSetValue(h->MKL_FFT_Handle, DFTI_CONJUGATE_EVEN_STORAGE, DFTI_COMPLEX_COMPLEX);
605 h->Status = DftiSetValue(h->MKL_FFT_Handle, DFTI_BACKWARD_SCALE, h->Scale);
607 h->Status = DftiCommitDescriptor(h->MKL_FFT_Handle);
610 h->useKissFFT_FLAG = 1;
613 if(h->useKissFFT_FLAG){
614 h->kissFFThandle_fwd = kiss_fftr_alloc(h->N, 0, NULL, NULL);
615 h->kissFFThandle_bkw = kiss_fftr_alloc(h->N, 1, NULL, NULL);
626#if defined(SAF_USE_FFTW)
627 free(h->fwd_bufferTD);
628 free(h->bwd_bufferTD);
629 free(h->fwd_bufferFD);
630 free(h->bwd_bufferFD);
631 fftwf_destroy_plan(h->p_bwd);
632 fftwf_destroy_plan(h->p_fwd);
633#elif defined(SAF_USE_INTEL_IPP)
634 if(h->useIPPfft_FLAG){
640 ippFree(h->hDFTspec);
644#elif defined(SAF_USE_APPLE_ACCELERATE_LP64) || defined(SAF_USE_APPLE_ACCELERATE_ILP64)
645 if(!h->useKissFFT_FLAG){
646# ifdef SAF_USE_INTERLEAVED_VDSP
647 vDSP_DFT_Interleaved_DestroySetup(h->DFT_fwd);
648 vDSP_DFT_Interleaved_DestroySetup(h->DFT_bwd);
651 vDSP_DFT_DestroySetup(h->DFT_fwd);
652 vDSP_DFT_DestroySetup(h->DFT_bwd);
653 free(h->VDSP_split_tmp.realp);
654 free(h->VDSP_split_tmp.imagp);
655 free(h->VDSP_split.realp);
656 free(h->VDSP_split.imagp);
659#elif defined(SAF_USE_INTEL_MKL_LP64) || defined(SAF_USE_INTEL_MKL_ILP64)
660 h->Status = DftiFreeDescriptor(&(h->MKL_FFT_Handle));
662 if(h->useKissFFT_FLAG){
663 kiss_fftr_free(h->kissFFThandle_fwd);
664 kiss_fftr_free(h->kissFFThandle_bkw);
677 float_complex* outputFD
682#if defined(SAF_USE_FFTW)
683 cblas_scopy(h->N, inputTD, 1, h->fwd_bufferTD, 1);
684 fftwf_execute(h->p_fwd);
685 cblas_ccopy(h->N/2+1, h->fwd_bufferFD, 1, outputFD, 1);
686#elif defined(SAF_USE_INTEL_IPP)
687 if(h->useIPPfft_FLAG)
688 ippsFFTFwd_RToCCS_32f((Ipp32f*)inputTD, (Ipp32f*)outputFD, h->hFFTspec, h->buffer);
690 ippsDFTFwd_RToCCS_32f((Ipp32f*)inputTD, (Ipp32f*)outputFD, h->hDFTspec, h->buffer);
691#elif defined(SAF_USE_APPLE_ACCELERATE_LP64) || defined(SAF_USE_APPLE_ACCELERATE_ILP64)
692 if(!h->useKissFFT_FLAG){
693# ifdef SAF_USE_INTERLEAVED_VDSP
694 vDSP_DFT_Interleaved_Execute(h->DFT_fwd, (DSPComplex*)inputTD, (DSPComplex*)outputFD);
695 outputFD[h->N/2] = cmplxf(((
float*)(&outputFD[0]))[1], 0.0f);
696 outputFD[0] = cmplxf(((
float*)(&outputFD[0]))[0], 0.0f);
698 vDSP_ctoz((DSPComplex*)inputTD, 2, &(h->VDSP_split_tmp), 1, (h->N)/2);
699 vDSP_DFT_Execute(h->DFT_fwd, h->VDSP_split_tmp.realp, h->VDSP_split_tmp.imagp, h->VDSP_split.realp, h->VDSP_split.imagp);
701 outputFD[0] = cmplxf(h->VDSP_split.realp[0], 0.0f);
702 cblas_scopy(h->N/2-1, &h->VDSP_split.realp[1], 1, &((
float*)(outputFD))[2], 2);
703 cblas_scopy(h->N/2-1, &h->VDSP_split.imagp[1], 1, &((
float*)(outputFD))[3], 2);
706 outputFD[h->N/2] = cmplxf(h->VDSP_split.imagp[0], 0.0f);
711 cblas_sscal(2*(h->N/2+1), 0.5f, (
float*)outputFD, 1);
713#elif defined(SAF_USE_INTEL_MKL_LP64) || defined(SAF_USE_INTEL_MKL_ILP64)
714 h->Status = DftiComputeForward(h->MKL_FFT_Handle, inputTD, outputFD);
716 if(h->useKissFFT_FLAG)
717 kiss_fftr(h->kissFFThandle_fwd, inputTD, (
kiss_fft_cpx*)outputFD);
723 float_complex* inputFD,
729#if defined(SAF_USE_FFTW)
730 cblas_ccopy(h->N/2+1, inputFD, 1, h->bwd_bufferFD, 1);
731 fftwf_execute(h->p_bwd);
732 cblas_scopy(h->N, h->bwd_bufferTD, 1, outputTD, 1);
733 cblas_sscal(h->N, h->Scale, outputTD, 1);
734#elif defined(SAF_USE_INTEL_IPP)
735 if(h->useIPPfft_FLAG)
736 ippsFFTInv_CCSToR_32f((Ipp32f*)inputFD, (Ipp32f*)outputTD, h->hFFTspec, h->buffer);
738 ippsDFTInv_CCSToR_32f((Ipp32f*)inputFD, (Ipp32f*)outputTD, h->hDFTspec, h->buffer);
739#elif defined(SAF_USE_APPLE_ACCELERATE_LP64) || defined(SAF_USE_APPLE_ACCELERATE_ILP64)
740 if(!h->useKissFFT_FLAG){
741# ifdef SAF_USE_INTERLEAVED_VDSP
742 memcpy(h->tempBuffer, inputFD, (h->N/2+1)*
sizeof(float_complex));
743 h->tempBuffer[1] = crealf(inputFD[h->N/2]);
744 vDSP_DFT_Interleaved_Execute(h->DFT_bwd, (DSPComplex*)h->tempBuffer, (DSPComplex*)outputTD);
746 h->VDSP_split_tmp.realp[0] = crealf(inputFD[0]);
747 h->VDSP_split_tmp.imagp[0] = crealf(inputFD[h->N/2]);
748 cblas_scopy(h->N/2-1, &((
float*)(inputFD))[2], 2, &h->VDSP_split_tmp.realp[1], 1);
749 cblas_scopy(h->N/2-1, &((
float*)(inputFD))[3], 2, &h->VDSP_split_tmp.imagp[1], 1);
750 vDSP_DFT_Execute(h->DFT_bwd, h->VDSP_split_tmp.realp, h->VDSP_split_tmp.imagp, h->VDSP_split.realp, h->VDSP_split.imagp);
751 vDSP_ztoc(&(h->VDSP_split), 1, (DSPComplex*)outputTD, 2, (h->N)/2);
754 vDSP_vsmul(outputTD, 1, &(h->Scale), outputTD, 1, h->N);
756#elif defined(SAF_USE_INTEL_MKL_LP64) || defined(SAF_USE_INTEL_MKL_ILP64)
757 h->Status = DftiComputeBackward(h->MKL_FFT_Handle, inputFD, outputTD);
759 if(h->useKissFFT_FLAG){
760 kiss_fftri(h->kissFFThandle_bkw, (
kiss_fft_cpx*)inputFD, outputTD);
761 cblas_sscal(h->N, 1.0f/(
float)(h->N), outputTD, 1);
780 h->Scale = 1.0f/(float)N;
781 saf_assert(N>=2,
"Only even (non zero) FFT sizes are supported");
782 h->useKissFFT_FLAG = 0;
783#if defined(SAF_USE_FFTW)
784 h->fwd_bufferTD =
malloc1d(h->N*
sizeof(fftwf_complex));
785 h->bwd_bufferTD =
malloc1d(h->N*
sizeof(fftwf_complex));
786 h->fwd_bufferFD =
malloc1d(h->N*
sizeof(fftwf_complex));
787 h->bwd_bufferFD =
malloc1d(h->N*
sizeof(fftwf_complex));
788 h->p_fwd = fftwf_plan_dft_1d(h->N, h->fwd_bufferTD, h->fwd_bufferFD, FFTW_FORWARD, FFTW_ESTIMATE);
789 h->p_bwd = fftwf_plan_dft_1d(h->N, h->bwd_bufferFD, h->bwd_bufferTD, FFTW_BACKWARD, FFTW_ESTIMATE);
790#elif defined(SAF_USE_INTEL_IPP)
792 if((
int)(log2f((
float)N) + 1.0f) == (
int)(log2f((
float)N))){
793 h->useIPPfft_FLAG = 1;
794 h->log2n = (int)(log2f((
float)N)+0.1f);
795 ippsFFTGetSize_C_32fc(h->log2n, IPP_FFT_DIV_INV_BY_N, ippAlgHintNone, &(h->specSize), &(h->specBufferSize), &(h->bufferSize));
797 h->memSpec = (Ipp8u*)ippMalloc(h->specSize);
798 h->buffer = (Ipp8u*)ippMalloc(h->bufferSize);
799 h->memInit = (Ipp8u*)ippMalloc(h->specBufferSize);
800 ippsFFTInit_C_32fc(&(h->hFFTspec), h->log2n, IPP_FFT_DIV_INV_BY_N, ippAlgHintNone, h->memSpec, h->memInit);
803 h->useIPPfft_FLAG = 0;
804 ippsDFTGetSize_C_32fc(N, IPP_FFT_DIV_INV_BY_N, ippAlgHintNone, &(h->specSize), &(h->specBufferSize), &(h->bufferSize));
805 h->hDFTspec = (IppsDFTSpec_C_32fc*)ippMalloc(h->specSize);
806 h->buffer = (Ipp8u*)ippMalloc(h->bufferSize);
807 h->memInit = (Ipp8u*)ippMalloc(h->specBufferSize);
808 ippsDFTInit_C_32fc(N, IPP_FFT_DIV_INV_BY_N, ippAlgHintNone, h->hDFTspec, h->memInit);
812#elif defined(SAF_USE_APPLE_ACCELERATE_LP64) || defined(SAF_USE_APPLE_ACCELERATE_ILP64)
813# ifdef SAF_USE_INTERLEAVED_VDSP
814 h->DFT_fwd = vDSP_DFT_Interleaved_CreateSetup(0, N, vDSP_DFT_FORWARD, vDSP_DFT_Interleaved_ComplextoComplex);
815 h->DFT_bwd = vDSP_DFT_Interleaved_CreateSetup(0, N, vDSP_DFT_INVERSE, vDSP_DFT_Interleaved_ComplextoComplex);
817 h->DFT_fwd = vDSP_DFT_zop_CreateSetup(0, N, vDSP_DFT_FORWARD);
818 h->DFT_bwd = vDSP_DFT_zop_CreateSetup(0, N, vDSP_DFT_INVERSE);
820 if(h->DFT_fwd==0 || h->DFT_bwd==0)
821 h->useKissFFT_FLAG = 1;
824 saf_assert(h->DFT_fwd!=0 && h->DFT_bwd!=0,
"Failed to create vDSP DFT");
825# ifndef SAF_USE_INTERLEAVED_VDSP
826 h->VDSP_split_tmp.realp =
malloc1d((h->N)*
sizeof(
float));
827 h->VDSP_split_tmp.imagp =
malloc1d((h->N)*
sizeof(
float));
828 h->VDSP_split.realp =
malloc1d((h->N)*
sizeof(
float));
829 h->VDSP_split.imagp =
malloc1d((h->N)*
sizeof(
float));
832#elif defined(SAF_USE_INTEL_MKL_LP64) || defined(SAF_USE_INTEL_MKL_ILP64)
833 h->MKL_FFT_Handle = 0;
834 h->Status = DftiCreateDescriptor( &(h->MKL_FFT_Handle), DFTI_SINGLE,
835 DFTI_COMPLEX, 1, h->N);
836 h->Status = DftiSetValue(h->MKL_FFT_Handle, DFTI_PLACEMENT, DFTI_NOT_INPLACE);
838 h->Status = DftiSetValue(h->MKL_FFT_Handle, DFTI_BACKWARD_SCALE, h->Scale);
840 h->Status = DftiCommitDescriptor(h->MKL_FFT_Handle);
843 h->useKissFFT_FLAG = 1;
846 if(h->useKissFFT_FLAG){
860#if defined(SAF_USE_FFTW)
861 free(h->fwd_bufferTD);
862 free(h->bwd_bufferTD);
863 free(h->fwd_bufferFD);
864 free(h->bwd_bufferFD);
865 fftwf_destroy_plan(h->p_bwd);
866 fftwf_destroy_plan(h->p_fwd);
867#elif defined(SAF_USE_INTEL_IPP)
868 if(h->useIPPfft_FLAG){
874 ippFree(h->hDFTspec);
878#elif defined(SAF_USE_APPLE_ACCELERATE_LP64) || defined(SAF_USE_APPLE_ACCELERATE_ILP64)
879 if(!h->useKissFFT_FLAG){
880# ifdef SAF_USE_INTERLEAVED_VDSP
881 vDSP_DFT_Interleaved_DestroySetup(h->DFT_fwd);
882 vDSP_DFT_Interleaved_DestroySetup(h->DFT_bwd);
884 vDSP_DFT_DestroySetup(h->DFT_fwd);
885 vDSP_DFT_DestroySetup(h->DFT_bwd);
886 free(h->VDSP_split_tmp.realp);
887 free(h->VDSP_split_tmp.imagp);
888 free(h->VDSP_split.realp);
889 free(h->VDSP_split.imagp);
892#elif defined(SAF_USE_INTEL_MKL_LP64) || defined(SAF_USE_INTEL_MKL_ILP64)
893 h->Status = DftiFreeDescriptor(&(h->MKL_FFT_Handle));
895 if(h->useKissFFT_FLAG){
896 kiss_fft_free(h->kissFFThandle_fwd);
897 kiss_fft_free(h->kissFFThandle_bkw);
909 float_complex* inputTD,
910 float_complex* outputFD
915#if defined(SAF_USE_FFTW)
916 cblas_ccopy(h->N, inputTD, 1, h->fwd_bufferTD, 1);
917 fftwf_execute(h->p_fwd);
918 cblas_ccopy(h->N, h->fwd_bufferFD, 1, outputFD, 1);
919#elif defined(SAF_USE_INTEL_IPP)
920 if(h->useIPPfft_FLAG)
921 ippsFFTFwd_CToC_32fc((Ipp32fc*)inputTD, (Ipp32fc*)outputFD, h->hFFTspec, h->buffer);
923 ippsDFTFwd_CToC_32fc((Ipp32fc*)inputTD, (Ipp32fc*)outputFD, h->hDFTspec, h->buffer);
924#elif defined(SAF_USE_APPLE_ACCELERATE_LP64) || defined(SAF_USE_APPLE_ACCELERATE_ILP64)
925 if(!h->useKissFFT_FLAG){
926# ifdef SAF_USE_INTERLEAVED_VDSP
927 vDSP_DFT_Interleaved_Execute(h->DFT_fwd, (DSPComplex*)inputTD, (DSPComplex*)outputFD);
929 cblas_scopy(h->N, &((
float*)(inputTD))[0], 2, h->VDSP_split_tmp.realp, 1);
930 cblas_scopy(h->N, &((
float*)(inputTD))[1], 2, h->VDSP_split_tmp.imagp, 1);
931 vDSP_DFT_Execute(h->DFT_fwd, h->VDSP_split_tmp.realp, h->VDSP_split_tmp.imagp, h->VDSP_split.realp, h->VDSP_split.imagp);
932 cblas_scopy(h->N, h->VDSP_split.realp, 1, &((
float*)(outputFD))[0], 2);
933 cblas_scopy(h->N, h->VDSP_split.imagp, 1, &((
float*)(outputFD))[1], 2);
936#elif defined(SAF_USE_INTEL_MKL_LP64) || defined(SAF_USE_INTEL_MKL_ILP64)
937 h->Status = DftiComputeForward(h->MKL_FFT_Handle, inputTD, outputFD);
939 if(h->useKissFFT_FLAG)
946 float_complex* inputFD,
947 float_complex* outputTD
952#if defined(SAF_USE_FFTW)
953 cblas_ccopy(h->N, inputFD, 1, h->bwd_bufferFD, 1);
954 fftwf_execute(h->p_bwd);
955 cblas_ccopy(h->N, h->bwd_bufferTD, 1, outputTD, 1);
956 cblas_sscal(2 * h->N, h->Scale, (
float*)outputTD, 1);
957#elif defined(SAF_USE_INTEL_IPP)
958 if(h->useIPPfft_FLAG)
959 ippsFFTInv_CToC_32fc((Ipp32fc*)inputFD, (Ipp32fc*)outputTD, h->hFFTspec, h->buffer);
961 ippsDFTInv_CToC_32fc((Ipp32fc*)inputFD, (Ipp32fc*)outputTD, h->hDFTspec, h->buffer);
962#elif defined(SAF_USE_APPLE_ACCELERATE_LP64) || defined(SAF_USE_APPLE_ACCELERATE_ILP64)
963 if(!h->useKissFFT_FLAG){
964# ifdef SAF_USE_INTERLEAVED_VDSP
965 vDSP_DFT_Interleaved_Execute(h->DFT_bwd, (DSPComplex*)inputFD, (DSPComplex*)outputTD);
967 cblas_scopy(h->N, &((
float*)(inputFD))[0], 2, h->VDSP_split_tmp.realp, 1);
968 cblas_scopy(h->N, &((
float*)(inputFD))[1], 2, h->VDSP_split_tmp.imagp, 1);
969 vDSP_DFT_Execute(h->DFT_bwd, h->VDSP_split_tmp.realp, h->VDSP_split_tmp.imagp, h->VDSP_split.realp, h->VDSP_split.imagp);
970 cblas_scopy(h->N, h->VDSP_split.realp, 1, &((
float*)(outputTD))[0], 2);
971 cblas_scopy(h->N, h->VDSP_split.imagp, 1, &((
float*)(outputTD))[1], 2);
973 cblas_sscal(2*(h->N), 1.0f/(
float)(h->N), (
float*)outputTD, 1);
975#elif defined(SAF_USE_INTEL_MKL_LP64) || defined(SAF_USE_INTEL_MKL_ILP64)
976 h->Status = DftiComputeBackward(h->MKL_FFT_Handle, inputFD, outputTD);
978 if(h->useKissFFT_FLAG){
980 cblas_sscal(2*(h->N), 1.0f/(
float)(h->N), (
float*)outputTD, 1);
void fftfilt(float *x, float *h, int x_len, int h_len, int nCH, float *y)
FFT-based convolution for FIR filters.
void saf_stft_backward(void *const hSTFT, float_complex ***dataFD, int framesize, float **dataTD)
Performs the backward-STFT operation for the current frame.
#define saf_assert(x, message)
Macro to make an assertion, along with a string explaining its purpose.
void saf_stft_forward(void *const hSTFT, float **dataTD, int framesize, float_complex ***dataFD)
Performs the forward-STFT operation for the current frame.
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 fftconv(float *x, float *h, int x_len, int h_len, int nCH, float *y)
FFT-based convolution of signal 'x' with filter 'h'.
SAF_STFT_FDDATA_FORMAT
Options for how the frequency domain data is permuted when using saf_stft.
void saf_fft_backward(void *const hFFT, float_complex *inputFD, float_complex *outputTD)
Performs the backward-FFT operation; use for complex to complex transformations.
void saf_fft_create(void **const phFFT, int N)
Creates an instance of saf_fft; complex<->complex FFT.
void saf_stft_channelChange(void *const hSTFT, int new_nCHin, int new_nCHout)
Changes the number of input/output channels.
void hilbert(float_complex *x, int x_len, float_complex *y)
Computes the discrete-time analytic signal via the Hilbert transform [1].
void saf_rfft_create(void **const phFFT, int N)
Creates an instance of saf_rfft; real<->half-complex (conjugate-symmetric) FFT.
void getWindowingFunction(WINDOWING_FUNCTION_TYPES type, int winlength, float *win)
Computes the weights of a specific windowing function.
void saf_fft_forward(void *const hFFT, float_complex *inputTD, float_complex *outputFD)
Performs the forward-FFT operation; use for complex to complex transformations.
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 getUniformFreqVector(int fftSize, float fs, float *freqVector)
Calculates the frequencies (in Hz) of uniformly spaced bins, for a given FFT size and sampling rate.
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 saf_stft_destroy(void **const phSTFT)
Destroys an instance of saf_stft.
#define ISEVEN(n)
Returns 1 if "n" is even valued, and 0 if it is not.
int nextpow2(int numsamp)
A simple function which returns the next power of 2.
void saf_stft_flushBuffers(void *const hSTFT)
Flushes the internal buffers with zeros.
void saf_fft_destroy(void **const phFFT)
Destroys an instance of saf_fft.
void saf_stft_create(void **const phSTFT, int winsize, int hopsize, int nCHin, int nCHout, SAF_STFT_FDDATA_FORMAT FDformat)
Creates an instance of saf_stft.
@ WINDOWING_FUNCTION_HANN
Hann.
@ SAF_STFT_TIME_CH_BANDS
nTimeHops x nChannels x nBands
@ SAF_STFT_BANDS_CH_TIME
nBands x nChannels x nTimeHops
void kiss_fft(kiss_fft_cfg cfg, const kiss_fft_cpx *fin, kiss_fft_cpx *fout)
kiss_fft(cfg,in_out_buf)
kiss_fft_cfg kiss_fft_alloc(int nfft, int inverse_fft, void *mem, size_t *lenmem)
kiss_fft_alloc
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)
void *** realloc3d_r(void ***ptr, size_t new_dim1, size_t new_dim2, size_t new_dim3, size_t prev_dim1, size_t prev_dim2, size_t prev_dim3, size_t data_size)
3-D realloc which does retain previous data order
void ** realloc2d_r(void **ptr, size_t new_dim1, size_t new_dim2, size_t prev_dim1, size_t prev_dim2, size_t data_size)
2-D realloc which does retain previous data order
void ** calloc2d(size_t dim1, size_t dim2, size_t data_size)
2-D calloc (contiguously allocated, so use free() as usual to deallocate)
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)
#define FLATTEN2D(A)
Use this macro when passing a 2-D dynamic multi-dimensional array to memset, memcpy or any other func...
#define FLATTEN3D(A)
Use this macro when passing a 3-D dynamic multi-dimensional array to memset, memcpy or any other func...
Include header for SAF externals.
Main header for the utilities module (SAF_UTILITIES_MODULE)
Complex data type used by kissFFT.
Data structure for complex-complex FFT transforms.
Data structure for real-(half)complex FFT transforms.
Data structure for short-time Fourier transform.