Пример #1
1
void  sc_kaiser_Sinc(double *x,int N,double *y)
{	
	for (register int i=0;i<N;i++)
	{		
		y[i] = sinc(x[i])*kaiser(x[i],N/2,3);
	}
}
Пример #2
0
// Design FIR doppler filter
//  _n      : filter length
//  _fd     : normalized doppler frequency (0 < _fd < 0.5)
//  _K      : Rice fading factor (K >= 0)
//  _theta  : LoS component angle of arrival
//  _h      : output coefficient buffer
void liquid_firdes_doppler(unsigned int _n,
                           float        _fd,
                           float        _K,
                           float        _theta,
                           float *      _h)
{
    float t, J, r, w;
    float beta = 4; // kaiser window parameter
    unsigned int i;
    for (i=0; i<_n; i++) {
        // time sample
        t = (float)i - (float)(_n-1)/2;

        // Bessel
        J = 1.5*liquid_besselj0f(fabsf((float)(2*M_PI*_fd*t)));

        // Rice-K component
        r = 1.5*_K/(_K+1)*cosf(2*M_PI*_fd*t*cosf(_theta));

        // Window
        w = kaiser(i, _n, beta, 0);

        // composite
        _h[i] = (J+r)*w;

        //printf("t=%f, J=%f, r=%f, w=%f\n", t, J, r, w);
    }
}
Пример #3
0
// create a resamp2 object
//  _m      :   filter semi-length (effective length: 4*_m+1)
//  _fc     :   center frequency of half-band filter
//  _As     :   stop-band attenuation [dB], _As > 0
RESAMP2() RESAMP2(_create)(unsigned int _m,
                           float        _fc,
                           float        _As)
{
    // validate input
    if (_m < 2) {
        fprintf(stderr,"error: resamp2_%s_create(), filter semi-length must be at least 2\n", EXTENSION_FULL);
        exit(1);
    }

    RESAMP2() q = (RESAMP2()) malloc(sizeof(struct RESAMP2(_s)));
    q->m  = _m;
    q->fc = _fc;
    q->As = _As;
    if ( q->fc < -0.5f || q->fc > 0.5f ) {
        fprintf(stderr,"error: resamp2_%s_create(), fc (%12.4e) must be in (-1,1)\n", EXTENSION_FULL, q->fc);
        exit(1);
    }

    // change filter length as necessary
    q->h_len = 4*(q->m) + 1;
    q->h = (TC *) malloc((q->h_len)*sizeof(TC));

    q->h1_len = 2*(q->m);
    q->h1 = (TC *) malloc((q->h1_len)*sizeof(TC));

    // design filter prototype
    unsigned int i;
    float t, h1, h2;
    TC h3;
    float beta = kaiser_beta_As(q->As);
    for (i=0; i<q->h_len; i++) {
        t = (float)i - (float)(q->h_len-1)/2.0f;
        h1 = sincf(t/2.0f);
        h2 = kaiser(i,q->h_len,beta,0);
#if TC_COMPLEX == 1
        h3 = cosf(2.0f*M_PI*t*q->fc) + _Complex_I*sinf(2.0f*M_PI*t*q->fc);
#else
        h3 = cosf(2.0f*M_PI*t*q->fc);
#endif
        q->h[i] = h1*h2*h3;
    }

    // resample, alternate sign, [reverse direction]
    unsigned int j=0;
    for (i=1; i<q->h_len; i+=2)
        q->h1[j++] = q->h[q->h_len - i - 1];

    // create dotprod object
    q->dp = DOTPROD(_create)(q->h1, 2*q->m);

    // create window buffers
    q->w0 = WINDOW(_create)(2*(q->m));
    q->w1 = WINDOW(_create)(2*(q->m));

    RESAMP2(_clear)(q);

    return q;
}
Пример #4
0
// Generate polyphase coefficients for channeliser
float *generatePolyphaseCoefficients(unsigned nchans, unsigned ntaps, FirWindow windowType)
{
    unsigned n = nchans * ntaps;

    double* window = new double[n];

    switch (windowType) {
        case HAMMING:
        {
            hamming(n, window);
            break;
        }
        case BLACKMAN:
        {
            blackman(n, window);
            break;
        }
        case GAUSSIAN:
        {
            double alpha = 3.5;
            gaussian(n, alpha, window);
            break;
        }
        case KAISER:
        {
            double beta = 9.0695;
            kaiser(n, beta, window);
            break;
        }
        default:
        {
            fprintf(stderr, "Invalid PFB window type. Exiting\n");
            exit(-1);
        }
    }

    double* result = new double[n];
    generateFirFilter(n - 1, 1.0 / nchans, window, result);

    delete[] window;
    
    float *coeff = (float *) malloc(nchans * ntaps * sizeof(float));

    for(unsigned t = 0; t < ntaps; ++t) {
        for(unsigned c = 0; c < nchans; ++c) {
            unsigned index = t * nchans + c;
            coeff[index] = result[index] / nchans;
            if (c % 2 == 0)
                coeff[index] = result[index] / nchans;
            else
                coeff[index] = -result[index] / nchans;
        }
    }

    delete[] result;

    return coeff;

}
Пример #5
0
void direct_calib(const long dims[5], complex float* sens, const long caldims[5], const complex float* data)
{
	complex float* tmp = md_alloc(5, caldims, CFL_SIZE);

	assert(1 == caldims[4]);
	assert(1 == dims[4]);

	md_copy(5, caldims, tmp, data, CFL_SIZE);

	// apply Kaiser-Bessel Window beta=4
	for (int z = 0; z < caldims[2]; z++)
		for (int y = 0; y < caldims[1]; y++)
			for (int x = 0; x < caldims[0]; x++)
				for (int c = 0; c < caldims[3]; c++)
					tmp[((c * caldims[2] + z) * caldims[1] + y) * caldims[0] + x]
						*= kaiser(4., caldims[2], z)
						* kaiser(4., caldims[1], y)
						* kaiser(4., caldims[0], x);

	md_resize_center(5, dims, sens, caldims, tmp, CFL_SIZE);

	ifftc(5, dims, 7, sens, sens);

	long dims1[5];
	md_select_dims(5, ~MD_BIT(COIL_DIM), dims1, dims);

	complex float* img = md_alloc(5, dims1, CFL_SIZE);

	md_zrss(5, dims, COIL_FLAG, img, sens);
#if 1
	long T = md_calc_size(5, dims1);
	for (int i = 0; i < T; i++)
		for (int j = 0; j < dims[COIL_DIM]; j++)
			sens[j * T + i] *= (cabs(img[i]) == 0.) ? 0. : (1. / cabs(img[i]));
#endif
	md_free(img);
}
Пример #6
0
/*
 * Returns a pointer to an array of length len representing one half of a
 * Kaiser sequence of size (len - 1) * 2 with shape alpha.
 */
double *
kaiser_table(double alpha, int len)
{
	double *ret;
	int i;
	int M = (len - 1) * 2;

	if ((ret = (double *)calloc(len, sizeof(double))) == NULL)
		return NULL;

	for (i = 0; i < len; i++)
		ret[i] = kaiser(alpha, M, len - i - 1);

	return ret;
}
Пример #7
0
static double *
make_low_pass_filter(double omega_pass, double omega_stop, double error, int *length_p)
{
	struct filter_param	p = filter(omega_pass, omega_stop, error);
	int		length;
	int		n;
	double		*lpf;

	length = p.M + 1;
	lpf = calloc (length, sizeof(double));
	for (n = 0; n < length; n++)
		lpf[n] = lowpass(n, p.M, omega_pass) * kaiser(n, p.M, p.beta);
	*length_p = length;
	return lpf;
}
Пример #8
0
static Resample_Real kaiser_filter(Resample_Real t)
{
   if (t < 0.0f)
      t = -t;

   if (t < KAISER_SUPPORT)
   {
      // db atten
      const Resample_Real att = 40.0f;
      const Resample_Real alpha = (Resample_Real)(exp(log((double)0.58417 * (att - 20.96)) * 0.4) + 0.07886 * (att - 20.96));
      //const Resample_Real alpha = KAISER_ALPHA;
      return (Resample_Real)clean(sinc(t) * kaiser(alpha, KAISER_SUPPORT, t));
   }

   return 0.0f;
}
Пример #9
0
    static float kaiser_filter(float t)
    {
        if (t < 0.0f)
            t = -t;

        if (t < KAISER_SUPPORT)
        {
            // db atten
            const float att = 40.0f;
            const float alpha = (float)(exp(log((double)0.58417 * (att - 20.96)) * 0.4) + 0.07886 * (att - 20.96));
            //const float alpha = KAISER_ALPHA;
            return (float)clean(sinc(t) * kaiser(alpha, KAISER_SUPPORT, t));
        }

        return 0.0f;
    }
Пример #10
0
// Kaiser-Bessel derived window (full window function)
void liquid_kbd_window(unsigned int _n,
                       float _beta,
                       float * _w)
{
    unsigned int i;
    // TODO add reference

    // validate input
    if (_n == 0) {
        fprintf(stderr,"error: liquid_kbd_window(), window length must be greater than zero\n");
        exit(1);
    } else if ( _n % 2 ) {
        fprintf(stderr,"error: liquid_kbd_window(), window length must be odd\n");
        exit(1);
    } else if ( _beta < 0.0f ) {
        fprintf(stderr,"error: liquid_kbd_window(), _beta must be positive\n");
        exit(1);
    }

    // compute half length
    unsigned int M = _n / 2;

    // generate regular Kaiser window, length M+1
    float w_kaiser[M+1];
    for (i=0; i<=M; i++)
        w_kaiser[i] = kaiser(i,M+1,_beta,0.0f);

    // compute sum(wk[])
    float w_sum = 0.0f;
    for (i=0; i<=M; i++)
        w_sum += w_kaiser[i];

    // accumulate window
    float w_acc = 0.0f;
    for (i=0; i<M; i++) {
        w_acc += w_kaiser[i];
        _w[i] = sqrtf(w_acc / w_sum);
    }

    // window has even symmetry; flip around index M
    for (i=0; i<M; i++)
        _w[_n-i-1] = _w[i];
}
Пример #11
0
double *xtract_init_window(const int N, const int type)
{
    double *window;

    window = malloc(N * sizeof(double));

    switch (type)
    {
    case XTRACT_GAUSS:
        gauss(window, N, 0.4);
        break;
    case XTRACT_HAMMING:
        hamming(window, N);
        break;
    case XTRACT_HANN:
        hann(window, N);
        break;
    case XTRACT_BARTLETT:
        bartlett(window, N);
        break;
    case XTRACT_TRIANGULAR:
        triangular(window, N);
        break;
    case XTRACT_BARTLETT_HANN:
        bartlett_hann(window, N);
        break;
    case XTRACT_BLACKMAN:
        blackman(window, N);
        break;
    case XTRACT_KAISER:
        kaiser(window, N, 3 * PI);
        break;
    case XTRACT_BLACKMAN_HARRIS:
        blackman_harris(window, N);
        break;
    default:
        hann(window, N);
        break;
    }

    return window;
}
Пример #12
0
double window(int type,int n,int i,double beta)
{
	/* 函数名称:
	 * 	窗口函数
	 * */
	int k;
	double pi,w;
	pi=4.0*atan(1.0);
	w=1.0;
	switch(type)
	{
	case 1:
		w=1.0;break;
	case 2:
		k=(n-2)/10;
		if(i<=k)
			w=0.5*(1.0-cos(i*pi/(k+1)));
		if(i>n-k-2)
			w=0.5*(1.0-cos((n-i-1)*pi/(k+1)));
		break;
	case 3:
		w=1.0-fabs(1.0-2*i/(n-1.0));
		break;
	case 4:
		w=0.5*(1.0-cos(2*pi*i/(n-1)));
		break;
	case 5:
		w=0.54-0.46*cos(2*pi*i/(n-1));
		break;
	case 6:
		w=0.42-0.5*cos(2*i*pi/(n-1))+0.08*cos(4*i*pi/(n-1));
		break;
	case 7:
		w=kaiser(i,n,beta);
		break;

	}
	return w;

	}
