This commit is contained in:
2021-10-14 13:47:35 +02:00
commit 6625a8dfaa
4026 changed files with 844291 additions and 0 deletions
@@ -0,0 +1,32 @@
PROJECT(openvibe-plugins-contrib-signal-processing)
SET(PROJECT_VERSION_MAJOR ${OV_GLOBAL_VERSION_MAJOR})
SET(PROJECT_VERSION ${OV_GLOBAL_VERSION_STRING})
FILE(GLOB_RECURSE SRC_FILES src/*.cpp src/*.h src/*.inl)
ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRC_FILES})
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
FOLDER ${PLUGINS_FOLDER}
COMPILE_FLAGS "-DOVP_Exports -DOVP_Shared")
# -----------------------------
INCLUDE("FindOpenViBE")
INCLUDE("FindOpenViBECommon")
INCLUDE("FindOpenViBEToolkit")
INCLUDE("FindOpenViBEModuleEBML")
# INCLUDE("FindThirdPartyBoost")
INCLUDE("FindThirdPartyITPP")
# -----------------------------
# Install files
# -----------------------------
INSTALL(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION ${DIST_BINDIR}
LIBRARY DESTINATION ${DIST_LIBDIR}
ARCHIVE DESTINATION ${DIST_LIBDIR})
INSTALL(DIRECTORY box-tutorials DESTINATION ${DIST_DATADIR}/openvibe/scenarios/)
INSTALL(DIRECTORY metaboxes DESTINATION ${DIST_DATADIR}/openvibe/)
@@ -0,0 +1,790 @@
<OpenViBE-Scenario>
<FormatVersion>1</FormatVersion>
<Creator>OpenVIBE</Creator>
<CreatorVersion>2.0</CreatorVersion>
<Settings></Settings>
<Inputs></Inputs>
<Outputs></Outputs>
<Boxes>
<Box>
<Identifier>(0x000002df, 0x00004ca1)</Identifier>
<Name>Reconstructed</Name>
<AlgorithmClassIdentifier>(0x0055be5f, 0x087bdd12)</AlgorithmClassIdentifier>
<Inputs>
<Input>
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
<Name>Data</Name>
</Input>
<Input>
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
<Name>Stimulations</Name>
</Input>
<Input>
<TypeIdentifier>(0x6ab26b81, 0x0f8c02f3)</TypeIdentifier>
<Name>Channel Units</Name>
</Input>
</Inputs>
<Settings>
<Setting>
<TypeIdentifier>(0x5de046a6, 0x086340aa)</TypeIdentifier>
<Name>Display Mode</Name>
<DefaultValue>Scan</DefaultValue>
<Value>Scan</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x33a30739, 0x00d5299b)</TypeIdentifier>
<Name>Auto vertical scale</Name>
<DefaultValue>Per channel</DefaultValue>
<Value>Per channel</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Scale refresh interval (secs)</Name>
<DefaultValue>5</DefaultValue>
<Value>5</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Vertical Scale</Name>
<DefaultValue>100</DefaultValue>
<Value>100</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Vertical Offset</Name>
<DefaultValue>0</DefaultValue>
<Value>0</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Time Scale</Name>
<DefaultValue>10</DefaultValue>
<Value>10</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
<Name>Horizontal ruler</Name>
<DefaultValue>true</DefaultValue>
<Value>true</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
<Name>Vertical ruler</Name>
<DefaultValue>false</DefaultValue>
<Value>false</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
<Name>Multiview</Name>
<DefaultValue>false</DefaultValue>
<Value>false</Value>
<Modifiability>false</Modifiability>
</Setting>
</Settings>
<Attributes>
<Attribute>
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
<Value>560.000000</Value>
</Attribute>
<Attribute>
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
<Value>800.000000</Value>
</Attribute>
<Attribute>
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
<Value>(0x92c056a7, 0x2dc71aff)</Value>
</Attribute>
<Attribute>
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
<Value></Value>
</Attribute>
<Attribute>
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
<Value>false</Value>
</Attribute>
<Attribute>
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
<Value>9</Value>
</Attribute>
<Attribute>
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
<Value>3</Value>
</Attribute>
</Attributes>
</Box>
<Box>
<Identifier>(0x000005e4, 0x00006597)</Identifier>
<Name>Amplitude</Name>
<AlgorithmClassIdentifier>(0x7b0ddb65, 0xfdc51488)</AlgorithmClassIdentifier>
<Inputs>
<Input>
<TypeIdentifier>(0x1f261c0a, 0x593bf6bd)</TypeIdentifier>
<Name>Matrix</Name>
</Input>
<Input>
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
<Name>Markers</Name>
</Input>
</Inputs>
<Settings>
<Setting>
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
<Name>Channel Localisation</Name>
<DefaultValue>${AdvancedViz_ChannelLocalisation}</DefaultValue>
<Value>${AdvancedViz_ChannelLocalisation}</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x8f02e3f6, 0xffb00f4b)</TypeIdentifier>
<Name>Temporal Coherence</Name>
<DefaultValue>Time Locked</DefaultValue>
<Value>Time Locked</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Time Scale</Name>
<DefaultValue>20</DefaultValue>
<Value>20</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
<Name>Matrix Count</Name>
<DefaultValue>50</DefaultValue>
<Value>50</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Gain</Name>
<DefaultValue>1</DefaultValue>
<Value>0.1</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
<Name>Caption</Name>
<DefaultValue></DefaultValue>
<Value></Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x3d3c7c7f, 0xef0e7129)</TypeIdentifier>
<Name>Color</Name>
<DefaultValue>${AdvancedViz_DefaultColorGradient}</DefaultValue>
<Value>${AdvancedViz_DefaultColorGradient}</Value>
<Modifiability>false</Modifiability>
</Setting>
</Settings>
<Attributes>
<Attribute>
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
<Value>400</Value>
</Attribute>
<Attribute>
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
<Value>560</Value>
</Attribute>
<Attribute>
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
<Value>(0xafb1edd5, 0x68e1da05)</Value>
</Attribute>
<Attribute>
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
<Value></Value>
</Attribute>
<Attribute>
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
<Value>7</Value>
</Attribute>
<Attribute>
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
<Value>2</Value>
</Attribute>
</Attributes>
</Box>
<Box>
<Identifier>(0x000009d1, 0x00005baa)</Identifier>
<Name>Sinus oscillator</Name>
<AlgorithmClassIdentifier>(0x7e33bdb8, 0x68194a4a)</AlgorithmClassIdentifier>
<Outputs>
<Output>
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
<Name>Generated signal</Name>
</Output>
</Outputs>
<Settings>
<Setting>
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
<Name>Channel count</Name>
<DefaultValue>4</DefaultValue>
<Value>1</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
<Name>Sampling frequency</Name>
<DefaultValue>512</DefaultValue>
<Value>256</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
<Name>Generated epoch sample count</Name>
<DefaultValue>32</DefaultValue>
<Value>128</Value>
<Modifiability>false</Modifiability>
</Setting>
</Settings>
<Attributes>
<Attribute>
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
<Value>160.000000</Value>
</Attribute>
<Attribute>
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
<Value>768.000000</Value>
</Attribute>
<Attribute>
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
<Value>(0x0b214ed8, 0x1f9ad83a)</Value>
</Attribute>
<Attribute>
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
<Value>(0x00000000, 0x013a1c38)</Value>
</Attribute>
<Attribute>
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
<Value>false</Value>
</Attribute>
<Attribute>
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
<Value>1</Value>
</Attribute>
<Attribute>
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
<Value>3</Value>
</Attribute>
</Attributes>
</Box>
<Box>
<Identifier>(0x00000d81, 0x00006768)</Identifier>
<Name>IFFT box</Name>
<AlgorithmClassIdentifier>(0xd533e997, 0x4afd2423)</AlgorithmClassIdentifier>
<Inputs>
<Input>
<TypeIdentifier>(0x1f261c0a, 0x593bf6bd)</TypeIdentifier>
<Name>real part</Name>
</Input>
<Input>
<TypeIdentifier>(0x1f261c0a, 0x593bf6bd)</TypeIdentifier>
<Name>imaginary part</Name>
</Input>
</Inputs>
<Outputs>
<Output>
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
<Name>Signal output</Name>
</Output>
</Outputs>
<Attributes>
<Attribute>
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
<Value>464.000000</Value>
</Attribute>
<Attribute>
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
<Value>784.000000</Value>
</Attribute>
<Attribute>
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
<Value>(0x9e5c01e9, 0xe6051e24)</Value>
</Attribute>
<Attribute>
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
<Value>(0x00000000, 0x378ea7ca)</Value>
</Attribute>
<Attribute>
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
<Value>false</Value>
</Attribute>
<Attribute>
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
<Value>1</Value>
</Attribute>
<Attribute>
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
<Value>2</Value>
</Attribute>
</Attributes>
</Box>
<Box>
<Identifier>(0x00002fc6, 0x000073a3)</Identifier>
<Name>Phase</Name>
<AlgorithmClassIdentifier>(0x7b0ddb65, 0xfdc51488)</AlgorithmClassIdentifier>
<Inputs>
<Input>
<TypeIdentifier>(0x1f261c0a, 0x593bf6bd)</TypeIdentifier>
<Name>Matrix</Name>
</Input>
<Input>
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
<Name>Markers</Name>
</Input>
</Inputs>
<Settings>
<Setting>
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
<Name>Channel Localisation</Name>
<DefaultValue>${AdvancedViz_ChannelLocalisation}</DefaultValue>
<Value>${AdvancedViz_ChannelLocalisation}</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x8f02e3f6, 0xffb00f4b)</TypeIdentifier>
<Name>Temporal Coherence</Name>
<DefaultValue>Time Locked</DefaultValue>
<Value>Time Locked</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Time Scale</Name>
<DefaultValue>20</DefaultValue>
<Value>20</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
<Name>Matrix Count</Name>
<DefaultValue>50</DefaultValue>
<Value>50</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Gain</Name>
<DefaultValue>1</DefaultValue>
<Value>1</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
<Name>Caption</Name>
<DefaultValue></DefaultValue>
<Value></Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x3d3c7c7f, 0xef0e7129)</TypeIdentifier>
<Name>Color</Name>
<DefaultValue>${AdvancedViz_DefaultColorGradient}</DefaultValue>
<Value>${AdvancedViz_DefaultColorGradient}</Value>
<Modifiability>false</Modifiability>
</Setting>
</Settings>
<Attributes>
<Attribute>
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
<Value>400</Value>
</Attribute>
<Attribute>
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
<Value>688</Value>
</Attribute>
<Attribute>
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
<Value>(0xafb1edd5, 0x68e1da05)</Value>
</Attribute>
<Attribute>
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
<Value></Value>
</Attribute>
<Attribute>
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
<Value>7</Value>
</Attribute>
<Attribute>
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
<Value>2</Value>
</Attribute>
</Attributes>
</Box>
<Box>
<Identifier>(0x00004b02, 0x00001fdd)</Identifier>
<Name>Spectral analysis</Name>
<AlgorithmClassIdentifier>(0x84218ff8, 0xa87e7995)</AlgorithmClassIdentifier>
<Inputs>
<Input>
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
<Name>Input signal</Name>
</Input>
</Inputs>
<Outputs>
<Output>
<TypeIdentifier>(0x1f261c0a, 0x593bf6bd)</TypeIdentifier>
<Name>Amplitude</Name>
</Output>
<Output>
<TypeIdentifier>(0x1f261c0a, 0x593bf6bd)</TypeIdentifier>
<Name>Phase</Name>
</Output>
<Output>
<TypeIdentifier>(0x1f261c0a, 0x593bf6bd)</TypeIdentifier>
<Name>Real Part</Name>
</Output>
<Output>
<TypeIdentifier>(0x1f261c0a, 0x593bf6bd)</TypeIdentifier>
<Name>Imag Part</Name>
</Output>
</Outputs>
<Settings>
<Setting>
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
<Name>Amplitude</Name>
<DefaultValue>true</DefaultValue>
<Value>true</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
<Name>Phase</Name>
<DefaultValue>false</DefaultValue>
<Value>true</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
<Name>Real Part</Name>
<DefaultValue>false</DefaultValue>
<Value>true</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
<Name>Imaginary Part</Name>
<DefaultValue>false</DefaultValue>
<Value>true</Value>
<Modifiability>false</Modifiability>
</Setting>
</Settings>
<Attributes>
<Attribute>
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
<Value>256.000000</Value>
</Attribute>
<Attribute>
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
<Value>768.000000</Value>
</Attribute>
<Attribute>
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
<Value>(0x4e5c55a0, 0xe69eb7db)</Value>
</Attribute>
<Attribute>
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
<Value>(0x00000000, 0x3a916194)</Value>
</Attribute>
<Attribute>
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
<Value>false</Value>
</Attribute>
<Attribute>
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
<Value>4</Value>
</Attribute>
<Attribute>
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
<Value>1</Value>
</Attribute>
<Attribute>
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
<Value>1</Value>
</Attribute>
</Attributes>
</Box>
<Box>
<Identifier>(0x000051d7, 0x00000db5)</Identifier>
<Name>Original</Name>
<AlgorithmClassIdentifier>(0x0055be5f, 0x087bdd12)</AlgorithmClassIdentifier>
<Inputs>
<Input>
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
<Name>Data</Name>
</Input>
<Input>
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
<Name>Stimulations</Name>
</Input>
<Input>
<TypeIdentifier>(0x6ab26b81, 0x0f8c02f3)</TypeIdentifier>
<Name>Channel Units</Name>
</Input>
</Inputs>
<Settings>
<Setting>
<TypeIdentifier>(0x5de046a6, 0x086340aa)</TypeIdentifier>
<Name>Display Mode</Name>
<DefaultValue>Scan</DefaultValue>
<Value>Scan</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x33a30739, 0x00d5299b)</TypeIdentifier>
<Name>Auto vertical scale</Name>
<DefaultValue>Per channel</DefaultValue>
<Value>Per channel</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Scale refresh interval (secs)</Name>
<DefaultValue>5</DefaultValue>
<Value>5</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Vertical Scale</Name>
<DefaultValue>100</DefaultValue>
<Value>100</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Vertical Offset</Name>
<DefaultValue>0</DefaultValue>
<Value>0</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Time Scale</Name>
<DefaultValue>10</DefaultValue>
<Value>10</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
<Name>Horizontal ruler</Name>
<DefaultValue>true</DefaultValue>
<Value>true</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
<Name>Vertical ruler</Name>
<DefaultValue>false</DefaultValue>
<Value>false</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
<Name>Multiview</Name>
<DefaultValue>false</DefaultValue>
<Value>false</Value>
<Modifiability>false</Modifiability>
</Setting>
</Settings>
<Attributes>
<Attribute>
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
<Value>256.000000</Value>
</Attribute>
<Attribute>
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
<Value>576.000000</Value>
</Attribute>
<Attribute>
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
<Value>(0x92c056a7, 0x2dc71aff)</Value>
</Attribute>
<Attribute>
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
<Value></Value>
</Attribute>
<Attribute>
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
<Value>false</Value>
</Attribute>
<Attribute>
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
<Value>9</Value>
</Attribute>
<Attribute>
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
<Value>3</Value>
</Attribute>
</Attributes>
</Box>
</Boxes>
<Links>
<Link>
<Identifier>(0x000011ae, 0x00002344)</Identifier>
<Source>
<BoxIdentifier>(0x00004b02, 0x00001fdd)</BoxIdentifier>
<BoxOutputIndex>1</BoxOutputIndex>
</Source>
<Target>
<BoxIdentifier>(0x00002fc6, 0x000073a3)</BoxIdentifier>
<BoxInputIndex>0</BoxInputIndex>
</Target>
</Link>
<Link>
<Identifier>(0x00002717, 0x00002653)</Identifier>
<Source>
<BoxIdentifier>(0x00004b02, 0x00001fdd)</BoxIdentifier>
<BoxOutputIndex>2</BoxOutputIndex>
</Source>
<Target>
<BoxIdentifier>(0x00000d81, 0x00006768)</BoxIdentifier>
<BoxInputIndex>0</BoxInputIndex>
</Target>
</Link>
<Link>
<Identifier>(0x00003b98, 0x00007502)</Identifier>
<Source>
<BoxIdentifier>(0x00004b02, 0x00001fdd)</BoxIdentifier>
<BoxOutputIndex>3</BoxOutputIndex>
</Source>
<Target>
<BoxIdentifier>(0x00000d81, 0x00006768)</BoxIdentifier>
<BoxInputIndex>1</BoxInputIndex>
</Target>
</Link>
<Link>
<Identifier>(0x0000501d, 0x0000052c)</Identifier>
<Source>
<BoxIdentifier>(0x000009d1, 0x00005baa)</BoxIdentifier>
<BoxOutputIndex>0</BoxOutputIndex>
</Source>
<Target>
<BoxIdentifier>(0x00004b02, 0x00001fdd)</BoxIdentifier>
<BoxInputIndex>0</BoxInputIndex>
</Target>
</Link>
<Link>
<Identifier>(0x000063c7, 0x00005015)</Identifier>
<Source>
<BoxIdentifier>(0x00000d81, 0x00006768)</BoxIdentifier>
<BoxOutputIndex>0</BoxOutputIndex>
</Source>
<Target>
<BoxIdentifier>(0x000002df, 0x00004ca1)</BoxIdentifier>
<BoxInputIndex>0</BoxInputIndex>
</Target>
</Link>
<Link>
<Identifier>(0x0000688a, 0x00001068)</Identifier>
<Source>
<BoxIdentifier>(0x000009d1, 0x00005baa)</BoxIdentifier>
<BoxOutputIndex>0</BoxOutputIndex>
</Source>
<Target>
<BoxIdentifier>(0x000051d7, 0x00000db5)</BoxIdentifier>
<BoxInputIndex>0</BoxInputIndex>
</Target>
</Link>
<Link>
<Identifier>(0x00006c16, 0x00004c37)</Identifier>
<Source>
<BoxIdentifier>(0x00004b02, 0x00001fdd)</BoxIdentifier>
<BoxOutputIndex>0</BoxOutputIndex>
</Source>
<Target>
<BoxIdentifier>(0x000005e4, 0x00006597)</BoxIdentifier>
<BoxInputIndex>0</BoxInputIndex>
</Target>
</Link>
</Links>
<Comments>
<Comment>
<Identifier>(0x00002920, 0x00007fea)</Identifier>
<Text>The reconstructed signal should
equal the original one
</Text>
<Attributes>
<Attribute>
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
<Value>1104.000000</Value>
</Attribute>
<Attribute>
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
<Value>498.000000</Value>
</Attribute>
</Attributes>
</Comment>
<Comment>
<Identifier>(0x00006544, 0x00006793)</Identifier>
<Text>A signal is decomposed by Fast Fourier Transform</Text>
<Attributes>
<Attribute>
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
<Value>1104.000000</Value>
</Attribute>
<Attribute>
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
<Value>256.000000</Value>
</Attribute>
</Attributes>
</Comment>
<Comment>
<Identifier>(0x00006c55, 0x00000be7)</Identifier>
<Text>At this stage the signals are in Fourier space
transmitted in the Spectrum stream format using
one stream for real and one for imaginary part</Text>
<Attributes>
<Attribute>
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
<Value>1104.000000</Value>
</Attribute>
<Attribute>
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
<Value>377.000000</Value>
</Attribute>
</Attributes>
</Comment>
</Comments>
<Metadata>
<Entry>
<Identifier>(0x0000775c, 0x000078ff)</Identifier>
<Type>(0x3bcce5d2, 0x43f2d968)</Type>
<Data>[{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"height":320,"identifier":"(0x00003f5d, 0x000063e0)","name":"Default window","parentIdentifier":"(0xffffffff, 0xffffffff)","type":1,"width":475},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"identifier":"(0x0000498b, 0x00003981)","index":0,"name":"Default tab","parentIdentifier":"(0x00003f5d, 0x000063e0)","type":2},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":2,"dividerPosition":228,"identifier":"(0x00007431, 0x00007d23)","index":0,"maxDividerPosition":275,"name":"Vertical split","parentIdentifier":"(0x0000498b, 0x00003981)","type":4},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":2,"dividerPosition":158,"identifier":"(0x000025c1, 0x00006774)","index":0,"maxDividerPosition":212,"name":"Vertical split","parentIdentifier":"(0x00007431, 0x00007d23)","type":4},{"boxIdentifier":"(0x000002df, 0x00004ca1)","childCount":0,"identifier":"(0x0000293c, 0x000050be)","index":1,"parentIdentifier":"(0x00007431, 0x00007d23)","type":3},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":2,"dividerPosition":69,"identifier":"(0x00007b2e, 0x00005e1f)","index":0,"maxDividerPosition":142,"name":"Vertical split","parentIdentifier":"(0x000025c1, 0x00006774)","type":4},{"boxIdentifier":"(0x00002fc6, 0x000073a3)","childCount":0,"identifier":"(0x00001fb9, 0x00004ce1)","index":1,"parentIdentifier":"(0x000025c1, 0x00006774)","type":3},{"boxIdentifier":"(0x000051d7, 0x00000db5)","childCount":0,"identifier":"(0x00007d91, 0x0000288c)","index":0,"parentIdentifier":"(0x00007b2e, 0x00005e1f)","type":3},{"boxIdentifier":"(0x000005e4, 0x00006597)","childCount":0,"identifier":"(0x00001fb4, 0x0000332d)","index":1,"parentIdentifier":"(0x00007b2e, 0x00005e1f)","type":3}]</Data>
</Entry>
</Metadata>
<Attributes>
<Attribute>
<Identifier>(0x790d75b8, 0x3bb90c33)</Identifier>
<Value>Jussi T. Lindgren / Inria</Value>
</Attribute>
<Attribute>
<Identifier>(0x8c1fc55b, 0x7b433dc2)</Identifier>
<Value>1.0</Value>
</Attribute>
<Attribute>
<Identifier>(0x9f5c4075, 0x4a0d3666)</Identifier>
<Value>FFT Decomposition</Value>
</Attribute>
<Attribute>
<Identifier>(0xf36a1567, 0xd13c53da)</Identifier>
<Value></Value>
</Attribute>
<Attribute>
<Identifier>(0xf6b2e3fa, 0x7bd43926)</Identifier>
<Value></Value>
</Attribute>
<Attribute>
<Identifier>(0xf8034a49, 0x8b3f37cc)</Identifier>
<Value></Value>
</Attribute>
</Attributes>
</OpenViBE-Scenario>
@@ -0,0 +1,93 @@
/**
* \page BoxAlgorithm_CSPSpatialFilterTrainer CSP Spatial Filter Trainer
__________________________________________________________________
Detailed description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_CSPSpatialFilterTrainer_Description|
This box computes spatial filters according to the Common Spatial Pattern algorithm. The goal of the algorithm is to improve the discrimination of two types of signals.
The spatial filters are constructed in a way they maximize the variance for signals of the first condition while at the same time they minimize it for the second condition.
This can be used for discriminating the signals of two commonly used motor-imagery tasks (e.g. left versus right hand movement).
It can also be used for two-class SSVEP experiments or any other experiment where the discriminative information is contained in the variance (or power in a certain band) of the signal conditions.
Please note that this implementation computes a <b>trace normalization</b>.
* |OVP_DocEnd_BoxAlgorithm_CSPSpatialFilterTrainer_Description|
__________________________________________________________________
Inputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_CSPSpatialFilterTrainer_Inputs|
* |OVP_DocEnd_BoxAlgorithm_CSPSpatialFilterTrainer_Inputs|
* |OVP_DocBegin_BoxAlgorithm_CSPSpatialFilterTrainer_Input1|
This stimulus input is needed to indicate the end of a recording session (or end of file). It then triggers the training/computation of the CSP filters.
* |OVP_DocEnd_BoxAlgorithm_CSPSpatialFilterTrainer_Input1|
* |OVP_DocBegin_BoxAlgorithm_CSPSpatialFilterTrainer_Input2|
This input expects epoched data for the first condition (e.g. epochs for left hand motor imagery).
* |OVP_DocEnd_BoxAlgorithm_CSPSpatialFilterTrainer_Input2|
* |OVP_DocBegin_BoxAlgorithm_CSPSpatialFilterTrainer_Input3|
This input expects epoched data for the second condition (e.g. epochs for right hand motor imagery).
* |OVP_DocEnd_BoxAlgorithm_CSPSpatialFilterTrainer_Input3|
__________________________________________________________________
Outputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_CSPSpatialFilterTrainer_Outputs|
* |OVP_DocEnd_BoxAlgorithm_CSPSpatialFilterTrainer_Outputs|
* |OVP_DocBegin_BoxAlgorithm_CSPSpatialFilterTrainer_Output1|
The CSP Trainer outputs the stimulation <b>OVTK_StimulationId_TrainCompleted</b> when the training process was successful. No output is produced if the process failed.
* |OVP_DocEnd_BoxAlgorithm_CSPSpatialFilterTrainer_Output1|
__________________________________________________________________
Settings description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_CSPSpatialFilterTrainer_Settings|
* |OVP_DocEnd_BoxAlgorithm_CSPSpatialFilterTrainer_Settings|
* |OVP_DocBegin_BoxAlgorithm_CSPSpatialFilterTrainer_Setting1|
This should contain the stimulus identifier denoting the end of a recording session or end of file, e.g. OVTK_GDF_End_Of_Session or OVTK_StimulationId_ExperimentStop.
* |OVP_DocEnd_BoxAlgorithm_CSPSpatialFilterTrainer_Setting1|
* |OVP_DocBegin_BoxAlgorithm_CSPSpatialFilterTrainer_Setting2|
This setting contains the path and filename of the configuration file in which the computed spatial filters are saved.
* |OVP_DocEnd_BoxAlgorithm_CSPSpatialFilterTrainer_Setting2|
* |OVP_DocBegin_BoxAlgorithm_CSPSpatialFilterTrainer_Setting3|
Here you need to determine how many spatial filters will be computed (default value is two).
* |OVP_DocEnd_BoxAlgorithm_CSPSpatialFilterTrainer_Setting3|
* |OVP_DocBegin_BoxAlgorithm_CSPSpatialFilterTrainer_Setting4|
If true, the output file will be a box configuration XML. Otherwise it will be a text format matrix.
* |OVP_DocEnd_BoxAlgorithm_CSPSpatialFilterTrainer_Setting4|
__________________________________________________________________
Examples description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_CSPSpatialFilterTrainer_Examples|
Before training the spatial filter you should first filter the data with respect to the desired band (e.g. for motor imagery, certain people display good results in a narrow pass-band of 8-12Hz, others in 8-30Hz).
As in the example scenario below, one could also opt for different pass-bands and compute filters in each of them, finally letting the subsequently trained classifier decide which features are important.
\image html csp_training.png "Example scenario to compute CSP filters"
Once the spatial filters are computed and saved in the configuration file, you will need to load it into the \ref Doc_BoxAlgorithm_SpatialFilter "Spatial Filter" box.
* |OVP_DocEnd_BoxAlgorithm_CSPSpatialFilterTrainer_Examples|
__________________________________________________________________
Miscellaneous description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_CSPSpatialFilterTrainer_Miscellaneous|
For the moment it is only implemented for two classes. Multiple classes can be supported in the future according to an all-versus-one scheme or through joint diagonalization.
* |OVP_DocEnd_BoxAlgorithm_CSPSpatialFilterTrainer_Miscellaneous|
*/
@@ -0,0 +1,91 @@
/**
* \page BoxAlgorithm_Downsampling Downsampling -
__________________________________________________________________
Detailed description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_Downsampling_Description|
*
* NOTE: This box has been deprecated. Please use
* Signal Resampling box instead.
*
* This plugin is used to downsample the input signal. First, a
* low-pass filter is applied to the input signal for anti-aliasing.
* Then, the input signal is downsampled at the new sampling rate.
* This plugin allows the selection of the kind of filter (Butterworth
* or Chebyshev), the new sampling rate and the frequency
* cutoff for the filter.
*
* |OVP_DocEnd_BoxAlgorithm_Downsampling_Description|
__________________________________________________________________
Inputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_Downsampling_Inputs|
* |OVP_DocEnd_BoxAlgorithm_Downsampling_Inputs|
*
* |OVP_DocBegin_BoxAlgorithm_Downsampling_Input1|
* The input signal.
* |OVP_DocEnd_BoxAlgorithm_Downsampling_Input1|
__________________________________________________________________
Outputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_Downsampling_Outputs|
* |OVP_DocEnd_BoxAlgorithm_Downsampling_Outputs|
*
* |OVP_DocBegin_BoxAlgorithm_Downsampling_Output1|
* |OVP_DocEnd_BoxAlgorithm_Downsampling_Output1|
__________________________________________________________________
Settings description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_Downsampling_Settings|
* |OVP_DocEnd_BoxAlgorithm_Downsampling_Settings|
*
* |OVP_DocBegin_BoxAlgorithm_Downsampling_Setting1|
* New sampling rate in Hz chosen to downsample the input signal.
* |OVP_DocEnd_BoxAlgorithm_Downsampling_Setting1|
*
* |OVP_DocBegin_BoxAlgorithm_Downsampling_Setting2|
* Select the frequency cutoff of the low-pass filter as a ratio (1/2,
* 1/3 or 1/4) of the new sampling rate.
* |OVP_DocEnd_BoxAlgorithm_Downsampling_Setting2|
*
* |OVP_DocBegin_BoxAlgorithm_Downsampling_Setting3|
* Select the kind of filter between Butterworth and Chebyshev.
* |OVP_DocEnd_BoxAlgorithm_Downsampling_Setting3|
*
* |OVP_DocBegin_BoxAlgorithm_Downsampling_Setting4|
* Order of the low-pass filter.
* |OVP_DocEnd_BoxAlgorithm_Downsampling_Setting4|
*
* |OVP_DocBegin_BoxAlgorithm_Downsampling_Setting5|
* If Chebyshev filter is selected, PassBand Ripple is a necessary info.
* |OVP_DocEnd_BoxAlgorithm_Downsampling_Setting5|
__________________________________________________________________
Examples description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_Downsampling_Examples|
* Let's consider our input signal sampling rate is 1 kHz.
* If the new selected sampling rate is 200 Hz and the Frequency
* cutoff ratio is 1/4, then a low-pass filter (with frequency
* cutoff equal to 200*1/4 = 50 Hz) is applied before downsampling
* at 200 Hz.
* |OVP_DocEnd_BoxAlgorithm_Downsampling_Examples|
__________________________________________________________________
Miscellaneous description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_Downsampling_Miscellaneous|
* This plugin downsamples the input signal and previously realizes
* an anti-aliasing filtering.
* |OVP_DocEnd_BoxAlgorithm_Downsampling_Miscellaneous|
*/
@@ -0,0 +1,129 @@
/**
* \page BoxAlgorithm_IndependentComponentAnalysisFastICA Independent Component Analysis (FastICA)
__________________________________________________________________
Detailed description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_IndependentComponentAnalysisFastICA_Description|
* This box attempts to find a decomposition of the signal to its
* independent components. The approach is based on the FastICA algorithm.
* |OVP_DocEnd_BoxAlgorithm_IndependentComponentAnalysisFastICA_Description|
__________________________________________________________________
Inputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_IndependentComponentAnalysisFastICA_Inputs|
* |OVP_DocEnd_BoxAlgorithm_IndependentComponentAnalysisFastICA_Inputs|
*
* |OVP_DocBegin_BoxAlgorithm_IndependentComponentAnalysisFastICA_Input1|
* The input signal.
* |OVP_DocEnd_BoxAlgorithm_IndependentComponentAnalysisFastICA_Input1|
__________________________________________________________________
Outputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_IndependentComponentAnalysisFastICA_Outputs|
* |OVP_DocEnd_BoxAlgorithm_IndependentComponentAnalysisFastICA_Outputs|
*
* |OVP_DocBegin_BoxAlgorithm_IndependentComponentAnalysisFastICA_Output1|
* The decomposed signal.
* |OVP_DocEnd_BoxAlgorithm_IndependentComponentAnalysisFastICA_Output1|
__________________________________________________________________
Settings description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_IndependentComponentAnalysisFastICA_Settings|
* |OVP_DocEnd_BoxAlgorithm_IndependentComponentAnalysisFastICA_Settings|
*
* |OVP_DocBegin_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting1|
* Number of independent components to extract (equals PCA dimension reduction)
* |OVP_DocEnd_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting1|
*
* |OVP_DocBegin_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting2|
* Which decomposition is desired?
* |OVP_DocEnd_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting2|
*
* |OVP_DocBegin_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting3|
* How many seconds of sample to collect to estimate the ICA model?
* |OVP_DocEnd_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting3|
*
* |OVP_DocBegin_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting4|
* Decomposition type. Deflation is an approach where each component is
* estimated separately in turns. Symmetric estimation optimizes all
* components at once.
* |OVP_DocEnd_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting4|
*
* |OVP_DocBegin_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting5|
* Maximum number of iterations
* |OVP_DocEnd_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting5|
*
* |OVP_DocBegin_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting6|
* Enable fine tuning?
* |OVP_DocEnd_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting6|
*
* |OVP_DocBegin_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting7|
* Maximum number of iterations for the fine tuning
* |OVP_DocEnd_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting7|
*
* |OVP_DocBegin_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting8|
* Used nonlinearity type
* |OVP_DocEnd_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting8|
*
* |OVP_DocBegin_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting9|
* Mu parameter
* |OVP_DocEnd_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting9|
*
* |OVP_DocBegin_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting10|
* Epsilon parameter
* |OVP_DocEnd_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting10|
*
* |OVP_DocBegin_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting11|
* Filename to save the estimated decomposition matrix W to
* |OVP_DocEnd_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting11|
*
* |OVP_DocBegin_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting12|
* Should the matrix W be saved to a file?
* |OVP_DocEnd_BoxAlgorithm_IndependentComponentAnalysisFastICA_Setting12|
*
* |OVP_DocEnd_BoxAlgorithm_IndependentComponentAnalysisFastICA_Settings|
__________________________________________________________________
Examples description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_IndependentComponentAnalysisFastICA_Examples|
* One use-case of ICA is to attempt to separate the signal of interest from
* nuisance artifacts. For example, supposing that ICA makes a meaningful decomposition
* of your EEG signal, you will see artifacts such as those from eyeblinks more
* clearly segregated to specific output channels instead of contaminating
* all of the channels.
* |OVP_DocEnd_BoxAlgorithm_IndependentComponentAnalysisFastICA_Examples|
__________________________________________________________________
Miscellaneous description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_IndependentComponentAnalysisFastICA_Miscellaneous|
* This plugin applies the FastICA algorithm to the input signal. The box can store the
* estimated decomposition matrix W to a file. This file can then be used later
* in the spatial filter box to apply the decomposition on fresh data.
*
* The box also outputs the decomposed signal, but the decomposition is active only
* after the model has been estimated (after the specified number of samples have been collected).
* If you wish to decompose the whole data, then you can first train the ICA model, save the matrix,
* and then separately apply it to the original data with the spatial filter.
*
* The FastICA algorithm is described in
*
* A. Hyvärinen. "Fast and Robust Fixed-Point Algorithms for Independent Component Analysis", IEEE Transactions on Neural Networks 10(3):626-634, 1999.
*
* The implementation used by the box is from the ITPP toolkit.
*
* |OVP_DocEnd_BoxAlgorithm_IndependentComponentAnalysisFastICA_Miscellaneous|
*/
@@ -0,0 +1,71 @@
/**
* \page BoxAlgorithm_Min_MaxDetection Min/Max detection -
__________________________________________________________________
Detailed description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_Min_MaxDetection_Description|
* This plugin is used to detect the minimum or the maximum value between
* 2 dates. This plugin allows the selection of the minimum or the maximum
* value to detect and the time start and time stop in between you are looking at.
* |OVP_DocEnd_BoxAlgorithm_Min_MaxDetection_Description|
__________________________________________________________________
Inputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_Min_MaxDetection_Inputs|
* |OVP_DocEnd_BoxAlgorithm_Min_MaxDetection_Inputs|
*
* |OVP_DocBegin_BoxAlgorithm_Min_MaxDetection_Input1|
* The input signal.
* |OVP_DocEnd_BoxAlgorithm_Min_MaxDetection_Input1|
__________________________________________________________________
Outputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_Min_MaxDetection_Outputs|
* |OVP_DocEnd_BoxAlgorithm_Min_MaxDetection_Outputs|
*
* |OVP_DocBegin_BoxAlgorithm_Min_MaxDetection_Output1|
* |OVP_DocEnd_BoxAlgorithm_Min_MaxDetection_Output1|
__________________________________________________________________
Settings description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_Min_MaxDetection_Settings|
* |OVP_DocEnd_BoxAlgorithm_Min_MaxDetection_Settings|
*
* |OVP_DocBegin_BoxAlgorithm_Min_MaxDetection_Setting1|
* Select if you want to detect the Min or the Max.
* |OVP_DocEnd_BoxAlgorithm_Min_MaxDetection_Setting1|
*
* |OVP_DocBegin_BoxAlgorithm_Min_MaxDetection_Setting2|
* Starting time the algorithm will search the Min/Max value.
* |OVP_DocEnd_BoxAlgorithm_Min_MaxDetection_Setting2|
*
* |OVP_DocBegin_BoxAlgorithm_Min_MaxDetection_Setting3|
* Ending time the algorithm will search the Min/Max value.
* |OVP_DocEnd_BoxAlgorithm_Min_MaxDetection_Setting3|
__________________________________________________________________
Examples description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_Min_MaxDetection_Examples|
* Let's consider our input signal is an ERP.
* To detect the P300 ERP, select Max value and a Time Window Start equal
* to 250 ms and a Time Window End equal to 450 ms.
* |OVP_DocEnd_BoxAlgorithm_Min_MaxDetection_Examples|
__________________________________________________________________
Miscellaneous description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_Min_MaxDetection_Miscellaneous|
* This plugin detects the minimum or the maximum value in a time window interval.
* |OVP_DocEnd_BoxAlgorithm_Min_MaxDetection_Miscellaneous|
*/
@@ -0,0 +1,86 @@
/**
* \page BoxAlgorithm_ModifiableTemporalFilter Modifiable Temporal filter -
__________________________________________________________________
Detailed description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_ModifiableTemporalFilter_Description|
* This plugin is used to filter the input signal. This plugin allows
* the selection of the kind of filter (Butterworth or Chebyshev),
* the kind of filter (low pass, high pass, band pass, band stop), the low
* or/and the high passband edge and the passband ripple for the Chebyshev filter.
* This box is a duplicate of the Temporal Filter box with all its settings marked as modifiable.
* Each time a setting changes, the box recompute the filter coefficients accordingly.
* |OVP_DocEnd_BoxAlgorithm_ModifiableTemporalFilter_Description|
__________________________________________________________________
Inputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_ModifiableTemporalFilter_Inputs|
* |OVP_DocEnd_BoxAlgorithm_ModifiableTemporalFilter_Inputs|
*
* |OVP_DocBegin_BoxAlgorithm_ModifiableTemporalFilter_Input1|
* The input signal.
* |OVP_DocEnd_BoxAlgorithm_ModifiableTemporalFilter_Input1|
__________________________________________________________________
Outputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_ModifiableTemporalFilter_Outputs|
* |OVP_DocEnd_BoxAlgorithm_ModifiableTemporalFilter_Outputs|
*
* |OVP_DocBegin_BoxAlgorithm_ModifiableTemporalFilter_Output1|
* |OVP_DocEnd_BoxAlgorithm_ModifiableTemporalFilter_Output1|
__________________________________________________________________
Settings description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_ModifiableTemporalFilter_Settings|
* |OVP_DocEnd_BoxAlgorithm_ModifiableTemporalFilter_Settings|
*
* |OVP_DocBegin_BoxAlgorithm_ModifiableTemporalFilter_Setting1|
* Select the name of filter between Butterworth and Chebyshev. Modifiable online.
* |OVP_DocEnd_BoxAlgorithm_ModifiableTemporalFilter_Setting1|
*
* |OVP_DocBegin_BoxAlgorithm_ModifiableTemporalFilter_Setting2|
* Select the kind of filter between Low pass, High pass, Band pass, Band stop. Modifiable online.
* |OVP_DocEnd_BoxAlgorithm_ModifiableTemporalFilter_Setting2|
*
* |OVP_DocBegin_BoxAlgorithm_ModifiableTemporalFilter_Setting3|
* Order of the low-pass filter. Modifiable online.
* |OVP_DocEnd_BoxAlgorithm_ModifiableTemporalFilter_Setting3|
*
* |OVP_DocBegin_BoxAlgorithm_ModifiableTemporalFilter_Setting4|
* Low edge for High pass, Band pass and Band stop filters. Modifiable online.
* |OVP_DocEnd_BoxAlgorithm_ModifiableTemporalFilter_Setting4|
*
* |OVP_DocBegin_BoxAlgorithm_ModifiableTemporalFilter_Setting5|
* High edge for Low pass, Band pass and Band stop filters. Modifiable online.
* |OVP_DocEnd_BoxAlgorithm_ModifiableTemporalFilter_Setting5|
*
* |OVP_DocBegin_BoxAlgorithm_ModifiableTemporalFilter_Setting6|
* If Chebyshev filter is selected, PassBand Ripple is a necessary info. Modifiable online.
* |OVP_DocEnd_BoxAlgorithm_ModifiableTemporalFilter_Setting6|
__________________________________________________________________
Examples description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_ModifiableTemporalFilter_Examples|
* Let's consider our input signal is very noisy (50 Hz).
* To filter this signal, select a Low pass Butterworth filter of 4th
* order and High PassBand Edge equal to 30 Hz for example.
* |OVP_DocEnd_BoxAlgorithm_ModifiableTemporalFilter_Examples|
__________________________________________________________________
Miscellaneous description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_ModifiableTemporalFilter_Miscellaneous|
* This plugin filters the input signal. Several filtering are available.
* |OVP_DocEnd_BoxAlgorithm_ModifiableTemporalFilter_Miscellaneous|
*/
@@ -0,0 +1,75 @@
/**
* \page BoxAlgorithm_SpectralAnalysisFFTINSERMContrib Spectral analysis -
__________________________________________________________________
Detailed description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Description|
The Spectral Analysis box performs spectrum computations on incoming signals and possible outputs include the spectrum amplitude (the power of the signal in a number of frequency bands), as well as its phase, real part and imaginary part. Output computations may be enabled/disabled from the settings dialog box. The analysis is performed using a <b> Fast Fourier Transform </b>.
* |OVP_DocEnd_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Description|
__________________________________________________________________
Inputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Inputs|
* |OVP_DocEnd_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Inputs|
* |OVP_DocBegin_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Input1|
The input signal.
* |OVP_DocEnd_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Input1|
__________________________________________________________________
Outputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Outputs|
* |OVP_DocEnd_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Outputs|
* |OVP_DocBegin_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Output1|
Amplitude of input signal in frequency bands.
* |OVP_DocEnd_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Output1|
* |OVP_DocBegin_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Output2|
Phase of input signal
* |OVP_DocEnd_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Output2|
* |OVP_DocBegin_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Output3|
Real part of input signal
* |OVP_DocEnd_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Output3|
* |OVP_DocBegin_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Output4|
Imaginary part of input signal
* |OVP_DocEnd_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Output4|
__________________________________________________________________
Settings description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Settings|
* |OVP_DocEnd_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Settings|
* |OVP_DocBegin_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Setting1|
* |OVP_DocEnd_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Setting1|
__________________________________________________________________
Examples description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Examples|
Practical example : visualizing the power spectrum of a signal.
Let's use a Signal Oscillator box to generator sinusoidal signals on one channel. Next we add a Spectral Analysis box and connect boxes together. We make sure the 'Amplitude' of the signal is computed by checking the appropriate setting in the settings dialog box (see image below). Finally, we connect the 'Amplitude' output connector of the Spectral Analysis box to the input connector of a Power Spectrum Display box. The player may now be launched to visualize the power spectrum of the signal.
\image html SpectralAnalysisFFTINSERMContrib_online.png "Visualizing the power spectrum of sinusoidal signals."
* |OVP_DocEnd_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Examples|
__________________________________________________________________
Miscellaneous description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Miscellaneous|
* |OVP_DocEnd_BoxAlgorithm_SpectralAnalysisFFTINSERMContrib_Miscellaneous|
*/
@@ -0,0 +1,90 @@
/**
* \page BoxAlgorithm_TemporalFilterINSERMContrib Temporal filter -
__________________________________________________________________
Detailed description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_TemporalFilterINSERMContrib_Description|
* This plugin is used to filter the input signal. This plugin allows
* the selection of the kind of filter (Butterworth or Chebyshev),
* the kind of filter (low pass, high pass, band pass, band stop), the low
* or/and the high passband edge and the passband ripple for the Chebyshev filter.
* |OVP_DocEnd_BoxAlgorithm_TemporalFilterINSERMContrib_Description|
__________________________________________________________________
Inputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_TemporalFilterINSERMContrib_Inputs|
* |OVP_DocEnd_BoxAlgorithm_TemporalFilterINSERMContrib_Inputs|
*
* |OVP_DocBegin_BoxAlgorithm_TemporalFilterINSERMContrib_Input1|
* The input signal.
* |OVP_DocEnd_BoxAlgorithm_TemporalFilterINSERMContrib_Input1|
__________________________________________________________________
Outputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_TemporalFilterINSERMContrib_Outputs|
* |OVP_DocEnd_BoxAlgorithm_TemporalFilterINSERMContrib_Outputs|
*
* |OVP_DocBegin_BoxAlgorithm_TemporalFilterINSERMContrib_Output1|
* |OVP_DocEnd_BoxAlgorithm_TemporalFilterINSERMContrib_Output1|
__________________________________________________________________
Settings description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_TemporalFilterINSERMContrib_Settings|
* |OVP_DocEnd_BoxAlgorithm_TemporalFilterINSERMContrib_Settings|
*
* |OVP_DocBegin_BoxAlgorithm_TemporalFilterINSERMContrib_Setting1|
* Select the name of filter between Butterworth and Chebyshev.
* |OVP_DocEnd_BoxAlgorithm_TemporalFilterINSERMContrib_Setting1|
*
* |OVP_DocBegin_BoxAlgorithm_TemporalFilterINSERMContrib_Setting2|
* Select the kind of filter between Low pass, High pass, Band pass, Band stop.
* |OVP_DocEnd_BoxAlgorithm_TemporalFilterINSERMContrib_Setting2|
*
* |OVP_DocBegin_BoxAlgorithm_TemporalFilterINSERMContrib_Setting3|
* Order of the low-pass filter.
* |OVP_DocEnd_BoxAlgorithm_TemporalFilterINSERMContrib_Setting3|
*
* |OVP_DocBegin_BoxAlgorithm_TemporalFilterINSERMContrib_Setting4|
* Low edge for High pass, Band pass and Band stop filters
* |OVP_DocEnd_BoxAlgorithm_TemporalFilterINSERMContrib_Setting4|
*
* |OVP_DocBegin_BoxAlgorithm_TemporalFilterINSERMContrib_Setting5|
* High edge for Low pass, Band pass and Band stop filters
* |OVP_DocEnd_BoxAlgorithm_TemporalFilterINSERMContrib_Setting5|
*
* |OVP_DocBegin_BoxAlgorithm_TemporalFilterINSERMContrib_Setting6|
* If Chebyshev filter is selected, PassBand Ripple is a necessary info.
* |OVP_DocEnd_BoxAlgorithm_TemporalFilterINSERMContrib_Setting6|
__________________________________________________________________
Examples description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_TemporalFilterINSERMContrib_Examples|
* Let's consider our input signal is very noisy (50 Hz).
* To filter this signal, select a Low pass Butterworth filter of 4th
* order and High PassBand Edge equal to 30 Hz for example.
* |OVP_DocEnd_BoxAlgorithm_TemporalFilterINSERMContrib_Examples|
__________________________________________________________________
Miscellaneous description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_TemporalFilterINSERMContrib_Miscellaneous|
* This plugin filters the input signal. Several filtering are available.
*
* The box is able to use filter orders that are larger than the input chunk
* size. However, with high order filters in general, remember to check that the
* filtered output of the box remains stable and meaningful. If not,
* try decreasing the filter order.
*
* |OVP_DocEnd_BoxAlgorithm_TemporalFilterINSERMContrib_Miscellaneous|
*/
@@ -0,0 +1,143 @@
/**
* \page BoxAlgorithm_UnivariateStatistics Univariate Statistics
__________________________________________________________________
Detailed description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_UnivariateStatistics_Description|
* This plugin computes the mean, variance, range, median, Inter-
* Quantile-Range and Percentile of each incoming sample
* buffer (or chunk) and outputs the resulting signals.
* |OVP_DocEnd_BoxAlgorithm_UnivariateStatistics_Description|
__________________________________________________________________
Inputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_UnivariateStatistics_Inputs|
* |OVP_DocEnd_BoxAlgorithm_UnivariateStatistics_Inputs|
* |OVP_DocBegin_BoxAlgorithm_UnivariateStatistics_Input1|
* The input signal.
* |OVP_DocEnd_BoxAlgorithm_UnivariateStatistics_Input1|
__________________________________________________________________
Outputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_UnivariateStatistics_Outputs|
* |OVP_DocEnd_BoxAlgorithm_UnivariateStatistics_Outputs|
* |OVP_DocBegin_BoxAlgorithm_UnivariateStatistics_Output1|
* Signal containing the averages of the input sample buffers.
* |OVP_DocEnd_BoxAlgorithm_UnivariateStatistics_Output1|
* |OVP_DocBegin_BoxAlgorithm_UnivariateStatistics_Output2|
* Signal containing the variance of the input sample buffers.
* Sample variance is a measure of the spread of or dispersion
* within a set of sample data.
* The sample variance is the sum of the squared deviations
* from their average divided by the number of observations in
* the data set.
* |OVP_DocEnd_BoxAlgorithm_UnivariateStatistics_Output2|
* |OVP_DocBegin_BoxAlgorithm_UnivariateStatistics_Output3|
* Signal containing the range of the input sample buffers.
* The range of a sample (or a data set) is a measure of the
* spread or the dispersion of the observations. It is the
* difference between the largest and the smallest observed
* value of some quantitative characteristic.
* |OVP_DocEnd_BoxAlgorithm_UnivariateStatistics_Output3|
* |OVP_DocBegin_BoxAlgorithm_UnivariateStatistics_Output4|
* Signal containing the median of the input sample buffers.
* The median is the value halfway through the ordered data
* set, below and above which there lies an equal number of
* data values.
* |OVP_DocEnd_BoxAlgorithm_UnivariateStatistics_Output4|
* |OVP_DocBegin_BoxAlgorithm_UnivariateStatistics_Output5|
* Signal containing the Inter-Quantile-Range of the input
* sample buffers.
* The inter-quartile range is a measure of the spread of or
* dispersion within a data set.
* It is calculated by taking the difference between the upper
* and the lower quartiles.
* |OVP_DocEnd_BoxAlgorithm_UnivariateStatistics_Output5|
* |OVP_DocBegin_BoxAlgorithm_UnivariateStatistics_Output6|
* Signal containing the percentile of the input sample buffers.
* Percentiles are values that divide a sample of data into one
* hundred groups containing (as far as possible) equal numbers
* of observations. For example, 30% of the data values lie below
* the 30th percentile.
* |OVP_DocEnd_BoxAlgorithm_UnivariateStatistics_Output6|
__________________________________________________________________
Settings description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_UnivariateStatistics_Settings|
* |OVP_DocEnd_BoxAlgorithm_UnivariateStatistics_Settings|
* |OVP_DocBegin_BoxAlgorithm_UnivariateStatistics_Setting1|
* Mean activation. If the box is checked, the mean is computed
* and the mean output send signal
* |OVP_DocEnd_BoxAlgorithm_UnivariateStatistics_Setting1|
* |OVP_DocBegin_BoxAlgorithm_UnivariateStatistics_Setting2|
* Variance activation. If the box is checked, the variance is computed
* and the variance output send signal
* |OVP_DocEnd_BoxAlgorithm_UnivariateStatistics_Setting2|
* |OVP_DocBegin_BoxAlgorithm_UnivariateStatistics_Setting3|
* Range activation. If the box is checked, the range is computed
* and the range output send signal
* |OVP_DocEnd_BoxAlgorithm_UnivariateStatistics_Setting3|
* |OVP_DocBegin_BoxAlgorithm_UnivariateStatistics_Setting4|
* Median activation. If the box is checked, the median is computed
* and the median output send signal
* |OVP_DocEnd_BoxAlgorithm_UnivariateStatistics_Setting4|
* |OVP_DocBegin_BoxAlgorithm_UnivariateStatistics_Setting5|
* Inter-Quantile-Range (IQR) activation. If the box is checked,
* the IQR is computed and the IQR output send signal
* |OVP_DocEnd_BoxAlgorithm_UnivariateStatistics_Setting5|
* |OVP_DocBegin_BoxAlgorithm_UnivariateStatistics_Setting6|
* Percentile activation. If the box is checked, the percentile
* is computed and the percentile output send signal
* |OVP_DocEnd_BoxAlgorithm_UnivariateStatistics_Setting6|
* |OVP_DocBegin_BoxAlgorithm_UnivariateStatistics_Setting7|
* Percentile value. Change the percentile value for percentile
* signal output
* |OVP_DocEnd_BoxAlgorithm_UnivariateStatistics_Setting7|
__________________________________________________________________
Examples description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_UnivariateStatistics_Examples|
* |OVP_DocEnd_BoxAlgorithm_UnivariateStatistics_Examples|
__________________________________________________________________
Miscellaneous description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_UnivariateStatistics_Miscellaneous|
* The output signal's sample count per channel per buffer is one,
* since a buffer contains the averages (per channel) of the values
* of an input buffer.
* Be careful of Down-sampling effect for signal, the sampling rate
* at output is divided by the number of input samples. This information
* is saved on integer, so this stay true only if division is without
* fractional part (or the subsampling should be a divisor of the number
* of samples)
* http://www.stats.gla.ac.uk/steps/glossary/presenting_data.html
* |OVP_DocEnd_BoxAlgorithm_UnivariateStatistics_Miscellaneous|
*/
@@ -0,0 +1,66 @@
/**
* \page BoxAlgorithm_WindowingINSERMContrib Windowing functions -
__________________________________________________________________
Detailed description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_WindowingINSERMContrib_Description|
* This plugin is used to apply a window to the input signal.
* This plugin allows the selection of the kind of window
* (Hamming, Hanning, Hann, Blackman, Triangular, Square Root).
* |OVP_DocEnd_BoxAlgorithm_WindowingINSERMContrib_Description|
__________________________________________________________________
Inputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_WindowingINSERMContrib_Inputs|
* |OVP_DocEnd_BoxAlgorithm_WindowingINSERMContrib_Inputs|
*
* |OVP_DocBegin_BoxAlgorithm_WindowingINSERMContrib_Input1|
* |OVP_DocEnd_BoxAlgorithm_WindowingINSERMContrib_Input1|
__________________________________________________________________
Outputs description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_WindowingINSERMContrib_Outputs|
* |OVP_DocEnd_BoxAlgorithm_WindowingINSERMContrib_Outputs|
*
* |OVP_DocBegin_BoxAlgorithm_WindowingINSERMContrib_Output1|
* |OVP_DocEnd_BoxAlgorithm_WindowingINSERMContrib_Output1|
__________________________________________________________________
Settings description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_WindowingINSERMContrib_Settings|
* |OVP_DocEnd_BoxAlgorithm_WindowingINSERMContrib_Settings|
*
* |OVP_DocBegin_BoxAlgorithm_WindowingINSERMContrib_Setting1|
* Select the name of window between Hamming, Hanning, Hann,
* Blackman, Triangular and Square Root.
* |OVP_DocEnd_BoxAlgorithm_WindowingINSERMContrib_Setting1|
__________________________________________________________________
Examples description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_WindowingINSERMContrib_Examples|
* Let's consider our input signal.
* To prevent rebound in spectrum analysis due to the square root
* windowing, select a Hanning window for example.
* |OVP_DocEnd_BoxAlgorithm_WindowingINSERMContrib_Examples|
__________________________________________________________________
Miscellaneous description
__________________________________________________________________
* |OVP_DocBegin_BoxAlgorithm_WindowingINSERMContrib_Miscellaneous|
* This plugin applies a window (weighting function) to each of the channels of the
* input signal. Several windows are available. Note that the window is applied
* separately per each chunk and each channel. It does not 'slide' over the streaming data.
* |OVP_DocEnd_BoxAlgorithm_WindowingINSERMContrib_Miscellaneous|
*/
Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

@@ -0,0 +1,675 @@
<OpenViBE-Scenario>
<FormatVersion>2</FormatVersion>
<Creator>OpenViBE Designer</Creator>
<CreatorVersion>2.2.0</CreatorVersion>
<Settings>
<Setting>
<Identifier>(0x53e968eb, 0x121c769a)</Identifier>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Low Cut Frequency</Name>
<DefaultValue>5</DefaultValue>
<Value>5</Value>
</Setting>
<Setting>
<Identifier>(0x8cad39ce, 0xdbca80d0)</Identifier>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>High Cut Frequency</Name>
<DefaultValue>35</DefaultValue>
<Value>35</Value>
</Setting>
<Setting>
<Identifier>(0x454af4a9, 0x3e55e77a)</Identifier>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Epoch Duration</Name>
<DefaultValue>4</DefaultValue>
<Value>4</Value>
</Setting>
<Setting>
<Identifier>(0xbb21ad6d, 0xda6c49a5)</Identifier>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Epoch Offset</Name>
<DefaultValue>0.5</DefaultValue>
<Value>0.5</Value>
</Setting>
<Setting>
<Identifier>(0xc956238b, 0xf31b7a91)</Identifier>
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
<Name>Class 1</Name>
<DefaultValue>OVTK_GDF_Left</DefaultValue>
<Value>OVTK_GDF_Left</Value>
</Setting>
<Setting>
<Identifier>(0xe28ee4db, 0xb8abaac1)</Identifier>
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
<Name>Class 2</Name>
<DefaultValue>OVTK_GDF_Right</DefaultValue>
<Value>OVTK_GDF_Right</Value>
</Setting>
<Setting>
<Identifier>(0x5b25c57b, 0xbcf2329e)</Identifier>
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
<Name>Train Trigger</Name>
<DefaultValue>OVTK_StimulationId_Train</DefaultValue>
<Value>OVTK_StimulationId_Train</Value>
</Setting>
<Setting>
<Identifier>(0x4c8b6ef1, 0xf834b8a0)</Identifier>
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
<Name>Spatial Filter Configuration</Name>
<DefaultValue>${Player_ScenarioDirectory}/scripts/csp-spatial-filter.xml</DefaultValue>
<Value>${Player_ScenarioDirectory}/scripts/csp-spatial-filter.xml</Value>
</Setting>
<Setting>
<Identifier>(0x2ad32f66, 0xd86a0623)</Identifier>
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
<Name>Filter Dimension</Name>
<DefaultValue>6</DefaultValue>
<Value>6</Value>
</Setting>
</Settings>
<Inputs>
<Input>
<Identifier>(0xe02590b0, 0x52f82985)</Identifier>
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
<Name>Input Signal</Name>
<LinkedBoxIdentifier>(0x000016d5, 0x000033f5)</LinkedBoxIdentifier>
<LinkedBoxInputIndex>0</LinkedBoxInputIndex>
</Input>
<Input>
<Identifier>(0x9493bcb8, 0xd8d4848f)</Identifier>
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
<Name>Input Stimulations</Name>
<LinkedBoxIdentifier>(0x00001c84, 0x0000598b)</LinkedBoxIdentifier>
<LinkedBoxInputIndex>0</LinkedBoxInputIndex>
</Input>
</Inputs>
<Outputs>
<Output>
<Identifier>(0xd3d905f7, 0x2b88c1ac)</Identifier>
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
<Name>Train-completed Flag</Name>
<LinkedBoxIdentifier>(0x00005515, 0x00006ba1)</LinkedBoxIdentifier>
<LinkedBoxOutputIndex>0</LinkedBoxOutputIndex>
</Output>
</Outputs>
<Boxes>
<Box>
<Identifier>(0x000016d5, 0x000033f5)</Identifier>
<Name>Temporal Filter</Name>
<AlgorithmClassIdentifier>(0xb4f9d042, 0x9d79f2e5)</AlgorithmClassIdentifier>
<Inputs>
<Input>
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
<Name>Input signal</Name>
</Input>
</Inputs>
<Outputs>
<Output>
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
<Name>Filtered signal</Name>
</Output>
</Outputs>
<Settings>
<Setting>
<TypeIdentifier>(0x2f2c606c, 0x8512ed68)</TypeIdentifier>
<Name>Filter method</Name>
<DefaultValue>Butterworth</DefaultValue>
<Value>Butterworth</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0xfa20178e, 0x4cba62e9)</TypeIdentifier>
<Name>Filter type</Name>
<DefaultValue>Band pass</DefaultValue>
<Value>Band pass</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
<Name>Filter order</Name>
<DefaultValue>4</DefaultValue>
<Value>5</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Low cut frequency (Hz)</Name>
<DefaultValue>29</DefaultValue>
<Value>$var{Low Cut Frequency}</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>High cut frequency (Hz)</Name>
<DefaultValue>40</DefaultValue>
<Value>$var{High Cut Frequency}</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Pass band ripple (dB)</Name>
<DefaultValue>0.5</DefaultValue>
<Value>1</Value>
<Modifiability>false</Modifiability>
</Setting>
</Settings>
<Attributes>
<Attribute>
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
<Value>304</Value>
</Attribute>
<Attribute>
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
<Value>1104</Value>
</Attribute>
<Attribute>
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
<Value>(0x27a4ceec, 0x876d6384)</Value>
</Attribute>
<Attribute>
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
<Value>(0x00000000, 0x002e3671)</Value>
</Attribute>
<Attribute>
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
<Value>1</Value>
</Attribute>
<Attribute>
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
<Value>6</Value>
</Attribute>
<Attribute>
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
<Value>1</Value>
</Attribute>
</Attributes>
</Box>
<Box>
<Identifier>(0x00001aa0, 0x00005f82)</Identifier>
<Name>Class 1</Name>
<AlgorithmClassIdentifier>(0x426163d1, 0x324237b0)</AlgorithmClassIdentifier>
<Inputs>
<Input>
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
<Name>Input signal</Name>
</Input>
<Input>
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
<Name>Input stimulations</Name>
</Input>
</Inputs>
<Outputs>
<Output>
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
<Name>Epoched signal</Name>
</Output>
</Outputs>
<Settings>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Epoch duration (in sec)</Name>
<DefaultValue>1</DefaultValue>
<Value>$var{Epoch Duration}</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Epoch offset (in sec)</Name>
<DefaultValue>0.5</DefaultValue>
<Value>$var{Epoch Offset}</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
<Name>Stimulation to epoch from</Name>
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
<Value>$var{Class 1}</Value>
<Modifiability>false</Modifiability>
</Setting>
</Settings>
<Attributes>
<Attribute>
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
<Value>384</Value>
</Attribute>
<Attribute>
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
<Value>1024</Value>
</Attribute>
<Attribute>
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
<Value>(0xa79941ae, 0x80708445)</Value>
</Attribute>
<Attribute>
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
<Value>1</Value>
</Attribute>
<Attribute>
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
<Value>3</Value>
</Attribute>
<Attribute>
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
<Value>2</Value>
</Attribute>
</Attributes>
</Box>
<Box>
<Identifier>(0x00001aa0, 0x00005f83)</Identifier>
<Name>Class 2</Name>
<AlgorithmClassIdentifier>(0x426163d1, 0x324237b0)</AlgorithmClassIdentifier>
<Inputs>
<Input>
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
<Name>Input signal</Name>
</Input>
<Input>
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
<Name>Input stimulations</Name>
</Input>
</Inputs>
<Outputs>
<Output>
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
<Name>Epoched signal</Name>
</Output>
</Outputs>
<Settings>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Epoch duration (in sec)</Name>
<DefaultValue>1</DefaultValue>
<Value>$var{Epoch Duration}</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
<Name>Epoch offset (in sec)</Name>
<DefaultValue>0.5</DefaultValue>
<Value>$var{Epoch Offset}</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
<Name>Stimulation to epoch from</Name>
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
<Value>$var{Class 2}</Value>
<Modifiability>false</Modifiability>
</Setting>
</Settings>
<Attributes>
<Attribute>
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
<Value>384</Value>
</Attribute>
<Attribute>
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
<Value>1184</Value>
</Attribute>
<Attribute>
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
<Value>(0xa79941ae, 0x80708445)</Value>
</Attribute>
<Attribute>
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
<Value>1</Value>
</Attribute>
<Attribute>
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
<Value>3</Value>
</Attribute>
<Attribute>
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
<Value>2</Value>
</Attribute>
</Attributes>
</Box>
<Box>
<Identifier>(0x00001c84, 0x0000598b)</Identifier>
<Name>Identity</Name>
<AlgorithmClassIdentifier>(0x5dffe431, 0x35215c50)</AlgorithmClassIdentifier>
<Inputs>
<Input>
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
<Name>Input stream</Name>
</Input>
</Inputs>
<Outputs>
<Output>
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
<Name>Output stream</Name>
</Output>
</Outputs>
<Attributes>
<Attribute>
<Identifier>(0x17ee7c08, 0x94c14893)</Identifier>
<Value></Value>
</Attribute>
<Attribute>
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
<Value>304</Value>
</Attribute>
<Attribute>
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
<Value>912</Value>
</Attribute>
<Attribute>
<Identifier>(0x30a4e5c9, 0x83502953)</Identifier>
<Value></Value>
</Attribute>
<Attribute>
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
<Value>(0xa8ffe2a3, 0x27038f03)</Value>
</Attribute>
<Attribute>
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
<Value></Value>
</Attribute>
<Attribute>
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
<Value>1</Value>
</Attribute>
<Attribute>
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
<Value>1</Value>
</Attribute>
<Attribute>
<Identifier>(0xfba64161, 0x65304e21)</Identifier>
<Value></Value>
</Attribute>
</Attributes>
</Box>
<Box>
<Identifier>(0x00001c84, 0x0000598c)</Identifier>
<Name>Identity</Name>
<AlgorithmClassIdentifier>(0x5dffe431, 0x35215c50)</AlgorithmClassIdentifier>
<Inputs>
<Input>
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
<Name>Input stream</Name>
</Input>
</Inputs>
<Outputs>
<Output>
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
<Name>Output stream</Name>
</Output>
</Outputs>
<Attributes>
<Attribute>
<Identifier>(0x17ee7c08, 0x94c14893)</Identifier>
<Value></Value>
</Attribute>
<Attribute>
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
<Value>416</Value>
</Attribute>
<Attribute>
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
<Value>912</Value>
</Attribute>
<Attribute>
<Identifier>(0x30a4e5c9, 0x83502953)</Identifier>
<Value></Value>
</Attribute>
<Attribute>
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
<Value>(0xa8ffe2a3, 0x27038f03)</Value>
</Attribute>
<Attribute>
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
<Value></Value>
</Attribute>
<Attribute>
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
<Value>1</Value>
</Attribute>
<Attribute>
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
<Value>1</Value>
</Attribute>
<Attribute>
<Identifier>(0xfba64161, 0x65304e21)</Identifier>
<Value></Value>
</Attribute>
</Attributes>
</Box>
<Box>
<Identifier>(0x00005515, 0x00006ba1)</Identifier>
<Name>CSP Spatial Filter Trainer</Name>
<AlgorithmClassIdentifier>(0x51db0d64, 0x2109714e)</AlgorithmClassIdentifier>
<Inputs>
<Input>
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
<Name>Stimulations</Name>
</Input>
<Input>
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
<Name>Signal condition 1</Name>
</Input>
<Input>
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
<Name>Signal condition 2</Name>
</Input>
</Inputs>
<Outputs>
<Output>
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
<Name>Train-completed Flag</Name>
</Output>
</Outputs>
<Settings>
<Setting>
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
<Name>Train Trigger</Name>
<DefaultValue>OVTK_GDF_End_Of_Session</DefaultValue>
<Value>OVTK_StimulationId_Train</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
<Name>Spatial filter configuration</Name>
<DefaultValue></DefaultValue>
<Value>$var{Spatial Filter Configuration}</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
<Name>Filter dimension</Name>
<DefaultValue>2</DefaultValue>
<Value>$var{Filter Dimension}</Value>
<Modifiability>false</Modifiability>
</Setting>
<Setting>
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
<Name>Save as box config</Name>
<DefaultValue>true</DefaultValue>
<Value>true</Value>
<Modifiability>false</Modifiability>
</Setting>
</Settings>
<Attributes>
<Attribute>
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
<Value>464</Value>
</Attribute>
<Attribute>
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
<Value>1104</Value>
</Attribute>
<Attribute>
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
<Value>(0x4b49a133, 0x42f38d94)</Value>
</Attribute>
<Attribute>
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
<Value>(0x00000000, 0x002a4d2d)</Value>
</Attribute>
<Attribute>
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
<Value>false</Value>
</Attribute>
<Attribute>
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
<Value>1</Value>
</Attribute>
<Attribute>
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
<Value>4</Value>
</Attribute>
<Attribute>
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
<Value>3</Value>
</Attribute>
</Attributes>
</Box>
</Boxes>
<Links>
<Link>
<Identifier>(0x00000c54, 0x000048d9)</Identifier>
<Source>
<BoxIdentifier>(0x00001aa0, 0x00005f82)</BoxIdentifier>
<BoxOutputIndex>0</BoxOutputIndex>
</Source>
<Target>
<BoxIdentifier>(0x00005515, 0x00006ba1)</BoxIdentifier>
<BoxInputIndex>1</BoxInputIndex>
</Target>
</Link>
<Link>
<Identifier>(0x00000cdf, 0x000029b9)</Identifier>
<Source>
<BoxIdentifier>(0x00001c84, 0x0000598c)</BoxIdentifier>
<BoxOutputIndex>0</BoxOutputIndex>
</Source>
<Target>
<BoxIdentifier>(0x00005515, 0x00006ba1)</BoxIdentifier>
<BoxInputIndex>0</BoxInputIndex>
</Target>
</Link>
<Link>
<Identifier>(0x0000104a, 0x00004869)</Identifier>
<Source>
<BoxIdentifier>(0x00001c84, 0x0000598b)</BoxIdentifier>
<BoxOutputIndex>0</BoxOutputIndex>
</Source>
<Target>
<BoxIdentifier>(0x00001aa0, 0x00005f82)</BoxIdentifier>
<BoxInputIndex>1</BoxInputIndex>
</Target>
</Link>
<Link>
<Identifier>(0x00001135, 0x00003548)</Identifier>
<Source>
<BoxIdentifier>(0x000016d5, 0x000033f5)</BoxIdentifier>
<BoxOutputIndex>0</BoxOutputIndex>
</Source>
<Target>
<BoxIdentifier>(0x00001aa0, 0x00005f83)</BoxIdentifier>
<BoxInputIndex>0</BoxInputIndex>
</Target>
</Link>
<Link>
<Identifier>(0x000015b8, 0x00000ac7)</Identifier>
<Source>
<BoxIdentifier>(0x00001c84, 0x0000598b)</BoxIdentifier>
<BoxOutputIndex>0</BoxOutputIndex>
</Source>
<Target>
<BoxIdentifier>(0x00001aa0, 0x00005f83)</BoxIdentifier>
<BoxInputIndex>1</BoxInputIndex>
</Target>
</Link>
<Link>
<Identifier>(0x00002287, 0x000005db)</Identifier>
<Source>
<BoxIdentifier>(0x000016d5, 0x000033f5)</BoxIdentifier>
<BoxOutputIndex>0</BoxOutputIndex>
</Source>
<Target>
<BoxIdentifier>(0x00001aa0, 0x00005f82)</BoxIdentifier>
<BoxInputIndex>0</BoxInputIndex>
</Target>
</Link>
<Link>
<Identifier>(0x00002d57, 0x00004b2f)</Identifier>
<Source>
<BoxIdentifier>(0x00001c84, 0x0000598b)</BoxIdentifier>
<BoxOutputIndex>0</BoxOutputIndex>
</Source>
<Target>
<BoxIdentifier>(0x00001c84, 0x0000598c)</BoxIdentifier>
<BoxInputIndex>0</BoxInputIndex>
</Target>
</Link>
<Link>
<Identifier>(0x00007d7b, 0x000049f7)</Identifier>
<Source>
<BoxIdentifier>(0x00001aa0, 0x00005f83)</BoxIdentifier>
<BoxOutputIndex>0</BoxOutputIndex>
</Source>
<Target>
<BoxIdentifier>(0x00005515, 0x00006ba1)</BoxIdentifier>
<BoxInputIndex>2</BoxInputIndex>
</Target>
</Link>
</Links>
<Comments></Comments>
<Metadata>
<Entry>
<Identifier>(0x00004fc8, 0x00005801)</Identifier>
<Type>(0x3bcce5d2, 0x43f2d968)</Type>
<Data>[{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"height":320,"identifier":"(0x00006ba8, 0x000061b1)","name":"Default window","parentIdentifier":"(0xffffffff, 0xffffffff)","type":1,"width":480},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"identifier":"(0x000023d0, 0x00003bbe)","index":0,"name":"Default tab","parentIdentifier":"(0x00006ba8, 0x000061b1)","type":2},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":0,"identifier":"(0x0000383b, 0x00001860)","index":0,"name":"Empty","parentIdentifier":"(0x000023d0, 0x00003bbe)","type":0}]</Data>
</Entry>
</Metadata>
<Attributes>
<Attribute>
<Identifier>(0x079d1f09, 0x667c7871)</Identifier>
<Value></Value>
</Attribute>
<Attribute>
<Identifier>(0x198dd621, 0xab7f153f)</Identifier>
<Value>(0x18bc5b7e, 0xe8b6d7da)</Value>
</Attribute>
<Attribute>
<Identifier>(0x20c6d158, 0xfe90aadd)</Identifier>
<Value>(0x05a13f95, 0xdfdc0e8f)</Value>
</Attribute>
<Attribute>
<Identifier>(0x60bc58ab, 0x7a1b4d83)</Identifier>
<Value></Value>
</Attribute>
<Attribute>
<Identifier>(0x790d75b8, 0x3bb90c33)</Identifier>
<Value>Thibaut Monseigne</Value>
</Attribute>
<Attribute>
<Identifier>(0x7a3a1558, 0xf12c63c2)</Identifier>
<Value>Add Temporal Filter (Butterworth Order 5) and separate in two class before Train</Value>
</Attribute>
<Attribute>
<Identifier>(0x84009d7c, 0x3c4e763b)</Identifier>
<Value>Make typical process before train</Value>
</Attribute>
<Attribute>
<Identifier>(0x8c1fc55b, 0x7b433dc2)</Identifier>
<Value>1.0</Value>
</Attribute>
<Attribute>
<Identifier>(0x9f5c4075, 0x4a0d3666)</Identifier>
<Value>CSP Spatial Filter Trainer Metabox</Value>
</Attribute>
<Attribute>
<Identifier>(0xf36a1567, 0xd13c53da)</Identifier>
<Value></Value>
</Attribute>
<Attribute>
<Identifier>(0xf6b2e3fa, 0x7bd43926)</Identifier>
<Value>Signal processing/Filtering/</Value>
</Attribute>
<Attribute>
<Identifier>(0xf8034a49, 0x8b3f37cc)</Identifier>
<Value>Inria</Value>
</Attribute>
</Attributes>
</OpenViBE-Scenario>
@@ -0,0 +1,230 @@
#include "ovpCAlgorithmUnivariateStatistics.h"
#include <algorithm>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
// ________________________________________________________________________________________________________________
//
bool CAlgoUnivariateStatistic::initialize()
{
ip_matrix.initialize(getInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_Matrix));
op_MeanMatrix.initialize(getOutputParameter(OVP_Algorithm_UnivariateStatistic_OutputParameterId_Mean));
op_VarianceMatrix.initialize(getOutputParameter(OVP_Algorithm_UnivariateStatistic_OutputParameterId_Var));
op_RangeMatrix.initialize(getOutputParameter(OVP_Algorithm_UnivariateStatistic_OutputParameterId_Range));
op_MedianMatrix.initialize(getOutputParameter(OVP_Algorithm_UnivariateStatistic_OutputParameterId_Med));
op_IQRMatrix.initialize(getOutputParameter(OVP_Algorithm_UnivariateStatistic_OutputParameterId_IQR));
op_PercentileMatrix.initialize(getOutputParameter(OVP_Algorithm_UnivariateStatistic_OutputParameterId_Percent));
ip_isMeanActive.initialize(this->getInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_MeanActive));
ip_isVarianceActive.initialize(this->getInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_VarActive));
ip_isRangeActive.initialize(this->getInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_RangeActive));
ip_isMedianActive.initialize(this->getInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_MedActive));
ip_isIQRActive.initialize(this->getInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_IQRActive));
ip_isPercentileActive.initialize(this->getInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_PercentActive));
ip_percentileValue.initialize(this->getInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_PercentValue));
op_compression.initialize(this->getOutputParameter(OVP_Algorithm_UnivariateStatistic_OutputParameterId_Compression));
return true;
}
bool CAlgoUnivariateStatistic::uninitialize()
{
op_compression.uninitialize();
ip_percentileValue.uninitialize();
ip_isMeanActive.uninitialize();
ip_isVarianceActive.uninitialize();
ip_isRangeActive.uninitialize();
ip_isMedianActive.uninitialize();
ip_isIQRActive.uninitialize();
ip_isPercentileActive.uninitialize();
op_MeanMatrix.uninitialize();
op_VarianceMatrix.uninitialize();
op_RangeMatrix.uninitialize();
op_MedianMatrix.uninitialize();
op_IQRMatrix.uninitialize();
op_PercentileMatrix.uninitialize();
ip_matrix.uninitialize();
return true;
}
// ________________________________________________________________________________________________________________
//
bool CAlgoUnivariateStatistic::process()
{
CMatrix* matrix = ip_matrix;
CMatrix* mean = op_MeanMatrix;
CMatrix* variance = op_VarianceMatrix;
CMatrix* range = op_RangeMatrix;
CMatrix* median = op_MedianMatrix;
CMatrix* iqr = op_IQRMatrix;
CMatrix* percentile = op_PercentileMatrix;
if (this->isInputTriggerActive(OVP_Algorithm_UnivariateStatistic_InputTriggerId_Initialize))
{
this->getLogManager() << Kernel::LogLevel_Debug << "input : " << matrix->getDimensionCount() << " : " << matrix->getDimensionSize(0) << "*" <<
matrix->getDimensionSize(1) << "\n";
//initialize matrix output
if (!setMatrixDimension(mean, matrix)) { return false; }
if (!setMatrixDimension(variance, matrix)) { return false; }
if (!setMatrixDimension(range, matrix)) { return false; }
if (!setMatrixDimension(median, matrix)) { return false; }
if (!setMatrixDimension(iqr, matrix)) { return false; }
if (!setMatrixDimension(percentile, matrix)) { return false; }
//inform about the compression on sampling rate due to this operation N->1 :=: fq->fq/N
op_compression = 1 / double(matrix->getDimensionSize(1));
//percentile value
m_percentileValue = ip_percentileValue;
//select operation to do (avoid unuseful calculus)
m_isSumActive = ip_isMeanActive || ip_isVarianceActive;
m_isSqaresumActive = ip_isVarianceActive;
m_isSortActive = ip_isRangeActive || ip_isMedianActive || ip_isIQRActive || ip_isPercentileActive;
if (m_isSumActive)
{
m_sumMatrix.copyDescription(*matrix);
m_sumMatrix.setDimensionSize(1, 1);
}
if (m_isSqaresumActive)
{
m_sumMatrix2.copyDescription(*matrix);
m_sumMatrix2.setDimensionSize(1, 1);
}
if (m_isSortActive) { m_sortMatrix.copyDescription(*matrix); }
}
if (this->isInputTriggerActive(OVP_Algorithm_UnivariateStatistic_InputTriggerId_Process))
{
///make necessary operations
//dimension
const double s = double(matrix->getDimensionSize(1));
//sum, sum square, sort
std::vector<double> vect(matrix->getDimensionSize(1));
for (size_t i = 0; i < matrix->getDimensionSize(0); ++i)
{
if (m_isSortActive)
{
//copy fonctionne pas car le buffer n'est pas unidirectionnel...
for (size_t j = 0; j < matrix->getDimensionSize(1); ++j) { vect[j] = matrix->getBuffer()[i * matrix->getDimensionSize(1) + j]; }
std::sort(vect.begin(), vect.end());
}
double y = 0, y2 = 0;
for (size_t j = 0; j < matrix->getDimensionSize(1); ++j)
{
const double x = matrix->getBuffer()[i * matrix->getDimensionSize(1) + j];
if (m_isSumActive) { y += x; }
if (m_isSqaresumActive) { y2 += x * x; }
if (m_isSortActive) { m_sortMatrix.getBuffer()[i * m_sortMatrix.getDimensionSize(1) + j] = vect.at(j); }
}
if (m_isSumActive) { m_sumMatrix.getBuffer()[i * m_sumMatrix.getDimensionSize(1)] = y; }
if (m_isSqaresumActive) { m_sumMatrix2.getBuffer()[i * m_sumMatrix2.getDimensionSize(1)] = y2; }
}
///make statistics operations...
if (ip_isMeanActive)
{
for (size_t i = 0; i < mean->getDimensionSize(0); ++i)
{
mean->getBuffer()[i * mean->getDimensionSize(1)] = m_sumMatrix.getBuffer()[i * m_sumMatrix.getDimensionSize(1)] / matrix->getDimensionSize(1);
}
}
if (ip_isVarianceActive)
{
for (size_t i = 0; i < variance->getDimensionSize(0); ++i)
{
const double y = m_sumMatrix.getBuffer()[i * m_sumMatrix.getDimensionSize(1)];
const double y2 = m_sumMatrix2.getBuffer()[i * m_sumMatrix2.getDimensionSize(1)];
variance->getBuffer()[i * variance->getDimensionSize(1)] = y2 / s - y * y / (s * s);
}
}
if (ip_isRangeActive)
{
for (size_t i = 0; i < range->getDimensionSize(0); ++i)
{
const double min = m_sortMatrix.getBuffer()[i * m_sortMatrix.getDimensionSize(1) + 0];
const double max = m_sortMatrix.getBuffer()[(i + 1) * m_sortMatrix.getDimensionSize(1) - 1];
range->getBuffer()[i * range->getDimensionSize(1)] = max - min;
}
}
if (ip_isMedianActive)
{
for (size_t i = 0; i < median->getDimensionSize(0); ++i)
{
median->getBuffer()[i * median->getDimensionSize(1)] =
(m_sortMatrix.getDimensionSize(1) % 2)
? m_sortMatrix.getBuffer()[i * m_sortMatrix.getDimensionSize(1) + m_sortMatrix.getDimensionSize(1) / 2 + 1 - 1]
: (m_sortMatrix.getBuffer()[i * m_sortMatrix.getDimensionSize(1) + m_sortMatrix.getDimensionSize(1) / 2 - 1]
+ m_sortMatrix.getBuffer()[i * m_sortMatrix.getDimensionSize(1) + m_sortMatrix.getDimensionSize(1) / 2 + 1 - 1]) / 2;
}
}
if (ip_isIQRActive)
{
for (size_t i = 0; i < iqr->getDimensionSize(0); ++i)
{
double flow = 0, up = 0;
const size_t reste = m_sortMatrix.getDimensionSize(1) % 4;
const size_t nb = 4 - reste;
for (size_t k = 0; k < nb; ++k)
{
flow += m_sortMatrix.getBuffer()[i * m_sortMatrix.getDimensionSize(1) + m_sortMatrix.getDimensionSize(1) / 4 - (nb - 1) + k - 1];
}
flow /= nb;
for (size_t k = 0; k < nb; ++k)
{
up += m_sortMatrix.getBuffer()[i * m_sortMatrix.getDimensionSize(1) + m_sortMatrix.getDimensionSize(1)
- m_sortMatrix.getDimensionSize(1) / 4 - 1 + k - 1];
}
up /= nb;
iqr->getBuffer()[i * iqr->getDimensionSize(1)] = up - flow;
}
}
if (ip_isPercentileActive)
{
const uint64_t value = m_percentileValue;
for (size_t i = 0; i < percentile->getDimensionSize(0); ++i)
{
percentile->getBuffer()[i * percentile->getDimensionSize(1)] = m_sortMatrix.getBuffer()[
i * m_sortMatrix.getDimensionSize(1) + std::max(int(0), int(m_sortMatrix.getDimensionSize(1) * value / 100 - 1))];
}
}
this->activateOutputTrigger(OVP_Algorithm_UnivariateStatistic_OutputTriggerId_ProcessDone, true);
}
return true;
}
bool CAlgoUnivariateStatistic::setMatrixDimension(CMatrix* matrix, CMatrix* ref)
{
//@todo We Allow matrix with 3 or more dimension ?
if (ref->getDimensionCount() < 2)
{
this->getLogManager() << Kernel::LogLevel_Warning << "Input matrix doesn't respect basic criteria (2 Dimensions)\n";
return false;
}
matrix->copyDescription(*ref);
return true;
}
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,101 @@
#pragma once
#include "../ovp_defines.h"
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
class CAlgoUnivariateStatistic final : public Toolkit::TAlgorithm<IAlgorithm>
{
public:
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool process() override;
_IsDerivedFromClass_Final_(Toolkit::TAlgorithm<IAlgorithm>, OVP_ClassId_AlgoUnivariateStatistic)
protected:
Kernel::TParameterHandler<CMatrix*> ip_matrix;
Kernel::TParameterHandler<CMatrix*> op_MeanMatrix;
Kernel::TParameterHandler<CMatrix*> op_VarianceMatrix;
Kernel::TParameterHandler<CMatrix*> op_RangeMatrix;
Kernel::TParameterHandler<CMatrix*> op_MedianMatrix;
Kernel::TParameterHandler<CMatrix*> op_IQRMatrix;
Kernel::TParameterHandler<CMatrix*> op_PercentileMatrix;
Kernel::TParameterHandler<bool> ip_isMeanActive;
Kernel::TParameterHandler<bool> ip_isVarianceActive;
Kernel::TParameterHandler<bool> ip_isRangeActive;
Kernel::TParameterHandler<bool> ip_isMedianActive;
Kernel::TParameterHandler<bool> ip_isIQRActive;
Kernel::TParameterHandler<bool> ip_isPercentileActive;
Kernel::TParameterHandler<uint64_t> ip_percentileValue;
Kernel::TParameterHandler<double> op_compression;
bool m_isSumActive = false;
bool m_isSqaresumActive = false;
bool m_isSortActive = false;
CMatrix m_sumMatrix;
CMatrix m_sumMatrix2;
CMatrix m_sortMatrix;
uint64_t m_percentileValue = 0;
bool setMatrixDimension(CMatrix* matrix, CMatrix* ref);
};
class CAlgoUnivariateStatisticDesc final : public IAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return CString("Signal Statistic"); }
CString getAuthorName() const override { return CString("Matthieu Goyat"); }
CString getAuthorCompanyName() const override { return CString("Gipsa-lab"); }
CString getShortDescription() const override { return CString("Calculate Mean, Variance, Median, etc. on the incoming buffer"); }
CString getDetailedDescription() const override { return CString(""); }
CString getCategory() const override { return CString("Signal processing/Statistics"); }
CString getVersion() const override { return CString("1.0"); }
CIdentifier getCreatedClass() const override { return OVP_ClassId_AlgoUnivariateStatistic; }
IPluginObject* create() override { return new CAlgoUnivariateStatistic(); }
bool getAlgorithmPrototype(Kernel::IAlgorithmProto& prototype) const override
{
prototype.addInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_Matrix, "Matrix input", Kernel::ParameterType_Matrix);
prototype.addInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_MeanActive, "active mean", Kernel::ParameterType_Boolean);
prototype.addInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_VarActive, "active variance", Kernel::ParameterType_Boolean);
prototype.addInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_RangeActive, "active range", Kernel::ParameterType_Boolean);
prototype.addInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_MedActive, "active median", Kernel::ParameterType_Boolean);
prototype.addInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_IQRActive, "active IQR", Kernel::ParameterType_Boolean);
prototype.addInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_PercentActive, "active Percentile", Kernel::ParameterType_Boolean);
prototype.addInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_PercentValue, "Percentile Value", Kernel::ParameterType_Integer);
prototype.addOutputParameter(OVP_Algorithm_UnivariateStatistic_OutputParameterId_Mean, "Mean output", Kernel::ParameterType_Matrix);
prototype.addOutputParameter(OVP_Algorithm_UnivariateStatistic_OutputParameterId_Var, "Variance output", Kernel::ParameterType_Matrix);
prototype.addOutputParameter(OVP_Algorithm_UnivariateStatistic_OutputParameterId_Range, "Range output", Kernel::ParameterType_Matrix);
prototype.addOutputParameter(OVP_Algorithm_UnivariateStatistic_OutputParameterId_Med, "Median output", Kernel::ParameterType_Matrix);
prototype.addOutputParameter(OVP_Algorithm_UnivariateStatistic_OutputParameterId_IQR, "Inter-Quantile-Range output", Kernel::ParameterType_Matrix);
prototype.addOutputParameter(OVP_Algorithm_UnivariateStatistic_OutputParameterId_Percent, "Percentile output", Kernel::ParameterType_Matrix);
prototype.addOutputParameter(OVP_Algorithm_UnivariateStatistic_OutputParameterId_Compression, "compression ratio", Kernel::ParameterType_Float);
prototype.addInputTrigger(OVP_Algorithm_UnivariateStatistic_InputTriggerId_Initialize, "Initialize");
prototype.addInputTrigger(OVP_Algorithm_UnivariateStatistic_InputTriggerId_Process, "Process");
prototype.addOutputTrigger(OVP_Algorithm_UnivariateStatistic_OutputTriggerId_ProcessDone, "Done");
return true;
}
_IsDerivedFromClass_Final_(IAlgorithmDesc, OVP_ClassId_AlgoUnivariateStatisticDesc)
};
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,324 @@
#if defined TARGET_HAS_ThirdPartyITPP
#include "ovpCApplyTemporalFilter.h"
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
void ComputeFilterInitialCondition(itpp::vec b, itpp::vec a, itpp::vec& zi)
{
int na, j, i;
na = length(a);
// FIXME is it necessary to keep next line uncomment ?
//int nb = length(b);
//--------------------------------------
// use sparse matrix to solve system of linear equations for initial conditions
// zi are the steady-state states of the filter b(z)/a(z) in the state-space
//implementation of the 'filter' command.
itpp::mat eye1;
eye1 = itpp::eye(na - 1);
itpp::mat eye2;
eye2 = itpp::eye(na - 2);
itpp::vec a1(na - 1);
itpp::vec zeros1(na - 2);
zeros1 = itpp::zeros(na - 2);
itpp::vec b1(na - 1);
itpp::vec a2(na - 1);
for (j = 1; j < na; ++j)
{
a1[j - 1] = - a[j];
b1[j - 1] = b[j];
a2[j - 1] = a[j];
}
itpp::mat matConc01;
itpp::mat matZeros1;
matZeros1 = itpp::zeros(na - 2, 1);
matConc01 = concat_vertical(eye2, transpose(matZeros1));
itpp::mat matA1;
matA1 = itpp::zeros(na - 1, 1);
matA1.set_col(0, a1);
itpp::mat matConc02;
matConc02 = concat_horizontal(matA1, matConc01);
itpp::mat matNum;
matNum = eye1 - matConc02;
itpp::vec vecDenom(na - 1);
for (i = 0; i < na - 1; ++i) { vecDenom[i] = b1[i] - (a2[i] * b[0]); }
zi = inv(matNum) * vecDenom;
}
void FilterIRR(itpp::vec b, itpp::vec a, itpp::vec data, itpp::vec v0, itpp::vec& dataFiltered, itpp::vec& vf)
{
int i, j, iV0 = 0;
double sumA, sumB;
double sumVf;
// FIXME is it necessary to keep next line uncomment ?
//int na = length(a);
const int nb = length(b);
const int size = length(data);
if (size < nb)
{
for (i = 0; i < size; ++i)
{
sumB = 0.0;
for (j = 0; j <= i; ++j) { sumB = sumB + (b[j] * data[i - j]); }
sumA = 0.0;
for (j = 0; j <= i; ++j) { sumA = sumA + (a[j] * dataFiltered[i - j]); }
dataFiltered[i] = sumB - sumA + v0[i];
}
for (i = 0; i < (nb - 1); ++i)
{
sumVf = 0.0;
double tmp = 0.0;
for (j = 0; j < (nb - 1); ++j)
{
if ((i + j) < (nb - 1))
{
if ((size - 1 - j) >= 0)
{
sumVf = sumVf + (b[i + j + 1] * data[size - 1 - j]) - (a[i + j + 1] * dataFiltered[size - 1 - j]);
iV0 = i + j + 1;
}
if ((size - 1 - j) < 0) { tmp = v0[iV0]; }
}
}
vf[i] = sumVf + tmp;
}
}
else
{
for (i = 0; i < nb - 1; ++i)
{
sumB = 0.0;
for (j = 0; j <= i; ++j) { sumB = sumB + (b[j] * data[i - j]); }
sumA = 0.0;
for (j = 0; j <= i; ++j) { sumA = sumA + (a[j] * dataFiltered[i - j]); }
dataFiltered[i] = sumB - sumA + v0[i];
}
for (i = nb - 1; i < size; ++i)
{
sumB = 0.0;
for (j = 0; j < nb; ++j) { sumB = sumB + (b[j] * data[i - j]); }
sumA = 0.0;
for (j = 0; j < nb; ++j) { sumA = sumA + (a[j] * dataFiltered[i - j]); }
dataFiltered[i] = sumB - sumA;
}
for (i = 0; i < nb - 1; ++i)
{
sumVf = 0.0;
for (j = i; j < nb - 1; ++j) { sumVf = sumVf + (b[j + 1] * data[size - 1 - j + i]) - (a[j + 1] * dataFiltered[size - 1 - j + i]); }
vf[i] = sumVf;
}
}
}
void Filtfilt(const itpp::vec& b, const itpp::vec& a, itpp::vec data, itpp::vec& dataFiltered)
{
int j;
const int na = length(a);
const int nb = length(b);
const int dataSize = length(data);
const int lengthEdgeTransients = 3 * (nb - 1);
itpp::vec xB = itpp::zeros(dataSize + (2 * lengthEdgeTransients));
itpp::vec yB = itpp::zeros(dataSize + (2 * lengthEdgeTransients));
itpp::vec yB2 = itpp::zeros(dataSize + (2 * lengthEdgeTransients));
itpp::vec yC = itpp::zeros(dataSize + (2 * lengthEdgeTransients));
itpp::vec yC2 = itpp::zeros(dataSize + (2 * lengthEdgeTransients));
itpp::vec zi(na - 1);
ComputeFilterInitialCondition(b, a, zi);
for (j = 0; j < lengthEdgeTransients; ++j) { xB[j] = (2 * data[0]) - data[lengthEdgeTransients - j]; }
for (j = 0; j < dataSize; ++j) { xB[j + lengthEdgeTransients] = data[j]; }
for (j = 0; j < lengthEdgeTransients; ++j) { xB[j + lengthEdgeTransients + dataSize] = (2 * data[dataSize - 1]) - data[dataSize - j - 2]; }
itpp::vec ziChan(na - 1);
for (j = 0; j < na - 1; ++j) { ziChan[j] = zi[j] * xB[0]; }
itpp::vec finalStates(na - 1);
FilterIRR(b, a, xB, ziChan, yB, finalStates);
for (j = 0; j < dataSize + (2 * lengthEdgeTransients); ++j) { yC[j] = yB[(dataSize + (2 * lengthEdgeTransients)) - 1 - j]; }
itpp::vec ziChan2(na - 1);
for (j = 0; j < na - 1; ++j) { ziChan2[j] = zi[j] * yC[0]; }
FilterIRR(b, a, yC, ziChan2, yB2, finalStates);
for (j = 0; j < dataSize + (2 * lengthEdgeTransients); ++j) { yC2[j] = yB2[(dataSize + (2 * lengthEdgeTransients)) - 1 - j]; }
for (j = 0; j < dataSize; ++j) { dataFiltered[j] = yC2[j + lengthEdgeTransients]; }
}
bool CApplyTemporalFilter::initialize()
{
bool res = true;
res &= ip_signalMatrix.initialize(getInputParameter(OVP_Algorithm_ApplyTemporalFilter_InputParameterId_SignalMatrix));
res &= ip_filterCoefsMatrix.initialize(getInputParameter(OVP_Algorithm_ApplyTemporalFilter_InputParameterId_FilterCoefsMatrix));
res &= op_signalMatrix.initialize(getOutputParameter(OVP_Algorithm_ApplyTemporalFilter_OutputParameterId_FilteredSignalMatrix));
return res;
}
bool CApplyTemporalFilter::uninitialize()
{
op_signalMatrix.uninitialize();
ip_filterCoefsMatrix.uninitialize();
ip_signalMatrix.uninitialize();
return true;
}
//
//
bool CApplyTemporalFilter::process()
{
CMatrix* iMatrix = ip_signalMatrix;
CMatrix* oMatrix = op_signalMatrix;
if (isInputTriggerActive(OVP_Algorithm_ApplyTemporalFilter_InputTriggerId_Initialize))
{
m_flagInitialize = true;
oMatrix->copyDescription(*iMatrix);
// dimension of input coef (numerator, denominator) filter
const size_t filterCoefNumeratorDimSize = ip_filterCoefsMatrix->getDimensionSize(0);
const size_t filterCoefDenominatorDimSize = ip_filterCoefsMatrix->getDimensionSize(0);
//coef filters vars
CMatrix* filterCoefInputMatrix = ip_filterCoefsMatrix;
double* filterCoefInput = filterCoefInputMatrix->getBuffer();
m_coefFilterDen = itpp::zeros(filterCoefDenominatorDimSize);
m_coefFilterNum = itpp::zeros(filterCoefNumeratorDimSize);
for (size_t i = 0; i < filterCoefNumeratorDimSize; ++i) { m_coefFilterNum[i] = filterCoefInput[i]; }
for (size_t i = 0; i < filterCoefDenominatorDimSize; ++i) { m_coefFilterDen[i] = filterCoefInput[filterCoefNumeratorDimSize + i]; }
}
// This mode is used when the consecutive input chunks are discontinuous in time
if (isInputTriggerActive(OVP_Algorithm_ApplyTemporalFilter_InputTriggerId_ApplyFilter))
{
// signal input vars
double* input = iMatrix->getBuffer();
// dimension of input signal buffer
const size_t nDim = ip_signalMatrix->getDimensionCount();
const size_t nChannels = ip_signalMatrix->getDimensionSize(0);
const size_t nEpoch = ip_signalMatrix->getDimensionSize(1);
// signal output vars
oMatrix->setDimensionCount(nDim);
for (size_t i = 0; i < nDim; ++i) { oMatrix->setDimensionSize(i, ip_signalMatrix->getDimensionSize(i)); }
double* filteredSignalMatrix = oMatrix->getBuffer();
itpp::vec y(nEpoch);
itpp::vec x = itpp::zeros(nEpoch);
// test that Filtfilt() won't exceed the data array boundaries
const size_t minSize = 3 * (m_coefFilterDen.size() - 1) + 1;
if (nEpoch < minSize)
{
this->getLogManager() << Kernel::LogLevel_Error << "Data chunk size (" << nEpoch << ") "
<< "is too short for the requirements of the filter (" << minSize << "). Please use a larger chunk size.\n";
return false;
}
for (size_t i = 0; i < nChannels; ++i)
{
for (size_t j = 0; j < nEpoch; ++j) { x[int(j)] = double(input[i * nEpoch + j]); }
// --- Modif Manu
Filtfilt(m_coefFilterNum, m_coefFilterDen, x, y);
// --- Fin Modif Manu
for (size_t k = 0; k < nEpoch; ++k) { filteredSignalMatrix[i * nEpoch + k] = y[k]; }
}
}
// This mode is used when the consecutive input chunks are continuous in time
if (isInputTriggerActive(OVP_Algorithm_ApplyTemporalFilter_InputTriggerId_ApplyFilterWithHistoric))
{
// signal input vars
double* input = iMatrix->getBuffer();
// dimension of input signal biuffer
const size_t nDim = ip_signalMatrix->getDimensionCount();
const size_t nChannels = ip_signalMatrix->getDimensionSize(0);
const size_t nEpoch = ip_signalMatrix->getDimensionSize(1);
// historic buffers
if (m_flagInitialize)
{
// --- Modif Manu
itpp::vec zi = itpp::zeros(int(ip_filterCoefsMatrix->getDimensionSize(0) - 1));
ComputeFilterInitialCondition(m_coefFilterNum, m_coefFilterDen, zi);
m_currentStates.resize(nChannels);
for (size_t i = 0; i < nChannels; ++i) { m_currentStates[i] = zi * double(input[i * nEpoch]); }
// --- Fin Modif Manu
m_flagInitialize = false;
}
// signal output vars
oMatrix->setDimensionCount(nDim);
for (size_t i = 0; i < nDim; ++i) { oMatrix->setDimensionSize(i, ip_signalMatrix->getDimensionSize(i)); }
double* filteredSignalMatrix = oMatrix->getBuffer();
itpp::vec x = itpp::zeros(nEpoch);
itpp::vec y(nEpoch);
//y = zeros(nEpoch);
for (size_t i = 0; i < nChannels; ++i)
{
for (size_t j = 0; j < nEpoch; ++j) { x[j] = double(input[i * nEpoch + j]); }
// --- Modif Manu
y = itpp::zeros(nEpoch);
FilterIRR(m_coefFilterNum, m_coefFilterDen, x, m_currentStates[i], y, m_currentStates[i]);
// --- Fin Modif Manu
for (size_t k = 0; k < nEpoch; ++k) { filteredSignalMatrix[i * nEpoch + k] = y[k]; }
}
}
return true;
}
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyITPP
@@ -0,0 +1,78 @@
#pragma once
#if defined TARGET_HAS_ThirdPartyITPP
#include "../ovp_defines.h"
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
#include <itpp/itstat.h>
#include <itpp/itsignal.h>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
class CApplyTemporalFilter final : virtual public Toolkit::TAlgorithm<IAlgorithm>
{
public:
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool process() override;
_IsDerivedFromClass_Final_(Toolkit::TAlgorithm<IAlgorithm>, OVP_ClassId_Algorithm_ApplyTemporalFilter)
protected:
Kernel::TParameterHandler<CMatrix*> ip_signalMatrix;
Kernel::TParameterHandler<CMatrix*> ip_filterCoefsMatrix;
Kernel::TParameterHandler<CMatrix*> op_signalMatrix;
itpp::vec m_coefFilterDen;
itpp::vec m_coefFilterNum;
std::vector<itpp::vec> m_currentStates;
bool m_flagInitialize = false;
};
class CApplyTemporalFilterDesc final : virtual public IAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return CString("Temporal Filter (INSERM contrib)"); }
CString getAuthorName() const override { return CString("Guillaume Gibert"); }
CString getAuthorCompanyName() const override { return CString("INSERM/U821"); }
CString getShortDescription() const override { return CString(""); }
CString getDetailedDescription() const override { return CString(""); }
CString getCategory() const override { return CString("Algorithm/Signal processing/Filter"); }
CString getVersion() const override { return CString("1.0"); }
CIdentifier getCreatedClass() const override { return OVP_ClassId_Algorithm_ApplyTemporalFilter; }
IPluginObject* create() override { return new CApplyTemporalFilter(); }
bool getAlgorithmPrototype(Kernel::IAlgorithmProto& prototype) const override
{
prototype.addInputParameter(OVP_Algorithm_ApplyTemporalFilter_InputParameterId_SignalMatrix, "Signal matrix", Kernel::ParameterType_Matrix);
prototype.addInputParameter(OVP_Algorithm_ApplyTemporalFilter_InputParameterId_FilterCoefsMatrix, "Filter coefficients matrix", Kernel::ParameterType_Matrix);
prototype.addOutputParameter(OVP_Algorithm_ApplyTemporalFilter_OutputParameterId_FilteredSignalMatrix, "Filtered signal matrix", Kernel::ParameterType_Matrix);
prototype.addInputTrigger(OVP_Algorithm_ApplyTemporalFilter_InputTriggerId_Initialize, "Initialize");
prototype.addInputTrigger(OVP_Algorithm_ApplyTemporalFilter_InputTriggerId_ApplyFilter, "Apply filter");
prototype.addInputTrigger(OVP_Algorithm_ApplyTemporalFilter_InputTriggerId_ApplyFilterWithHistoric, "Apply filter with historic");
return true;
}
_IsDerivedFromClass_Final_(IAlgorithmDesc, OVP_ClassId_Algorithm_ApplyTemporalFilterDesc)
};
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyITPP
@@ -0,0 +1,639 @@
#if defined TARGET_HAS_ThirdPartyITPP
#include "ovpCComputeTemporalFilterCoefficients.h"
#include <limits>
#include <cmath>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
// Add 2complexes
void CComputeTemporalFilterCoefficients::addComplex(cmplex* a, cmplex* b, cmplex* c)
{
c->real = b->real + a->real;
c->imag = b->imag + a->imag;
}
// Substract 2 complex
void CComputeTemporalFilterCoefficients::subComplex(cmplex* a, cmplex* b, cmplex* c)
{
c->real = b->real - a->real;
c->imag = b->imag - a->imag;
}
// Multiply 2 complexes
void CComputeTemporalFilterCoefficients::mulComplex(cmplex* a, cmplex* b, cmplex* c)
{
const double y = b->real * a->real - b->imag * a->imag;
c->imag = b->real * a->imag + b->imag * a->real;
c->real = y;
}
// Divide 2 complex numbers
void CComputeTemporalFilterCoefficients::divComplex(cmplex* a, cmplex* b, cmplex* c) const
{
const double y = a->real * a->real + a->imag * a->imag;
const double p = b->real * a->real + b->imag * a->imag;
const double q = b->imag * a->real - b->real * a->imag;
if (y < 1.0)
{
const double w = MAXNUM * y;
if ((fabs(p) > w) || (fabs(q) > w) || (y == 0.0))
{
c->real = MAXNUM;
c->imag = MAXNUM;
std::cout << "divCOMPLEX: OVERFLOW" << std::endl;
return;
}
}
c->real = p / y;
c->imag = q / y;
}
// Compute abs of a complex
double CComputeTemporalFilterCoefficients::absComplex(cmplex* z) const
{
int ex, ey;
const double re = fabs(z->real);
const double im = fabs(z->imag);
if (re == 0.0) { return (im); }
if (im == 0.0) { return (re); }
// Get the exponents of the numbers
frexp(re, &ex);
frexp(im, &ey);
// Check if one number is tiny compared to the other
int e = ex - ey;
if (e > PREC) { return (re); }
if (e < -PREC) { return (im); }
// Find approximate exponent e of the geometric mean.
e = (ex + ey) >> 1;
// Rescale so mean is about 1
const double x = ldexp(re, -e);
double y = ldexp(im, -e);
// Hypotenuse of the right triangle
double b = sqrt(x * x + y * y);
// Compute the exponent of the answer.
y = frexp(b, &ey);
ey = e + ey;
// Check it for overflow and underflow.
if (ey > MAXEXP)
{
std::cout << "absCOMPLEX: OVERFLOW" << std::endl;
return (std::numeric_limits<double>::infinity());
}
if (ey < MINEXP) { return (0.0); }
// Undo the scaling
b = ldexp(b, e);
return (b);
}
// Compute sqrt of a complex number
void CComputeTemporalFilterCoefficients::sqrtComplex(cmplex* z, cmplex* w) const
{
cmplex q, s;
double r, t;
const double x = z->real;
const double y = z->imag;
if (y == 0.0)
{
if (x < 0.0)
{
w->real = 0.0;
w->imag = sqrt(-x);
return;
}
w->real = sqrt(x);
w->imag = 0.0;
return;
}
if (x == 0.0)
{
r = fabs(y);
r = sqrt(0.5 * r);
if (y > 0) { w->real = r; }
else { w->real = -r; }
w->imag = r;
return;
}
// Approximate sqrt(x^2+y^2) - x = y^2/2x - y^4/24x^3 + ... .
// The relative error in the first term is approximately y^2/12x^2 .
if ((fabs(y) < 2.e-4 * fabs(x)) && (x > 0)) { t = 0.25 * y * (y / x); }
else
{
r = absComplex(z);
t = 0.5 * (r - x);
}
r = sqrt(t);
q.imag = r;
q.real = y / (2.0 * r);
// Heron iteration in complex arithmetic
divComplex(&q, z, &s);
addComplex(&q, &s, w);
w->real *= 0.5;
w->imag *= 0.5;
}
// compute s plane poles and zeros
void CComputeTemporalFilterCoefficients::findSPlanePolesAndZeros()
{
m_nPoles = (m_filterOrder + 1) / 2;
m_nZeros = 0;
m_zs = itpp::zeros(m_arraySize);
double dm;
size_t ii = 0;
double db;
if (m_filterMethod == EFilterMethod::Butterworth)//poles equally spaced around the unit circle
{
if (m_filterOrder & 1) { dm = 0.0; }
else { dm = itpp::pi / (2.0 * double(m_filterOrder)); }
for (size_t i = 0; i < m_nPoles; ++i)// poles
{
const size_t lr = i + i;
m_zs[lr] = -cos(dm);
m_zs[lr + 1] = sin(dm);
dm += itpp::pi / double(m_filterOrder);
}
if (m_filterType == EFilterType::HighPass || m_filterType == EFilterType::BandStop) // high pass or band reject
{
// map s => 1/s
for (size_t j = 0; j < m_nPoles; ++j)
{
const size_t ir = j + j;
ii = ir + 1;
db = m_zs[ir] * m_zs[ir] + m_zs[ii] * m_zs[ii];
m_zs[ir] = m_zs[ir] / db;
m_zs[ii] = m_zs[ii] / db;
}
// The zeros at infinity map to the origin.
m_nZeros = m_nPoles;
if (m_filterType == EFilterType::BandStop) { m_nZeros += m_filterOrder / 2; }
for (size_t j = 0; j < m_nZeros; ++j)
{
const size_t ir = ii + 1;
ii = ir + 1;
m_zs[ir] = 0.0;
m_zs[ii] = 0.0;
}
}
}
if (m_filterMethod == EFilterMethod::Chebyshev)
{
//For Chebyshev, find radii of two Butterworth circles (See Gold & Rader, page 60)
m_rho = (m_phi - 1.0) * (m_phi + 1); // m_rho = m_eps^2 = {sqrt(1+m_eps^2)}^2 - 1
m_eps = sqrt(m_rho); // sqrt( 1 + 1/m_eps^2 ) + 1/m_eps = {sqrt(1 + m_eps^2) + 1} / m_eps
m_phi = (m_phi + 1.0) / m_eps;
m_phi = pow(m_phi, double(1.0) / m_filterOrder); // raise to the 1/n power
db = 0.5 * (m_phi + 1.0 / m_phi); // y coordinates are on this circle
const double da = 0.5 * (m_phi - 1.0 / m_phi); // x coordinates are on this circle
if (m_filterOrder & 1) { dm = 0.0; }
else { dm = itpp::pi / (2.0 * double(m_filterOrder)); }
for (size_t i = 0; i < m_nPoles; ++i)// poles
{
const size_t lr = i + i;
m_zs[lr] = -da * cos(dm);
m_zs[lr + 1] = db * sin(dm);
dm += itpp::pi / double(m_filterOrder);
}
if (m_filterType == EFilterType::HighPass || m_filterType == EFilterType::BandStop)// high pass or band reject
{
// map s => 1/s
for (size_t j = 0; j < m_nPoles; ++j)
{
const size_t ir = j + j;
ii = ir + 1;
db = m_zs[ir] * m_zs[ir] + m_zs[ii] * m_zs[ii];
m_zs[ir] = m_zs[ir] / db;
m_zs[ii] = m_zs[ii] / db;
}
// The zeros at infinity map to the origin.
m_nZeros = m_nPoles;
if (m_filterType == EFilterType::BandStop) { m_nZeros += m_filterOrder / 2; }
for (size_t j = 0; j < m_nZeros; ++j)
{
const size_t ir = ii + 1;
ii = ir + 1;
m_zs[ir] = 0.0;
m_zs[ii] = 0.0;
}
}
}
}
//convert s plane poles and zeros to the z plane.
void CComputeTemporalFilterCoefficients::convertSPlanePolesAndZerosToZPlane()
{
// Vars
cmplex r, cnum, cden, cwc, ca, cb, b4Ac;
cmplex cone = { 1.0, 0.0 };
cmplex* z = new cmplex[m_arraySize];
double* pp = new double[m_arraySize];
double* y = new double[m_arraySize];
double* aa = new double[m_arraySize];
double c = 0.0, a = 0.0, b = 0.0, pn = 0.0, an = 0.0, gam = 0.0, ai = 0.0, cng = 0.0, gain = 0.0;
size_t nc = 0, jt = 0, ii = 0, ir = 0, jj = 0, jh = 0, jl = 0, mh = 0;
c = m_tanAng;
for (size_t i = 0; i < m_arraySize; ++i)
{
z[i].real = 0.0;
z[i].imag = 0.0;
}
nc = m_nPoles;
jt = -1;
ii = -1;
for (size_t icnt = 0; icnt < 2; ++icnt)
{
do
{
ir = ii + 1;
ii = ir + 1;
r.real = m_zs[ir];
r.imag = m_zs[ii];
if (m_filterType == EFilterType::LowPass || m_filterType == EFilterType::HighPass)
{
// Substitute s - r = s/wc - r = (1/wc)(z-1)/(z+1) - r
//
// 1 1 - r wc ( 1 + r wc )
// = --- -------- ( z - -------- )
// z+1 wc ( 1 - r wc )
//
// giving the root in the z plane.
cnum.real = 1 + c * r.real;
cnum.imag = c * r.imag;
cden.real = 1 - c * r.real;
cden.imag = -c * r.imag;
jt += 1;
divComplex(&cden, &cnum, &z[jt]);
if (r.imag != 0.0)
{
// fill in complex conjugate root
jt += 1;
z[jt].real = z[jt - 1].real;
z[jt].imag = -z[jt - 1].imag;
}
}
if (m_filterType == EFilterType::BandPass || m_filterType == EFilterType::BandStop)
{
// Substitute s - r => s/wc - r
//
// z^2 - 2 z cgam + 1
// => ------------------ - r
// (z^2 + 1) wc
//
// 1
// = ------------ [ (1 - r wc) z^2 - 2 cgam z + 1 + r wc ]
// (z^2 + 1) wc
//
// and solve for the roots in the z plane.
if (m_filterMethod == EFilterMethod::Chebyshev) { cwc.real = m_cbp; }
else { cwc.real = m_tanAng; }
cwc.imag = 0.0;
// r * wc //
mulComplex(&r, &cwc, &cnum);
// a = 1 - r wc //
subComplex(&cnum, &cone, &ca);
// 1 - (r wc)^2 //
mulComplex(&cnum, &cnum, &b4Ac);
subComplex(&b4Ac, &cone, &b4Ac);
// 4ac //
b4Ac.real *= 4.0;
b4Ac.imag *= 4.0;
// b //
cb.real = -2.0 * m_cosGam;
cb.imag = 0.0;
// b^2 //
mulComplex(&cb, &cb, &cnum);
// b^2 - 4ac//
subComplex(&b4Ac, &cnum, &b4Ac);
// sqrt() //
sqrtComplex(&b4Ac, &b4Ac);
// -b //
cb.real = -cb.real;
cb.imag = -cb.imag;
// 2a //
ca.real *= 2.0;
ca.imag *= 2.0;
// -b +sqrt(b^2-4ac) //
addComplex(&b4Ac, &cb, &cnum);
// ... /2a //
divComplex(&ca, &cnum, &cnum);
jt += 1;
z[jt].real = cnum.real;
z[jt].imag = cnum.imag;
if (cnum.imag != 0.0)
{
jt += 1;
z[jt].real = cnum.real;
z[jt].imag = -cnum.imag;
}
if ((r.imag != 0.0) || cnum.imag == 0.0)
{
// -b - sqrt( b^2 - 4ac) //
subComplex(&b4Ac, &cb, &cnum);
// ... /2a //
divComplex(&ca, &cnum, &cnum);
jt += 1;
z[jt].real = cnum.real;
z[jt].imag = cnum.imag;
if (cnum.imag != 0.0)
{
jt += 1;
z[jt].real = cnum.real;
z[jt].imag = -cnum.imag;
}
}
}
} while (--nc > 0);
if (icnt == 0)
{
m_zOrd = jt + 1;
if (m_nZeros <= 0) { icnt = 2; }
}
nc = m_nZeros;
}
// Generate the remaining zeros
while (2 * m_zOrd - 1 > jt)
{
if (m_filterType != EFilterType::HighPass)
{
jt += 1;
z[jt].real = -1.0;
z[jt].imag = 0.0;
}
if (m_filterType == EFilterType::BandPass || m_filterType == EFilterType::HighPass)
{
jt += 1;
z[jt].real = 1.0;
z[jt].imag = 0.0;
}
}
// Expand the poles and zeros into numerator and denominator polynomials
for (size_t j = 0; j < m_arraySize; ++j) { aa[j] = 0.0; }
for (size_t icnt = 0; icnt < 2; ++icnt)
{
for (size_t j = 0; j < m_arraySize; ++j)
{
pp[j] = 0.0;
y[j] = 0.0;
}
pp[0] = 1.0;
for (size_t j = 0; j < m_zOrd; ++j)
{
jj = j;
if (icnt) { jj += m_zOrd; }
a = z[jj].real;
b = z[jj].imag;
for (size_t k = 0; k <= j; ++k)
{
jh = j - k;
pp[jh + 1] = pp[jh + 1] - a * pp[jh] + b * y[jh];
y[jh + 1] = y[jh + 1] - b * pp[jh] - a * y[jh];
}
}
if (icnt == 0) { for (size_t j = 0; j <= m_zOrd; ++j) { aa[j] = pp[j]; } }
}
// Scale factors of the pole and zero polynomials
if (m_filterType == EFilterType::HighPass) { a = -1.0; }
else { a = 1.0; }
if (m_filterType == EFilterType::HighPass || m_filterType == EFilterType::LowPass || m_filterType ==
EFilterType::BandStop)
{
pn = 1.0;
an = 1.0;
for (size_t j = 1; j <= m_zOrd; ++j)
{
pn = a * pn + pp[j];
an = a * an + aa[j];
}
}
if (m_filterType == EFilterType::BandPass)
{
gam = itpp::pi / 2.0 - asin(m_cosGam); // = acos( cgam ) //
mh = m_zOrd / 2;
pn = pp[mh];
an = aa[mh];
ai = 0.0;
if (mh > ((m_zOrd / 4) * 2))
{
ai = 1.0;
pn = 0.0;
an = 0.0;
}
for (size_t j = 1; j <= mh; ++j)
{
a = gam * j - ai * itpp::pi / 2.0;
cng = cos(a);
jh = mh + j;
jl = mh - j;
pn = pn + cng * (pp[jh] + (1.0 - 2.0 * ai) * pp[jl]);
an = an + cng * (aa[jh] + (1.0 - 2.0 * ai) * aa[jl]);
}
}
gain = an / (pn * m_scale);
if (pn == 0.0) { gain = 1.0; }
for (size_t j = 0; j <= m_zOrd; ++j) { pp[j] = gain * pp[j]; }
for (size_t j = 0; j <= m_zOrd; ++j)
{
m_coefFilterDen[j] = pp[j];
m_coefFilterNum[j] = aa[j];
}
delete [] z;
delete [] pp;
delete [] y;
delete [] aa;
}
bool CComputeTemporalFilterCoefficients::initialize()
{
ip_sampling.initialize(getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_Sampling));
ip_filterMethod.initialize(getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_FilterMethod));
ip_filterType.initialize(getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_FilterType));
ip_filterOrder.initialize(getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_FilterOrder));
ip_lowCutFrequency.initialize(getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_LowCutFrequency));
ip_highCutFrequency.initialize(getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_HighCutFrequency));
ip_bandPassRipple.initialize(getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_BandPassRipple));
op_matrix.initialize(getOutputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_OutputParameterId_Matrix));
return true;
}
bool CComputeTemporalFilterCoefficients::uninitialize()
{
op_matrix.uninitialize();
ip_bandPassRipple.uninitialize();
ip_highCutFrequency.uninitialize();
ip_lowCutFrequency.uninitialize();
ip_filterOrder.uninitialize();
ip_filterType.uninitialize();
ip_filterMethod.uninitialize();
ip_sampling.uninitialize();
return true;
}
// ________________________________________________________________________________________________________________
//
bool CComputeTemporalFilterCoefficients::process()
{
if (isInputTriggerActive(OVP_Algorithm_ComputeTemporalFilterCoefs_InputTriggerId_Initialize))
{
m_sampling = size_t(ip_sampling);
m_filterMethod = EFilterMethod(uint64_t(ip_filterMethod));
m_filterType = EFilterType(uint64_t(ip_filterType));
m_filterOrder = size_t(ip_filterOrder);
m_lowPassBandEdge = ip_lowCutFrequency;
m_highPassBandEdge = ip_highCutFrequency;
m_passBandRipple = ip_bandPassRipple;
m_arraySize = 4 * m_filterOrder; // Maximum size of array involved in computation
}
if (isInputTriggerActive(OVP_Algorithm_ComputeTemporalFilterCoefs_InputTriggerId_ComputeCoefs))
{
if (m_filterMethod == EFilterMethod::Butterworth || m_filterMethod == EFilterMethod::Chebyshev)
{
if (m_filterType == EFilterType::LowPass || m_filterType == EFilterType::HighPass)
{
m_dimSize = m_filterOrder + 1;
m_coefFilterDen = itpp::zeros(m_dimSize);
m_coefFilterNum = itpp::zeros(m_dimSize);
}
else
{
m_dimSize = 2 * m_filterOrder + 1;
m_coefFilterDen = itpp::zeros(m_dimSize);
m_coefFilterNum = itpp::zeros(m_dimSize);
}
if (m_filterMethod == EFilterMethod::Chebyshev)
{
// For Chebyshev filter, ripples go from 1.0 to 1/sqrt(1+m_eps^2)
m_phi = exp(0.5 * m_passBandRipple / (10.0 / log(10.0)));
if ((m_filterOrder & 1) == 0) { m_scale = m_phi; }
else { m_scale = 1.0; }
}
m_nyquist = m_sampling / 2;
//locate edges
if (m_filterType == EFilterType::LowPass) { m_lowPassBandEdge = 0.0; }
//local variables
double bandWidth, highFrequencyEdge;
if (m_filterType == EFilterType::HighPass)
{
bandWidth = m_highPassBandEdge;
highFrequencyEdge = double(m_nyquist);
}
else
{
bandWidth = m_highPassBandEdge - m_lowPassBandEdge;
highFrequencyEdge = m_highPassBandEdge;
}
//convert to Frequency correspondence for bilinear transformation
// Wanalog = tan( 2 pi Fdigital T / 2 )
// where T = 1/fs
const double ang = double(bandWidth) * itpp::pi / double(m_sampling);
const double cosAng = cos(ang);
m_tanAng = sin(ang) / cosAng; // Wanalog
// Transformation from low-pass to band-pass critical frequencies
// Center frequency
// cos( 1/2 (Whigh+Wlow) T )
// cos( Wcenter T ) = -------------------------
// cos( 1/2 (Whigh-Wlow) T )
//
// Band edges
// cos( Wcenter T) - cos( Wdigital T )
// Wanalog = -----------------------------------
// sin( Wdigital T )
highFrequencyEdge = itpp::pi * (highFrequencyEdge + m_lowPassBandEdge) / double(m_sampling);
m_cosGam = cos(highFrequencyEdge) / cosAng;
highFrequencyEdge = 2.0 * itpp::pi * m_highPassBandEdge / double(m_sampling);
m_cbp = (m_cosGam - cos(highFrequencyEdge)) / sin(highFrequencyEdge);
if (m_filterMethod == EFilterMethod::Butterworth) { m_scale = 1.0; }
findSPlanePolesAndZeros();
convertSPlanePolesAndZerosToZPlane();
}
CMatrix* oMatrix = op_matrix;
oMatrix->resize(m_dimSize, 2); // Push m_coefFilterDen and m_coefFilterNum as two column vectors m_dimension rows
double* filterCoefMatrix = oMatrix->getBuffer();
for (size_t i = 0; i < m_dimSize; ++i)
{
filterCoefMatrix[i] = m_coefFilterDen[i];
filterCoefMatrix[m_dimSize + i] = m_coefFilterNum[i];
}
}
return true;
}
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyITPP
@@ -0,0 +1,135 @@
#pragma once
#if defined TARGET_HAS_ThirdPartyITPP
#include "../ovp_defines.h"
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
#include <itpp/itstat.h>
#include <itpp/itsignal.h>
#define PREC 27
#define MAXEXP 1024
#define MINEXP -1077
#define MAXNUM 1.79769313486231570815E308
typedef struct
{
double real;
double imag;
} cmplex;
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
class CComputeTemporalFilterCoefficients : virtual public Toolkit::TAlgorithm<IAlgorithm>
{
public:
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool process() override;
_IsDerivedFromClass_Final_(Toolkit::TAlgorithm<IAlgorithm>, OVP_ClassId_Algorithm_ComputeTemporalFilterCoefs)
// Functions for Butterworth and Chebyshev filters
void findSPlanePolesAndZeros();
void convertSPlanePolesAndZerosToZPlane();
// Functions for Complex arithmetic
double absComplex(cmplex* z) const;
void divComplex(cmplex* a, cmplex* b, cmplex* c) const;
void sqrtComplex(cmplex* z, cmplex* w) const;
static void addComplex(cmplex* a, cmplex* b, cmplex* c);
static void mulComplex(cmplex* a, cmplex* b, cmplex* c);
static void subComplex(cmplex* a, cmplex* b, cmplex* c);
protected:
Kernel::TParameterHandler<uint64_t> ip_sampling;
Kernel::TParameterHandler<uint64_t> ip_filterMethod;
Kernel::TParameterHandler<uint64_t> ip_filterType;
Kernel::TParameterHandler<uint64_t> ip_filterOrder;
Kernel::TParameterHandler<double> ip_lowCutFrequency;
Kernel::TParameterHandler<double> ip_highCutFrequency;
Kernel::TParameterHandler<double> ip_bandPassRipple;
Kernel::TParameterHandler<CMatrix*> op_matrix;
size_t m_filterOrder = 0;
EFilterMethod m_filterMethod = EFilterMethod::Butterworth;
EFilterType m_filterType = EFilterType::BandPass;
double m_lowPassBandEdge = 0;
double m_highPassBandEdge = 0;
double m_passBandRipple = 0;
size_t m_arraySize = 0;
itpp::vec m_coefFilterNum;
itpp::vec m_coefFilterDen;
double m_phi = 0;
double m_scale = 0;
double m_tanAng = 0;
double m_cosGam = 0;
double m_cbp = 0;
size_t m_sampling = 0;
size_t m_nyquist = 0;
size_t m_nPoles = 0;
size_t m_nZeros = 0;
itpp::vec m_zs;
size_t m_zOrd = 0;
double m_rho = 0;
double m_eps = 0;
size_t m_dimSize = 0;
};
class CComputeTemporalFilterCoefficientsDesc final : virtual public IAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return CString("Compute Filter Coefficients"); }
CString getAuthorName() const override { return CString("Guillaume Gibert"); }
CString getAuthorCompanyName() const override { return CString("INSERM/U821"); }
CString getShortDescription() const override { return CString(""); }
CString getDetailedDescription() const override { return CString(""); }
CString getCategory() const override { return CString("Algorithm/Signal processing/Filter"); }
CString getVersion() const override { return CString("1.0"); }
CIdentifier getCreatedClass() const override { return OVP_ClassId_Algorithm_ComputeTemporalFilterCoefs; }
IPluginObject* create() override { return new CComputeTemporalFilterCoefficients(); }
bool getAlgorithmPrototype(Kernel::IAlgorithmProto& prototype) const override
{
prototype.addInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_Sampling, "Sampling frequency", Kernel::ParameterType_UInteger);
prototype.addInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_FilterMethod, "Filter method", Kernel::ParameterType_UInteger);
prototype.addInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_FilterType, "Filter type", Kernel::ParameterType_UInteger);
prototype.addInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_FilterOrder, "Filter order", Kernel::ParameterType_UInteger);
prototype.addInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_LowCutFrequency, "Low cut frequency",
Kernel::ParameterType_Float);
prototype.addInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_HighCutFrequency, "High cut frequency",
Kernel::ParameterType_Float);
prototype.addInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_BandPassRipple, "Band pass ripple", Kernel::ParameterType_Float);
prototype.addOutputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_OutputParameterId_Matrix, "Matrix", Kernel::ParameterType_Matrix);
prototype.addInputTrigger(OVP_Algorithm_ComputeTemporalFilterCoefs_InputTriggerId_Initialize, "Initialize");
prototype.addInputTrigger(OVP_Algorithm_ComputeTemporalFilterCoefs_InputTriggerId_ComputeCoefs, "Compute coefficients");
return true;
}
_IsDerivedFromClass_Final_(IAlgorithmDesc, OVP_ClassId_Algorithm_ComputeTemporalFilterCoefsDesc)
};
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyITPP
@@ -0,0 +1,90 @@
#include "ovpCDetectingMinMax.h"
#include <cmath>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
// ________________________________________________________________________________________________________________
//
bool CDetectingMinMax::initialize()
{
ip_signalMatrix.initialize(getInputParameter(OVP_Algorithm_DetectingMinMax_InputParameterId_SignalMatrix));
ip_sampling.initialize(getInputParameter(OVP_Algorithm_DetectingMinMax_InputParameterId_Sampling));
ip_timeWindowStart.initialize(getInputParameter(OVP_Algorithm_DetectingMinMax_InputParameterId_TimeWindowStart));
ip_timeWindowEnd.initialize(getInputParameter(OVP_Algorithm_DetectingMinMax_InputParameterId_TimeWindowEnd));
op_signalMatrix.initialize(getOutputParameter(OVP_Algorithm_DetectingMinMax_OutputParameterId_SignalMatrix));
return true;
}
bool CDetectingMinMax::uninitialize()
{
op_signalMatrix.uninitialize();
ip_timeWindowEnd.uninitialize();
ip_timeWindowStart.uninitialize();
ip_sampling.uninitialize();
ip_signalMatrix.uninitialize();
return true;
}
// ________________________________________________________________________________________________________________
//
bool CDetectingMinMax::process()
{
// signal input vars
CMatrix* iMatrix = ip_signalMatrix;
double* ibuffer = iMatrix->getBuffer();
// signal output vars
CMatrix* oMatrix = op_signalMatrix;
oMatrix->resize(1, 1);
double* oBuffer = oMatrix->getBuffer();
if (isInputTriggerActive(OVP_Algorithm_DetectingMinMax_InputTriggerId_Initialize)) { }
if (isInputTriggerActive(OVP_Algorithm_DetectingMinMax_InputTriggerId_DetectsMin))
{
// dimension of input signal biuffer
const size_t nChannel = ip_signalMatrix->getDimensionSize(0);
const size_t EpochSize = ip_signalMatrix->getDimensionSize(1);
// Must be changed
double minValue = 1E10;
for (size_t i = 0; i < nChannel; ++i)
{
for (size_t j = 0; j < EpochSize; ++j) { if (ibuffer[i * EpochSize + j] < minValue) { minValue = ibuffer[i * EpochSize + j]; } }
}
oBuffer[0] = minValue;
}
if (isInputTriggerActive(OVP_Algorithm_DetectingMinMax_InputTriggerId_DetectsMax))
{
// dimension of input signal biuffer
const size_t nChannels = ip_signalMatrix->getDimensionSize(0);
const size_t epochSize = ip_signalMatrix->getDimensionSize(1);
// Must be changed
double maxValue = -1E10;
for (size_t i = 0; i < nChannels; ++i)
{
const uint64_t start = uint64_t(floor(ip_timeWindowStart / 1000. * ip_sampling));
const uint64_t stop = uint64_t(floor(ip_timeWindowEnd / 1000. * ip_sampling));
for (uint64_t j = start; j < stop; ++j) { if (ibuffer[i * epochSize + j] > maxValue) { maxValue = ibuffer[i * epochSize + j]; } }
}
oBuffer[0] = maxValue;
}
return true;
}
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,70 @@
#pragma once
#include "../ovp_defines.h"
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
class CDetectingMinMax final : virtual public Toolkit::TAlgorithm<IAlgorithm>
{
public:
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool process() override;
_IsDerivedFromClass_Final_(Toolkit::TAlgorithm<IAlgorithm>, OVP_ClassId_Algorithm_DetectingMinMax)
protected:
Kernel::TParameterHandler<CMatrix*> ip_signalMatrix;
Kernel::TParameterHandler<uint64_t> ip_sampling;
Kernel::TParameterHandler<double> ip_timeWindowStart;
Kernel::TParameterHandler<double> ip_timeWindowEnd;
Kernel::TParameterHandler<CMatrix*> op_signalMatrix;
};
class CDetectingMinMaxDesc final : virtual public IAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return CString("Detects Min or Max of input buffer"); }
CString getAuthorName() const override { return CString("Guillaume Gibert"); }
CString getAuthorCompanyName() const override { return CString("INSERM/U821"); }
CString getShortDescription() const override { return CString(""); }
CString getDetailedDescription() const override { return CString(""); }
CString getCategory() const override { return CString("Algorithm/Signal processing/Basic"); }
CString getVersion() const override { return CString("1.0"); }
CIdentifier getCreatedClass() const override { return OVP_ClassId_Algorithm_DetectingMinMax; }
IPluginObject* create() override { return new CDetectingMinMax(); }
bool getAlgorithmPrototype(Kernel::IAlgorithmProto& prototype) const override
{
prototype.addInputParameter(OVP_Algorithm_DetectingMinMax_InputParameterId_SignalMatrix, "Signal input matrix", Kernel::ParameterType_Matrix);
prototype.addInputParameter(OVP_Algorithm_DetectingMinMax_InputParameterId_TimeWindowStart, "Time window start", Kernel::ParameterType_Float);
prototype.addInputParameter(OVP_Algorithm_DetectingMinMax_InputParameterId_TimeWindowEnd, "Time window end", Kernel::ParameterType_Float);
prototype.addInputParameter(OVP_Algorithm_DetectingMinMax_InputParameterId_Sampling, "Sampling frequency", Kernel::ParameterType_UInteger);
prototype.addOutputParameter(OVP_Algorithm_DetectingMinMax_OutputParameterId_SignalMatrix, "Signal output matrix", Kernel::ParameterType_Matrix);
prototype.addInputTrigger(OVP_Algorithm_DetectingMinMax_InputTriggerId_Initialize, "Initialize");
prototype.addInputTrigger(OVP_Algorithm_DetectingMinMax_InputTriggerId_DetectsMin, "Detects min");
prototype.addInputTrigger(OVP_Algorithm_DetectingMinMax_InputTriggerId_DetectsMax, "Detects max");
return true;
}
_IsDerivedFromClass_Final_(IAlgorithmDesc, OVP_ClassId_Algorithm_DetectingMinMaxDesc)
};
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,162 @@
#include "ovpCDownsampling.h"
#include <cmath> //floor, ceil
#include <cstdlib>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
// ________________________________________________________________________________________________________________
//
bool CDownsampling::initialize()
{
ip_sampling.initialize(getInputParameter(OVP_Algorithm_Downsampling_InputParameterId_Sampling));
ip_newSampling.initialize(getInputParameter(OVP_Algorithm_Downsampling_InputParameterId_NewSampling));
ip_signalMatrix.initialize(getInputParameter(OVP_Algorithm_Downsampling_InputParameterId_SignalMatrix));
op_signalMatrix.initialize(getOutputParameter(OVP_Algorithm_Downsampling_OutputParameterId_SignalMatrix));
m_lastValueOrigSignal = nullptr;
m_first = true;
return true;
}
bool CDownsampling::uninitialize()
{
free(m_lastValueOrigSignal);
m_lastValueOrigSignal = nullptr;
op_signalMatrix.uninitialize();
ip_signalMatrix.uninitialize();
ip_newSampling.uninitialize();
ip_sampling.uninitialize();
return true;
}
// ________________________________________________________________________________________________________________
//
bool CDownsampling::process()
{
size_t oEpochSize, indexBegOutput;
double blocDuration, endTime;
// signal input vars
CMatrix* iMatrix = ip_signalMatrix;
double* iBuffer = iMatrix->getBuffer();
const size_t nChannels = ip_signalMatrix->getDimensionSize(0);
const size_t iEpochSize = ip_signalMatrix->getDimensionSize(1);
const double iSampling = double(ip_sampling);
const double oSampling = double(ip_newSampling);
// signal output vars
CMatrix* oMatrix = op_signalMatrix;
oMatrix->setDimensionCount(ip_signalMatrix->getDimensionCount());
if ((m_first) || (isInputTriggerActive(OVP_Algorithm_Downsampling_InputTriggerId_Resample)))
{
oEpochSize = size_t(floor(iEpochSize * (oSampling / iSampling)));
blocDuration = double(iEpochSize - 1) / iSampling;
endTime = blocDuration;
m_lastTimeOrigSignal = 0;
m_lastTimeNewSignal = 0;
if (m_first)
{
m_lastValueOrigSignal = static_cast<double*>(calloc(nChannels, sizeof(double)));
if (m_lastValueOrigSignal == nullptr) { this->getLogManager() << Kernel::LogLevel_Error << "Memory allocation : last values of original signal.\n"; }
}
}
else
{
blocDuration = double(iEpochSize) / iSampling;
endTime = m_lastTimeOrigSignal + blocDuration;
const double timePassed = endTime - m_lastTimeNewSignal;
oEpochSize = size_t(floor(timePassed * oSampling));
}
if (oEpochSize == 0)
{
this->getLogManager() << Kernel::LogLevel_Error << "Output epoch size is 0. Increase input epoch size.\n";
return false;
}
// this->getLogManager() << Kernel::LogLevel_Info << "blockDur " << blocDuration << " et " << endTime << " lt " << m_lastTimeNewSignal << " td " << timeDiff << " dim " << oMatrixDimensionSizeEpoch << "\n";
oMatrix->setDimensionSize(0, nChannels);
oMatrix->setDimensionSize(1, oEpochSize);
double* oBuffer = oMatrix->getBuffer();
if (isInputTriggerActive(OVP_Algorithm_Downsampling_InputTriggerId_Initialize)) { }
if ((isInputTriggerActive(OVP_Algorithm_Downsampling_InputTriggerId_ResampleWithHistoric))
|| (isInputTriggerActive(OVP_Algorithm_Downsampling_InputTriggerId_Resample)))
{
double countNew = 0, prev;
int indexInput;
for (size_t i = 0; i < nChannels; ++i)
{
double countOrig = m_lastTimeOrigSignal;
countNew = m_lastTimeNewSignal + (1.0 / double(ip_newSampling));
double timePrev = m_lastTimeOrigSignal;
if ((m_first) || (isInputTriggerActive(OVP_Algorithm_Downsampling_InputTriggerId_Resample)))
{
prev = iBuffer[i * iEpochSize];
oBuffer[i * oEpochSize] = prev;
indexBegOutput = 1;
indexInput = 0;
}
else
{
prev = m_lastValueOrigSignal[i];
indexBegOutput = 0;
indexInput = -1;
}
for (uint64_t j = indexBegOutput; j < oEpochSize; ++j)
{
while ((indexInput < int(iEpochSize)) && (countOrig < countNew))
{
countOrig += 1.0 / double(ip_sampling);
indexInput++;
}
if (indexInput == -1) { this->getLogManager() << Kernel::LogLevel_Warning << "Downsampling problem : index value=-1\n"; }
else if (indexInput < int(iEpochSize))
{
const double cur = iBuffer[(i * iEpochSize) + indexInput];
oBuffer[(i * oEpochSize) + j] = ((cur - prev) * (countNew - timePrev) / (countOrig - timePrev)) + prev;
prev = cur;
timePrev = countOrig;
}
else
{
this->getLogManager() << Kernel::LogLevel_Warning << "Downsampling problem : sample #" << j << "/" << oEpochSize <<
" time original signal=" << countOrig << " time new signal=" << countNew << " new signal sample #" << indexInput <<
" /" << iEpochSize << "\n";
j = oEpochSize;
}
countNew += 1.0 / oSampling;
}
if (oEpochSize > 0) { m_lastValueOrigSignal[i] = iBuffer[(i * iEpochSize) + iEpochSize - 1]; }
}
if (oEpochSize > 0)
{
m_lastTimeNewSignal = countNew - (1.0 / oSampling);
m_lastTimeOrigSignal = endTime;
}
if (m_first) { m_first = false; }
}
return true;
}
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,69 @@
#pragma once
#include "../ovp_defines.h"
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
class CDownsampling final : virtual public Toolkit::TAlgorithm<IAlgorithm>
{
public:
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool process() override;
_IsDerivedFromClass_Final_(Toolkit::TAlgorithm<IAlgorithm>, OVP_ClassId_Algorithm_Downsampling)
protected:
Kernel::TParameterHandler<uint64_t> ip_sampling;
Kernel::TParameterHandler<uint64_t> ip_newSampling;
Kernel::TParameterHandler<CMatrix*> ip_signalMatrix;
Kernel::TParameterHandler<CMatrix*> op_signalMatrix;
double* m_lastValueOrigSignal = nullptr;
double m_lastTimeOrigSignal = 0;
double m_lastTimeNewSignal = 0;
bool m_first = false;
};
class CDownsamplingDesc final : virtual public IAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return CString("Downsampling"); }
CString getAuthorName() const override { return CString("G. Gibert - E. Maby - P.E. Aguera"); }
CString getAuthorCompanyName() const override { return CString("INSERM/U821"); }
CString getShortDescription() const override { return CString("Downsamples input signal."); }
CString getDetailedDescription() const override { return CString("Downsamples input signal to the new sampling rate chosen by user."); }
CString getCategory() const override { return CString("Signal processing Gpl/Basic"); }
CString getVersion() const override { return CString("1.1"); }
CIdentifier getCreatedClass() const override { return OVP_ClassId_Algorithm_Downsampling; }
IPluginObject* create() override { return new CDownsampling(); }
bool getAlgorithmPrototype(Kernel::IAlgorithmProto& prototype) const override
{
prototype.addInputParameter(OVP_Algorithm_Downsampling_InputParameterId_Sampling, "Sampling frequency", Kernel::ParameterType_UInteger);
prototype.addInputParameter(OVP_Algorithm_Downsampling_InputParameterId_NewSampling, "New sampling frequency", Kernel::ParameterType_UInteger);
prototype.addInputParameter(OVP_Algorithm_Downsampling_InputParameterId_SignalMatrix, "Signal matrix", Kernel::ParameterType_Matrix);
prototype.addOutputParameter(OVP_Algorithm_Downsampling_OutputParameterId_SignalMatrix, "Signal matrix", Kernel::ParameterType_Matrix);
prototype.addInputTrigger(OVP_Algorithm_Downsampling_InputTriggerId_Initialize, "Initialize");
prototype.addInputTrigger(OVP_Algorithm_Downsampling_InputTriggerId_Resample, "Resample");
prototype.addInputTrigger(OVP_Algorithm_Downsampling_InputTriggerId_ResampleWithHistoric, "Resample with historic");
return true;
}
_IsDerivedFromClass_Final_(IAlgorithmDesc, OVP_ClassId_Algorithm_DownsamplingDesc)
};
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,307 @@
#if defined TARGET_HAS_ThirdPartyITPP
#include "ovpCBoxAlgorithmCSPSpatialFilterTrainer.h"
#include <complex>
#include <cstdio>
#include <map>
#include <math.h>
#include <iostream>
#include <itpp/base/algebra/eigen.h>
#include <itpp/base/algebra/inv.h>
#include <itpp/stat/misc_stat.h>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
// Taken from http://techlogbook.wordpress.com/2009/08/12/adding-generalized-eigenvalue-functions-to-it
// http://techlogbook.wordpress.com/2009/08/12/calling-lapack-functions-from-c-codes
// http://sourceforge.net/projects/itpp/forums/forum/115656/topic/3363490?message=7557038
//
// http://icl.cs.utk.edu/projectsfiles/f2j/javadoc/org/netlib/lapack/DSYGV.html
// http://www.lassp.cornell.edu/sethna/GeneDynamics/NetworkCodeDocumentation/lapack_8h.html#a17
namespace {
extern "C" {
// This symbol comes from LAPACK
/*
void zggev_(char *jobvl, char *jobvr, int *n, std::complex<double> *a,
int *lda, std::complex<double> *b, int *ldb, std::complex<double> *alpha,
std::complex<double> *beta, std::complex<double> *vl,
int *ldvl, std::complex<double> *vr, int *ldvr,
std::complex<double> *work, int *lwork, double *rwork, int *info);
*/
int dsygv_(int* itype, char* jobz, char* uplo, int* n, double* a,
int* lda, double* b, int* ldb, double* w, double* work, int* lwork, int* info);
}
} // namespace
namespace itppextcsp {
itpp::mat convert(const CMatrix& matrix)
{
itpp::mat res(matrix.getDimensionSize(1), matrix.getDimensionSize(0));
if (matrix.getBufferElementCount() != 0) { memcpy(res._data(), matrix.getBuffer(), matrix.getBufferElementCount() * sizeof(double)); }
return res.transpose();
}
itpp::mat cov(const itpp::mat& matrix)
{
itpp::mat centered = repmat(sum(matrix, 2), 1, matrix.cols(), false);
centered = centered / double(matrix.cols());
centered = matrix - centered;
itpp::mat res = centered * centered.transpose();
res = res / double(matrix.cols() - 1);
res = res / trace(res);
return res;
}
} // namespace itppextcsp
bool CBoxAlgorithmCSPSpatialFilterTrainer::initialize()
{
m_stimDecoder = new Toolkit::TStimulationDecoder<CBoxAlgorithmCSPSpatialFilterTrainer>();
m_stimDecoder->initialize(*this, 0);
m_signalDecoderCondition1 = new Toolkit::TSignalDecoder<CBoxAlgorithmCSPSpatialFilterTrainer>();
m_signalDecoderCondition1->initialize(*this, 1);
m_signalDecoderCondition2 = new Toolkit::TSignalDecoder<CBoxAlgorithmCSPSpatialFilterTrainer>();
m_signalDecoderCondition2->initialize(*this, 2);
m_encoder.initialize(*this, 0);
m_stimID = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
m_spatialFilterConfigFilename = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1);
m_filterDimension = uint64_t(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2));
m_saveAsBoxConfig = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 3);
return true;
}
bool CBoxAlgorithmCSPSpatialFilterTrainer::uninitialize()
{
m_signalDecoderCondition1->uninitialize();
delete m_signalDecoderCondition1;
m_signalDecoderCondition2->uninitialize();
delete m_signalDecoderCondition2;
m_stimDecoder->uninitialize();
delete m_stimDecoder;
m_encoder.uninitialize();
return true;
}
bool CBoxAlgorithmCSPSpatialFilterTrainer::processInput(const size_t /*index*/)
{
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
return true;
}
bool CBoxAlgorithmCSPSpatialFilterTrainer::process()
{
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
bool shouldTrain = false;
uint64_t date = 0, startTime = 0, endTime = 0;
for (size_t i = 0; i < boxContext.getInputChunkCount(0); ++i)
{
m_stimDecoder->decode(i);
if (m_stimDecoder->isHeaderReceived())
{
m_encoder.encodeHeader();
boxContext.markOutputAsReadyToSend(0, boxContext.getInputChunkStartTime(0, i), boxContext.getInputChunkEndTime(0, i));
}
if (m_stimDecoder->isBufferReceived())
{
Kernel::TParameterHandler<IStimulationSet*> op_stimSet(m_stimDecoder->getOutputStimulationSet());
for (size_t j = 0; j < op_stimSet->getStimulationCount(); ++j) { shouldTrain |= (op_stimSet->getStimulationIdentifier(j) == m_stimID); }
if (shouldTrain)
{
date = op_stimSet->getStimulationDate(op_stimSet->getStimulationCount() - 1);
startTime = boxContext.getInputChunkStartTime(0, i);
endTime = boxContext.getInputChunkEndTime(0, i);
}
}
if (m_stimDecoder->isEndReceived()) { m_encoder.encodeEnd(); }
boxContext.markInputAsDeprecated(0, i);
}
if (shouldTrain)
{
this->getLogManager() << Kernel::LogLevel_Info << "Received train stimulation - be patient\n";
this->getLogManager() << Kernel::LogLevel_Trace << "Estimating cov for condition 1...\n";
itpp::mat covarianceMatrixCondition1;
int nCondition1Trials = 0;
int condition1ChunkSize = 0;
int condition2ChunkSize = 0;
for (size_t i = 0; i < boxContext.getInputChunkCount(1); ++i)
{
m_signalDecoderCondition1->decode(i);
if (m_signalDecoderCondition1->isHeaderReceived())
{
Kernel::TParameterHandler<CMatrix*> ip_matrix(m_signalDecoderCondition1->getOutputMatrix());
covarianceMatrixCondition1.set_size(ip_matrix->getDimensionSize(0), ip_matrix->getDimensionSize(0));
covarianceMatrixCondition1.zeros();
condition1ChunkSize = ip_matrix->getDimensionSize(1);
this->getLogManager() << Kernel::LogLevel_Debug << "Cov matrix size for condition 1 is [" << ip_matrix->getDimensionSize(0) << "x"
<< ip_matrix->getDimensionSize(0) << "], chunk size is " << condition1ChunkSize << " samples\n";
}
if (m_signalDecoderCondition1->isBufferReceived())
{
Kernel::TParameterHandler<CMatrix*> ip_matrix(m_signalDecoderCondition1->getOutputMatrix());
itpp::mat matrix = itppextcsp::convert(*ip_matrix);
covarianceMatrixCondition1 += itppextcsp::cov(matrix);
nCondition1Trials++;
}
if (m_signalDecoderCondition1->isEndReceived()) { }
boxContext.markInputAsDeprecated(1, i);
}
covarianceMatrixCondition1 = covarianceMatrixCondition1 / double(nCondition1Trials);
this->getLogManager() << Kernel::LogLevel_Trace << "Number of chunks for condition 1: " << nCondition1Trials << "\n";
this->getLogManager() << Kernel::LogLevel_Trace << "Estimating cov for condition 2...\n";
itpp::mat covarianceMatrixCondition2;
int nCondition2Trials = 0;
for (size_t i = 0; i < boxContext.getInputChunkCount(2); ++i)
{
m_signalDecoderCondition2->decode(i);
if (m_signalDecoderCondition2->isHeaderReceived())
{
Kernel::TParameterHandler<CMatrix*> ip_matrix(m_signalDecoderCondition2->getOutputMatrix());
covarianceMatrixCondition2.set_size(ip_matrix->getDimensionSize(0), ip_matrix->getDimensionSize(0));
covarianceMatrixCondition2.zeros();
condition2ChunkSize = ip_matrix->getDimensionSize(1);
this->getLogManager() << Kernel::LogLevel_Debug << "Cov matrix size for condition 2 is [" << ip_matrix->getDimensionSize(0) << "x"
<< ip_matrix->getDimensionSize(0) << "], chunk size is " << condition2ChunkSize << " samples\n";
}
if (m_signalDecoderCondition2->isBufferReceived())
{
Kernel::TParameterHandler<CMatrix*> ip_matrix(m_signalDecoderCondition2->getOutputMatrix());
itpp::mat matrix = itppextcsp::convert(*ip_matrix);
covarianceMatrixCondition2 += itppextcsp::cov(matrix);
nCondition2Trials++;
}
if (m_signalDecoderCondition2->isEndReceived()) { }
boxContext.markInputAsDeprecated(2, i);
}
covarianceMatrixCondition2 = covarianceMatrixCondition2 / double(nCondition2Trials);
if (covarianceMatrixCondition1.cols() != covarianceMatrixCondition2.cols())
{
this->getLogManager() << Kernel::LogLevel_Error << "The two inputs do not seem to have the same number of channels, "
<< covarianceMatrixCondition1.cols() << " vs " << covarianceMatrixCondition2.cols() << "\n";
return false;
}
this->getLogManager() << Kernel::LogLevel_Info << "Data covariance dims are [" << covarianceMatrixCondition1.rows() << "x" << covarianceMatrixCondition1.cols()
<< "]. Number of samples per condition : \n";
this->getLogManager() << Kernel::LogLevel_Info << " cond1 = " << nCondition1Trials << " chunks, sized " << condition1ChunkSize << " -> "
<< nCondition1Trials * condition1ChunkSize << " samples\n";
this->getLogManager() << Kernel::LogLevel_Info << " cond2 = " << nCondition2Trials << " chunks, sized " << condition2ChunkSize << " -> "
<< nCondition2Trials * condition2ChunkSize << " samples\n";
if (nCondition1Trials == 0 || nCondition2Trials == 0)
{
this->getLogManager() << Kernel::LogLevel_Error << "No signal received... Can't continue\n";
return true;
}
this->getLogManager() << Kernel::LogLevel_Trace << "Computing eigen vector decomposition...\n";
itpp::cmat eigenVector;
itpp::cvec eigenValue;
size_t nChannel = covarianceMatrixCondition1.rows();
if (eig(inv(covarianceMatrixCondition2) * covarianceMatrixCondition1, eigenValue, eigenVector))
{
std::map<double, itpp::vec> vEigenVector;
for (size_t i = 0; i < nChannel; ++i)
{
itpp::cvec v = eigenVector.get_col(i);
vEigenVector[itpp::real(eigenValue)[i]] = itpp::real(v);
}
// Collect the output vectors here
CMatrix outputVectors(m_filterDimension, nChannel);
size_t steps = 0, cnt = 0;
this->getLogManager() << Kernel::LogLevel_Debug << "lowest eigenvalues: " << "\n";
for (auto it = vEigenVector.begin(); it != vEigenVector.end() && steps < ceil(m_filterDimension / 2.0); ++it, steps++)
{
this->getLogManager() << Kernel::LogLevel_Debug << it->first << ", ";
for (size_t j = 0; j < nChannel; ++j) { outputVectors.getBuffer()[cnt++] = it->second[j]; }
}
this->getLogManager() << Kernel::LogLevel_Debug << "\n";
this->getLogManager() << Kernel::LogLevel_Debug << "highest eigenvalues: " << "\n";
steps = 0;
for (auto it = vEigenVector.rbegin(); it != vEigenVector.rend() && steps < floor(m_filterDimension / 2.0); ++it, steps++)
{
this->getLogManager() << Kernel::LogLevel_Debug << it->first << ", ";
for (size_t j = 0; j < nChannel; ++j) { outputVectors.getBuffer()[cnt++] = it->second[j]; }
}
this->getLogManager() << Kernel::LogLevel_Debug << "\n";
if (m_saveAsBoxConfig)
{
FILE* file = fopen(m_spatialFilterConfigFilename.toASCIIString(), "wb");
if (!file)
{
this->getLogManager() << Kernel::LogLevel_Error << "The file [" << m_spatialFilterConfigFilename <<
"] could not be opened for writing...\n";
return false;
}
fprintf(file, "<OpenViBE-SettingsOverride>\n");
fprintf(file, "\t<SettingValue>");
cnt = 0;
for (size_t i = 0; i < m_filterDimension; ++i)
{
for (size_t j = 0; j < nChannel; ++j) { fprintf(file, "%e ", outputVectors.getBuffer()[cnt++]); }
}
fprintf(file, "</SettingValue>\n");
fprintf(file, "\t<SettingValue>%d</SettingValue>\n", m_filterDimension);
fprintf(file, "\t<SettingValue>%d</SettingValue>\n", nChannel);
fprintf(file, "\t<SettingValue></SettingValue>\n");
fprintf(file, "</OpenViBE-SettingsOverride>\n");
fclose(file);
}
else
{
if (!Toolkit::Matrix::saveToTextFile(outputVectors, m_spatialFilterConfigFilename))
{
this->getLogManager() << Kernel::LogLevel_Error << "Unable to save to [" << m_spatialFilterConfigFilename << "\n";
return false;
}
}
}
else
{
this->getLogManager() << Kernel::LogLevel_ImportantWarning << "Eigen vector decomposition failed...\n";
return true;
}
this->getLogManager() << Kernel::LogLevel_Info << "CSP Spatial filter trained successfully.\n";
m_encoder.getInputStimulationSet()->clear();
m_encoder.getInputStimulationSet()->appendStimulation(OVTK_StimulationId_TrainCompleted, date, 0);
m_encoder.encodeBuffer();
boxContext.markOutputAsReadyToSend(0, startTime, endTime);
}
return true;
}
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyITPP
@@ -0,0 +1,88 @@
// @copyright notice: Possibly due to dependencies, this box used to be GPL before upgrade to AGPL3
#pragma once
#include "../ovp_defines.h"
#if defined TARGET_HAS_ThirdPartyITPP
#include "../ovp_defines.h"
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
class CBoxAlgorithmCSPSpatialFilterTrainer final : public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
{
public:
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool processInput(const size_t index) override;
bool process() override;
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_CSPSpatialFilterTrainer)
protected:
Toolkit::TStimulationDecoder<CBoxAlgorithmCSPSpatialFilterTrainer>* m_stimDecoder = nullptr;
Toolkit::TSignalDecoder<CBoxAlgorithmCSPSpatialFilterTrainer>* m_signalDecoderCondition1 = nullptr;
Toolkit::TSignalDecoder<CBoxAlgorithmCSPSpatialFilterTrainer>* m_signalDecoderCondition2 = nullptr;
Toolkit::TStimulationEncoder<CBoxAlgorithmCSPSpatialFilterTrainer> m_encoder;
uint64_t m_stimID = 0;
CString m_spatialFilterConfigFilename;
size_t m_filterDimension = 0;
bool m_saveAsBoxConfig = false;
};
class CBoxAlgorithmCSPSpatialFilterTrainerDesc final : public IBoxAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return CString("CSP Spatial Filter Trainer"); }
CString getAuthorName() const override { return CString("Dieter Devlaminck"); }
CString getAuthorCompanyName() const override { return CString("Ghent University"); }
CString getShortDescription() const override { return CString("Computes spatial filter coeffcients according to the Common Spatial Pattern algorithm."); }
CString getDetailedDescription() const override
{
return CString(
"The CSP algortihm increases the signal variance for one condition while minimizing the variance for the other condition.");
}
CString getCategory() const override { return CString("Signal processing/Filtering"); }
CString getVersion() const override { return CString("1.0"); }
CString getStockItemName() const override { return CString(""); }
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_CSPSpatialFilterTrainer; }
IPluginObject* create() override { return new CBoxAlgorithmCSPSpatialFilterTrainer; }
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
{
prototype.addInput("Stimulations", OV_TypeId_Stimulations);
prototype.addInput("Signal condition 1", OV_TypeId_Signal);
prototype.addInput("Signal condition 2", OV_TypeId_Signal);
prototype.addSetting("Train Trigger", OV_TypeId_Stimulation, "OVTK_GDF_End_Of_Session");
prototype.addSetting("Spatial filter configuration", OV_TypeId_Filename, "");
prototype.addSetting("Filter dimension", OV_TypeId_Integer, "2");
prototype.addSetting("Save as box config", OV_TypeId_Boolean, "true");
prototype.addOutput("Train-completed Flag", OV_TypeId_Stimulations);
return true;
}
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_CSPSpatialFilterTrainerDesc)
};
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyITPP
@@ -0,0 +1,68 @@
#include "ovpCBoxAlgorithmSynchro.h"
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
bool CBoxAlgorithmSynchro::initialize()
{
m_inputChannel.initialize(this);
m_outputChannel.initialize(this);
m_stimulationReceivedStart = false;
return true;
}
bool CBoxAlgorithmSynchro::uninitialize()
{
m_inputChannel.uninitialize();
m_outputChannel.uninitialize();
return true;
}
bool CBoxAlgorithmSynchro::processInput(const size_t /*index*/)
{
this->getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
return true;
}
bool CBoxAlgorithmSynchro::process()
{
// FIXME is it necessary to keep next line uncomment ?
//IBoxIO& boxContext = this->getDynamicBoxContext();
if (m_inputChannel.isWorking())
{
// process stimulations
for (size_t index = 0, nb = m_inputChannel.getNStimulationBuffers(); index < nb; ++index)
{
uint64_t startTime, endTime;
IStimulationSet* stimset = m_inputChannel.getStimulation(startTime, endTime, index);
if (!stimset) { break; }
m_outputChannel.sendStimulation(stimset, startTime, endTime);
}
// process signal
for (size_t index = 0, nb = m_inputChannel.getNSignalBuffers(); index < nb; ++index)
{
uint64_t startTime, endTime;
CMatrix* matrix = m_inputChannel.getSignal(startTime, endTime, index++);
if (!matrix) { break; }
m_outputChannel.sendSignal(matrix, startTime, endTime);
}
}
else if (m_inputChannel.hasSynchro())
{
m_outputChannel.processSynchroSignal(m_inputChannel.getStimulationPosition(), m_inputChannel.getSignalPosition());
m_inputChannel.startWorking();
}
else if (m_inputChannel.hasHeader()) { m_inputChannel.waitForSynchro(); }
else if (m_inputChannel.waitForSignalHeader()) { m_outputChannel.sendHeader(m_inputChannel.getSamplingRate(), m_inputChannel.getMatrixPtr()); }
return true;
}
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,72 @@
#pragma once
#include "../ovp_defines.h"
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
#include "ovpCInputChannel.h"
#include "ovpCOutputChannel.h"
#include <string>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
class CBoxAlgorithmSynchro final : public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
{
public:
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool processInput(const size_t index) override;
bool process() override;
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_Synchro)
protected:
//Intern ressources
bool m_stimulationReceivedStart = false;
// new
CInputChannel m_inputChannel;
COutputChannel m_outputChannel;
};
class CBoxAlgorithmSynchroDesc final : public IBoxAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return CString("Stream Synchronization"); }
CString getAuthorName() const override { return CString("Gelu Ionescu & Matthieu Goyat"); }
CString getAuthorCompanyName() const override { return CString("GIPSA-lab"); }
CString getShortDescription() const override { return CString("Synchronize two acquisition servers"); }
CString getDetailedDescription() const override { return CString(""); }
CString getCategory() const override { return CString("Signal processing/Basic"); }
CString getVersion() const override { return CString("1.0"); }
CString getStockItemName() const override { return CString("gtk-missing-image"); }
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_Synchro; }
IPluginObject* create() override { return new CBoxAlgorithmSynchro; }
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
{
prototype.addInput("Input signal", OV_TypeId_Signal);
prototype.addInput("Input stimulation", OV_TypeId_Stimulations);
prototype.addOutput("Output signal", OV_TypeId_Signal);
prototype.addOutput("Output stimulation", OV_TypeId_Stimulations);
prototype.addSetting("Synchronisation stimulation", OV_TypeId_Stimulation, "OVTK_StimulationId_ExperimentStart");
// prototype.addFlag (Kernel::BoxFlag_CanModifyInput);
return true;
}
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_SynchroDesc)
};
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,360 @@
#include "ovpCBoxAlgorithmUnivariateStatistics.h"
#include "../algorithms/ovpCAlgorithmUnivariateStatistics.h"
#include <iostream>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
bool CBoxUnivariateStatistic::initialize()
{
//initialise en/decoder function of the input type
this->getStaticBoxContext().getInputType(0, m_inputTypeID);
#if 0 // this is not needed as you know you always habe signal
if(m_inputTypeID==OV_TypeId_StreamedMatrix)
{
m_decoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StreamedMatrixDecoder));
m_meanEncoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StreamedMatrixEncoder));
m_varianceEncoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StreamedMatrixEncoder));
m_rangeEncoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StreamedMatrixEncoder));
m_medianEncoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StreamedMatrixEncoder));
m_iqrEncoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StreamedMatrixEncoder));
m_percentileEncoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StreamedMatrixEncoder));
}
else if(m_inputTypeID==OV_TypeId_FeatureVector)
{
m_decoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_FeatureVectorDecoder));
m_meanEncoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_FeatureVectorEncoder));
m_varianceEncoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_FeatureVectorEncoder));
m_rangeEncoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_FeatureVectorEncoder));
m_medianEncoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_FeatureVectorEncoder));
m_iqrEncoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_FeatureVectorEncoder));
m_percentileEncoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_FeatureVectorEncoder));
}
else if(m_inputTypeID==OV_TypeId_Signal)
{
#endif
m_decoder = &getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_SignalDecoder));
m_meanEncoder = &getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_SignalEncoder));
m_varianceEncoder = &getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_SignalEncoder));
m_rangeEncoder = &getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_SignalEncoder));
m_medianEncoder = &getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_SignalEncoder));
m_iqrEncoder = &getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_SignalEncoder));
m_percentileEncoder = &getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_SignalEncoder));
#if 0 // this is not needed as you know you always habe signal
}
else if(m_inputTypeID==OV_TypeId_Spectrum)
{
m_decoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_SpectrumDecoder));
m_meanEncoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_SpectrumEncoder));
m_varianceEncoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_SpectrumEncoder));
m_rangeEncoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_SpectrumEncoder));
m_medianEncoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_SpectrumEncoder));
m_iqrEncoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_SpectrumEncoder));
m_percentileEncoder=&getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_SpectrumEncoder));
}
else
{
this->getLogManager() << Kernel::LogLevel_Debug << "Input type is not planned : no matrix base. This box can't work, so it is disabled\n";
return false;
}
#endif
m_decoder->initialize();
m_meanEncoder->initialize();
m_varianceEncoder->initialize();
m_rangeEncoder->initialize();
m_medianEncoder->initialize();
m_iqrEncoder->initialize();
m_percentileEncoder->initialize();
//initialize the real algorithm this box encapsulate
m_matrixStatistic = &getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_ClassId_AlgoUnivariateStatistic));
m_matrixStatistic->initialize();
//initialize all handlers
m_matrixStatistic->getInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_Matrix)->setReferenceTarget(
m_decoder->getOutputParameter(OVP_GD_Algorithm_StreamedMatrixDecoder_OutputParameterId_Matrix));
m_meanEncoder->getInputParameter(OVP_GD_Algorithm_StreamedMatrixEncoder_InputParameterId_Matrix)->setReferenceTarget(
m_matrixStatistic->getOutputParameter(OVP_Algorithm_UnivariateStatistic_OutputParameterId_Mean));
m_varianceEncoder->getInputParameter(OVP_GD_Algorithm_StreamedMatrixEncoder_InputParameterId_Matrix)->setReferenceTarget(
m_matrixStatistic->getOutputParameter(OVP_Algorithm_UnivariateStatistic_OutputParameterId_Var));
m_rangeEncoder->getInputParameter(OVP_GD_Algorithm_StreamedMatrixEncoder_InputParameterId_Matrix)->setReferenceTarget(
m_matrixStatistic->getOutputParameter(OVP_Algorithm_UnivariateStatistic_OutputParameterId_Range));
m_medianEncoder->getInputParameter(OVP_GD_Algorithm_StreamedMatrixEncoder_InputParameterId_Matrix)->setReferenceTarget(
m_matrixStatistic->getOutputParameter(OVP_Algorithm_UnivariateStatistic_OutputParameterId_Med));
m_iqrEncoder->getInputParameter(OVP_GD_Algorithm_StreamedMatrixEncoder_InputParameterId_Matrix)->setReferenceTarget(
m_matrixStatistic->getOutputParameter(OVP_Algorithm_UnivariateStatistic_OutputParameterId_IQR));
m_percentileEncoder->getInputParameter(OVP_GD_Algorithm_StreamedMatrixEncoder_InputParameterId_Matrix)->setReferenceTarget(
m_matrixStatistic->getOutputParameter(OVP_Algorithm_UnivariateStatistic_OutputParameterId_Percent));
#if 0 // this is not needed as you know you always habe signal
/// specific connection for what is different of matrix base
if(m_inputTypeID==OV_TypeId_Signal)
{
#endif
op_sampling.initialize(m_decoder->getOutputParameter(OVP_GD_Algorithm_SignalDecoder_OutputParameterId_Sampling));
m_meanEncoder->getInputParameter(OVP_GD_Algorithm_SignalEncoder_InputParameterId_Sampling)->setReferenceTarget(
m_decoder->getOutputParameter(OVP_GD_Algorithm_SignalDecoder_OutputParameterId_Sampling));
m_varianceEncoder->getInputParameter(OVP_GD_Algorithm_SignalEncoder_InputParameterId_Sampling)->setReferenceTarget(
m_decoder->getOutputParameter(OVP_GD_Algorithm_SignalDecoder_OutputParameterId_Sampling));
m_rangeEncoder->getInputParameter(OVP_GD_Algorithm_SignalEncoder_InputParameterId_Sampling)->setReferenceTarget(
m_decoder->getOutputParameter(OVP_GD_Algorithm_SignalDecoder_OutputParameterId_Sampling));
m_medianEncoder->getInputParameter(OVP_GD_Algorithm_SignalEncoder_InputParameterId_Sampling)->setReferenceTarget(
m_decoder->getOutputParameter(OVP_GD_Algorithm_SignalDecoder_OutputParameterId_Sampling));
m_iqrEncoder->getInputParameter(OVP_GD_Algorithm_SignalEncoder_InputParameterId_Sampling)->setReferenceTarget(
m_decoder->getOutputParameter(OVP_GD_Algorithm_SignalDecoder_OutputParameterId_Sampling));
m_percentileEncoder->getInputParameter(OVP_GD_Algorithm_SignalEncoder_InputParameterId_Sampling)->setReferenceTarget(
m_decoder->getOutputParameter(OVP_GD_Algorithm_SignalDecoder_OutputParameterId_Sampling));
#if 0 // this is not needed as you know you always habe signal
}
else if(m_inputTypeID==OV_TypeId_Spectrum)
{
m_meanEncoder->getInputParameter(OVP_GD_Algorithm_SpectrumEncoder_InputParameterId_MinMaxFrequencyBands)->setReferenceTarget(m_decoder->getOutputParameter(OVP_GD_Algorithm_SpectrumDecoder_OutputParameterId_MinMaxFrequencyBands));
m_varianceEncoder->getInputParameter(OVP_GD_Algorithm_SpectrumEncoder_InputParameterId_MinMaxFrequencyBands)->setReferenceTarget(m_decoder->getOutputParameter(OVP_GD_Algorithm_SpectrumDecoder_OutputParameterId_MinMaxFrequencyBands));
m_rangeEncoder->getInputParameter(OVP_GD_Algorithm_SpectrumEncoder_InputParameterId_MinMaxFrequencyBands)->setReferenceTarget(m_decoder->getOutputParameter(OVP_GD_Algorithm_SpectrumDecoder_OutputParameterId_MinMaxFrequencyBands));
m_medianEncoder->getInputParameter(OVP_GD_Algorithm_SpectrumEncoder_InputParameterId_MinMaxFrequencyBands)->setReferenceTarget(m_decoder->getOutputParameter(OVP_GD_Algorithm_SpectrumDecoder_OutputParameterId_MinMaxFrequencyBands));
m_iqrEncoder->getInputParameter(OVP_GD_Algorithm_SpectrumEncoder_InputParameterId_MinMaxFrequencyBands)->setReferenceTarget(m_decoder->getOutputParameter(OVP_GD_Algorithm_SpectrumDecoder_OutputParameterId_MinMaxFrequencyBands));
m_percentileEncoder->getInputParameter(OVP_GD_Algorithm_SpectrumEncoder_InputParameterId_MinMaxFrequencyBands)->setReferenceTarget(m_decoder->getOutputParameter(OVP_GD_Algorithm_SpectrumDecoder_OutputParameterId_MinMaxFrequencyBands));
}
#endif
op_compression.initialize(m_matrixStatistic->getOutputParameter(OVP_Algorithm_UnivariateStatistic_OutputParameterId_Compression));
ip_isMeanActive.initialize(m_matrixStatistic->getInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_MeanActive));
ip_isVarianceActive.initialize(m_matrixStatistic->getInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_VarActive));
ip_isRangeActive.initialize(m_matrixStatistic->getInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_RangeActive));
ip_isMedianActive.initialize(m_matrixStatistic->getInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_MedActive));
ip_isIQRActive.initialize(m_matrixStatistic->getInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_IQRActive));
ip_isPercentileActive.initialize(m_matrixStatistic->getInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_PercentActive));
//get dis/enabled output wanted
ip_isMeanActive = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
ip_isVarianceActive = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1);
ip_isRangeActive = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2);
ip_isMedianActive = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 3);
ip_isIQRActive = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 4);
ip_isPercentileActive = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 5);
//the percentile value
ip_parameterValue.initialize(m_matrixStatistic->getInputParameter(OVP_Algorithm_UnivariateStatistic_InputParameterId_PercentValue));
ip_parameterValue = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 6);
return true;
}
bool CBoxUnivariateStatistic::uninitialize()
{
#if 0
if(m_inputTypeID==OV_TypeId_Signal)
{
#endif
op_sampling.uninitialize();
#if 0
}
#endif
ip_parameterValue.uninitialize();
m_matrixStatistic->uninitialize();
m_meanEncoder->uninitialize();
m_varianceEncoder->uninitialize();
m_rangeEncoder->uninitialize();
m_medianEncoder->uninitialize();
m_iqrEncoder->uninitialize();
m_percentileEncoder->uninitialize();
m_decoder->uninitialize();
this->getAlgorithmManager().releaseAlgorithm(*m_matrixStatistic);
this->getAlgorithmManager().releaseAlgorithm(*m_meanEncoder);
this->getAlgorithmManager().releaseAlgorithm(*m_varianceEncoder);
this->getAlgorithmManager().releaseAlgorithm(*m_rangeEncoder);
this->getAlgorithmManager().releaseAlgorithm(*m_medianEncoder);
this->getAlgorithmManager().releaseAlgorithm(*m_iqrEncoder);
this->getAlgorithmManager().releaseAlgorithm(*m_percentileEncoder);
this->getAlgorithmManager().releaseAlgorithm(*m_decoder);
return true;
}
bool CBoxUnivariateStatistic::processInput(const size_t /*index*/)
{
this->getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
return true;
}
bool CBoxUnivariateStatistic::process()
{
Kernel::IBoxIO& boxContext = getDynamicBoxContext();
//for each input, calculate statistics and return the value
for (size_t j = 0; j < boxContext.getInputChunkCount(0); ++j)
{
Kernel::TParameterHandler<const IMemoryBuffer*> iBufferHandle(
m_decoder->getInputParameter(OVP_GD_Algorithm_StreamedMatrixDecoder_InputParameterId_MemoryBufferToDecode));
Kernel::TParameterHandler<IMemoryBuffer*> oBufferHandleMean(
m_meanEncoder->getOutputParameter(OVP_GD_Algorithm_StreamedMatrixEncoder_OutputParameterId_EncodedMemoryBuffer));
Kernel::TParameterHandler<IMemoryBuffer*> oBufferHandleVar(
m_varianceEncoder->getOutputParameter(OVP_GD_Algorithm_StreamedMatrixEncoder_OutputParameterId_EncodedMemoryBuffer));
Kernel::TParameterHandler<IMemoryBuffer*> oBufferHandleRange(
m_rangeEncoder->getOutputParameter(OVP_GD_Algorithm_StreamedMatrixEncoder_OutputParameterId_EncodedMemoryBuffer));
Kernel::TParameterHandler<IMemoryBuffer*> oBufferHandleMedian(
m_medianEncoder->getOutputParameter(OVP_GD_Algorithm_StreamedMatrixEncoder_OutputParameterId_EncodedMemoryBuffer));
Kernel::TParameterHandler<IMemoryBuffer*> oBufferHandleIqr(
m_iqrEncoder->getOutputParameter(OVP_GD_Algorithm_StreamedMatrixEncoder_OutputParameterId_EncodedMemoryBuffer));
Kernel::TParameterHandler<IMemoryBuffer*> oBufferHandlePercent(
m_percentileEncoder->getOutputParameter(OVP_GD_Algorithm_StreamedMatrixEncoder_OutputParameterId_EncodedMemoryBuffer));
iBufferHandle = boxContext.getInputChunk(0, j);
oBufferHandleMean = boxContext.getOutputChunk(0);
oBufferHandleVar = boxContext.getOutputChunk(1);
oBufferHandleRange = boxContext.getOutputChunk(2);
oBufferHandleMedian = boxContext.getOutputChunk(3);
oBufferHandleIqr = boxContext.getOutputChunk(4);
oBufferHandlePercent = boxContext.getOutputChunk(5);
m_decoder->process();
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_StreamedMatrixDecoder_OutputTriggerId_ReceivedHeader))
{
m_matrixStatistic->process(OVP_Algorithm_UnivariateStatistic_InputTriggerId_Initialize);
#if 0 // this is not needed as you know you always habe signal
if(m_inputTypeID==OV_TypeId_FeatureVector)
{
}
if(m_inputTypeID==OV_TypeId_Signal)
{
#endif
this->getLogManager() << Kernel::LogLevel_Debug << "DownSampling information : " << op_sampling << "*" << op_compression << "=>" <<
op_sampling * op_compression << "\n";
op_sampling = uint64_t(op_sampling * op_compression);
if (op_sampling == 0) { this->getLogManager() << Kernel::LogLevel_Warning << "Output sampling Rate is null, it could produce problem in next boxes \n"; }
#if 0 // this is not needed as you know you always habe signal
}
else if(m_inputTypeID==OV_TypeId_Spectrum)
{
}
#endif
if (ip_isMeanActive)
{
m_meanEncoder->process(OVP_GD_Algorithm_StreamedMatrixEncoder_InputTriggerId_EncodeHeader);
boxContext.markOutputAsReadyToSend(0, boxContext.getInputChunkStartTime(0, j), boxContext.getInputChunkEndTime(0, j));
}
if (ip_isVarianceActive)
{
m_varianceEncoder->process(OVP_GD_Algorithm_StreamedMatrixEncoder_InputTriggerId_EncodeHeader);
boxContext.markOutputAsReadyToSend(1, boxContext.getInputChunkStartTime(0, j), boxContext.getInputChunkEndTime(0, j));
}
if (ip_isRangeActive)
{
m_rangeEncoder->process(OVP_GD_Algorithm_StreamedMatrixEncoder_InputTriggerId_EncodeHeader);
boxContext.markOutputAsReadyToSend(2, boxContext.getInputChunkStartTime(0, j), boxContext.getInputChunkEndTime(0, j));
}
if (ip_isMedianActive)
{
m_medianEncoder->process(OVP_GD_Algorithm_StreamedMatrixEncoder_InputTriggerId_EncodeHeader);
boxContext.markOutputAsReadyToSend(3, boxContext.getInputChunkStartTime(0, j), boxContext.getInputChunkEndTime(0, j));
}
if (ip_isIQRActive)
{
m_iqrEncoder->process(OVP_GD_Algorithm_StreamedMatrixEncoder_InputTriggerId_EncodeHeader);
boxContext.markOutputAsReadyToSend(4, boxContext.getInputChunkStartTime(0, j), boxContext.getInputChunkEndTime(0, j));
}
if (ip_isPercentileActive)
{
m_percentileEncoder->process(OVP_GD_Algorithm_StreamedMatrixEncoder_InputTriggerId_EncodeHeader);
boxContext.markOutputAsReadyToSend(5, boxContext.getInputChunkStartTime(0, j), boxContext.getInputChunkEndTime(0, j));
}
}//end header
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_StreamedMatrixDecoder_OutputTriggerId_ReceivedBuffer))
{
m_matrixStatistic->process(OVP_Algorithm_UnivariateStatistic_InputTriggerId_Process);
if (m_matrixStatistic->isOutputTriggerActive(OVP_Algorithm_UnivariateStatistic_OutputTriggerId_ProcessDone))
{
#if 0
if(m_inputTypeID == OV_TypeId_FeatureVector) { }
if(m_inputTypeID == OV_TypeId_Signal) { }
else if(m_inputTypeID == OV_TypeId_Spectrum) { }
#endif
if (ip_isMeanActive)
{
m_meanEncoder->process(OVP_GD_Algorithm_StreamedMatrixEncoder_InputTriggerId_EncodeBuffer);
boxContext.markOutputAsReadyToSend(0, boxContext.getInputChunkStartTime(0, j), boxContext.getInputChunkEndTime(0, j));
}
if (ip_isVarianceActive)
{
m_varianceEncoder->process(OVP_GD_Algorithm_StreamedMatrixEncoder_InputTriggerId_EncodeBuffer);
boxContext.markOutputAsReadyToSend(1, boxContext.getInputChunkStartTime(0, j), boxContext.getInputChunkEndTime(0, j));
}
if (ip_isRangeActive)
{
m_rangeEncoder->process(OVP_GD_Algorithm_StreamedMatrixEncoder_InputTriggerId_EncodeBuffer);
boxContext.markOutputAsReadyToSend(2, boxContext.getInputChunkStartTime(0, j), boxContext.getInputChunkEndTime(0, j));
}
if (ip_isMedianActive)
{
m_medianEncoder->process(OVP_GD_Algorithm_StreamedMatrixEncoder_InputTriggerId_EncodeBuffer);
boxContext.markOutputAsReadyToSend(3, boxContext.getInputChunkStartTime(0, j), boxContext.getInputChunkEndTime(0, j));
}
if (ip_isIQRActive)
{
m_iqrEncoder->process(OVP_GD_Algorithm_StreamedMatrixEncoder_InputTriggerId_EncodeBuffer);
boxContext.markOutputAsReadyToSend(4, boxContext.getInputChunkStartTime(0, j), boxContext.getInputChunkEndTime(0, j));
}
if (ip_isPercentileActive)
{
m_percentileEncoder->process(OVP_GD_Algorithm_StreamedMatrixEncoder_InputTriggerId_EncodeBuffer);
boxContext.markOutputAsReadyToSend(5, boxContext.getInputChunkStartTime(0, j), boxContext.getInputChunkEndTime(0, j));
}
}
else { this->getLogManager() << Kernel::LogLevel_Debug << "Process not activated\n"; }
}//end buffer
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_StreamedMatrixDecoder_OutputTriggerId_ReceivedEnd))
{
#if 0
if(m_inputTypeID == OV_TypeId_FeatureVector) { }
if(m_inputTypeID == OV_TypeId_Signal) { }
else if(m_inputTypeID == OV_TypeId_Spectrum) { }
#endif
if (ip_isMeanActive)
{
m_meanEncoder->process(OVP_GD_Algorithm_StreamedMatrixEncoder_InputTriggerId_EncodeEnd);
boxContext.markOutputAsReadyToSend(0, boxContext.getInputChunkStartTime(0, j), boxContext.getInputChunkEndTime(0, j));
}
if (ip_isVarianceActive)
{
m_varianceEncoder->process(OVP_GD_Algorithm_StreamedMatrixEncoder_InputTriggerId_EncodeEnd);
boxContext.markOutputAsReadyToSend(1, boxContext.getInputChunkStartTime(0, j), boxContext.getInputChunkEndTime(0, j));
}
if (ip_isRangeActive)
{
m_rangeEncoder->process(OVP_GD_Algorithm_StreamedMatrixEncoder_InputTriggerId_EncodeEnd);
boxContext.markOutputAsReadyToSend(2, boxContext.getInputChunkStartTime(0, j), boxContext.getInputChunkEndTime(0, j));
}
if (ip_isMedianActive)
{
m_medianEncoder->process(OVP_GD_Algorithm_StreamedMatrixEncoder_InputTriggerId_EncodeEnd);
boxContext.markOutputAsReadyToSend(3, boxContext.getInputChunkStartTime(0, j), boxContext.getInputChunkEndTime(0, j));
}
if (ip_isIQRActive)
{
m_iqrEncoder->process(OVP_GD_Algorithm_StreamedMatrixEncoder_InputTriggerId_EncodeEnd);
boxContext.markOutputAsReadyToSend(4, boxContext.getInputChunkStartTime(0, j), boxContext.getInputChunkEndTime(0, j));
}
if (ip_isPercentileActive)
{
m_percentileEncoder->process(OVP_GD_Algorithm_StreamedMatrixEncoder_InputTriggerId_EncodeEnd);
boxContext.markOutputAsReadyToSend(5, boxContext.getInputChunkStartTime(0, j), boxContext.getInputChunkEndTime(0, j));
}
}//end ender
boxContext.markInputAsDeprecated(0, j);
}
return true;
}
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,88 @@
#pragma once
#include "../ovp_defines.h"
#include <toolkit/ovtk_all.h>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
class CBoxUnivariateStatistic final : public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
{
public:
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool processInput(const size_t index) override;
bool process() override;
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_UnivariateStatistic)
protected:
Kernel::IAlgorithmProxy* m_decoder = nullptr;
Kernel::IAlgorithmProxy* m_meanEncoder = nullptr;
Kernel::IAlgorithmProxy* m_varianceEncoder = nullptr;
Kernel::IAlgorithmProxy* m_rangeEncoder = nullptr;
Kernel::IAlgorithmProxy* m_medianEncoder = nullptr;
Kernel::IAlgorithmProxy* m_iqrEncoder = nullptr;
Kernel::IAlgorithmProxy* m_percentileEncoder = nullptr;
Kernel::IAlgorithmProxy* m_matrixStatistic = nullptr;
Kernel::TParameterHandler<double> op_compression;
Kernel::TParameterHandler<uint64_t> op_sampling;
Kernel::TParameterHandler<bool> ip_isMeanActive;
Kernel::TParameterHandler<bool> ip_isVarianceActive;
Kernel::TParameterHandler<bool> ip_isRangeActive;
Kernel::TParameterHandler<bool> ip_isMedianActive;
Kernel::TParameterHandler<bool> ip_isIQRActive;
Kernel::TParameterHandler<bool> ip_isPercentileActive;
Kernel::TParameterHandler<uint64_t> ip_parameterValue;
CIdentifier m_inputTypeID = CIdentifier::undefined();
};
class CBoxUnivariateStatisticDesc final : public IBoxAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return CString("Univariate Statistics"); }
CString getAuthorName() const override { return CString("Matthieu Goyat"); }
CString getAuthorCompanyName() const override { return CString("Gipsa-lab"); }
CString getShortDescription() const override { return CString("Mean, Variance, Median, etc. on the incoming Signal"); }
CString getDetailedDescription() const override { return CString(""); }
CString getCategory() const override { return CString("Signal processing/Statistics"); }
CString getVersion() const override { return CString("1.0"); }
CString getStockItemName() const override { return CString("gtk-missing-image"); }
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_UnivariateStatistic; }
IPluginObject* create() override { return new CBoxUnivariateStatistic(); }
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
{
prototype.addInput("Input Signals", OV_TypeId_Signal);
prototype.addOutput("Mean", OV_TypeId_Signal);
prototype.addOutput("Variance", OV_TypeId_Signal);
prototype.addOutput("Range", OV_TypeId_Signal);
prototype.addOutput("Median", OV_TypeId_Signal);
prototype.addOutput("IQR", OV_TypeId_Signal);
prototype.addOutput("Percentile", OV_TypeId_Signal);
prototype.addSetting("Mean", OV_TypeId_Boolean, "true");
prototype.addSetting("Variance", OV_TypeId_Boolean, "true");
prototype.addSetting("Range", OV_TypeId_Boolean, "true");
prototype.addSetting("Median", OV_TypeId_Boolean, "true");
prototype.addSetting("IQR", OV_TypeId_Boolean, "true");
prototype.addSetting("Percentile", OV_TypeId_Boolean, "true");
prototype.addSetting("Percentile value", OV_TypeId_Float, "30");
return true;
}
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_UnivariateStatisticDesc)
};
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,121 @@
#include "ovpCDetectingMinMaxBoxAlgorithm.h"
#include <iostream>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
bool CDetectingMinMaxBoxAlgorithm::initialize()
{
CIdentifier inputTypeID;
getStaticBoxContext().getInputType(0, inputTypeID);
if (inputTypeID == OV_TypeId_Signal)
{
m_decoder = &getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_SignalDecoder));
m_encoder = &getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StreamedMatrixEncoder));
}
else { return false; }
m_decoder->initialize();
m_encoder->initialize();
// Detects MinMax of signal input buffer
m_detectingMinMax = &getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_ClassId_Algorithm_DetectingMinMax));
m_detectingMinMax->initialize();
// compute filter coefs settings
const CString minMax = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
m_maxFlag = false;
m_minFlag = false;
if (this->getTypeManager().getEnumerationEntryValueFromName(OVP_TypeId_MinMax, minMax) == size_t(EMinMax::Min)) { m_minFlag = true; }
if (this->getTypeManager().getEnumerationEntryValueFromName(OVP_TypeId_MinMax, minMax) == size_t(EMinMax::Max)) { m_maxFlag = true; }
const double start = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1);
const double end = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2);
// DetectingMinMax settings
m_detectingMinMax->getInputParameter(OVP_Algorithm_DetectingMinMax_InputParameterId_SignalMatrix)->setReferenceTarget(
m_decoder->getOutputParameter(OVP_GD_Algorithm_StreamedMatrixDecoder_OutputParameterId_Matrix));
m_detectingMinMax->getInputParameter(OVP_Algorithm_DetectingMinMax_InputParameterId_Sampling)->setReferenceTarget(
m_decoder->getOutputParameter(OVP_GD_Algorithm_SignalDecoder_OutputParameterId_Sampling));
m_detectingMinMax->getInputParameter(OVP_Algorithm_DetectingMinMax_InputParameterId_TimeWindowStart)->setValue(&start);
m_detectingMinMax->getInputParameter(OVP_Algorithm_DetectingMinMax_InputParameterId_TimeWindowEnd)->setValue(&end);
// encoder settings
m_encoder->getInputParameter(OVP_GD_Algorithm_StreamedMatrixEncoder_InputParameterId_Matrix)->setReferenceTarget(
m_detectingMinMax->getOutputParameter(OVP_Algorithm_DetectingMinMax_OutputParameterId_SignalMatrix));
m_lastStartTime = 0;
m_lastEndTime = 0;
return true;
}
bool CDetectingMinMaxBoxAlgorithm::uninitialize()
{
m_encoder->uninitialize();
m_decoder->uninitialize();
m_detectingMinMax->uninitialize();
getAlgorithmManager().releaseAlgorithm(*m_encoder);
getAlgorithmManager().releaseAlgorithm(*m_decoder);
getAlgorithmManager().releaseAlgorithm(*m_detectingMinMax);
return true;
}
bool CDetectingMinMaxBoxAlgorithm::processInput(const size_t /*index*/)
{
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
return true;
}
bool CDetectingMinMaxBoxAlgorithm::process()
{
Kernel::IBoxIO& boxContext = getDynamicBoxContext();
const size_t nInput = getStaticBoxContext().getInputCount();
for (size_t i = 0; i < nInput; ++i)
{
for (size_t j = 0; j < boxContext.getInputChunkCount(i); ++j)
{
Kernel::TParameterHandler<const IMemoryBuffer*> iBufferHandle(
m_decoder->getInputParameter(OVP_GD_Algorithm_SignalDecoder_InputParameterId_MemoryBufferToDecode));
Kernel::TParameterHandler<IMemoryBuffer*> oBufferHandle(
m_encoder->getOutputParameter(OVP_GD_Algorithm_StreamedMatrixEncoder_OutputParameterId_EncodedMemoryBuffer));
iBufferHandle = boxContext.getInputChunk(i, j);
oBufferHandle = boxContext.getOutputChunk(i);
const uint64_t tEnd = m_lastStartTime + boxContext.getInputChunkEndTime(i, j) - boxContext.getInputChunkStartTime(i, j);
m_decoder->process();
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_SignalDecoder_OutputTriggerId_ReceivedHeader))
{
m_detectingMinMax->process(OVP_Algorithm_DetectingMinMax_InputTriggerId_Initialize);
m_encoder->process(OVP_GD_Algorithm_StreamedMatrixEncoder_InputTriggerId_EncodeHeader);
boxContext.markOutputAsReadyToSend(i, m_lastStartTime, tEnd);
}
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_SignalDecoder_OutputTriggerId_ReceivedBuffer))
{
if (m_minFlag) { m_detectingMinMax->process(OVP_Algorithm_DetectingMinMax_InputTriggerId_DetectsMin); }
if (m_maxFlag) { m_detectingMinMax->process(OVP_Algorithm_DetectingMinMax_InputTriggerId_DetectsMax); }
m_encoder->process(OVP_GD_Algorithm_StreamedMatrixEncoder_InputTriggerId_EncodeBuffer);
boxContext.markOutputAsReadyToSend(i, m_lastStartTime, tEnd);
}
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_SignalDecoder_OutputTriggerId_ReceivedEnd))
{
m_encoder->process(OVP_GD_Algorithm_StreamedMatrixEncoder_InputTriggerId_EncodeEnd);
boxContext.markOutputAsReadyToSend(i, m_lastStartTime, tEnd);
}
m_lastStartTime = boxContext.getInputChunkStartTime(i, j);
m_lastEndTime = boxContext.getInputChunkEndTime(i, j);
boxContext.markInputAsDeprecated(i, j);
}
}
return true;
}
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,74 @@
// @copyright notice: Possibly due to dependencies, this box used to be GPL before upgrade to AGPL3
#pragma once
#include "../ovp_defines.h"
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
class CDetectingMinMaxBoxAlgorithm final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
{
public:
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool processInput(const size_t index) override;
bool process() override;
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_Box_DetectingMinMaxBoxAlgorithm)
protected:
Kernel::IAlgorithmProxy* m_decoder = nullptr;
Kernel::IAlgorithmProxy* m_encoder = nullptr;
Kernel::IAlgorithmProxy* m_detectingMinMax = nullptr;
uint64_t m_lastStartTime = 0;
uint64_t m_lastEndTime = 0;
bool m_minFlag = false;
bool m_maxFlag = false;
};
class CDetectingMinMaxBoxAlgorithmDesc final : virtual public IBoxAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return CString("Min/Max detection"); }
CString getAuthorName() const override { return CString("Guillaume Gibert"); }
CString getAuthorCompanyName() const override { return CString("INSERM/U821"); }
CString getShortDescription() const override { return CString("Outputs the minimum or the maximum value inside a time window"); }
CString getDetailedDescription() const override { return CString("Either min or max detection can be specified as a box parameter"); }
CString getCategory() const override { return CString("Signal processing/Basic"); }
CString getVersion() const override { return CString("1.0"); }
CString getStockItemName() const override { return CString(""); }
CIdentifier getCreatedClass() const override { return OVP_ClassId_Box_DetectingMinMaxBoxAlgorithm; }
IPluginObject* create() override { return new CDetectingMinMaxBoxAlgorithm(); }
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
{
prototype.addInput("Input epochs", OV_TypeId_Signal);
prototype.addOutput("Output epochs", OV_TypeId_StreamedMatrix);
prototype.addSetting("Min/Max", OVP_TypeId_MinMax, "Max");
prototype.addSetting("Time window start", OV_TypeId_Float, "300");
prototype.addSetting("Time window end", OV_TypeId_Float, "500");
return true;
}
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_Box_DetectingMinMaxBoxAlgorithmDesc)
};
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,237 @@
#include "ovpCDownsamplingBoxAlgorithm.h"
#include <cstdlib>
#include <climits>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
bool CDownsamplingBoxAlgorithm::initialize()
{
CIdentifier inputTypeID;
getStaticBoxContext().getInputType(0, inputTypeID);
if (inputTypeID == OV_TypeId_Signal)
{
CIdentifier algorithmID = getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_SignalDecoder);
if (algorithmID == CIdentifier::undefined())
{
this->getLogManager() << Kernel::LogLevel_Error << "Unable to find algorithm " << OVP_GD_ClassId_Algorithm_SignalDecoder << "\n";
return false;
}
m_decoder = &getAlgorithmManager().getAlgorithm(algorithmID);
algorithmID = getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_SignalEncoder);
if (algorithmID == CIdentifier::undefined())
{
this->getLogManager() << Kernel::LogLevel_Error << "Unable to find algorithm " << OVP_GD_ClassId_Algorithm_SignalEncoder << "\n";
return false;
}
m_encoder = &getAlgorithmManager().getAlgorithm(algorithmID);
}
else
{
this->getLogManager() << Kernel::LogLevel_Error << "Only 'signal' input type is supported\n";
return false;
}
m_decoder->initialize();
m_encoder->initialize();
ip_bufferToDecode.initialize(m_decoder->getInputParameter(OVP_GD_Algorithm_SignalDecoder_InputParameterId_MemoryBufferToDecode));
op_encodedBuffer.initialize(m_encoder->getOutputParameter(OVP_GD_Algorithm_SignalEncoder_OutputParameterId_EncodedMemoryBuffer));
// Compute filter coeff algorithm
m_computeTemporalFilterCoefs = &getAlgorithmManager().getAlgorithm(
getAlgorithmManager().createAlgorithm(OVP_ClassId_Algorithm_ComputeTemporalFilterCoefs));
m_computeTemporalFilterCoefs->initialize();
// Apply filter to signal input buffer
m_applyTemporalFilter = &getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_ClassId_Algorithm_ApplyTemporalFilter));
m_applyTemporalFilter->initialize();
// Compute Downsampling of signal input buffer
m_downsampling = &getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_ClassId_Algorithm_Downsampling));
m_downsampling->initialize();
// Compute filter coefs settings
m_newSampling = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
const CString ratio = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1);
const CString filter = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2);
const CString filterOrder = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 3);
const CString passBandRipple = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 4);
double ratioValue = 1.0 / 4;
if (this->getTypeManager().getEnumerationEntryValueFromName(OVP_TypeId_FrequencyCutOffRatio, ratio) == size_t(EFrequencyCutOffRatio::R14))
{
ratioValue = 1.0 / 4;
}
if (this->getTypeManager().getEnumerationEntryValueFromName(OVP_TypeId_FrequencyCutOffRatio, ratio) == size_t(EFrequencyCutOffRatio::R13))
{
ratioValue = 1.0 / 3;
}
if (this->getTypeManager().getEnumerationEntryValueFromName(OVP_TypeId_FrequencyCutOffRatio, ratio) == size_t(EFrequencyCutOffRatio::R12))
{
ratioValue = 1.0 / 2;
}
uint64_t filterValue = this->getTypeManager().getEnumerationEntryValueFromName(OVP_TypeId_FilterMethod, filter);
uint64_t kindFilter = uint64_t(EFilterType::LowPass); //Low Pass
uint64_t order = atoi(filterOrder);
double lowCutFrequency = 0;
double highCutFrequency = double(m_newSampling) * ratioValue;
double passBandRippleValue = atof(passBandRipple);
// Compute filter settings
m_computeTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_Sampling)->setReferenceTarget(
m_decoder->getOutputParameter(OVP_GD_Algorithm_SignalDecoder_OutputParameterId_Sampling));
m_computeTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_FilterMethod)->setValue(&filterValue);
m_computeTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_FilterType)->setValue(&kindFilter);
m_computeTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_FilterOrder)->setValue(&order);
m_computeTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_LowCutFrequency)->setValue(&lowCutFrequency);
m_computeTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_HighCutFrequency)->setValue(&highCutFrequency);
m_computeTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_BandPassRipple)->setValue(&passBandRippleValue);
// Apply filter settings
m_applyTemporalFilter->getInputParameter(OVP_Algorithm_ApplyTemporalFilter_InputParameterId_SignalMatrix)->setReferenceTarget(
m_decoder->getOutputParameter(OVP_GD_Algorithm_SignalDecoder_OutputParameterId_Matrix));
m_applyTemporalFilter->getInputParameter(OVP_Algorithm_ApplyTemporalFilter_InputParameterId_FilterCoefsMatrix)->setReferenceTarget(
m_computeTemporalFilterCoefs->getOutputParameter(
OVP_Algorithm_ComputeTemporalFilterCoefs_OutputParameterId_Matrix));
// Downsampling settings
m_downsampling->getInputParameter(OVP_Algorithm_Downsampling_InputParameterId_SignalMatrix)->setReferenceTarget(
m_applyTemporalFilter->getOutputParameter(OVP_Algorithm_ApplyTemporalFilter_OutputParameterId_FilteredSignalMatrix));
m_downsampling->getInputParameter(OVP_Algorithm_Downsampling_InputParameterId_Sampling)->setReferenceTarget(
m_decoder->getOutputParameter(OVP_GD_Algorithm_SignalDecoder_OutputParameterId_Sampling));
m_downsampling->getInputParameter(OVP_Algorithm_Downsampling_InputParameterId_NewSampling)->setValue(&m_newSampling);
// Encoder settings
m_encoder->getInputParameter(OVP_GD_Algorithm_SignalEncoder_InputParameterId_Sampling)->setValue(&m_newSampling);
m_iSignal.initialize(m_decoder->getOutputParameter(OVP_GD_Algorithm_SignalDecoder_OutputParameterId_Matrix));
m_oSignal.initialize(m_encoder->getInputParameter(OVP_GD_Algorithm_SignalEncoder_InputParameterId_Matrix));
m_samplingRate.initialize(m_decoder->getOutputParameter(OVP_GD_Algorithm_SignalDecoder_OutputParameterId_Sampling));
m_signalDesc = new CMatrix();
m_lastEndTime = uint64_t(-1);
m_flagFirstTime = true;
m_warned = false;
m_lastBufferSize = 0;
m_currentBufferSize = 0;
return true;
}
bool CDownsamplingBoxAlgorithm::uninitialize()
{
delete m_signalDesc;
m_signalDesc = nullptr;
m_applyTemporalFilter->uninitialize();
m_computeTemporalFilterCoefs->uninitialize();
m_encoder->uninitialize();
m_decoder->uninitialize();
m_downsampling->uninitialize();
getAlgorithmManager().releaseAlgorithm(*m_applyTemporalFilter);
getAlgorithmManager().releaseAlgorithm(*m_computeTemporalFilterCoefs);
getAlgorithmManager().releaseAlgorithm(*m_encoder);
getAlgorithmManager().releaseAlgorithm(*m_decoder);
getAlgorithmManager().releaseAlgorithm(*m_downsampling);
return true;
}
bool CDownsamplingBoxAlgorithm::processInput(const size_t /*index*/)
{
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
return true;
}
bool CDownsamplingBoxAlgorithm::process()
{
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
for (size_t j = 0; j < boxContext.getInputChunkCount(0); ++j)
{
ip_bufferToDecode = boxContext.getInputChunk(0, j);
op_encodedBuffer = boxContext.getOutputChunk(0);
const uint64_t tStart = boxContext.getInputChunkStartTime(0, j);
const uint64_t tEnd = boxContext.getInputChunkEndTime(0, j);
m_decoder->process();
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_SignalDecoder_OutputTriggerId_ReceivedHeader))
{
m_computeTemporalFilterCoefs->process(OVP_Algorithm_ComputeTemporalFilterCoefs_InputTriggerId_Initialize);
m_computeTemporalFilterCoefs->process(OVP_Algorithm_ComputeTemporalFilterCoefs_InputTriggerId_ComputeCoefs);
m_applyTemporalFilter->process(OVP_Algorithm_ApplyTemporalFilter_InputTriggerId_Initialize);
}
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_SignalDecoder_OutputTriggerId_ReceivedBuffer))
{
bool success = true;
if (m_lastEndTime == tStart)
{
success &= m_applyTemporalFilter->process(OVP_Algorithm_ApplyTemporalFilter_InputTriggerId_ApplyFilterWithHistoric);
success &= m_downsampling->process(OVP_Algorithm_Downsampling_InputTriggerId_ResampleWithHistoric);
}
else
{
success &= m_applyTemporalFilter->process(OVP_Algorithm_ApplyTemporalFilter_InputTriggerId_ApplyFilter);
success &= m_downsampling->process(OVP_Algorithm_Downsampling_InputTriggerId_Resample);
}
if (!success)
{
this->getLogManager() << Kernel::LogLevel_Error << "Subalgorithm failed, returning\n";
return false;
}
Kernel::TParameterHandler<CMatrix*> signal(m_downsampling->getOutputParameter(OVP_Algorithm_Downsampling_OutputParameterId_SignalMatrix));
m_currentBufferSize = signal->getDimensionSize(1);
if ((m_flagFirstTime) || (m_currentBufferSize != m_lastBufferSize))
{
if (!m_flagFirstTime && !m_warned)
{
// this->getLogManager() << Kernel::LogLevel_Warning << "This box is flagged as unstable !\n";
this->getLogManager() << Kernel::LogLevel_Warning <<
"The input sampling frequency is not an integer multiple of the output sampling frequency, or the input epoch size is unsuitable. This results in creation of size varying output chunks. This may cause crash in downstream boxes.\n";
this->getLogManager() << Kernel::LogLevel_Debug << "(current block size is " << m_currentBufferSize << ", new block size is " <<
m_lastBufferSize << ")\n";
m_warned = true;
}
m_signalDesc->resize(m_iSignal->getDimensionSize(0), m_currentBufferSize);
for (size_t k = 0; k < m_iSignal->getDimensionSize(0); ++k) { m_signalDesc->setDimensionLabel(0, k, m_iSignal->getDimensionLabel(0, k)); }
m_oSignal.setReferenceTarget(m_signalDesc);
m_encoder->process(OVP_GD_Algorithm_SignalEncoder_InputTriggerId_EncodeHeader);
boxContext.markOutputAsReadyToSend(0, tStart, tStart);
m_lastBufferSize = m_currentBufferSize;
m_flagFirstTime = false;
}
m_oSignal.setReferenceTarget(m_downsampling->getOutputParameter(OVP_Algorithm_Downsampling_OutputParameterId_SignalMatrix));
m_encoder->process(OVP_GD_Algorithm_SignalEncoder_InputTriggerId_EncodeBuffer);
boxContext.markOutputAsReadyToSend(0, tStart, tEnd);
m_lastBufferSize = m_currentBufferSize;
}
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_SignalDecoder_OutputTriggerId_ReceivedEnd))
{
m_encoder->process(OVP_GD_Algorithm_SignalEncoder_InputTriggerId_EncodeEnd);
boxContext.markOutputAsReadyToSend(0, tStart, tEnd);
}
m_lastEndTime = tEnd;
boxContext.markInputAsDeprecated(0, j);
}
return true;
}
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,93 @@
// @copyright notice: Possibly due to dependencies, this box used to be GPL before upgrade to AGPL3
#pragma once
#include "../ovp_defines.h"
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
class CDownsamplingBoxAlgorithm final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
{
public:
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool processInput(const size_t index) override;
bool process() override;
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_Box_DownsamplingBoxAlgorithm)
protected:
Kernel::IAlgorithmProxy* m_decoder = nullptr;
Kernel::IAlgorithmProxy* m_encoder = nullptr;
Kernel::IAlgorithmProxy* m_computeTemporalFilterCoefs = nullptr;
Kernel::IAlgorithmProxy* m_applyTemporalFilter = nullptr;
Kernel::IAlgorithmProxy* m_downsampling = nullptr;
Kernel::TParameterHandler<const IMemoryBuffer*> ip_bufferToDecode;
Kernel::TParameterHandler<IMemoryBuffer*> op_encodedBuffer;
Kernel::TParameterHandler<CMatrix*> m_iSignal;
Kernel::TParameterHandler<CMatrix*> m_oSignal;
CMatrix* m_signalDesc = nullptr;
uint64_t m_newSampling = 0;
Kernel::TParameterHandler<uint64_t> m_samplingRate;
uint64_t m_lastEndTime = 0;
bool m_flagFirstTime = false;
bool m_warned = false;
size_t m_lastBufferSize = 0;
size_t m_currentBufferSize = 0;
uint64_t m_signalType = 0;
};
class CDownsamplingBoxAlgorithmDesc final : virtual public IBoxAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return CString("Downsampling"); }
CString getAuthorName() const override { return CString("G. Gibert - E. Maby - P.E. Aguera"); }
CString getAuthorCompanyName() const override { return CString("INSERM/U821"); }
CString getShortDescription() const override { return CString("Filters and downsamples input buffer."); }
CString getDetailedDescription() const override
{
return CString(
"First, applies a low-pass (Butterworth or Chebyshev) filter (frequency cut is 1/4, 1/3 or 1/2 of the new sampling rate) to input buffers of signal for anti-aliasing. Then, the input buffers of signal is downsampled.");
}
CString getCategory() const override { return CString("Signal processing/Basic"); }
CString getVersion() const override { return CString("1.01"); }
CString getStockItemName() const override { return CString(""); }
CIdentifier getCreatedClass() const override { return OVP_ClassId_Box_DownsamplingBoxAlgorithm; }
IPluginObject* create() override { return new CDownsamplingBoxAlgorithm(); }
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
{
prototype.addInput("Input signal", OV_TypeId_Signal);
prototype.addOutput("Output signal", OV_TypeId_Signal);
prototype.addSetting("New sampling rate (Hz)", OV_TypeId_Integer, "32");
prototype.addSetting("Frequency cutoff ratio", OVP_TypeId_FrequencyCutOffRatio, "1/4");
prototype.addSetting("Name of filter", OVP_TypeId_FilterMethod, "Butterworth");
prototype.addSetting("Filter order", OV_TypeId_Integer, "4");
prototype.addSetting("Pass band ripple (dB)", OV_TypeId_Float, "0.5");
prototype.addFlag(OV_AttributeId_Box_FlagIsUnstable);
prototype.addFlag(Kernel::BoxFlag_IsDeprecated);
return true;
}
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_Box_DownsamplingBoxAlgorithmDesc)
};
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,234 @@
#if defined TARGET_HAS_ThirdPartyITPP
#include "ovpCFastICA.h"
#include <iostream>
#include <itpp/itstat.h>
#include <itpp/itsignal.h>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
void CFastICA::computeICA()
{
const size_t nChannel = m_decoder.getOutputMatrix()->getDimensionSize(0);
const size_t nSample = m_decoder.getOutputMatrix()->getDimensionSize(1);
const double* iBuffer = m_decoder.getOutputMatrix()->getBuffer();
const size_t nICs = m_encoder.getInputMatrix()->getDimensionSize(0);
itpp::mat sources(nChannel, nSample); // current block (for decomposing)
itpp::mat bufferSources(nChannel, m_buffSize); // accumulated blocks (for training)
itpp::mat ICs(nICs, nSample);
//mat Mix_mat(nChannel, nChannel);
itpp::mat sepMat(nICs, nChannel);
//mat Dewhite(nChannel, nChannel);
// Append the data to a FIFO buffer
for (size_t i = 0; i < nChannel; ++i)
{
for (size_t j = 0; j < m_buffSize; ++j)
{
if (j < m_buffSize - nSample)
{
m_fifoBuffer[i * m_buffSize + j + nSample] = m_fifoBuffer[i * m_buffSize + j]; // memory shift
if (j < nSample)
{
m_fifoBuffer[i * m_buffSize + j] = double(iBuffer[i * nSample + nSample - 1 - j]);
sources(int(i), int(j)) = double(iBuffer[i * nSample + j]);
}
}
bufferSources(int(i), int(m_buffSize - 1 - j)) = m_fifoBuffer[i * m_buffSize + j];
}
}
m_nSample += nSample;
if ((m_nSample >= m_buffSize) && (m_trained == false))
{
this->getLogManager() << Kernel::LogLevel_Trace << "Instanciating the Fast_ICA object with " << m_nSample << " samples.\n";
itpp::Fast_ICA fastica(bufferSources);
this->getLogManager() << Kernel::LogLevel_Trace << "Setting the number of ICs to extract to " << nICs << " and configuring FastICA...\n";
if (m_mode == EFastICAMode::PCA || m_mode == EFastICAMode::Whiten) { fastica.set_pca_only(true); }
else
{
fastica.set_approach(int(m_type));
fastica.set_non_linearity(int(m_nonLin));
fastica.set_max_num_iterations(m_nRepMax);
fastica.set_fine_tune(m_setFineTune);
fastica.set_max_fine_tune(m_nTuneMax);
fastica.set_mu(m_setMu);
fastica.set_epsilon(m_epsilon);
}
fastica.set_nrof_independent_components(nICs);
//if(m_nSample>nSample) fastica.set_init_guess((Dewhite * Dewhite.T()) * Sep_mat.T());
this->getLogManager() << Kernel::LogLevel_Trace << "Explicit launch of the Fast_ICA algorithm. Can occasionally take time.\n";
fastica.separate();
this->getLogManager() << Kernel::LogLevel_Trace << "Retrieving separating matrix from fastica .\n";
if (m_mode == EFastICAMode::PCA) { sepMat = fastica.get_principal_eigenvectors().transpose(); }
else if (m_mode == EFastICAMode::Whiten) { sepMat = fastica.get_whitening_matrix(); }
else { sepMat = fastica.get_separating_matrix(); }
m_trained = true;
double* demixer = m_demixer.getBuffer();
for (size_t i = 0; i < nICs; ++i) { for (size_t j = 0; j < nChannel; ++j) { demixer[i * nChannel + j] = sepMat(int(i), int(j)); } }
}
else
{
// Use the previously stored matrix
const double* demixer = m_demixer.getBuffer();
for (size_t i = 0; i < nICs; ++i) { for (size_t j = 0; j < nChannel; ++j) { sepMat(int(i), int(j)) = demixer[i * nChannel + j]; } }
}
// Effective demixing (ICA after m_duration sec)
ICs = sepMat * sources;
double* buffer = m_encoder.getInputMatrix()->getBuffer();
//this->getLogManager() << Kernel::LogLevel_Trace << "Filling output buffer with ICs .\n";
for (size_t i = 0; i < nICs; ++i) { for (size_t j = 0; j < nSample; ++j) { buffer[i * nSample + j] = ICs(int(i), int(j)); } }
}
bool CFastICA::initialize()
{
m_decoder.initialize(*this, 0);
m_encoder.initialize(*this, 0);
m_nICs = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
m_mode = EFastICAMode(uint64_t(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1)));
m_duration = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2);
m_type = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 3);
m_nRepMax = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 4);
m_setFineTune = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 5);
m_nTuneMax = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 6);
m_nonLin = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 7);
m_setMu = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 8);
m_epsilon = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 9);
m_spatialFilterFilename = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 10);
m_saveAsFile = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 11);
m_fifoBuffer = nullptr;
m_fileSaved = false;
if (m_saveAsFile && m_spatialFilterFilename == CString(""))
{
this->getLogManager() << "If save is enabled, filename must be provided\n";
return false;
}
return true;
}
bool CFastICA::uninitialize()
{
m_encoder.uninitialize();
m_decoder.uninitialize();
if (m_fifoBuffer)
{
delete[] m_fifoBuffer;
m_fifoBuffer = nullptr;
}
return true;
}
bool CFastICA::processInput(const size_t /*index*/)
{
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
return true;
}
bool CFastICA::process()
{
IDynamicBoxContext* boxContext = getBoxAlgorithmContext()->getDynamicBoxContext();
// Process input data
for (size_t i = 0; i < boxContext->getInputChunkCount(0); ++i)
{
m_decoder.decode(i);
if (m_decoder.isHeaderReceived())
{
// Set the output (encoder) matrix prorperties from the input (decoder)
if (m_decoder.getOutputMatrix()->getDimensionCount() != 2)
{
this->getLogManager() << Kernel::LogLevel_Error << "Needs a 2 dimensional (rows x cols) matrix as input\n";
return false;
}
m_buffSize = size_t(m_decoder.getOutputSamplingRate()) * m_duration;
const size_t nChannel = m_decoder.getOutputMatrix()->getDimensionSize(0);
const size_t nSample = m_decoder.getOutputMatrix()->getDimensionSize(1);
delete[] m_fifoBuffer;
m_fifoBuffer = new double[nChannel * m_buffSize];
this->getLogManager() << Kernel::LogLevel_Trace << "FIFO buffer initialized with " << nChannel * m_buffSize << ".\n";
if (m_nICs > nChannel)
{
this->getLogManager() << Kernel::LogLevel_Warning << "Trying to estimate more components than channels, truncating\n";
m_nICs = nChannel;
}
for (size_t j = 0; j < nChannel * m_buffSize; ++j) { m_fifoBuffer[j] = 0.0; }
m_nSample = 0;
m_trained = false;
CMatrix* matrix = m_encoder.getInputMatrix();
matrix->resize(m_nICs, nSample);
m_encoder.getInputSamplingRate() = m_decoder.getOutputSamplingRate();
std::string prefix;
if (m_mode == EFastICAMode::PCA) { prefix = "PC"; }
else if (m_mode == EFastICAMode::Whiten) { prefix = "Wh"; }
else { prefix = "IC"; }
for (size_t c = 0; c < m_nICs; ++c) { matrix->setDimensionLabel(0, c, (prefix + std::to_string(c + 1)).c_str()); }
m_encoder.encodeHeader();
m_demixer.resize(m_nICs, nChannel);
// Set the demixer to (partial) identity matrix to start with
m_demixer.resetBuffer();
double* demixer = m_demixer.getBuffer();
for (size_t c = 0; c < m_nICs; ++c) { demixer[c * nChannel + c] = 1.0; }
getBoxAlgorithmContext()->getDynamicBoxContext()->markOutputAsReadyToSend(0, 0, 0);
}
if (m_decoder.isBufferReceived())
{
const uint64_t startTime = boxContext->getInputChunkStartTime(0, i);
const uint64_t endTime = boxContext->getInputChunkEndTime(0, i);
computeICA();
if ((m_saveAsFile) && (m_trained) && (m_fileSaved == false))
{
if (!Toolkit::Matrix::saveToTextFile(m_demixer, m_spatialFilterFilename))
{
this->getLogManager() << Kernel::LogLevel_Warning << "Unable to save to [" << m_spatialFilterFilename << "\n";
}
m_fileSaved = true;
}
m_encoder.encodeBuffer();
getBoxAlgorithmContext()->getDynamicBoxContext()->markOutputAsReadyToSend(0, startTime, endTime);
}
// if (m_decoder.isEndReceived()) { } // NOP
}
return true;
}
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyITPP
@@ -0,0 +1,115 @@
// @copyright notice: Possibly due to dependencies, this box used to be GPL before upgrade to AGPL3
#pragma once
#if defined TARGET_HAS_ThirdPartyITPP
#include "../ovp_defines.h"
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
#include <map>
#include <string>
// TODO create a member function to get rid of this
#ifndef CString2Boolean
#define CString2Boolean(string) (strcmp(string,"true"))?0:1
#endif
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
/**
* The FastICA plugin's main class.
*/
class CFastICA final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
{
public:
CFastICA() {}
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool processInput(const size_t index) override;
bool process() override;
_IsDerivedFromClass_Final_(IBoxAlgorithm, OVP_ClassId_FastICA)
protected:
void computeICA();
Toolkit::TSignalDecoder<CFastICA> m_decoder;
Toolkit::TSignalEncoder<CFastICA> m_encoder;
double* m_fifoBuffer = nullptr;
CMatrix m_demixer; // The estimated matrix W
bool m_trained = false;
bool m_fileSaved = false;
size_t m_buffSize = 0;
size_t m_nSample = 0;
size_t m_nICs = 0;
size_t m_duration = 0;
size_t m_nRepMax = 0;
size_t m_nTuneMax = 0;
CString m_spatialFilterFilename;
bool m_saveAsFile = false;
bool m_setFineTune = false;
double m_setMu = 0;
double m_epsilon = 0;
size_t m_nonLin = 0;
size_t m_type = 0;
EFastICAMode m_mode = EFastICAMode::ICA;
};
class CFastICADesc final : virtual public IBoxAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return CString("Independent Component Analysis (FastICA)"); }
CString getAuthorName() const override { return CString("Guillaume Gibert / Jeff B."); }
CString getAuthorCompanyName() const override { return CString("INSERM / Independent"); }
CString getShortDescription() const override { return CString("Computes fast independent component analysis"); }
CString getDetailedDescription() const override { return CString(""); }
CString getCategory() const override { return CString("Signal processing/Independent component analysis"); }
CString getVersion() const override { return CString("0.2"); }
CIdentifier getCreatedClass() const override { return OVP_ClassId_FastICA; }
IPluginObject* create() override { return new CFastICA(); }
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
{
prototype.addInput("Input signal", OV_TypeId_Signal);
prototype.addOutput("Output signal", OV_TypeId_Signal);
prototype.addSetting("Number of components to extract", OV_TypeId_Integer, "4");
prototype.addSetting("Operating mode", OVP_TypeId_FastICA_OperatingMode, "ICA");
prototype.addSetting("Sample size (seconds) for estimation", OV_TypeId_Integer, "120");
prototype.addSetting("Decomposition type", OVP_TypeId_FastICA_DecompositionType, "Symmetric");
prototype.addSetting("Max number of reps for the ICA convergence", OV_TypeId_Integer, "100000");
prototype.addSetting("Fine tuning", OV_TypeId_Boolean, "true");
prototype.addSetting("Max number of reps for the fine tuning", OV_TypeId_Integer, "100");
prototype.addSetting("Used nonlinearity", OVP_TypeId_FastICA_Nonlinearity, "Tanh");
prototype.addSetting("Internal Mu parameter for FastICA", OV_TypeId_Float, "1.0");
prototype.addSetting("Internal Epsilon parameter for FastICA", OV_TypeId_Float, "0.0001");
prototype.addSetting("Spatial filter filename", OV_TypeId_Filename, "");
prototype.addSetting("Save the spatial filter/demixing matrix", OV_TypeId_Boolean, "false");
prototype.addFlag(OV_AttributeId_Box_FlagIsUnstable);
return true;
}
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_FastICADesc)
};
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyITPP
@@ -0,0 +1,253 @@
#include "ovpCInputChannel.h"
#include <iostream>
#include <cstring>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
namespace {
class _AutoCast_
{
public:
_AutoCast_(const Kernel::IBox& box, Kernel::IConfigurationManager& configManager, const size_t index) : m_configManager(configManager)
{
box.getSettingValue(index, m_settingValue);
}
operator uint64_t() const { return m_configManager.expandAsUInteger(m_settingValue); }
operator int64_t() const { return m_configManager.expandAsInteger(m_settingValue); }
operator double() const { return m_configManager.expandAsFloat(m_settingValue); }
operator bool() const { return m_configManager.expandAsBoolean(m_settingValue); }
operator const CString() const { return m_configManager.expand(m_settingValue); }
protected:
Kernel::IConfigurationManager& m_configManager;
CString m_settingValue;
};
} // namespace
CInputChannel::CInputChannel()
{
m_oMatrix[0] = nullptr;
m_oMatrix[1] = nullptr;
}
CInputChannel::~CInputChannel()
{
if (m_oMatrix[0]) { delete m_oMatrix[0]; }
if (m_oMatrix[1]) { delete m_oMatrix[1]; }
}
bool CInputChannel::initialize(Toolkit::TBoxAlgorithm<IBoxAlgorithm>* boxAlgorithm)
{
m_status = 0;
m_oMatrix[0] = nullptr;
m_oMatrix[1] = nullptr;
m_timeStimulationPos = 0;
m_timeStimulationStart = 0;
m_timeStimulationEnd = 0;
m_hasFirstStimulation = false;
m_timeSignalPos = 0;
m_timeSignalStart = 0;
m_timeSignalEnd = 0;
m_stimulationSet = nullptr;
m_boxAlgorithm = boxAlgorithm;
m_ptrMatrixIdx = 0;
m_synchroStimulation = m_boxAlgorithm->getTypeManager().getEnumerationEntryValueFromName(
OV_TypeId_Stimulation,
_AutoCast_(m_boxAlgorithm->getStaticBoxContext(), m_boxAlgorithm->getConfigurationManager(), 0));
m_signalDecoder = &m_boxAlgorithm->getAlgorithmManager().getAlgorithm(
m_boxAlgorithm->getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_SignalDecoder));
m_signalDecoder->initialize();
ip_bufferSignal.initialize(m_signalDecoder->getInputParameter(OVP_GD_Algorithm_SignalDecoder_InputParameterId_MemoryBufferToDecode));
op_matrixSignal.initialize(m_signalDecoder->getOutputParameter(OVP_GD_Algorithm_SignalDecoder_OutputParameterId_Matrix));
op_sampling.initialize(m_signalDecoder->getOutputParameter(OVP_GD_Algorithm_SignalDecoder_OutputParameterId_Sampling));
m_stimDecoder = &m_boxAlgorithm->getAlgorithmManager().getAlgorithm(
m_boxAlgorithm->getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StimulationDecoder));
m_stimDecoder->initialize();
ip_bufferStimulation.initialize(m_stimDecoder->getInputParameter(OVP_GD_Algorithm_StimulationDecoder_InputParameterId_MemoryBufferToDecode));
op_stimulationSet.initialize(m_stimDecoder->getOutputParameter(OVP_GD_Algorithm_StimulationDecoder_OutputParameterId_StimulationSet));
return true;
}
bool CInputChannel::uninitialize()
{
op_stimulationSet.uninitialize();
ip_bufferStimulation.uninitialize();
m_stimDecoder->uninitialize();
m_boxAlgorithm->getAlgorithmManager().releaseAlgorithm(*m_stimDecoder);
op_sampling.uninitialize();
op_matrixSignal.uninitialize();
ip_bufferSignal.uninitialize();
m_signalDecoder->uninitialize();
m_boxAlgorithm->getAlgorithmManager().releaseAlgorithm(*m_signalDecoder);
return true;
}
bool CInputChannel::waitForSignalHeader()
{
Kernel::IBoxIO& boxContext = m_boxAlgorithm->getDynamicBoxContext();
if (boxContext.getInputChunkCount(SIGNAL_CHANNEL))
{
ip_bufferSignal = boxContext.getInputChunk(SIGNAL_CHANNEL, 0);
m_signalDecoder->process();
if (m_signalDecoder->isOutputTriggerActive(OVP_GD_Algorithm_SignalDecoder_OutputTriggerId_ReceivedHeader))
{
m_status |= SIGNAL_HEADER_DETECTED;
if (m_oMatrix[0]) { delete m_oMatrix[0]; }
m_oMatrix[0] = new CMatrix();
if (m_oMatrix[1]) { delete m_oMatrix[1]; }
m_oMatrix[1] = new CMatrix();
m_oMatrix[0]->copyDescription(*op_matrixSignal);
m_oMatrix[1]->copyDescription(*op_matrixSignal);
boxContext.markInputAsDeprecated(SIGNAL_CHANNEL, 0);
return true;
}
}
return false;
}
void CInputChannel::waitForSynchro()
{
waitForSynchroStimulation();
waitForSynchroSignal();
}
void CInputChannel::waitForSynchroStimulation()
{
if (hasSynchroStimulation()) { return; }
Kernel::IBoxIO& boxContext = m_boxAlgorithm->getDynamicBoxContext();
for (size_t i = 0; i < boxContext.getInputChunkCount(STIMULATION_CHANNEL); ++i) //Stimulation de l'input 1
{
ip_bufferStimulation = boxContext.getInputChunk(STIMULATION_CHANNEL, i);
m_stimDecoder->process();
m_stimulationSet = op_stimulationSet;
m_timeStimulationStart = boxContext.getInputChunkStartTime(STIMULATION_CHANNEL, i);
m_timeStimulationEnd = boxContext.getInputChunkEndTime(STIMULATION_CHANNEL, i);
for (size_t j = 0; j < m_stimulationSet->getStimulationCount(); ++j)
{
if (m_stimulationSet->getStimulationIdentifier(j) == m_synchroStimulation)
{
m_status |= STIMULATION_SYNCHRO_DETECTED;
m_timeStimulationPos = m_stimulationSet->getStimulationDate(j);
m_boxAlgorithm->getLogManager() << Kernel::LogLevel_Info << "Get Synchronisation Stimulation at channel " << STIMULATION_CHANNEL << "\n";
return;
}
}
boxContext.markInputAsDeprecated(STIMULATION_CHANNEL, i);
}
}
void CInputChannel::waitForSynchroSignal()
{
if (m_timeStimulationStart == 0 || hasSynchroSignal()) { return; }
Kernel::IBoxIO& boxContext = m_boxAlgorithm->getDynamicBoxContext();
if (hasSynchroStimulation())
{
for (size_t i = 0; i < boxContext.getInputChunkCount(SIGNAL_CHANNEL); ++i) //Stimulation de l'input 1
{
m_timeSignalStart = boxContext.getInputChunkStartTime(SIGNAL_CHANNEL, i);
m_timeSignalEnd = boxContext.getInputChunkEndTime(SIGNAL_CHANNEL, i);
if ((m_timeStimulationPos >= m_timeSignalStart) && (m_timeStimulationPos < m_timeSignalEnd)) { processSynchroSignal(); }
boxContext.markInputAsDeprecated(SIGNAL_CHANNEL, i);
if (hasSynchroSignal()) { break; }
}
}
else
{
for (size_t i = 0; i < boxContext.getInputChunkCount(SIGNAL_CHANNEL); ++i) //Stimulation de l'input 1
{
m_timeSignalEnd = boxContext.getInputChunkEndTime(SIGNAL_CHANNEL, i);
if (m_timeSignalEnd < m_timeStimulationStart) { boxContext.markInputAsDeprecated(SIGNAL_CHANNEL, i); }
}
}
}
void CInputChannel::processSynchroSignal()
{
m_status |= SIGNAL_SYNCHRO_DETECTED;
m_nChannels = m_oMatrix[0]->getDimensionSize(0);
m_nSamples = m_oMatrix[0]->getDimensionSize(1);
m_firstBlock = size_t(double(m_nSamples * (m_timeStimulationPos - m_timeSignalStart)) / double(m_timeSignalEnd - m_timeSignalStart));
m_secondBlock = m_nSamples - m_firstBlock;
m_timeSignalPos = m_timeSignalEnd;
copyData(false, m_ptrMatrixIdx);
m_boxAlgorithm->getLogManager() << Kernel::LogLevel_Info << "Cutting parameter for both part : " << m_firstBlock << "+" << m_secondBlock << "\n";
}
IStimulationSet* CInputChannel::getStimulation(uint64_t& startTimestamp, uint64_t& endTimestamp, const size_t stimulationIndex)
{
Kernel::IBoxIO& boxContext = m_boxAlgorithm->getDynamicBoxContext();
ip_bufferStimulation = boxContext.getInputChunk(STIMULATION_CHANNEL, stimulationIndex);
m_stimDecoder->process();
m_stimulationSet = op_stimulationSet;
startTimestamp = m_hasFirstStimulation ? boxContext.getInputChunkStartTime(STIMULATION_CHANNEL, stimulationIndex) : m_timeStimulationPos;
endTimestamp = boxContext.getInputChunkEndTime(STIMULATION_CHANNEL, stimulationIndex);
m_hasFirstStimulation = true;
boxContext.markInputAsDeprecated(STIMULATION_CHANNEL, stimulationIndex);
return m_stimulationSet;
}
CMatrix* CInputChannel::getSignal(uint64_t& startTimestamp, uint64_t& endTimestamp, const size_t signalIndex)
{
Kernel::IBoxIO& boxContext = m_boxAlgorithm->getDynamicBoxContext();
ip_bufferSignal = boxContext.getInputChunk(SIGNAL_CHANNEL, signalIndex);
m_signalDecoder->process();
if (!m_signalDecoder->isOutputTriggerActive(OVP_GD_Algorithm_SignalDecoder_OutputTriggerId_ReceivedBuffer)) { return nullptr; }
startTimestamp = boxContext.getInputChunkStartTime(SIGNAL_CHANNEL, signalIndex);
endTimestamp = boxContext.getInputChunkEndTime(SIGNAL_CHANNEL, signalIndex);
copyData(true, m_ptrMatrixIdx);
copyData(false, m_ptrMatrixIdx + 1);
boxContext.markInputAsDeprecated(SIGNAL_CHANNEL, signalIndex);
return getMatrix();
}
void CInputChannel::copyData(const bool copyFirstBlock, const size_t matrixIndex)
{
CMatrix*& buffer = m_oMatrix[matrixIndex & 1];
double* src = op_matrixSignal->getBuffer() + (copyFirstBlock ? 0 : m_firstBlock);
double* dst = buffer->getBuffer() + (copyFirstBlock ? m_secondBlock : 0);
const size_t size = (copyFirstBlock ? m_firstBlock : m_secondBlock) * sizeof(double);
for (size_t i = 0; i < m_nChannels; i++, src += m_nSamples, dst += m_nSamples) { memcpy(dst, src, size_t(size)); }
}
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,102 @@
#pragma once
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
#define SET_BIT(bit) (1 << bit)
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
class CInputChannel
{
typedef enum
{
NOT_STARTED = 0,
SIGNAL_HEADER_DETECTED = SET_BIT(0),
STIMULATION_SYNCHRO_DETECTED = SET_BIT(1),
SIGNAL_SYNCHRO_DETECTED = SET_BIT(2),
IN_WORK = SET_BIT(3),
} status_t;
typedef enum
{
SIGNAL_CHANNEL,
STIMULATION_CHANNEL,
} channel_t;
public:
CInputChannel();
~CInputChannel();
bool initialize(Toolkit::TBoxAlgorithm<IBoxAlgorithm>* boxAlgorithm);
bool uninitialize();
bool hasHeader() const { return (m_status & SIGNAL_HEADER_DETECTED) != 0; }
bool hasSynchro() const { return hasSynchroStimulation() && hasSynchroSignal(); }
bool isWorking() const { return (m_status & IN_WORK) != 0; }
bool waitForSignalHeader();
void waitForSynchro();
void startWorking() { m_status |= IN_WORK; }
uint64_t getStimulationPosition() const { return m_timeStimulationPos; }
uint64_t getSignalPosition() const { return m_timeSignalPos; }
size_t getNStimulationBuffers() const { return m_boxAlgorithm->getDynamicBoxContext().getInputChunkCount(STIMULATION_CHANNEL); }
size_t getNSignalBuffers() const { return m_boxAlgorithm->getDynamicBoxContext().getInputChunkCount(SIGNAL_CHANNEL); }
IStimulationSet* getStimulation(uint64_t& startTimestamp, uint64_t& endTimestamp, size_t stimulationIndex);
CMatrix* getSignal(uint64_t& startTimestamp, uint64_t& endTimestamp, size_t signalIndex);
CMatrix* getMatrixPtr() { return m_oMatrix[m_ptrMatrixIdx & 1]; }
uint64_t getSamplingRate() const { return op_sampling; }
private:
bool hasSynchroStimulation() const { return (m_status & STIMULATION_SYNCHRO_DETECTED) != 0; }
bool hasSynchroSignal() const { return (m_status & SIGNAL_SYNCHRO_DETECTED) != 0; }
void waitForSynchroStimulation();
void waitForSynchroSignal();
void processSynchroSignal();
CMatrix* getMatrix() { return m_oMatrix[m_ptrMatrixIdx++ & 1]; }
void copyData(bool copyFirstBlock, size_t matrixIndex);
protected:
uint16_t m_status = 0;
CMatrix* m_oMatrix[2];
uint64_t m_ptrMatrixIdx = 0;
uint64_t m_synchroStimulation = 0;
uint64_t m_timeStimulationPos = 0;
uint64_t m_timeStimulationStart = 0;
uint64_t m_timeStimulationEnd = 0;
bool m_hasFirstStimulation = false;
uint64_t m_timeSignalPos = 0;
uint64_t m_timeSignalStart = 0;
uint64_t m_timeSignalEnd = 0;
size_t m_firstBlock = 0;
size_t m_secondBlock = 0;
size_t m_nSamples = 0;
size_t m_nChannels = 0;
bool m_hasFirstChunk = false;
IStimulationSet* m_stimulationSet = nullptr;
// parent memory
Toolkit::TBoxAlgorithm<IBoxAlgorithm>* m_boxAlgorithm = nullptr;
// signal section
Kernel::IAlgorithmProxy* m_signalDecoder = nullptr;
Kernel::TParameterHandler<const IMemoryBuffer*> ip_bufferSignal;
Kernel::TParameterHandler<CMatrix*> op_matrixSignal;
Kernel::TParameterHandler<uint64_t> op_sampling;
// stimulation section
Kernel::IAlgorithmProxy* m_stimDecoder = nullptr;
Kernel::TParameterHandler<const IMemoryBuffer*> ip_bufferStimulation;
Kernel::TParameterHandler<IStimulationSet*> op_stimulationSet;
};
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,297 @@
#include "ovpCModTemporalFilterBoxAlgorithm.h"
#include <cstdlib>
#include <cerrno>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
bool CModTemporalFilterBoxAlgorithm::initialize()
{
m_hasBeenInit = false;
m_decoder = &getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_SignalDecoder));
m_encoder = &getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_SignalEncoder));
m_decoder->initialize();
m_encoder->initialize();
ip_bufferToDecode.initialize(m_decoder->getInputParameter(OVP_GD_Algorithm_SignalDecoder_InputParameterId_MemoryBufferToDecode));
op_encodedBuffer.initialize(m_encoder->getOutputParameter(OVP_GD_Algorithm_SignalEncoder_OutputParameterId_EncodedMemoryBuffer));
// Compute filter coeff algorithm
m_computeModTemporalFilterCoefs = &getAlgorithmManager().getAlgorithm(
getAlgorithmManager().createAlgorithm(OVP_ClassId_Algorithm_ComputeTemporalFilterCoefs));
m_computeModTemporalFilterCoefs->initialize();
// Apply filter to signal input buffer
m_applyModTemporalFilter = &getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_ClassId_Algorithm_ApplyTemporalFilter));
m_applyModTemporalFilter->initialize();
m_lastEndTime = 0;
m_encoder->getInputParameter(OVP_GD_Algorithm_SignalEncoder_InputParameterId_Sampling)->setReferenceTarget(
m_decoder->getOutputParameter(OVP_GD_Algorithm_SignalDecoder_OutputParameterId_Sampling));
m_filterMethod = CString("");
m_filterType = CString("");
m_filterOrder = CString("");
m_lowBand = CString("");
m_highBand = CString("");
m_passBandRiple = CString("");
if (!updateSettings())
{
this->getLogManager() << Kernel::LogLevel_Error << "The box cannot be initialized.\n";
return false;
}
m_computeModTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_Sampling)->setReferenceTarget(
m_decoder->getOutputParameter(OVP_GD_Algorithm_SignalDecoder_OutputParameterId_Sampling));
// apply filter settings
m_applyModTemporalFilter->getInputParameter(OVP_Algorithm_ApplyTemporalFilter_InputParameterId_SignalMatrix)->setReferenceTarget(
m_decoder->getOutputParameter(OVP_GD_Algorithm_SignalDecoder_OutputParameterId_Matrix));
m_applyModTemporalFilter->getInputParameter(OVP_Algorithm_ApplyTemporalFilter_InputParameterId_FilterCoefsMatrix)->setReferenceTarget(
m_computeModTemporalFilterCoefs->getOutputParameter(
OVP_Algorithm_ComputeTemporalFilterCoefs_OutputParameterId_Matrix));
m_encoder->getInputParameter(OVP_GD_Algorithm_SignalEncoder_InputParameterId_Matrix)->setReferenceTarget(
m_applyModTemporalFilter->getOutputParameter(OVP_Algorithm_ApplyTemporalFilter_OutputParameterId_FilteredSignalMatrix));
return true;
}
bool CModTemporalFilterBoxAlgorithm::updateSettings()
{
bool retVal = false;
bool error = false;
char* endPtr = nullptr;
//get the settings
const CString filter = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
const CString kindFilter = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1);
const CString filterOrder = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2);
const CString lowPassBandEdge = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 3);
const CString highPassBandEdge = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 4);
const CString passBandRipple = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 5);
if (m_filterMethod != filter)
{
const uint64_t parameter = this->getTypeManager().getEnumerationEntryValueFromName(OVP_TypeId_FilterMethod, filter);
if (parameter == CIdentifier::undefined().id())
{
this->getLogManager() << Kernel::LogLevel_Error << "Unrecognized filter method " << filter << ".\n";
error = true;
}
else
{
Kernel::TParameterHandler<uint64_t> ip_nameFilter(
m_computeModTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_FilterMethod));
ip_nameFilter = parameter;
retVal = true;
}
m_filterMethod = filter; //We set up the new value to avoid to repeat the error log over and over again
}
if (m_filterType != kindFilter)
{
const uint64_t parameter = this->getTypeManager().getEnumerationEntryValueFromName(OVP_TypeId_FilterType, kindFilter);
if (parameter == CIdentifier::undefined().id())
{
this->getLogManager() << Kernel::LogLevel_Error << "Unrecognized filter type " << kindFilter << ".\n";
error = true;
}
else
{
Kernel::TParameterHandler<uint64_t> ip_kindFilter(
m_computeModTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_FilterType));
ip_kindFilter = parameter;
retVal = true;
}
m_filterType = kindFilter; //We set up the new value to avoid to repeat the error log over and over again
}
if (m_filterOrder != filterOrder)
{
errno = 0;
const int64_t parameter = strtol(filterOrder, &endPtr, 10);
if (parameter <= 0 || (errno != 0 && parameter == 0) || *endPtr != '\0' || errno == ERANGE)
{
this->getLogManager() << Kernel::LogLevel_Error << "Wrong filter order (" << filterOrder << "). Should be one or more.\n";
error = true;
}
else
{
Kernel::TParameterHandler<uint64_t> ip_filterOrder(
m_computeModTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_FilterOrder));
ip_filterOrder = parameter;
retVal = true;
}
m_filterOrder = filterOrder; //We set up the new value to avoid to repeat the error log over and over again
}
if (m_lowBand != lowPassBandEdge)
{
Kernel::TParameterHandler<double> ip_highCutFrequency(
m_computeModTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_HighCutFrequency));
errno = 0;
const double parameter = strtod(lowPassBandEdge, &endPtr);
if (parameter < 0 || (errno != 0 && parameter == 0) || *endPtr != '\0' || errno == ERANGE)
{
this->getLogManager() << Kernel::LogLevel_Error << "Wrong low cut frequency (" << lowPassBandEdge << " Hz). Should be positive.\n";
error = true;
}
else if (m_hasBeenInit && parameter > double(ip_highCutFrequency)
)//If it's not the first init we need to check that we do not set a wrong frequency according to the high one
{
this->getLogManager() << Kernel::LogLevel_Error << "Wrong low cut frequency (" << lowPassBandEdge << " Hz). Should be under the high cut frequency "
<< double(ip_highCutFrequency) << " Hz.\n";
error = true;
}
else
{
Kernel::TParameterHandler<double> ip_lowCutFrequency(
m_computeModTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_LowCutFrequency));
ip_lowCutFrequency = parameter;
retVal = true;
}
m_lowBand = lowPassBandEdge;
}
if (m_highBand != highPassBandEdge)
{
Kernel::TParameterHandler<double> ip_lowCutFrequency(
m_computeModTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_LowCutFrequency));
errno = 0;
const double parameter = strtod(highPassBandEdge, &endPtr);
if (parameter < 0 || (errno != 0 && parameter == 0) || *endPtr != '\0' || errno == ERANGE)
{
this->getLogManager() << Kernel::LogLevel_Error << "Wrong high cut frequency (" << highPassBandEdge << " Hz). Should be positive.\n";
error = true;
}
else if (parameter < double(ip_lowCutFrequency))
{
this->getLogManager() << Kernel::LogLevel_Error << "Wrong high cut frequency (" << highPassBandEdge << " Hz). Should be over the low cut frequency "
<< double(ip_lowCutFrequency) << " Hz.\n";
error = true;
}
else
{
Kernel::TParameterHandler<double> ip_highCutFrequency(
m_computeModTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_HighCutFrequency));
ip_highCutFrequency = parameter;
retVal = true;
}
m_highBand = highPassBandEdge;
}
if (m_passBandRiple != passBandRipple)
{
errno = 0;
const double parameter = strtod(passBandRipple, &endPtr);
if ((errno != 0 && parameter == 0) || *endPtr != '\0' || errno == ERANGE)
{
this->getLogManager() << Kernel::LogLevel_Error << "Wrong pass band ripple (" << passBandRipple << " dB).\n";
error = true;
}
else
{
Kernel::TParameterHandler<double> ip_passBandRipple(
m_computeModTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_BandPassRipple));
ip_passBandRipple = parameter;
retVal = true;
}
m_passBandRiple = passBandRipple;
}
//If it was the original init we return false to stop the init process
if (!m_hasBeenInit && error) { return false; }
m_hasBeenInit = true;
return retVal;
}
bool CModTemporalFilterBoxAlgorithm::compute()
{
//compute filter coeff
if (!m_computeModTemporalFilterCoefs->process(OVP_Algorithm_ComputeTemporalFilterCoefs_InputTriggerId_Initialize)) { return false; }
if (!m_computeModTemporalFilterCoefs->process(OVP_Algorithm_ComputeTemporalFilterCoefs_InputTriggerId_ComputeCoefs)) { return false; }
if (!m_applyModTemporalFilter->process(OVP_Algorithm_ApplyTemporalFilter_InputTriggerId_Initialize)) { return false; }
return true;
}
bool CModTemporalFilterBoxAlgorithm::uninitialize()
{
m_applyModTemporalFilter->uninitialize();
m_computeModTemporalFilterCoefs->uninitialize();
m_encoder->uninitialize();
m_decoder->uninitialize();
getAlgorithmManager().releaseAlgorithm(*m_applyModTemporalFilter);
getAlgorithmManager().releaseAlgorithm(*m_computeModTemporalFilterCoefs);
getAlgorithmManager().releaseAlgorithm(*m_encoder);
getAlgorithmManager().releaseAlgorithm(*m_decoder);
return true;
}
bool CModTemporalFilterBoxAlgorithm::processInput(const size_t /*index*/)
{
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
return true;
}
bool CModTemporalFilterBoxAlgorithm::process()
{
Kernel::IBoxIO& boxContext = getDynamicBoxContext();
const size_t nInput = getStaticBoxContext().getInputCount();
for (size_t i = 0; i < nInput; ++i)
{
for (size_t j = 0; j < boxContext.getInputChunkCount(i); ++j)
{
//TParameterHandler < const IMemoryBuffer* > iBufferHandle(m_decoder->getInputParameter(OVP_GD_Algorithm_SignalDecoder_InputParameterId_MemoryBufferToDecode));
//TParameterHandler < IMemoryBuffer* > oBufferHandle(m_encoder->getOutputParameter(OVP_GD_Algorithm_SignalEncoder_OutputParameterId_EncodedMemoryBuffer));
//iBufferHandle=boxContext.getInputChunk(i, j);
//oBufferHandle=boxContext.getOutputChunk(i);
ip_bufferToDecode = boxContext.getInputChunk(i, j);
op_encodedBuffer = boxContext.getOutputChunk(i);
const uint64_t start = boxContext.getInputChunkStartTime(i, j);
const uint64_t end = boxContext.getInputChunkEndTime(i, j);
if (!m_decoder->process()) { return false; }
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_SignalDecoder_OutputTriggerId_ReceivedHeader))
{
compute();
if (!m_encoder->process(OVP_GD_Algorithm_SignalEncoder_InputTriggerId_EncodeHeader)) { return false; }
boxContext.markOutputAsReadyToSend(i, start, end);
}
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_SignalDecoder_OutputTriggerId_ReceivedBuffer))
{
//recompute if the settings have changed only
if (updateSettings() && !compute()) { this->getLogManager() << Kernel::LogLevel_Error << "error during computation\n"; }
if (m_lastEndTime == start)
{
if (!m_applyModTemporalFilter->process(OVP_Algorithm_ApplyTemporalFilter_InputTriggerId_ApplyFilterWithHistoric)) { return false; }
}
else { if (!m_applyModTemporalFilter->process(OVP_Algorithm_ApplyTemporalFilter_InputTriggerId_ApplyFilter)) { return false; } }
if (!m_encoder->process(OVP_GD_Algorithm_SignalEncoder_InputTriggerId_EncodeBuffer)) { return false; }
boxContext.markOutputAsReadyToSend(i, start, end);
}
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_SignalDecoder_OutputTriggerId_ReceivedEnd))
{
if (!m_encoder->process(OVP_GD_Algorithm_SignalEncoder_InputTriggerId_EncodeEnd)) { return false; }
boxContext.markOutputAsReadyToSend(i, start, end);
}
m_lastEndTime = end;
boxContext.markInputAsDeprecated(i, j);
}
}
return true;
}
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,98 @@
// @copyright notice: Possibly due to dependencies, this box used to be GPL before upgrade to AGPL3
#pragma once
#include "../ovp_defines.h"
#include <toolkit/ovtk_all.h>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
class CModTemporalFilterBoxAlgorithm final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
{
public:
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool processInput(const size_t index) override;
bool process() override;
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_Box_ModTemporalFilterBoxAlgorithm)
protected:
//update the settings value from the UI
//return true if any setting has changed
bool updateSettings();
//compute the filter coeff
//return false if failed
bool compute();
Kernel::IAlgorithmProxy* m_decoder = nullptr;
Kernel::IAlgorithmProxy* m_encoder = nullptr;
Kernel::IAlgorithmProxy* m_computeModTemporalFilterCoefs = nullptr;
Kernel::IAlgorithmProxy* m_applyModTemporalFilter = nullptr;
Kernel::TParameterHandler<const IMemoryBuffer*> ip_bufferToDecode;
Kernel::TParameterHandler<IMemoryBuffer*> op_encodedBuffer;
uint64_t m_lastEndTime = 0;
//setting last value to avoid recompute if they haven't changed
CString m_filterMethod;
CString m_filterType;
CString m_filterOrder;
CString m_lowBand;
CString m_highBand;
CString m_passBandRiple;
bool m_hasBeenInit = false;
};
class CModTemporalFilterBoxAlgorithmDesc final : virtual public IBoxAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return CString("Modifiable Temporal filter"); }
CString getAuthorName() const override { return CString("Guillaume Gibert / lmahe"); }
CString getAuthorCompanyName() const override { return CString("INSERM/U821 INRIA"); }
CString getShortDescription() const override { return CString("Applies temporal filtering on time signal, modifiable parameters"); }
CString getDetailedDescription() const override
{
return CString("The user can choose among a variety of filter types to process the signal and change the settings online");
}
CString getCategory() const override { return CString("Signal processing/Temporal Filtering"); }
CString getVersion() const override { return CString("1.0"); }
CString getStockItemName() const override { return CString(""); }
CIdentifier getCreatedClass() const override { return OVP_ClassId_Box_ModTemporalFilterBoxAlgorithm; }
IPluginObject* create() override { return new CModTemporalFilterBoxAlgorithm(); }
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
{
prototype.addInput("Input signal", OV_TypeId_Signal);
prototype.addOutput("Filtered signal", OV_TypeId_Signal);
prototype.addSetting("Filter method", OVP_TypeId_FilterMethod, "Butterworth", true);
prototype.addSetting("Filter type", OVP_TypeId_FilterType, "Band Pass", true);
prototype.addSetting("Filter order", OV_TypeId_Integer, "4", true);
prototype.addSetting("Low cut frequency (Hz)", OV_TypeId_Float, "29", true);
prototype.addSetting("High cut frequency (Hz)", OV_TypeId_Float, "40", true);
prototype.addSetting("Pass band ripple (dB)", OV_TypeId_Float, "0.5", true);
prototype.addFlag(OV_AttributeId_Box_FlagIsUnstable);
return true;
}
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_Box_ModTemporalFilterBoxAlgorithmDesc)
};
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,102 @@
#include "ovpCOutputChannel.h"
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
bool COutputChannel::initialize(Toolkit::TBoxAlgorithm<IBoxAlgorithm>* boxAlgorithm)
{
m_boxAlgorithm = boxAlgorithm;
m_signalEncoder = &m_boxAlgorithm->getAlgorithmManager().getAlgorithm(
m_boxAlgorithm->getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_SignalEncoder));
m_signalEncoder->initialize();
op_bufferSignal.initialize(m_signalEncoder->getOutputParameter(OVP_GD_Algorithm_SignalEncoder_OutputParameterId_EncodedMemoryBuffer));
ip_matrixSignal.initialize(m_signalEncoder->getInputParameter(OVP_GD_Algorithm_SignalEncoder_InputParameterId_Matrix));
ip_sampling.initialize(m_signalEncoder->getInputParameter(OVP_GD_Algorithm_SignalEncoder_InputParameterId_Sampling));
m_stimEncoder = &m_boxAlgorithm->getAlgorithmManager().getAlgorithm(
m_boxAlgorithm->getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StimulationEncoder));
m_stimEncoder->initialize();
op_bufferStimulation.initialize(m_stimEncoder->getOutputParameter(OVP_GD_Algorithm_StimulationEncoder_OutputParameterId_EncodedMemoryBuffer));
ip_stimulationSet.initialize(m_stimEncoder->getInputParameter(OVP_GD_Algorithm_StimulationEncoder_InputParameterId_StimulationSet));
return true;
}
bool COutputChannel::uninitialize()
{
ip_sampling.uninitialize();
ip_matrixSignal.uninitialize();
op_bufferSignal.uninitialize();
m_signalEncoder->uninitialize();
m_boxAlgorithm->getAlgorithmManager().releaseAlgorithm(*m_signalEncoder);
op_bufferStimulation.uninitialize();
ip_stimulationSet.uninitialize();
m_stimEncoder->uninitialize();
m_boxAlgorithm->getAlgorithmManager().releaseAlgorithm(*m_stimEncoder);
return true;
}
void COutputChannel::sendStimulation(IStimulationSet* stimset, const uint64_t startTime, const uint64_t endTime)
{
Kernel::IBoxIO& boxContext = m_boxAlgorithm->getDynamicBoxContext();
for (size_t j = 0; j < stimset->getStimulationCount(); ++j)
{
if (stimset->getStimulationDate(j) < m_timeStimulationPos)
{
stimset->removeStimulation(j);
j--;
}
else { stimset->setStimulationDate(j, stimset->getStimulationDate(j) - m_timeStimulationPos); }
}
ip_stimulationSet = stimset;
op_bufferStimulation = boxContext.getOutputChunk(STIMULATION_CHANNEL);
m_stimEncoder->process(OVP_GD_Algorithm_StimulationEncoder_InputTriggerId_EncodeBuffer);
boxContext.markOutputAsReadyToSend(STIMULATION_CHANNEL, startTime - m_timeStimulationPos, endTime - m_timeStimulationPos);
}
void COutputChannel::sendHeader(const size_t sampling, CMatrix* matrix)
{
Kernel::IBoxIO& boxContext = m_boxAlgorithm->getDynamicBoxContext();
m_buffer = matrix;
m_sampling = sampling;
op_bufferSignal = boxContext.getOutputChunk(SIGNAL_CHANNEL);
ip_matrixSignal = m_buffer;
ip_sampling = m_sampling;
//copy channel names
for (size_t i = 0; i < matrix->getDimensionSize(0); ++i) { ip_matrixSignal->setDimensionLabel(0, i, matrix->getDimensionLabel(0, i)); }
m_signalEncoder->process(OVP_GD_Algorithm_SignalEncoder_InputTriggerId_EncodeHeader);
boxContext.markOutputAsReadyToSend(SIGNAL_CHANNEL, 0, 0);
}
void COutputChannel::sendSignal(CMatrix* matrix, const uint64_t startTime, const uint64_t endTime)
{
Kernel::IBoxIO& boxContext = m_boxAlgorithm->getDynamicBoxContext();
op_bufferSignal = boxContext.getOutputChunk(SIGNAL_CHANNEL);
ip_matrixSignal = matrix;
ip_sampling = m_sampling;
m_signalEncoder->process(OVP_GD_Algorithm_SignalEncoder_InputTriggerId_EncodeBuffer);
boxContext.markOutputAsReadyToSend(SIGNAL_CHANNEL, startTime - m_timeSignalPos, endTime - m_timeSignalPos);
}
void COutputChannel::processSynchroSignal(const uint64_t stimulationPos, const uint64_t signalPos)
{
m_timeStimulationPos = stimulationPos;
m_timeSignalPos = signalPos;
}
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,54 @@
#pragma once
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
class COutputChannel
{
typedef enum
{
SIGNAL_CHANNEL,
STIMULATION_CHANNEL,
} channel_t;
public:
bool initialize(Toolkit::TBoxAlgorithm<IBoxAlgorithm>* boxAlgorithm);
bool uninitialize();
void sendStimulation(IStimulationSet* stimset, uint64_t startTime, uint64_t endTime);
void sendSignal(CMatrix* matrix, uint64_t startTime, uint64_t endTime);
void sendHeader(const size_t sampling, CMatrix* matrix);
void processSynchroSignal(uint64_t stimulationPos, uint64_t signalPos);
protected:
CMatrix* m_buffer = nullptr;
uint64_t m_timeStimulationPos = 0;
uint64_t m_timeSignalPos = 0;
uint64_t m_sampling = 0;
// parent memory
Toolkit::TBoxAlgorithm<IBoxAlgorithm>* m_boxAlgorithm = nullptr;
// signal section
Kernel::IAlgorithmProxy* m_signalEncoder = nullptr;
Kernel::TParameterHandler<IMemoryBuffer*> op_bufferSignal;
Kernel::TParameterHandler<CMatrix*> ip_matrixSignal;
Kernel::TParameterHandler<uint64_t> ip_sampling;
// stimulation section
Kernel::IAlgorithmProxy* m_stimEncoder = nullptr;
Kernel::TParameterHandler<IMemoryBuffer*> op_bufferStimulation;
Kernel::TParameterHandler<IStimulationSet*> ip_stimulationSet;
};
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,198 @@
#if defined TARGET_HAS_ThirdPartyITPP
#include "ovpCSpectralAnalysis.h"
#include <iostream>
#include <itpp/itstat.h>
#include <itpp/itsignal.h>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
bool CSpectralAnalysis::initialize()
{
//reads the plugin settings
const CString setting = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
const uint64_t components = this->getTypeManager().getBitMaskEntryCompositionValueFromName(OVP_TypeId_SpectralComponent, setting);
m_amplitudeSpectrum = ((components & uint64_t(ESpectralComponent::Amplitude)) > 0);
m_phaseSpectrum = ((components & uint64_t(ESpectralComponent::Phase)) > 0);
m_realPartSpectrum = ((components & uint64_t(ESpectralComponent::RealPart)) > 0);
m_imagPartSpectrum = ((components & uint64_t(ESpectralComponent::ImaginaryPart)) > 0);
m_decoder.initialize(*this, 0);
for (size_t i = 0; i < 4; ++i) { m_encoders[i].initialize(*this, i); }
return true;
}
bool CSpectralAnalysis::uninitialize()
{
for (size_t i = 0; i < 4; ++i) { m_encoders[i].uninitialize(); }
m_decoder.uninitialize();
return true;
}
bool CSpectralAnalysis::processInput(const size_t /*index*/)
{
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
return true;
}
bool CSpectralAnalysis::process()
{
Kernel::IBoxIO* context = getBoxAlgorithmContext()->getDynamicBoxContext();
const size_t nInputChunk = context->getInputChunkCount(0);
char frequencyBandName[1024];
for (size_t idx = 0; idx < nInputChunk; ++idx)
{
m_lastChunkStartTime = context->getInputChunkStartTime(0, idx);
m_lastChunkEndTime = context->getInputChunkEndTime(0, idx);
m_decoder.decode(idx);
if (m_decoder.isHeaderReceived())//dealing with the signal header
{
//get signal info
m_nSample = m_decoder.getOutputMatrix()->getDimensionSize(1);
m_nChannel = m_decoder.getOutputMatrix()->getDimensionSize(0);
m_sampling = size_t(m_decoder.getOutputSamplingRate());
if (m_nSample == 0)
{
this->getLogManager() << Kernel::LogLevel_Error << "Chunk size appears to be 0, not supported.\n";
return false;
}
if (m_nChannel == 0)
{
this->getLogManager() << Kernel::LogLevel_Error << "Channel count appears to be 0, not supported.\n";
return false;
}
if (m_sampling == 0)
{
this->getLogManager() << Kernel::LogLevel_Error << "Sampling rate appears to be 0, not supported.\n";
return false;
}
//we need two matrices for the spectrum encoders, the Frequency bands and the one inherited form streamed matrix (see doc for details)
CMatrix* frequencyBands = new CMatrix();
CMatrix* streamedMatrix = new CMatrix();
// For real signals, if N is sample count, bins [0,N/2] (inclusive) contain non-redundant information, i.e. N/2+1 entries.
m_halfFFTSize = m_nSample / 2 + 1;
m_nFrequencyBand = m_halfFFTSize;
streamedMatrix->copyDescription(*m_decoder.getOutputMatrix());
streamedMatrix->setDimensionSize(1, m_nFrequencyBand);
frequencyBands->resize(m_nFrequencyBand);
double* buffer = frequencyBands->getBuffer();
// @fixme would be more proper to use 'bins', one bin with a hz tag per array entry
for (size_t j = 0; j < m_nFrequencyBand; ++j)
{
buffer[j] = j * (double(m_sampling) / m_nSample);
sprintf(frequencyBandName, "%lg", buffer[j]);
streamedMatrix->setDimensionLabel(0, j, frequencyBandName);//set the names of the frequency bands
}
for (size_t j = 0; j < 4; ++j)
{
//copy the information for each encoder
m_encoders[j].getInputFrequencyAbscissa()->copy(*frequencyBands);
m_encoders[j].getInputMatrix()->copy(*streamedMatrix);
m_encoders[j].getInputSamplingRate().setReferenceTarget(m_decoder.getOutputSamplingRate());
}
if (m_amplitudeSpectrum)
{
m_encoders[0].encodeHeader();
context->markOutputAsReadyToSend(0, m_lastChunkStartTime, m_lastChunkEndTime);
}
if (m_phaseSpectrum)
{
m_encoders[1].encodeHeader();
context->markOutputAsReadyToSend(1, m_lastChunkStartTime, m_lastChunkEndTime);
}
if (m_realPartSpectrum)
{
m_encoders[2].encodeHeader();
context->markOutputAsReadyToSend(2, m_lastChunkStartTime, m_lastChunkEndTime);
}
if (m_imagPartSpectrum)
{
m_encoders[3].encodeHeader();
context->markOutputAsReadyToSend(3, m_lastChunkStartTime, m_lastChunkEndTime);
}
delete frequencyBands;
delete streamedMatrix;
}
if (m_decoder.isBufferReceived())
{
//get input buffer
const double* buffer = m_decoder.getOutputMatrix()->getBuffer();
//do the processing
itpp::vec x(m_nSample);
itpp::cvec y(m_nSample);
itpp::cvec z(m_nChannel * m_halfFFTSize);
for (size_t i = 0; i < m_nChannel; ++i)
{
for (size_t j = 0; j < m_nSample; ++j) { x[j] = double(*(buffer + i * m_nSample + j)); }
y = fft_real(x);
//test block
// itpp::vec h = ifft_real(y);
// std::cout << "Fx: " << x.size() << ", x=" << x << "\n" << "FF: " << y.size() << ", y=" << y << "\n" << "Fr: " << h.size() << ", x'=" << h << "\n";
for (size_t k = 0; k < m_halfFFTSize; ++k) { z[k + i * m_halfFFTSize] = y[k]; }
}
if (m_amplitudeSpectrum)
{
CMatrix* matrix = m_encoders[0].getInputMatrix();
double* buf = matrix->getBuffer();
for (size_t i = 0; i < m_nChannel * m_halfFFTSize; ++i) { *(buf + i) = sqrt(real(z[i]) * real(z[i]) + imag(z[i]) * imag(z[i])); }
m_encoders[0].encodeBuffer();
context->markOutputAsReadyToSend(0, m_lastChunkStartTime, m_lastChunkEndTime);
}
if (m_phaseSpectrum)
{
CMatrix* matrix = m_encoders[1].getInputMatrix();
double* buf = matrix->getBuffer();
for (size_t i = 0; i < m_nChannel * m_halfFFTSize; ++i) { *(buf + i) = imag(z[i]) / real(z[i]); }
m_encoders[1].encodeBuffer();
context->markOutputAsReadyToSend(1, m_lastChunkStartTime, m_lastChunkEndTime);
}
if (m_realPartSpectrum)
{
CMatrix* matrix = m_encoders[2].getInputMatrix();
double* buf = matrix->getBuffer();
for (size_t i = 0; i < m_nChannel * m_halfFFTSize; ++i) { *(buf + i) = real(z[i]); }
m_encoders[2].encodeBuffer();
context->markOutputAsReadyToSend(2, m_lastChunkStartTime, m_lastChunkEndTime);
}
if (m_imagPartSpectrum)
{
CMatrix* matrix = m_encoders[3].getInputMatrix();
double* buf = matrix->getBuffer();
for (size_t i = 0; i < m_nChannel * m_halfFFTSize; ++i) { *(buf + i) = imag(z[i]); }
m_encoders[3].encodeBuffer();
context->markOutputAsReadyToSend(3, m_lastChunkStartTime, m_lastChunkEndTime);
}
}
context->markInputAsDeprecated(0, idx);
}
return true;
}
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
#endif
@@ -0,0 +1,97 @@
// @copyright notice: Possibly due to dependencies, this box used to be GPL before upgrade to AGPL3
#pragma once
#if defined TARGET_HAS_ThirdPartyITPP
#include "../ovp_defines.h"
#include <toolkit/ovtk_all.h>
#include <map>
#include <string>
#ifndef CString2Boolean
#define CString2Boolean(string) (strcmp(string,"true"))?0:1
#endif
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
/**
* The Spectral Anlaysis plugin's main class.
*/
class CSpectralAnalysis final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
{
public:
CSpectralAnalysis() { }
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool processInput(const size_t index) override;
bool process() override;
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_SpectralAnalysis)
private:
//start time and end time of the last arrived chunk
uint64_t m_lastChunkStartTime = 0;
uint64_t m_lastChunkEndTime = 0;
//codecs
Toolkit::TSignalDecoder<CSpectralAnalysis> m_decoder;
Toolkit::TSpectrumEncoder<CSpectralAnalysis> m_encoders[4];
///number of channels
size_t m_nChannel = 0;
size_t m_sampling = 0;
size_t m_nFrequencyBand = 0;
size_t m_nSample = 0;
size_t m_halfFFTSize = 1; // m_nSample / 2 + 1;
bool m_amplitudeSpectrum = false;
bool m_phaseSpectrum = false;
bool m_realPartSpectrum = false;
bool m_imagPartSpectrum = false;
};
class CSpectralAnalysisDesc final : virtual public IBoxAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return CString("Spectral Analysis (FFT)(INSERM contrib)"); }
CString getAuthorName() const override { return CString("Guillaume Gibert"); }
CString getAuthorCompanyName() const override { return CString("INSERM"); }
CString getShortDescription() const override { return CString("Compute spectral analysis using Fast Fourier Transform"); }
CString getDetailedDescription() const override { return CString(""); }
CString getCategory() const override { return CString("Signal processing/Spectral Analysis"); }
CString getVersion() const override { return CString("0.1"); }
CIdentifier getCreatedClass() const override { return OVP_ClassId_SpectralAnalysis; }
IPluginObject* create() override { return new CSpectralAnalysis(); }
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
{
prototype.addInput("Input signal", OV_TypeId_Signal);
prototype.addOutput("Amplitude", OV_TypeId_Spectrum);
prototype.addOutput("Phase", OV_TypeId_Spectrum);
prototype.addOutput("Real Part", OV_TypeId_Spectrum);
prototype.addOutput("Imag Part", OV_TypeId_Spectrum);
prototype.addSetting("Spectral components", OVP_TypeId_SpectralComponent, "Amplitude");
return true;
}
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_SpectralAnalysisDesc)
};
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyITPP
@@ -0,0 +1,206 @@
#include "ovpCTemporalFilterBoxAlgorithm.h"
#include <cstdlib>
#include <cerrno>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
bool CTemporalFilterBoxAlgorithm::initialize()
{
m_decoder = new Toolkit::TSignalDecoder<CTemporalFilterBoxAlgorithm>(*this, 0);
m_encoder = new Toolkit::TSignalEncoder<CTemporalFilterBoxAlgorithm>(*this, 0);
// Compute filter coeff algorithm
m_computeTemporalFilterCoefs = &getAlgorithmManager().getAlgorithm(
getAlgorithmManager().createAlgorithm(OVP_ClassId_Algorithm_ComputeTemporalFilterCoefs));
m_computeTemporalFilterCoefs->initialize();
// Apply filter to signal input buffer
m_applyTemporalFilter = &getAlgorithmManager().getAlgorithm(getAlgorithmManager().createAlgorithm(OVP_ClassId_Algorithm_ApplyTemporalFilter));
m_applyTemporalFilter->initialize();
m_lastEndTime = 0;
// compute filter coefs settings
const CString filter = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
const CString kindFilter = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1);
const CString order = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2);
const CString lowPassBandEdge = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 3);
const CString highPassBandEdge = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 4);
const CString passBandRipple = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 5);
bool initError = false;
char* endPtr = nullptr;
uint64_t uiParameter = this->getTypeManager().getEnumerationEntryValueFromName(OVP_TypeId_FilterMethod, filter);
if (uiParameter == CIdentifier::undefined().id())
{
this->getLogManager() << Kernel::LogLevel_Error << "Unrecognized filter method " << filter << ".\n";
initError = true;
}
Kernel::TParameterHandler<uint64_t> ip_nameFilter(
m_computeTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_FilterMethod));
ip_nameFilter = uiParameter;
uiParameter = this->getTypeManager().getEnumerationEntryValueFromName(OVP_TypeId_FilterType, kindFilter);
if (uiParameter == CIdentifier::undefined().id())
{
this->getLogManager() << Kernel::LogLevel_Error << "Unrecognized filter type " << kindFilter << ".\n";
initError = true;
}
Kernel::TParameterHandler<uint64_t> ip_kindFilter(
m_computeTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_FilterType));
ip_kindFilter = uiParameter;
errno = 0;
const int64_t intParameter = strtol(order, &endPtr, 10);
if (intParameter <= 0 || (errno != 0 && intParameter == 0) || *endPtr != '\0' || errno == ERANGE)
{
this->getLogManager() << Kernel::LogLevel_Error << "Wrong filter order (" << order << "). Should be one or more.\n";
initError = true;
}
Kernel::TParameterHandler<uint64_t> ip_filterOrder(
m_computeTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_FilterOrder));
ip_filterOrder = intParameter;
errno = 0;
double dParameter = strtod(lowPassBandEdge, &endPtr);
if (dParameter < 0 || (errno != 0 && dParameter == 0) || *endPtr != '\0' || errno == ERANGE)
{
this->getLogManager() << Kernel::LogLevel_Error << "Wrong low cut frequency (" << lowPassBandEdge << " Hz). Should be positive.\n";
initError = true;
}
Kernel::TParameterHandler<double> ip_lowCutFrequency(
m_computeTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_LowCutFrequency));
ip_lowCutFrequency = dParameter;
errno = 0;
dParameter = strtod(highPassBandEdge, &endPtr);
if (dParameter < 0 || (errno != 0 && dParameter == 0) || *endPtr != '\0' || errno == ERANGE)
{
this->getLogManager() << Kernel::LogLevel_Error << "Wrong high cut frequency (" << highPassBandEdge << " Hz). Should be positive.\n";
initError = true;
}
else if (dParameter < double(ip_lowCutFrequency))
{
this->getLogManager() << Kernel::LogLevel_Error << "Wrong high cut frequency (" << highPassBandEdge << " Hz). Should be over the low cut frequency "
<< lowPassBandEdge << " Hz.\n";
initError = true;
}
Kernel::TParameterHandler<double> ip_highCutFrequency(
m_computeTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_HighCutFrequency));
ip_highCutFrequency = dParameter;
errno = 0;
dParameter = strtod(passBandRipple, &endPtr);
if ((errno != 0 && dParameter == 0) || *endPtr != '\0' || errno == ERANGE)
{
this->getLogManager() << Kernel::LogLevel_Error << "Wrong pass band ripple (" << passBandRipple << " dB).\n";
initError = true;
}
Kernel::TParameterHandler<double> ip_passBandRipple(
m_computeTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_BandPassRipple));
ip_passBandRipple = dParameter;
Kernel::TParameterHandler<uint64_t>
ip_sampling(m_computeTemporalFilterCoefs->getInputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_Sampling));
ip_sampling.setReferenceTarget(m_decoder->getOutputSamplingRate());
// apply filter settings
m_applyTemporalFilter->getInputParameter(OVP_Algorithm_ApplyTemporalFilter_InputParameterId_FilterCoefsMatrix)->setReferenceTarget(
m_computeTemporalFilterCoefs->getOutputParameter(OVP_Algorithm_ComputeTemporalFilterCoefs_OutputParameterId_Matrix));
m_encoder->getInputMatrix().setReferenceTarget(
m_applyTemporalFilter->getOutputParameter(OVP_Algorithm_ApplyTemporalFilter_OutputParameterId_FilteredSignalMatrix));
m_encoder->getInputSamplingRate().setReferenceTarget(m_decoder->getOutputSamplingRate());
if (initError)
{
this->getLogManager() << Kernel::LogLevel_Error << "Something went wrong during the intialization. Desactivation of the box.\n";
return false;
}
return true;
}
bool CTemporalFilterBoxAlgorithm::uninitialize()
{
m_applyTemporalFilter->uninitialize();
getAlgorithmManager().releaseAlgorithm(*m_applyTemporalFilter);
m_computeTemporalFilterCoefs->uninitialize();
getAlgorithmManager().releaseAlgorithm(*m_computeTemporalFilterCoefs);
//codecs
m_encoder->uninitialize();
delete m_encoder;
m_decoder->uninitialize();
delete m_decoder;
return true;
}
bool CTemporalFilterBoxAlgorithm::processInput(const size_t /*index*/)
{
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
return true;
}
bool CTemporalFilterBoxAlgorithm::process()
{
Kernel::IBoxIO& boxContext = getDynamicBoxContext();
const size_t nInput = getStaticBoxContext().getInputCount();
for (size_t i = 0; i < nInput; ++i)
{
for (size_t j = 0; j < boxContext.getInputChunkCount(i); ++j)
{
const uint64_t tStart = boxContext.getInputChunkStartTime(i, j);
const uint64_t tEnd = boxContext.getInputChunkEndTime(i, j);
if (!m_decoder->decode(j)) { return false; }
//this has to be done here as it does not work if done once in initialize()
CMatrix* iMatrix = m_decoder->getOutputMatrix();
Kernel::TParameterHandler<CMatrix*> matrixToFilter = m_applyTemporalFilter->getInputParameter(
OVP_Algorithm_ApplyTemporalFilter_InputParameterId_SignalMatrix);
matrixToFilter.setReferenceTarget(iMatrix);
if (m_decoder->isHeaderReceived())
{
if (!m_computeTemporalFilterCoefs->process(OVP_Algorithm_ComputeTemporalFilterCoefs_InputTriggerId_Initialize)) { return false; }
if (!m_computeTemporalFilterCoefs->process(OVP_Algorithm_ComputeTemporalFilterCoefs_InputTriggerId_ComputeCoefs)) { return false; }
if (!m_applyTemporalFilter->process(OVP_Algorithm_ApplyTemporalFilter_InputTriggerId_Initialize)) { return false; }
if (!m_encoder->encodeHeader()) { return false; }
boxContext.markOutputAsReadyToSend(i, tStart, tEnd);
}
if (m_decoder->isBufferReceived())
{
if (m_lastEndTime == tStart)
{
if (!m_applyTemporalFilter->process(OVP_Algorithm_ApplyTemporalFilter_InputTriggerId_ApplyFilterWithHistoric)) { return false; }
}
else { if (!m_applyTemporalFilter->process(OVP_Algorithm_ApplyTemporalFilter_InputTriggerId_ApplyFilter)) { return false; } }
if (!m_encoder->encodeBuffer()) { return false; }
boxContext.markOutputAsReadyToSend(i, tStart, tEnd);
}
if (m_decoder->isEndReceived())
{
if (!m_encoder->encodeEnd()) { return false; }
boxContext.markOutputAsReadyToSend(i, tStart, tEnd);
}
// m_lastStartTime=tStart;
m_lastEndTime = tEnd;
boxContext.markInputAsDeprecated(i, j);
}
}
return true;
}
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,75 @@
// @copyright notice: Possibly due to dependencies, this box used to be GPL before upgrade to AGPL3
#pragma once
#include "../ovp_defines.h"
#include <toolkit/ovtk_all.h>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
class CTemporalFilterBoxAlgorithm final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
{
public:
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool processInput(const size_t index) override;
bool process() override;
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_Box_TemporalFilterBoxAlgorithm)
protected:
Toolkit::TSignalDecoder<CTemporalFilterBoxAlgorithm>* m_decoder = nullptr;
Toolkit::TSignalEncoder<CTemporalFilterBoxAlgorithm>* m_encoder = nullptr;
Kernel::IAlgorithmProxy* m_computeTemporalFilterCoefs = nullptr;
Kernel::IAlgorithmProxy* m_applyTemporalFilter = nullptr;
Kernel::TParameterHandler<const IMemoryBuffer*> ip_bufferToDecode;
Kernel::TParameterHandler<IMemoryBuffer*> op_encodedBuffer;
//uint64_t m_lastStartTime = 0;
uint64_t m_lastEndTime = 0;
};
class CTemporalFilterBoxAlgorithmDesc final : virtual public IBoxAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return CString("Temporal Filter (INSERM contrib)"); }
CString getAuthorName() const override { return CString("Guillaume Gibert"); }
CString getAuthorCompanyName() const override { return CString("INSERM/U821"); }
CString getShortDescription() const override { return CString("Applies temporal filtering on time signal"); }
CString getDetailedDescription() const override { return CString("The user can choose among a variety of filter types to process the signal"); }
CString getCategory() const override { return CString("Signal processing/Temporal Filtering"); }
CString getVersion() const override { return CString("1.0"); }
CString getStockItemName() const override { return CString(""); }
CIdentifier getCreatedClass() const override { return OVP_ClassId_Box_TemporalFilterBoxAlgorithm; }
IPluginObject* create() override { return new CTemporalFilterBoxAlgorithm(); }
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
{
prototype.addInput("Input signal", OV_TypeId_Signal);
prototype.addOutput("Filtered signal", OV_TypeId_Signal);
prototype.addSetting("Filter method", OVP_TypeId_FilterMethod, "Butterworth");
prototype.addSetting("Filter type", OVP_TypeId_FilterType, "Band Pass");
prototype.addSetting("Filter order", OV_TypeId_Integer, "4");
prototype.addSetting("Low cut frequency (Hz)", OV_TypeId_Float, "29");
prototype.addSetting("High cut frequency (Hz)", OV_TypeId_Float, "40");
prototype.addSetting("Pass band ripple (dB)", OV_TypeId_Float, "0.5");
return true;
}
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_Box_TemporalFilterBoxAlgorithmDesc)
};
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,115 @@
#if defined TARGET_HAS_ThirdPartyITPP
#include "ovpCWindowingFunctions.h"
#include <iostream>
#include <itpp/itcomm.h>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
void CWindowingFunctions::setSampleBuffer(const double* buffer) const
{
itpp::vec windows = itpp::ones(int(m_SamplesPerBuffer));
if (m_WindowMethod == EWindowMethod::Hamming) { windows = itpp::hamming(int(m_SamplesPerBuffer)); }
else if (m_WindowMethod == EWindowMethod::Hanning) { windows = itpp::hanning(int(m_SamplesPerBuffer)); }
else if (m_WindowMethod == EWindowMethod::Hann) { windows = itpp::hann(int(m_SamplesPerBuffer)); }
else if (m_WindowMethod == EWindowMethod::Blackman) { windows = itpp::blackman(int(m_SamplesPerBuffer)); }
else if (m_WindowMethod == EWindowMethod::Triangular) { windows = itpp::triang(int(m_SamplesPerBuffer)); }
else if (m_WindowMethod == EWindowMethod::SquareRoot) { windows = itpp::sqrt_win(int(m_SamplesPerBuffer)); }
for (size_t i = 0; i < m_NChannel; ++i)
{
for (size_t j = 0; j < m_SamplesPerBuffer; ++j) { m_Buffer[i * m_SamplesPerBuffer + j] = double(buffer[i * m_SamplesPerBuffer + j]) * windows(int(j)); }
}
}
bool CWindowingFunctions::initialize()
{
//reads the plugin settings
const CString method = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
m_WindowMethod = EWindowMethod(this->getTypeManager().getEnumerationEntryValueFromName(OVP_TypeId_WindowMethod, method));
m_Decoder = new Toolkit::TSignalDecoder<CWindowingFunctions>(*this, 0);
m_Encoder = new Toolkit::TSignalEncoder<CWindowingFunctions>(*this, 0);
return true;
}
bool CWindowingFunctions::uninitialize()
{
m_Decoder->uninitialize();
delete m_Decoder;
m_Encoder->uninitialize();
delete m_Encoder;
return true;
}
bool CWindowingFunctions::processInput(const size_t /*index*/)
{
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
return true;
}
bool CWindowingFunctions::process()
{
IDynamicBoxContext* boxContext = getBoxAlgorithmContext()->getDynamicBoxContext();
// Process input data
for (size_t i = 0; i < boxContext->getInputChunkCount(0); ++i)
{
size_t chunkSize;
const uint8_t* buffer;
boxContext->getInputChunk(0, i, m_LastChunkStartTime, m_LastChunkEndTime, chunkSize, buffer);
m_Decoder->decode(i);
if (m_Decoder->isHeaderReceived())
{
CMatrix* iMatrix = m_Decoder->getOutputMatrix();
CMatrix* oMatrix = m_Encoder->getInputMatrix();
oMatrix->copy(*iMatrix);
m_Buffer = oMatrix->getBuffer();
m_SamplesPerBuffer = oMatrix->getDimensionSize(1);
m_NChannel = oMatrix->getDimensionSize(0);
const size_t sampling = m_Decoder->getOutputSamplingRate();
m_Encoder->getInputSamplingRate() = sampling;
m_Encoder->encodeHeader();
boxContext->markOutputAsReadyToSend(i, m_LastChunkStartTime, m_LastChunkEndTime);
}
if (m_Decoder->isBufferReceived())
{
CMatrix* iMatrix = m_Decoder->getOutputMatrix();
m_Buffer = m_Encoder->getInputMatrix()->getBuffer();
setSampleBuffer(iMatrix->getBuffer());
m_Encoder->encodeBuffer();
boxContext->markOutputAsReadyToSend(i, m_LastChunkStartTime, m_LastChunkEndTime);
}
if (m_Decoder->isEndReceived())
{
m_Encoder->encodeEnd();
boxContext->markOutputAsReadyToSend(i, m_LastChunkStartTime, m_LastChunkEndTime);
}
boxContext->markInputAsDeprecated(0, i);
//m_pReader->processData(buffer, chunkSize);
}
return true;
}
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyITPP
@@ -0,0 +1,110 @@
// @copyright notice: Possibly due to dependencies, this box used to be GPL before upgrade to AGPL3
#pragma once
#if defined TARGET_HAS_ThirdPartyITPP
#include "../ovp_defines.h"
#include <toolkit/ovtk_all.h>
#include <vector>
#include <map>
#include <string>
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
namespace WindowingFunctions {
// Used to store information about the signal stream
class CSignalDescription
{
public:
CSignalDescription() { }
size_t m_StreamVersion = 1;
size_t m_Sampling = 0;
size_t m_NChannel = 0;
size_t m_NSample = 0;
std::vector<std::string> m_ChannelName;
size_t m_CurrentChannel = 0;
bool m_ReadyToSend = false;
};
} // namespace WindowingFunctions
/**
* The Window Anlaysis plugin's main class.
*/
class CWindowingFunctions final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
{
public:
CWindowingFunctions() { }
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool processInput(const size_t index) override;
bool process() override;
_IsDerivedFromClass_Final_(IBoxAlgorithm, OVP_ClassId_WindowingFunctions)
void setSampleBuffer(const double* buffer) const;
//start time and end time of the last arrived chunk
uint64_t m_LastChunkStartTime = 0;
uint64_t m_LastChunkEndTime = 0;
size_t m_SamplesPerBuffer = 0;
size_t m_NChannel = 0;
// Needed to write on the plugin output
Toolkit::TSignalDecoder<CWindowingFunctions>* m_Decoder = nullptr;
Toolkit::TSignalEncoder<CWindowingFunctions>* m_Encoder = nullptr;
//! Structure containing information about the signal stream
WindowingFunctions::CSignalDescription* m_SignalDesc = nullptr;
//! Size of the matrix buffer (output signal)
size_t m_BufferSize = 0;
//! Output signal's matrix buffer
double* m_Buffer = nullptr;
EWindowMethod m_WindowMethod = EWindowMethod::None;
};
class CWindowingFunctionsDesc final : virtual public IBoxAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return CString("Windowing (INSERM contrib)"); }
CString getAuthorName() const override { return CString("Guillaume Gibert"); }
CString getAuthorCompanyName() const override { return CString("INSERM"); }
CString getShortDescription() const override { return CString("Apply a window to the signal buffer"); }
CString getDetailedDescription() const override { return CString(""); }
CString getCategory() const override { return CString("Signal processing/Windowing"); }
CString getVersion() const override { return CString("0.1"); }
CIdentifier getCreatedClass() const override { return OVP_ClassId_WindowingFunctions; }
IPluginObject* create() override { return new CWindowingFunctions(); }
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
{
prototype.addInput("Input signal", OV_TypeId_Signal);
prototype.addOutput("Output signal", OV_TypeId_Signal);
prototype.addSetting("Window method", OVP_TypeId_WindowMethod, "Hamming");
return true;
}
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_WindowingFunctionsDesc)
};
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE
#endif // TARGET_HAS_ThirdPartyITPP
@@ -0,0 +1,132 @@
#pragma once
// @BEGIN inserm-gpl
// Boxes
//---------------------------------------------------------------------------------------------------
#define OVP_ClassId_SpectralAnalysis OpenViBE::CIdentifier(0x1491AFA8, 0xF81E49D5)
#define OVP_ClassId_SpectralAnalysisDesc OpenViBE::CIdentifier(0xD011A66C, 0x61EF37D0)
#define OVP_ClassId_Algorithm_DetectingMinMax OpenViBE::CIdentifier(0x46C14A64, 0xE00541DD)
#define OVP_ClassId_Algorithm_DetectingMinMaxDesc OpenViBE::CIdentifier(0x5B194CDA, 0x54E6DEC7)
#define OVP_ClassId_Box_DetectingMinMaxBoxAlgorithm OpenViBE::CIdentifier(0xD647A2C4, 0xD4833160)
#define OVP_ClassId_Box_DetectingMinMaxBoxAlgorithmDesc OpenViBE::CIdentifier(0xEF9E296A, 0x10285AE1)
#define OVP_ClassId_Algorithm_Downsampling OpenViBE::CIdentifier(0xBBBB4E18, 0x17695604)
#define OVP_ClassId_Algorithm_DownsamplingDesc OpenViBE::CIdentifier(0xC08BA8C1, 0x3A3B6E26)
#define OVP_ClassId_Box_DownsamplingBoxAlgorithm OpenViBE::CIdentifier(0x6755FD0F, 0xE4857EA8)
#define OVP_ClassId_Box_DownsamplingBoxAlgorithmDesc OpenViBE::CIdentifier(0xC8A99636, 0x81EF1AAD)
#define OVP_ClassId_Algorithm_ComputeTemporalFilterCoefs OpenViBE::CIdentifier(0x55BAD77B, 0x5D8563A7)
#define OVP_ClassId_Algorithm_ComputeTemporalFilterCoefsDesc OpenViBE::CIdentifier(0xD871BD98, 0x705ED068)
#define OVP_ClassId_Algorithm_ApplyTemporalFilter OpenViBE::CIdentifier(0x9662518A, 0xE301A6FF)
#define OVP_ClassId_Algorithm_ApplyTemporalFilterDesc OpenViBE::CIdentifier(0xAC0D004F, 0x0CFC5D9E)
#define OVP_ClassId_Box_TemporalFilterBoxAlgorithm OpenViBE::CIdentifier(0x4469F0B2, 0x1DA995E5)
#define OVP_ClassId_Box_TemporalFilterBoxAlgorithmDesc OpenViBE::CIdentifier(0x8BF6DD60, 0xBF02FA77)
#define OVP_ClassId_Box_ModTemporalFilterBoxAlgorithm OpenViBE::CIdentifier(0xBF49D042, 0x9D79FE52)
#define OVP_ClassId_Box_ModTemporalFilterBoxAlgorithmDesc OpenViBE::CIdentifier(0x7BF4BA62, 0xAF829A73)
#define OVP_ClassId_WindowingFunctions OpenViBE::CIdentifier(0x0B2F38AE, 0x6B0CF98F)
#define OVP_ClassId_WindowingFunctionsDesc OpenViBE::CIdentifier(0x40BFF79E, 0xA7BA6EAE)
#define OVP_ClassId_FastICA OpenViBE::CIdentifier(0x00649B6E, 0x6C88CD17)
#define OVP_ClassId_FastICADesc OpenViBE::CIdentifier(0x00E9436C, 0x41C904CA)
#define OVP_ClassId_AlgoUnivariateStatistic OpenViBE::CIdentifier(0x07A71212, 0x53D93D1C)
#define OVP_ClassId_AlgoUnivariateStatisticDesc OpenViBE::CIdentifier(0x408157F7, 0x4F1209F7)
#define OVP_ClassId_BoxAlgorithm_CSPSpatialFilterTrainer OpenViBE::CIdentifier(0x51DB0D64, 0x2109714E)
#define OVP_ClassId_BoxAlgorithm_CSPSpatialFilterTrainerDesc OpenViBE::CIdentifier(0x05120978, 0x14E061CD)
#define OVP_ClassId_BoxAlgorithm_Synchro OpenViBE::CIdentifier(0x7D8C1A18, 0x4C273A91)
#define OVP_ClassId_BoxAlgorithm_SynchroDesc OpenViBE::CIdentifier(0x4E806E5E, 0x5035290D)
#define OVP_ClassId_BoxAlgorithm_UnivariateStatistic OpenViBE::CIdentifier(0x6118159D, 0x600C40B9)
#define OVP_ClassId_BoxAlgorithm_UnivariateStatisticDesc OpenViBE::CIdentifier(0x36F742D9, 0x6D1477B2)
// Type definitions
//---------------------------------------------------------------------------------------------------
#define OVP_TypeId_SpectralComponent OpenViBE::CIdentifier(0x764E148A, 0xC704D4F5)
#define OVP_TypeId_FilterMethod OpenViBE::CIdentifier(0x2F2C606C, 0x8512ED68)
#define OVP_TypeId_FilterType OpenViBE::CIdentifier(0xFA20178E, 0x4CBA62E9)
#define OVP_TypeId_WindowMethod OpenViBE::CIdentifier(0x0A430FE4, 0x4F318280)
#define OVP_TypeId_FrequencyCutOffRatio OpenViBE::CIdentifier(0x709FC9DF, 0x30A2CB2A)
#define OVP_TypeId_MinMax OpenViBE::CIdentifier(0x4263AC45, 0x0AF5E07E)
#define OVP_TypeId_FastICA_OperatingMode OpenViBE::CIdentifier(0x43A71032, 0x4AF96B9F)
#define OVP_TypeId_FastICA_DecompositionType OpenViBE::CIdentifier(0x7B876033, 0x13590B93)
#define OVP_TypeId_FastICA_Nonlinearity OpenViBE::CIdentifier(0x4313472F, 0x37FD5961)
enum class ESpectralComponent { Amplitude = 1, Phase = 2, RealPart = 4, ImaginaryPart = 8 };
enum class EFilterMethod { Butterworth, Chebyshev, YuleWalker };
enum class EFilterType { LowPass, BandPass, HighPass, BandStop };
enum class EWindowMethod { None, Hamming, Hanning, Hann, Blackman, Triangular, SquareRoot };
enum class EFrequencyCutOffRatio { R14, R13, R12 };
enum class EMinMax { Min, Max };
enum class EFastICAMode { PCA, Whiten, ICA };
enum class EFastICADecomposition { Symmetric = 1, Deflate = 2 }; // Symmetric Must match ITPP
enum class EFastICANonlinearity { Pow3 = 10, Tanh = 20, Gauss= 30, Skew = 40 }; // Use x^3/tanh(x)/Gaussian/skew non-linearity. Pow3 Must match ITPP.
// Global defines
//---------------------------------------------------------------------------------------------------
#ifdef TARGET_HAS_ThirdPartyOpenViBEPluginsGlobalDefines
#include "ovp_global_defines.h"
#endif // TARGET_HAS_ThirdPartyOpenViBEPluginsGlobalDefines
#define OV_AttributeId_Box_FlagIsUnstable OpenViBE::CIdentifier(0x666FFFFF, 0x666FFFFF)
#define OVP_Algorithm_DetectingMinMax_InputParameterId_SignalMatrix OpenViBE::CIdentifier(0x9CA3B6BB, 0x6E24A3E3)
#define OVP_Algorithm_DetectingMinMax_InputParameterId_TimeWindowStart OpenViBE::CIdentifier(0xB3DED659, 0xD8A85CFA)
#define OVP_Algorithm_DetectingMinMax_InputParameterId_TimeWindowEnd OpenViBE::CIdentifier(0x9F55A091, 0xA042E9C0)
#define OVP_Algorithm_DetectingMinMax_InputParameterId_Sampling OpenViBE::CIdentifier(0x8519915D, 0xB6BE506D)
#define OVP_Algorithm_DetectingMinMax_OutputParameterId_SignalMatrix OpenViBE::CIdentifier(0x853F2DE5, 0x628237CE)
#define OVP_Algorithm_DetectingMinMax_InputTriggerId_Initialize OpenViBE::CIdentifier(0x6B43B69D, 0xDA1EAE30)
#define OVP_Algorithm_DetectingMinMax_InputTriggerId_DetectsMin OpenViBE::CIdentifier(0xFCB3CFC2, 0x980E3085)
#define OVP_Algorithm_DetectingMinMax_InputTriggerId_DetectsMax OpenViBE::CIdentifier(0x24926194, 0x086E6C2A)
#define OVP_Algorithm_Downsampling_InputParameterId_Sampling OpenViBE::CIdentifier(0x7C510AFB, 0x4F2B9FB7)
#define OVP_Algorithm_Downsampling_InputParameterId_NewSampling OpenViBE::CIdentifier(0x8617E5FA, 0xC39CDBE7)
#define OVP_Algorithm_Downsampling_InputTriggerId_Initialize OpenViBE::CIdentifier(0x82D96F84, 0x9479A701)
#define OVP_Algorithm_Downsampling_InputTriggerId_Resample OpenViBE::CIdentifier(0x2A88AFF5, 0x79ECAEB3)
#define OVP_Algorithm_Downsampling_InputTriggerId_ResampleWithHistoric OpenViBE::CIdentifier(0xD5740B33, 0x3785C886)
#define OVP_Algorithm_Downsampling_InputParameterId_SignalMatrix OpenViBE::CIdentifier(0xBB09054A, 0xEF13B2C6)
#define OVP_Algorithm_Downsampling_OutputParameterId_SignalMatrix OpenViBE::CIdentifier(0x4B9BE135, 0x14C10757)
#define OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_Sampling OpenViBE::CIdentifier(0x25A9A0FF, 0x168F1B50)
#define OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_FilterMethod OpenViBE::CIdentifier(0xCFB7CDC9, 0x3EFF788E)
#define OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_FilterType OpenViBE::CIdentifier(0x1B7BCB2C, 0xE235A6E7)
#define OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_FilterOrder OpenViBE::CIdentifier(0x8DA1E555, 0x17E17828)
#define OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_LowCutFrequency OpenViBE::CIdentifier(0x3175B774, 0xA15AEEB2)
#define OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_HighCutFrequency OpenViBE::CIdentifier(0xE36387B7, 0xFB766612)
#define OVP_Algorithm_ComputeTemporalFilterCoefs_InputParameterId_BandPassRipple OpenViBE::CIdentifier(0xB1500ED4, 0x0E558759)
#define OVP_Algorithm_ComputeTemporalFilterCoefs_OutputParameterId_Matrix OpenViBE::CIdentifier(0xE5B2A753, 0x150500B4)
#define OVP_Algorithm_ComputeTemporalFilterCoefs_InputTriggerId_Initialize OpenViBE::CIdentifier(0x3D2CBA61, 0x3FCF0DAC)
#define OVP_Algorithm_ComputeTemporalFilterCoefs_InputTriggerId_ComputeCoefs OpenViBE::CIdentifier(0x053A2C6E, 0x3A878825)
#define OVP_Algorithm_ApplyTemporalFilter_InputParameterId_FilterCoefsMatrix OpenViBE::CIdentifier(0xD316C4E7, 0xE4E89FD3)
#define OVP_Algorithm_ApplyTemporalFilter_InputParameterId_SignalMatrix OpenViBE::CIdentifier(0xD5339105, 0x1D1293F0)
#define OVP_Algorithm_ApplyTemporalFilter_OutputParameterId_FilteredSignalMatrix OpenViBE::CIdentifier(0x463276D1, 0xEAEE8AAD)
#define OVP_Algorithm_ApplyTemporalFilter_InputTriggerId_Initialize OpenViBE::CIdentifier(0x3DAE69C7, 0x7CFCBE2C)
#define OVP_Algorithm_ApplyTemporalFilter_InputTriggerId_ApplyFilter OpenViBE::CIdentifier(0xBC1F5655, 0x9807B400)
#define OVP_Algorithm_ApplyTemporalFilter_InputTriggerId_ApplyFilterWithHistoric OpenViBE::CIdentifier(0xB7B7D546, 0x6000FF51)
#define OVP_Algorithm_UnivariateStatistic_OutputParameterId_Mean OpenViBE::CIdentifier(0x2E1E6A87, 0x17F37568)
#define OVP_Algorithm_UnivariateStatistic_OutputParameterId_Var OpenViBE::CIdentifier(0x479E18C9, 0x34A561AC)
#define OVP_Algorithm_UnivariateStatistic_OutputParameterId_Range OpenViBE::CIdentifier(0x3CBC7D63, 0x5BF90946)
#define OVP_Algorithm_UnivariateStatistic_OutputParameterId_Med OpenViBE::CIdentifier(0x2B236D6C, 0x4A37734F)
#define OVP_Algorithm_UnivariateStatistic_OutputParameterId_IQR OpenViBE::CIdentifier(0x7A4E5C6E, 0x16EA324E)
#define OVP_Algorithm_UnivariateStatistic_OutputParameterId_Percent OpenViBE::CIdentifier(0x77443BEF, 0x687B139F)
#define OVP_Algorithm_UnivariateStatistic_OutputParameterId_PercentValue OpenViBE::CIdentifier(0x2E9B5EEA, 0x58BC5AB6)
#define OVP_Algorithm_UnivariateStatistic_OutputParameterId_Compression OpenViBE::CIdentifier(0x2A9C502C, 0x582959DA)
#define OVP_Algorithm_UnivariateStatistic_InputParameterId_Matrix OpenViBE::CIdentifier(0x1769269C, 0x41910DB9)
#define OVP_Algorithm_UnivariateStatistic_InputParameterId_MeanActive OpenViBE::CIdentifier(0x6CE22614, 0x3BFD4A7A)
#define OVP_Algorithm_UnivariateStatistic_InputParameterId_VarActive OpenViBE::CIdentifier(0x304B052D, 0x04F51601)
#define OVP_Algorithm_UnivariateStatistic_InputParameterId_RangeActive OpenViBE::CIdentifier(0x4EA54A91, 0x69B90629)
#define OVP_Algorithm_UnivariateStatistic_InputParameterId_MedActive OpenViBE::CIdentifier(0x6B0F55F1, 0x30015B5B)
#define OVP_Algorithm_UnivariateStatistic_InputParameterId_IQRActive OpenViBE::CIdentifier(0x4F99672C, 0x7DFF3192)
#define OVP_Algorithm_UnivariateStatistic_InputParameterId_PercentActive OpenViBE::CIdentifier(0x3CA94023, 0x44E450C6)
#define OVP_Algorithm_UnivariateStatistic_InputParameterId_PercentValue OpenViBE::CIdentifier(0x0CB41979, 0x1CFF5A9C)
#define OVP_Algorithm_UnivariateStatistic_InputTriggerId_SpecialInitialize OpenViBE::CIdentifier(0x38274F8D, 0x5FB938D2)
#define OVP_Algorithm_UnivariateStatistic_InputTriggerId_Initialize OpenViBE::CIdentifier(0x42CC2481, 0x70300F6D)
#define OVP_Algorithm_UnivariateStatistic_InputTriggerId_Process OpenViBE::CIdentifier(0x6CCD1D92, 0x02043C21)
#define OVP_Algorithm_UnivariateStatistic_OutputTriggerId_ProcessDone OpenViBE::CIdentifier(0x34630103, 0x3F5F0A43)
@@ -0,0 +1,117 @@
#include <vector>
#include <openvibe/ov_all.h>
#include "ovp_defines.h"
#include "box-algorithms/ovpCBoxAlgorithmCSPSpatialFilterTrainer.h" // ghent univ
#include "algorithms/ovpCAlgorithmUnivariateStatistics.h" // gipsa
#include "box-algorithms/ovpCBoxAlgorithmUnivariateStatistics.h" // gipsa
#include "box-algorithms/ovpCBoxAlgorithmSynchro.h" // gipsa
// @BEGIN inserm-gpl
#include "algorithms/ovpCDetectingMinMax.h"
#include "box-algorithms/ovpCDetectingMinMaxBoxAlgorithm.h"
#include "box-algorithms/ovpCWindowingFunctions.h"
#include "box-algorithms/ovpCFastICA.h"
#include "box-algorithms/ovpCSpectralAnalysis.h"
#include "algorithms/ovpCApplyTemporalFilter.h"
#include "algorithms/ovpCComputeTemporalFilterCoefficients.h"
#include "box-algorithms/ovpCTemporalFilterBoxAlgorithm.h"
#include "box-algorithms/ovpCModTemporalFilterBoxAlgorithm.h"
#include "algorithms/ovpCDownsampling.h"
#include "box-algorithms/ovpCDownsamplingBoxAlgorithm.h"
#include "algorithms/ovpCDetectingMinMax.h"
#include "box-algorithms/ovpCDetectingMinMaxBoxAlgorithm.h"
// @END inserm-gpl
namespace OpenViBE {
namespace Plugins {
namespace SignalProcessing {
OVP_Declare_Begin()
#if defined TARGET_HAS_ThirdPartyITPP
OVP_Declare_New(CBoxAlgorithmCSPSpatialFilterTrainerDesc); // ghent univ
#endif
OVP_Declare_New(CBoxAlgorithmSynchroDesc) // gipsa
OVP_Declare_New(CAlgoUnivariateStatisticDesc); // gipsa
OVP_Declare_New(CBoxUnivariateStatisticDesc); // gipsa
// @BEGIN inserm-gpl
context.getTypeManager().registerBitMaskType(OVP_TypeId_SpectralComponent, "Spectral component");
context.getTypeManager().registerBitMaskEntry(OVP_TypeId_SpectralComponent, "Amplitude", size_t(ESpectralComponent::Amplitude));
context.getTypeManager().registerBitMaskEntry(OVP_TypeId_SpectralComponent, "Phase", size_t(ESpectralComponent::Phase));
context.getTypeManager().registerBitMaskEntry(OVP_TypeId_SpectralComponent, "Real part", size_t(ESpectralComponent::RealPart));
context.getTypeManager().registerBitMaskEntry(OVP_TypeId_SpectralComponent, "Imaginary part", size_t(ESpectralComponent::ImaginaryPart));
context.getTypeManager().registerEnumerationType(OVP_TypeId_FilterMethod, "Filter method");
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_FilterMethod, "Butterworth", size_t(EFilterMethod::Butterworth));
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_FilterMethod, "Chebyshev", size_t(EFilterMethod::Chebyshev));
context.getTypeManager().registerEnumerationType(OVP_TypeId_FilterType, "Filter type");
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_FilterType, "Low Pass", size_t(EFilterType::LowPass));
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_FilterType, "Band Pass", size_t(EFilterType::BandPass));
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_FilterType, "High Pass", size_t(EFilterType::HighPass));
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_FilterType, "Band Stop", size_t(EFilterType::BandStop));
context.getTypeManager().registerEnumerationType(OVP_TypeId_WindowMethod, "Window method");
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_WindowMethod, "Hamming", size_t(EWindowMethod::Hamming));
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_WindowMethod, "Hanning", size_t(EWindowMethod::Hanning));
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_WindowMethod, "Hann", size_t(EWindowMethod::Hann));
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_WindowMethod, "Blackman", size_t(EWindowMethod::Blackman));
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_WindowMethod, "Triangular", size_t(EWindowMethod::Triangular));
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_WindowMethod, "Square root", size_t(EWindowMethod::SquareRoot));
context.getTypeManager().registerEnumerationType(OVP_TypeId_FrequencyCutOffRatio, "Frequency cut off ratio");
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_FrequencyCutOffRatio, "1/4", size_t(EFrequencyCutOffRatio::R14));
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_FrequencyCutOffRatio, "1/3", size_t(EFrequencyCutOffRatio::R13));
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_FrequencyCutOffRatio, "1/2", size_t(EFrequencyCutOffRatio::R12));
context.getTypeManager().registerEnumerationType(OVP_TypeId_MinMax, "Min/Max");
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_MinMax, "Min", size_t(EMinMax::Min));
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_MinMax, "Max", size_t(EMinMax::Max));
context.getTypeManager().registerEnumerationEntry(OV_TypeId_BoxAlgorithmFlag, OV_AttributeId_Box_FlagIsUnstable.toString(),
OV_AttributeId_Box_FlagIsUnstable.id());
#if defined TARGET_HAS_ThirdPartyITPP
OVP_Declare_New(CSpectralAnalysisDesc);
OVP_Declare_New(CFastICADesc);
context.getTypeManager().registerEnumerationType(OVP_TypeId_FastICA_OperatingMode, "Operating mode");
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_FastICA_OperatingMode, "PCA", size_t(EFastICAMode::PCA));
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_FastICA_OperatingMode, "Whiten", size_t(EFastICAMode::Whiten));
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_FastICA_OperatingMode, "ICA", size_t(EFastICAMode::ICA));
context.getTypeManager().registerEnumerationType(OVP_TypeId_FastICA_DecompositionType, "Decomposition type");
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_FastICA_DecompositionType, "Symmetric", size_t(EFastICADecomposition::Symmetric));
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_FastICA_DecompositionType, "Deflate", size_t(EFastICADecomposition::Deflate));
context.getTypeManager().registerEnumerationType(OVP_TypeId_FastICA_Nonlinearity, "Nonlinearity");
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_FastICA_Nonlinearity, "Pow3", size_t(EFastICANonlinearity::Pow3));
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_FastICA_Nonlinearity, "Tanh", size_t(EFastICANonlinearity::Tanh));
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_FastICA_Nonlinearity, "Gauss", size_t(EFastICANonlinearity::Gauss));
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_FastICA_Nonlinearity, "Skew", size_t(EFastICANonlinearity::Skew));
OVP_Declare_New(CWindowingFunctionsDesc);
OVP_Declare_New(CComputeTemporalFilterCoefficientsDesc);
OVP_Declare_New(CTemporalFilterBoxAlgorithmDesc);
OVP_Declare_New(CModTemporalFilterBoxAlgorithmDesc);
OVP_Declare_New(CApplyTemporalFilterDesc);
#endif // TARGET_HAS_ThirdPartyITPP
OVP_Declare_New(CDownsamplingDesc);
OVP_Declare_New(CDownsamplingBoxAlgorithmDesc);
OVP_Declare_New(CDetectingMinMaxDesc);
OVP_Declare_New(CDetectingMinMaxBoxAlgorithmDesc);
// @END inserm-gpl
OVP_Declare_End()
} // namespace SignalProcessing
} // namespace Plugins
} // namespace OpenViBE