SAF
Loading...
Searching...
No Matches
afSTFT_internal.c
Go to the documentation of this file.
1/*
2 Copyright (c) 2015 Juha Vilkamo
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21 */
22
50#include "afSTFT_internal.h"
51#include "afSTFT_protoFilter.h"
52
53/* ========================================================================== */
54/* Internal functions */
55/* ========================================================================== */
56
58(
59 void** handle,
60 int hopSize,
61 int inChannels,
62 int outChannels,
63 int LDmode,
64 int hybridMode
65)
66{
67 int k, ch, dsFactor;
68 float eq;
69
70 *handle = malloc(sizeof(afSTFTlib_internal_data));
71
72 /* Basic initializations */
74
75 h->inChannels = inChannels;
76 h->outChannels = outChannels;
77 h->hopSize = hopSize;
78 dsFactor = 1024/hopSize;
79 h->hLen = 10240/dsFactor;
80 h->totalHops=10;
81 h->hopIndexIn=0;
82 h->hopIndexOut=0;
83 h->LDmode = LDmode;
84 h->protoFilter = (float*)malloc(sizeof(float)*h->hLen);
85 h->protoFilterI = (float*)malloc(sizeof(float)*h->hLen);
86 h->inBuffer = (float**)malloc(sizeof(float*)*h->inChannels);
87 h->outBuffer = (float**)malloc(sizeof(float*)*h->outChannels);
88 h->fftProcessFrameTD = (float*)calloc(sizeof(float),h->hopSize*2);
89#ifdef AFSTFT_USE_SAF_UTILITIES
90 saf_rfft_create(&(h->hSafFFT), h->hopSize*2);
91 h->fftProcessFrameFD = calloc((h->hopSize+1), sizeof(float_complex));
92 h->tempHopBuffer = malloc(h->hopSize*sizeof(float));
93#else
94 switch (hopSize) {
95 case 32:
96 h->log2n=6;
97 break;
98 case 64:
99 h->log2n=7;
100 break;
101 case 128:
102 h->log2n=8;
103 break;
104 case 256:
105 h->log2n=9;
106 break;
107 case 512:
108 h->log2n=10;
109 break;
110 case 1024:
111 h->log2n=11;
112 break;
113 default:
114 // No other modes defined
115 return;
116 break;
117 }
118 h->fftProcessFrameFD = (float*)calloc(sizeof(float),(h->hopSize+1)*2);
119 vtInitFFT(&(h->vtFFT), h->fftProcessFrameTD, h->fftProcessFrameFD, h->log2n);
120#endif
121
122 /* Normalization to ensure 0dB gain */
123 if (h->LDmode==0) {
124#ifdef AFSTFT_USE_SAF_UTILITIES
125 eq = 2.0f/sqrtf(5.487604141f);
126#else
127 eq = 1.0f/sqrtf((float)h->hopSize*5.487604141f);
128#endif
129 for (k=0; k<h->hLen; k++) {
130 h->protoFilter[h->hLen-k-1] = __afSTFT_protoFilter1024[k*dsFactor]*eq;
131 h->protoFilterI[h->hLen-k-1] = __afSTFT_protoFilter1024[k*dsFactor]*eq;
132 }
133 }
134 else
135 {
136#ifdef AFSTFT_USE_SAF_UTILITIES
137 eq = 2.0f/sqrtf(4.544559956f);
138#else
139 eq = 1.0f/sqrtf((float)h->hopSize*4.544559956f);
140#endif
141 for (k=0; k<h->hLen; k++) {
142 h->protoFilter[h->hLen-k-1] = __afSTFT_protoFilter1024LD[k*dsFactor]*eq;
143 h->protoFilterI[k]=__afSTFT_protoFilter1024LD[k*dsFactor]*eq;
144 }
145 }
146 for(ch=0;ch<h->inChannels;ch++)
147 h->inBuffer[ch] = (float*)calloc(h->hLen,sizeof(float));
148
149 for(ch=0;ch<h->outChannels;ch++)
150 h->outBuffer[ch] = (float*)calloc(h->hLen,sizeof(float));
151
152 /* Initialize the hybrid filter memory etc. */
153 h->hybridMode=hybridMode;
154 if (h->hybridMode)
155 afHybridInit(&(h->h_afHybrid), h->hopSize, h->inChannels,h->outChannels);
156}
157
159(
160 void* handle,
161 int new_inChannels,
162 int new_outChannels
163)
164{
166 afHybrid *hyb_h = h->h_afHybrid;
167
168 int i, ch, sample;
169 if(h->inChannels!=new_inChannels){
170 for(i=new_inChannels; i<h->inChannels; i++)
171 free(h->inBuffer[i]);
172 h->inBuffer = (float**)realloc(h->inBuffer, sizeof(float*)*new_inChannels);
173 for(i=h->inChannels; i<new_inChannels; i++)
174 h->inBuffer[i] = (float*)calloc(h->hLen,sizeof(float));
175 }
176
177 if(h->outChannels!=new_outChannels){
178 for(i=new_outChannels; i<h->outChannels; i++)
179 free(h->outBuffer[i]);
180 h->outBuffer = (float**)realloc(h->outBuffer, sizeof(float*)*new_outChannels);
181 for(i=h->outChannels; i<new_outChannels; i++)
182 h->outBuffer[i] = (float*)calloc(h->hLen,sizeof(float));
183 }
184
185 if (h->hybridMode) {
186 hyb_h = h->h_afHybrid;
187 if (hyb_h->inChannels != new_inChannels) {
188 for (ch = new_inChannels; ch < hyb_h->inChannels; ch++) {
189 for (sample = 0; sample < 7; sample++) {
190 free(hyb_h->analysisBuffer[ch][sample].re);
191 free(hyb_h->analysisBuffer[ch][sample].im);
192 }
193 free(hyb_h->analysisBuffer[ch]);
194 }
195 hyb_h->analysisBuffer = (complexVector**) realloc(hyb_h->analysisBuffer, sizeof(complexVector*) * new_inChannels);
196 for (ch = hyb_h->inChannels; ch < new_inChannels; ch++) {
197 hyb_h->analysisBuffer[ch] = (complexVector*) malloc(sizeof(complexVector) * 7);
198 for (sample = 0; sample < 7; sample++) {
199 hyb_h->analysisBuffer[ch][sample].re = (float*) calloc(sizeof(float), h->hopSize + 1);
200 hyb_h->analysisBuffer[ch][sample].im = (float*) calloc(sizeof(float), h->hopSize + 1);
201 }
202 }
203 }
204 }
205 h->inChannels = new_inChannels;
206 h->outChannels = new_outChannels;
207 if (h->hybridMode){
208 hyb_h->inChannels = new_inChannels;
209 hyb_h->outChannels = new_outChannels;
210 }
211}
212
214(
215 void* handle
216)
217{
219 afHybrid *hyb_h = h->h_afHybrid;
220 int i, ch, sample;
221
222 for(i=0; i<h->inChannels; i++)
223 memset(h->inBuffer[i], 0, h->hLen*sizeof(float));
224 for(i=0; i<h->outChannels; i++)
225 memset(h->outBuffer[i], 0, h->hLen*sizeof(float));
226 if (h->hybridMode){
227 for(ch=0; ch<hyb_h->inChannels; ch++) {
228 for (sample=0;sample<7;sample++) {
229 memset(hyb_h->analysisBuffer[ch][sample].re, 0, sizeof(float)*(h->hopSize+1));
230 memset(hyb_h->analysisBuffer[ch][sample].im, 0, sizeof(float)*(h->hopSize+1));
231
232 }
233 }
234 }
235}
236
238(
239 void* handle,
240 float** inTD,
241 complexVector* outFD
242)
243{
245 int ch,k,hopIndex_this,hopIndex_this2;
246 float *p1,*p2,*p3;
247#ifndef AFSTFT_USE_SAF_UTILITIES
248 float *p4;
249#endif
250 int lr;
251
252 for (ch=0;ch<h->inChannels;ch++)
253 {
254 /* Copy the input frame into the memory buffer */
255 hopIndex_this2 = h->hopIndexIn;
256 p1=&(h->inBuffer[ch][hopIndex_this2*h->hopSize]);
257 p2=inTD[ch];
258 //memcpy((void*)p1,(void*)p2,sizeof(float)*(h->hopSize));
259 cblas_scopy(h->hopSize, p2, 1, p1, 1);
260
261 hopIndex_this2++;
262 if (hopIndex_this2 >= h->totalHops)
263 {
264 hopIndex_this2 = 0;
265 }
266
267 /* Apply prototype filter to the collected data in the memory buffer, and fold the result (for the FFT operation). */
268 p1 = h->fftProcessFrameTD;
269#ifdef AFSTFT_USE_SAF_UTILITIES
270 memset(p1, 0, h->hopSize*2*sizeof(float));
271#else
272 vtClr(p1, h->hopSize*2);
273#endif
274 lr=0; /* Left or right part of the frame */
275 hopIndex_this = hopIndex_this2;
276 for (k=0;k<h->totalHops;k++)
277 {
278 p1=&(h->inBuffer[ch][h->hopSize*hopIndex_this]);
279 p2=&(h->protoFilter[k*h->hopSize]);
280 if (lr==1)
281 {
282 p3=&(h->fftProcessFrameTD[h->hopSize]);
283 lr=0;
284 }
285 else
286 {
287 p3=&(h->fftProcessFrameTD[0]);
288 lr=1;
289 }
290#ifdef AFSTFT_USE_SAF_UTILITIES
291 utility_svvmul(p1, p2, h->hopSize, h->tempHopBuffer);
292 cblas_saxpy(h->hopSize, 1.0f, h->tempHopBuffer, 1, p3, 1);
293#else
294 vtVma(p1, p2, p3, h->hopSize); /* Vector multiply-add */
295#endif
296 hopIndex_this++;
297 if (hopIndex_this >= h->totalHops)
298 {
299 hopIndex_this = 0;
300 }
301 }
302
303 /* Apply FFT and copy the data to the output vector */
304#ifdef AFSTFT_USE_SAF_UTILITIES
305 saf_rfft_forward(h->hSafFFT, h->fftProcessFrameTD, h->fftProcessFrameFD);
306 cblas_scopy(h->hopSize+1, (float*)h->fftProcessFrameFD, 2, outFD[ch].re, 1);
307 cblas_scopy(h->hopSize+1, (float*)h->fftProcessFrameFD + 1, 2, outFD[ch].im, 1);
308#else
309 vtRunFFT(h->vtFFT,1);
310 outFD[ch].re[0]=h->fftProcessFrameFD[0];
311 outFD[ch].im[0]=0.0f; /* DC im = 0 */
312 outFD[ch].re[h->hopSize]=h->fftProcessFrameFD[h->hopSize];
313 outFD[ch].im[h->hopSize]=0.0f; /* Nyquist im = 0 */
314 p1 = outFD[ch].re + 1;
315 p2 = outFD[ch].im + 1;
316 p3 = h->fftProcessFrameFD + 1;
317 p4 = h->fftProcessFrameFD + 1 + h->hopSize;
318 memcpy((void*)p1,(void*)p3,sizeof(float)*(h->hopSize - 1));
319 memcpy((void*)p2,(void*)p4,sizeof(float)*(h->hopSize - 1));
320#endif
321 }
322 h->hopIndexIn++;
323 if (h->hopIndexIn >= h->totalHops)
324 {
325 h->hopIndexIn = 0;
326 }
327
328 /* Subdivide lowest bands with half-band filters if hybrid mode is enabled */
329 if (h->hybridMode)
330 {
331 afHybridForward(h->h_afHybrid, outFD);
332 }
333}
334
336(
337 void* handle,
338 complexVector* inFD,
339 float** outTD
340)
341{
343 int ch,k,hopIndex_this,hopIndex_this2;
344 float *p1,*p2,*p3;
345#ifndef AFSTFT_USE_SAF_UTILITIES
346 float *p4;
347#endif
348 int lr;
349
350 /* Combine subdivided lowest bands if hybrid mode is enabled */
351 if (h->hybridMode)
352 {
353 afHybridInverse(h->h_afHybrid, inFD);
354 }
355
356 for (ch=0;ch<h->outChannels;ch++)
357 {
358 /* Copy data from input to internal memory */
359 hopIndex_this2 = h->hopIndexOut;
360
361 /* Inverse FFT */
362#ifdef AFSTFT_USE_SAF_UTILITIES
363 cblas_scopy(h->hopSize+1, inFD[ch].re, 1, (float*)h->fftProcessFrameFD, 2);
364 cblas_scopy(h->hopSize+1, inFD[ch].im, 1, (float*)h->fftProcessFrameFD + 1, 2);
365
366 /* The low delay mode requires this procedure corresponding to the circular shift of the data in the time domain */
367 if (h->LDmode == 1)
368 for (k=1; k<h->hopSize; k+=2)
369 h->fftProcessFrameFD[k] = crmulf(h->fftProcessFrameFD[k], -1.0f);
370
371 saf_rfft_backward(h->hSafFFT, h->fftProcessFrameFD, h->fftProcessFrameTD);
372#else
373 h->fftProcessFrameFD[0] = inFD[ch].re[0]; /* DC */
374 h->fftProcessFrameFD[h->hopSize] = inFD[ch].re[h->hopSize]; /* Nyquist */
375 p1 = inFD[ch].re + 1;
376 p2 = inFD[ch].im + 1;
377 p3 = h->fftProcessFrameFD + 1;
378 p4 = h->fftProcessFrameFD + 1 + h->hopSize;
379 memcpy((void*)p3,(void*)p1,sizeof(float)*(h->hopSize - 1));
380 memcpy((void*)p4,(void*)p2,sizeof(float)*(h->hopSize - 1));
381
382 /* The low delay mode requires this procedure corresponding to the circular shift of the data in the time domain */
383 if (h->LDmode == 1) {
384 for (k=1;k<h->hopSize;k+=2) {
385 *p3 = -*p3;
386 *p4 = -*p4;
387 p3+=2;
388 p4+=2;
389 }
390 }
391
392 vtRunFFT(h->vtFFT, -1);
393#endif
394
395 /* Clear buffer at the pointer location and increment the pointer */
396 p1 = &(h->outBuffer[ch][hopIndex_this2*h->hopSize]);
397#ifdef AFSTFT_USE_SAF_UTILITIES
398 memset(p1, 0, h->hopSize*sizeof(float));
399#else
400 vtClr(p1,h->hopSize);
401#endif
402 hopIndex_this2++;
403 if (hopIndex_this2 >= h->totalHops)
404 {
405 hopIndex_this2=0;
406 }
407 hopIndex_this = hopIndex_this2;
408
409 lr=0; /* Left or right part of the frame */
410 for (k=0;k<h->totalHops;k++)
411 {
412 /* Apply the prototype filter to the repeated version of the IFFT'd data. */
413 p1=&(h->outBuffer[ch][h->hopSize*hopIndex_this]);
414 p2=&(h->protoFilterI[k*h->hopSize]);
415
416 if (lr==1)
417 {
418 p3=&(h->fftProcessFrameTD[h->hopSize]);
419 lr=0;
420 }
421 else
422 {
423 p3=&(h->fftProcessFrameTD[0]);
424 lr=1;
425 }
426
427 /* Overlap-add to the existing data in the memory buffer (from previous frames). */
428#ifdef AFSTFT_USE_SAF_UTILITIES
429 utility_svvmul(p2, p3, h->hopSize, h->tempHopBuffer);
430 cblas_saxpy(h->hopSize, 1.0f, h->tempHopBuffer, 1, p1, 1);
431#else
432 vtVma(p2, p3, p1, h->hopSize); /* Vector multiply-add */
433#endif
434 hopIndex_this++;
435 if (hopIndex_this >= h->totalHops)
436 {
437 hopIndex_this = 0;
438 }
439 }
440
441 /* Copy a frame from work memory to the output */
442 p1 = outTD[ch];
443 p2 = &(h->outBuffer[ch][h->hopSize*hopIndex_this]);
444 memcpy((void*)p1,(void*)p2,sizeof(float)*(h->hopSize));
445
446 }
447 h->hopIndexOut++;
448 if (h->hopIndexOut >= h->totalHops)
449 {
450 h->hopIndexOut=0;
451 }
452
453}
454
456(
457 void* handle
458)
459{
461 int ch;
462 if (h->hybridMode)
463 {
464 afHybridFree(h->h_afHybrid);
465 }
466 for(ch=0;ch<h->inChannels;ch++)
467 {
468 free(h->inBuffer[ch]);
469 }
470
471 for(ch=0;ch<h->outChannels;ch++)
472 {
473 free(h->outBuffer[ch]);
474 }
475 free(h->protoFilter);
476 free(h->protoFilterI);
477 free(h->inBuffer);
478 free(h->outBuffer);
479 free(h->fftProcessFrameTD);
480 free(h->fftProcessFrameFD);
481#ifdef AFSTFT_USE_SAF_UTILITIES
482 saf_rfft_destroy(&(h->hSafFFT));
483 free(h->tempHopBuffer);
484#else
485 vtFreeFFT(h->vtFFT);
486#endif
487 free(h);
488}
489
490
491/* ========================================================================== */
492/* Internal functions */
493/* ========================================================================== */
494
496(
497 void** handle,
498 int hopSize,
499 int inChannels,
500 int outChannels
501)
502{
503 /* Allocates 7 samples of memory for FIR filtering at lowest bands, and for delays at other bands. */
504 int ch,sample;
505 *handle = malloc(sizeof(afHybrid));
506 afHybrid *h = (afHybrid*)(*handle);
507 h->inChannels = inChannels;
508 h->hopSize = hopSize;
509 h->outChannels = outChannels;
510 h->analysisBuffer = (complexVector**)malloc(sizeof(complexVector*)*h->inChannels);
511 h->loopPointer=0;
512 for (ch=0;ch<h->inChannels;ch++)
513 {
514 h->analysisBuffer[ch] = (complexVector*)malloc(sizeof(complexVector)*7);
515 for (sample=0;sample<7;sample++)
516 {
517 h->analysisBuffer[ch][sample].re=(float*)calloc(sizeof(float),h->hopSize+1);
518 h->analysisBuffer[ch][sample].im=(float*)calloc(sizeof(float),h->hopSize+1);
519 }
520 }
521}
522
524(
525 void* handle,
526 complexVector* FD
527)
528{
529 afHybrid *h = (afHybrid*)(handle);
530 int ch,band,sample,realImag;
531 float *pr1, *pr2, *pi1, *pi2;
532 float re,im;
533 int sampleIndices[7];
534 int loopPointerThis;
535 h->loopPointer++;
536 if( h->loopPointer == 7)
537 {
538 h->loopPointer = 0;
539 }
540
541 for (ch=0;ch<h->inChannels;ch++)
542 {
543 /* Copy data from input to the memory buffer */
544 pr1 = FD[ch].re;
545 pi1 = FD[ch].im;
546 pr2 = h->analysisBuffer[ch][h->loopPointer].re;
547 pi2 = h->analysisBuffer[ch][h->loopPointer].im;
548// memcpy(pr2, pr1, sizeof(float)*(h->hopSize+1));
549// memcpy(pi2, pi1, sizeof(float)*(h->hopSize+1));
550 cblas_scopy(h->hopSize+1, pr1, 1, pr2, 1);
551 cblas_scopy(h->hopSize+1, pi1, 1, pi2, 1);
552
553 /* Get the pointer to a position corresponding to the group delay of the linear-phase half-band filter. */
554 loopPointerThis = h->loopPointer - 3;
555 if( loopPointerThis < 0)
556 {
557 loopPointerThis += 7;
558 }
559 pr1 = FD[ch].re;
560 pr2 = h->analysisBuffer[ch][loopPointerThis].re;
561 for (realImag=0;realImag<2;realImag++)
562 {
563 /* The 0.5 multipliers are the center coefficients of the half-band FIR filters. Data is duplicated for the half-bands. */
564 *pr1 = *pr2;
565 *(pr1+1) = *(pr2+1)*0.5f;
566 *(pr1+2) = *(pr1+1);
567 *(pr1+3) = *(pr2+2)*0.5f;
568 *(pr1+4) = *(pr1+3);
569 *(pr1+5) = *(pr2+3)*0.5f;
570 *(pr1+6) = *(pr1+5);
571 *(pr1+7) = *(pr2+4)*0.5f;
572 *(pr1+8) = *(pr1+7);
573
574 /* The rest of the bands are shifted upwards in the frequency indices, and delayed by the group delay of the half-band filters */
575 //memcpy((void*)(pr1+9),(void*)(pr2+5),sizeof(float)*(h->hopSize-4));
576 cblas_scopy(h->hopSize-4, pr2+5, 1, pr1+9, 1);
577
578 /* Repeat process for the imaginary part, at next iteration. */
579 pr1 = FD[ch].im;
580 pr2 = h->analysisBuffer[ch][loopPointerThis].im;
581 }
582
583 for (sample=0;sample<7;sample++)
584 {
585 sampleIndices[sample]=h->loopPointer+1+sample;
586 if(sampleIndices[sample] > 6)
587 {
588 sampleIndices[sample]-=7;
589 }
590
591 }
592 for (band=1; band<5; band++)
593 {
594 /* The rest of the half-band FIR filtering is implemented below. The real<->imaginary shifts are for shifting the half-band filter spectra. */
595 re = -COEFF1*h->analysisBuffer[ch][sampleIndices[6]].im[band];
596 im = COEFF1*h->analysisBuffer[ch][sampleIndices[6]].re[band];
597 re -= COEFF2*h->analysisBuffer[ch][sampleIndices[4]].im[band];
598 im += COEFF2*h->analysisBuffer[ch][sampleIndices[4]].re[band];
599 re += COEFF2*h->analysisBuffer[ch][sampleIndices[2]].im[band];
600 im -= COEFF2*h->analysisBuffer[ch][sampleIndices[2]].re[band];
601 re += COEFF1*h->analysisBuffer[ch][sampleIndices[0]].im[band];
602 im -= COEFF1*h->analysisBuffer[ch][sampleIndices[0]].re[band];
603
604 /* The addition or subtraction process below provides the upper and lower half-band spectra (the coefficient 0.5 had the same sign for both bands).
605 The half-band orders are switched for bands=1,3 with respect to band=2,4, because of the organization of the spectral data at the downsampled frequency band signals. As the result of the order switching, the bands are organized by the ascending spectral position. */
606 if (band == 1 || band== 3)
607 {
608 FD[ch].re[band*2-1] -= re;
609 FD[ch].im[band*2-1] -= im;
610 FD[ch].re[band*2] += re;
611 FD[ch].im[band*2] += im;
612 }
613 else
614 {
615 FD[ch].re[band*2-1] += re;
616 FD[ch].im[band*2-1] += im;
617 FD[ch].re[band*2] -= re;
618 FD[ch].im[band*2] -= im;
619 }
620
621 }
622 }
623}
624
626(
627 void* handle,
628 complexVector* FD
629)
630{
631 afHybrid *h = (afHybrid*)(handle);
632 int ch,realImag;
633 float *pr;
634
635 for (ch=0;ch<h->outChannels;ch++)
636 {
637 pr = FD[ch].re;
638 for (realImag=0;realImag<2;realImag++)
639 {
640 /* Since no downsampling was applied, the inverse hybrid filtering is just sum of the bands */
641 *(pr+1) = *(pr+1) + *(pr+2);
642 *(pr+2) = *(pr+3) + *(pr+4);
643 *(pr+3) = *(pr+5) + *(pr+6);
644 *(pr+4) = *(pr+7) + *(pr+8);
645
646 /* The rest of the bands are shifted to their original positions */
647 memmove((void*)(pr+5),(void*)(pr+9),sizeof(float)*(h->hopSize-4));
648
649 /* Repeat process for the imaginary part, at next iteration. */
650 pr = FD[ch].im;
651 }
652 }
653}
654
656(
657 void* handle
658)
659{
660 int ch,sample;
661 afHybrid *h = (afHybrid*)(handle);
662 for (ch=0;ch<h->inChannels;ch++)
663 {
664 for (sample=0;sample<7;sample++)
665 {
666 free(h->analysisBuffer[ch][sample].re);
667 free(h->analysisBuffer[ch][sample].im);
668 }
669 free(h->analysisBuffer[ch]);
670
671 }
672 free(h->analysisBuffer);
673 free(handle);
674}
void afSTFTlib_channelChange(void *handle, int new_inChannels, int new_outChannels)
Re-allocates memory to support a change in the number of input/output channels.
void afSTFTlib_clearBuffers(void *handle)
Flushes time-domain buffers with zeros.
void afHybridForward(void *handle, complexVector *FD)
Forward hybrid-filtering transform.
void afHybridInverse(void *handle, complexVector *FD)
Inverse hybrid-filtering transform.
void afHybridInit(void **handle, int hopSize, int inChannels, int outChannels)
Creates and initialises an instance of the afHybrid filtering structure.
void afSTFTlib_forward(void *handle, float **inTD, complexVector *outFD)
Applies the forward afSTFT transform.
void afSTFTlib_inverse(void *handle, complexVector *inFD, float **outTD)
Applies the backward afSTFT transform.
void afSTFTlib_free(void *handle)
Destroys an instance of afSTFTlib.
void afSTFTlib_init(void **handle, int hopSize, int inChannels, int outChannels, int LDmode, int hybridMode)
Initialises an instance of afSTFTlib [1].
void afHybridFree(void *handle)
Frees an instnce of the afHybrid filtering structure.
A modified version of afSTFTlib.
#define COEFF2
Filter coefficient 1 for hybrid filtering.
#define COEFF1
Filter coefficient 0 for hybrid filtering.
Prototype filter used by afSTFTlib.
const float __afSTFT_protoFilter1024[10240]
Prototype filter used by afSTFTlib.
const float __afSTFT_protoFilter1024LD[10240]
Prototype filter used by afSTFTlib (low-delay mode)
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_rfft_create(void **const phFFT, int N)
Creates an instance of saf_rfft; real<->half-complex (conjugate-symmetric) FFT.
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.
Data structure for the hybrid filtering employed by afSTFTlib.
Main data structure for afSTFTlib.
Complex data type used by afSTFTlib.