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" ); }