int main() {
    // options
    unsigned int num_channels=8;    // number of channels
    unsigned int m=2;               // filter delay
    float As=-60;                   // stop-band attenuation
    unsigned int num_frames=25;     // number of frames

    // create objects
    firpfbch_crcf c = firpfbch_crcf_create_kaiser(LIQUID_ANALYZER, num_channels, m, As);

    //firpfbch_crcf_print(c);

    FILE*fid = fopen(OUTPUT_FILENAME,"w");
    fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME);
    fprintf(fid,"clear all;\nclose all;\n\n");
    fprintf(fid,"num_channels=%u;\n", num_channels);
    fprintf(fid,"num_frames=%u;\n", num_frames);

    fprintf(fid,"x = zeros(1,%u);\n",  num_channels * num_frames);
    fprintf(fid,"y  = zeros(%u,%u);\n", num_channels, num_frames);

    unsigned int i, j, n=0;
    float complex x[num_channels];  // time-domain input
    float complex y[num_channels];  // channelized output

    // create nco: sweeps entire range of frequencies over the evaluation interval
    nco_crcf nco_tx = nco_crcf_create(LIQUID_VCO);
    nco_crcf_set_frequency(nco_tx, 0.0f);
    float df = 2*M_PI/(num_channels*num_frames);
    printf("fr/ch:");
    for (j=0; j<num_channels; j++)  printf("%3u",j);
    printf("\n");
    for (i=0; i<num_frames; i++) {

        // generate frame of data
        for (j=0; j<num_channels; j++) {
            nco_crcf_cexpf(nco_tx, &x[j]);
            nco_crcf_adjust_frequency(nco_tx, df);
            nco_crcf_step(nco_tx);
        }

        // execute analysis filter bank
        firpfbch_crcf_analyzer_execute(c, x, y);

        printf("%4u : ", i);
        for (j=0; j<num_channels; j++) {
            if (cabsf(y[j]) > num_channels / 4)
                printf(" x ");
            else
                printf(" . ");
        }
        printf("\n");

        // write output to file
        for (j=0; j<num_channels; j++) {
            // frequency data
            fprintf(fid,"y(%4u,%4u) = %12.4e + j*%12.4e;\n", j+1, i+1, crealf(y[j]), cimagf(y[j]));

            // time data
            fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", n+1, crealf(x[j]), cimag(x[j]));
            n++;
        }
    }

    // destroy objects
    nco_crcf_destroy(nco_tx);
    firpfbch_crcf_destroy(c);

    // plot results
    fprintf(fid,"\n\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"subplot(2,1,1);\n");
    fprintf(fid,"  plot(1:length(x),real(x),1:length(x),imag(x));\n");
    fprintf(fid,"  xlabel('time');\n");
    fprintf(fid,"  ylabel('signal');\n");
    fprintf(fid,"subplot(2,1,2);\n");
    fprintf(fid,"  plot(20*log10(abs(y.')/num_channels));\n");
    fprintf(fid,"  xlabel('time (decimated)');\n");
    fprintf(fid,"  ylabel('channelized energy [dB]');\n");

    fprintf(fid,"n=min(num_channels,8);\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"for i=1:n\n");
    fprintf(fid,"  subplot(n,1,i);\n");
    fprintf(fid,"  plot(1:num_frames,real(y(i,:)),1:num_frames,imag(y(i,:)));\n");
    fprintf(fid,"  axis off;\n");
    fprintf(fid,"  ylabel(num2str(i));\n");
    fprintf(fid,"end;\n");


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

    printf("done.\n");
    return 0;
}
Exemplo n.º 2
0
void SDRPostThread::runPFBCH(SDRThreadIQData *data_in) {
    if (numChannels != data_in->numChannels || sampleRate != data_in->sampleRate) {
        numChannels = data_in->numChannels;
        sampleRate = data_in->sampleRate;
        initPFBChannelizer();
        doRefresh.store(true);
    }
    
    size_t dataSize = data_in->data.size();
    size_t outSize = data_in->data.size();
    
    if (outSize > dataOut.capacity()) {
        dataOut.reserve(outSize);
    }
    if (outSize != dataOut.size()) {
        dataOut.resize(outSize);
    }
    
    if (iqDataOutQueue != NULL && !iqDataOutQueue->full()) {
        DemodulatorThreadIQData *iqDataOut = visualDataBuffers.getBuffer();
        
        bool doVis = false;
        
        if (iqVisualQueue != NULL && !iqVisualQueue->full()) {
            doVis = true;
        }
        
        iqDataOut->setRefCount(1 + (doVis?1:0));
        
        iqDataOut->frequency = data_in->frequency;
        iqDataOut->sampleRate = data_in->sampleRate;
        iqDataOut->data.assign(data_in->data.begin(), data_in->data.begin() + dataSize);
        
        iqDataOutQueue->push(iqDataOut);
        if (doVis) {
            iqVisualQueue->push(iqDataOut);
        }
    }
    
    if (frequency != data_in->frequency) {
        frequency = data_in->frequency;
        doRefresh.store(true);
    }
    
    if (doRefresh.load()) {
        updateActiveDemodulators();
        updateChannels();
        doRefresh.store(false);
    }
    
    DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
    int activeDemodChannel = -1;
    
    // Find active demodulators
    if (nRunDemods) {
        
        // channelize data
        // firpfbch output rate is (input rate / channels)
        for (int i = 0, iMax = dataSize; i < iMax; i+=numChannels) {
            firpfbch_crcf_analyzer_execute(channelizer, &data_in->data[i], &dataOut[i]);
        }
        
        for (int i = 0, iMax = numChannels+1; i < iMax; i++) {
            demodChannelActive[i] = 0;
        }
        
        // Find nearest channel for each demodulator
        for (size_t i = 0; i < nRunDemods; i++) {
            DemodulatorInstance *demod = runDemods[i];
            demodChannel[i] = getChannelAt(demod->getFrequency());
            if (demod == activeDemod) {
                activeDemodChannel = demodChannel[i];
            }
        }
        
        for (size_t i = 0; i < nRunDemods; i++) {
            // cache channel usage refcounts
            if (demodChannel[i] >= 0) {
                demodChannelActive[demodChannel[i]]++;
            }
        }
        
        // Run channels
        for (int i = 0; i < numChannels+1; i++) {
            int doDemodVis = ((activeDemodChannel == i) && (iqActiveDemodVisualQueue != NULL) && !iqActiveDemodVisualQueue->full())?1:0;
            
            if (!doDemodVis && demodChannelActive[i] == 0) {
                continue;
            }
            
            DemodulatorThreadIQData *demodDataOut = buffers.getBuffer();
            demodDataOut->setRefCount(demodChannelActive[i] + doDemodVis);
            demodDataOut->frequency = chanCenters[i];
            demodDataOut->sampleRate = chanBw;
            
            // Calculate channel buffer size
            size_t chanDataSize = (outSize/numChannels);
            
            if (demodDataOut->data.size() != chanDataSize) {
                if (demodDataOut->data.capacity() < chanDataSize) {
                    demodDataOut->data.reserve(chanDataSize);
                }
                demodDataOut->data.resize(chanDataSize);
            }
            
            int idx = i;
            
            // Extra channel wraps lower side band of lowest channel
            // to fix frequency gap on upper side of spectrum
            if (i == numChannels) {
                idx = (numChannels/2);
            }
            
            // prepare channel data buffer
            if (i == 0) {   // Channel 0 requires DC correction
                if (dcBuf.size() != chanDataSize) {
                    dcBuf.resize(chanDataSize);
                }
                for (size_t j = 0; j < chanDataSize; j++) {
                    dcBuf[j] = dataOut[idx];
                    idx += numChannels;
                }
                iirfilt_crcf_execute_block(dcFilter, &dcBuf[0], chanDataSize, &demodDataOut->data[0]);
            } else {
                for (size_t j = 0; j < chanDataSize; j++) {
                    demodDataOut->data[j] = dataOut[idx];
                    idx += numChannels;
                }
            }
            
            if (doDemodVis) {
                iqActiveDemodVisualQueue->push(demodDataOut);
            }
            
            for (size_t j = 0; j < nRunDemods; j++) {
                if (demodChannel[j] == i) {
                    DemodulatorInstance *demod = runDemods[j];
                    demod->getIQInputDataPipe()->push(demodDataOut);
                }
            }
        }
    }
}
Exemplo n.º 3
0
int main() {
    // options
    unsigned int num_channels=4;    // number of channels
    unsigned int p=3;               // filter length (symbols)
    unsigned int num_symbols=6;     // number of symbols

    // derived values
    unsigned int num_samples = num_channels * num_symbols;

    unsigned int i;
    unsigned int j;

    // generate synthesis filter
    // NOTE : these coefficients can be random; the purpose of this
    //        exercise is to demonstrate mathematical equivalence
    unsigned int h_len = p*num_channels;
    float h[h_len];
    for (i=0; i<h_len; i++) h[i] = randnf();

    // generate analysis filter
    unsigned int g_len = p*num_channels;
    float g[g_len];
    for (i=0; i<g_len; i++)
        g[i] = h[g_len-i-1];

    // create synthesis/analysis filter objects
    firfilt_crcf fs = firfilt_crcf_create(h, h_len);
    firfilt_crcf fa = firfilt_crcf_create(g, g_len);

    // create synthesis/analysis filterbank channelizer objects
    firpfbch_crcf qs = firpfbch_crcf_create(LIQUID_SYNTHESIZER, num_channels, p, h);
    firpfbch_crcf qa = firpfbch_crcf_create(LIQUID_ANALYZER,    num_channels, p, g);

    float complex x[num_samples];                   // random input (noise)
    float complex Y0[num_symbols][num_channels];    // channelized output (filterbank)
    float complex Y1[num_symbols][num_channels];    // channelized output
    float complex z0[num_samples];                  // time-domain output (filterbank)
    float complex z1[num_samples];                  // time-domain output

    // generate input sequence (complex noise)
    for (i=0; i<num_samples; i++)
        x[i] = randnf() * cexpf(_Complex_I*randf()*2*M_PI);

    // 
    // ANALYZERS
    //
    
    // 
    // run analysis filter bank
    //
    for (i=0; i<num_symbols; i++)
        firpfbch_crcf_analyzer_execute(qa, &x[i*num_channels], &Y0[i][0]);


    // 
    // run traditional down-converter (inefficient)
    //
    float dphi; // carrier frequency
    unsigned int n=0;
    for (i=0; i<num_channels; i++) {

        // reset filter
        firfilt_crcf_clear(fa);

        // set center frequency
        dphi = 2.0f * M_PI * (float)i / (float)num_channels;

        // reset symbol counter
        n=0;

        for (j=0; j<num_samples; j++) {
            // push down-converted sample into filter
            firfilt_crcf_push(fa, x[j]*cexpf(-_Complex_I*j*dphi));

            // compute output at the appropriate sample time
            assert(n<num_symbols);
            if ( ((j+1)%num_channels)==0 ) {
                firfilt_crcf_execute(fa, &Y1[n][i]);
                n++;
            }
        }
        assert(n==num_symbols);

    }


    // 
    // SYNTHESIZERS
    //

    // 
    // run synthesis filter bank
    //
    for (i=0; i<num_symbols; i++)
        firpfbch_crcf_synthesizer_execute(qs, &Y0[i][0], &z0[i*num_channels]);

    // 
    // run traditional up-converter (inefficient)
    //

    // clear output array
    for (i=0; i<num_samples; i++)
        z1[i] = 0.0f;

    float complex y_hat;
    for (i=0; i<num_channels; i++) {
        // reset filter
        firfilt_crcf_clear(fs);

        // set center frequency
        dphi = 2.0f * M_PI * (float)i / (float)num_channels;

        // reset input symbol counter
        n=0;

        for (j=0; j<num_samples; j++) {

            // interpolate sequence
            if ( (j%num_channels)==0 ) {
                assert(n<num_symbols);
                firfilt_crcf_push(fs, Y1[n][i]);
                n++;
            } else {
                firfilt_crcf_push(fs, 0);
            }
            firfilt_crcf_execute(fs, &y_hat);

            // accumulate up-converted sample
            z1[j] += y_hat * cexpf(_Complex_I*j*dphi);
        }
        assert(n==num_symbols);
    }

    // destroy objects
    firfilt_crcf_destroy(fs);
    firfilt_crcf_destroy(fa);
    firpfbch_crcf_destroy(qs);
    firpfbch_crcf_destroy(qa);


    //
    // RESULTS
    //

    // 
    // analyzers
    //

    // print filterbank channelizer
    printf("\n");
    printf("filterbank channelizer:\n");
    for (i=0; i<num_symbols; i++) {
        printf("%3u: ", i);
        for (j=0; j<num_channels; j++) {
            printf("  %8.5f+j%8.5f, ", crealf(Y0[i][j]), cimagf(Y0[i][j]));
        }
        printf("\n");
    }

    // print traditional channelizer
    printf("\n");
    printf("traditional channelizer:\n");
    for (i=0; i<num_symbols; i++) {
        printf("%3u: ", i);
        for (j=0; j<num_channels; j++) {
            printf("  %8.5f+j%8.5f, ", crealf(Y1[i][j]), cimagf(Y1[i][j]));
        }
        printf("\n");
    }


    float mse_analyzer[num_channels];
    float complex d;
    for (i=0; i<num_channels; i++) {
        mse_analyzer[i] = 0.0f;
        for (j=0; j<num_symbols; j++) {
            d = Y0[j][i] - Y1[j][i];
            mse_analyzer[i] += crealf(d*conjf(d));
        }

        mse_analyzer[i] /= num_symbols;
    }
    printf("\n");
    printf("rmse: ");
    for (i=0; i<num_channels; i++)
        printf("%12.4e          ", sqrt(mse_analyzer[i]));
    printf("\n");


    // 
    // synthesizers
    //

    printf("\n");
    printf("output: filterbank:             traditional:\n");
    for (i=0; i<num_samples; i++) {
        printf("%3u: %10.5f+%10.5fj  %10.5f+%10.5fj\n",
            i,
            crealf(z0[i]), cimagf(z0[i]),
            crealf(z1[i]), cimagf(z1[i]));
    }

    float mse_synthesizer = 0.0f;
    for (i=0; i<num_samples; i++) {
        d = z0[i] - z1[i];
        mse_synthesizer += crealf(d*conjf(d));
    }
    mse_synthesizer /= num_samples;
    printf("\n");
    printf("rmse: %12.4e\n", sqrtf(mse_synthesizer));

    //
    // EXPORT DATA TO FILE
    //

    FILE * fid = fopen(OUTPUT_FILENAME,"w");
    fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME);
    fprintf(fid,"clear all;\n");
    fprintf(fid,"close all;\n");
    fprintf(fid,"num_channels=%u;\n", num_channels);
    fprintf(fid,"num_symbols=%u;\n", num_symbols);
    fprintf(fid,"num_samples = num_channels*num_symbols;\n");

    fprintf(fid,"x  = zeros(1,num_samples);\n");
    fprintf(fid,"y0 = zeros(num_symbols,num_channels);\n");
    fprintf(fid,"y1 = zeros(num_symbols,num_channels);\n");
    fprintf(fid,"z0 = zeros(1,num_samples);\n");
    fprintf(fid,"z1 = zeros(1,num_samples);\n");

    // input
    for (i=0; i<num_samples; i++)
        fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(x[i]), cimag(x[i]));

    // analysis
    for (i=0; i<num_symbols; i++) {
        for (j=0; j<num_channels; j++) {
            fprintf(fid,"y0(%4u,%4u) = %12.4e + j*%12.4e;\n", i+1, j+1, crealf(Y0[i][j]), cimag(Y0[i][j]));
            fprintf(fid,"y1(%4u,%4u) = %12.4e + j*%12.4e;\n", i+1, j+1, crealf(Y1[i][j]), cimag(Y1[i][j]));
        }
    }

    // synthesis
    for (i=0; i<num_samples; i++) {
        fprintf(fid,"z0(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(z0[i]), cimag(z0[i]));
        fprintf(fid,"z1(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(z1[i]), cimag(z1[i]));
    }
    fprintf(fid,"z0 = z0 / num_channels;\n");
    fprintf(fid,"z1 = z1 / num_channels;\n");

    // plot results
    fprintf(fid,"\n\n");
    fprintf(fid,"ts = 0:(num_symbols-1);\n");
    fprintf(fid,"for i=1:num_channels,\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"title(['channel ' num2str(i)]);\n");
    fprintf(fid,"subplot(2,1,1);\n");
    fprintf(fid,"    plot(ts,real(y0(:,i)),'-x', ts,real(y1(:,i)),'s');\n");
    //fprintf(fid,"    axis([0 (num_symbols-1) -2 2]);\n");
    fprintf(fid,"subplot(2,1,2);\n");
    fprintf(fid,"    plot(ts,imag(y0(:,i)),'-x', ts,imag(y1(:,i)),'s');\n");
    //fprintf(fid,"    axis([0 (num_symbols-1) -2 2]);\n");
    fprintf(fid,"end;\n");

    fprintf(fid,"t  = 0:(num_samples-1);\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"title('composite');\n");
    fprintf(fid,"subplot(2,1,1);\n");
    fprintf(fid,"    plot(t,real(z0),'-x', t,real(z1),'s');\n");
    fprintf(fid,"subplot(2,1,2);\n");
    fprintf(fid,"    plot(t,imag(z0),'-x', t,imag(z1),'s');\n");


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

    printf("done.\n");
    return 0;
}
Exemplo n.º 4
0
int main() {
    // options
    unsigned int num_channels=6;    // must be even number
    unsigned int num_symbols=32;    // number of symbols
    unsigned int m=3;               // filter delay (symbols)
    float beta = 0.9f;              // filter excess bandwidth factor
    int ftype = LIQUID_RNYQUIST_ARKAISER;

    // number of frames (compensate for filter delay)
    unsigned int num_frames = num_symbols + 2*m;

    unsigned int num_samples = num_channels * num_frames;

    // create synthesizer/analyzer objects
    firpfbch_crcf cs0 = firpfbch_crcf_create_rnyquist(LIQUID_SYNTHESIZER, num_channels, m, beta, ftype);
    firpfbch_crcf cs1 = firpfbch_crcf_create_rnyquist(LIQUID_SYNTHESIZER, num_channels, m, beta, ftype);

    firpfbch_crcf ca0 = firpfbch_crcf_create_rnyquist(LIQUID_ANALYZER,    num_channels, m, beta, ftype);
    firpfbch_crcf ca1 = firpfbch_crcf_create_rnyquist(LIQUID_ANALYZER,    num_channels, m, beta, ftype);

    FILE*fid = fopen(OUTPUT_FILENAME,"w");
    fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME);
    fprintf(fid,"clear all;\nclose all;\n\n");
    fprintf(fid,"num_channels=%u;\n", num_channels);
    fprintf(fid,"num_symbols=%u;\n", num_symbols);
    fprintf(fid,"num_samples=%u;\n", num_samples);

    fprintf(fid,"X = zeros(%u,%u);\n", num_channels, num_frames);
    fprintf(fid,"y = zeros(1,%u);\n",  num_samples);
    fprintf(fid,"Y = zeros(%u,%u);\n", num_channels, num_frames);

    unsigned int i, j, n=0;
    unsigned int k2 = num_channels/2;
    float complex X[num_channels];  // channelized symbols
    float complex y[num_channels];  // interpolated time-domain samples
    float complex Y[num_channels];  // received symbols

    // temporary buffers
    float complex X0[num_channels];
    float complex X1[num_channels];
    float complex y0[num_channels];
    float complex y1[num_channels];
    float complex y1_prime[num_channels];
    for (i=0; i<num_channels; i++) y1_prime[i] = 0.0f;

    float complex Z0[num_channels];
    float complex Z1[num_channels];
    float complex z0[num_channels];
    float complex z1[num_channels];
    //float complex z0_prime[num_channels];
    //float complex z1_prime[num_channels];
    for (i=0; i<num_channels; i++) z0[i] = 0.0f;
    for (i=0; i<num_channels; i++) z1[i] = 0.0f;

    for (i=0; i<num_frames; i++) {

        // generate frame data (random QPSK symbols)
        for (j=0; j<num_channels; j++) {
            X[j] = (rand()%2 ? 1.0f : -1.0f) +
                   (rand()%2 ? 1.0f : -1.0f)*_Complex_I;
        }

        // execute synthesyzer
        //ofdmoqam_execute(cs, X, y);
        for (j=0; j<num_channels; j+=2) {
            // even channels
            X0[j+0] = crealf(X[j+0]);
            X1[j+0] = cimagf(X[j+0])*_Complex_I;

            // odd channels
            X0[j+1] = cimagf(X[j+1])*_Complex_I;
            X1[j+1] = crealf(X[j+1]);
        }
        /*
        for (j=0; j<num_channels; j++)
            printf("X(%3u)  = %12.8f + j*%12.8f\n", j, crealf(X[j]), cimagf(X[j]));
        printf("\n");
        for (j=0; j<num_channels; j++)
            printf("X0(%3u) = %12.8f + j*%12.8f\n", j, crealf(X0[j]), cimagf(X0[j]));
        printf("\n");
        */
        firpfbch_crcf_synthesizer_execute(cs0, X0, y0);
        firpfbch_crcf_synthesizer_execute(cs1, X1, y1);
        // delay lower branch by half a symbol:
        // copy first half of symbol from lower branch
        memmove(&y1_prime[k2], &y1[0], k2*sizeof(float complex));
        // add symbols
        for (j=0; j<num_channels; j++)
            y[j] = y0[j] + y1_prime[j];
        // finish delay
        // copy last half of symbol from lower branch
        memmove(&y1_prime[0], &y1[k2], k2*sizeof(float complex));

        // channel

        // execute analyzer
        //ofdmoqam_execute(ca, y, Y);
        // delay lower branch by half a symbol
        // copy first half of symbol to lower branch
        memmove(&z1[k2], &y[0], k2*sizeof(float complex));
        // run analyzer
        firpfbch_crcf_analyzer_execute(ca0, z0, Z0);
        firpfbch_crcf_analyzer_execute(ca1, z1, Z1);
        // finish delay
        // copy last half of symbol to lower branch
        memmove(&z1[0], &y[k2], k2*sizeof(float complex));
        // copy full symbol on upper branch
        memmove(z0,y,num_channels*sizeof(float complex));
        for (j=0; j<num_channels; j+=2) {
            // even channels
            Y[j+0] = crealf(Z0[j+0]) + cimagf(Z1[j+0])*_Complex_I;

            // odd channels
            Y[j+1] = cimagf(Z0[j+1])*_Complex_I + crealf(Z1[j+1]);
        }

        // write output to file
        for (j=0; j<num_channels; j++) {
            // frequency data
            fprintf(fid,"X(%4u,%4u) = %12.4e + j*%12.4e;\n", j+1, i+1, crealf(X[j]), cimagf(X[j]));

            // time data
            fprintf(fid,"y(%4u) = %12.4e + j*%12.4e;\n", n+1, crealf(y[j]), cimag(y[j]));

            // received data
            fprintf(fid,"Y(%4u,%4u) = %12.4e + j*%12.4e;\n", j+1, i+1, crealf(Y[j]), cimagf(Y[j]));
            n++;
        }
    }

    // print results
    fprintf(fid,"\n\n");
    fprintf(fid,"s0 =  1:%u;\n", num_symbols);
    fprintf(fid,"s1 = %u:%u;\n", 2*m+1, num_symbols + 2*m);
    fprintf(fid,"Y = Y / num_channels; %% normalize by fft size\n");
    fprintf(fid,"for i=1:min(6,num_channels),\n");
    fprintf(fid,"    figure;\n");
    fprintf(fid,"    subplot(2,1,1);\n");
    fprintf(fid,"    plot(1:num_symbols,real(X(i,s0)),'-x',1:num_symbols,real(Y(i,s1)),'-x');\n");
    fprintf(fid,"    ylabel('Re');\n");
    fprintf(fid,"    title(['channel ' num2str(i-1)]);\n");
    fprintf(fid,"    subplot(2,1,2);\n");
    fprintf(fid,"    plot(1:num_symbols,imag(X(i,s0)),'-x',1:num_symbols,imag(Y(i,s1)),'-x');\n");
    fprintf(fid,"    ylabel('Im');\n");
    fprintf(fid,"    pause(0.2);\n");
    fprintf(fid,"end;\n");

    // plot time-domain output
    fprintf(fid,"\n\n");
    fprintf(fid,"t =  1:num_samples;\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"plot(t,real(y),'-', t,imag(y),'-');\n");
    fprintf(fid,"xlabel('time');\n");
    fprintf(fid,"ylabel('time series');\n");

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

    // destroy objects
    firpfbch_crcf_destroy(cs0);
    firpfbch_crcf_destroy(cs1);
    firpfbch_crcf_destroy(ca0);
    firpfbch_crcf_destroy(ca1);

    printf("done.\n");
    return 0;
}
Exemplo n.º 5
0
int main() {
    // options
    unsigned int num_channels=8;    // number of channels
    unsigned int m=4;               // filter delay
    float As=60;                    // stop-band attenuation
    unsigned int num_frames=25;     // number of frames

    //
    unsigned int i;
    unsigned int k;

    // derived values
    unsigned int num_samples = num_frames * num_channels;

    // data arrays
    float complex x[num_samples];  // time-domain input  [size: num_samples  x 1         ]
    float complex y[num_samples];  // channelized output [size: num_channels x num_frames]

    // initialize input with zeros
    for (i=0; i<num_samples; i++)
        x[i] = 0.0f;

    // generate input signal(s)
    unsigned int num_signals = 4;
    float fc[4] = {0.0f,   0.25f,  0.375f, -0.375f}; // center frequencies
    float bw[4] = {0.035f, 0.035f, 0.035f,  0.035f}; // bandwidths
    unsigned int pulse_len = 137;
    float pulse[pulse_len];
    for (i=0; i<num_signals; i++) {
        // create pulse
        liquid_firdes_kaiser(pulse_len, bw[i], 50.0f, 0.0f, pulse);

        // add pulse to input signal with carrier offset
        for (k=0; k<pulse_len; k++)
            x[k] += pulse[k] * cexpf(_Complex_I*2*M_PI*fc[i]*k) * bw[i];
    }

    // create prototype filter
    unsigned int h_len = 2*num_channels*m + 1;
    float h[h_len];
    liquid_firdes_kaiser(h_len, 0.5f/(float)num_channels, As, 0.0f, h);

#if 0
    // create filterbank channelizer object using internal method for filter
    firpfbch_crcf q = firpfbch_crcf_create_kaiser(LIQUID_ANALYZER, num_channels, m, As);
#else
    // create filterbank channelizer object using external filter coefficients
    firpfbch_crcf q = firpfbch_crcf_create(LIQUID_ANALYZER, num_channels, 2*m, h);
#endif

    // channelize input data
    for (i=0; i<num_frames; i++) {
        // execute analysis filter bank
        firpfbch_crcf_analyzer_execute(q, &x[i*num_channels], &y[i*num_channels]);
    }

    // destroy channelizer object
    firpfbch_crcf_destroy(q);
    
    // 
    // export results to file
    //
    FILE * fid = fopen(OUTPUT_FILENAME,"w");
    fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME);
    fprintf(fid,"clear all;\n");
    fprintf(fid,"close all;\n");
    fprintf(fid,"num_channels = %u;\n", num_channels);
    fprintf(fid,"m            = %u;\n", m);
    fprintf(fid,"num_frames   = %u;\n", num_frames);
    fprintf(fid,"h_len        = 2*num_channels*m+1;\n");
    fprintf(fid,"num_samples  = num_frames*num_channels;\n");

    fprintf(fid,"h = zeros(1,h_len);\n");
    fprintf(fid,"x = zeros(1,num_samples);\n");
    fprintf(fid,"y = zeros(num_channels, num_frames);\n");

    // save prototype filter
    for (i=0; i<h_len; i++)
        fprintf(fid,"  h(%6u) = %12.4e;\n", i+1, h[i]);

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

    // save channelized output signals
    for (i=0; i<num_frames; i++) {
        for (k=0; k<num_channels; k++) {
            float complex v = y[i*num_channels + k];
            fprintf(fid,"  y(%3u,%6u) = %12.4e + 1i*%12.4e;\n", k+1, i+1, crealf(v), cimagf(v));
        }
    }

    // plot results
    fprintf(fid,"\n");
    fprintf(fid,"nfft = 1024;\n"); // TODO: use nextpow2
    fprintf(fid,"f = [0:(nfft-1)]/nfft - 0.5;\n");
    fprintf(fid,"H = 20*log10(abs(fftshift(fft(h/num_channels,nfft))));\n");
    fprintf(fid,"X = 20*log10(abs(fftshift(fft(x,nfft))));\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"subplot(2,1,1);\n");
    fprintf(fid,"  plot(f, H, 'Color', [0 0.5 0.25], 'LineWidth', 2);\n");
    fprintf(fid,"  axis([-0.5 0.5 -100 10]);\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"  xlabel('Normalized Frequency [f/F_s]');\n");
    fprintf(fid,"  ylabel('Prototype Filter PSD');\n");
    fprintf(fid,"subplot(2,1,2);\n");
    fprintf(fid,"  plot(f, X, 'Color', [0 0.25 0.5], 'LineWidth', 2);\n");
    fprintf(fid,"  axis([-0.5 0.5 -100 0]);\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"  xlabel('Normalized Frequency [f/F_s]');\n");
    fprintf(fid,"  ylabel('Input PSD');\n");

    // compute the PSD of each output and plot results on a square grid
    fprintf(fid,"n = ceil(sqrt(num_channels));\n");
    fprintf(fid,"figure;\n");
    fprintf(fid,"for i=1:num_channels,\n");
    fprintf(fid,"  Y = 20*log10(abs(fftshift(fft(y(i,:),nfft))));\n");
    fprintf(fid,"  subplot(n,n,i);\n");
    fprintf(fid,"  plot(f, Y, 'Color', [0.25 0 0.25], 'LineWidth', 1.5);\n");
    fprintf(fid,"  axis([-0.5 0.5 -120 20]);\n");
    fprintf(fid,"  grid on;\n");
    fprintf(fid,"  title(num2str(i-1));\n");
    fprintf(fid,"end;\n");

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

    printf("done.\n");
    return 0;
}
//
// AUTOTEST: validate analysis correctness
//
void autotest_firpfbch_crcf_analysis()
{
    float tol = 1e-4f;              // error tolerance
    unsigned int num_channels=4;    // number of channels
    unsigned int p=5;               // filter length (symbols)
    unsigned int num_symbols=12;    // number of symbols

    // derived values
    unsigned int num_samples = num_channels * num_symbols;

    unsigned int i;
    unsigned int j;

    // generate filter
    // NOTE : these coefficients can be random; the purpose of this
    //        exercise is to demonstrate mathematical equivalence
    unsigned int h_len = p*num_channels;
    float h[h_len];
    for (i=0; i<h_len; i++) h[i] = randnf();

    // create filterbank object
    firpfbch_crcf q = firpfbch_crcf_create(LIQUID_ANALYZER, num_channels, p, h);

    // generate filter object
    firfilt_crcf f = firfilt_crcf_create(h, h_len);

    // allocate memory for arrays
    float complex y[num_samples];                   // time-domain input
    float complex Y0[num_symbols][num_channels];    // channelized output
    float complex Y1[num_symbols][num_channels];    // channelized output

    // generate input sequence (complex noise)
    for (i=0; i<num_samples; i++)
        y[i] = randnf() * cexpf(_Complex_I*randf()*2*M_PI);

    // 
    // run analysis filter bank
    //

    for (i=0; i<num_symbols; i++)
        firpfbch_crcf_analyzer_execute(q, &y[i*num_channels], &Y0[i][0]);


    // 
    // run traditional down-converter (inefficient)
    //

    float dphi; // carrier frequency
    unsigned int n=0;
    for (i=0; i<num_channels; i++) {

        // reset filter
        firfilt_crcf_clear(f);

        // set center frequency
        dphi = 2.0f * M_PI * (float)i / (float)num_channels;

        // reset symbol counter
        n=0;

        for (j=0; j<num_samples; j++) {
            // push down-converted sample into filter
            firfilt_crcf_push(f, y[j]*cexpf(-_Complex_I*j*dphi));

            // compute output at the appropriate sample time
            assert(n<num_symbols);
            if ( ((j+1)%num_channels)==0 ) {
                firfilt_crcf_execute(f, &Y1[n][i]);
                n++;
            }
        }
        assert(n==num_symbols);

    }

    // destroy objects
    firfilt_crcf_destroy(f);
    firpfbch_crcf_destroy(q);

    if (liquid_autotest_verbose) {
        // print filterbank channelizer
        printf("\n");
        printf("filterbank channelizer:\n");
        for (i=0; i<num_symbols; i++) {
            printf("%3u: ", i);
            for (j=0; j<num_channels; j++) {
                printf("  %8.5f+j%8.5f, ", crealf(Y0[i][j]), cimagf(Y0[i][j]));
            }
            printf("\n");
        }

        // print traditional channelizer
        printf("\n");
        printf("traditional channelizer:\n");
        for (i=0; i<num_symbols; i++) {
            printf("%3u: ", i);
            for (j=0; j<num_channels; j++) {
                printf("  %8.5f+j%8.5f, ", crealf(Y1[i][j]), cimagf(Y1[i][j]));
            }
            printf("\n");
        }
    }

    // compare results
    for (i=0; i<num_symbols; i++) {
        for (j=0; j<num_channels; j++) {
            CONTEND_DELTA( crealf(Y0[i][j]), crealf(Y1[i][j]), tol );
            CONTEND_DELTA( cimagf(Y0[i][j]), cimagf(Y1[i][j]), tol );
        }
    }

}