Пример #13
0
/*
 * fir coef in g, cuttoff frequency in fc
 */
static void designfir(float *g , float fc)
{
    int i;
    float xi, omega, att, beta ;
    float w[ORDER2];

    for (i =0; i < ORDER2 ; i++)
    {
        xi = (float) i + 0.5;
        omega = PI * xi;
        g[i] = sin( (double) omega * fc) / omega;
    }

    att = 40.; /* attenuation  in  db */
    beta = (float) exp(log((double)0.58417 * (att - 20.96)) * 0.4) + 0.07886
           * (att - 20.96);
    kaiser( w, ORDER2, beta);

    /* Matrix product */
    for (i =0; i < ORDER2 ; i++)
        g[i] = g[i] * w[i];
}
Пример #14
0
// Design FIR using kaiser window
//  _n      : filter length, _n > 0
//  _fc     : cutoff frequency, 0 < _fc < 0.5
//  _As     : stop-band attenuation [dB], _As > 0
//  _mu     : fractional sample offset, -0.5 < _mu < 0.5
//  _h      : output coefficient buffer, [size: _n x 1]
void liquid_firdes_kaiser(unsigned int _n,
                          float _fc,
                          float _As,
                          float _mu,
                          float *_h)
{
    // validate inputs
    if (_mu < -0.5f || _mu > 0.5f) {
        fprintf(stderr,"error: liquid_firdes_kaiser(), _mu (%12.4e) out of range [-0.5,0.5]\n", _mu);
        exit(1);
    } else if (_fc < 0.0f || _fc > 0.5f) {
        fprintf(stderr,"error: liquid_firdes_kaiser(), cutoff frequency (%12.4e) out of range (0, 0.5)\n", _fc);
        exit(1);
    } else if (_n == 0) {
        fprintf(stderr,"error: liquid_firdes_kaiser(), filter length must be greater than zero\n");
        exit(1);
    }

    // choose kaiser beta parameter (approximate)
    float beta = kaiser_beta_As(_As);

    float t, h1, h2; 
    unsigned int i;
    for (i=0; i<_n; i++) {
        t = (float)i - (float)(_n-1)/2 + _mu;
     
        // sinc prototype
        h1 = sincf(2.0f*_fc*t);

        // kaiser window
        h2 = kaiser(i,_n,beta,_mu);

        //printf("t = %f, h1 = %f, h2 = %f\n", t, h1, h2);

        // composite
        _h[i] = h1*h2;
    }
}
Пример #15
0
// Kaiser-Bessel derived window
float liquid_kbd(unsigned int _n,
                 unsigned int _N,
                 float _beta)
{
    // TODO add reference

    // validate input
    if (_n >= _N) {
        fprintf(stderr,"error: liquid_kbd(), index exceeds maximum\n");
        exit(1);
    } else if (_N == 0) {
        fprintf(stderr,"error: liquid_kbd(), window length must be greater than zero\n");
        exit(1);
    } else if ( _N % 2 ) {
        fprintf(stderr,"error: liquid_kbd(), window length must be odd\n");
        exit(1);
    }

    unsigned int M = _N / 2;
    if (_n >= M)
        return liquid_kbd(_N-_n-1,_N,_beta);

    float w0 = 0.0f;
    float w1 = 0.0f;
    float w;
    unsigned int i;
    for (i=0; i<=M; i++) {
        // compute Kaiser window
        w = kaiser(i,M+1,_beta,0.0f);

        // accumulate window sums
        w1 += w;
        if (i <= _n) w0 += w;
    }
    //printf("%12.8f / %12.8f = %12.8f\n", w0, w1, w0/w1);

    return sqrtf(w0 / w1);
}
Пример #16
0
// create spgram object
//  _nfft       : FFT size
//  _wtype      : window type, e.g. LIQUID_WINDOW_HAMMING
//  _window_len : window length
//  _delay      : delay between transforms, _delay > 0
SPGRAM() SPGRAM(_create)(unsigned int _nfft,
                         int          _wtype,
                         unsigned int _window_len,
                         unsigned int _delay)
{
    // validate input
    if (_nfft < 2) {
        fprintf(stderr,"error: spgram%s_create(), fft size must be at least 2\n", EXTENSION);
        exit(1);
    } else if (_window_len > _nfft) {
        fprintf(stderr,"error: spgram%s_create(), window size cannot exceed fft size\n", EXTENSION);
        exit(1);
    } else if (_window_len == 0) {
        fprintf(stderr,"error: spgram%s_create(), window size must be greater than zero\n", EXTENSION);
        exit(1);
    } else if (_wtype == LIQUID_WINDOW_KBD && _window_len % 2) {
        fprintf(stderr,"error: spgram%s_create(), KBD window length must be even\n", EXTENSION);
        exit(1);
    } else if (_delay == 0) {
        fprintf(stderr,"error: spgram%s_create(), delay must be greater than 0\n", EXTENSION);
        exit(1);
    }

    // allocate memory for main object
    SPGRAM() q = (SPGRAM()) malloc(sizeof(struct SPGRAM(_s)));

    // set input parameters
    q->nfft       = _nfft;
    q->wtype      = _wtype;
    q->window_len = _window_len;
    q->delay      = _delay;
    q->frequency  =  0;
    q->sample_rate= -1;

    // set object for full accumulation
    SPGRAM(_set_alpha)(q, -1.0f);

    // create FFT arrays, object
    q->buf_time = (TC*) malloc((q->nfft)*sizeof(TC));
    q->buf_freq = (TC*) malloc((q->nfft)*sizeof(TC));
    q->psd      = (T *) malloc((q->nfft)*sizeof(T ));
    q->fft      = FFT_CREATE_PLAN(q->nfft, q->buf_time, q->buf_freq, FFT_DIR_FORWARD, FFT_METHOD);

    // create buffer
    q->buffer = WINDOW(_create)(q->window_len);

    // create window
    q->w = (T*) malloc((q->window_len)*sizeof(T));
    unsigned int i;
    unsigned int n = q->window_len;
    float beta = 10.0f;
    float zeta =  3.0f;
    for (i=0; i<n; i++) {
        switch (q->wtype) {
        case LIQUID_WINDOW_HAMMING:         q->w[i] = hamming(i,n);         break;
        case LIQUID_WINDOW_HANN:            q->w[i] = hann(i,n);            break;
        case LIQUID_WINDOW_BLACKMANHARRIS:  q->w[i] = blackmanharris(i,n);  break;
        case LIQUID_WINDOW_BLACKMANHARRIS7: q->w[i] = blackmanharris7(i,n); break;
        case LIQUID_WINDOW_KAISER:          q->w[i] = kaiser(i,n,beta,0);   break;
        case LIQUID_WINDOW_FLATTOP:         q->w[i] = flattop(i,n);         break;
        case LIQUID_WINDOW_TRIANGULAR:      q->w[i] = triangular(i,n,n);    break;
        case LIQUID_WINDOW_RCOSTAPER:       q->w[i] = liquid_rcostaper_windowf(i,n/3,n); break;
        case LIQUID_WINDOW_KBD:             q->w[i] = liquid_kbd(i,n,zeta); break;
        default:
            fprintf(stderr,"error: spgram%s_create(), invalid window\n", EXTENSION);
            exit(1);
        }
    }

    // scale by window magnitude, FFT size
    float g = 0.0f;
    for (i=0; i<q->window_len; i++)
        g += q->w[i] * q->w[i];
    g = M_SQRT2 / ( sqrtf(g / q->window_len) * sqrtf((float)(q->nfft)) );

    // scale window and copy
    for (i=0; i<q->window_len; i++)
        q->w[i] = g * q->w[i];

    // reset the spgram object
    q->num_samples_total    = 0;
    q->num_transforms_total = 0;
    SPGRAM(_reset)(q);

    // return new object
    return q;
}
Пример #17
0
int main(int argc, char*argv[])
{
    // options
    float r=1.2f;           // resampling rate (output/input)
    float As=80.0f;         // resampling filter stop-band attenuation [dB]
    unsigned int nx=400;    // number of input samples
    float fc=0.40f;         // complex sinusoid frequency

    int dopt;
    while ((dopt = getopt(argc,argv,"hr:s:n:")) != EOF) {
        switch (dopt) {
        case 'h':   usage();            return 0;
        case 'r':   r   = atof(optarg); break;
        case 's':   As  = atof(optarg); break;
        case 'n':   nx  = atoi(optarg); break;
        default:
            exit(1);
        }
    }

    // validate input
    if (nx == 0) {
        fprintf(stderr,"error: %s, number of input samples must be greater than zero\n", argv[0]);
        exit(1);
    } else if (r <= 0.0f) {
        fprintf(stderr,"error: %s, resampling rate must be greater than zero\n", argv[0]);
        exit(1);
    } else if ( fabsf(log2f(r)) > 10 ) {
        fprintf(stderr,"error: %s, resampling rate unreasonable\n", argv[0]);
        exit(1);
    }

    unsigned int i;

    // derived values
    unsigned int ny_alloc = (unsigned int) (2*(float)nx * r);  // allocation for output

    // allocate memory for arrays
    float complex x[nx];
    float complex y[ny_alloc];

    // generate input
    unsigned int window_len = (3*nx)/4;
    for (i=0; i<nx; i++)
        x[i] = i < window_len ? cexpf(_Complex_I*2*M_PI*fc*i) * kaiser(i,window_len,10.0f,0.0f) : 0.0f;

    // create multi-stage arbitrary resampler object
    msresamp_crcf q = msresamp_crcf_create(r,As);
    msresamp_crcf_print(q);
    float delay = msresamp_crcf_get_delay(q);

    // run resampler
    unsigned int ny;
    msresamp_crcf_execute(q, x, nx, y, &ny);

    // print basic results
    printf("input samples   : %u\n", nx);
    printf("output samples  : %u\n", ny);
    printf("delay           : %f samples\n", delay);

    // clean up allocated objects
    msresamp_crcf_destroy(q);

    //
    // export output
    //
    // open/initialize output file
    FILE*fid = fopen(OUTPUT_FILENAME,"w");
    fprintf(fid,"%% %s: auto-generated file\n",OUTPUT_FILENAME);
    fprintf(fid,"clear all;\n");
    fprintf(fid,"close all;\n");
    fprintf(fid,"\n");
    fprintf(fid,"r=%12.8f;\n", r);
    fprintf(fid,"delay = %f;\n", delay);

    // save input series
    fprintf(fid,"nx = %u;\n", nx);
    fprintf(fid,"x = zeros(1,nx);\n");
    for (i=0; i<nx; i++)
        fprintf(fid,"x(%6u) = %12.4e + j*%12.4e;\n", i+1, crealf(x[i]), cimagf(x[i]));

    // save output series
    fprintf(fid,"ny = %u;\n", ny);
    fprintf(fid,"y = zeros(1,ny);\n");
    for (i=0; i<ny; i++)
        fprintf(fid,"y(%6u) = %12.4e + j*%12.4e;\n", i+1, crealf(y[i]), cimagf(y[i]));

    // output results
    fprintf(fid,"\n\n");
    fprintf(fid,"%% plot frequency-domain result\n");
    fprintf(fid,"nfft=1024;\n");
    fprintf(fid,"%% estimate PSD, normalize by array length\n");
    fprintf(fid,"X=20*log10(abs(fftshift(fft(x,nfft)/length(x))));\n");
    fprintf(fid,"Y=20*log10(abs(fftshift(fft(y,nfft)/length(y))));\n");
    fprintf(fid,"G = max(X);\n");
    fprintf(fid,"X = X - G;\n");
    fprintf(fid,"Y = Y - G;\n");
    fprintf(fid,"f=[0:(nfft-1)]/nfft-0.5;\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"if r>1, fx = f/r; fy = f;   %% interpolated\n");
    fprintf(fid,"else,   fx = f;   fy = f*r; %% decimated\n");
    fprintf(fid,"end;\n");
    fprintf(fid,"plot(fx,X,'Color',[0.5 0.5 0.5],fy,Y,'LineWidth',2);\n");
    fprintf(fid,"grid on;\n\n");
    fprintf(fid,"xlabel('normalized frequency');\n");
    fprintf(fid,"ylabel('PSD [dB]');\n");
    fprintf(fid,"legend('original','resampled','location','northeast');");
    fprintf(fid,"axis([-0.5 0.5 -120 10]);\n");

    fprintf(fid,"\n\n");
    fprintf(fid,"%% plot time-domain result\n");
    fprintf(fid,"tx=[0:(length(x)-1)];\n");
    fprintf(fid,"ty=[0:(length(y)-1)]/r-delay;\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"subplot(2,1,1);\n");
    fprintf(fid,"  plot(tx,real(x),'-s','Color',[0.5 0.5 0.5],'MarkerSize',1,...\n");
    fprintf(fid,"       ty,real(y),'-s','Color',[0.5 0 0],    'MarkerSize',1);\n");
    fprintf(fid,"  legend('original','resampled','location','northeast');");
    fprintf(fid,"  xlabel('time');\n");
    fprintf(fid,"  ylabel('real');\n");
    fprintf(fid,"  grid on;\n\n");
    fprintf(fid,"subplot(2,1,2);\n");
    fprintf(fid,"  plot(tx,imag(x),'-s','Color',[0.5 0.5 0.5],'MarkerSize',1,...\n");
    fprintf(fid,"       ty,imag(y),'-s','Color',[0 0.5 0],    'MarkerSize',1);\n");
    fprintf(fid,"  legend('original','resampled','location','northeast');");
    fprintf(fid,"  xlabel('time');\n");
    fprintf(fid,"  ylabel('imag');\n");
    fprintf(fid,"  grid on;\n\n");

    fclose(fid);
    printf("results written to %s\n",OUTPUT_FILENAME);

    printf("done.\n");
    return 0;
}
Пример #18
0
int main(int argc, char*argv[])
{
    unsigned int m=5;               // filter semi-length
    float fc=0.037f;                // input tone frequency
    unsigned int num_samples = 64;  // number of output samples
    float As=60.0f;                 // stop-band attenuation [dB]

    int dopt;
    while ((dopt = getopt(argc,argv,"hn:m:s:")) != EOF) {
        switch (dopt) {
        case 'h':   usage();                    return 0;
        case 'n':   num_samples = atoi(optarg); break;
        case 'm':   m           = atoi(optarg); break;
        case 's':   As          = atof(optarg); break;
        default:
            exit(1);
        }
    }
    unsigned int i;

    // allocate arrays
    float complex x[2*num_samples]; // input array
    float complex y[  num_samples]; // output array

    // generate input
    unsigned int w_len = 2*num_samples - 4*m;   // window length
    float beta = 8.0f;                          // kaiser window factor
    float w_sum = 0.0f;                         // gain due to window
    for (i=0; i<2*num_samples; i++) {
        // compute windowing function and keep track of gain
        float w = (i < w_len ? kaiser(i,w_len,beta,0) : 0.0f);
        w_sum += w;

        // compute windowed complex sinusoid
        x[i] = w * cexpf(_Complex_I*2*M_PI*fc*i);
    }

    // create/print the half-band resampler
    resamp2_crcf q = resamp2_crcf_create(m,0,As);
    resamp2_crcf_print(q);
    unsigned int delay = resamp2_crcf_get_delay(q);

    // run the resampler
    for (i=0; i<num_samples; i++) {
        // execute the decimator
        resamp2_crcf_decim_execute(q, &x[2*i], &y[i]);

        // print results to screen
        printf("y(%3u) = %8.4f + j*%8.4f;\n", i+1, crealf(y[i]), cimagf(y[i]));
    }

    // destroy half-band resampler
    resamp2_crcf_destroy(q);

    // 
    // export results
    //
    FILE*fid = fopen(OUTPUT_FILENAME,"w");
    fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME);
    fprintf(fid,"clear all;\nclose all;\n\n");
    fprintf(fid,"h_len=%u;\n", 4*m+1);
    fprintf(fid,"num_samples=%u;\n", num_samples);
    fprintf(fid,"delay      =%u;\n", delay);
    fprintf(fid,"w_sum      =%12.8f;\n", w_sum);
        
    for (i=0; i<num_samples; i++) {
        // save results to output file
        fprintf(fid,"x(%3u) = %12.8f + j*%12.8f;\n", 2*i+1,      crealf(x[2*i+0]),      cimagf(x[2*i+0]));
        fprintf(fid,"x(%3u) = %12.8f + j*%12.8f;\n", 2*i+2,      crealf(x[2*i+1]),      cimagf(x[2*i+1]));
        fprintf(fid,"y(%3u) = %12.8f + j*%12.8f;\n", i+1,   0.5f*crealf(y[i    ]), 0.5f*cimagf(y[i    ]));
    }

    // plot time series
    fprintf(fid,"tx =  0:(2*num_samples-1);\n");
    fprintf(fid,"ty = [0:(  num_samples-1)]*2 - delay;\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"subplot(2,1,1);\n");
    fprintf(fid,"  plot(tx,real(x),'-s','Color',[0.5 0.5 0.5],'MarkerSize',1,...\n");
    fprintf(fid,"       ty,real(y),'-s','Color',[0.5 0.0 0.0],'MarkerSize',1);\n");
    fprintf(fid,"  legend('original','decimated','location','northeast');");
    fprintf(fid,"  axis([-delay 2*num_samples -1.2 1.2]);\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"  xlabel('Normalized Time [t/T_s]');\n");
    fprintf(fid,"  ylabel('real');\n");
    fprintf(fid,"subplot(2,1,2);\n");
    fprintf(fid,"  plot(tx,imag(x),'-s','Color',[0.5 0.5 0.5],'MarkerSize',1,...\n");
    fprintf(fid,"       ty,imag(y),'-s','Color',[0.0 0.5 0.0],'MarkerSize',1);\n");
    fprintf(fid,"  legend('original','decimated','location','northeast');");
    fprintf(fid,"  axis([-delay 2*num_samples -1.2 1.2]);\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"  xlabel('Normalized Time [t/T_s]');\n");
    fprintf(fid,"  ylabel('imag');\n");

    // plot spectrum
    fprintf(fid,"nfft=512;\n");
    fprintf(fid,"g = 1/w_sum;\n");
    fprintf(fid,"X=20*log10(abs(fftshift(fft(  x*g,nfft))));\n");
    fprintf(fid,"Y=20*log10(abs(fftshift(fft(2*y*g,nfft))));\n");
    fprintf(fid,"f=[0:(nfft-1)]/nfft-0.5;\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(f,  X,'LineWidth',1,  'Color',[0.5 0.5 0.5],...\n");
    fprintf(fid,"     f/2,Y,'LineWidth',1.5,'Color',[0.1 0.3 0.5]);\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"xlabel('Normalized Frequency [f/F_s]');\n");
    fprintf(fid,"ylabel('PSD [dB]');\n");
    fprintf(fid,"legend('original','decimated','location','northeast');");
    fprintf(fid,"axis([-0.5 0.5 -100 10]);\n");

    fclose(fid);
    printf("results written to %s\n", OUTPUT_FILENAME);

    printf("done.\n");
    return 0;
}
Пример #19
0
/* Design FIR filter using the Window method

   n     filter length must be odd for HP and BS filters
   w     buffer for the filter taps (must be n long)
   fc    cutoff frequencies (1 for LP and HP, 2 for BP and BS)
         0 < fc < 1 where 1 <=> Fs/2
   flags window and filter type as defined in filter.h
         variables are ored together: i.e. LP|HAMMING will give a
         low pass filter designed using a hamming window
   opt   beta constant used only when designing using kaiser windows

   returns 0 if OK, -1 if fail
*/
TfirFilter::_ftype_t* TfirFilter::design_fir(unsigned int *n, _ftype_t* fc, int type, int window, _ftype_t opt)
{
  unsigned int  o   = *n & 1;            // Indicator for odd filter length
  unsigned int  end = ((*n + 1) >> 1) - o;       // Loop end
  unsigned int  i;                      // Loop index

  _ftype_t k1 = 2 * _ftype_t(M_PI);             // 2*pi*fc1
  _ftype_t k2 = 0.5f * (_ftype_t)(1 - o);// Constant used if the filter has even length
  _ftype_t k3;                           // 2*pi*fc2 Constant used in BP and BS design
  _ftype_t g  = 0.0f;                    // Gain
  _ftype_t t1,t2,t3;                     // Temporary variables
  _ftype_t fc1,fc2;                      // Cutoff frequencies

  // Sanity check
  if(*n==0) return NULL;
  fc[0]=limit(fc[0],_ftype_t(0.001),_ftype_t(1));

  if (!o && (type==TfirSettings::BANDSTOP || type==TfirSettings::HIGHPASS))
   (*n)++;
  _ftype_t *w=(_ftype_t*)aligned_calloc(sizeof(_ftype_t),*n);

  // Get window coefficients
  switch(window){
  case(TfirSettings::WINDOW_BOX):
    boxcar(*n,w); break;
  case(TfirSettings::WINDOW_TRIANGLE):
    triang(*n,w); break;
  case(TfirSettings::WINDOW_HAMMING):
    hamming(*n,w); break;
  case(TfirSettings::WINDOW_HANNING):
    hanning(*n,w); break;
  case(TfirSettings::WINDOW_BLACKMAN):
    blackman(*n,w); break;
  case(TfirSettings::WINDOW_FLATTOP):
    flattop(*n,w); break;
  case(TfirSettings::WINDOW_KAISER):
    kaiser(*n,w,opt); break;
  default:
   {
    delete []w;
    return NULL;
   }
  }

  if(type==TfirSettings::LOWPASS || type==TfirSettings::HIGHPASS){
    fc1=*fc;
    // Cutoff frequency must be < 0.5 where 0.5 <=> Fs/2
    fc1 = ((fc1 <= 1.0) && (fc1 > 0.0)) ? fc1/2 : 0.25f;
    k1 *= fc1;

    if(type==TfirSettings::LOWPASS){ // Low pass filter

      // If the filter length is odd, there is one point which is exactly
      // in the middle. The value at this point is 2*fCutoff*sin(x)/x,
      // where x is zero. To make sure nothing strange happens, we set this
      // value separately.
      if (o){
        w[end] = fc1 * w[end] * 2.0f;
        g=w[end];
      }

      // Create filter
      for (i=0 ; i<end ; i++){
        t1 = (_ftype_t)(i+1) - k2;
        w[end-i-1] = w[*n-end+i] = _ftype_t(w[end-i-1] * sin(k1 * t1)/(M_PI * t1)); // Sinc
        g += 2*w[end-i-1]; // Total gain in filter
      }
    }
    else{ // High pass filter
      //if (!o) // High pass filters must have odd length
      // return -1;
      w[end] = _ftype_t(1.0 - (fc1 * w[end] * 2.0));
      g= w[end];

      // Create filter
      for (i=0 ; i<end ; i++){
        t1 = (_ftype_t)(i+1);
        w[end-i-1] = w[*n-end+i] = _ftype_t(-1 * w[end-i-1] * sin(k1 * t1)/(M_PI * t1)); // Sinc
        g += ((i&1) ? (2*w[end-i-1]) : (-2*w[end-i-1])); // Total gain in filter
      }
    }
  }

  if(type==TfirSettings::BANDPASS || type==TfirSettings::BANDSTOP){
    fc1=fc[0];
    fc2=limit(fc[1],_ftype_t(0.001),_ftype_t(1));
    // Cutoff frequencies must be < 1.0 where 1.0 <=> Fs/2
    fc1 = ((fc1 <= 1.0) && (fc1 > 0.0)) ? fc1/2 : 0.25f;
    fc2 = ((fc2 <= 1.0) && (fc2 > 0.0)) ? fc2/2 : 0.25f;
    k3  = k1 * fc2; // 2*pi*fc2
    k1 *= fc1;      // 2*pi*fc1

    if(type==TfirSettings::BANDPASS){ // Band pass
      // Calculate center tap
      if (o){
        g=w[end]*(fc1+fc2);
        w[end] = (fc2 - fc1) * w[end] * 2.0f;
      }

      // Create filter
      for (i=0 ; i<end ; i++){
        t1 = (_ftype_t)(i+1) - k2;
        t2 = _ftype_t(sin(k3 * t1)/(M_PI * t1)); // Sinc fc2
        t3 = _ftype_t(sin(k1 * t1)/(M_PI * t1)); // Sinc fc1
        g += w[end-i-1] * (t3 + t2);   // Total gain in filter
        w[end-i-1] = w[*n-end+i] = w[end-i-1] * (t2 - t3);
      }
    }
    else{ // Band stop
      //if (!o) // Band stop filters must have odd length
      //  return -1;
      w[end] = _ftype_t(1.0 - (fc2 - fc1) * w[end] * 2.0);
      g= w[end];

      // Create filter
      for (i=0 ; i<end ; i++){
        t1 = (_ftype_t)(i+1);
        t2 = _ftype_t(sin(k1 * t1)/(M_PI * t1)); // Sinc fc1
        t3 = _ftype_t(sin(k3 * t1)/(M_PI * t1)); // Sinc fc2
        w[end-i-1] = w[*n-end+i] = w[end-i-1] * (t2 - t3);
        g += 2*w[end-i-1]; // Total gain in filter
      }
    }
  }

  // Normalize gain
  g=1/g;
  for (i=0; i<*n; i++)
    w[i] *= g;

  return w;
}
Пример #20
0
static int srconv(CSOUND *csound, int argc, char **argv)
{
    MYFLT
      *input,     /* pointer to start of input buffer */
      *output,    /* pointer to start of output buffer */
      *nextIn,    /* pointer to next empty word in input */
      *nextOut,   /* pointer to next empty word in output */
      *fxval = 0, /* pointer to start of time-array for time-vary function */
      *fyval = 0, /* pointer to start of P-scale-array for time-vary func */
      *i0,        /* pointer */
      *i1;        /* pointer */

    float
      *window,    /* pointer to center of analysis window */
      *wj,        /* pointer to window */
      *wj1;       /* pointer to window */

    int
      M = 2401,   /* length of window impulse response */
      N = 120,    /* length of sinc period */
      L = 120,    /* internal sample rate is L*Rin */
      m,          /* current input sample in buffer */
      o,          /* current input at L*Rin mod L */
      del,        /* increment */
      WinLen,     /* half-length of window at L*Rin */
      wLen,       /* half-length of window at Rin */
      jMin,       /* initial offset in window */
      mMax;       /* maximum valid m */

    long
      n,                        /* current input sample */
      nMax = 2000000000;        /* last input sample (unless EOF) */

    MYFLT
      beta = FL(6.8),           /* parameter for Kaiser window */
      sum,                      /* scale factor for renormalizing windows */
      fdel,                     /* float del */
      idel,                     /* float del */
      fo,                       /* float o */
      of,                       /* fractional o */
      fL = (MYFLT) L,           /* float L */
      iw,                       /* interpolated window */
      tvx0 = 0,                 /* current x value of time-var function */
      tvx1 = 0,                 /* next x value of time-var function */
      tvdx,                     /* tvx1 - tvx0 */
      tvy0 = 0,                 /* current y value of time-var function */
      tvy1 = 0,                 /* next y value of time-var function */
      tvdy,                     /* tvy1 - tvy0 */
      tvslope = 0,              /* tvdy / tvdx */
      time,                     /* n / Rin */
      invRin,                   /* 1. / Rin */
      P = FL(0.0),              /* Rin / Rout */
      Rin = FL(0.0),            /* input sampling rate */
      Rout = FL(0.0);           /* output sample rate */

    int
      i,k,                      /* index variables */
      nread,                    /* number of bytes read */
      tvflg = 0,                /* flag for time-varying time-scaling */
      tvnxt = 0,                /* counter for stepping thru time-var func */
      tvlen,                    /* length of time-varying function */
      Chans = 1,                /* number of channels */
      chan,                     /* current channel */
      Q = 2;                    /* quality factor */

    FILE        *tvfp = NULL;   /* time-vary function file */
    SOUNDIN     *p;
    int         channel = ALLCHNLS;
    MYFLT       beg_time = FL(0.0), input_dur = FL(0.0), sr = FL(0.0);
    char        *infile = NULL, *bfile = NULL;
    SNDFILE     *inf = NULL;
    char        c, *s;
    const char  *envoutyp;
    char        outformch = 's';
    unsigned    outbufsiz = 0U;
    SNDFILE     *outfd = NULL;
    OPARMS      O;
    int         block = 0;
    char        err_msg[256];

    O.outformat = AE_SHORT;
    /* csound->e0dbfs = csound->dbfs_to_float = FL(1.0);*/

    if ((envoutyp = csound->GetEnv(csound, "SFOUTYP")) != NULL) {
      if (strcmp(envoutyp, "AIFF") == 0)
        O.filetyp = TYP_AIFF;
      else if (strcmp(envoutyp, "WAV") == 0)
        O.filetyp = TYP_WAV;
      else if (strcmp(envoutyp, "IRCAM") == 0)
        O.filetyp = TYP_IRCAM;
      else {
        snprintf(err_msg, 256, Str("%s not a recognized SFOUTYP env setting"),
                envoutyp);
        dieu(csound, err_msg);
        return -1;
      }
    }

    /* call getopt to interpret commandline */

    ++argv;
    while (--argc > 0) {
      s = *argv++;
      if (*s++ == '-') {                /* read all flags:  */
        while ((c = *s++) != '\0') {
          switch (c) {
          case 'o':
            FIND(Str("no outfilename"))
            O.outfilename = s;         /* soundout name */
            for ( ; *s != '\0'; s++) ;
            if (strcmp(O.outfilename, "stdin") == 0) {
              csound->ErrorMsg(csound, Str("-o cannot be stdin"));
              return -1;
            }
#if defined WIN32
            if (strcmp(O.outfilename, "stdout") == 0) {
              csound->ErrorMsg(csound, Str("stdout audio not supported"));
              return -1;
            }
#endif
            break;
          case 'A':
            O.filetyp = TYP_AIFF;      /* AIFF output request*/
            break;
          case 'J':
            O.filetyp = TYP_IRCAM;     /* IRCAM output request */
            break;
          case 'W':
            O.filetyp = TYP_WAV;       /* WAV output request */
            break;
          case 'h':
            O.filetyp = TYP_RAW;       /* skip sfheader  */
            break;
          case 'c':
          case '8':
          case 'a':
          case 'u':
          case 's':
          case 'l':
          case '3':
          case 'f':
            outformch = set_output_format(csound, c, outformch, &O);
            break;
          case 'R':
            O.rewrt_hdr = 1;
            break;
          case 'H':
            if (isdigit(*s)) {
              int n;
              sscanf(s, "%d%n", &O.heartbeat, &n);
              s += n;
            }
            else O.heartbeat = 1;
            break;
          case 'N':
            O.ringbell = 1;        /* notify on completion */
            break;
          case 'Q':
            FIND(Str("No Q argument"))
            sscanf(s,"%d", &Q);
            while (*++s);
            break;
          case 'P':
            FIND(Str("No P argument"))
#if defined(USE_DOUBLE)
            csound->sscanf(s,"%lf", &P);
#else
            csound->sscanf(s,"%f", &P);
#endif
            while (*++s);
            break;
          case 'r':
            FIND(Str("No r argument"))
#if defined(USE_DOUBLE)
            csound->sscanf(s,"%lf", &Rout);
#else
            csound->sscanf(s,"%f", &Rout);
#endif
            while (*++s);
            break;
          case 'i':
            FIND(Str("No break file"))
            tvflg = 1;
            bfile = s;
            while ((*s++)) {}; s--;
            break;
          default:
            csound->Message(csound, Str("Looking at %c\n"), c);
            usage(csound);    /* this exits with error */
            return -1;
          }
        }
      }
      else if (infile == NULL) {
        infile = --s;
        csound->Message(csound, Str("Infile set to %s\n"), infile);
      }
      else {
        csound->Message(csound, Str("End with %s\n"), s);
        usage(csound);
        return -1;
      }
    }
    if (infile == NULL) {
      csound->Message(csound, Str("No input given\n"));
      usage(csound);
      return -1;
    }
    if ((inf = csound->SAsndgetset(csound, infile, &p, &beg_time,
                                   &input_dur, &sr, channel)) == NULL) {
      csound->ErrorMsg(csound, Str("error while opening %s"), infile);
      return -1;
    }
    if (Rin == FL(0.0))
      Rin = (MYFLT)p->sr;
    if (Chans == 0)
      Chans = (int) p->nchanls;
    if (Chans == 0)
      Chans = 1;

    if ((P != FL(0.0)) && (Rout != FL(0.0))) {
      strncpy(err_msg, Str("srconv: cannot specify both -r and -P"), 256);
      goto err_rtn_msg;
    }
    if (P != FL(0.0))
      Rout = Rin / P;
    else if (Rout == FL(0.0))
      Rout = Rin;

    if (tvflg) {
      P = FL(0.0);        /* will be reset to max in time-vary function */
      if ((tvfp = fopen(bfile, "r")) == NULL) {
        strncpy(err_msg,
                Str("srconv: cannot open time-vary function file"), 256);
        goto err_rtn_msg;
      }
      /* register file to be closed by csoundReset() */
      (void) csound->CreateFileHandle(csound, &tvfp, CSFILE_STD, bfile);
      if (UNLIKELY(fscanf(tvfp, "%d", &tvlen) != 1))
        csound->Message(csound, Str("Read failure\n"));
      if(tvlen <= 0) {
            strncpy(err_msg, Str("srconv: tvlen <= 0 "), 256);
            goto err_rtn_msg;
       }
      fxval = (MYFLT*) csound->Malloc(csound, tvlen * sizeof(MYFLT));
      fyval = (MYFLT*) csound->Malloc(csound, tvlen * sizeof(MYFLT));
      i0 = fxval;
      i1 = fyval;
      for (i = 0; i < tvlen; i++, i0++, i1++) {
#ifdef USE_DOUBLE
        if ((fscanf(tvfp, "%lf %lf", i0, i1)) != 2)
#else
        if ((fscanf(tvfp, "%f %f", i0, i1)) != 2)
#endif
          {
            strncpy(err_msg, Str("srconv: too few x-y pairs "
                                 "in time-vary function file"), 256);
            goto err_rtn_msg;
          }
        if (*i1 > P)
          P = *i1;
      }
      Rout = Rin / P;    /* this is min Rout */
      tvx0 = fxval[0];
      tvx1 = fxval[1];
      tvy0 = fyval[0];
      tvy1 = fyval[1];
      tvdx = tvx1 - tvx0;
      if (tvx0 != FL(0.0)) {
        strncpy(err_msg, Str("srconv: first x value "
                             "in time-vary function must be 0"), 256);
        goto err_rtn_msg;
      }
      if (tvy0 <= FL(0.0)) {
        strncpy(err_msg, Str("srconv: invalid initial y value "
                             "in time-vary function"),256);
        goto err_rtn_msg;
      }
      if (tvdx <= FL(0.0)) {
        strncpy(err_msg,
                       Str("srconv: invalid x values in time-vary function"),
                       256);
        goto err_rtn_msg;
      }
      tvdy = tvy1 - tvy0;
      tvslope = tvdy / tvdx;
      tvnxt = 1;
    }
    /* This is not right *********  */
    if (P != FL(0.0)) {
      csound->SetUtilSr(csound,Rin);
    }
    if (P == FL(0.0)) {
      csound->SetUtilSr(csound,Rout);
    }

    if (O.outformat == 0)
      O.outformat = AE_SHORT;//p->format;
    O.sfsampsize = csound->sfsampsize(FORMAT2SF(O.outformat));
    if (O.filetyp == TYP_RAW) {
      O.sfheader = 0;
      O.rewrt_hdr = 0;
    }
    else
      O.sfheader = 1;
#ifdef NeXT
    if (O.outfilename == NULL && !O.filetyp)
      O.outfilename = "test.snd";
    else if (O.outfilename == NULL)
      O.outfilename = "test";
#else
    if (O.outfilename == NULL) {
      if (O.filetyp == TYP_WAV)
        O.outfilename = "test.wav";
      else if (O.filetyp == TYP_AIFF)
        O.outfilename = "test.aif";
      else
        O.outfilename = "test";
    }
#endif
    {
      SF_INFO sfinfo;
      char    *name;
      memset(&sfinfo, 0, sizeof(SF_INFO));
      sfinfo.samplerate = (int) ((double) Rout + 0.5);
      sfinfo.channels = (int) p->nchanls;
      //printf("filetyp=%x outformat=%x\n", O.filetyp, O.outformat);
      sfinfo.format = TYPE2SF(O.filetyp) | FORMAT2SF(O.outformat);
      if (strcmp(O.outfilename, "stdout") != 0) {
        name = csound->FindOutputFile(csound, O.outfilename, "SFDIR");
        if (name == NULL) {
          snprintf(err_msg, 256, Str("cannot open %s."), O.outfilename);
          goto err_rtn_msg;
        }
        outfd = sf_open(name, SFM_WRITE, &sfinfo);
        if (outfd != NULL)
          csound->NotifyFileOpened(csound, name,
                                   csound->type2csfiletype(O.filetyp,
                                                           O.outformat),
                                   1, 0);
        else {
          snprintf(err_msg, 256, Str("libsndfile error: %s\n"), sf_strerror(NULL));
          goto err_rtn_msg;
        }
        csound->Free(csound, name);
      }
      else
        outfd = sf_open_fd(1, SFM_WRITE, &sfinfo, 1);
      if (outfd == NULL) {
        snprintf(err_msg, 256, Str("cannot open %s."), O.outfilename);
        goto err_rtn_msg;
      }
      /* register file to be closed by csoundReset() */
      (void) csound->CreateFileHandle(csound, &outfd, CSFILE_SND_W,
                                      O.outfilename);
      sf_command(outfd, SFC_SET_CLIPPING, NULL, SF_TRUE);
    }
    csound->SetUtilSr(csound, (MYFLT)p->sr);
    csound->SetUtilNchnls(csound, Chans = p->nchanls);

    outbufsiz = OBUF * O.sfsampsize;                   /* calc outbuf size */
    csound->Message(csound, Str("writing %d-byte blks of %s to %s"),
                    outbufsiz, csound->getstrformat(O.outformat),
                    O.outfilename);
    csound->Message(csound, " (%s)\n", csound->type2string(O.filetyp));

 /* this program performs arbitrary sample-rate conversion
    with high fidelity.  the method is to step through the
    input at the desired sampling increment, and to compute
    the output points as appropriately weighted averages of
    the surrounding input points.  there are two cases to
    consider: 1) sample rates are in a small-integer ratio -
    weights are obtained from table, 2) sample rates are in
    a large-integer ratio - weights are linearly
    interpolated from table.  */

 /* calculate increment: if decimating, then window is impulse response of low-
    pass filter with cutoff frequency at half of Rout; if interpolating,
    then window is ipulse response of lowpass filter with cutoff frequency
    at half of Rin. */

    fdel = ((MYFLT) (L * Rin) / Rout);
    del = (int) ((double) fdel + 0.5);
    idel = (MYFLT) del;
    if (del > L)
      N = del;
    if ((Q >= 1) && (Q <= 8))
      M = Q * N * 10 + 1;
    if (tvflg)
      fdel = tvy0 * L;

    invRin  =  FL(1.0) / Rin;

    /* make window: the window is the product of a kaiser and a sin(x)/x */
    window = (float*) csound->Calloc(csound, (size_t) (M + 2) * sizeof(float));
    WinLen = (M-1)/2;
    window += WinLen;
    wLen = (M/2 - L) / L;

    kaiser(M, window, WinLen, 1, (double) beta);

    for (i = 1; i <= WinLen; i++) {
      double  tmp = (double) N;
      tmp = tmp * sin(PI * (double) i / tmp) / (PI * (double) i);
      window[i] = (float) ((double) window[i] * tmp);
    }

    if (Rout < Rin) {
#if 0
      sum = (MYFLT) window[0];
      for (i = L-1; i <= WinLen; i += L)
        sum += (MYFLT) window[i];
      sum = FL(2.0) / sum;
#else
      sum = Rout / (Rin * (MYFLT) window[0]);
#endif
    }
    else
      sum = FL(1.0) / (MYFLT) window[0];

    window[0] = (float) ((double) window[0] * (double) sum);
    for (i = 1; i <= WinLen; i++) {
      window[i] = (float) ((double) window[i] * (double) sum);
      *(window - i) = window[i];
    }

    window[WinLen + 1] = 0.0f;

 /* set up input buffer:  nextIn always points to the next empty
    word in the input buffer.  If the buffer is full, then
    nextIn jumps back to the beginning, and the old values
    are written over. */

    input = (MYFLT*) csound->Calloc(csound, (size_t) IBUF * sizeof(MYFLT));

 /* set up output buffer:  nextOut always points to the next empty
    word in the output buffer.  If the buffer is full, then
    it is flushed, and nextOut jumps back to the beginning. */

    output = (MYFLT*) csound->Calloc(csound, (size_t) OBUF * sizeof(MYFLT));
    nextOut = output;

 /* initialization: */

    nread = csound->getsndin(csound, inf, input, IBUF2, p);
    for(i=0; i < nread; i++)
       input[i] *= 1.0/csound->Get0dBFS(csound);
    nMax = (long)(input_dur * p->sr);
    nextIn = input + nread;
    for (i = nread; i < IBUF2; i++)
      *(nextIn++) = FL(0.0);
    jMin = -(wLen + 1) * L;
    mMax = IBUF2;
    o = n = m = 0;
    fo = FL(0.0);

 /* main loop:   If nMax is not specified it is assumed to be very large
    and then readjusted when read detects the end of input. */

    while (n < nMax) {

      time = n * invRin;

      /* case 1:  (Rin / Rout) * 120 = integer  */

      if ((tvflg == 0) && (idel == fdel)) {
        /* apply window (window is sampled at L * Rin) */

        for (chan = 0; chan < Chans; chan++) {
          *nextOut = FL(0.0);
          k = Chans * (m - wLen) + chan - Chans;
          if (k < 0)
            k += IBUF;
          wj = window + jMin - o;
          for (i = -wLen; i <= wLen+1; i++){
            wj += L;
            k += Chans;
            if (k >= IBUF)
              k -= IBUF;
            *nextOut += (MYFLT) *wj * *(input + k);
          }
          nextOut++;
          if (nextOut >= (output + OBUF)) {
            nextOut = output;
            writebuffer(csound, output, &block, outfd, OBUF, &O);
          }
        }

        /* move window (window advances by del samples at L*Rin sample rate) */

        o += del;
        while (o >= L) {
          o -= L;
          n++;
          m++;
          if ((Chans * (m + wLen + 1)) >= mMax) {
            if (!csound->CheckEvents(csound))
              csound->LongJmp(csound, 1);
            mMax += IBUF2;
            if (nextIn >= (input + IBUF))
              nextIn = input;
            nread = csound->getsndin(csound, inf, nextIn, IBUF2, p);
            for(i=0; i < nread; i++)
               input[i] *= 1.0/csound->Get0dBFS(csound);
            nextIn += nread;
            if (nread < IBUF2)
              nMax = n + wLen + (nread / Chans) + 1;
            for (i = nread; i < IBUF2; i++)
              *(nextIn++) = FL(0.0);
          }
          if ((Chans * m) >= IBUF) {
            m = 0;
            mMax = IBUF2;
          }
        }
      }

      /* case 2: (Rin / Rout) * 120 = non-integer constant */

      else {

        /* apply window (window values are linearly interpolated) */

        for (chan = 0; chan < Chans; chan++) {
          *nextOut = FL(0.0);
          o = (int)fo;
          of = fo - o;
          wj = window + jMin - o;
          wj1 = wj + 1;
          k = Chans * (m - wLen) + chan - Chans;
          if (k < 0)
            k += IBUF;
          for (i = -wLen; i <= wLen+1; i++) {
            wj += L;
            wj1 += L;
            k += Chans;
            if (k >= IBUF)
              k -= IBUF;
            iw = (MYFLT) *wj + of * ((MYFLT) *wj1 - (MYFLT) *wj);
            *nextOut += iw * *(input + k);
          }
          nextOut++;
          if (nextOut >= (output + OBUF)) {
            nextOut = output;
            writebuffer(csound, output, &block, outfd, OBUF, &O);
          }
        }

        /* move window */

        fo += fdel;
        while (fo >= fL) {
          fo -= fL;
          n++;
          m++;
          if ((Chans * (m + wLen + 1)) >= mMax) {
            if (!csound->CheckEvents(csound))
              csound->LongJmp(csound, 1);
            mMax += IBUF2;
            if (nextIn >= (input + IBUF))
              nextIn = input;
            nread = csound->getsndin(csound, inf, nextIn, IBUF2, p);
            for(i=0; i < nread; i++)
               input[i] *= 1.0/csound->Get0dBFS(csound);
            nextIn += nread;
            if (nread < IBUF2)
              nMax = n + wLen + (nread / Chans) + 1;
            for (i = nread; i < IBUF2; i++)
              *(nextIn++) = FL(0.0);
          }
          if ((Chans * m) >= IBUF) {
            m = 0;
            mMax = IBUF2;
          }
        }

        if (tvflg && (time > FL(0.0))) {
          while (tvflg && (time >= tvx1)) {
            if (++tvnxt >= tvlen)
              tvflg = 0;
            else {
              tvx0 = tvx1;
              tvx1 = fxval[tvnxt];
              tvy0 = tvy1;
              tvy1 = fyval[tvnxt];
              tvdx = tvx1 - tvx0;
              if (tvdx <= FL(0.0)) {
                strncpy(err_msg, Str("srconv: invalid x values "
                                     "in time-vary function"), 256);
                goto err_rtn_msg;
              }
              tvdy = tvy1 - tvy0;
              tvslope = tvdy / tvdx;
            }
          }
          P = tvy0 + tvslope * (time - tvx0);
          fdel = (MYFLT) L * P;
        }
      }

    }
    nread = nextOut - output;
    writebuffer(csound, output, &block, outfd, nread, &O);
    csound->Message(csound, "\n\n");
    if (O.ringbell)
      csound->MessageS(csound, CSOUNDMSG_REALTIME, "\a");
    return 0;

 err_rtn_msg:
    csound->ErrorMsg(csound, err_msg);
    return -1;
}
Пример #21
0
void FIRFilter::wdfir (
    filter_type type,
    Real  atten,
    Real  fl,
    Real  fh)
{
    size_t ieo, nh;
    Real c, c1, c3, xn, beta, x;

    ieo = _filtCoeff.size() % 2;
    if (!(ieo == 1 || type == lowpass || type == bandpass))
    {
        //
        // Some filter types must have an odd number of taps
        //
        _filtCoeff.resize(_filtCoeff.size() - 1);
        ieo = 1;
    }

    //
    // Window coefficients
    //
    const size_t sz = _filtCoeff.size();
    RealArray winCoef(sz);

    //
    // Compute the ideal (unwindowed) impulse response
    //
    if (type == hilbert)
    {
        _filtCoeff = Real(0);

        nh = (1 + sz) / 2;
        for (size_t ii = nh; ii < sz; ii += 2)
        {
            x = M_PI * (ii + 1 - nh) * 0.5;
            _filtCoeff[ii] = -sin (x) * sin (x) / x;

            size_t jj = nh - (ii + 2 - nh);
            _filtCoeff[jj] = -_filtCoeff[ii];
        }
    }
    else
    {
        c1 = fl;
        if (type == bandpass || type == bandstop)
            c1 = fh - fl;

        nh = (1 + sz) / 2;
        if (ieo == 1)
            _filtCoeff[nh - 1] = 2.0 * c1;

        for (size_t ii = ieo; ii < nh; ii++)
        {
            xn = ii;
            if (ieo == 0)
                xn += 0.5;

            c = M_PI * xn;
            c3 = c * c1;
            if (type == lowpass || type == highpass)
                c3 *= 2.0;

            size_t jj = nh + ii - ieo;
            _filtCoeff[jj] = sin (c3) / c;

            if (type == bandpass || type == bandstop)
                _filtCoeff[jj] *= 2.0 * cos (c * (fl + fh));

            _filtCoeff[nh - ii - 1] = _filtCoeff[jj];
        }
    }

    //
    // Apply a Kaiser-Bessel window
    //
    if (atten > 50.0)
    {
        beta = 0.1102 * (atten - 8.7);
    }
    else if (atten >= 20.96 && atten <= 50.0)
    {
        Real tmp = atten - 20.96;
        beta = 0.58417 * pow (tmp, Real(0.4)) + 0.07886 * tmp;
    }
    else // if (atten < 20.96)
    {
        beta = Real(0);
    }
    kaiser (winCoef, beta);
    _filtCoeff *= winCoef;

    if (type == lowpass || type == bandpass)
    {
        return;
    }
    else if (type == hilbert)
    {
        Real kk = 1;
        Real sum = Real(0);
        for (size_t ii = nh; ii < sz; ii += 2)
        {
            sum += kk * _filtCoeff[ii];
            kk = -kk;
        }
        _filtCoeff *= (-0.5 / sum);

        return;
    }

    _filtCoeff *= -1;
    _filtCoeff[nh - 1] += 1;

}  // end wdfir
Пример #22
0
int main(int argc, char*argv[])
{
    // options
    float r           = 1.1f;   // resampling rate (output/input)
    unsigned int m    = 13;     // resampling filter semi-length (filter delay)
    float As          = 60.0f;  // resampling filter stop-band attenuation [dB]
    float bw          = 0.45f;  // resampling filter bandwidth
    unsigned int npfb = 64;     // number of filters in bank (timing resolution)
    unsigned int n    = 400;    // number of input samples
    float fc          = 0.044f; // complex sinusoid frequency

    int dopt;
    while ((dopt = getopt(argc,argv,"hr:m:b:s:p:n:f:")) != EOF) {
        switch (dopt) {
        case 'h':   usage();            return 0;
        case 'r':   r    = atof(optarg); break;
        case 'm':   m    = atoi(optarg); break;
        case 'b':   bw   = atof(optarg); break;
        case 's':   As   = atof(optarg); break;
        case 'p':   npfb = atoi(optarg); break;
        case 'n':   n    = atoi(optarg); break;
        case 'f':   fc   = atof(optarg); break;
        default:
            exit(1);
        }
    }

    // validate input
    if (r <= 0.0f) {
        fprintf(stderr,"error: %s, resampling rate must be greater than zero\n", argv[0]);
        exit(1);
    } else if (m == 0) {
        fprintf(stderr,"error: %s, filter semi-length must be greater than zero\n", argv[0]);
        exit(1);
    } else if (bw == 0.0f || bw >= 0.5f) {
        fprintf(stderr,"error: %s, filter bandwidth must be in (0,0.5)\n", argv[0]);
        exit(1);
    } else if (As < 0.0f) {
        fprintf(stderr,"error: %s, filter stop-band attenuation must be greater than zero\n", argv[0]);
        exit(1);
    } else if (npfb == 0) {
        fprintf(stderr,"error: %s, filter bank size must be greater than zero\n", argv[0]);
        exit(1);
    } else if (n == 0) {
        fprintf(stderr,"error: %s, number of input samples must be greater than zero\n", argv[0]);
        exit(1);
    }

    unsigned int i;

    // number of input samples (zero-padded)
    unsigned int nx = n + m;

    // output buffer with extra padding for good measure
    unsigned int y_len = (unsigned int) ceilf(1.1 * nx * r) + 4;

    // arrays
    float complex x[nx];
    float complex y[y_len];

    // create resampler
    resamp_crcf q = resamp_crcf_create(r,m,bw,As,npfb);

    // generate input signal
    float wsum = 0.0f;
    for (i=0; i<nx; i++) {
        // compute window
        float w = i < n ? kaiser(i, n, 10.0f, 0.0f) : 0.0f;

        // apply window to complex sinusoid
        x[i] = cexpf(_Complex_I*2*M_PI*fc*i) * w;

        // accumulate window
        wsum += w;
    }

    // resample
    unsigned int ny=0;
#if 0
    // execute one sample at a time
    unsigned int nw;
    for (i=0; i<nx; i++) {
        // execute resampler, storing in output buffer
        resamp_crcf_execute(q, x[i], &y[ny], &nw);

        // increment output size
        ny += nw;
    }
#else
    // execute on block of samples
    resamp_crcf_execute_block(q, x, nx, y, &ny);
#endif

    // clean up allocated objects
    resamp_crcf_destroy(q);

    // 
    // analyze resulting signal
    //

    // check that the actual resampling rate is close to the target
    float r_actual = (float)ny / (float)nx;
    float fy = fc / r;      // expected output frequency

    // run FFT and ensure that carrier has moved and that image
    // frequencies and distortion have been adequately suppressed
    unsigned int nfft = 1 << liquid_nextpow2(ny);
    float complex yfft[nfft];   // fft input
    float complex Yfft[nfft];   // fft output
    for (i=0; i<nfft; i++)
        yfft[i] = i < ny ? y[i] : 0.0f;
    fft_run(nfft, yfft, Yfft, LIQUID_FFT_FORWARD, 0);
    fft_shift(Yfft, nfft);  // run FFT shift

    // find peak frequency
    float Ypeak = 0.0f;
    float fpeak = 0.0f;
    float max_sidelobe = -1e9f;     // maximum side-lobe [dB]
    float main_lobe_width = 0.07f;  // TODO: figure this out from Kaiser's equations
    for (i=0; i<nfft; i++) {
        // normalized output frequency
        float f = (float)i/(float)nfft - 0.5f;

        // scale FFT output appropriately
        float Ymag = 20*log10f( cabsf(Yfft[i] / (r * wsum)) );

        // find frequency location of maximum magnitude
        if (Ymag > Ypeak || i==0) {
            Ypeak = Ymag;
            fpeak = f;
        }

        // find peak side-lobe value, ignoring frequencies
        // within a certain range of signal frequency
        if ( fabsf(f-fy) > main_lobe_width )
            max_sidelobe = Ymag > max_sidelobe ? Ymag : max_sidelobe;
    }

    // print results and check frequency location
    printf("  desired resampling rate   :   %12.8f\n", r);
    printf("  measured resampling rate  :   %12.8f    (%u/%u)\n", r_actual, ny, nx);
    printf("  peak spectrum             :   %12.8f dB (expected 0.0 dB)\n", Ypeak);
    printf("  peak frequency            :   %12.8f    (expected %-12.8f)\n", fpeak, fy);
    printf("  max sidelobe              :   %12.8f dB (expected at least %.2f dB)\n", max_sidelobe, -As);


    // 
    // export results
    //
    FILE * fid = fopen(OUTPUT_FILENAME,"w");
    fprintf(fid,"%% %s: auto-generated file\n",OUTPUT_FILENAME);
    fprintf(fid,"clear all;\n");
    fprintf(fid,"close all;\n");
    fprintf(fid,"m=%u;\n", m);
    fprintf(fid,"npfb=%u;\n",  npfb);
    fprintf(fid,"r=%12.8f;\n", r);

    fprintf(fid,"nx = %u;\n", nx);
    fprintf(fid,"x = zeros(1,nx);\n");
    for (i=0; i<nx; i++)
        fprintf(fid,"x(%3u) = %12.4e + j*%12.4e;\n", i+1, crealf(x[i]), cimagf(x[i]));

    fprintf(fid,"ny = %u;\n", ny);
    fprintf(fid,"y = zeros(1,ny);\n");
    for (i=0; i<ny; i++)
        fprintf(fid,"y(%3u) = %12.4e + j*%12.4e;\n", i+1, crealf(y[i]), cimagf(y[i]));

    fprintf(fid,"\n\n");
    fprintf(fid,"%% plot frequency-domain result\n");
    fprintf(fid,"nfft=2^nextpow2(max(nx,ny));\n");
    fprintf(fid,"%% estimate PSD, normalize by array length\n");
    fprintf(fid,"X=20*log10(abs(fftshift(fft(x,nfft)/length(x))));\n");
    fprintf(fid,"Y=20*log10(abs(fftshift(fft(y,nfft)/length(y))));\n");
    fprintf(fid,"G=max(X);\n");
    fprintf(fid,"X=X-G;\n");
    fprintf(fid,"Y=Y-G;\n");
    fprintf(fid,"f=[0:(nfft-1)]/nfft-0.5;\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"if r>1, fx = f/r; fy = f;   %% interpolated\n");
    fprintf(fid,"else,   fx = f;   fy = f*r; %% decimated\n");
    fprintf(fid,"end;\n");
    fprintf(fid,"plot(fx,X,'Color',[0.5 0.5 0.5],fy,Y,'LineWidth',2);\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"xlabel('normalized frequency');\n");
    fprintf(fid,"ylabel('PSD [dB]');\n");
    fprintf(fid,"legend('original','resampled','location','northeast');");
    fprintf(fid,"axis([-0.5 0.5 -120 20]);\n");

    fprintf(fid,"\n\n");
    fprintf(fid,"%% plot time-domain result\n");
    fprintf(fid,"tx=[0:(length(x)-1)];\n");
    fprintf(fid,"ty=[0:(length(y)-1)]/r-m;\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"subplot(2,1,1);\n");
    fprintf(fid,"  plot(tx,real(x),'-s','Color',[0.5 0.5 0.5],'MarkerSize',1,...\n");
    fprintf(fid,"       ty,real(y),'-s','Color',[0.5 0 0],    'MarkerSize',1);\n");
    fprintf(fid,"  legend('original','resampled','location','northeast');");
    fprintf(fid,"  xlabel('time');\n");
    fprintf(fid,"  ylabel('real');\n");
    fprintf(fid,"subplot(2,1,2);\n");
    fprintf(fid,"  plot(tx,imag(x),'-s','Color',[0.5 0.5 0.5],'MarkerSize',1,...\n");
    fprintf(fid,"       ty,imag(y),'-s','Color',[0 0.5 0],    'MarkerSize',1);\n");
    fprintf(fid,"  legend('original','resampled','location','northeast');");
    fprintf(fid,"  xlabel('time');\n");
    fprintf(fid,"  ylabel('imag');\n");

    fclose(fid);
    printf("results written to %s\n",OUTPUT_FILENAME);

    printf("done.\n");
    return 0;
}
Пример #23
0
int main(int argc, char** argv)
{
    // nc is the number of bits to store the coefficients
    const int nc = 32;

    bool polyphase = false;
    unsigned int polyM = 160;
    unsigned int polyN = 147;
    bool debug = false;
    double Fs = 48000;
    double Fc = 20478;
    double atten = 1;
    int format = 0;


    // in order to keep the errors associated with the linear
    // interpolation of the coefficients below the quantization error
    // we must satisfy:
    //   2^nz >= 2^(nc/2)
    //
    // for 16 bit coefficients that would be 256
    //
    // note that increasing nz only increases memory requirements,
    // but doesn't increase the amount of computation to do.
    //
    //
    // see:
    // Smith, J.O. Digital Audio Resampling Home Page
    // https://ccrma.stanford.edu/~jos/resample/, 2011-03-29
    //
    int nz = 4;

    //         | 0.1102*(A - 8.7)                         A > 50
    //  beta = | 0.5842*(A - 21)^0.4 + 0.07886*(A - 21)   21 <= A <= 50
    //         | 0                                        A < 21
    //   with A is the desired stop-band attenuation in dBFS
    //
    // for eg:
    //
    //    30 dB    2.210
    //    40 dB    3.384
    //    50 dB    4.538
    //    60 dB    5.658
    //    70 dB    6.764
    //    80 dB    7.865
    //    90 dB    8.960
    //   100 dB   10.056
    double beta = 7.865;


    // 2*nzc = (A - 8) / (2.285 * dw)
    //      with dw the transition width = 2*pi*dF/Fs
    //
    int nzc = 8;

    //
    // Example:
    // 44.1 KHz to 48 KHz resampling
    // 100 dB rejection above 28 KHz
    //   (the spectrum will fold around 24 KHz and we want 100 dB rejection
    //    at the point where the folding reaches 20 KHz)
    //  ...___|_____
    //        |     \|
    //        | ____/|\____
    //        |/alias|     \
    //  ------/------+------\---------> KHz
    //       20     24     28

    // Transition band 8 KHz, or dw = 1.0472
    //
    // beta = 10.056
    // nzc  = 20
    //

    int ch;
    while ((ch = getopt(argc, argv, ":hds:c:n:f:l:b:p:v:")) != -1) {
        switch (ch) {
            case 'd':
                debug = true;
                break;
            case 'p':
                if (sscanf(optarg, "%u/%u", &polyM, &polyN) != 2) {
                    usage(argv[0]);
                }
                polyphase = true;
                break;
            case 's':
                Fs = atof(optarg);
                break;
            case 'c':
                Fc = atof(optarg);
                break;
            case 'n':
                nzc = atoi(optarg);
                break;
            case 'l':
                nz = atoi(optarg);
                break;
            case 'f':
                if (!strcmp(optarg,"fixed")) format = 0;
                else if (!strcmp(optarg,"float")) format = 1;
                else usage(argv[0]);
                break;
            case 'b':
                beta = atof(optarg);
                break;
            case 'v':
                atten = pow(10, -fabs(atof(optarg))*0.05 );
                break;
            case 'h':
            default:
                usage(argv[0]);
                break;
        }
    }

    // cut off frequency ratio Fc/Fs
    double Fcr = Fc / Fs;


    // total number of coefficients (one side)
    const int M = (1 << nz);
    const int N = M * nzc;

    // generate the right half of the filter
    if (!debug) {
        printf("// cmd-line: ");
        for (int i=1 ; i<argc ; i++) {
            printf("%s ", argv[i]);
        }
        printf("\n");
        if (!polyphase) {
            printf("const int32_t RESAMPLE_FIR_SIZE           = %d;\n", N);
            printf("const int32_t RESAMPLE_FIR_LERP_INT_BITS  = %d;\n", nz);
            printf("const int32_t RESAMPLE_FIR_NUM_COEF       = %d;\n", nzc);
        } else {
            printf("const int32_t RESAMPLE_FIR_SIZE           = %d;\n", 2*nzc*polyN);
            printf("const int32_t RESAMPLE_FIR_NUM_COEF       = %d;\n", 2*nzc);
        }
        if (!format) {
            printf("const int32_t RESAMPLE_FIR_COEF_BITS      = %d;\n", nc);
        }
        printf("\n");
        printf("static %s resampleFIR[] = {", !format ? "int32_t" : "float");
    }

    if (!polyphase) {
        for (int i=0 ; i<=M ; i++) { // an extra set of coefs for interpolation
            for (int j=0 ; j<nzc ; j++) {
                int ix = j*M + i;
                double x = (2.0 * M_PI * ix * Fcr) / (1 << nz);
                double y = kaiser(ix+N, 2*N, beta) * sinc(x) * 2.0 * Fcr;
                y *= atten;

                if (!debug) {
                    if (j == 0)
                        printf("\n    ");
                }

                if (!format) {
                    int64_t yi = floor(y * ((1ULL<<(nc-1))) + 0.5);
                    if (yi >= (1LL<<(nc-1))) yi = (1LL<<(nc-1))-1;
                    printf("0x%08x, ", int32_t(yi));
                } else {
                    printf("%.9g%s ", y, debug ? "," : "f,");
                }
            }
        }
    } else {
        for (int j=0 ; j<polyN ; j++) {
            // calculate the phase
            double p = ((polyM*j) % polyN) / double(polyN);
            if (!debug) printf("\n    ");
            else        printf("\n");
            // generate a FIR per phase
            for (int i=-nzc ; i<nzc ; i++) {
                double x = 2.0 * M_PI * Fcr * (i + p);
                double y = kaiser(i+N, 2*N, beta) * sinc(x) * 2.0 * Fcr;;
                y *= atten;
                if (!format) {
                    int64_t yi = floor(y * ((1ULL<<(nc-1))) + 0.5);
                    if (yi >= (1LL<<(nc-1))) yi = (1LL<<(nc-1))-1;
                    printf("0x%08x", int32_t(yi));
                } else {
                    printf("%.9g%s", y, debug ? "" : "f");
                }

                if (debug && (i==nzc-1)) {
                } else {
                    printf(", ");
                }
            }
        }
    }

    if (!debug) {
        printf("\n};");
    }
    printf("\n");
    return 0;
}
Пример #24
0
// 
// AUTOTEST : test multi-stage arbitrary resampler
//
void autotest_msresamp_crcf()
{
    // options
    unsigned int m = 13;        // filter semi-length (filter delay)
    float r=0.127115323f;       // resampling rate (output/input)
    float As=60.0f;             // resampling filter stop-band attenuation [dB]
    unsigned int n=1200;        // number of input samples
    float fx=0.0254230646f;     // complex input sinusoid frequency (0.2*r)
    //float bw=0.45f;             // resampling filter bandwidth
    //unsigned int npfb=64;       // number of filters in bank (timing resolution)

    unsigned int i;

    // number of input samples (zero-padded)
    unsigned int nx = n + m;

    // output buffer with extra padding for good measure
    unsigned int y_len = (unsigned int) ceilf(1.1 * nx * r) + 4;

    // arrays
    float complex x[nx];
    float complex y[y_len];

    // create resampler
    msresamp_crcf q = msresamp_crcf_create(r,As);

    // generate input signal
    float wsum = 0.0f;
    for (i=0; i<nx; i++) {
        // compute window
        float w = i < n ? kaiser(i, n, 10.0f, 0.0f) : 0.0f;

        // apply window to complex sinusoid
        x[i] = cexpf(_Complex_I*2*M_PI*fx*i) * w;

        // accumulate window
        wsum += w;
    }

    // resample
    unsigned int ny=0;
    unsigned int nw;
    for (i=0; i<nx; i++) {
        // execute resampler, storing in output buffer
        msresamp_crcf_execute(q, &x[i], 1, &y[ny], &nw);

        // increment output size
        ny += nw;
    }

    // clean up allocated objects
    msresamp_crcf_destroy(q);

    // 
    // analyze resulting signal
    //

    // check that the actual resampling rate is close to the target
    float r_actual = (float)ny / (float)nx;
    float fy = fx / r;      // expected output frequency

    // run FFT and ensure that carrier has moved and that image
    // frequencies and distortion have been adequately suppressed
    unsigned int nfft = 1 << liquid_nextpow2(ny);
    float complex yfft[nfft];   // fft input
    float complex Yfft[nfft];   // fft output
    for (i=0; i<nfft; i++)
        yfft[i] = i < ny ? y[i] : 0.0f;
    fft_run(nfft, yfft, Yfft, LIQUID_FFT_FORWARD, 0);
    fft_shift(Yfft, nfft);  // run FFT shift

    // find peak frequency
    float Ypeak = 0.0f;
    float fpeak = 0.0f;
    float max_sidelobe = -1e9f;     // maximum side-lobe [dB]
    float main_lobe_width = 0.07f;  // TODO: figure this out from Kaiser's equations
    for (i=0; i<nfft; i++) {
        // normalized output frequency
        float f = (float)i/(float)nfft - 0.5f;

        // scale FFT output appropriately
        Yfft[i] /= (r * wsum);
        float Ymag = 20*log10f( cabsf(Yfft[i]) );

        // find frequency location of maximum magnitude
        if (Ymag > Ypeak || i==0) {
            Ypeak = Ymag;
            fpeak = f;
        }

        // find peak side-lobe value, ignoring frequencies
        // within a certain range of signal frequency
        if ( fabsf(f-fy) > main_lobe_width )
            max_sidelobe = Ymag > max_sidelobe ? Ymag : max_sidelobe;
    }

    if (liquid_autotest_verbose) {
        // print results
        printf("  desired resampling rate   :   %12.8f\n", r);
        printf("  measured resampling rate  :   %12.8f    (%u/%u)\n", r_actual, ny, nx);
        printf("  peak spectrum             :   %12.8f dB (expected 0.0 dB)\n", Ypeak);
        printf("  peak frequency            :   %12.8f    (expected %-12.8f)\n", fpeak, fy);
        printf("  max sidelobe              :   %12.8f dB (expected at least %.2f dB)\n", max_sidelobe, -As);
    }
    CONTEND_DELTA(     r_actual, r,    0.01f ); // check actual output sample rate
    CONTEND_DELTA(     Ypeak,    0.0f, 0.25f ); // peak should be about 0 dB
    CONTEND_DELTA(     fpeak,    fy,   0.01f ); // peak frequency should be nearly 0.2
    CONTEND_LESS_THAN( max_sidelobe, -As );     // maximum side-lobe should be sufficiently low

#if 0
    // export results for debugging
    char filename[] = "msresamp_crcf_autotest.m";
    FILE*fid = fopen(filename,"w");
    fprintf(fid,"%% %s: auto-generated file\n",filename);
    fprintf(fid,"clear all;\n");
    fprintf(fid,"close all;\n");
    fprintf(fid,"r    = %12.8f;\n", r);
    fprintf(fid,"nx   = %u;\n", nx);
    fprintf(fid,"ny   = %u;\n", ny);
    fprintf(fid,"nfft = %u;\n", nfft);

    fprintf(fid,"Y = zeros(1,nfft);\n");
    for (i=0; i<nfft; i++)
        fprintf(fid,"Y(%3u) = %12.4e + j*%12.4e;\n", i+1, crealf(Yfft[i]), cimagf(Yfft[i]));

    fprintf(fid,"\n\n");
    fprintf(fid,"%% plot frequency-domain result\n");
    fprintf(fid,"f=[0:(nfft-1)]/nfft-0.5;\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(f,20*log10(abs(Y)),'Color',[0.25 0.5 0.0],'LineWidth',2);\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"xlabel('normalized frequency');\n");
    fprintf(fid,"ylabel('PSD [dB]');\n");
    fprintf(fid,"axis([-0.5 0.5 -120 20]);\n");

    fclose(fid);
    printf("results written to %s\n",filename);
#endif
}
int main() {
    unsigned int h_len=20;              // filter length
    float beta = 0.3f;                  // stop-band attenuation
    unsigned int num_samples=64;        // number of samples

    // derived values
    unsigned int n = num_samples + h_len;   // extend length of analysis to
                                        // incorporate filter delay

    // create filterbank
    qmfb_crcf q = qmfb_crcf_create(h_len, beta, LIQUID_QMFB_ANALYZER);
    qmfb_crcf_print(q);

    FILE*fid = fopen(OUTPUT_FILENAME,"w");
    fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME);
    fprintf(fid,"clear all;\nclose all;\n\n");
    fprintf(fid,"n=%u;\n", n);
    fprintf(fid,"x = zeros(1,%u);\n", 2*n);
    fprintf(fid,"y = zeros(2,%u);\n",   n);

    unsigned int i;
    float complex x[2*n], y[2][n];

    // generate time-domain signal (windowed sinusoidal pulses)
    nco_crcf nco_0 = nco_crcf_create(LIQUID_VCO);
    nco_crcf nco_1 = nco_crcf_create(LIQUID_VCO);
    nco_crcf_set_frequency(nco_0, 0.122*M_PI);
    nco_crcf_set_frequency(nco_1, 0.779*M_PI);
    float complex x0,x1;
    for (i=0; i<2*num_samples; i++) {
        nco_crcf_cexpf(nco_0, &x0);
        nco_crcf_cexpf(nco_1, &x1);
        x[i] = (x0 + x1) * kaiser(i,2*num_samples,10.0f,0.0f);
        nco_crcf_step(nco_0);
        nco_crcf_step(nco_1);
    }
    // pad end with zeros
    for (i=2*num_samples; i<2*n; i++)
        x[i] = 0.0f;

    // compute QMF sub-channel output
    for (i=0; i<n; i++) {
        qmfb_crcf_execute(q, x[2*i+0], x[2*i+1], y[0]+i, y[1]+i);
    }

    // write results to output file
    for (i=0; i<n; i++) {
        fprintf(fid,"x(%3u) = %8.4f + j*%8.4f;\n", 2*i+1, crealf(x[2*i+0]), cimagf(x[2*i+0]));
        fprintf(fid,"x(%3u) = %8.4f + j*%8.4f;\n", 2*i+2, crealf(x[2*i+1]), cimagf(x[2*i+1]));

        fprintf(fid,"y(1,%3u) = %8.4f + j*%8.4f;\n", i+1, crealf(y[0][i]),  cimagf(y[0][i]));
        fprintf(fid,"y(2,%3u) = %8.4f + j*%8.4f;\n", i+1, crealf(y[1][i]),  cimagf(y[1][i]));
    }

    // plot time-domain results
    fprintf(fid,"t0=0:(2*n-1);\n");
    fprintf(fid,"t1=0:(n-1);\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"subplot(3,1,1); plot(t0,real(x),t0,imag(x)); ylabel('x(t)');\n");
    fprintf(fid,"subplot(3,1,2); plot(t1,real(y(1,:)),t1,imag(y(1,:))); ylabel('y_0(t)');\n");
    fprintf(fid,"subplot(3,1,3); plot(t1,real(y(2,:)),t1,imag(y(2,:))); ylabel('y_1(t)');\n");

    // plot freq-domain results
    fprintf(fid,"nfft=512; %% must be even number\n");
    fprintf(fid,"X=20*log10(abs(fftshift(fft(x/n,nfft))));\n");
    fprintf(fid,"Y0=20*log10(abs(fftshift(fft(y(1,:)/n,nfft))));\n");
    fprintf(fid,"Y1=20*log10(abs(fftshift(fft(y(2,:)/n,nfft))));\n");
    // Y1 needs to be split into two regions
    fprintf(fid,"f=[0:(nfft-1)]/nfft - 0.5;\n");
    fprintf(fid,"t0 = [1]:[nfft/2];\n");
    fprintf(fid,"t1 = [nfft/2+1]:[nfft];\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"hold on;\n");
    fprintf(fid,"    plot(f,X,'Color',[0.5 0.5 0.5]);\n");
    fprintf(fid,"    plot(f/2,Y0,'LineWidth',2,'Color',[0 0.5 0]);\n");
    fprintf(fid,"    plot(f(t0)/2+0.5,Y1(t0),'LineWidth',2,'Color',[0.5 0 0]);\n");
    fprintf(fid,"    plot(f(t1)/2-0.5,Y1(t1),'LineWidth',2,'Color',[0.5 0 0]);\n");
    fprintf(fid,"hold off;\n");
    fprintf(fid,"grid on;\nxlabel('normalized frequency');\nylabel('PSD [dB]');\n");
    fprintf(fid,"legend('original','Y_0','Y_1',1);");
    fprintf(fid,"axis([-0.5 0.5 -140 20]);\n");

    fclose(fid);
    printf("results written to %s\n", OUTPUT_FILENAME);

    qmfb_crcf_destroy(q);
    nco_crcf_destroy(nco_0);
    nco_crcf_destroy(nco_1);
    printf("done.\n");
    return 0;
}