Пример #1
0
/*
 * FFT of the length 15 * (2^N)
 */
static void fft_calc(CeltIMDCTContext *s, FFTComplex *out, const FFTComplex *in,
                     int N, ptrdiff_t stride)
{
    if (N) {
        const FFTComplex *exptab = s->exptab[N];
        const int len2 = 15 * (1 << (N - 1));
        int k;

        fft_calc(s, out,        in,          N - 1, stride * 2);
        fft_calc(s, out + len2, in + stride, N - 1, stride * 2);

        for (k = 0; k < len2; k++) {
            FFTComplex t;

            CMUL(t, out[len2 + k], exptab[k]);

            out[len2 + k].re = out[k].re - t.re;
            out[len2 + k].im = out[k].im - t.im;

            out[k].re += t.re;
            out[k].im += t.im;
        }
    } else
        fft15(s, out, in, stride);
}
Пример #2
0
static void celt_imdct_half(CeltIMDCTContext *s, float *dst, const float *src,
                            ptrdiff_t stride, float scale)
{
    FFTComplex *z = (FFTComplex *)dst;
    const int len8 = s->len4 / 2;
    const float *in1 = src;
    const float *in2 = src + (s->len2 - 1) * stride;
    int i;

    for (i = 0; i < s->len4; i++) {
        FFTComplex tmp = { *in2, *in1 };
        CMUL(s->tmp[i], tmp, s->twiddle_exptab[i]);
        in1 += 2 * stride;
        in2 -= 2 * stride;
    }

    fft_calc(s, z, s->tmp, s->fft_n, 1);

    for (i = 0; i < len8; i++) {
        float r0, i0, r1, i1;

        CMUL3(r0, i1, z[len8 - i - 1].im, z[len8 - i - 1].re,  s->twiddle_exptab[len8 - i - 1].im, s->twiddle_exptab[len8 - i - 1].re);
        CMUL3(r1, i0, z[len8 + i].im,     z[len8 + i].re,      s->twiddle_exptab[len8 + i].im,     s->twiddle_exptab[len8 + i].re);
        z[len8 - i - 1].re = scale * r0;
        z[len8 - i - 1].im = scale * i0;
        z[len8 + i].re     = scale * r1;
        z[len8 + i].im     = scale * i1;
    }
}
Пример #3
0
void fft_calc(const int N,const double *x,complex double *X,complex double *P,const int step,const complex double *twids)
{
    complex double *S = P + N/2;
    if (N == 1){
	X[0] = x[0];
	return;
    }
    
    fft_calc(N/2, x,      S,   X,2*step, twids);
    fft_calc(N/2, x+step, P,   X,2*step, twids);	    

    int k;
    for (k=0;k<N/2;k++){
	P[k] = P[k]*twids[k*step];
	X[k]     = S[k] + P[k];
	X[k+N/2] = S[k] - P[k];
    }

}
Пример #4
0
void fft_calc(const int N, const double *x, Complex *X, Complex *P, const int step, const Complex *twids){
    int k;
    Complex *S = P + N/2;
    if (N == 1){
	X[0].re = x[0];
        X[0].im = 0;
	return;
    }
    
    fft_calc(N/2, x,      S,   X,2*step, twids);
    fft_calc(N/2, x+step, P,   X,2*step, twids);
 
    for (k=0;k<N/2;k++){
		P[k] = mult_complex(P[k],twids[k*step]);
		X[k]     = add_complex(S[k],P[k]);
		X[k+N/2] = sub_complex(S[k],P[k]);
    }

}
Пример #5
0
int fft(const double *x, const int N, Complex *X){

    Complex *twiddle_factors = (Complex*)malloc(sizeof(Complex)*(N/2));
    Complex *Xt = (Complex*)malloc(sizeof(Complex)*(N));
    int k;
    for (k=0;k<N/2;k++){
	twiddle_factors[k] = polar_to_complex(1.0, 2.0*PI*k/N);
    }
    fft_calc(N, x, X, Xt, 1, twiddle_factors);

    free(twiddle_factors);
    free(Xt);

    return 0;

}
Пример #6
0
/**
 * Compute inverse MDCT of size N = 2^nbits
 * @param output N samples
 * @param input N/2 samples
 * @param tmp N/2 samples
 */
void ff_imdct_calc(MDCTContext *s, FFTSample *output, 
                   const FFTSample *input, FFTSample *tmp)
{
    int k, n8, n4, n2, n, j;
    const uint16_t *revtab = s->fft.revtab;
    const FFTSample *tcos = s->tcos;
    const FFTSample *tsin = s->tsin;
    const FFTSample *in1, *in2;
    FFTComplex *z = (FFTComplex *)tmp;

    n = 1 << s->nbits;
    n2 = n >> 1;
    n4 = n >> 2;
    n8 = n >> 3;

    /* pre rotation */
    in1 = input;
    in2 = input + n2 - 1;
    for(k = 0; k < n4; k++) {
        j=revtab[k];
        CMUL(z[j].re, z[j].im, *in2, *in1, tcos[k], tsin[k]);
        in1 += 2;
        in2 -= 2;
    }
    fft_calc(&s->fft, z);

    /* post rotation + reordering */
    /* XXX: optimize */
    for(k = 0; k < n4; k++) {
        CMUL(z[k].re, z[k].im, z[k].re, z[k].im, tcos[k], tsin[k]);
    }
    for(k = 0; k < n8; k++) {
        output[2*k] = -z[n8 + k].im;
        output[n2-1-2*k] = z[n8 + k].im;

        output[2*k+1] = z[n8-1-k].re;
        output[n2-1-2*k-1] = -z[n8-1-k].re;

        output[n2 + 2*k]=-z[k+n8].re;
        output[n-1- 2*k]=-z[k+n8].re;

        output[n2 + 2*k+1]=z[n8-k-1].im;
        output[n-2 - 2 * k] = z[n8-k-1].im;
    }
}
Пример #7
0
int fft(double *x, int N, complex double *X)
{

    complex double *twiddle_factors = (complex double*)malloc(sizeof(complex double)*(N/2));
    complex double *Xt = (complex double*)malloc(sizeof(complex double)*N);

    int k;
    for (k=0;k<N/2;k++){
	twiddle_factors[k] = polar_to_complex(1.0, 2.0*PI*k/N);
    }
    fft_calc(N, x, X, Xt, 1, twiddle_factors);

    free(twiddle_factors);
    free(Xt);

    return 0;

}
Пример #8
0
/**
 * Compute MDCT of size N = 2^nbits
 * @param input N samples
 * @param out N/2 samples
 * @param tmp temporary storage of N/2 samples
 */
