void TuneFilterDecimate_i::configureTFD(BULKIO::StreamSRI &sri) {
	LOG_TRACE(TuneFilterDecimate_i, "Configuring SRI: "
			<< "sri.xdelta = " << sri.xdelta
			<< "sri.streamID = " << sri.streamID)
					Real tmpInputSampleRate = 1 / sri.xdelta; // Calculate sample rate received from SRI
	bool lastInputComplex = inputComplex;
	if (sri.mode==1)
	{
		inputComplex=true;
		chan_if =0.0; //center of band is 0 if we are complex
	}
	else
	{
		inputComplex = false;
		chan_if = tmpInputSampleRate/4.0; //center of band is fs/4 if we are real
		//output is always complex even if input is real
		sri.mode=1;
	}

	DecimationFactor = floor(tmpInputSampleRate/DesiredOutputRate);
	LOG_DEBUG(TuneFilterDecimate_i, "DecimationFactor = " << DecimationFactor);
	if (DecimationFactor <1) {
		LOG_WARN(TuneFilterDecimate_i, "Decimation less than 1, setting to minimum")
						DecimationFactor=1;
	}

	bool sampleRateChanged =(InputRate != tmpInputSampleRate);
	if (sampleRateChanged)
	{
		InputRate = tmpInputSampleRate;
		LOG_DEBUG(TuneFilterDecimate_i, "Sample rate changed: InputRate = " << InputRate);
	}

	// Calculate new output sample rate & modify the referenced SRI structure
	ActualOutputRate = InputRate / DecimationFactor;
	sri.xdelta = 1.0 / ActualOutputRate;
	LOG_DEBUG(TuneFilterDecimate_i, "Output xdelta = " << sri.xdelta
			<< " ActualOutputRate " << ActualOutputRate);

	if (ActualOutputRate < FilterBW)
		LOG_WARN(TuneFilterDecimate_i, "ActualOutputRate " << ActualOutputRate << " is less than FilterBW " << FilterBW);

	// Retrieve the front-end collected RF to determine the IF
	bool validCollectionRF = false;
	bool validChannelRF = false;
	double collection_rf = getKeywordByID<CORBA::Double>(sri, "COL_RF", validCollectionRF);
	double channel_rf = getKeywordByID<CORBA::Double>(sri, "CHAN_RF", validChannelRF);
	double tmpInputRF;
	if ((validCollectionRF) && (validChannelRF)) {
		LOG_WARN(TuneFilterDecimate_i, "Input SRI contains both COL_RF and CHAN_RF, using CHAN_RF");
		tmpInputRF = channel_rf;
	} else if (validCollectionRF) {
		tmpInputRF = collection_rf;
	} else if (validChannelRF) {
		tmpInputRF = channel_rf;
	} else {
		if (TuneMode == "RF") {
			LOG_WARN(TuneFilterDecimate_i, "Input SRI lacks RF keyword.  RF tuning cannot be performed.");
			return;
		}
		tmpInputRF = 0;
	}
	bool inputComplexChanged = lastInputComplex ^ inputComplex;

	if (tmpInputRF != InputRF) {
		LOG_DEBUG(TuneFilterDecimate_i, "Input RF changed " << tmpInputRF);
		InputRF = tmpInputRF;

		// If the TuneMode is RF, we actually need to retune
		if (TuneMode == "RF") {
			configureTuner("TuningRF");
        } else if (TuneMode == "NORM") {
            configureTuner("TuningNorm");
        }
		TuningRF = InputRF + TuningIF - chan_if;
		LOG_DEBUG(TuneFilterDecimate_i, "Tuning RF: " << TuningRF);
	}
	else if (TuneMode == "RF" && inputComplexChanged)
	{
		//the RF didn't change but the IF is changing because we have switched between real and complex data
		configureTuner("TuningRF");
		LOG_DEBUG(TuneFilterDecimate_i, "Tuning RF: " << TuningRF);
	}

	// Add the CHAN_RF keyword to the SRI if we know the input RF
	if (InputRF != 0) {
		if(!setKeywordByID<CORBA::Double>(sri, "CHAN_RF", (double)TuningRF))
			LOG_WARN(TuneFilterDecimate_i, "SRI Keyword CHAN_RF could not be set.");
	}

	// Reconfigure the tuner classes only if the sample rate has changed
	if ((tuner== NULL) || sampleRateChanged) {
		LOG_DEBUG(TuneFilterDecimate_i, "Remaking tuner");

		if (tuner != NULL) {
			delete tuner;
		}

		if (TuneMode == "NORM") {
			configureTuner("TuningNorm");
		} else if (TuneMode == "IF") {
			configureTuner("TuningIF");
		} else if (TuneMode == "RF") {
			configureTuner("TuningRF");
		}

		tuner = new Tuner(tunerInput, f_complexIn, TuningNorm);
	}

	if ((filter==NULL) || sampleRateChanged || RemakeFilter) {
		LOG_DEBUG(TuneFilterDecimate_i, "Remaking filter");

		if((filter != NULL) || (decimate != NULL)) {
			delete filter;
			delete decimate;
		}
/*
 *                    ASCII ART to explain the filter design
 *
 *  Lowpass (Real filter)
 *  ---------|
 *           \
 *            \
 *             \
 *              |
 *  ----------------------------------
 *  0        FL FL+tw   fsOut/2   fsIn/2
 *
 *  The basic gist is we tune first, then filter.
 *  Then we filter
 *  Then we decimate
 *
 *  This means the filter is a LOWPASS filter which must be designed given the INPUT sampling frequency.
 *  The transition frequency happens at 1/2 the requested tune bandwidth.  Thus FL = FilterBW / 2.0.
 *  We need the transition region to "finish" by fsOut/2 to avoid aliasing, so we do a check for that too.
 *
 */
		Real FL = FilterBW / 2.0;

		//calculate the transition frequency necessary to avoid aliasing
		Real maxTW = (ActualOutputRate/2.0)-FL;
		if (maxTW > 0 && maxTW <  filterProps.TransitionWidth)
		{
			LOG_WARN(TuneFilterDecimate_i, "input transition width "<< filterProps.TransitionWidth<<"  too large - replacing with "<< maxTW);
			filterProps.TransitionWidth = maxTW;
		}

		// We generate our FIR filter taps here. The read-only property 'taps' is set.
		// 	- We use the transition width and ripple specified by the user to create the filter taps.
		// 	- Normalized lowpass cutoff frequency is the only one we need; upper cutoff not used
		RealVector tmpVec;
		taps = filterdesigner_.wdfirHz(tmpVec, FIRFilter::lowpass, filterProps.Ripple, filterProps.TransitionWidth,
				FL, 0, InputRate, MIN_NUM_TAPS, MAX_NUM_TAPS);
		filterCoeff.clear();
		filterCoeff.reserve(tmpVec.size());
		for (RealVector::iterator i = tmpVec.begin(); i!=tmpVec.end(); i++)
			filterCoeff.push_back(*i);

		// Minimum FFT_size implemented
		size_t minFftSize = std::max(MIN_FFT_SIZE, pow2ge(2*taps));
		if(filterProps.FFT_size < minFftSize) {
			LOG_DEBUG(TuneFilterDecimate_i, "FFT_size too small, set to " << minFftSize);
			filterProps.FFT_size = minFftSize;
		} else if (filterProps.FFT_size > MAX_FFT_SIZE)
		{
			LOG_DEBUG(TuneFilterDecimate_i, "FFT_size too large, set to " << MAX_FFT_SIZE);
			filterProps.FFT_size = MAX_FFT_SIZE;
		}
		filter = new firfilter(filterProps.FFT_size, f_realOut, f_complexOut, filterCoeff);
		decimate = new Decimate(f_complexOut, decimateOutput, DecimationFactor);
		RemakeFilter = false;	
	}

	LOG_TRACE(TuneFilterDecimate_i, "Exit configureSRI()");
}
Пример #2
0
real CompressedDataColumn::sumColumn(int nRows) {
	RealVector values;
	fill(values, nRows);
	return std::accumulate(values.begin(), values.end(), static_cast<real>(0.0));
}
Пример #3
0
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// devImprovedPeakAlgorithm
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void DevSuite::devImprovedPeakAlgorithm()
{
   Logger msg( "devImprovedPeakAlgorithm" );
   msg << Msg::Info << "Running devImprovedPeakAlgorithm..." << Msg::EndReq;

   // Take fourier bin size = 4096
   // Take sine with phase = 0
   // Make center frequency variable
   // Pick range around center frequency with delta_freq
   // Compute max rel amp as function of freq delta (envelope)
   // First sort by amp, remove all non-increasing frequency entries

   size_t fourierSize = 4096;
   size_t zeroPadSize = 3*fourierSize;

   const RealVector& centreFreqs = realVector( 400 );
   double deltaRange = 100;
   size_t numFreqs = 100;
   const double freqDelta = deltaRange / numFreqs;

   SamplingInfo samplingInfo;
   Synthesizer::SineGenerator sineGen( samplingInfo );

   RealVector relMaxY;
   RealVector diffX;

   for ( size_t iCentreFreq = 0; iCentreFreq < centreFreqs.size(); ++iCentreFreq )
   {
      for ( size_t iFreq = 0; iFreq < numFreqs; ++iFreq )
      {
         double frequency = centreFreqs[ iCentreFreq ] + freqDelta * iFreq;
         sineGen.setFrequency( frequency );
         RawPcmData::Ptr data = sineGen.generate( fourierSize );

         WaveAnalysis::SpectralReassignmentTransform transform( samplingInfo, fourierSize, zeroPadSize, 2 );
         WaveAnalysis::StftData::Ptr stftData = transform.execute( *data );
         const WaveAnalysis::SrSpectrum& spec = stftData->getSrSpectrum( 0 );

         const RealVector& x = spec.getFrequencies();
         RealVector&& y = spec.getMagnitude();

         y /= Utils::getMaxValue( y );
         RealVector deltaX = x - frequency;
         // msg << Msg::Info << deltaX << Msg::EndReq;

         relMaxY.insert( relMaxY.end(), y.begin(), y.end() );
         diffX.insert( diffX.end(), deltaX.begin(), deltaX.end() );
      }
   }

   SortCache relYSc( diffX );
   const RealVector& relMaxYSorted = relYSc.applyTo( relMaxY );
   const RealVector& relDiffXSorted = relYSc.applyTo( diffX );

   Math::Log10Function log10;

   gPlotFactory().createPlot( "envelope" );
   gPlotFactory().createGraph( relDiffXSorted, relMaxYSorted );

   // Create envelope by requiring linear interpolation is always above curve.
   size_t nEnvelopeSamples = 500;

   RealVector linearGrid = Utils::createRangeReal( -1000, 1000, nEnvelopeSamples );
   RealVector zeros = RealVector( nEnvelopeSamples, 0 );

   gPlotFactory().createScatter( linearGrid, zeros, Plotting::MarkerDrawAttr( Qt::red ) );


   gPlotFactory().createPlot( "envelopLog" );
   gPlotFactory().createGraph( relDiffXSorted, log10.evalMany( relMaxYSorted ) );



   // RealVector fCorr = spec.getFrequencyCorrections();
   // for ( size_t i = 0; i < spec.getFrequencies().size(); ++i )
   // {
   //    fCorr[ i ] /= spec.getFrequency( i );
   // }


   // Math::Log10Function log10Fct;

   // gPlotFactory().createPlot( "plot1" );
   // gPlotFactory().createGraph( x, log10Fct.evalMany( y ), Qt::blue );
   // gPlotFactory().createScatter( x, log10Fct.evalMany( y ) );
   // gPlotFactory().createGraph( x, log10Fct.evalMany( fCorr ), Qt::green );
   // gPlotFactory().createScatter( x, log10Fct.evalMany( fCorr ), Plotting::MarkerDrawAttr( Qt::red ) );

   // msg << Msg::Info << "Number of spectra in STFT: " << stftData->getNumSpectra() << Msg::EndReq;
   // for ( size_t iSpec = 0; iSpec < stftData->getNumSpectra(); ++iSpec )
   // {
   //    const WaveAnalysis::WindowLocation* windowLoc = stftData->getSpectrum( iSpec ).getWindowLocation();
   //    msg << Msg::Info << "WindowLocation: [" << windowLoc->getFirstSample() << ", " << windowLoc->getLastSample() << "]" << Msg::EndReq;
   // }



}