コード例 #1
0
ファイル: ModemFMStereo.cpp プロジェクト: mhmh1990/CubicSDR
void ModemFMStereo::disposeKit(ModemKit *kit) {
    ModemKitFMStereo *fmkit = (ModemKitFMStereo *)kit;
    
    msresamp_rrrf_destroy(fmkit->audioResampler);
    msresamp_rrrf_destroy(fmkit->stereoResampler);
    firfilt_rrrf_destroy(fmkit->firStereoLeft);
    firfilt_rrrf_destroy(fmkit->firStereoRight);
    firhilbf_destroy(fmkit->firStereoR2C);
    firhilbf_destroy(fmkit->firStereoC2R);
    nco_crcf_destroy(fmkit->stereoPilot);
    if (fmkit->iirDemphR) { iirfilt_rrrf_destroy(fmkit->iirDemphR); }
    if (fmkit->iirDemphL) { iirfilt_rrrf_destroy(fmkit->iirDemphL); }
}
コード例 #2
0
ファイル: iirfilt_runtest.c プロジェクト: Clivia/liquid-dsp
// autotest helper function
//  _b      :   filter coefficients (numerator)
//  _a      :   filter coefficients (denominator)
//  _h_len  :   filter coefficients length
//  _x      :   input array
//  _x_len  :   input array length
//  _y      :   output array
//  _y_len  :   output array length
void iirfilt_rrrf_test(float *      _b,
                       float *      _a,
                       unsigned int _h_len,
                       float *      _x,
                       unsigned int _x_len,
                       float *      _y,
                       unsigned int _y_len)
{
    float tol = 0.001f;

    // load filter coefficients externally
    iirfilt_rrrf q = iirfilt_rrrf_create(_b, _h_len, _a, _h_len);

    // allocate memory for output
    float y_test[_y_len];

    unsigned int i;
    // compute output
    for (i=0; i<_x_len; i++) {
        iirfilt_rrrf_execute(q, _x[i], &y_test[i]);
        
        CONTEND_DELTA( y_test[i], _y[i], tol );
    }

    // destroy filter object
    iirfilt_rrrf_destroy(q);
}
コード例 #3
0
//
// AUTOTEST : iir group delay (second-order sections), n=8
//
void autotest_iir_groupdelay_sos_n8()
{
    // create coefficients arrays (7th-order Butterworth)
    float B[12] = {
        0.00484212,   0.00968423,   0.00484212,
        1.00000000,   2.00000000,   1.00000000,
        1.00000000,   2.00000000,   1.00000000,
        1.00000000,   1.00000000,   0.00000000};

    float A[12] = {
        1.00000000,  -0.33283597,   0.07707999,
        1.00000000,  -0.38797498,   0.25551325,
        1.00000000,  -0.51008475,   0.65066898,
        1.00000000,  -0.15838444,   0.00000000};

    float tol = 1e-3f;
    unsigned int i;

    // create testing vectors
    float fc[7] = { 0.00000,
                    0.06250,
                    0.12500,
                    0.18750,
                    0.25000,
                    0.31250,
                    0.37500};

    float g0[7] = { 3.09280801068444,
                    3.30599360247944,
                    4.18341028373046,
                    7.71934054380586,
                    4.34330109915390,
                    2.60203085226210,
                    1.97868452107144};

    //
    // test with iir filter (second-order sections)
    //

    // create filter
    iirfilt_rrrf filter = iirfilt_rrrf_create_sos(B,A,4);

    // run tests
    float g;
    for (i=0; i<7; i++) {
        g = iirfilt_rrrf_groupdelay(filter, fc[i]);
        CONTEND_DELTA( g, g0[i], tol );
    }

    // destroy filter
    iirfilt_rrrf_destroy(filter);
}
コード例 #4
0
ファイル: cpfskmod.c プロジェクト: 0xLeo/liquid-dsp
// destroy cpfskmod object
void cpfskmod_destroy(cpfskmod _q)
{
    // destroy pulse-shaping filter/interpolator
    free(_q->ht);
    free(_q->phase_interp);
    firinterp_rrrf_destroy(_q->interp);

    // destroy phase integrator
    iirfilt_rrrf_destroy(_q->integrator);

    // free main object memory
    free(_q);
}
コード例 #5
0
//
// AUTOTEST : iir group delay, n=3
//
void autotest_iir_groupdelay_n3()
{
    // create coefficients array
    float b[3] = {0.20657210,  0.41314420, 0.20657210};
    float a[3] = {1.00000000, -0.36952737, 0.19581573};

    float tol = 1e-3f;
    unsigned int i;

    // create testing vectors
    float fc[4] = { 0.000,
                    0.125,
                    0.250,
                    0.375};
    
    float g0[4] = { 0.973248939389634,
                    1.366481121240365,
                    1.227756735863196,
                    0.651058521306726};

    // run tests
    float g;
    for (i=0; i<4; i++) {
        g = iir_group_delay(b, 3, a, 3, fc[i]);
        CONTEND_DELTA( g, g0[i], tol );
    }

    // create filter
    iirfilt_rrrf filter = iirfilt_rrrf_create(b,3,a,3);

    // run tests again
    for (i=0; i<4; i++) {
        g = iirfilt_rrrf_groupdelay(filter, fc[i]);
        CONTEND_DELTA( g, g0[i], tol );
    }

    // destroy filter
    iirfilt_rrrf_destroy(filter);
}
コード例 #6
0
//
// AUTOTEST : iir group delay, n=8
//
void autotest_iir_groupdelay_n8()
{
    // create coefficients arrays (7th-order Butterworth)
    float b[8];
    b[  0] =   0.00484212;
    b[  1] =   0.03389481;
    b[  2] =   0.10168444;
    b[  3] =   0.16947407;
    b[  4] =   0.16947407;
    b[  5] =   0.10168444;
    b[  6] =   0.03389481;
    b[  7] =   0.00484212;

    float a[8];
    a[  0] =   1.00000000;
    a[  1] =  -1.38928008;
    a[  2] =   1.67502367;
    a[  3] =  -1.05389738;
    a[  4] =   0.50855154;
    a[  5] =  -0.14482945;
    a[  6] =   0.02625222;
    a[  7] =  -0.00202968;

    float tol = 1e-3f;
    unsigned int i;

    // create testing vectors
    float fc[7] = { 0.00000,
                    0.06250,
                    0.12500,
                    0.18750,
                    0.25000,
                    0.31250,
                    0.37500};

    float g0[7] = { 3.09280801068444,
                    3.30599360247944,
                    4.18341028373046,
                    7.71934054380586,
                    4.34330109915390,
                    2.60203085226210,
                    1.97868452107144};

    // run tests
    float g;
    for (i=0; i<7; i++) {
        g = iir_group_delay(b, 8, a, 8, fc[i]);
        CONTEND_DELTA( g, g0[i], tol );
    }

    //
    // test with iir filter (tf)
    //

    // create filter
    iirfilt_rrrf filter = iirfilt_rrrf_create(b,8,a,8);

    // run tests again
    for (i=0; i<7; i++) {
        g = iirfilt_rrrf_groupdelay(filter, fc[i]);
        CONTEND_DELTA( g, g0[i], tol );
    }

    // destroy filter
    iirfilt_rrrf_destroy(filter);
}
コード例 #7
0
int main(int argc, char*argv[]) {
    srand( time(NULL) );

    // options
    float phase_offset = M_PI / 4.0f;   // phase offset
    float frequency_offset = 0.3f;      // frequency offset
    float pll_bandwidth = 0.01f;        // PLL bandwidth
    float zeta = 1/sqrtf(2.0f);         // PLL damping factor
    float K = 1000.0f;                  // PLL loop gain
    unsigned int n=512;                 // number of iterations

    int dopt;
    while ((dopt = getopt(argc,argv,"uhb:z:K:n:p:f:")) != EOF) {
        switch (dopt) {
        case 'u':
        case 'h':
            usage();
            return 0;
        case 'b':
            pll_bandwidth = atof(optarg);
            break;
        case 'z':
            zeta = atof(optarg);
            break;
        case 'K':
            K = atof(optarg);
            break;
        case 'n':
            n = atoi(optarg);
            break;
        case 'p':
            phase_offset = atof(optarg);
            break;
        case 'f':
            frequency_offset= atof(optarg);
            break;
        default:
            exit(1);
        }
    }
    unsigned int d=n/32;      // print every "d" lines

    // validate input
    if (pll_bandwidth <= 0.0f) {
        fprintf(stderr,"error: bandwidth must be greater than 0\n");
        exit(1);
    } else if (zeta <= 0.0f) {
        fprintf(stderr,"error: damping factor must be greater than 0\n");
        exit(1);
    } else if (K <= 0.0f) {
        fprintf(stderr,"error: loop gain must be greater than 0\n");
        exit(1);
    }

    // data arrays
    float complex x[n];         // input complex sinusoid
    float complex y[n];         // output complex sinusoid
    float phase_error[n];       // output phase error

    // generate PLL filter
    float b[3];
    float a[3];
    iirdes_pll_active_lag(pll_bandwidth, zeta, K, b, a);
    iirfilt_rrrf pll = iirfilt_rrrf_create(b,3,a,3);
    iirfilt_rrrf_print(pll);

    unsigned int i;
    float phi;
    for (i=0; i<n; i++) {
        phi = phase_offset + i*frequency_offset;
        x[i] = cexpf(_Complex_I*phi);
    }

    // run loop
    float theta = 0.0f;
    y[0] = 1.0f;
    for (i=0; i<n; i++) {

        // generate complex sinusoid
        y[i] = cexpf(_Complex_I*theta);

        // compute phase error
        phase_error[i] = cargf(x[i]*conjf(y[i]));

        // update pll
        iirfilt_rrrf_execute(pll, phase_error[i], &theta);

        // print phase error
        if ((i)%d == 0 || i==n-1 || i==0)
            printf("%4u : phase error = %12.8f\n", i, phase_error[i]);
    }

    // destroy filter object
    iirfilt_rrrf_destroy(pll);

    // write 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 = %u;\n", n);
    fprintf(fid,"x = zeros(1,n);\n");
    fprintf(fid,"y = zeros(1,n);\n");
    for (i=0; i<n; i++) {
        fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(x[i]), cimagf(x[i]));
        fprintf(fid,"y(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(y[i]), cimagf(y[i]));
        fprintf(fid,"e(%4u) = %12.4e;\n", i+1, phase_error[i]);
    }
    fprintf(fid,"t=0:(n-1);\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"subplot(2,1,1);\n");
    fprintf(fid,"  plot(t,real(x),t,real(y));\n");
    fprintf(fid,"  xlabel('time');\n");
    fprintf(fid,"  ylabel('real');\n");
    fprintf(fid,"subplot(2,1,2);\n");
    fprintf(fid,"  plot(t,imag(x),t,imag(y));\n");
    fprintf(fid,"  xlabel('time');\n");
    fprintf(fid,"  ylabel('imag');\n");

    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(t,e);\n");
    fprintf(fid,"xlabel('time');\n");
    fprintf(fid,"ylabel('phase error');\n");
    fprintf(fid,"grid on;\n");

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

    printf("done.\n");
    return 0;
}
コード例 #8
0
ファイル: modem_ampmodem.c プロジェクト: Sangstbk/liquid-dsp
int main(int argc, char*argv[])
{
    // options
    float mod_index = 0.1f;         // modulation index (bandwidth)
    float fc = 0.10f;               // AM carrier
    liquid_ampmodem_type type = LIQUID_AMPMODEM_DSB;
    int suppressed_carrier = 0;     // suppress the carrier?
    unsigned int num_samples = 201; // number of samples
    float SNRdB = 60.0f;            // signal-to-noise ratio [dB]

    // derived values
    unsigned int nfft = 1024;

    // create mod/demod objects
    ampmodem mod   = ampmodem_create(mod_index, fc, type, suppressed_carrier);
    ampmodem demod = ampmodem_create(mod_index, fc, type, suppressed_carrier);
    ampmodem_print(mod);

    unsigned int i;
    float x[num_samples];
    float complex y[num_samples];
    float z[num_samples];

#if 0
    // generate input data: windowed sinusoid
    float f_audio = 0.04179f;   // input sine frequency
    for (i=0; i<num_samples; i++) {
        x[i] = sinf(2*M_PI*i*f_audio) + 0.5f*sinf(2*M_PI*i*f_audio*1.8f);
        x[i] *= 0.7f*hamming(i,num_samples);
    }
#else
    // generate un-modulated input signal (filtered noise)
    float fc_audio = 0.07f;
    float f0_audio = 0.10f;
    iirfilt_rrrf f = iirfilt_rrrf_create_prototype(LIQUID_IIRDES_BUTTER,
                                                   LIQUID_IIRDES_BANDPASS,
                                                   LIQUID_IIRDES_SOS,
                                                   6, fc_audio, f0_audio, 1.0f, 1.0f);

    // push noise through filter
    for (i=0; i<100; i++)
        iirfilt_rrrf_execute(f, 1.5f*randnf(), &x[0]);
    // generate filtered/windowed output
    for (i=0; i<num_samples; i++) {
        iirfilt_rrrf_execute(f, 1.5f*randnf(), &x[i]);

        x[i] *= hamming(i,num_samples);
    }
    iirfilt_rrrf_destroy(f);
#endif

    // modulate signal
    for (i=0; i<num_samples; i++)
        ampmodem_modulate(mod, x[i], &y[i]);

    // add noise
    float nstd = powf(10.0f,-SNRdB/20.0f);
    for (i=0; i<num_samples; i++)
        cawgn(&y[i], nstd);

    // demodulate signal
    for (i=0; i<num_samples; i++)
        ampmodem_demodulate(demod, y[i], &z[i]);
    
    // destroy objects
    ampmodem_destroy(mod);
    ampmodem_destroy(demod);

    // compute power spectral density
    float complex Y[nfft];
    liquid_doc_psdwindow wtype = LIQUID_DOC_PSDWINDOW_HANN;
    int normalize = 1;
    liquid_doc_compute_psdcf(y, num_samples, Y, nfft, wtype, normalize);

    // 
    // export output files
    //
    FILE * fid;

    // time-domain plot
    fid = fopen(OUTPUT_FILENAME_TIME,"w");
    if (!fid) {
        fprintf(stderr,"error: %s, could not open '%s' for writing\n", argv[0], OUTPUT_FILENAME_TIME);
        exit(1);
    }
    fprintf(fid,"# %s: auto-generated file\n\n", OUTPUT_FILENAME_TIME);
    fprintf(fid,"reset\n");
    fprintf(fid,"set terminal postscript eps enhanced color solid rounded\n");
    fprintf(fid,"set xrange [0:%u];\n",num_samples-1);
    fprintf(fid,"set yrange [-1.2:1.2]\n");
    fprintf(fid,"set size ratio 0.3\n");
    fprintf(fid,"set xlabel 'Sample Index'\n");
    fprintf(fid,"set key top right nobox\n");
    fprintf(fid,"set ytics -5,0.5,5\n");
    fprintf(fid,"set grid xtics ytics\n");
    fprintf(fid,"set pointsize 0.6\n");
    fprintf(fid,"set grid linetype 1 linecolor rgb '%s' lw 1\n", LIQUID_DOC_COLOR_GRID);
    fprintf(fid,"set multiplot layout 2,1 scale 1.0,1.0\n");

    fprintf(fid,"# input/demodulated signals\n");
    fprintf(fid,"set ylabel 'input/output signal'\n");
    fprintf(fid,"plot '-' using 1:2 with lines linetype 1 linewidth 2 linecolor rgb '%s' title 'input',\\\n",LIQUID_DOC_COLOR_RED);
    fprintf(fid,"     '-' using 1:2 with lines linetype 1 linecolor rgb '%s' title 'demodulated'\n",LIQUID_DOC_COLOR_GRAY);
    for (i=0; i<num_samples; i++)
        fprintf(fid,"%12u %12.4e\n", i, x[i]);
    fprintf(fid,"e\n");
    for (i=0; i<num_samples; i++)
        fprintf(fid,"%12u %12.4e\n", i, z[i]);
    fprintf(fid,"e\n");

    fprintf(fid,"# demodulated signals\n");
    fprintf(fid,"set ylabel 'modulated signal'\n");
    fprintf(fid,"plot '-' using 1:2 with lines linetype 1 linewidth 1 linecolor rgb '%s' title 'real',\\\n",LIQUID_DOC_COLOR_BLUE);
    fprintf(fid,"     '-' using 1:2 with lines linetype 1 linewidth 1 linecolor rgb '%s' title 'imag',\\\n",LIQUID_DOC_COLOR_GREEN);
    fprintf(fid,"     '-' using 1:2 with lines linetype 0 linewidth 2 linecolor rgb '#222222' notitle,\\\n");
    fprintf(fid,"     '-' using 1:2 with lines linetype 0 linewidth 2 linecolor rgb '#222222' notitle\n");
    for (i=0; i<num_samples; i++)
        fprintf(fid,"%12u %12.4e\n", i, crealf(y[i]));
    fprintf(fid,"e\n");
    for (i=0; i<num_samples; i++)
        fprintf(fid,"%12u %12.4e\n", i, cimagf(y[i]));
    fprintf(fid,"e\n");

    for (i=0; i<num_samples; i++)
        fprintf(fid,"%12u %12.4e\n", i, cabsf(y[i]));
    fprintf(fid,"e\n");

    for (i=0; i<num_samples; i++)
        fprintf(fid,"%12u %12.4e\n", i, -cabsf(y[i]));
    fprintf(fid,"e\n");

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


    // frequency-domain plot
    fid = fopen(OUTPUT_FILENAME_FREQ,"w");
    if (!fid) {
        fprintf(stderr,"error: %s, could not open '%s' for writing\n", argv[0], OUTPUT_FILENAME_FREQ);
        exit(1);
    }
    fprintf(fid,"# %s: auto-generated file\n\n", OUTPUT_FILENAME_FREQ);
    fprintf(fid,"reset\n");
    fprintf(fid,"set terminal postscript eps enhanced color solid rounded\n");
    fprintf(fid,"set xrange [-0.5:0.5];\n");
    fprintf(fid,"set yrange [-100:10]\n");
    fprintf(fid,"set size ratio 0.6\n");
    fprintf(fid,"set xlabel 'Normalized Frequency'\n");
    fprintf(fid,"set ylabel 'Power Spectral Density [dB]'\n");
    fprintf(fid,"set nokey\n");
    fprintf(fid,"set xtics -0.5,0.1,0.5\n");
    fprintf(fid,"set ytics -200,20,200\n");
    fprintf(fid,"set grid xtics ytics\n");
    fprintf(fid,"set grid linetype 1 linecolor rgb '%s' lw 1\n", LIQUID_DOC_COLOR_GRID);

    fprintf(fid,"# spectrum\n");
    fprintf(fid,"set style fill solid 0.1\n");
    fprintf(fid,"plot '-' using 1:2 with filledcurves above y1=-200 linetype 1 linewidth 3 linecolor rgb '%s' title 'input'\n",LIQUID_DOC_COLOR_PURPLE);
    for (i=0; i<nfft; i++)
        fprintf(fid,"%12.8f %12.4e\n", (float)i/(float)nfft - 0.5f, 20*log10f(cabsf(Y[(i+nfft/2)%nfft])));
    fprintf(fid,"e\n");

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

    return 0;
}
コード例 #9
0
int main(int argc, char*argv[]) {
    // options
    unsigned int k  = 8;        // filter samples/symbol
    unsigned int bps= 1;        // number of bits/symbol
    float h         = 0.5f;     // modulation index (h=1/2 for MSK)
    unsigned int num_data_symbols = 20; // number of data symbols
    float SNRdB     = 80.0f;    // signal-to-noise ratio [dB]
    float cfo       = 0.0f;     // carrier frequency offset
    float cpo       = 0.0f;     // carrier phase offset
    float tau       = 0.0f;     // fractional symbol offset
    enum {
        TXFILT_SQUARE=0,
        TXFILT_RCOS_FULL,
        TXFILT_RCOS_HALF,
        TXFILT_GMSK,
    } tx_filter_type = TXFILT_SQUARE;
    float gmsk_bt = 0.35f;              // GMSK bandwidth-time factor

    int dopt;
    while ((dopt = getopt(argc,argv,"ht:k:b:H:B:n:s:F:P:T:")) != EOF) {
        switch (dopt) {
        case 'h': usage();                         return 0;
        case 't':
            if (strcmp(optarg,"square")==0) {
                tx_filter_type = TXFILT_SQUARE;
            } else if (strcmp(optarg,"rcos-full")==0) {
                tx_filter_type = TXFILT_RCOS_FULL;
            } else if (strcmp(optarg,"rcos-half")==0) {
                tx_filter_type = TXFILT_RCOS_HALF;
            } else if (strcmp(optarg,"gmsk")==0) {
                tx_filter_type = TXFILT_GMSK;
            } else {
                fprintf(stderr,"error: %s, unknown filter type '%s'\n", argv[0], optarg);
                exit(1);
            }
            break;
        case 'k': k = atoi(optarg);                break;
        case 'b': bps = atoi(optarg);              break;
        case 'H': h = atof(optarg);                break;
        case 'B': gmsk_bt = atof(optarg);          break;
        case 'n': num_data_symbols = atoi(optarg); break;
        case 's': SNRdB = atof(optarg);            break;
        case 'F': cfo   = atof(optarg);            break;
        case 'P': cpo   = atof(optarg);            break;
        case 'T': tau   = atof(optarg);            break;
        default:
            exit(1);
        }
    }

    unsigned int i;

    // derived values
    unsigned int num_symbols = num_data_symbols;
    unsigned int num_samples = k*num_symbols;
    unsigned int M = 1 << bps;              // constellation size
    float nstd = powf(10.0f, -SNRdB/20.0f);

    // arrays
    unsigned char sym_in[num_symbols];      // input symbols
    float phi[num_samples];                 // transmitted phase
    float complex x[num_samples];           // transmitted signal
    float complex y[num_samples];           // received signal
    float complex z[num_samples];           // output...
    //unsigned char sym_out[num_symbols];     // output symbols

    unsigned int ht_len = 0;
    unsigned int tx_delay = 0;
    float * ht = NULL;
    switch (tx_filter_type) {
    case TXFILT_SQUARE:
        // regular MSK
        ht_len = k;
        tx_delay = 1;
        ht = (float*) malloc(ht_len *sizeof(float));
        for (i=0; i<ht_len; i++)
            ht[i] = h * M_PI / (float)k;
        break;
    case TXFILT_RCOS_FULL:
        // full-response raised-cosine pulse
        ht_len = k;
        tx_delay = 1;
        ht = (float*) malloc(ht_len *sizeof(float));
        for (i=0; i<ht_len; i++)
            ht[i] = h * M_PI / (float)k * (1.0f - cosf(2.0f*M_PI*i/(float)ht_len));
        break;
    case TXFILT_RCOS_HALF:
        // partial-response raised-cosine pulse
        ht_len = 3*k;
        tx_delay = 2;
        ht = (float*) malloc(ht_len *sizeof(float));
        for (i=0; i<ht_len; i++)
            ht[i] = 0.0f;
        for (i=0; i<2*k; i++)
            ht[i+k/2] = h * 0.5f * M_PI / (float)k * (1.0f - cosf(2.0f*M_PI*i/(float)(2*k)));
        break;
    case TXFILT_GMSK:
        ht_len = 2*k*3+1+k;
        tx_delay = 4;
        ht = (float*) malloc(ht_len *sizeof(float));
        for (i=0; i<ht_len; i++)
            ht[i] = 0.0f;
        liquid_firdes_gmsktx(k,3,gmsk_bt,0.0f,&ht[k/2]);
        for (i=0; i<ht_len; i++)
            ht[i] *= h * 2.0f / (float)k;
        break;
    default:
        fprintf(stderr,"error: %s, invalid tx filter type\n", argv[0]);
        exit(1);
    }
    for (i=0; i<ht_len; i++)
        printf("ht(%3u) = %12.8f;\n", i+1, ht[i]);
    firinterp_rrrf interp_tx = firinterp_rrrf_create(k, ht, ht_len);

    // generate symbols and interpolate
    // phase-accumulating filter (trapezoidal integrator)
    float b[2] = {0.5f,  0.5f};
    if (tx_filter_type == TXFILT_SQUARE) {
        // square filter: rectangular integration with one sample of delay
        b[0] = 0.0f;
        b[1] = 1.0f;
    }
    float a[2] = {1.0f, -1.0f};
    iirfilt_rrrf integrator = iirfilt_rrrf_create(b,2,a,2);
    float theta = 0.0f;
    for (i=0; i<num_symbols; i++) {
        sym_in[i] = rand() % M;
        float v = 2.0f*sym_in[i] - (float)(M-1);    // +/-1, +/-3, ... +/-(M-1)
        firinterp_rrrf_execute(interp_tx, v, &phi[k*i]);

        // accumulate phase
        unsigned int j;
        for (j=0; j<k; j++) {
            iirfilt_rrrf_execute(integrator, phi[i*k+j], &theta);
            x[i*k+j] = cexpf(_Complex_I*theta);
        }
    }
    iirfilt_rrrf_destroy(integrator);

    // push through channel
    for (i=0; i<num_samples; i++) {
        // add carrier frequency/phase offset
        y[i] = x[i]*cexpf(_Complex_I*(cfo*i + cpo));

        // add noise
        y[i] += nstd*(randnf() + _Complex_I*randnf())*M_SQRT1_2;
    }
    
    // create decimator
    unsigned int m = 3;
    float bw = 0.0f;
    float beta = 0.0f;
    firfilt_crcf decim_rx = NULL;
    switch (tx_filter_type) {
    case TXFILT_SQUARE:
        //bw = 0.9f / (float)k;
        bw = 0.4f;
        decim_rx = firfilt_crcf_create_kaiser(2*k*m+1, bw, 60.0f, 0.0f);
        firfilt_crcf_set_scale(decim_rx, 2.0f * bw);
        break;
    case TXFILT_RCOS_FULL:
        if (M==2) {
            decim_rx = firfilt_crcf_create_rnyquist(LIQUID_FIRFILT_GMSKRX,k,m,0.5f,0);
            firfilt_crcf_set_scale(decim_rx, 1.33f / (float)k);
        } else {
            decim_rx = firfilt_crcf_create_rnyquist(LIQUID_FIRFILT_GMSKRX,k/2,2*m,0.9f,0);
            firfilt_crcf_set_scale(decim_rx, 3.25f / (float)k);
        }
        break;
    case TXFILT_RCOS_HALF:
        if (M==2) {
            decim_rx = firfilt_crcf_create_rnyquist(LIQUID_FIRFILT_GMSKRX,k,m,0.3f,0);
            firfilt_crcf_set_scale(decim_rx, 1.10f / (float)k);
        } else {
            decim_rx = firfilt_crcf_create_rnyquist(LIQUID_FIRFILT_GMSKRX,k/2,2*m,0.27f,0);
            firfilt_crcf_set_scale(decim_rx, 2.90f / (float)k);
        }
        break;
    case TXFILT_GMSK:
        bw = 0.5f / (float)k;
        // TODO: figure out beta value here
        beta = (M == 2) ? 0.8*gmsk_bt : 1.0*gmsk_bt;
        decim_rx = firfilt_crcf_create_rnyquist(LIQUID_FIRFILT_GMSKRX,k,m,beta,0);
        firfilt_crcf_set_scale(decim_rx, 2.0f * bw);
        break;
    default:
        fprintf(stderr,"error: %s, invalid tx filter type\n", argv[0]);
        exit(1);
    }
    printf("bw = %f\n", bw);

    // run receiver
    unsigned int n=0;
    unsigned int num_errors = 0;
    unsigned int num_symbols_checked = 0;
    float complex z_prime = 0.0f;
    for (i=0; i<num_samples; i++) {
        // push through filter
        firfilt_crcf_push(decim_rx, y[i]);
        firfilt_crcf_execute(decim_rx, &z[i]);

        // decimate output
        if ( (i%k)==0 ) {
            // compute instantaneous frequency scaled by modulation index
            float phi_hat = cargf(conjf(z_prime) * z[i]) / (h * M_PI);

            // estimate transmitted symbol
            float v = (phi_hat + (M-1.0))*0.5f;
            unsigned int sym_out = ((int) roundf(v)) % M;

            // save current point
            z_prime = z[i];

            // print result to screen
            printf("%3u : %12.8f + j%12.8f, <f=%8.4f : %8.4f> (%1u)",
                    n, crealf(z[i]), cimagf(z[i]), phi_hat, v, sym_out);
            if (n >= m+tx_delay) {
                num_errors += (sym_out == sym_in[n-m-tx_delay]) ? 0 : 1;
                num_symbols_checked++;
                printf(" (%1u)\n", sym_in[n-m-tx_delay]);
            } else {
                printf("\n");
            }
            n++;
        }
    }

    // print number of errors
    printf("errors : %3u / %3u\n", num_errors, num_symbols_checked);

    // destroy objects
    firinterp_rrrf_destroy(interp_tx);
    firfilt_crcf_destroy(decim_rx);

    // compute power spectral density of transmitted signal
    unsigned int nfft = 1024;
    float psd[nfft];
    spgramcf periodogram = spgramcf_create_kaiser(nfft, nfft/2, 8.0f);
    spgramcf_estimate_psd(periodogram, y, num_samples, psd);
    spgramcf_destroy(periodogram);

    // 
    // 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,"k = %u;\n", k);
    fprintf(fid,"h = %f;\n", h);
    fprintf(fid,"num_symbols = %u;\n", num_symbols);
    fprintf(fid,"num_samples = %u;\n", num_samples);
    fprintf(fid,"nfft        = %u;\n", nfft);
    fprintf(fid,"delay       = %u; %% receive filter delay\n", tx_delay);

    fprintf(fid,"x   = zeros(1,num_samples);\n");
    fprintf(fid,"y   = zeros(1,num_samples);\n");
    fprintf(fid,"z   = zeros(1,num_samples);\n");
    fprintf(fid,"phi = zeros(1,num_samples);\n");
    for (i=0; i<num_samples; i++) {
        fprintf(fid,"x(%4u) = %12.8f + j*%12.8f;\n", i+1, crealf(x[i]), cimagf(x[i]));
        fprintf(fid,"y(%4u) = %12.8f + j*%12.8f;\n", i+1, crealf(y[i]), cimagf(y[i]));
        fprintf(fid,"z(%4u) = %12.8f + j*%12.8f;\n", i+1, crealf(z[i]), cimagf(z[i]));
        fprintf(fid,"phi(%4u) = %12.8f;\n", i+1, phi[i]);
    }
    // save PSD
    fprintf(fid,"psd = zeros(1,nfft);\n");
    for (i=0; i<nfft; i++)
        fprintf(fid,"psd(%4u) = %12.8f;\n", i+1, psd[i]);

    fprintf(fid,"t=[0:(num_samples-1)]/k;\n");
    fprintf(fid,"i = 1:k:num_samples;\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"subplot(3,4,1:3);\n");
    fprintf(fid,"  plot(t,real(x),'-', t(i),real(x(i)),'bs','MarkerSize',4,...\n");
    fprintf(fid,"       t,imag(x),'-', t(i),imag(x(i)),'gs','MarkerSize',4);\n");
    fprintf(fid,"  axis([0 num_symbols -1.2 1.2]);\n");
    fprintf(fid,"  xlabel('time');\n");
    fprintf(fid,"  ylabel('x(t)');\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"subplot(3,4,5:7);\n");
    fprintf(fid,"  plot(t-delay,real(z),'-', t(i)-delay,real(z(i)),'bs','MarkerSize',4,...\n");
    fprintf(fid,"       t-delay,imag(z),'-', t(i)-delay,imag(z(i)),'gs','MarkerSize',4);\n");
    fprintf(fid,"  axis([0 num_symbols -1.2 1.2]);\n");
    fprintf(fid,"  xlabel('time');\n");
    fprintf(fid,"  ylabel('\"matched\" filter output');\n");
    fprintf(fid,"  grid on;\n");
    // plot I/Q constellations
    fprintf(fid,"subplot(3,4,4);\n");
    fprintf(fid,"  plot(real(y),imag(y),'-',real(y(i)),imag(y(i)),'rs','MarkerSize',3);\n");
    fprintf(fid,"  xlabel('I');\n");
    fprintf(fid,"  ylabel('Q');\n");
    fprintf(fid,"  axis([-1 1 -1 1]*1.2);\n");
    fprintf(fid,"  axis square;\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"subplot(3,4,8);\n");
    fprintf(fid,"  plot(real(z),imag(z),'-',real(z(i)),imag(z(i)),'rs','MarkerSize',3);\n");
    fprintf(fid,"  xlabel('I');\n");
    fprintf(fid,"  ylabel('Q');\n");
    fprintf(fid,"  axis([-1 1 -1 1]*1.2);\n");
    fprintf(fid,"  axis square;\n");
    fprintf(fid,"  grid on;\n");
    // plot PSD
    fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n");
    fprintf(fid,"subplot(3,4,9:12);\n");
    fprintf(fid,"  plot(f,psd,'LineWidth',1.5);\n");
    fprintf(fid,"  axis([-0.5 0.5 -40 20]);\n");
    fprintf(fid,"  xlabel('Normalized Frequency [f/F_s]');\n");
    fprintf(fid,"  ylabel('PSD [dB]');\n");
    fprintf(fid,"  grid on;\n");

#if 0
    fprintf(fid,"figure;\n");
    fprintf(fid,"  %% compute instantaneous received frequency\n");
    fprintf(fid,"  freq_rx = arg( conj(z(:)) .* circshift(z(:),-1) )';\n");
    fprintf(fid,"  freq_rx(1:(k*delay)) = 0;\n");
    fprintf(fid,"  freq_rx(end) = 0;\n");
    fprintf(fid,"  %% compute instantaneous tx/rx phase\n");
    if (tx_filter_type == TXFILT_SQUARE) {
        fprintf(fid,"  theta_tx = filter([0 1],[1 -1],phi)/(h*pi);\n");
        fprintf(fid,"  theta_rx = filter([0 1],[1 -1],freq_rx)/(h*pi);\n");
    } else {
        fprintf(fid,"  theta_tx = filter([0.5 0.5],[1 -1],phi)/(h*pi);\n");
        fprintf(fid,"  theta_rx = filter([0.5 0.5],[1 -1],freq_rx)/(h*pi);\n");
    }
    fprintf(fid,"  %% plot instantaneous tx/rx phase\n");
    fprintf(fid,"  plot(t,      theta_tx,'-b', t(i),      theta_tx(i),'sb',...\n");
    fprintf(fid,"       t-delay,theta_rx,'-r', t(i)-delay,theta_rx(i),'sr');\n");
    fprintf(fid,"  xlabel('time');\n");
    fprintf(fid,"  ylabel('instantaneous phase/(h \\pi)');\n");
    fprintf(fid,"  legend('transmitted','syms','received/filtered','syms','location','northwest');\n");
    fprintf(fid,"  grid on;\n");
#else
    // plot filter response
    fprintf(fid,"ht_len = %u;\n", ht_len);
    fprintf(fid,"ht     = zeros(1,ht_len);\n");
    for (i=0; i<ht_len; i++)
        fprintf(fid,"ht(%4u) = %12.8f;\n", i+1, ht[i]);
    fprintf(fid,"gt1 = filter([0.5 0.5],[1 -1],ht) / (pi*h);\n");
    fprintf(fid,"gt2 = filter([0.0 1.0],[1 -1],ht) / (pi*h);\n");
    fprintf(fid,"tfilt = [0:(ht_len-1)]/k - delay + 0.5;\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(tfilt,ht, '-x','MarkerSize',4,...\n");
    fprintf(fid,"     tfilt,gt1,'-x','MarkerSize',4,...\n");
    fprintf(fid,"     tfilt,gt2,'-x','MarkerSize',4);\n");
    fprintf(fid,"axis([tfilt(1) tfilt(end) -0.1 1.1]);\n");
    fprintf(fid,"legend('pulse','trap. int.','rect. int.','location','northwest');\n");
    fprintf(fid,"grid on;\n");
#endif

    fclose(fid);
    printf("results written to '%s'\n", OUTPUT_FILENAME);
    
    // free allocated filter memory
    free(ht);

    return 0;
}
コード例 #10
0
ファイル: pll_example.c プロジェクト: 0xLeo/liquid-dsp
int main() {
    // parameters
    float phase_offset      = 0.8f;     // carrier phase offset
    float frequency_offset  = 0.01f;    // carrier frequency offset
    float wn                = 0.05f;    // pll bandwidth
    float zeta              = 0.707f;   // pll damping factor
    float K                 = 1000;     // pll loop gain
    unsigned int n          = 256;      // number of samples
    unsigned int d          = n/32;     // print every "d" lines

    //
    float theta[n];         // input phase
    float complex x[n];     // input sinusoid
    float phi[n];           // output phase
    float complex y[n];     // output sinusoid

    // generate iir loop filter object
    iirfilt_rrrf H = iirfilt_rrrf_create_pll(wn, zeta, K);
    iirfilt_rrrf_print(H);

    unsigned int i;

    // generate input
    float t=phase_offset;
    float dt = frequency_offset;
    for (i=0; i<n; i++) {
        theta[i] = t;
        x[i] = cexpf(_Complex_I*theta[i]);

        t += dt;
    }

    // run loop
    float phi_hat=0.0f;
    for (i=0; i<n; i++) {
        y[i] = cexpf(_Complex_I*phi_hat);

        // compute error
        float e = cargf(x[i]*conjf(y[i]));

        if ( (i%d)==0 )
            printf("e(%3u) = %12.8f;\n", i, e);

        // filter error
        iirfilt_rrrf_execute(H,e,&phi_hat);

        phi[i] = phi_hat;
    }

    // destroy filter
    iirfilt_rrrf_destroy(H);

    // open output file
    FILE * fid = fopen(OUTPUT_FILENAME,"w");
    fprintf(fid,"clear all;\n");
    fprintf(fid,"n=%u;\n",n);

    for (i=0; i<n; i++) {
        fprintf(fid,"theta(%3u) = %16.8e;\n", i+1, theta[i]);
        fprintf(fid,"  phi(%3u) = %16.8e;\n", i+1, phi[i]);
    }
    fprintf(fid,"t=0:(n-1);\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(t,theta,t,phi);\n");
    fprintf(fid,"xlabel('sample index');\n");
    fprintf(fid,"ylabel('phase');\n");

    fclose(fid);

    printf("output written to %s.\n", OUTPUT_FILENAME);

    printf("done.\n");
    return 0;
}
コード例 #11
0
ファイル: pll_design_test.c プロジェクト: 0xLeo/liquid-dsp
int main() {
    // parameters
    float phase_offset = 0.8f;
    float frequency_offset = 0.01f;
    float pll_bandwidth = 0.05f;
    float pll_damping_factor = 0.707f;
    unsigned int n=256;     // number of iterations
    unsigned int d=n/32;    // print every "d" lines

    //
    float theta[n];         // input phase
    float complex x[n];     // input sinusoid
    float phi[n];           // output phase
    float complex y[n];     // output sinusoid

    // generate iir loop filter(s)
    float a[3];
    float b[3];
    float wn = pll_bandwidth;
    float zeta = pll_damping_factor;
    float K = 10; // loop gain

#if 0
    // loop filter (active lag)
    float t1 = K/(wn*wn);
    float t2 = 2*zeta/wn - 1/K;

    b[0] = 2*K*(1.+t2/2.0f);
    b[1] = 2*K*2.;
    b[2] = 2*K*(1.-t2/2.0f);

    a[0] =  1 + t1/2.0f;
    a[1] = -t1;
    a[2] = -1 + t1/2.0f;
#else
    // loop filter (active PI)
    float t1 = K/(wn*wn);
    float t2 = 2*zeta/wn;

    b[0] = 2*K*(1.+t2/2.0f);
    b[1] = 2*K*2.;
    b[2] = 2*K*(1.-t2/2.0f);

    a[0] =  t1/2.0f;
    a[1] = -t1;
    a[2] =  t1/2.0f;
#endif
    iirfilt_rrrf H = iirfilt_rrrf_create(b,3,a,3);
    iirfilt_rrrf_print(H);

    unsigned int i;

    // generate input
    float t=phase_offset;
    float dt = frequency_offset;
    for (i=0; i<n; i++) {
        theta[i] = t;
        x[i] = cexpf(_Complex_I*theta[i]);

        t += dt;
    }

    // run loop
    float phi_hat=0.0f;
    for (i=0; i<n; i++) {
        y[i] = cexpf(_Complex_I*phi_hat);

        // compute error
        float e = cargf(x[i]*conjf(y[i]));

        if ( (i%d)==0 )
            printf("e(%3u) = %12.8f;\n", i, e);

        // filter error
        iirfilt_rrrf_execute(H,e,&phi_hat);

        phi[i] = phi_hat;
    }

    // destroy filter
    iirfilt_rrrf_destroy(H);

    // open output file
    FILE * fid = fopen(OUTPUT_FILENAME,"w");
    fprintf(fid,"clear all;\n");
    fprintf(fid,"n=%u;\n",n);

    fprintf(fid,"a(1) = %16.8e;\n", a[0]);
    fprintf(fid,"a(2) = %16.8e;\n", a[1]);
    fprintf(fid,"a(3) = %16.8e;\n", a[2]);

    fprintf(fid,"b(1) = %16.8e;\n", b[0]);
    fprintf(fid,"b(2) = %16.8e;\n", b[1]);
    fprintf(fid,"b(3) = %16.8e;\n", b[2]);

    //fprintf(fid,"figure;\n");
    //fprintf(fid,"freqz(b,a);\n");

    for (i=0; i<n; i++) {
        fprintf(fid,"theta(%3u) = %16.8e;\n", i+1, theta[i]);
        fprintf(fid,"  phi(%3u) = %16.8e;\n", i+1, phi[i]);
    }
    fprintf(fid,"t=0:(n-1);\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(t,theta,t,phi);\n");
    fprintf(fid,"xlabel('sample index');\n");
    fprintf(fid,"ylabel('phase');\n");

    fclose(fid);

    printf("output written to %s.\n", OUTPUT_FILENAME);

    printf("done.\n");
    return 0;
}
コード例 #12
0
ファイル: lpc_example.c プロジェクト: Clivia/liquid-dsp
int main() {
    // options
    unsigned int n = 200;   // input sequence length
    unsigned int p = 4;     // prediction filter order

    // original filter
#if 1
    // autoregressive moving average filter
    // ./examples/iirdes_example -t butter -n3 -otf -f0.2
    float b[4] = {0.01809893, 0.05429679, 0.05429679, 0.01809893};
    float a[4] = {1.00000000, -1.76004195, 1.18289328, -0.27805993};
#else
    // autoregressive filter
    float b[4] = {1.0f, 0.0f, 0.0f, 0.0f};
    float a[4] = {1.0f, 0.5f, 0.4f, 0.3f};
#endif

    // create filter object
    iirfilt_rrrf f = iirfilt_rrrf_create(b,4, a,4);
    iirfilt_rrrf_print(f);

    unsigned int i;

    // allocate memory for data arrays
    float x[n];         // input noise sequence
    float y[n];         // output filtered noise sequence
    float a_hat[p+1];   // lpc output
    float g_hat[p+1];   // lpc output

    // generate input noise signal
    for (i=0; i<n; i++) {
        x[i] = randnf();
        //x[i] = ( (i%20) == 0 ) ? 1.0f : 0.0f;
    }

    // run filter
    for (i=0; i<n; i++)
        iirfilt_rrrf_execute(f, x[i], &y[i]);

    // destroy filter object
    iirfilt_rrrf_destroy(f);

    // run linear prediction algorithm
    liquid_lpc(y,n,p,a_hat,g_hat);

    // run prediction filter
    float a_lpc[p+1];
    float b_lpc[p+1];
    for (i=0; i<p+1; i++) {
        a_lpc[i] = (i==0) ? 1.0f : 0.0f;
        b_lpc[i] = (i==0) ? 0.0f : -a_hat[i];
    }
    f = iirfilt_rrrf_create(b_lpc,p+1, a_lpc,p+1);
    iirfilt_rrrf_print(f);
    float y_hat[n];
    for (i=0; i<n; i++)
        iirfilt_rrrf_execute(f, y[i], &y_hat[i]);
    iirfilt_rrrf_destroy(f);

    // compute prediction error
    float err[n];
    for (i=0; i<n; i++)
        err[i] = y[i] - y_hat[i];

    // compute autocorrelation of prediction error
    float lag[n];
    float rxx[n];
    for (i=0; i<n; i++) {
        lag[i] = (float)i;
        rxx[i] = 0.0f;
        unsigned int j;
        for (j=i; j<n; j++)
            rxx[i] += err[j] * err[j-i];
    }
    float rxx0 = rxx[0];
    for (i=0; i<n; i++)
        rxx[i] /= rxx0;

    // print results
    for (i=0; i<p+1; i++)
        printf("  a[%3u] = %12.8f, g[%3u] = %12.8f\n", i, a_hat[i], i, g_hat[i]);

    printf("  prediction rmse = %12.8f\n", sqrtf(rxx0 / n));

    // 
    // plot results to 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,"p=%u;\n", p);
    fprintf(fid,"n=%u;\n",n);

#if 0
    fprintf(fid,"b  = zeros(1,p+1);\n");
    fprintf(fid,"a  = zeros(1,p+1);\n");
    for (i=0; i<p+1; i++) {
        fprintf(fid,"b(%4u) = %12.4e;\n", i+1, b_lpc[i]);
        fprintf(fid,"a(%4u) = %12.4e;\n", i+1, a_lpc[i]);
    }
#endif

    fprintf(fid,"x      = zeros(1,n);\n");
    fprintf(fid,"y      = zeros(1,n);\n");
    fprintf(fid,"y_hat  = zeros(1,n);\n");
    fprintf(fid,"lag    = zeros(1,n);\n");
    fprintf(fid,"rxx    = zeros(1,n);\n");
    for (i=0; i<n; i++) {
        fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(x[i]), cimagf(x[i]));
        fprintf(fid,"y(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(y[i]), cimagf(y[i]));
        fprintf(fid,"y_hat(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(y_hat[i]), cimagf(y_hat[i]));
        fprintf(fid,"lag(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(lag[i]), cimagf(lag[i]));
        fprintf(fid,"rxx(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(rxx[i]), cimagf(rxx[i]));
    }

    // plot output
    fprintf(fid,"t=0:(n-1);\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"  plot(t,x,'-','Color',[1 1 1]*0.5,'LineWidth',1,...\n");
    fprintf(fid,"       t,y,'-','Color',[0 0.5 0.25],'LineWidth',2);\n");
    fprintf(fid,"  xlabel('time');\n");
    fprintf(fid,"  ylabel('real');\n");
    fprintf(fid,"  legend('input','filtered output',1);\n");
    fprintf(fid,"  grid on;\n");

    fprintf(fid,"figure;\n");
    fprintf(fid,"subplot(5,1,1:3);\n");
    fprintf(fid,"  plot(t,y,t,y_hat);\n");
    fprintf(fid,"  ylabel('signal');\n");
    fprintf(fid,"  legend('y','lpc estimate',1);\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"subplot(5,1,4);\n");
    fprintf(fid,"  plot(t,y-y_hat);\n");
    fprintf(fid,"  ylabel('error');\n");
    fprintf(fid,"subplot(5,1,5);\n");
    fprintf(fid,"  plot(t,rxx);\n");
    fprintf(fid,"  xlabel('time');\n");
    fprintf(fid,"  ylabel('r_{xx}(e)');\n");

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

    printf("done.\n");
    return 0;
}