void ff_mdct_calc(MDCTContext *s, FFTSample *out, 
                  const FFTSample *input, FFTSample *tmp)
{
    int i, j, n, n8, n4, n2, n3;
    FFTSample re, im, re1, im1;
    const uint16_t *revtab = s->fft.revtab;
    const FFTSample *tcos = s->tcos;
    const FFTSample *tsin = s->tsin;
    FFTComplex *x = (FFTComplex *)tmp;

    n = 1 << s->nbits;
    n2 = n >> 1;
    n4 = n >> 2;
    n8 = n >> 3;
    n3 = 3 * n4;

    /* pre rotation */
    for(i=0;i<n8;i++) {
        re = -input[2*i+3*n4] - input[n3-1-2*i];
        im = -input[n4+2*i] + input[n4-1-2*i];
        j = revtab[i];
        CMUL(x[j].re, x[j].im, re, im, -tcos[i], tsin[i]);

        re = input[2*i] - input[n2-1-2*i];
        im = -(input[n2+2*i] + input[n-1-2*i]);
        j = revtab[n8 + i];
        CMUL(x[j].re, x[j].im, re, im, -tcos[n8 + i], tsin[n8 + i]);
    }

    fft_calc(&s->fft, x);
  
    /* post rotation */
    for(i=0;i<n4;i++) {
        re = x[i].re;
        im = x[i].im;
        CMUL(re1, im1, re, im, -tsin[i], -tcos[i]);
        out[2*i] = im1;
        out[n2-1-2*i] = re1;
    }
}
Пример #9
0
//--------------------------------------------------------------
// start vom Oszi (Endlosloop)
//--------------------------------------------------------------
void oszi_start(void)
{
  MENU_Status_t status;

  p_oszi_draw_background();
  UB_Graphic2D_Copy2DMA(Menu.akt_transparenz);  

  while(1) {
    //---------------------------------------------
    // warten bis GUI-Timer abgelaufen ist
    //---------------------------------------------
    if(GUI_Timer_ms==0) {
      GUI_Timer_ms=GUI_INTERVALL_MS;
      //--------------------------------------
      // User-Button einlesen (fuer RUN/STOP)
      //--------------------------------------
      if(UB_Button_OnClick(BTN_USER)==true) {
        status=MENU_NO_CHANGE;
        if(Menu.trigger.mode==2) { // "single"
          if(Menu.trigger.single==4) {
            Menu.trigger.single=5;  // von "Ready" auf "Stop"
            status=MENU_CHANGE_NORMAL;
          }
        }
        else { // "normal" oder "auto"
          if(Menu.trigger.single==0) {
            Menu.trigger.single=1; // von "Run" auf "Stop"
            status=MENU_CHANGE_NORMAL;
          }
          else if(Menu.trigger.single==1) {
            Menu.trigger.single=2; // von "Stop" auf "Weiter"
            status=MENU_CHANGE_NORMAL;
          }
        }
      }
      else {
        //--------------------------------------
        // Test ob Touch betaetigt
        //--------------------------------------
        status=menu_check_touch();
      }
      if(status!=MENU_NO_CHANGE) {
        p_oszi_draw_background();
        if(status==MENU_CHANGE_FRQ) ADC_change_Frq(Menu.timebase.value);
        if(status==MENU_CHANGE_MODE) {
          ADC_change_Mode(Menu.trigger.mode);
          if(Menu.trigger.mode!=2) {
            Menu.trigger.single=0;
          }
          else {
            Menu.trigger.single=3;
          }
          p_oszi_draw_background(); // nochmal zeichnen, zum update
          ADC_UB.status=ADC_VORLAUF;
          TIM_Cmd(TIM2, ENABLE);
        }
        if(status==MENU_SEND_DATA) {
          p_oszi_draw_background(); // nochmal zeichnen, zum update
          p_oszi_draw_adc();
          // gesendet wird am Ende
        }
      }

      if(Menu.trigger.mode==1) {
        //--------------------------------------
        // Trigger-Mode = "AUTO"
        // Screnn immer neu zeichnen
        //--------------------------------------
        if(Menu.trigger.single==0) {
          if ((ADC1_DMA_STREAM->CR & DMA_SxCR_CT) == 0) {
            ADC_UB.trigger_pos=SCALE_X_MITTE;
            ADC_UB.trigger_quarter=2;
          }
          else {
            ADC_UB.trigger_pos=SCALE_X_MITTE;
            ADC_UB.trigger_quarter=4;
          }
          p_oszi_sort_adc();
          p_oszi_fill_fft();
          if(Menu.fft.mode!=0) fft_calc();
          p_oszi_draw_adc();
          ADC_UB.status=ADC_VORLAUF;
          UB_Led_Toggle(LED_RED);
        }
        else if(Menu.trigger.single==1) {
          // Button "STOP" wurde gedrückt
          // Timer analten
          TIM_Cmd(TIM2, DISABLE);
          if(status!=MENU_NO_CHANGE) p_oszi_draw_adc();
        }
        else if(Menu.trigger.single==2) {
          // Button "START" wurde gedrückt
          Menu.trigger.single=0;
          ADC_UB.status=ADC_VORLAUF;
          TIM_Cmd(TIM2, ENABLE);
          if(status!=MENU_NO_CHANGE) p_oszi_draw_adc();
        }
      }
      else if(Menu.trigger.mode==0) {
        //--------------------------------------
        // Trigger-Mode = "NORMAL"
        // Screnn nur zeichnen, nach Triggerevent
        //--------------------------------------
        if(Menu.trigger.single==0) {
          if(ADC_UB.status==ADC_READY) {
            UB_Led_Toggle(LED_RED);
            p_oszi_sort_adc();
            p_oszi_fill_fft();
            if(Menu.fft.mode!=0) fft_calc();
            p_oszi_draw_adc();
            ADC_UB.status=ADC_VORLAUF;
            TIM_Cmd(TIM2, ENABLE);
          }
          else {
            // oder wenn Menu verändert wurde
            if(status!=MENU_NO_CHANGE) p_oszi_draw_adc();
          }
        }
        else if(Menu.trigger.single==1) {
          // Button "STOP" wurde gedrückt
          // Timer analten
          TIM_Cmd(TIM2, DISABLE);
          if(status!=MENU_NO_CHANGE) p_oszi_draw_adc();
        }
        else if(Menu.trigger.single==2) {
          // Button "START" wurde gedrückt
          Menu.trigger.single=0;
          ADC_UB.status=ADC_VORLAUF;
          TIM_Cmd(TIM2, ENABLE);
          if(status!=MENU_NO_CHANGE) p_oszi_draw_adc();
        }
      }
      else {
        //--------------------------------------
        // Trigger-Mode = "SINGLE"
        // Screnn nur einmal zeichnen, nach Triggerevent
        //--------------------------------------
        if(Menu.trigger.single==3) {
          // warten auf Trigger-Event
          if(ADC_UB.status==ADC_READY) {
            Menu.trigger.single=4;
            UB_Led_Toggle(LED_RED);
            p_oszi_sort_adc();
            p_oszi_fill_fft();
            if(Menu.fft.mode!=0) fft_calc();
            p_oszi_draw_adc();
          }
          else {
            // oder wenn Menu verändert wurde
            if(status!=MENU_NO_CHANGE) p_oszi_draw_adc();
          }
        }
        else if(Menu.trigger.single==5) {
          // Button "Reset" wurde gedrückt
          Menu.trigger.single=3;
          p_oszi_draw_adc();
          ADC_UB.status=ADC_VORLAUF;
          TIM_Cmd(TIM2, ENABLE);
        }
        else {
          // oder wenn Menu verändert wurde
          if(status!=MENU_NO_CHANGE) p_oszi_draw_adc();
        }
      }

      if(GUI.gui_xpos==GUI_XPOS_OFF) {
        // ohne GUI => ohne Transparenz zeichnen
        UB_Graphic2D_Copy1DMA();
      }
      else {
        // mit GUI => mit Transparenz zeichnen
        UB_Graphic2D_Copy2DMA(Menu.akt_transparenz);
      }

      // Refreh vom LCD
      UB_LCD_Refresh();

      // event. Daten senden
      if(Menu.send.data!=0) {
        p_oszi_send_data();
        Menu.send.data=0;
      }
    }
  }
}
Пример #10
0
double Equalizer::filter( QByteArray &data, bool flush )
{
	if ( canFilter )
	{
		mutex.lock();

		if ( !flush )
		{
			float *samples = ( float * )data.data();
			const int size = data.size() / sizeof( float );
			for ( int c = 0 ; c < chn ; ++c ) //Buforowanie danych
				for ( int i = 0 ; i < size ; i += chn )
					input[ c ].append( samples[ c+i ] );
		}
		else for ( int c = 0 ; c < chn ; ++c ) //Dokładanie ciszy
			input[ c ].resize( FFT_SIZE );

		data.clear();
		const int chunks = input.at( 0 ).size() / FFT_SIZE_2 - 1;
		if ( chunks > 0 ) //Jeżeli jest wystarczająca ilość danych
		{
			data.resize( chn * sizeof( float ) * FFT_SIZE_2 * chunks );
			float *samples = ( float * )data.data();
			for ( int c = 0 ; c < chn ; ++c )
			{
				int pos = c;
				while ( input.at( c ).size() >= FFT_SIZE )
				{
					for ( int i = 0 ; i < FFT_SIZE ; ++i )
						complex[ i ] = ( FFTComplex ){ input.at( c ).at( i ), 0.0f };
					if ( !flush )
						input[ c ].remove( 0, FFT_SIZE_2 );
					else
						input[ c ].clear();

					fft_calc( fftIn, complex );
					for ( int i = 0 ; i < FFT_SIZE_2 ; ++i )
					{
						complex[            i ].re *= f.at( i );
						complex[            i ].im *= f.at( i );
						complex[ FFT_SIZE-1-i ].re *= f.at( i );
						complex[ FFT_SIZE-1-i ].im *= f.at( i );
					}
					fft_calc( fftOut, complex );

					if ( last_samples.at( c ).isEmpty() )
					{
						for ( int i = 0 ; i < FFT_SIZE_2 ; ++i, pos += chn )
							samples[ pos ] = complex[ i ].re / FFT_SIZE;
						last_samples[ c ].resize( FFT_SIZE_2 );
					}
					else for ( int i = 0 ; i < FFT_SIZE_2 ; ++i, pos += chn )
						samples[ pos ] = ( complex[ i ].re / FFT_SIZE ) * wind_f.at( i ) + last_samples.at( c ).at( i );

					for ( int i = FFT_SIZE_2 ; i < FFT_SIZE ; ++i )
						last_samples[ c ][ i-FFT_SIZE_2 ] = ( complex[ i ].re / FFT_SIZE ) * wind_f.at( i );
				}
			}
		}

		mutex.unlock();
		return FFT_SIZE / ( double )srate;
	}
	return 0.0;
}
Пример #11
0
int main(int argc, char **argv)
{
    FFTComplex *tab, *tab1, *tab_ref;
    FFTSample *tabtmp, *tab2;
    int it, i, c;
    int do_speed = 0;
    int do_mdct = 0;
    int do_inverse = 0;
    FFTContext s1, *s = &s1;
    MDCTContext m1, *m = &m1;
    int fft_nbits, fft_size;

    mm_flags = 0;
    fft_nbits = 9;
    for(;;) {
        c = getopt(argc, argv, "hsimn:");
        if (c == -1)
            break;
        switch(c) {
        case 'h':
            help();
            break;
        case 's':
            do_speed = 1;
            break;
        case 'i':
            do_inverse = 1;
            break;
        case 'm':
            do_mdct = 1;
            break;
        case 'n':
            fft_nbits = atoi(optarg);
            break;
        }
    }

    fft_size = 1 << fft_nbits;
    tab = av_malloc(fft_size * sizeof(FFTComplex));
    tab1 = av_malloc(fft_size * sizeof(FFTComplex));
    tab_ref = av_malloc(fft_size * sizeof(FFTComplex));
    tabtmp = av_malloc(fft_size / 2 * sizeof(FFTSample));
    tab2 = av_malloc(fft_size * sizeof(FFTSample));

    if (do_mdct) {
        if (do_inverse)
            printf("IMDCT");
        else
            printf("MDCT");
        ff_mdct_init(m, fft_nbits, do_inverse);
    } else {
        if (do_inverse)
            printf("IFFT");
        else
            printf("FFT");
        fft_init(s, fft_nbits, do_inverse);
        fft_ref_init(fft_nbits, do_inverse);
    }
    printf(" %d test\n", fft_size);

    /* generate random data */

    for(i=0;i<fft_size;i++) {
        tab1[i].re = frandom();
        tab1[i].im = frandom();
    }

    /* checking result */
    printf("Checking...\n");

    if (do_mdct) {
        if (do_inverse) {
            imdct_ref((float *)tab_ref, (float *)tab1, fft_size);
            ff_imdct_calc(m, tab2, (float *)tab1, tabtmp);
            check_diff((float *)tab_ref, tab2, fft_size);
        } else {
            mdct_ref((float *)tab_ref, (float *)tab1, fft_size);
            
            ff_mdct_calc(m, tab2, (float *)tab1, tabtmp);

            check_diff((float *)tab_ref, tab2, fft_size / 2);
        }
    } else {
        memcpy(tab, tab1, fft_size * sizeof(FFTComplex));
        fft_permute(s, tab);
        fft_calc(s, tab);
        
        fft_ref(tab_ref, tab1, fft_nbits);
        check_diff((float *)tab_ref, (float *)tab, fft_size * 2);
    }

    /* do a speed test */

    if (do_speed) {
        int64_t time_start, duration;
        int nb_its;

        printf("Speed test...\n");
        /* we measure during about 1 seconds */
        nb_its = 1;
        for(;;) {
            time_start = gettime();
            for(it=0;it<nb_its;it++) {
                if (do_mdct) {
                    if (do_inverse) {
                        ff_imdct_calc(m, (float *)tab, (float *)tab1, tabtmp);
                    } else {
                        ff_mdct_calc(m, (float *)tab, (float *)tab1, tabtmp);
                    }
                } else {
                    memcpy(tab, tab1, fft_size * sizeof(FFTComplex));
                    fft_calc(s, tab);
                }
            }
            duration = gettime() - time_start;
            if (duration >= 1000000)
                break;
            nb_its *= 2;
        }
        printf("time: %0.1f us/transform [total time=%0.2f s its=%d]\n", 
               (double)duration / nb_its, 
               (double)duration / 1000000.0,
               nb_its);
    }
    
    if (do_mdct) {
        ff_mdct_end(m);
    } else {
        fft_end(s);
    }
    return 0;
}
Пример #12
0
int main(int argc, char **argv)
{
    FFTComplex *tab, *tab1, *tab_ref;
    FFTSample *tab2;
    enum tf_transform transform = TRANSFORM_FFT;
    FFTContext *m, *s;
#if FFT_FLOAT
    RDFTContext *r;
    DCTContext *d;
#endif /* FFT_FLOAT */
    int it, i, err = 1;
    int do_speed = 0, do_inverse = 0;
    int fft_nbits = 9, fft_size;
    double scale = 1.0;
    AVLFG prng;

#if !AVFFT
    s = av_mallocz(sizeof(*s));
    m = av_mallocz(sizeof(*m));
#endif

#if !AVFFT && FFT_FLOAT
    r = av_mallocz(sizeof(*r));
    d = av_mallocz(sizeof(*d));
#endif

    av_lfg_init(&prng, 1);

    for (;;) {
        int c = getopt(argc, argv, "hsimrdn:f:c:");
        if (c == -1)
            break;
        switch (c) {
        case 'h':
            help();
            return 1;
        case 's':
            do_speed = 1;
            break;
        case 'i':
            do_inverse = 1;
            break;
        case 'm':
            transform = TRANSFORM_MDCT;
            break;
        case 'r':
            transform = TRANSFORM_RDFT;
            break;
        case 'd':
            transform = TRANSFORM_DCT;
            break;
        case 'n':
            fft_nbits = atoi(optarg);
            break;
        case 'f':
            scale = atof(optarg);
            break;
        case 'c':
        {
            unsigned cpuflags = av_get_cpu_flags();

            if (av_parse_cpu_caps(&cpuflags, optarg) < 0)
                return 1;

            av_force_cpu_flags(cpuflags);
            break;
        }
        }
    }

    fft_size = 1 << fft_nbits;
    tab      = av_malloc_array(fft_size, sizeof(FFTComplex));
    tab1     = av_malloc_array(fft_size, sizeof(FFTComplex));
    tab_ref  = av_malloc_array(fft_size, sizeof(FFTComplex));
    tab2     = av_malloc_array(fft_size, sizeof(FFTSample));

    if (!(tab && tab1 && tab_ref && tab2))
        goto cleanup;

    switch (transform) {
#if CONFIG_MDCT
    case TRANSFORM_MDCT:
        av_log(NULL, AV_LOG_INFO, "Scale factor is set to %f\n", scale);
        if (do_inverse)
            av_log(NULL, AV_LOG_INFO, "IMDCT");
        else
            av_log(NULL, AV_LOG_INFO, "MDCT");
        mdct_init(&m, fft_nbits, do_inverse, scale);
        break;
#endif /* CONFIG_MDCT */
    case TRANSFORM_FFT:
        if (do_inverse)
            av_log(NULL, AV_LOG_INFO, "IFFT");
        else
            av_log(NULL, AV_LOG_INFO, "FFT");
        fft_init(&s, fft_nbits, do_inverse);
        if ((err = fft_ref_init(fft_nbits, do_inverse)) < 0)
            goto cleanup;
        break;
#if FFT_FLOAT
#    if CONFIG_RDFT
    case TRANSFORM_RDFT:
        if (do_inverse)
            av_log(NULL, AV_LOG_INFO, "IDFT_C2R");
        else
            av_log(NULL, AV_LOG_INFO, "DFT_R2C");
        rdft_init(&r, fft_nbits, do_inverse ? IDFT_C2R : DFT_R2C);
        if ((err = fft_ref_init(fft_nbits, do_inverse)) < 0)
            goto cleanup;
        break;
#    endif /* CONFIG_RDFT */
#    if CONFIG_DCT
    case TRANSFORM_DCT:
        if (do_inverse)
            av_log(NULL, AV_LOG_INFO, "DCT_III");
        else
            av_log(NULL, AV_LOG_INFO, "DCT_II");
            dct_init(&d, fft_nbits, do_inverse ? DCT_III : DCT_II);
        break;
#    endif /* CONFIG_DCT */
#endif /* FFT_FLOAT */
    default:
        av_log(NULL, AV_LOG_ERROR, "Requested transform not supported\n");
        goto cleanup;
    }
    av_log(NULL, AV_LOG_INFO, " %d test\n", fft_size);

    /* generate random data */

    for (i = 0; i < fft_size; i++) {
        tab1[i].re = frandom(&prng);
        tab1[i].im = frandom(&prng);
    }

    /* checking result */
    av_log(NULL, AV_LOG_INFO, "Checking...\n");

    switch (transform) {
#if CONFIG_MDCT
    case TRANSFORM_MDCT:
        if (do_inverse) {
            imdct_ref(&tab_ref->re, &tab1->re, fft_nbits);
            imdct_calc(m, tab2, &tab1->re);
            err = check_diff(&tab_ref->re, tab2, fft_size, scale);
        } else {
            mdct_ref(&tab_ref->re, &tab1->re, fft_nbits);
            mdct_calc(m, tab2, &tab1->re);
            err = check_diff(&tab_ref->re, tab2, fft_size / 2, scale);
        }
        break;
#endif /* CONFIG_MDCT */
    case TRANSFORM_FFT:
        memcpy(tab, tab1, fft_size * sizeof(FFTComplex));
        fft_permute(s, tab);
        fft_calc(s, tab);

        fft_ref(tab_ref, tab1, fft_nbits);
        err = check_diff(&tab_ref->re, &tab->re, fft_size * 2, 1.0);
        break;
#if FFT_FLOAT
#if CONFIG_RDFT
    case TRANSFORM_RDFT:
    {
        int fft_size_2 = fft_size >> 1;
        if (do_inverse) {
            tab1[0].im          = 0;
            tab1[fft_size_2].im = 0;
            for (i = 1; i < fft_size_2; i++) {
                tab1[fft_size_2 + i].re =  tab1[fft_size_2 - i].re;
                tab1[fft_size_2 + i].im = -tab1[fft_size_2 - i].im;
            }

            memcpy(tab2, tab1, fft_size * sizeof(FFTSample));
            tab2[1] = tab1[fft_size_2].re;

            rdft_calc(r, tab2);
            fft_ref(tab_ref, tab1, fft_nbits);
            for (i = 0; i < fft_size; i++) {
                tab[i].re = tab2[i];
                tab[i].im = 0;
            }
            err = check_diff(&tab_ref->re, &tab->re, fft_size * 2, 0.5);
        } else {
            for (i = 0; i < fft_size; i++) {
                tab2[i]    = tab1[i].re;
                tab1[i].im = 0;
            }
            rdft_calc(r, tab2);
            fft_ref(tab_ref, tab1, fft_nbits);
            tab_ref[0].im = tab_ref[fft_size_2].re;
            err = check_diff(&tab_ref->re, tab2, fft_size, 1.0);
        }
        break;
    }
#endif /* CONFIG_RDFT */
#if CONFIG_DCT
    case TRANSFORM_DCT:
        memcpy(tab, tab1, fft_size * sizeof(FFTComplex));
        dct_calc(d, &tab->re);
        if (do_inverse)
            idct_ref(&tab_ref->re, &tab1->re, fft_nbits);
        else
            dct_ref(&tab_ref->re, &tab1->re, fft_nbits);
        err = check_diff(&tab_ref->re, &tab->re, fft_size, 1.0);
        break;
#endif /* CONFIG_DCT */
#endif /* FFT_FLOAT */
    }

    /* do a speed test */

    if (do_speed) {
        int64_t time_start, duration;
        int nb_its;

        av_log(NULL, AV_LOG_INFO, "Speed test...\n");
        /* we measure during about 1 seconds */
        nb_its = 1;
        for (;;) {
            time_start = av_gettime_relative();
            for (it = 0; it < nb_its; it++) {
                switch (transform) {
                case TRANSFORM_MDCT:
                    if (do_inverse)
                        imdct_calc(m, &tab->re, &tab1->re);
                    else
                        mdct_calc(m, &tab->re, &tab1->re);
                    break;
                case TRANSFORM_FFT:
                    memcpy(tab, tab1, fft_size * sizeof(FFTComplex));
                    fft_calc(s, tab);
                    break;
#if FFT_FLOAT
                case TRANSFORM_RDFT:
                    memcpy(tab2, tab1, fft_size * sizeof(FFTSample));
                    rdft_calc(r, tab2);
                    break;
                case TRANSFORM_DCT:
                    memcpy(tab2, tab1, fft_size * sizeof(FFTSample));
                    dct_calc(d, tab2);
                    break;
#endif /* FFT_FLOAT */
                }
            }
            duration = av_gettime_relative() - time_start;
            if (duration >= 1000000)
                break;
            nb_its *= 2;
        }
        av_log(NULL, AV_LOG_INFO,
               "time: %0.1f us/transform [total time=%0.2f s its=%d]\n",
               (double) duration / nb_its,
               (double) duration / 1000000.0,
               nb_its);
    }

    switch (transform) {
#if CONFIG_MDCT
    case TRANSFORM_MDCT:
        mdct_end(m);
        break;
#endif /* CONFIG_MDCT */
    case TRANSFORM_FFT:
        fft_end(s);
        break;
#if FFT_FLOAT
#    if CONFIG_RDFT
    case TRANSFORM_RDFT:
        rdft_end(r);
        break;
#    endif /* CONFIG_RDFT */
#    if CONFIG_DCT
    case TRANSFORM_DCT:
        dct_end(d);
        break;
#    endif /* CONFIG_DCT */
#endif /* FFT_FLOAT */
    }

cleanup:
    av_free(tab);
    av_free(tab1);
    av_free(tab2);
    av_free(tab_ref);
    av_free(exptab);

#if !AVFFT
    av_free(s);
    av_free(m);
#endif

#if !AVFFT && FFT_FLOAT
    av_free(r);
    av_free(d);
#endif

    if (err)
        printf("Error: %d.\n", err);

    return !!err;
}
Пример #13
0
AUD_Int32s denoise_aud( AUD_Int16s *pInBuf, AUD_Int16s *pOutBuf, AUD_Int32s inLen )
{
    Fft_16s        *hFft        = NULL;
    Ifft_16s       *hIfft       = NULL;
    AUD_Window16s  *hWin        = NULL;

    AUD_Int32s     frameSize    = 512;
    AUD_Int32s     frameStride  = 256;
    AUD_Int32s     frameOverlap = 256;
    AUD_Int32s     nFFT         = frameSize;
    AUD_Int32s     nSpecLen     = nFFT / 2 + 1;
    AUD_Int32s     nNoiseFrame  = 6; // (AUD_Int32s)( ( 0.25 * SAMPLE_RATE - frameSize ) / frameStride + 1 );

    AUD_Int32s     i, j, k, m, n, ret;

    AUD_Int32s     cleanLen     = 0;

    // pre-emphasis
    // sig_preemphasis( pInBuf, pInBuf, inLen );

    // init hamming module
    win16s_init( &hWin, AUD_WIN_HAMM, frameSize, 14 );
    AUD_ASSERT( hWin );

    // init fft handle
    fft_init( &hFft, nFFT, 15 );
    AUD_ASSERT( hFft );

    // init ifft handle
    ifft_init( &hIfft, nFFT, 15 );
    AUD_ASSERT( hIfft );

    AUD_Int16s *pFrame  = (AUD_Int16s*)calloc( frameSize * sizeof(AUD_Int16s), 1 );
    AUD_ASSERT( pFrame );

    // FFT
    AUD_Int32s *pFFTMag  = (AUD_Int32s*)calloc( nFFT * sizeof(AUD_Int32s), 1 );
    AUD_ASSERT( pFFTMag );
    AUD_Int32s *pFFTRe   = (AUD_Int32s*)calloc( nFFT * sizeof(AUD_Int32s), 1 );
    AUD_ASSERT( pFFTRe );
    AUD_Int32s *pFFTIm   = (AUD_Int32s*)calloc( nFFT * sizeof(AUD_Int32s), 1 );
    AUD_ASSERT( pFFTIm );

    AUD_Int32s *pFFTCleanRe = (AUD_Int32s*)calloc( nFFT * sizeof(AUD_Int32s), 1 );
    AUD_ASSERT( pFFTCleanRe );
    AUD_Int32s *pFFTCleanIm = (AUD_Int32s*)calloc( nFFT * sizeof(AUD_Int32s), 1 );
    AUD_ASSERT( pFFTCleanIm );

    // noise spectrum
    AUD_Double *pNoiseEn = (AUD_Double*)calloc( nSpecLen * sizeof(AUD_Double), 1 );
    AUD_ASSERT( pNoiseEn );

    AUD_Double *pNoiseB = (AUD_Double*)calloc( nSpecLen * sizeof(AUD_Double), 1 );
    AUD_ASSERT( pNoiseB );

    AUD_Double *pXPrev = (AUD_Double*)calloc( nSpecLen * sizeof(AUD_Double), 1 );
    AUD_ASSERT( pXPrev );

    AUD_Double *pAb = (AUD_Double*)calloc( nSpecLen * sizeof(AUD_Double), 1 );
    AUD_ASSERT( pAb );

    AUD_Double *pH = (AUD_Double*)calloc( nSpecLen * sizeof(AUD_Double), 1 );
    AUD_ASSERT( pH );

    AUD_Double *pGammak = (AUD_Double*)calloc( nSpecLen * sizeof(AUD_Double), 1 );
    AUD_ASSERT( pGammak );

    AUD_Double *pKsi = (AUD_Double*)calloc( nSpecLen * sizeof(AUD_Double), 1 );
    AUD_ASSERT( pKsi );

    AUD_Double *pLogSigmak = (AUD_Double*)calloc( nSpecLen * sizeof(AUD_Double), 1 );
    AUD_ASSERT( pLogSigmak );

    AUD_Double *pAlpha = (AUD_Double*)calloc( nSpecLen * sizeof(AUD_Double), 1 );
    AUD_ASSERT( pAlpha );

    AUD_Int32s *pLinToBark = (AUD_Int32s*)calloc( nSpecLen * sizeof(AUD_Int32s), 1 );
    AUD_ASSERT( pLinToBark );

    AUD_Int16s *pxOld   = (AUD_Int16s*)calloc( frameOverlap * sizeof(AUD_Int16s), 1 );
    AUD_ASSERT( pxOld );
    AUD_Int16s *pxClean = (AUD_Int16s*)calloc( nFFT * sizeof(AUD_Int16s), 1 );
    AUD_ASSERT( pxClean );

    /*
    AUD_Int32s critBandEnds[22] = { 0, 100, 200, 300, 400, 510, 630, 770, 920, 1080, 1270,
                                    1480, 1720, 2000, 2320, 2700, 3150, 3700, 4400, 5300, 6400, 7700 };
    */
    AUD_Int32s critFFTEnds[CRITICAL_BAND_NUM + 1]  = { 0, 4, 7, 10, 13, 17, 21, 25, 30, 35, 41, 48, 56, 64,
                                                       75, 87, 101, 119, 141, 170, 205, 247, 257 };

    // generate linear->bark transform mapping
    k = 0;
    for ( i = 0; i < CRITICAL_BAND_NUM; i++ )
    {
        while ( k >= critFFTEnds[i] &&  k < critFFTEnds[i + 1] )
        {
            pLinToBark[k] = i;
            k++;
        }
    }

    AUD_Double absThr[CRITICAL_BAND_NUM] = { 38, 31, 22, 18.5, 15.5, 13, 11, 9.5, 8.75, 7.25, 4.75, 2.75,
                                             1.5, 0.5, 0, 0, 0, 0, 2, 7, 12, 15.5 };

    AUD_Double dbOffset[CRITICAL_BAND_NUM];
    AUD_Double sumn[CRITICAL_BAND_NUM];
    AUD_Double spread[CRITICAL_BAND_NUM];

    for ( i = 0; i < CRITICAL_BAND_NUM; i++ )
    {
        absThr[i]   = pow( 10., absThr[i] / 10. ) / nFFT / ( 65535. * 65535. );
        dbOffset[i] = 10. + i;

        sumn[i]   = 0.474 + i;
        spread[i] = pow( 10., ( 15.81 + 7.5 * sumn[i] - 17.5 * sqrt( 1. + sumn[i] * sumn[i] ) ) / 10. );
    }

    AUD_Double dcGain[CRITICAL_BAND_NUM];
    for ( i = 0; i < CRITICAL_BAND_NUM; i++ )
    {
        dcGain[i] = 0.;
        for ( j = 0; j < CRITICAL_BAND_NUM; j++ )
        {
            dcGain[i] += spread[MABS( i - j )];
        }
    }

    AUD_Matrix exPatMatrix;
    exPatMatrix.rows     = CRITICAL_BAND_NUM;
    exPatMatrix.cols     = nSpecLen;
    exPatMatrix.dataType = AUD_DATATYPE_DOUBLE;
    ret = createMatrix( &exPatMatrix );
    AUD_ASSERT( ret == 0 );

    // excitation pattern
    AUD_Int32s index = 0;
    for ( i = 0; i < exPatMatrix.rows; i++ )
    {
        AUD_Double *pExpatRow = exPatMatrix.pDouble + i * exPatMatrix.cols;

        for ( j = 0; j < exPatMatrix.cols; j++ )
        {
            index = MABS( i - pLinToBark[j] );
            pExpatRow[j] = spread[index];
        }
    }

    AUD_Int32s frameNum = (inLen - frameSize) / frameStride + 1;
    AUD_ASSERT( frameNum > nNoiseFrame );

    // compute noise mean
    for ( i = 0; i < nNoiseFrame; i++ )
    {
        win16s_calc( hWin, pInBuf + i * frameSize, pFrame );

        fft_mag( hFft, pFrame, frameSize, pFFTMag );

        for ( j = 0; j < nSpecLen; j++ )
        {
            pNoiseEn[j] += pFFTMag[j] / 32768. * pFFTMag[j] / 32768.;
        }
    }
    for ( j = 0; j < nSpecLen; j++ )
    {
        pNoiseEn[j] /= nNoiseFrame;
    }

    // get cirtical band mean filtered noise power
    AUD_Int32s k1 = 0, k2 = 0;
    for ( i = 0; i < CRITICAL_BAND_NUM; i++ )
    {
        k1 = k2;
        AUD_Double segSum = 0.;
        while ( k2 >= critFFTEnds[i] &&  k2 < critFFTEnds[i + 1] )
        {
            segSum += pNoiseEn[k2];
            k2++;
        }
        segSum /= ( k2 - k1 );

        for ( m = k1; m < k2; m++ )
        {
            pNoiseB[m] = segSum;
        }
    }

#if 0
    AUDLOG( "noise band spectrum:\n" );
    for ( j = 0; j < nSpecLen; j++ )
    {
        AUDLOG( "%.2f, ", pNoiseB[j] );
    }
    AUDLOG( "\n" );
#endif

    AUD_Matrix frameMatrix;
    frameMatrix.rows     = nSpecLen;
    frameMatrix.cols     = 1;
    frameMatrix.dataType = AUD_DATATYPE_DOUBLE;
    ret = createMatrix( &frameMatrix );
    AUD_ASSERT( ret == 0 );
    AUD_Double *pFrameEn = frameMatrix.pDouble;

    AUD_Matrix xMatrix;
    xMatrix.rows     = nSpecLen;
    xMatrix.cols     = 1;
    xMatrix.dataType = AUD_DATATYPE_DOUBLE;
    ret = createMatrix( &xMatrix );
    AUD_ASSERT( ret == 0 );
    AUD_Double *pX = xMatrix.pDouble;

    AUD_Matrix cMatrix;
    cMatrix.rows     = CRITICAL_BAND_NUM;
    cMatrix.cols     = 1;
    cMatrix.dataType = AUD_DATATYPE_DOUBLE;
    ret = createMatrix( &cMatrix );
    AUD_ASSERT( ret == 0 );
    AUD_Double *pC = cMatrix.pDouble;

    AUD_Matrix tMatrix;
    tMatrix.rows     = 1;
    tMatrix.cols     = CRITICAL_BAND_NUM;
    tMatrix.dataType = AUD_DATATYPE_DOUBLE;
    ret = createMatrix( &tMatrix );
    AUD_ASSERT( ret == 0 );
    AUD_Double *pT = tMatrix.pDouble;

    AUD_Matrix tkMatrix;
    tkMatrix.rows     = 1;
    tkMatrix.cols     = nSpecLen;
    tkMatrix.dataType = AUD_DATATYPE_DOUBLE;
    ret = createMatrix( &tkMatrix );
    AUD_ASSERT( ret == 0 );
    AUD_Double *pTk = tkMatrix.pDouble;

    AUD_Double dB0[CRITICAL_BAND_NUM];
    AUD_Double epsilon = pow( 2, -52 );

    #define ESTIMATE_MASKTHRESH( sigMatrix, tkMatrix )\
    do {\
        AUD_Double *pSig = sigMatrix.pDouble; \
        for ( m = 0; m < exPatMatrix.rows; m++ ) \
        { \
            AUD_Double suma = 0.; \
            AUD_Double *pExpatRow = exPatMatrix.pDouble + m * exPatMatrix.cols; \
            for ( n = 0; n < exPatMatrix.cols; n++ ) \
            { \
                suma += pExpatRow[n] * pSig[n]; \
            } \
            pC[m] = suma; \
        } \
        AUD_Double product = 1.; \
        AUD_Double sum     = 0.; \
        for ( m = 0; m < sigMatrix.rows; m++ ) \
        { \
            product *= pSig[m]; \
            sum     += pSig[m]; \
        } \
        AUD_Double power = 1. / sigMatrix.rows;\
        AUD_Double sfmDB = 10. * log10( pow( product, power ) / sum / sigMatrix.rows + epsilon ); \
        AUD_Double alpha = AUD_MIN( 1., sfmDB / (-60.) ); \
        for ( m = 0; m < tMatrix.cols; m++ ) \
        { \
            dB0[m] = dbOffset[m] * alpha + 5.5; \
            pT[m]  = pC[m] / pow( 10., dB0[m] / 10. ) / dcGain[m]; \
            pT[m]  = AUD_MAX( pT[m], absThr[m] ); \
        } \
        for ( m = 0; m < tkMatrix.cols; m++ ) \
        { \
            pTk[m] = pT[pLinToBark[m]]; \
        } \
       } while ( 0 )

    AUD_Double aa    = 0.98;
    AUD_Double mu    = 0.98;
    AUD_Double eta   = 0.15;
    AUD_Double vadDecision;

    k = 0;
    // start processing
    for ( i = 0; i < frameNum; i++ )
    {
        win16s_calc( hWin, pInBuf + i * frameStride, pFrame );

        fft_calc( hFft, pFrame, frameSize, pFFTRe, pFFTIm );

        // compute SNR
        vadDecision = 0.;
        for ( j = 0; j < nSpecLen; j++ )
        {
            pFrameEn[j] = pFFTRe[j] / 32768. * pFFTRe[j] / 32768. + pFFTIm[j] / 32768. * pFFTIm[j] / 32768.;

            pGammak[j]  = AUD_MIN( pFrameEn[j] / pNoiseEn[j], 40. );

            if ( i > 0 )
            {
                pKsi[j] = aa * pXPrev[j] / pNoiseEn[j] + ( 1 - aa ) * AUD_MAX( pGammak[j] - 1., 0. );
            }
            else
            {
                pKsi[j] = aa + ( 1. - aa ) * AUD_MAX( pGammak[j] - 1., 0. );
            }

            pLogSigmak[j] = pGammak[j] * pKsi[j] / ( 1. + pKsi[j] ) - log( 1. + pKsi[j] );

            vadDecision += ( j > 0 ? 2 : 1 ) * pLogSigmak[j];
        }
        vadDecision /= nFFT;

#if 0
        AUDLOG( "X prev:\n" );
        for ( j = 0; j < nSpecLen; j++ )
        {
            AUDLOG( "%.2f, ", pXPrev[j] );
        }
        AUDLOG( "\n" );
#endif

#if 0
        AUDLOG( "gamma k:\n" );
        for ( j = 0; j < nSpecLen; j++ )
        {
            AUDLOG( "%.2f, ", pGammak[j] );
        }
        AUDLOG( "\n" );
#endif

#if 0
        AUDLOG( "ksi:\n" );
        for ( j = 0; j < nSpecLen; j++ )
        {
            AUDLOG( "%.2f, ", pKsi[j] );
        }
        AUDLOG( "\n" );
#endif

#if 0
        AUDLOG( "log sigma k:\n" );
        for ( j = 0; j < nSpecLen; j++ )
        {
            AUDLOG( "%.2f, ", pLogSigmak[j] );
        }
        AUDLOG( "\n" );
#endif

        // AUDLOG( "vadDecision: %.2f\n", vadDecision );
        // re-estimate noise
        if ( vadDecision < eta )
        {
            for ( j = 0; j < nSpecLen; j++ )
            {
                pNoiseEn[j] = mu * pNoiseEn[j] + ( 1. - mu ) * pFrameEn[j];
            }

            // re-estimate crital band based noise
            AUD_Int32s k1 = 0, k2 = 0;
            for ( int band = 0; band < CRITICAL_BAND_NUM; band++ )
            {
                k1 = k2;
                AUD_Double segSum = 0.;
                while ( k2 >= critFFTEnds[band] &&  k2 < critFFTEnds[band + 1] )
                {
                    segSum += pNoiseEn[k2];
                    k2++;
                }
                segSum /= ( k2 - k1 );

                for ( m = k1; m < k2; m++ )
                {
                    pNoiseB[m] = segSum;
                }
            }

#if 0
            AUDLOG( "noise band spectrum:\n" );
            for ( j = 0; j < nSpecLen; j++ )
            {
                AUDLOG( "%.2f, ", pNoiseB[j] );
            }
            AUDLOG( "\n" );
#endif
        }

        for ( j = 0; j < nSpecLen; j++ )
        {
            pX[j]     = AUD_MAX( pFrameEn[j] - pNoiseEn[j], 0.001 );
            pXPrev[j] = pFrameEn[j];
        }

        ESTIMATE_MASKTHRESH( xMatrix, tkMatrix );
        for ( int iter = 0; iter < 2; iter++ )
        {
            for ( j = 0; j < nSpecLen; j++ )
            {
                pAb[j]      = pNoiseB[j] + pNoiseB[j] * pNoiseB[j] / pTk[j];
                pFrameEn[j] = pFrameEn[j] * pFrameEn[j] / ( pFrameEn[j] + pAb[j] );
                ESTIMATE_MASKTHRESH( frameMatrix, tkMatrix );

#if 0
                showMatrix( &tMatrix );
#endif
            }
        }

#if 0
        AUDLOG( "tk:\n" );
        for ( j = 0; j < nSpecLen; j++ )
        {
            AUDLOG( "%.2f, ", pTk[j] );
        }
        AUDLOG( "\n" );
#endif

        pAlpha[0]      = ( pNoiseB[0] + pTk[0] ) * ( pNoiseB[0] / pTk[0] );
        pH[0]          = pFrameEn[0] / ( pFrameEn[0] + pAlpha[0] );
        pXPrev[0]     *= pH[0] * pH[0];
        pFFTCleanRe[0] = 0;
        pFFTCleanIm[0] = 0;
        for ( j = 1; j < nSpecLen; j++ )
        {
            pAlpha[j] = ( pNoiseB[j] + pTk[j] ) * ( pNoiseB[j] / pTk[j] );

            pH[j]     = pFrameEn[j] / ( pFrameEn[j] + pAlpha[j] );

            pFFTCleanRe[j] = pFFTCleanRe[nFFT - j] = (AUD_Int32s)round( pH[j] * pFFTRe[j] );
            pFFTCleanIm[j]        = (AUD_Int32s)round( pH[j] * pFFTIm[j] );
            pFFTCleanIm[nFFT - j] = -pFFTCleanIm[j];

            pXPrev[j] *= pH[j] * pH[j];
        }

#if 0
        AUDLOG( "denoise transfer function:\n" );
        for ( j = 0; j < nSpecLen; j++ )
        {
            AUDLOG( "%.2f, ", pH[j] );
        }
        AUDLOG( "\n" );
#endif

#if 0
        AUDLOG( "clean FFT with phase:\n" );
        for ( j = 0; j < nFFT; j++ )
        {
            AUDLOG( "%d + j%d, ", pFFTCleanRe[j], pFFTCleanIm[j] );
        }
        AUDLOG( "\n" );
#endif

        ifft_real( hIfft, pFFTCleanRe, pFFTCleanIm, nFFT, pxClean );

#if 0
        AUDLOG( "clean speech:\n" );
        for ( j = 0; j < nFFT; j++ )
        {
            AUDLOG( "%d, ", pxClean[j] );
        }
        AUDLOG( "\n" );
#endif

        for ( j = 0; j < frameStride; j++ )
        {
            if ( j < frameOverlap )
            {
                pOutBuf[k + j] = pxOld[j] + pxClean[j];
                pxOld[j] = pxClean[frameStride + j];
            }
            else
            {
                pOutBuf[k + j] = pxClean[j];
            }
        }

        k        += frameStride;
        cleanLen += frameStride;
    }

    // de-emphasis
    // sig_deemphasis( pOutBuf, pOutBuf, cleanLen );

    win16s_free( &hWin );
    fft_free( &hFft );
    ifft_free( &hIfft );

    free( pFrame );
    free( pNoiseEn );
    free( pNoiseB );

    free( pFFTMag );
    free( pFFTRe );
    free( pFFTIm );
    free( pXPrev );
    free( pAb );
    free( pH );

    free( pFFTCleanRe );
    free( pFFTCleanIm );

    free( pxOld );
    free( pxClean );

    free( pGammak );
    free( pKsi );
    free( pLogSigmak );
    free( pAlpha );
    free( pLinToBark );

    ret = createMatrix( &xMatrix );
    AUD_ASSERT( ret == 0 );

    ret = destroyMatrix( &exPatMatrix );
    AUD_ASSERT( ret == 0 );

    ret = destroyMatrix( &frameMatrix );
    AUD_ASSERT( ret == 0 );

    ret = destroyMatrix( &cMatrix );
    AUD_ASSERT( ret == 0 );

    ret = destroyMatrix( &tMatrix );
    AUD_ASSERT( ret == 0 );

    ret = destroyMatrix( &tkMatrix );
    AUD_ASSERT( ret == 0 );

    return cleanLen;
}
Пример #14
0
AUD_Int32s denoise_mmse( AUD_Int16s *pInBuf, AUD_Int16s *pOutBuf, AUD_Int32s inLen )
{
    Fft_16s        *hFft        = NULL;
    Ifft_16s       *hIfft       = NULL;
    AUD_Window16s  *hWin        = NULL;

    AUD_Int32s     frameSize    = 512;
    AUD_Int32s     frameStride  = 256;
    AUD_Int32s     frameOverlap = 256;
    AUD_Int32s     nFFT         = frameSize;
    AUD_Int32s     nSpecLen     = nFFT / 2 + 1;
    AUD_Int32s     nNoiseFrame  = (AUD_Int32s)( ( 0.25 * SAMPLE_RATE - frameSize ) / frameStride + 1 );;

    AUD_Int32s     i, j, k;

    AUD_Int32s     cleanLen = 0;

    // pre-emphasis
    // sig_preemphasis( pInBuf, pInBuf, inLen );

    // init hamming module
    win16s_init( &hWin, AUD_WIN_HAMM, frameSize, 14 );
    AUD_ASSERT( hWin );

    // init fft handle
    fft_init( &hFft, nFFT, 15 );
    AUD_ASSERT( hFft );

    // init ifft handle
    ifft_init( &hIfft, nFFT, 15 );
    AUD_ASSERT( hIfft );

    AUD_Int16s *pFrame  = (AUD_Int16s*)calloc( frameSize * sizeof(AUD_Int16s), 1 );
    AUD_ASSERT( pFrame );

    // FFT
    AUD_Int32s *pFFTMag  = (AUD_Int32s*)calloc( nFFT * sizeof(AUD_Int32s), 1 );
    AUD_ASSERT( pFFTMag );
    AUD_Int32s *pFFTRe   = (AUD_Int32s*)calloc( nFFT * sizeof(AUD_Int32s), 1 );
    AUD_ASSERT( pFFTRe );
    AUD_Int32s *pFFTIm   = (AUD_Int32s*)calloc( nFFT * sizeof(AUD_Int32s), 1 );
    AUD_ASSERT( pFFTIm );

    AUD_Int32s *pFFTCleanRe = (AUD_Int32s*)calloc( nFFT * sizeof(AUD_Int32s), 1 );
    AUD_ASSERT( pFFTCleanRe );
    AUD_Int32s *pFFTCleanIm = (AUD_Int32s*)calloc( nFFT * sizeof(AUD_Int32s), 1 );
    AUD_ASSERT( pFFTCleanIm );

    AUD_Double *pNoiseMean = (AUD_Double*)calloc( nSpecLen * sizeof(AUD_Double), 1 );
    AUD_ASSERT( pNoiseMean );
    AUD_Int32s *pFFTCleanMag = (AUD_Int32s*)calloc( nSpecLen * sizeof(AUD_Int32s), 1 );
    AUD_ASSERT( pFFTCleanMag );

    AUD_Int16s *pxOld   = (AUD_Int16s*)calloc( frameSize * sizeof(AUD_Int16s), 1 );
    AUD_ASSERT( pxOld );
    AUD_Int16s *pxClean = (AUD_Int16s*)calloc( frameSize * sizeof(AUD_Int16s), 1 );
    AUD_ASSERT( pxClean );


    for ( i = 0; (i < nNoiseFrame) && ( (i * frameStride + frameSize) < inLen ); i++ )
    {
        win16s_calc( hWin, pInBuf + i * frameSize, pFrame );

        fft_mag( hFft, pFrame, frameSize, pFFTMag );

        for ( j = 0; j < nSpecLen; j++ )
        {
            pNoiseMean[j] += (AUD_Double)pFFTMag[j];
        }
    }
    // compute noise mean
    for ( j = 0; j < nSpecLen; j++ )
    {
        pNoiseMean[j] /= nNoiseFrame;
    }

    AUD_Double thres = 3.;
    AUD_Double alpha = 2.;
    AUD_Double flr   = 0.002;
    AUD_Double G     = 0.9;
    AUD_Double snr, beta;
    AUD_Double tmp;
    AUD_Double sigEnergy, noiseEnergy;

    k = 0;
    // start processing
    for ( i = 0; (i * frameStride + frameSize) < inLen; i++ )
    {
        win16s_calc( hWin, pInBuf + i * frameStride, pFrame );

        fft_calc( hFft, pFrame, frameSize, pFFTRe, pFFTIm );

        // compute SNR
        sigEnergy   = 0.;
        noiseEnergy = 0.;
        for ( j = 0; j < nSpecLen; j++ )
        {
            tmp          = pFFTRe[j] / 32768. * pFFTRe[j] / 32768. + pFFTIm[j] / 32768. * pFFTIm[j] / 32768.;
            sigEnergy   += tmp;
            noiseEnergy += pNoiseMean[j] / 32768. * pNoiseMean[j] / 32768.;

            tmp = sqrt( tmp ) * 32768.;
            if ( tmp > MAX_INT32S )
            {
                AUD_ECHO
                pFFTMag[j] = MAX_INT32S;
            }
            else
            {
                pFFTMag[j] = (AUD_Int32s)round( tmp );
            }
        }

        snr  = 10. * log10( sigEnergy / noiseEnergy );
        beta = berouti( snr );

        // AUDLOG( "signal energy: %.2f, noise energy: %.2f, snr: %.2f, beta: %.2f\n", sigEnergy, noiseEnergy, snr, beta );

#if 0
        AUDLOG( "noisy FFT:\n" );
        for ( j = 0; j < nSpecLen; j++ )
        {
            AUDLOG( "%d, ", pFFTMag[j] );
        }
        AUDLOG( "\n" );
#endif

        tmp = 0.;
        for ( j = 0; j < nSpecLen; j++ )
        {
            tmp  = AUD_MAX( pow( pFFTMag[j], alpha ) - beta * pow( pNoiseMean[j], alpha ), flr * pow( pNoiseMean[j], alpha ) );

            pFFTCleanMag[j] = (AUD_Int32s)round( pow( tmp, 1. / alpha ) );
        }

        // re-estimate noise
        if ( snr < thres )
        {
            AUD_Double tmpNoise;
            for ( j = 0; j < nSpecLen; j++ )
            {
                tmpNoise = G * pow( pNoiseMean[j], alpha ) + ( 1 - G ) * pow( pFFTMag[j], alpha );
                pNoiseMean[j] = pow( tmpNoise, 1. / alpha );
            }
        }

#if 0
        AUDLOG( "clean FFT:\n" );
        for ( j = 0; j < nSpecLen; j++ )
        {
            AUDLOG( "%d, ", pFFTCleanMag[j] );
        }
        AUDLOG( "\n" );
#endif

        pFFTCleanRe[0] = pFFTCleanMag[0];
        pFFTCleanIm[0] = 0;
        AUD_Double costheta, sintheta;
        for ( j = 1; j < nSpecLen; j++ )
        {
            if ( pFFTMag[j] != 0 )
            {
                costheta = (AUD_Double)pFFTRe[j] / (AUD_Double)pFFTMag[j];
                sintheta = (AUD_Double)pFFTIm[j] / (AUD_Double)pFFTMag[j];
                pFFTCleanRe[nFFT - j] = pFFTCleanRe[j] = (AUD_Int32s)round( costheta * pFFTCleanMag[j] );
                pFFTCleanIm[j]        = (AUD_Int32s)round( sintheta * pFFTCleanMag[j] );
                pFFTCleanIm[nFFT - j] = -pFFTCleanIm[j];
            }
            else
            {
                pFFTCleanRe[nFFT - j] = pFFTCleanRe[j] = pFFTCleanMag[j];
                pFFTCleanIm[nFFT - j] = pFFTCleanIm[j] = 0;
            }
        }

#if 0
        AUDLOG( "clean FFT with phase:\n" );
        for ( j = 0; j < nFFT; j++ )
        {
            AUDLOG( "%d + j%d, ", pFFTCleanRe[j], pFFTCleanIm[j] );
        }
        AUDLOG( "\n" );
#endif

        ifft_real( hIfft, pFFTCleanRe, pFFTCleanIm, nFFT, pxClean );

#if 0
        AUDLOG( "clean speech:\n" );
        for ( j = 0; j < nFFT; j++ )
        {
            AUDLOG( "%d, ", pxClean[j] );
        }
        AUDLOG( "\n" );
#endif

        for ( j = 0; j < frameStride; j++ )
        {
            pOutBuf[k + j] = pxOld[j] + pxClean[j];
            pxOld[j]       = pxClean[frameOverlap + j];
        }

        k        += frameStride;
        cleanLen += frameStride;
    }

    // de-emphasis
    // sig_deemphasis( pOutBuf, pOutBuf, cleanLen );

    win16s_free( &hWin );
    fft_free( &hFft );
    ifft_free( &hIfft );

    free( pFrame );
    free( pNoiseMean );

    free( pFFTMag );
    free( pFFTRe );
    free( pFFTIm );

    free( pFFTCleanMag );
    free( pFFTCleanRe );
    free( pFFTCleanIm );

    free( pxOld );
    free( pxClean );

    return cleanLen;
}
Пример #15
0
AUD_Int32s denoise_wiener( AUD_Int16s *pInBuf, AUD_Int16s *pOutBuf, AUD_Int32s inLen )
{
    Fft_16s        *hFft        = NULL;
    Ifft_16s       *hIfft       = NULL;
    AUD_Window16s  *hWin        = NULL;
    _VAD_Nest      vadState;

    AUD_Int32s     frameSize    = 512;
    AUD_Int32s     frameStride  = 256;
    AUD_Int32s     nFFT         = frameSize;
    AUD_Int32s     nSpecLen     = nFFT / 2 + 1;
    AUD_Int32s     nNoiseFrame  = (AUD_Int32s)( ( 0.25 * SAMPLE_RATE - frameSize ) / frameStride + 1 );

    AUD_Int32s     i, j, k;

    AUD_Int32s     cleanLen = 0;

    vadState.meanEn        = 280;
    vadState.nbSpeechFrame = 0;
    vadState.hangOver      = 0;

    AUD_Int16s *pFrame  = (AUD_Int16s*)calloc( frameSize * sizeof(AUD_Int16s), 1 );
    AUD_ASSERT( pFrame );

    AUD_Double *pNoiseMean = (AUD_Double*)calloc( nSpecLen * sizeof(AUD_Double), 1 );
    AUD_ASSERT( pNoiseMean );

    AUD_Double *pLamdaD = (AUD_Double*)calloc( nSpecLen * sizeof(AUD_Double), 1 );
    AUD_ASSERT( pLamdaD );

    AUD_Double *pXi = (AUD_Double*)calloc( nSpecLen * sizeof(AUD_Double), 1 );
    AUD_ASSERT( pXi );

    AUD_Double *pGamma = (AUD_Double*)calloc( nSpecLen * sizeof(AUD_Double), 1 );
    AUD_ASSERT( pGamma );

    AUD_Double *pG = (AUD_Double*)calloc( nSpecLen * sizeof(AUD_Double), 1 );
    AUD_ASSERT( pG );

    AUD_Double *pGammaNew = (AUD_Double*)calloc( nSpecLen * sizeof(AUD_Double), 1 );
    AUD_ASSERT( pGammaNew );

    for ( j = 0; j < nSpecLen; j++ )
    {
        pG[j]         = 1.;
        pGamma[j]     = 1.;
    }

    // FFT
    AUD_Int32s *pFFTMag  = (AUD_Int32s*)calloc( nFFT * sizeof(AUD_Int32s), 1 );
    AUD_ASSERT( pFFTMag );
    AUD_Int32s *pFFTRe   = (AUD_Int32s*)calloc( nFFT * sizeof(AUD_Int32s), 1 );
    AUD_ASSERT( pFFTRe );
    AUD_Int32s *pFFTIm   = (AUD_Int32s*)calloc( nFFT * sizeof(AUD_Int32s), 1 );
    AUD_ASSERT( pFFTIm );

    AUD_Double *pFFTCleanMag = (AUD_Double*)calloc( nFFT * sizeof(AUD_Double), 1 );
    AUD_ASSERT( pFFTCleanMag );

    AUD_Int32s *pFFTCleanRe = (AUD_Int32s*)calloc( nFFT * sizeof(AUD_Int32s), 1 );
    AUD_ASSERT( pFFTCleanRe );
    AUD_Int32s *pFFTCleanIm = (AUD_Int32s*)calloc( nFFT * sizeof(AUD_Int32s), 1 );
    AUD_ASSERT( pFFTCleanIm );

    AUD_Int16s *pxClean = (AUD_Int16s*)calloc( nFFT * sizeof(AUD_Int16s), 1 );
    AUD_ASSERT( pxClean );

    memset( pOutBuf, 0, inLen * sizeof(AUD_Int16s) );

    // init hamming module
    win16s_init( &hWin, AUD_WIN_HAMM, frameSize, 14 );
    AUD_ASSERT( hWin );

    // init fft handle
    fft_init( &hFft, nFFT, 15 );
    AUD_ASSERT( hFft );

    // init ifft handle
    ifft_init( &hIfft, nFFT, 15 );
    AUD_ASSERT( hIfft );

    // noise manipulation
    for ( i = 0; (i < nNoiseFrame) && ( (i * frameStride + frameSize) < inLen ); i++ )
    {
        win16s_calc( hWin, pInBuf + i * frameStride, pFrame );

        fft_mag( hFft, pFrame, frameSize, pFFTMag );

        for ( j = 0; j < nSpecLen; j++ )
        {
            pNoiseMean[j] += (AUD_Double)pFFTMag[j];
            pLamdaD[j]    += (AUD_Double)pFFTMag[j] * (AUD_Double)pFFTMag[j];
        }
    }
    // compute noise mean
    for ( j = 0; j < nSpecLen; j++ )
    {
        pNoiseMean[j] /= nNoiseFrame;
        pLamdaD[j]    /= nNoiseFrame;
    }

    AUD_Int32s vadFlag  = 0;
    AUD_Double noiseLen = 9.;
    AUD_Double alpha    = 0.99;
    k = 0;
    for ( i = 0; (i * frameStride + frameSize) < inLen; i++ )
    {
        win16s_calc( hWin, pInBuf + i * frameStride, pFrame );

        fft_calc( hFft, pFrame, frameSize, pFFTRe, pFFTIm );

        for ( j = 0; j < nSpecLen; j++ )
        {
            pFFTMag[j] = (AUD_Int32s)round( sqrt( (AUD_Double)pFFTRe[j] * pFFTRe[j] + (AUD_Double)pFFTIm[j] * pFFTIm[j] ) );
        }

#if 0
        AUDLOG( "noisy FFT:\n" );
        for ( j = 0; j < nSpecLen; j++ )
        {
            AUDLOG( "%d, ", pFFTMag[j] );
        }
        AUDLOG( "\n" );
#endif

        vadFlag = vad_nest( &vadState, pFrame, frameSize );
        if ( vadFlag == 0 )
        {
            for ( j = 0; j < nSpecLen; j++ )
            {
                pNoiseMean[j] = ( noiseLen * pNoiseMean[j] + (AUD_Double)pFFTMag[j] ) / ( noiseLen + 1. );
                pLamdaD[j]    = ( noiseLen * pLamdaD[j] + (AUD_Double)pFFTMag[j] * pFFTMag[j] ) / ( noiseLen + 1. );
            }
        }

        for ( j = 0; j < nSpecLen; j++ )
        {
            pGammaNew[j] = (AUD_Double)pFFTMag[j] * pFFTMag[j] / pLamdaD[j];
            pXi[j]       = alpha * pG[j] * pG[j] * pGamma[j] + ( 1. - alpha ) * AUD_MAX( pGammaNew[j] - 1., 0. );
            pGamma[j]    = pGammaNew[j];
            pG[j]        = pXi[j]  / ( pXi[j] + 1. );

            pFFTCleanMag[j] = pG[j] * pFFTMag[j];
        }

#if 0
        AUDLOG( "clean FFT:\n" );
        for ( j = 0; j < nSpecLen; j++ )
        {
            AUDLOG( "%.2f, ", pFFTCleanMag[j] );
        }
        AUDLOG( "\n" );
#endif

        // combine to real/im part of IFFT
        pFFTCleanRe[0] = pFFTCleanMag[0];
        pFFTCleanIm[0] = 0;
        AUD_Double costheta, sintheta;
        for ( j = 1; j < nSpecLen; j++ )
        {
            if ( pFFTMag[j] != 0 )
            {
                costheta = (AUD_Double)pFFTRe[j] / (AUD_Double)pFFTMag[j];
                sintheta = (AUD_Double)pFFTIm[j] / (AUD_Double)pFFTMag[j];
                pFFTCleanRe[nFFT - j] = pFFTCleanRe[j] = (AUD_Int32s)round( costheta * pFFTCleanMag[j] );
                pFFTCleanIm[j] = (AUD_Int32s)round( sintheta * pFFTCleanMag[j] );
                pFFTCleanIm[nFFT - j] = -pFFTCleanIm[j];
            }
            else
            {
                pFFTCleanRe[nFFT - j] = pFFTCleanRe[j] = pFFTCleanMag[j];
                pFFTCleanIm[nFFT - j] = pFFTCleanIm[j] = 0;
            }
        }

        ifft_real( hIfft, pFFTCleanRe, pFFTCleanIm, nFFT, pxClean );

#if 0
        AUDLOG( "clean FFT with phase:\n" );
        for ( j = 0; j < nFFT; j++ )
        {
            AUDLOG( "%d + j%d, ", pFFTCleanRe[j], pFFTCleanIm[j] );
        }
        AUDLOG( "\n" );
#endif

        for ( j = 0; j < frameSize; j++ )
        {
            pOutBuf[k + j] = pOutBuf[k + j] + pxClean[j];
        }

        k        += frameStride;
        cleanLen += frameStride;
    }

    win16s_free( &hWin );
    fft_free( &hFft );
    ifft_free( &hIfft );

    free( pFrame );
    free( pNoiseMean );
    free( pLamdaD );
    free( pXi );
    free( pGamma );
    free( pG );
    free( pGammaNew );

    free( pFFTMag );
    free( pFFTRe );
    free( pFFTIm );

    free( pFFTCleanMag );
    free( pFFTCleanRe );
    free( pFFTCleanIm );

    free( pxClean );

    return cleanLen;
}