int main(int argc, char *argv[])
{
    // Signal settings.
    double rate = 1e6;
    double freq = 10e3;
    double fc = 150e3;

    // Modulation settings
    double gain = 1;
    double rel_fc = fc / rate;
    double rel_fs = freq / rate;

    boost::shared_ptr<SharedType<double> > fcr(new SharedType<double>(rel_fc));

    // Specific Modulation Settings.
    AmDemod::SideBand sideBand = AmDemod::SideBand::DOUBLE;
    unsigned int constSize = 16;
    int supp_carrier = 1;
    double mod_index = 0.5;

    // Frame size and FFT size.
    size_t N = 2048;
    size_t frameSize = 384;

    /***************************************************************************************************
     *                                      Create stream object                                       *
     **************************************************************************************************/

    // AM Stream function.
    StreamFunction * _streamFunction = new AmFunction(new cosFunction(freq), mod_index, rel_fc, sideBand, supp_carrier);
    //StreamFunction * _streamFunction = new eFunction(freq);
    StreamFunction * _noisyStreamFunction = new AwgnFunction(_streamFunction, 0, 1e6, 1e6);
    // FM Stream Function
    //StreamFunction * _streamFunction = new FmFunction(new cosFunction(freq), mod_index, rel_fc);

    // MPSK Stream Function
    //StreamFunction * _streamFunction = new DigitalFunction(new MPskFunction(constSize), rel_fs, rel_fc);

    // ------------ Create Streamer Object ------------ //
    // UhdMock Object
    boost::scoped_ptr < Streamer > _dataStream(new UhdMock(_noisyStreamFunction, rate, gain, frameSize));
    // UhdRead Object
    //    boost::scoped_ptr < Streamer > _dataStream(new UhdRead(rate, freq, gain, frameSize));

    /***************************************************************************************************
     *                                     Initialize utilities                                        *
     **************************************************************************************************/

    // Get shared buffer
    boost::shared_ptr < SharedBuffer<std::complex<double> > > _buffer(_dataStream->getBuffer());

    // Create fft generator function.
    FFTGenerator _fftGen(_buffer, rate, N);

    AmcClassifier<double, AMC::ModType> * classifier = new AmcZnDecisionTree();
    //classifier->load("test0");
    std::string dir = "/home/jcq/git/Automatic-Modulation-Classification-ELEN4012/train-data/2015-10-12-3";
    ClassifierTrainer ct(classifier,dir);
    ct.train();
    ct.save("test0");
    //AMC::FeatureExtractor _featureExtractor(_buffer, classifier, N, rate);
    AMC::FeatureExtractor _featureExtractor(_buffer, classifier, rate, fcr, N);
    AMC::FeatureExtractor _featureExtractor(_buffer, rate, fcr, bwr,N,1);



    /***************************************************************************************************
     *                                      Initialize GUI Objects                                     *
     **************************************************************************************************/

    // Initialize interface.
    QApplication _app(argc, argv);
    MainWindow _mainWindow(rate, N);
    _mainWindow.show();

    _mainWindow.setData(_fftGen.getFreqVec(), _fftGen.getFftVec());
    _mainWindow.setBuffer(_buffer);
    _mainWindow.setSharedModType(_featureExtractor.getSharedModType());

    /***************************************************************************************************
     *                                          Start threads.                                         *
     **************************************************************************************************/

    _dataStream->startStream();

//    _amcRecv.startDemod();
    _fftGen.startFft();
    _featureExtractor.start(AMC::FeatureExtractor::ExtractionMode::CLASSIFY);

    return _app.exec();
}
int main(int argc, char *argv[])
{
    // Signal settings.
    double rate = 1e6;
    double freq = 10e3;
    double fc = 150e3;

    // Modulation settings
    double gain = 1;
    double rel_fc = fc / rate;
    double rel_fs = freq / rate;

    // Specific Modulation Settings.
    AmDemod::SideBand sideBand = AmDemod::SideBand::DOUBLE;
    unsigned int constSize = 2;
    int supp_carrier = 0;
    double mod_index = 0.5;

    // Frame size and FFT size.
    size_t N = 2048;
    size_t frameSize = 384;

/***************************************************************************************************
 *                                      Create stream object                                       *
 **************************************************************************************************/

    // AM Stream function.
    StreamFunction * _streamFunction = new AmFunction(new cosFunction(freq), mod_index, rel_fc, sideBand, supp_carrier);

    // FM Stream Function
//    StreamFunction * _streamFunction = new FmFunction(new cosFunction(freq), mod_index, rel_fc);

    // MPSK Stream Function
//    StreamFunction * _streamFunction = new DigitalFunction(new MPskFunction(constSize), rel_fs, rel_fc);

    // ------------ Create Streamer Object ------------ //
    // UhdMock Object
    boost::scoped_ptr < Streamer > _dataStream(new UhdMock(_streamFunction, rate, gain, frameSize));
    // UhdRead Object
    //    boost::scoped_ptr < Streamer > _dataStream(new UhdRead(rate, freq, gain, frameSize));

/***************************************************************************************************
 *                                     Initialize utilities                                        *
 **************************************************************************************************/

    // Get shared buffer
    boost::shared_ptr < SharedBuffer<std::complex<double> > > _buffer(_dataStream->getBuffer());
    boost::shared_ptr < SharedType<double> > _fc(_dataStream->getFc());
    boost::shared_ptr < SharedType<double> > _window(_dataStream->getWindow());

    // Create fft generator function.
    FFTGenerator _fftGen(_buffer, rate, N);

    AmcClassifier<double, AMC::ModType> * classifier = new AmcCvDecisionTree();
    AMC::FeatureExtractor _featureExtractor(_buffer, classifier, N, rate);

    boost::shared_ptr < SharedType<AMC::ModType> > _modType(_featureExtractor.getSharedModType());

/***************************************************************************************************
 *                                      Create Demodulator                                         *
 **************************************************************************************************/

    // Create demodulator object.
    AmcRecv _amcRecv(_buffer, N);
    _amcRecv.setFc(_fc);
    _amcRecv.setModType(_modType);

    // Am Demodulator.
    _amcRecv.setDemod(new AmDemod(mod_index, rel_fc, sideBand, supp_carrier));

    // Fm Demodulator.
//    _amcRecv.setDemod(new FmDemod(mod_index, rel_fc));

    // MPSK Demodulator
//    _amcRecv.setDemod(new DigitalDemod(new MPskDemod(constSize), rel_fc));

/***************************************************************************************************
 *                                      Initialize GUI Objects                                     *
 **************************************************************************************************/

    // Initialize interface.
    QApplication _app(argc, argv);
    MainWindow _mainWindow(rate, N);
    _mainWindow.show();

/***************************************************************************************************
 *                                      Share some buffers                                         *
 **************************************************************************************************/
    _fftGen.setFc(_fc);

    _mainWindow.setData(_fftGen.getFreqVec(), _fftGen.getFftVec());
    _mainWindow.setBuffer(_buffer);
    _mainWindow.setSharedModType(_modType);
    _mainWindow.setFc(_fc);
    _mainWindow.setWindow(_window);

/***************************************************************************************************
 *                                          Start threads.                                         *
 **************************************************************************************************/

    _dataStream->startStream();
    _amcRecv.startDemod();
    _fftGen.startFft();
    _featureExtractor.start(AMC::FeatureExtractor::ExtractionMode::CLASSIFY);

    return _app.exec();
}