void
FFTFilter::DetermineSignalProperties( SignalProperties& ioProperties, int inFFTType ) const
{
  int numChannels = Parameter( "FFTInputChannels" )->NumValues(),
      fftWindowLength = static_cast<int>( ioProperties.Elements() * Parameter( "FFTWindowLength" ).InSampleBlocks() );
  if( numChannels > 0 && fftWindowLength == 0 )
    bcierr << "FFTWindowLength must exceed a single sample's duration" << endl;
  double freqRange = ioProperties.SamplingRate() / 2.0;

  switch( inFFTType )
  {
    case eInput:
      break;

    case ePower:
    {
      ioProperties.SetName( "FFT Power Spectrum" )
                  .SetChannels( numChannels )
                  .SetElements( fftWindowLength / 2 + 1 );
      ioProperties.ElementUnit().SetOffset( 0.0 )
                                .SetGain( freqRange / ( ioProperties.Elements() - 1 ) )
                                .SetSymbol( "Hz" );
      double amplitude = ioProperties.ValueUnit().RawMax() - ioProperties.ValueUnit().RawMin();
      ioProperties.ValueUnit().SetRawMin( 0 )
                              .SetRawMax( amplitude * amplitude );
      ioProperties.ElementUnit().SetRawMin( 0 )
                                .SetRawMax( ioProperties.Elements() - 1 );
    } break;

    case eHalfcomplex:
      ioProperties.SetName( "FFT Coefficients" )
                  .SetChannels( numChannels )
                  .SetElements( fftWindowLength );
      ioProperties.ElementUnit().SetRawMin( 0 )
                                .SetRawMax( fftWindowLength - 1 )
                                .SetOffset( 0 )
                                .SetGain( 1 )
                                .SetSymbol( "" );
      break;

    default:
      throw std_logic_error( "Unknown value of FFT type" );
  }
}
void
Normalizer::Preflight( const SignalProperties& Input,
                             SignalProperties& Output ) const
{
  if( Parameter( "NormalizerOffsets" )->NumValues() < Input.Channels() )
    bcierr << "The number of entries in the NormalizerOffsets parameter must match "
           << "the number of input channels"
           << endl;
  if( Parameter( "NormalizerGains" )->NumValues() < Input.Channels() )
    bcierr << "The number of entries in the NormalizerGains parameter must match "
           << "the number of input channels"
           << endl;

  ParamRef Adaptation = Parameter( "Adaptation" );
  if( Adaptation->NumValues() < Input.Channels() )
    bcierr << "The number of entries in the Adaptation parameter must match "
           << "the number of input channels"
           << endl;

  bool adaptation = false;
  for( int channel = 0;
      channel < Input.Channels() && channel < Adaptation->NumValues();
      ++channel )
    adaptation |= ( Adaptation( channel ) != none );

  if( adaptation )
  {
    GenericSignal preflightSignal( Input );

    string UpdateTrigger = Parameter( "UpdateTrigger" );
    if( !UpdateTrigger.empty() )
      Expression( UpdateTrigger ).Evaluate( &preflightSignal );

    ParamRef BufferConditions = Parameter( "BufferConditions" );
    if( BufferConditions->NumColumns() > Input.Channels() )
      bcierr << "The number of columns in the BufferConditions parameter "
             << "may not exceed the number of input channels"
             << endl;

    // Evaluate all expressions to test for validity.
    for( int row = 0; row < BufferConditions->NumRows(); ++row )
      for( int col = 0; col < BufferConditions->NumColumns(); ++col )
        Expression( BufferConditions( row, col ) ).Evaluate( &preflightSignal );

    double bufferSize = Parameter( "BufferLength" ).InSampleBlocks();
    if( bufferSize < 1 )
      bciout << "The BufferLength parameter specifies a zero-sized buffer"
             << endl;
  }
  // Request output signal properties:
  Output = Input;
  // Describe output:
  if( adaptation )
    Output.ValueUnit().SetOffset( 0 ).SetGain( 1 ).SetSymbol( "" )
                      .SetRawMin( -2 ).SetRawMax( 2 );
}
示例#3
0
void
FFTFilter::DetermineSignalProperties( SignalProperties& ioProperties, int inFFTType ) const
{
  int numChannels = Parameter( "FFTInputChannels" )->NumValues(),
      fftWindowLength = Parameter( "SampleBlockSize" )
                        * MeasurementUnits::ReadAsTime( Parameter( "FFTWindowLength" ) );
  if( numChannels > 0 && fftWindowLength == 0 )
    bcierr << "FFTWindowLength must exceed a single sample's duration" << endl;

  switch( inFFTType )
  {
    case eInput:
      break;

    case ePower:
    {
      ioProperties.SetName( "FFT Power Spectrum" )
                  .SetChannels( numChannels )
                  .SetElements( fftWindowLength / 2 + 1 );
      float freqScale = Parameter( "SamplingRate" ) / 2.0 / ioProperties.Elements();
      ioProperties.ElementUnit().SetOffset( freqScale / 2 )
                                .SetGain( freqScale )
                                .SetSymbol( "Hz" );
      float amplitude = ioProperties.ValueUnit().RawMax() - ioProperties.ValueUnit().RawMin();
      ioProperties.ValueUnit().SetRawMin( 0 )
                              .SetRawMax( amplitude * amplitude );
    } break;

    case eHalfcomplex:
      ioProperties.SetName( "FFT Coefficients" )
                  .SetChannels( numChannels )
                  .SetElements( fftWindowLength );
      break;

    default:
      assert( false );
  }
}
示例#4
0
void
ARFilter::Preflight( const SignalProperties& Input,
                           SignalProperties& Output ) const
{
  // Parameter consistency checks.
  float windowLength = MeasurementUnits::ReadAsTime( Parameter( "WindowLength" ) );
  int samplesInWindow = windowLength * Parameter( "SampleBlockSize" );
  if( samplesInWindow < Parameter( "ModelOrder" ) )
    bcierr << "WindowLength parameter must be large enough"
           << " for the number of samples to exceed the model order"
           << endl;

  Output = Input;
  switch( int( Parameter( "OutputType" ) ) )
  {
    case SpectralAmplitude:
    case SpectralPower:
    {
      float firstBinCenter = MeasurementUnits::ReadAsFreq( Parameter( "FirstBinCenter" ) ),
            lastBinCenter = MeasurementUnits::ReadAsFreq( Parameter( "LastBinCenter" ) ),
            binWidth = MeasurementUnits::ReadAsFreq( Parameter( "BinWidth" ) );

      if( firstBinCenter > 0.5 || firstBinCenter < 0
          || lastBinCenter > 0.5 || lastBinCenter < 0 )
        bcierr << "FirstBinCenter and LastBinCenter must be greater zero and"
               << " less than half the sampling rate"
               << endl;
      if( firstBinCenter >= lastBinCenter )
        bcierr << "FirstBinCenter must be less than LastBinCenter" << endl;
      if( binWidth <= 0 )
        bcierr << "BinWidth must be greater zero" << endl;
      else
      {
        int numBins = ::floor( ( lastBinCenter - firstBinCenter + eps ) / binWidth + 1 );
        Output.SetElements( numBins );
      }
      Output.ElementUnit().SetOffset( firstBinCenter / binWidth )
                          .SetGain( binWidth * Parameter( "SamplingRate" ) )
                          .SetSymbol( "Hz" );
      Output.ValueUnit().SetRawMin( 0 );
      float inputAmplitude = Input.ValueUnit().RawMax() - Input.ValueUnit().RawMin(),
            whiteNoisePowerPerBin = inputAmplitude * inputAmplitude / binWidth / 10;
      switch( int( Parameter( "OutputType" ) ) )
      {
        case SpectralAmplitude:
          Output.SetName( "AR Amplitude Spectrum" );
          Output.ValueUnit().SetOffset( 0 )
                            .SetGain( 1e-6 )
                            .SetSymbol( "V/sqrt(Hz)" )
                            .SetRawMax( ::sqrt( whiteNoisePowerPerBin ) );
          break;

        case SpectralPower:
        {
          Output.SetName( "AR Power Spectrum" );
          Output.ValueUnit().SetOffset( 0 )
                            .SetGain( 1 )
                            .SetSymbol( "(muV)^2/Hz" )
                            .SetRawMax( whiteNoisePowerPerBin );
        } break;
      }
    } break;

    case ARCoefficients:
      Output.SetName( "AR Coefficients" );
      Output.SetElements( Parameter( "ModelOrder" ) );
      Output.ElementUnit().SetOffset( 0 )
                          .SetGain( 1 )
                          .SetSymbol( "" );
      Output.ValueUnit().SetOffset( 0 )
                        .SetGain( 1 )
                        .SetSymbol( "" )
                        .SetRawMin( -1 )
                        .SetRawMax( 1 );
      break;

    default:
      bcierr << "Unknown OutputType" << endl;
  }
  Output.ElementUnit().SetRawMin( 0 )
                      .SetRawMax( Output.Elements() - 1 );
}
示例#5
0
void
LinearClassifier::Preflight( const SignalProperties& Input,
                                   SignalProperties& Output ) const
{
  // Determine the classifier matrix format:
  int controlSignalChannels = 0;
  const ParamRef& Classifier = Parameter( "Classifier" );
  if( Classifier->NumColumns() != 4 )
    bcierr << "Classifier parameter must have 4 columns "
           << "(input channel, input element, output channel, weight)"
           << endl;
  else
  {
    for( int row = 0; row < Classifier->NumRows(); ++row )
    {
      if( Classifier( row, 2 ) < 1 )
        bcierr << "Output channels must be positive integers"
               << endl;

      float ch = Input.ChannelIndex( Classifier( row, 0 ) );
      if( ch < 0 )
        bcierr << DescribeEntry( row, 0 )
               << " points to negative input index"
               << endl;
      else if( ::floor( ch ) > Input.Channels() )
        bcierr << "Channel specification in "
               << DescribeEntry( row, 0 )
               << " exceeds number of input channels"
               << endl;
      if( ::fmod( ch, 1.0f ) > 1e-2 )
        bciout << "Channel specification in physical units: "
               << DescribeEntry( row, 0 )
               << " does not exactly meet a single channel"
               << endl;

      float el = Input.ElementIndex( Classifier( row, 1 ) );
      if( el < 0 )
        bcierr << DescribeEntry( row, 1 )
               << " points to negative input index"
               << endl;
      if( ::floor( el ) > Input.Elements() )
        bcierr << "Element (bin) specification in "
               << DescribeEntry( row, 1 )
               << " exceeds number of input elements"
               << endl;
      if( ::fmod( el, 1.0f ) > 1e-2 )
        bciout << "Element (bin) specification in physical units: "
               << DescribeEntry( row, 1 )
               << " does not exactly meet a single element"
               << endl;

      int outputChannel =  Classifier( row, 2 );
      controlSignalChannels = max( controlSignalChannels, outputChannel );
    }
  }
  // Requested output signal properties.
  Output = SignalProperties( controlSignalChannels, 1, Input.Type() );
  // Output description.
  Output.ChannelUnit() = Input.ChannelUnit();
  Output.ValueUnit().SetRawMin( Input.ValueUnit().RawMin() )
                    .SetRawMax( Input.ValueUnit().RawMax() );

  float secsPerBlock = Parameter( "SampleBlockSize" ) / Parameter( "SamplingRate" );
  Output.ElementUnit().SetOffset( 0 ).SetGain( secsPerBlock ).SetSymbol( "s" );
  int visualizationTime = Output.ElementUnit().PhysicalToRaw( "15s" );
  Output.ElementUnit().SetRawMin( 0 ).SetRawMax( visualizationTime - 1 );
}