示例#1
0
void
SpatialFilter::Preflight( const SignalProperties& Input,
                                SignalProperties& Output ) const
{
  // Parameter/Input consistency.
  if( Input.Channels() != Parameter( "SpatialFilter" )->NumColumns() )
    bcierr << "The input signal's number of channels must match "
           << "the number of columns in the SpatialFilter parameter"
           << endl;

  // Output signal description.
  Output = Input;
  Output.SetChannels( 0 ).SetChannels( Parameter( "SpatialFilter" )->NumRows() );
  if( !Parameter( "SpatialFilter" )->RowLabels().IsTrivial() )
    for( int i = 0; i < Parameter( "SpatialFilter" )->NumRows(); ++i )
      Output.ChannelLabels()[ i ] = Parameter( "SpatialFilter" )->RowLabels()[ i ];
}
void
BufferedADC::Preflight( const SignalProperties&,
                        SignalProperties& Output ) const
{
    if( Parameter( "SourceBufferSize" ).InSampleBlocks() < 2 )
        bcierr << "The SourceBufferSize parameter must be greater or"
               << " equal 2 sample blocks."
               << endl;
    State( "SourceTime" );
    State( "Running" );
    mAcquisitionProperties = Output;
    this->OnPreflight( mAcquisitionProperties );
    Output = mAcquisitionProperties;
    int numStateChannels = 0;
    for( int ch = 0; ch < Output.Channels(); ++ch )
    {
        bool isStateChannel = ( *Output.ChannelLabels()[ch].c_str() == StateMark );
        if( numStateChannels && !isStateChannel )
            bcierr_ << "State channels must be located at the end of the channel list";
        else if( isStateChannel )
            ++numStateChannels;
    }
    Output.SetChannels( Output.Channels() - numStateChannels );
}
void
FFTFilter::Initialize( const SignalProperties& Input, const SignalProperties& /*Output*/ )
{
  mFFTOutputSignal = ( eFFTOutputSignal )( int )Parameter( "FFTOutputSignal" );
  mFFTWindowLength = static_cast<int>( Input.Elements() * Parameter( "FFTWindowLength" ).InSampleBlocks() );
  mFFTWindow = ( eFFTWindow )( int )Parameter( "FFTWindow" );

  mFFTInputChannels.clear();

  for( size_t i = 0; i < mVisualizations.size(); ++i )
    mVisualizations[ i ].Send( CfgID::Visible, false );
  mVisualizations.clear();
  mVisualizeFFT = int( Parameter( "VisualizeFFT" ) );
  if( mVisualizeFFT || mFFTOutputSignal == ePower )
  {
    mVisProperties = Input;
    DetermineSignalProperties( mVisProperties, ePower );
    PhysicalUnit elementUnit = mVisProperties.ElementUnit();
    mVisProperties.SetChannels( mVisProperties.Elements() );
    for( int i = 0; i < mVisProperties.Channels(); ++i )
      mVisProperties.ChannelLabels()[i] = elementUnit.RawToPhysical( mVisProperties.Channels() - i - 1 );
    mVisProperties.SetElements( 1 );
    mVisProperties.ElementUnit() = Input.ElementUnit();
    mVisProperties.ElementUnit().SetGain( mVisProperties.ElementUnit().Gain() * Input.Elements() );
    mPowerSpectrum = GenericSignal( mVisProperties );
  }
  for( int i = 0; i < Parameter( "FFTInputChannels" )->NumValues(); ++i )
  {
    size_t ch = static_cast<size_t>( Input.ChannelIndex( Parameter( "FFTInputChannels" )( i ) ) );
    mFFTInputChannels.push_back( ch );
    if( mVisualizeFFT )
    {
      ostringstream oss_i;
      oss_i << i + 1;
      mVisualizations.push_back( GenericVisualization( string( "FFT" ) + oss_i.str() ) );

      ostringstream oss_ch;
      oss_ch << "FFT for Ch ";
      if( Input.ChannelLabels().IsTrivial() )
        oss_ch << i + 1;
      else
        oss_ch << Input.ChannelLabels()[ch];

      mVisualizations.back().Send( mVisProperties )
                            .Send( CfgID::WindowTitle, oss_ch.str().c_str() )
                            .Send( CfgID::GraphType, CfgID::Field2d )
                            .Send( CfgID::Visible, true );
    }
  }

  mWindow.clear();
  mWindow.resize( mFFTWindowLength, 1.0 );
  float phasePerSample = static_cast<float>( M_PI ) / static_cast<float>( mFFTWindowLength );
  // Window coefficients: None Hamming Hann Blackman
  const float a1[] = {    0,   0.46f,  0.5f, 0.5f, },
              a2[] = {    0,   0,      0,    0.08f };

  for( int i = 0; i < mFFTWindowLength; ++i )
    mWindow[ i ] = 1.0f - a1[ mFFTWindow ] - a2[ mFFTWindow ]
                   + a1[ mFFTWindow ] * cos( static_cast<float>( i ) * phasePerSample )
                   + a2[ mFFTWindow ] * cos( static_cast<float>( i ) * 2.0f * phasePerSample );

  mValueBuffers.resize( mFFTInputChannels.size() );
  ResetValueBuffers( mFFTWindowLength );

  bool fftRequired = ( mVisualizeFFT || mFFTOutputSignal != eInput)
                     && mFFTInputChannels.size() > 0;
  if( !fftRequired )
    mFFTInputChannels.clear();
  else
    mFFT.Initialize( mFFTWindowLength );
}
void
RDAClientADC::OnPreflight( SignalProperties& Output ) const
{
  // Resource availability and parameter consistency checks.
  RDA::Connection preflightConnection;
  int numSignalChannels = 0,
      numMarkerChannels = 0,
      numOutputChannels = 0;
  preflightConnection.Open( Parameter( "HostName" ) );
  if( preflightConnection )
  {
    const RDA::Info& info = preflightConnection.Info();
    bool goodOffsets = true,
         goodGains   = true;
    numSignalChannels = info.numChannels;
    string matchMessage = " parameter must match the number of channels"
                          " in the recording software";
    if( Parameter( "AddMarkerChannel" ) != 0 )
    {
      numMarkerChannels = 1;
      matchMessage += " plus one marker channel";
    }
    numOutputChannels = numSignalChannels + numMarkerChannels;
    if( Parameter( "SourceCh" ) != numOutputChannels )
      bcierr << "The SourceCh "
             << matchMessage
             << " (" << numOutputChannels << ") ";

    if( Parameter( "SourceChOffset" )->NumValues() != numOutputChannels )
      bcierr << "The number of values in the SourceChOffset"
             << matchMessage
             << " (" << numOutputChannels << ") ";
    else
      for( int i = 0; i < numSignalChannels; ++i )
        goodOffsets &= ( Parameter( "SourceChOffset" )( i ) == 0 );

    if( !goodOffsets )
      bcierr << "The SourceChOffset values for the first "
             << numSignalChannels << " channels "
             << "must be 0";


    if( Parameter( "SourceChGain" )->NumValues() != numOutputChannels )
      bcierr << "The number of values in the SourceChGain"
             << matchMessage
             << " (" << numOutputChannels << ") ";
    else
      for( int i = 0; i < numSignalChannels; ++i )
      {
        double gain = info.channelResolutions[ i ];
        double prmgain = Parameter( "SourceChGain")( i );
        bool same = ( 1e-3 > ::fabs( prmgain - gain ) / ( gain ? gain : 1.0 ) );
        goodGains &= same;

        if ( !same ) bciout << "The RDA server says the gain of"
                            << " channel " << i+1
                            << " is " << gain
                            << " whereas the corresponding value in the"
                            << " SourceChGain parameter is " << prmgain;
      }

    if( !goodGains )
      bcierr << "The SourceChGain values for the first "
             << numSignalChannels << " channels "
             << "must match the channel resolutions settings "
             << "in the recording software";


    if( info.samplingInterval < Limits( info.samplingInterval ).epsilon() )
      bcierr << "The recording software reports an infinite sampling rate "
             << "-- make sure it shows a running signal in its window";
    else
    {
      double sourceSamplingRate = 1e6 / info.samplingInterval;
      if( Parameter( "SamplingRate" ).InHertz() != sourceSamplingRate )
        bcierr << "The SamplingRate parameter must match "
               << "the setting in the recording software "
               << "(" << sourceSamplingRate << ")";

      // Check whether block sizes are sub-optimal.
      int sampleBlockSize = Parameter( "SampleBlockSize" ),
          sourceBlockSize = static_cast<int>( info.blockDuration / info.samplingInterval );
      if( sampleBlockSize % sourceBlockSize != 0 )
        bcierr << "System block size is " << sampleBlockSize << ", must be equal to "
               << "or a multiple of the RDA server's block size, which is " << sourceBlockSize;
    }
  }

  // Requested output signal properties.
#if RDA_FLOAT
  Output = SignalProperties( numOutputChannels + 1, Parameter( "SampleBlockSize" ), SignalType::float32 );
#else
  bciwarn << "You are using the 16 bit variant of the RDA protocol, which is"
          << " considered unreliable. Switching to float is recommended" << endl;
  Output = SignalProperties( numOutputChannels + 1, Parameter( "SampleBlockSize" ), SignalType::int16 );
#endif // RDA_FLOAT
  Output.ChannelLabels()[Output.Channels() - 1] = StateMark + string( "RDAMarkers" );
}