init
This commit is contained in:
+53
@@ -0,0 +1,53 @@
|
||||
PROJECT(openvibe-plugins-matlab)
|
||||
|
||||
SET(PROJECT_VERSION_MAJOR ${OV_GLOBAL_VERSION_MAJOR})
|
||||
SET(PROJECT_VERSION ${OV_GLOBAL_VERSION_STRING})
|
||||
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/share/OV_stimulations.m
|
||||
DEPENDS openvibe-stimulation-generator ${OPENVIBE_SDK_PATH}/share/openvibe/toolkit/stimulation_list.txt
|
||||
COMMAND openvibe-stimulation-generator
|
||||
--matlab
|
||||
${OPENVIBE_SDK_PATH}/share/openvibe/toolkit/stimulation_list.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/share/OV_stimulations.m
|
||||
COMMENT "Generating matlab stimulation sources..." )
|
||||
|
||||
add_custom_target(generate_matlab_stimulations_file DEPENDS share/OV_stimulations.m)
|
||||
|
||||
|
||||
FILE(GLOB_RECURSE SRC_FILES src/*.cpp src/*.h src/*.inl)
|
||||
ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRC_FILES})
|
||||
add_dependencies(openvibe-plugins-matlab generate_matlab_stimulations_file)
|
||||
|
||||
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("FindOpenViBEModuleSystem")
|
||||
INCLUDE("FindOpenViBEModuleFS")
|
||||
|
||||
INCLUDE("FindThirdPartyMatlab")
|
||||
|
||||
# ---------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
# ---------------------------------
|
||||
|
||||
|
||||
# -----------------------------
|
||||
# Install files
|
||||
# -----------------------------
|
||||
INSTALL(TARGETS ${PROJECT_NAME}
|
||||
RUNTIME DESTINATION ${DIST_BINDIR}
|
||||
LIBRARY DESTINATION ${DIST_LIBDIR}
|
||||
ARCHIVE DESTINATION ${DIST_LIBDIR})
|
||||
|
||||
INSTALL(DIRECTORY share/ DESTINATION ${DIST_DATADIR}/openvibe/plugins/matlab)
|
||||
|
||||
INSTALL(DIRECTORY box-tutorials DESTINATION ${DIST_DATADIR}/openvibe/scenarios/)
|
||||
+543
@@ -0,0 +1,543 @@
|
||||
<OpenViBE-Scenario>
|
||||
<FormatVersion>2</FormatVersion>
|
||||
<Creator>OpenViBE Designer</Creator>
|
||||
<CreatorVersion>2.2.0</CreatorVersion>
|
||||
<Settings></Settings>
|
||||
<Inputs></Inputs>
|
||||
<Outputs></Outputs>
|
||||
<Boxes>
|
||||
<Box>
|
||||
<Identifier>(0x00002bed, 0x00001e7e)</Identifier>
|
||||
<Name>Raw signal</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>304</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>544</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>(0x000043a1, 0x00007d94)</Identifier>
|
||||
<Name>Tuto 1 : Signal filter</Name>
|
||||
<AlgorithmClassIdentifier>(0x03303e0e, 0x39fe10df)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Signal input</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Trigger</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Filtered Signal</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Box clock frequency in Hz</Name>
|
||||
<DefaultValue>64</DefaultValue>
|
||||
<Value>32</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
|
||||
<Name>Matlab executable (path)</Name>
|
||||
<DefaultValue>C:/Program Files (x86)/MATLAB/R2013b/bin/win32/matlab.exe</DefaultValue>
|
||||
<Value></Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Matlab working directory</Name>
|
||||
<DefaultValue>[path-to-my-matlab-workspace]</DefaultValue>
|
||||
<Value>${Player_ScenarioDirectory}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Initialize function</Name>
|
||||
<DefaultValue>bci_Initialize</DefaultValue>
|
||||
<Value>tuto1_signal_filter_Initialize</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Process function</Name>
|
||||
<DefaultValue>bci_Process</DefaultValue>
|
||||
<Value>tuto1_signal_filter_Process</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Uninitialize function</Name>
|
||||
<DefaultValue>bci_Uninitialize</DefaultValue>
|
||||
<Value>tuto1_signal_filter_Uninitialize</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Zero trigger</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_01</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_01</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x17ee7c08, 0x94c14893)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>240</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>336</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x30a4e5c9, 0x83502953)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xc0b69293, 0x2c33365a)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x61d11811, 0x71e65362)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>6</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xf191c1c8, 0xa0123976)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xfba64161, 0x65304e21)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00004e6e, 0x00000d13)</Identifier>
|
||||
<Name>Matlab output</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>400</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>352</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>(0x00006b9e, 0x0000124c)</Identifier>
|
||||
<Name>Press 'a' to set all samples to 0</Name>
|
||||
<AlgorithmClassIdentifier>(0x00d317b9, 0x6324c3ff)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Outgoing Stimulations</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
|
||||
<Name>Filename</Name>
|
||||
<DefaultValue>${Path_Data}/plugins/stimulation/simple-keyboard-to-stimulations.txt</DefaultValue>
|
||||
<Value>${Path_Data}/plugins/stimulation/simple-keyboard-to-stimulations.txt</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>112</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>496</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x8d89d3b7, 0x8339d210)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00007bdb, 0x0000106d)</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>2</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Sampling frequency</Name>
|
||||
<DefaultValue>512</DefaultValue>
|
||||
<Value>512</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Generated epoch sample count</Name>
|
||||
<DefaultValue>32</DefaultValue>
|
||||
<Value>16</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>112</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>304</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x0b214ed8, 0x1f9ad83a)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>3</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
</Boxes>
|
||||
<Links>
|
||||
<Link>
|
||||
<Identifier>(0x000014b6, 0x00007cdc)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00007bdb, 0x0000106d)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00002bed, 0x00001e7e)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00004c29, 0x0000420f)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00007bdb, 0x0000106d)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x000043a1, 0x00007d94)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x0000516a, 0x00000f70)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00006b9e, 0x0000124c)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x000043a1, 0x00007d94)</BoxIdentifier>
|
||||
<BoxInputIndex>1</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x000066b4, 0x00006517)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x000043a1, 0x00007d94)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00004e6e, 0x00000d13)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
</Links>
|
||||
<Comments>
|
||||
<Comment>
|
||||
<Identifier>(0x00000f2b, 0x00004d77)</Identifier>
|
||||
<Text>You can browse each box' documentation by selecting the box and pressing <b>F1</b>
|
||||
|
||||
The documentation page for this tutorial is available at:
|
||||
<i>openvibe.inria.fr/tutorial-using-matlab-with-openvibe</i></Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>400</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>32</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
<Comment>
|
||||
<Identifier>(0x00002ca7, 0x00004cd8)</Identifier>
|
||||
<Text><b>Configure the Matlab Scripting box:</b>
|
||||
|
||||
<span color="red"> Set the matlab executable path before use !</span>
|
||||
|
||||
Enter the path to your local Matlab installation.
|
||||
|
||||
You can choose the Stimulation trigger
|
||||
that will set all input samples to 0</Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>144</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>240</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
</Comments>
|
||||
<Metadata>
|
||||
<Entry>
|
||||
<Identifier>(0x0000775c, 0x000078ff)</Identifier>
|
||||
<Type>(0x3bcce5d2, 0x43f2d968)</Type>
|
||||
<Data>[{"boxIdentifier":"(0x00006b9e, 0x0000124c)","childCount":0,"identifier":"(0x00001cbe, 0x000035db)","parentIdentifier":"(0xffffffff, 0xffffffff)","type":3},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"height":492,"identifier":"(0x0000500a, 0x00001fd8)","name":"Default window","parentIdentifier":"(0xffffffff, 0xffffffff)","type":1,"width":634},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"identifier":"(0x0000288c, 0x00006c84)","index":0,"name":"Default tab","parentIdentifier":"(0x0000500a, 0x00001fd8)","type":2},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":2,"dividerPosition":221,"identifier":"(0x000017f0, 0x00006465)","index":0,"maxDividerPosition":447,"name":"Vertical split","parentIdentifier":"(0x0000288c, 0x00006c84)","type":4},{"boxIdentifier":"(0x00002bed, 0x00001e7e)","childCount":0,"identifier":"(0x00006c72, 0x00007d16)","index":0,"parentIdentifier":"(0x000017f0, 0x00006465)","type":3},{"boxIdentifier":"(0x00004e6e, 0x00000d13)","childCount":0,"identifier":"(0x000073ee, 0x00006c76)","index":1,"parentIdentifier":"(0x000017f0, 0x00006465)","type":3}]</Data>
|
||||
</Entry>
|
||||
</Metadata>
|
||||
</OpenViBE-Scenario>
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
% tuto1_signal_filter_Initialize.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 25 May 2012
|
||||
%
|
||||
% The function tuto1_signal_filter_Initialize is called when pressing 'play' in the scenario.
|
||||
%
|
||||
function box_out = tuto1_signal_filter_Initialize(box_in)
|
||||
|
||||
disp('Matlab initialize function has been called.')
|
||||
|
||||
box_in.user_data.trigger_state = false;
|
||||
|
||||
% Don't forget to pass the modified box as output.
|
||||
box_out = box_in;
|
||||
|
||||
end
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
% tuto1_signal_filter_Process.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 25 May 2012
|
||||
%
|
||||
% The function tuto1_signal_filter_Process is called at the clock frequency.
|
||||
%
|
||||
|
||||
function box_out = tuto1_signal_filter_Process(box_in)
|
||||
|
||||
% we iterate over the pending chunks on input 2 (STIMULATIONS)
|
||||
for i = 1: OV_getNbPendingInputChunk(box_in,2)
|
||||
|
||||
% we pop the first chunk to be processed, note that box_in is used as the output variable to continue processing
|
||||
[box_in, start_time, end_time, stim_set] = OV_popInputBuffer(box_in,2);
|
||||
|
||||
% the stimulation set is a 3xN matrix.
|
||||
% The openvibe stimulation stream sends even empty stimulation set
|
||||
% so the following boxes know there is no stimulation to expect in
|
||||
% the latest time range. These empty chunk are also in the matlab buffer.
|
||||
if(numel(stim_set) >= 3) % at least one stim in the set.
|
||||
fprintf('Received stimulation code %i at time %f\n', stim_set(1), stim_set(2))
|
||||
if stim_set(1) == box_in.settings(1).value % I'm lazy... I only check the first stim in the set.
|
||||
box_in.user_data.trigger_state = ~box_in.user_data.trigger_state;
|
||||
disp('Trigger is switched.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
% we iterate over the pending chunks on input 1 (SIGNAL)
|
||||
for i = 1: OV_getNbPendingInputChunk(box_in,1)
|
||||
|
||||
% we pop the first chunk to be processed, note that box_in is used as the output variable to continue processing
|
||||
[box_in, start_time, end_time, matrix_data] = OV_popInputBuffer(box_in,1);
|
||||
|
||||
box_in.outputs{1}.header = box_in.inputs{1}.header;
|
||||
|
||||
% if requested, all samples are set to 0
|
||||
if(box_in.user_data.trigger_state)
|
||||
matrix_data(1:end) = 0;
|
||||
end
|
||||
|
||||
% we add the chunk to the signal output buffer. Note that we use box_in as the output variable.
|
||||
box_in = OV_addOutputBuffer(box_in,1,start_time,end_time,matrix_data);
|
||||
|
||||
end
|
||||
|
||||
% Pass the modified box as output to continue processing
|
||||
box_out = box_in;
|
||||
end
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
% tuto1_signal_filter_Uninitialize.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 25 May 2012
|
||||
%
|
||||
% The function tuto1_signal_filter_Uninitialize is called when pressing 'stop' in the scenario.
|
||||
%
|
||||
function box_out = tuto1_signal_filter_Uninitialize(box_in)
|
||||
disp('Matlab uninitialize function has been called.')
|
||||
|
||||
box_out = box_in;
|
||||
end
|
||||
|
||||
+688
@@ -0,0 +1,688 @@
|
||||
<OpenViBE-Scenario>
|
||||
<FormatVersion>2</FormatVersion>
|
||||
<Creator>OpenViBE Designer</Creator>
|
||||
<CreatorVersion>2.2.0</CreatorVersion>
|
||||
<Settings></Settings>
|
||||
<Inputs></Inputs>
|
||||
<Outputs></Outputs>
|
||||
<Boxes>
|
||||
<Box>
|
||||
<Identifier>(0x000008b2, 0x000031dd)</Identifier>
|
||||
<Name>Corrupted signal</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>416</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>304</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>(0x00001dc6, 0x00006378)</Identifier>
|
||||
<Name>Time based epoching</Name>
|
||||
<AlgorithmClassIdentifier>(0x00777fa0, 0x5dc3f560)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Input signal</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Epoched signal 1</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Epoch 1 duration (in sec)</Name>
|
||||
<DefaultValue>1</DefaultValue>
|
||||
<Value>2</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Epoch 1 intervals (in sec)</Name>
|
||||
<DefaultValue>0.5</DefaultValue>
|
||||
<Value>2</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x17ee7c08, 0x94c14893)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>192</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>352</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xc5ff41e9, 0xccc59a01)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x000027c9, 0x0000731d)</Identifier>
|
||||
<Name>1</Name>
|
||||
<AlgorithmClassIdentifier>(0x361722e8, 0x311574e8)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Input signal</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Output signal</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Channel List</Name>
|
||||
<DefaultValue>:</DefaultValue>
|
||||
<Value>:</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x3bcf9e67, 0x0c23994d)</TypeIdentifier>
|
||||
<Name>Action</Name>
|
||||
<DefaultValue>Select</DefaultValue>
|
||||
<Value>Select</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x666f25e9, 0x3e5738d6)</TypeIdentifier>
|
||||
<Name>Channel Matching Method</Name>
|
||||
<DefaultValue>Smart</DefaultValue>
|
||||
<Value>Smart</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>112</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>400</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x30a4e5c9, 0x83502953)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x277826e1, 0xa30a3bd0)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
|
||||
<Value></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>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x000066c7, 0x00005ac8)</Identifier>
|
||||
<Name>Generic stream reader</Name>
|
||||
<AlgorithmClassIdentifier>(0x6468099f, 0x0370095a)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Output stream 1</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
|
||||
<Name>Filename</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>${Path_Data}/scenarios/signals/bci-ssvep-training.ov</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x17ee7c08, 0x94c14893)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>48</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>400</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x30a4e5c9, 0x83502953)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xf37b8e7a, 0x1bc33e4e)</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00007ec5, 0x00003579)</Identifier>
|
||||
<Name>Tuto2 : FFT</Name>
|
||||
<AlgorithmClassIdentifier>(0x03303e0e, 0x39fe10df)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Signal input</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Filtered Signal</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Box clock frequency in Hz</Name>
|
||||
<DefaultValue>64</DefaultValue>
|
||||
<Value>32</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
|
||||
<Name>Matlab executable (path)</Name>
|
||||
<DefaultValue>C:/Program Files (x86)/MATLAB/R2013b/bin/win32/matlab.exe</DefaultValue>
|
||||
<Value></Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Matlab working directory</Name>
|
||||
<DefaultValue>[path-to-my-matlab-workspace]</DefaultValue>
|
||||
<Value>${Player_ScenarioDirectory}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Initialize function</Name>
|
||||
<DefaultValue>bci_Initialize</DefaultValue>
|
||||
<Value>tuto2_FFT_filter_Initialize</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Process function</Name>
|
||||
<DefaultValue>bci_Process</DefaultValue>
|
||||
<Value>tuto2_FFT_filter_Process</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Uninitialize function</Name>
|
||||
<DefaultValue>bci_Uninitialize</DefaultValue>
|
||||
<Value>tuto2_FFT_filter_Uninitialize</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Noise frequency</Name>
|
||||
<DefaultValue>20</DefaultValue>
|
||||
<Value>20</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Noise amplitude</Name>
|
||||
<DefaultValue>10</DefaultValue>
|
||||
<Value>10</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Plot range : min frequency</Name>
|
||||
<DefaultValue>5</DefaultValue>
|
||||
<Value>5</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Plot range : max frequency</Name>
|
||||
<DefaultValue>50</DefaultValue>
|
||||
<Value>50</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x17ee7c08, 0x94c14893)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>288</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>336</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x30a4e5c9, 0x83502953)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xc0b69293, 0x2c33365a)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x61d11811, 0x71e65362)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>6</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xf191c1c8, 0xa0123976)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xfba64161, 0x65304e21)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00007f47, 0x00001bc6)</Identifier>
|
||||
<Name>Raw signal</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>416</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>464</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>(0x00002758, 0x00001276)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x000027c9, 0x0000731d)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00007f47, 0x00001bc6)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x000046f2, 0x00007e90)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x000027c9, 0x0000731d)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00001dc6, 0x00006378)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x0000494d, 0x00004db5)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00001dc6, 0x00006378)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00007ec5, 0x00003579)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00006c26, 0x00006a80)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00007ec5, 0x00003579)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x000008b2, 0x000031dd)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00006c31, 0x00005c81)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x000066c7, 0x00005ac8)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x000027c9, 0x0000731d)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
</Links>
|
||||
<Comments>
|
||||
<Comment>
|
||||
<Identifier>(0x000020c1, 0x00005db7)</Identifier>
|
||||
<Text>We extract a 2 seconds window
|
||||
every 2 seconds</Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>96</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>176</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
<Comment>
|
||||
<Identifier>(0x000032ad, 0x000007b4)</Identifier>
|
||||
<Text><b>Configure the Matlab Scripting box:</b>
|
||||
|
||||
<span color="red"> Set the matlab executable path
|
||||
and the working directory before use !</span>
|
||||
|
||||
If you want to add a sinusoid noise to the signal
|
||||
set the noise frequency and amplitude.
|
||||
Amplitude to 0 results in no noise.
|
||||
|
||||
Set the frequency range for the plot scale.</Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>96</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>288</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
<Comment>
|
||||
<Identifier>(0x00003f54, 0x00005026)</Identifier>
|
||||
<Text>You can browse each box' documentation by selecting the box and pressing <b>F1</b>
|
||||
|
||||
The documentation page for this tutorial is available at:
|
||||
<i>openvibe.inria.fr/tutorial-using-matlab-with-openvibe</i></Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>400</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>-16</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
<Comment>
|
||||
<Identifier>(0x00006b7a, 0x000044fb)</Identifier>
|
||||
<Text>The signal display boxes prints
|
||||
on a 2 seconds horizontal scale</Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>96</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>400</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
</Comments>
|
||||
<Metadata>
|
||||
<Entry>
|
||||
<Identifier>(0x0000775c, 0x000078ff)</Identifier>
|
||||
<Type>(0x3bcce5d2, 0x43f2d968)</Type>
|
||||
<Data>[{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"height":362,"identifier":"(0x00005a65, 0x00005347)","name":"Default window","parentIdentifier":"(0xffffffff, 0xffffffff)","type":1,"width":442},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"identifier":"(0x00007762, 0x000022c1)","index":0,"name":"Default tab","parentIdentifier":"(0x00005a65, 0x00005347)","type":2},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":2,"dividerPosition":156,"identifier":"(0x00007f9f, 0x00002f07)","index":0,"maxDividerPosition":317,"name":"Vertical split","parentIdentifier":"(0x00007762, 0x000022c1)","type":4},{"boxIdentifier":"(0x00007f47, 0x00001bc6)","childCount":0,"identifier":"(0x00006697, 0x000030ae)","index":0,"parentIdentifier":"(0x00007f9f, 0x00002f07)","type":3},{"boxIdentifier":"(0x000008b2, 0x000031dd)","childCount":0,"identifier":"(0x000062cd, 0x0000001e)","index":1,"parentIdentifier":"(0x00007f9f, 0x00002f07)","type":3}]</Data>
|
||||
</Entry>
|
||||
</Metadata>
|
||||
</OpenViBE-Scenario>
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
% tuto2_FFT_filter_Initialize.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 25 May 2012
|
||||
%
|
||||
|
||||
function box_out = tuto2_FFT_filter_Initialize(box_in)
|
||||
|
||||
% we display the setting values
|
||||
disp('Box settings are:')
|
||||
for i=1:size(box_in.settings,2)
|
||||
fprintf('\t%s : %s\n',box_in.settings(i).name, num2str(box_in.settings(i).value));
|
||||
end
|
||||
|
||||
% let's add a user-defined indicator to know if the output header is set
|
||||
box_in.user_data.is_headerset = false;
|
||||
|
||||
% We also add some statistics
|
||||
box_in.user_data.nb_matrix_processed = 0;
|
||||
box_in.user_data.mean_fft_matrix = 0;
|
||||
|
||||
box_out = box_in;
|
||||
|
||||
end
|
||||
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
% tuto2_FFT_filter_Process.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 25 May 2012
|
||||
%
|
||||
|
||||
function box_out = tuto2_FFT_filter_Process(box_in)
|
||||
|
||||
for i = 1: OV_getNbPendingInputChunk(box_in,1)
|
||||
if(~box_in.user_data.is_headerset)
|
||||
% The output is the input + noise, only on first channel
|
||||
box_in.outputs{1}.header = box_in.inputs{1}.header;
|
||||
box_in.outputs{1}.header.nb_channels = 1;
|
||||
box_in.outputs{1}.header.channel_names = {'FFT'};
|
||||
box_in.user_data.is_headerset = 1;
|
||||
% We print the header in the console
|
||||
disp('Input header is :')
|
||||
box_in.inputs{1}.header
|
||||
disp('Output header is :')
|
||||
box_in.outputs{1}.header
|
||||
end
|
||||
|
||||
% we increment the matrix count
|
||||
box_in.user_data.nb_matrix_processed = box_in.user_data.nb_matrix_processed + 1;
|
||||
|
||||
[box_in, start_time, end_time, matrix_data] = OV_popInputBuffer(box_in,1);
|
||||
|
||||
Fs = box_in.inputs{1}.header.sampling_rate; % Sampling frequency
|
||||
T = 1/Fs; % Sample time
|
||||
L = box_in.inputs{1}.header.nb_samples_per_buffer; % Length of signal
|
||||
t = (0:L-1)*T; % Time vector
|
||||
|
||||
% We generate the requested sinusoid noise
|
||||
noise_amplitude = box_in.settings(2).value;
|
||||
noise_frequency = box_in.settings(1).value;
|
||||
sinusoid = noise_amplitude * sin(2*pi* noise_frequency *t);
|
||||
|
||||
% We add this sinus to the original signal on first channel only
|
||||
sig = sinusoid + matrix_data(1,1:L);
|
||||
subplot(3,1,1);
|
||||
plot(Fs*t,sinusoid)
|
||||
title('Noise')
|
||||
xlabel('time (seconds)')
|
||||
|
||||
subplot(3,1,2);
|
||||
plot(Fs*t,sig)
|
||||
title('Signal Corrupted with the noise (channel 1)')
|
||||
xlabel('time (seconds)')
|
||||
|
||||
NFFT = 2^nextpow2(L); % Next power of 2 from length of y
|
||||
Y = fft(sig,NFFT)/L;
|
||||
f = Fs/2*linspace(0,1,NFFT/2+1);
|
||||
|
||||
% Plot single-sided amplitude spectrum.
|
||||
plot_range_fmin = box_in.settings(3).value;
|
||||
plot_range_fmax = box_in.settings(4).value;
|
||||
subplot(3,1,3)
|
||||
plot(f(plot_range_fmin*2:plot_range_fmax*2),2*abs(Y(plot_range_fmin*2:plot_range_fmax*2)))
|
||||
title('Single-Sided Amplitude Spectrum of the corrupted signal (channel 1)')
|
||||
xlabel('Frequency (Hz)')
|
||||
ylabel('Amplitude')
|
||||
|
||||
% we sum the FFT for later mean computation
|
||||
if box_in.user_data.nb_matrix_processed == 1
|
||||
box_in.user_data.mean_fft_matrix = Y;
|
||||
else
|
||||
box_in.user_data.mean_fft_matrix = box_in.user_data.mean_fft_matrix + Y;
|
||||
end
|
||||
|
||||
box_in = OV_addOutputBuffer(box_in,1,start_time,end_time,sig);
|
||||
end
|
||||
|
||||
box_out = box_in;
|
||||
end
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
% tuto2_FFT_filter_Uninitialize.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 25 May 2012
|
||||
%
|
||||
% The function tuto2_FFT_filter_Uninitialize is called when pressing 'stop' in the scenario.
|
||||
% We compute the mean FFT and plot it.
|
||||
%
|
||||
function box_out = tuto2_FFT_filter_Uninitialize(box_in)
|
||||
disp('Uninitializing the box...')
|
||||
|
||||
Fs = box_in.inputs{1}.header.sampling_rate; % Sampling frequency
|
||||
L = box_in.inputs{1}.header.nb_samples_per_buffer; % Length of signal
|
||||
|
||||
NFFT = 2^nextpow2(L);
|
||||
f = Fs/2*linspace(0,1,NFFT/2+1);
|
||||
|
||||
box_in.user_data.mean_fft_matrix = box_in.user_data.mean_fft_matrix / box_in.user_data.nb_matrix_processed;
|
||||
|
||||
%% we close the previous figure window and plot the mean FFT between 5 and 50Hz.
|
||||
close(gcf);
|
||||
plot_range_fmin = box_in.settings(3).value;
|
||||
plot_range_fmax = box_in.settings(4).value;
|
||||
plot(f(plot_range_fmin*2:plot_range_fmax*2),2*abs(box_in.user_data.mean_fft_matrix(plot_range_fmin*2:plot_range_fmax*2)))
|
||||
title('MEAN Single-Sided Amplitude Spectrum of the corrupted signal (channel 1)')
|
||||
xlabel('Frequency (Hz)')
|
||||
ylabel('Amplitude')
|
||||
|
||||
% We pause the execution for 10 seconds (to be able to see the figure before the scenario is stopped)
|
||||
pause(10);
|
||||
|
||||
box_out = box_in;
|
||||
end
|
||||
|
||||
+338
@@ -0,0 +1,338 @@
|
||||
<OpenViBE-Scenario>
|
||||
<FormatVersion>2</FormatVersion>
|
||||
<Creator>OpenViBE Designer</Creator>
|
||||
<CreatorVersion>2.2.0</CreatorVersion>
|
||||
<Settings></Settings>
|
||||
<Inputs></Inputs>
|
||||
<Outputs></Outputs>
|
||||
<Boxes>
|
||||
<Box>
|
||||
<Identifier>(0x00001c6f, 0x00005a88)</Identifier>
|
||||
<Name>Tuto 3 : sinus generator</Name>
|
||||
<AlgorithmClassIdentifier>(0x03303e0e, 0x39fe10df)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>New output</Name>
|
||||
</Output>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>New output(1)</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Box clock frequency in Hz</Name>
|
||||
<DefaultValue>64</DefaultValue>
|
||||
<Value>32</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
|
||||
<Name>Matlab executable (path)</Name>
|
||||
<DefaultValue>C:/Program Files (x86)/MATLAB/R2013b/bin/win32/matlab.exe</DefaultValue>
|
||||
<Value></Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Matlab working directory</Name>
|
||||
<DefaultValue>${Player_ScenarioDirectory}</DefaultValue>
|
||||
<Value>${Player_ScenarioDirectory}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Initialize function</Name>
|
||||
<DefaultValue>matlab_Initialize</DefaultValue>
|
||||
<Value>tuto3_sinus_generator_Initialize</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Process function</Name>
|
||||
<DefaultValue>matlab_Process</DefaultValue>
|
||||
<Value>tuto3_sinus_generator_Process</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Uninitialize function</Name>
|
||||
<DefaultValue>matlab_Uninitialize</DefaultValue>
|
||||
<Value>tuto3_sinus_generator_Uninitialize</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Channel count</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>4</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Samples per buffer</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>16</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Amplitude</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>5</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation</Name>
|
||||
<DefaultValue>OVTK_GDF_Artifact_EOG_Large</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_01</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x17ee7c08, 0x94c14893)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>208</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>400</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x30a4e5c9, 0x83502953)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xc0b69293, 0x2c33365a)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x61d11811, 0x71e65362)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x6e3d4519)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>false</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>6</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xf191c1c8, 0xa0123976)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xfba64161, 0x65304e21)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00002f39, 0x000039fc)</Identifier>
|
||||
<Name>Signal display</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>336</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>400</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>(0x00003443, 0x00005347)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00001c6f, 0x00005a88)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00002f39, 0x000039fc)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00007d44, 0x000014de)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00001c6f, 0x00005a88)</BoxIdentifier>
|
||||
<BoxOutputIndex>1</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00002f39, 0x000039fc)</BoxIdentifier>
|
||||
<BoxInputIndex>1</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
</Links>
|
||||
<Comments>
|
||||
<Comment>
|
||||
<Identifier>(0x00000b01, 0x0000700e)</Identifier>
|
||||
<Text>You can browse each box' documentation by selecting the box and pressing <b>F1</b>
|
||||
|
||||
The documentation page for this tutorial is available at:
|
||||
<i>openvibe.inria.fr/tutorial-using-matlab-with-openvibe</i></Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>400</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>0</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
<Comment>
|
||||
<Identifier>(0x00001e22, 0x0000145c)</Identifier>
|
||||
<Text><b>Configure the Matlab Scripting box:</b>
|
||||
|
||||
<span color="red"> Set the matlab executable path
|
||||
and the working directory before use !</span>
|
||||
|
||||
You can select the number of channels
|
||||
and size of data chunk.
|
||||
Sampling frequency = box clock freqeuncy * samples per block
|
||||
|
||||
The box generates one sinus signal per channel
|
||||
with frequency
|
||||
F(channel i) = 10 * i Hz
|
||||
|
||||
The box sends one stimulation per second</Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>32</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>272</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
</Comments>
|
||||
<Metadata>
|
||||
<Entry>
|
||||
<Identifier>(0x0000775c, 0x000078ff)</Identifier>
|
||||
<Type>(0x3bcce5d2, 0x43f2d968)</Type>
|
||||
<Data>[{"boxIdentifier":"(0x00002f39, 0x000039fc)","childCount":0,"identifier":"(0x00005e17, 0x00003f09)","parentIdentifier":"(0xffffffff, 0xffffffff)","type":3},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"height":320,"identifier":"(0x00006dc8, 0x00002e10)","name":"Default window","parentIdentifier":"(0xffffffff, 0xffffffff)","type":1,"width":480},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"identifier":"(0x000023aa, 0x00003482)","index":0,"name":"Default tab","parentIdentifier":"(0x00006dc8, 0x00002e10)","type":2},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":0,"identifier":"(0x00005c13, 0x00001d05)","index":0,"name":"Empty","parentIdentifier":"(0x000023aa, 0x00003482)","type":0}]</Data>
|
||||
</Entry>
|
||||
</Metadata>
|
||||
</OpenViBE-Scenario>
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
% tuto3_sinus_generator_Initialize.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 25 May 2012
|
||||
%
|
||||
|
||||
function box_out = tuto3_sinus_generator_Initialize(box_in)
|
||||
|
||||
% we display the setting values
|
||||
disp('Box settings are:')
|
||||
for i=1:size(box_in.settings,2)
|
||||
fprintf('\t%s : %s\n',box_in.settings(i).name, num2str(box_in.settings(i).value));
|
||||
end
|
||||
|
||||
% As we produce the signal ourselves, we already know the output header
|
||||
% we construct the channel names
|
||||
nb_channels = box_in.settings(1).value;
|
||||
channel_names = cell(1,nb_channels);
|
||||
for chan = 1 : nb_channels
|
||||
channel_names{chan} = sprintf('channel %i',chan);
|
||||
end
|
||||
% and deduce the other header elements from the box settings
|
||||
nb_samples_per_buffer = box_in.settings(2).value;
|
||||
sampling_rate = box_in.clock_frequency * nb_samples_per_buffer;
|
||||
|
||||
box_in = OV_setSignalOutputHeader(box_in, 1, nb_channels, nb_samples_per_buffer, channel_names, sampling_rate);
|
||||
box_in = OV_setStimulationOutputHeader(box_in,2);
|
||||
|
||||
% end time of the last chunk sent
|
||||
box_in.user_data.last_end_time = 0;
|
||||
% number of call to the process function
|
||||
box_in.user_data.call_count = 0;
|
||||
% sample count
|
||||
box_in.user_data.nb_samples = 0;
|
||||
|
||||
box_out = box_in;
|
||||
end
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
% tuto3_sinus_generator_Process.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 25 May 2012
|
||||
%
|
||||
|
||||
function box_out = tuto3_sinus_generator_Process(box_in)
|
||||
|
||||
channel_count = box_in.settings(1).value;
|
||||
samples_per_buffer = box_in.settings(2).value;
|
||||
amplitude = box_in.settings(3).value;
|
||||
stimulation = box_in.settings(4).value;
|
||||
|
||||
start_time = box_in.user_data.last_end_time;
|
||||
end_time = box_in.clock;
|
||||
% We produce data of the past step (e.g. at t2 we produce the data of [t1,t2]), thus we skip the first call
|
||||
if start_time ~= 0
|
||||
T = 1/box_in.outputs{1}.header.sampling_rate;
|
||||
t = (box_in.user_data.nb_samples:box_in.user_data.nb_samples+samples_per_buffer-1)*T;
|
||||
signal = zeros(channel_count, samples_per_buffer);
|
||||
freq = 10;
|
||||
for chan = 1 : channel_count
|
||||
sinus = amplitude * sin(2*pi* freq *t);
|
||||
signal(chan,1:samples_per_buffer) = sinus;
|
||||
freq = freq + 10;
|
||||
end
|
||||
|
||||
if mod(box_in.user_data.call_count, box_in.clock_frequency) == 0
|
||||
stim_set = [stimulation; box_in.clock; 0];
|
||||
disp('Sending a stimulation...');
|
||||
else
|
||||
stim_set = [];
|
||||
end
|
||||
|
||||
box_in = OV_addOutputBuffer(box_in,1,start_time,end_time,signal);
|
||||
box_in = OV_addOutputBuffer(box_in,2,start_time,end_time,stim_set);
|
||||
|
||||
box_in.user_data.nb_samples = box_in.user_data.nb_samples + samples_per_buffer;
|
||||
end
|
||||
|
||||
box_in.user_data.last_end_time = end_time;
|
||||
box_in.user_data.call_count = box_in.user_data.call_count +1;
|
||||
|
||||
box_out = box_in;
|
||||
end
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
% tuto3_sinus_generator_Uninitialize.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 25 May 2012
|
||||
%
|
||||
% The function tuto3_sinus_generator_Uninitialize is called when pressing 'stop' in the scenario.
|
||||
%
|
||||
function box_out = tuto3_sinus_generator_Uninitialize(box_in)
|
||||
disp('Uninitializing the box...')
|
||||
|
||||
box_out = box_in;
|
||||
|
||||
end
|
||||
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* \page BoxAlgorithm_MatlabScripting Matlab Scripting
|
||||
__________________________________________________________________
|
||||
|
||||
Detailed description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_MatlabScripting_Description|
|
||||
The Matlab Scripting box uses the Matlab Engine to process data using Matlab.
|
||||
This box can be configured with any number of inputs, outputs and settings, of any type.
|
||||
You will need a valid Matlab installation and license at runtime. This box is currently compatible with
|
||||
Matlab 32 and 64 bits on Linux, but only with Matlab 32 bits on Windows.
|
||||
|
||||
For a complete tutorial, please check <a href="http://openvibe.inria.fr/tutorial-using-matlab-with-openvibe">this documentation page</a>.
|
||||
* |OVP_DocEnd_BoxAlgorithm_MatlabScripting_Description|
|
||||
__________________________________________________________________
|
||||
|
||||
Settings description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_MatlabScripting_Settings|
|
||||
* |OVP_DocEnd_BoxAlgorithm_MatlabScripting_Settings|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_MatlabScripting_Setting1|
|
||||
The box clock frequency can be an integer between 1 and 128Hz. This tells how many time per second the box "Process" function will be called.
|
||||
* |OVP_DocEnd_BoxAlgorithm_MatlabScripting_Setting1|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_MatlabScripting_Setting2|
|
||||
User must set the place where to find the Matlab executables. On windows it should be in the bin/win32 directory.
|
||||
On Linux, fill this setting with the command line you are using to launch Matlab on your computer.
|
||||
* |OVP_DocEnd_BoxAlgorithm_MatlabScripting_Setting2|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_MatlabScripting_Setting3|
|
||||
Please enter the Matlab working directory in which this box will work. This should be the absolute adress of the folder where you have put all the function files.
|
||||
* |OVP_DocEnd_BoxAlgorithm_MatlabScripting_Setting3|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_MatlabScripting_Setting4|
|
||||
The name of the matlab function called when initializing the box (i.e. when pressing play in the scenario).
|
||||
This function is called only once.
|
||||
|
||||
Its signature must be: [box_out] = initialize(box_in), where box_out and box_in are specific structure.
|
||||
Please see the dedicated <a href="http://openvibe.inria.fr/tutorial-using-matlab-with-openvibe">tutorial</a> for a complete reference.
|
||||
* |OVP_DocEnd_BoxAlgorithm_MatlabScripting_Setting4|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_MatlabScripting_Setting5|
|
||||
The name of the matlab function called on every tick of the process loop.
|
||||
This function is called at the box clock frequency.
|
||||
|
||||
Its signature must be: [box_out] = process(box_in), where box_out and box_in are specific structure.
|
||||
Please see the dedicated <a href="http://openvibe.inria.fr/tutorial-using-matlab-with-openvibe">tutorial</a> for a complete reference.
|
||||
* |OVP_DocEnd_BoxAlgorithm_MatlabScripting_Setting5|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_MatlabScripting_Setting6|
|
||||
The name of the matlab function called when uninitializing the box (i.e. when pressing stop in the scenario).
|
||||
This function is called only once.
|
||||
|
||||
Its signature must be: [box_out] = uninitialize(box_in), where box_out and box_in are specific structure.
|
||||
Please see the dedicated <a href="http://openvibe.inria.fr/tutorial-using-matlab-with-openvibe">tutorial</a> for a complete reference.
|
||||
* |OVP_DocEnd_BoxAlgorithm_MatlabScripting_Setting6|
|
||||
__________________________________________________________________
|
||||
|
||||
Examples description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_MatlabScripting_Examples|
|
||||
The dedicated <a href="http://openvibe.inria.fr/tutorial-using-matlab-with-openvibe">tutorial</a> provides 3 examples:
|
||||
- Signal filtering
|
||||
- FFT computation and spectrum plot in Matlab
|
||||
- Signal and stimulation generator
|
||||
* |OVP_DocEnd_BoxAlgorithm_MatlabScripting_Examples|
|
||||
__________________________________________________________________
|
||||
|
||||
Miscellaneous description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_MatlabScripting_Miscellaneous|
|
||||
* |OVP_DocEnd_BoxAlgorithm_MatlabScripting_Miscellaneous|
|
||||
*/
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 85 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 105 KiB |
+19
@@ -0,0 +1,19 @@
|
||||
% openvibe toolbox for Matlab
|
||||
% OV_addInputBuffer.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 13 Jan. 2012
|
||||
|
||||
% Appends a new signal chunk to a signal input buffer in a matlab box instance.
|
||||
% -------------------------------
|
||||
% MEANT TO BE USED BY OPENVIBE
|
||||
|
||||
function box_out = OV_addInputBuffer(box_in, input_index, start_time, end_time, matrix_data)
|
||||
|
||||
chunk.start_time = start_time;
|
||||
chunk.end_time = end_time;
|
||||
chunk.matrix_data = matrix_data;
|
||||
box_in.inputs{input_index}.buffer{size(box_in.inputs{input_index}.buffer,2)+1} = chunk;
|
||||
|
||||
box_out = box_in;
|
||||
end
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
% openvibe toolbox for Matlab
|
||||
% OV_addOutputBuffer.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 13 Jan. 2012
|
||||
|
||||
% Appends a new chunk in an output buffer,
|
||||
% meant to be popped by the openvibe box.
|
||||
% -------------------------------
|
||||
% MEANT TO BE USED IN USER SCRIPT
|
||||
|
||||
function box_out = OV_addOutputBuffer(box_in, output_index, start_time, end_time, matrix_data)
|
||||
|
||||
chunk.start_time = start_time;
|
||||
chunk.end_time = end_time;
|
||||
chunk.matrix_data = matrix_data;
|
||||
box_in.outputs{output_index}.buffer{size(box_in.outputs{output_index}.buffer,2)+1} = chunk;
|
||||
|
||||
box_out = box_in;
|
||||
end
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_createBoxInstance.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
%
|
||||
% This file is meant to be executed prior to any user defined script.
|
||||
% It construct the objects used by the other functions of the toolkit
|
||||
% MEANT TO BE USED BY OPENVIBE
|
||||
%
|
||||
%out
|
||||
|
||||
|
||||
function box = OV_createBoxInstance(input_count, output_count)
|
||||
|
||||
box = [];
|
||||
box.settings = [];
|
||||
box.inputs = {};
|
||||
for i = 1 : input_count
|
||||
box.inputs{i}.header = {};
|
||||
box.inputs{i}.buffer = {};
|
||||
end
|
||||
|
||||
box.outputs = {};
|
||||
for i = 1 : output_count
|
||||
box.outputs{i}.header = {};
|
||||
box.outputs{i}.buffer = {};
|
||||
end
|
||||
box.user_data = {};
|
||||
|
||||
box.clock = 0;
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_define.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% This file is meant to be executed prior to any user defined script.
|
||||
% It declare all stim IDs as variable for use by the user.
|
||||
% MEANT TO BE CALLED BY OPENVIBE
|
||||
%
|
||||
% Stimulation codes
|
||||
% Originally from openvibe-toolkit/ovtk_defines.h
|
||||
|
||||
|
||||
function OV_define()
|
||||
|
||||
% STREAM TYPES:
|
||||
global OV_TypeId_EBMLStream;
|
||||
OV_TypeId_EBMLStream = uint64(hex2dec('434F65872EFD2B7E'));
|
||||
global OV_TypeId_ChannelLocalisation;
|
||||
OV_TypeId_ChannelLocalisation = uint64(hex2dec('013DF452A3A8879A'));
|
||||
global OV_TypeId_ExperimentationInformation; % deprecated
|
||||
OV_TypeId_ExperimentationInformation = uint64(hex2dec('403488E7565D70B6')); % deprecated
|
||||
global OV_TypeId_ExperimentInfo;
|
||||
OV_TypeId_ExperimentInfo = uint64(hex2dec('403488E7565D70B6'));
|
||||
global OV_TypeId_Stimulations;
|
||||
OV_TypeId_Stimulations = uint64(hex2dec('6F752DD0082A321E'));
|
||||
global OV_TypeId_StreamedMatrix;
|
||||
OV_TypeId_StreamedMatrix = uint64(hex2dec('544A003E6DCBA5F6'));
|
||||
global OV_TypeId_FeatureVector;
|
||||
OV_TypeId_FeatureVector = uint64(hex2dec('17341935152FF448'));
|
||||
global OV_TypeId_Signal;
|
||||
OV_TypeId_Signal = uint64(hex2dec('5BA36127195FEAE1'));
|
||||
global OV_TypeId_Spectrum;
|
||||
OV_TypeId_Spectrum = uint64(hex2dec('1F261C0A593BF6BD'));
|
||||
|
||||
% SETTING TYPES:
|
||||
global OV_TypeId_Boolean;
|
||||
OV_TypeId_Boolean = uint64(hex2dec('2CDB2F0B12F231EA'));
|
||||
global OV_TypeId_Integer;
|
||||
OV_TypeId_Integer = uint64(hex2dec('007DEEF92F3E95C6'));
|
||||
global OV_TypeId_Float;
|
||||
OV_TypeId_Float = uint64(hex2dec('512A166F5C3EF83F'));
|
||||
global OV_TypeId_String;
|
||||
OV_TypeId_String = uint64(hex2dec('79A9EDEB245D83FC'));
|
||||
global OV_TypeId_Filename;
|
||||
OV_TypeId_Filename = uint64(hex2dec('330306DD74A95F98'));
|
||||
global OV_TypeId_Script;
|
||||
OV_TypeId_Script = uint64(hex2dec('B0D0DB4549CBC34A'));
|
||||
global OV_TypeId_Stimulation;
|
||||
OV_TypeId_Stimulation = uint64(hex2dec('2C132D6E44AB0D97'));
|
||||
global OV_TypeId_LogLevel;
|
||||
OV_TypeId_LogLevel = uint64(hex2dec('A88B36670871638C'));
|
||||
global OV_TypeId_Color;
|
||||
OV_TypeId_Color = uint64(hex2dec('7F45A2A97DB12219'));
|
||||
global OV_TypeId_ColorGradient;
|
||||
OV_TypeId_ColorGradient = uint64(hex2dec('3D3C7C7FEF0E7129'));
|
||||
|
||||
|
||||
% STIM CODES:
|
||||
global OVTK_StimulationId_LabelStart;
|
||||
OVTK_StimulationId_LabelStart = uint64(hex2dec('00008100'));
|
||||
global OVTK_StimulationId_LabelEnd;
|
||||
OVTK_StimulationId_LabelEnd = uint64(hex2dec('000081ff'));
|
||||
|
||||
global OVTK_StimulationId_NumberStart;
|
||||
OVTK_StimulationId_NumberStart = uint64(hex2dec('00000000'));
|
||||
global OVTK_StimulationId_NumberEnd;
|
||||
OVTK_StimulationId_NumberEnd = uint64(hex2dec('000000ff'));
|
||||
end
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
% openvibe toolbox for Matlab
|
||||
% OV_getSignalOutputHeader.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% Set the header information on a signal output.
|
||||
% MEANT TO BE USED IN USER SCRIPT
|
||||
|
||||
function [errno, nb_channels, channel_names, dynamic] = OV_getChannelLocalisationOutputHeader(box_in, output_index)
|
||||
|
||||
if(numel(box_in.outputs{output_index}.header) == 0)
|
||||
nb_channels = 0;
|
||||
channel_names = 0;
|
||||
dynamic = 0;
|
||||
errno = 1;
|
||||
else
|
||||
nb_channels = box_in.outputs{output_index}.header.nb_channels;
|
||||
channel_names = box_in.outputs{output_index}.header.channel_names;
|
||||
dynamic = box_in.outputs{output_index}.header.dynamic;
|
||||
errno = 0;
|
||||
end
|
||||
|
||||
end
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
% openvibe toolbox for Matlab
|
||||
% OV_getSignalOutputHeader.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% Set the header information on a signal output.
|
||||
% MEANT TO BE USED IN USER SCRIPT
|
||||
|
||||
function [errno, nb_features, labels] = OV_getFeatureVectorOutputHeader(box_in, output_index)
|
||||
|
||||
if(numel(box_in.outputs{output_index}.header) == 0)
|
||||
nb_features = 0;
|
||||
labels = 0;
|
||||
errno = 1;
|
||||
else
|
||||
nb_features = box_in.outputs{output_index}.header.nb_features;
|
||||
labels = box_in.outputs{output_index}.header.labels;
|
||||
errno = 0;
|
||||
end
|
||||
|
||||
end
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_hasPendingInputChunk.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 13 Jan. 2012
|
||||
|
||||
% Tests if there is pending Input chunk in the buffer
|
||||
% -------------------------------
|
||||
% MEANT TO BE USED IN USER SCRIPT
|
||||
|
||||
function nb_pending = OV_getNbPendingInputChunk(box_in, input_index)
|
||||
|
||||
if(input_index > size(box_in.inputs,2))
|
||||
disp('Error while calling OV_getNbPendingOutputChunk : output index out-of-range.')
|
||||
nb_pending = 0;
|
||||
else
|
||||
nb_pending = size(box_in.inputs{input_index}.buffer,2);
|
||||
end
|
||||
|
||||
end
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_hasPendingOutputChunk.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 13 Jan. 2012
|
||||
|
||||
% Tests if there is pending output chunk in the buffer
|
||||
% -------------------------------
|
||||
% MEANT TO BE USED IN USER SCRIPT
|
||||
|
||||
function nb_pending = OV_getNbPendingOutputChunk(box_in, output_index)
|
||||
|
||||
if(output_index > size(box_in.outputs,2))
|
||||
disp('Error while calling OV_getNbPendingOutputChunk : output index out-of-range.')
|
||||
nb_pending = 0;
|
||||
else
|
||||
nb_pending = size(box_in.outputs{output_index}.buffer,2);
|
||||
end
|
||||
|
||||
end
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
% openvibe toolbox for Matlab
|
||||
% OV_getSignalOutputHeader.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% Set the header information on a signal output.
|
||||
% MEANT TO BE USED IN USER SCRIPT
|
||||
|
||||
function [errno, nb_channels, nb_samples_per_buffer, channel_names, sampling_rate] = OV_getSignalOutputHeader(box_in, output_index)
|
||||
|
||||
if(numel(box_in.outputs{output_index}.header) == 0)
|
||||
nb_channels = 0;
|
||||
nb_samples_per_buffer = 0;
|
||||
channel_names = 0;
|
||||
sampling_rate = 0;
|
||||
errno = 1;
|
||||
else
|
||||
nb_channels = box_in.outputs{output_index}.header.nb_channels;
|
||||
nb_samples_per_buffer = box_in.outputs{output_index}.header.nb_samples_per_buffer;
|
||||
channel_names = box_in.outputs{output_index}.header.channel_names;
|
||||
sampling_rate = box_in.outputs{output_index}.header.sampling_rate;
|
||||
errno = 0;
|
||||
end
|
||||
|
||||
end
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
% openvibe toolbox for Matlab
|
||||
% OV_getSpectrumOutputHeader.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% Set the header information on a signal output.
|
||||
% MEANT TO BE USED IN USER SCRIPT
|
||||
|
||||
function [errno, nb_channels, channel_names, nb_abscissas, abscissas_names, abscissas_linear, sampling_rate] = OV_getSpectrumOutputHeader(box_in, output_index)
|
||||
|
||||
if(numel(box_in.outputs{output_index}.header) == 0)
|
||||
nb_channels = 0;
|
||||
channel_names = 0;
|
||||
nb_abscissas = 0;
|
||||
abscissas_names = 0;
|
||||
abscissas_linear = 0;
|
||||
sampling_rate = 0;
|
||||
errno = 1;
|
||||
else
|
||||
nb_channels = box_in.outputs{output_index}.header.nb_channels;
|
||||
channel_names = box_in.outputs{output_index}.header.channel_names;
|
||||
|
||||
nb_abscissas = box_in.outputs{output_index}.header.nb_abscissas;
|
||||
abscissas_names = box_in.outputs{output_index}.header.abscissas_names;
|
||||
abscissas_linear = box_in.outputs{output_index}.header.abscissas;
|
||||
%reshape(box_in.outputs{output_index}.header.bands,1,numel(box_in.outputs{output_index}.header.bands));
|
||||
sampling_rate = box_in.outputs{output_index}.header.sampling_rate;
|
||||
errno = 0;
|
||||
end
|
||||
end
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
% openvibe toolbox for Matlab
|
||||
% OV_getStimulationOutputHeader.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% Set the header information on a signal output.
|
||||
% MEANT TO BE USED IN USER SCRIPT
|
||||
|
||||
function OV_getStimulationOutputHeader(box_in, output_index)
|
||||
|
||||
%This function does nothing, the stimulation header is empty.
|
||||
|
||||
end
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
% openvibe toolbox for Matlab
|
||||
% OV_getStimulationOutputHeader.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% Set the header information on a signal output.
|
||||
% MEANT TO BE USED IN USER SCRIPT
|
||||
|
||||
function OV_getStimulationsOutputHeader(box_in, output_index)
|
||||
|
||||
%This function does nothing, the stimulation header is empty.
|
||||
|
||||
end
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
% openvibe toolbox for Matlab
|
||||
% OV_getStreamedMatrixOutputHeader.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% Set the header information on a signal output.
|
||||
% MEANT TO BE USED IN USER SCRIPT
|
||||
|
||||
function [errno, nb_dimensions, dimension_sizes, dimension_labels] = OV_getStreamedMatrixOutputHeader(box_in, output_index)
|
||||
|
||||
if(numel(box_in.outputs{output_index}.header) == 0)
|
||||
nb_dimensions = 0;
|
||||
dimension_sizes = 0;
|
||||
dimension_labels = 0;
|
||||
errno = 1;
|
||||
else
|
||||
nb_dimensions = box_in.outputs{output_index}.header.nb_dimensions;
|
||||
dimension_sizes = box_in.outputs{output_index}.header.dimension_sizes;
|
||||
dimension_labels = box_in.outputs{output_index}.header.dimension_labels;
|
||||
errno = 0;
|
||||
end
|
||||
|
||||
end
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_popInputBuffer.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 13 Jan. 2012
|
||||
|
||||
% Pops the first signal chunk on an input
|
||||
% -------------------------------
|
||||
% output = matrix data (matlab format)
|
||||
% -------------------------------
|
||||
% MEANT TO BE USED IN USER SCRIPT
|
||||
|
||||
function [box_out, start_time,end_time, matrix_data] = OV_popInputBuffer(box_in, input_index)
|
||||
|
||||
if size(box_in.inputs{input_index}.buffer,2) == 0
|
||||
start_time = -1;
|
||||
end_time = -1;
|
||||
matrix_data = [];
|
||||
else
|
||||
start_time = box_in.inputs{input_index}.buffer{1}.start_time;
|
||||
end_time = box_in.inputs{input_index}.buffer{1}.end_time;
|
||||
matrix_data = box_in.inputs{input_index}.buffer{1}.matrix_data;
|
||||
end
|
||||
|
||||
box_in.inputs{input_index}.buffer = box_in.inputs{input_index}.buffer(2:end);
|
||||
|
||||
box_out = box_in;
|
||||
|
||||
end
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_popOutputBuffer.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% pops the last chunk in the output buffer
|
||||
% MEANT TO BE USED IN OPENVIBE
|
||||
|
||||
function [box_out, start_time, end_time, linear_matrix_size, linear_data] = OV_popOutputBuffer(box_in, output_index)
|
||||
|
||||
if size(box_in.outputs{output_index}.buffer,1) == 0
|
||||
start_time = -1;
|
||||
end_time = -1;
|
||||
linear_data = [];
|
||||
linear_matrix_size = 0;
|
||||
else
|
||||
start_time = box_in.outputs{output_index}.buffer{1}.start_time;
|
||||
end_time = box_in.outputs{output_index}.buffer{1}.end_time;
|
||||
nb_elements = size(box_in.outputs{output_index}.buffer{1}.matrix_data(1:end),2);
|
||||
linear_data = box_in.outputs{output_index}.buffer{1}.matrix_data;
|
||||
linear_matrix_size = nb_elements;
|
||||
end
|
||||
|
||||
box_in.outputs{output_index}.buffer = box_in.outputs{output_index}.buffer(2:end);
|
||||
|
||||
box_out = box_in;
|
||||
|
||||
end
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_popOutputBufferReshape.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% pops the last chunk in the output buffer
|
||||
% MEANT TO BE USED IN OPENVIBE
|
||||
|
||||
function [box_out, start_time, end_time, linear_matrix_size, linear_data] = OV_popOutputBufferReshape(box_in, output_index)
|
||||
|
||||
if size(box_in.outputs{output_index}.buffer,1) == 0
|
||||
start_time = -1;
|
||||
end_time = -1;
|
||||
linear_data = [];
|
||||
linear_matrix_size = 0;
|
||||
else
|
||||
start_time = box_in.outputs{output_index}.buffer{1}.start_time;
|
||||
end_time = box_in.outputs{output_index}.buffer{1}.end_time;
|
||||
nb_elements = numel(box_in.outputs{output_index}.buffer{1}.matrix_data);
|
||||
linear_data = reshape(box_in.outputs{output_index}.buffer{1}.matrix_data',1,nb_elements);
|
||||
linear_matrix_size = nb_elements;
|
||||
end
|
||||
|
||||
box_in.outputs{output_index}.buffer = box_in.outputs{output_index}.buffer(2:end);
|
||||
|
||||
box_out = box_in;
|
||||
|
||||
end
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_setChannelLocalizationInputHeader.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% Set the header information on a Channel Localization input.
|
||||
|
||||
function box_out = OV_setChannelLocalisationInputHeader(box_in, input_index, nb_channels, channel_names, dynamic)
|
||||
|
||||
box_in.inputs{input_index}.header.type = 'Channel Localisation Stream';
|
||||
box_in.inputs{input_index}.header.nb_channels = nb_channels;
|
||||
box_in.inputs{input_index}.header.channel_names = channel_names;
|
||||
box_in.inputs{input_index}.header.dynamic = dynamic;
|
||||
|
||||
box_in.inputs{input_index}.buffer = {};
|
||||
|
||||
box_out = box_in;
|
||||
end
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_setChannelLocalizationInputHeader.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% Set the header information on a Channel Localization input.
|
||||
|
||||
function box_out = OV_setChannelLocalisationOutputHeader(box_in, output_index, nb_channels, channel_names, dynamic)
|
||||
|
||||
box_in.output{output_index}.header.type = 'Channel Localisation Stream';
|
||||
box_in.output{output_index}.header.nb_channels = nb_channels;
|
||||
box_in.output{output_index}.header.channel_names = channel_names;
|
||||
box_in.output{output_index}.header.dynamic = dynamic;
|
||||
|
||||
box_in.output{output_index}.buffer = {};
|
||||
|
||||
box_out = box_in;
|
||||
end
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_setFeatureVectorInputHeader.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% Set the header information on a Feature Vector input.
|
||||
|
||||
function box_out = OV_setFeatureVectorInputHeader(box_in, input_index, nb_features, labels)
|
||||
|
||||
box_in.inputs{input_index}.header.type = 'Feature Vector Stream';
|
||||
box_in.inputs{input_index}.header.nb_features = nb_features;
|
||||
box_in.inputs{input_index}.header.labels = labels;
|
||||
|
||||
box_in.inputs{input_index}.buffer = {};
|
||||
|
||||
box_out = box_in;
|
||||
end
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_setFeatureVectorInputHeader.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% Set the header information on a Feature Vector input.
|
||||
|
||||
function box_out = OV_setFeatureVectorOutputHeader(box_in, output_index, nb_features, labels)
|
||||
|
||||
box_in.outputs{output_index}.header.type = 'Feature Vector Stream';
|
||||
box_in.outputs{output_index}.header.nb_features = nb_features;
|
||||
box_in.outputs{output_index}.header.labels = labels;
|
||||
|
||||
box_in.outputs{output_index}.buffer = {};
|
||||
|
||||
box_out = box_in;
|
||||
end
|
||||
@@ -0,0 +1,15 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_setSettings.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% This file is meant to be executed prior to any user defined script.
|
||||
% It construct the objects used by the other functions of the toolkit
|
||||
% MEANT TO BE USED BY OPENVIBE
|
||||
|
||||
function box_out = OV_setSettings(box_in, names, types, values)
|
||||
|
||||
box_in.settings = struct('name',names,'type',types,'value',values);
|
||||
box_out = box_in;
|
||||
end
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_setSignalInputHeader.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% Set the header information on a signal input.
|
||||
|
||||
function box_out = OV_setSignalInputHeader(box_in, input_index, nb_channel, nb_samples_per_buffer, channel_names, sampling_rate)
|
||||
|
||||
box_in.inputs{input_index}.header.type = 'Signal Stream';
|
||||
box_in.inputs{input_index}.header.nb_channels = nb_channel;
|
||||
box_in.inputs{input_index}.header.nb_samples_per_buffer = nb_samples_per_buffer;
|
||||
box_in.inputs{input_index}.header.channel_names = channel_names;
|
||||
box_in.inputs{input_index}.header.sampling_rate = sampling_rate;
|
||||
|
||||
box_in.inputs{input_index}.buffer = {};
|
||||
|
||||
box_out = box_in;
|
||||
end
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_setSignalOutputHeader.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% Set the header information on a signal output.
|
||||
% MEANT TO BE USED IN USER SCRIPT
|
||||
|
||||
function box_out = OV_setSignalOutputHeader(box_in, output_index, nb_channel, nb_samples_per_buffer, channel_names, sampling_rate)
|
||||
|
||||
box_in.outputs{output_index}.header.type = 'Signal Stream';
|
||||
box_in.outputs{output_index}.header.nb_channels = nb_channel;
|
||||
box_in.outputs{output_index}.header.nb_samples_per_buffer = nb_samples_per_buffer;
|
||||
box_in.outputs{output_index}.header.channel_names = channel_names;
|
||||
box_in.outputs{output_index}.header.sampling_rate = sampling_rate;
|
||||
|
||||
box_in.outputs{output_index}.buffer = {};
|
||||
|
||||
box_out = box_in;
|
||||
end
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_setSpectrumHeader.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% Set the header information on a Spectrum input.
|
||||
|
||||
function box_out = OV_setSpectrumInputHeader(box_in, input_index, nb_channels, channel_names, nb_abscissas, abscissas_names, abscissas, sampling_rate)
|
||||
|
||||
box_in.inputs{input_index}.header.type = 'Spectrum Stream';
|
||||
box_in.inputs{input_index}.header.nb_channels = nb_channels;
|
||||
box_in.inputs{input_index}.header.channel_names = channel_names;
|
||||
box_in.inputs{input_index}.header.nb_abscissas = nb_abscissas;
|
||||
box_in.inputs{input_index}.header.abscissas_names = abscissas_names;
|
||||
box_in.inputs{input_index}.header.abscissas = abscissas;
|
||||
box_in.inputs{input_index}.header.sampling_rate = sampling_rate;
|
||||
|
||||
box_in.inputs{input_index}.buffer = {};
|
||||
|
||||
box_out = box_in;
|
||||
end
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_setSpectrumOutputHeader.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% Set the header information on a Spectrum input.
|
||||
|
||||
function box_out = OV_setSpectrumOutputHeader(box_in, output_index, nb_channels, channel_names, nb_abscissas, abscissas_names, abscissas, sampling_rate)
|
||||
|
||||
box_in.outputs{output_index}.header.type = 'Spectrum Stream';
|
||||
box_in.outputs{output_index}.header.nb_channels = nb_channels;
|
||||
box_in.outputs{output_index}.header.channel_names = channel_names;
|
||||
|
||||
box_in.outputs{output_index}.header.nb_abscissas = nb_abscissas;
|
||||
box_in.outputs{output_index}.header.abscissas_names = abscissas_names;
|
||||
box_in.outputs{output_index}.header.abscissas = abscissas;
|
||||
box_in.outputs{output_index}.header.sampling_rate = sampling_rate;
|
||||
|
||||
box_in.outputs{output_index}.buffer = {};
|
||||
|
||||
box_out = box_in;
|
||||
end
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_setChannelLocalizationInputHeader.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% Set the header information on a Stimulation input.
|
||||
|
||||
function box_out = OV_setStimulationInputHeader(box_in, input_index)
|
||||
|
||||
box_in.inputs{input_index}.header.type = 'Stimulation Stream';
|
||||
|
||||
box_in.inputs{input_index}.buffer = {};
|
||||
|
||||
box_out = box_in;
|
||||
end
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_setStimulationOutputHeader.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% Set the header information on a Stimulation input.
|
||||
|
||||
function box_out = OV_setStimulationOutputHeader(box_in, output_index)
|
||||
|
||||
box_in.outputs{output_index}.header.type = 'Stimulation Stream';
|
||||
|
||||
box_in.outputs{output_index}.buffer = {};
|
||||
|
||||
box_out = box_in;
|
||||
end
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_setChannelLocalizationInputHeader.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% Set the header information on a Stimulation input.
|
||||
|
||||
function box_out = OV_setStimulationsInputHeader(box_in, input_index)
|
||||
|
||||
box_in.inputs{input_index}.header.type = 'Stimulation Stream';
|
||||
|
||||
box_in.inputs{input_index}.buffer = {};
|
||||
|
||||
box_out = box_in;
|
||||
end
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_setStimulationOutputHeader.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% Set the header information on a Stimulation input.
|
||||
|
||||
function box_out = OV_setStimulationsOutputHeader(box_in, output_index)
|
||||
|
||||
box_in.outputs{output_index}.header.type = 'Stimulation Stream';
|
||||
|
||||
box_in.outputs{output_index}.buffer = {};
|
||||
|
||||
box_out = box_in;
|
||||
end
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_setStreamedMatrixInputHeader.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% Set the header information on a streamed Matrix input.
|
||||
|
||||
function box_out = OV_setStreamedMatrixInputHeader(box_in, input_index, nb_dim, dim_sizes, dim_labels)
|
||||
|
||||
box_in.inputs{input_index}.header.type = 'Streamed Matrix Stream';
|
||||
box_in.inputs{input_index}.header.nb_dimensions = nb_dim;
|
||||
box_in.inputs{input_index}.header.dimension_sizes = dim_sizes;
|
||||
box_in.inputs{input_index}.header.dimension_labels = dim_labels;
|
||||
|
||||
box_in.inputs{input_index}.buffer = {};
|
||||
|
||||
box_out = box_in;
|
||||
end
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
% OV_MATLAB toolkit
|
||||
% OV_setStreamedMatrixOutputHeader.m
|
||||
% -------------------------------
|
||||
% Author : Laurent Bonnet (INRIA)
|
||||
% Date : 28/07/2011
|
||||
|
||||
% Set the header information on a signal output.
|
||||
% MEANT TO BE USED IN USER SCRIPT
|
||||
|
||||
function box_out = OV_setStreamedMatrixOutputHeader(box_in, output_index, nb_dim, dim_sizes, dim_labels)
|
||||
|
||||
box_in.outputs{output_index}.header.type = 'Streamed Matrix Stream';
|
||||
box_in.outputs{output_index}.header.nb_dimensions = nb_dim;
|
||||
box_in.outputs{output_index}.header.dimension_sizes = dim_sizes;
|
||||
box_in.outputs{output_index}.header.dimension_labels = dim_labels;
|
||||
|
||||
box_in.outputs{output_index}.buffer = {};
|
||||
|
||||
box_out = box_in;
|
||||
end
|
||||
+733
@@ -0,0 +1,733 @@
|
||||
#include <iomanip>
|
||||
#if defined TARGET_HAS_ThirdPartyMatlab
|
||||
|
||||
#include "ovpCBoxAlgorithmMatlabScripting.h"
|
||||
|
||||
#include <system/ovCMath.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
#include <algorithm>
|
||||
|
||||
#include <mex.h>
|
||||
#include <engine.h>
|
||||
|
||||
#include <fs/Files.h>
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
#include <windows.h>
|
||||
#include <direct.h>
|
||||
#define getCurrentDir _getcwd
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#define getCurrentDir getcwd
|
||||
#endif
|
||||
|
||||
|
||||
// Size of the internal buffer storing matlab messages, in char
|
||||
#define MATLAB_BUFFER 2048
|
||||
#define MATLAB_ENGINE ((Engine*)m_engineHandle)
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Matlab {
|
||||
|
||||
// Sanitizes a path so that it only has / or \ characters and has a / or \ in the end.
|
||||
// @fixme should move to plugins-FS possibly
|
||||
void CBoxAlgorithmMatlabScripting::sanitizePath(CString& pathToModify)
|
||||
{
|
||||
std::string tmpPath(pathToModify);
|
||||
// Append / to end of path if its not there already
|
||||
if (tmpPath.length() > 0)
|
||||
{
|
||||
const char lastChar = tmpPath.at(tmpPath.length() - 1);
|
||||
if (lastChar != '\\' && lastChar != '/') { tmpPath += "/"; }
|
||||
}
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
std::replace(tmpPath.begin(), tmpPath.end(), '/', '\\'); // Convert '/' to '\'
|
||||
#endif
|
||||
pathToModify = tmpPath.c_str();
|
||||
}
|
||||
|
||||
// The checkFailureRoutine() verifies the result of a matlab call (via engine or helper functions) given as argument.
|
||||
// If the result is false (the matlab call failed), the message msg is printed in the Error Log Level, and the macro returns false.
|
||||
// The Matlab output buffer is then printed. If an error message is detected in the buffer, the same error message is printed and
|
||||
// the macro returns false.
|
||||
bool CBoxAlgorithmMatlabScripting::checkFailureRoutine(const bool result, const CString& msg)
|
||||
{
|
||||
OV_ERROR_UNLESS_KRF(result, msg, Kernel::ErrorType::BadProcessing);
|
||||
|
||||
m_errorDetected = false;
|
||||
this->printOutputBufferWithFormat();
|
||||
OV_ERROR_UNLESS_KRF(!m_errorDetected, msg, Kernel::ErrorType::BadProcessing);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmMatlabScripting::openMatlabEngineSafely()
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "Trying to open the Matlab engine\n";
|
||||
#if defined TARGET_OS_Linux
|
||||
m_engineHandle = ::engOpen(m_matlabPath.toASCIIString());
|
||||
OV_ERROR_UNLESS_KRF(m_matlabEngine, "Could not open the Matlab engine.\nThe configured path to the matlab executable was expanded as '" << m_matlabPath << "'.", Kernel::ErrorType::BadProcessing);
|
||||
}
|
||||
#elif defined TARGET_OS_Windows
|
||||
__try { m_engineHandle = engOpen(nullptr); }
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "First call to the MATLAB engine failed.\n";
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "To use this box you must have MATLAB installed on your computer.\n";
|
||||
#if defined(TARGET_ARCHITECTURE_x64)
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "For this build of OpenViBE, MATLAB needs to be a 64bit version.\n";
|
||||
#else
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "For this build of OpenViBE, MATLAB needs to be a 32bit version.\n";
|
||||
#endif
|
||||
m_engineHandle = nullptr;
|
||||
}
|
||||
if (!MATLAB_ENGINE)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "Could not open the Matlab engine.\nThe matlab binary path was reasoned to be '" << m_matlabPath << "'.\n";
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
OV_ERROR_KRF("Only Linux and Windows are supported", Kernel::ErrorType::BadVersion);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmMatlabScripting::initialize()
|
||||
{
|
||||
m_engineHandle = nullptr;
|
||||
m_matlabBuffer = nullptr;
|
||||
m_helper = new CMatlabHelper(this->getLogManager(), this->getErrorManager());
|
||||
|
||||
m_clockFrequency = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
|
||||
|
||||
for (size_t i = 0; i < getStaticBoxContext().getInputCount(); ++i)
|
||||
{
|
||||
CIdentifier type;
|
||||
getStaticBoxContext().getInputType(i, type);
|
||||
Toolkit::TDecoder<CBoxAlgorithmMatlabScripting>* decoder = nullptr;
|
||||
if (type == OV_TypeId_StreamedMatrix) { decoder = new Toolkit::TStreamedMatrixDecoder<CBoxAlgorithmMatlabScripting>(*this, i); }
|
||||
else if (type == OV_TypeId_ChannelLocalisation) { decoder = new Toolkit::TChannelLocalisationDecoder<CBoxAlgorithmMatlabScripting>(*this, i); }
|
||||
else if (type == OV_TypeId_FeatureVector) { decoder = new Toolkit::TFeatureVectorDecoder<CBoxAlgorithmMatlabScripting>(*this, i); }
|
||||
else if (type == OV_TypeId_Spectrum) { decoder = new Toolkit::TSpectrumDecoder<CBoxAlgorithmMatlabScripting>(*this, i); }
|
||||
else if (type == OV_TypeId_Signal) { decoder = new Toolkit::TSignalDecoder<CBoxAlgorithmMatlabScripting>(*this, i); }
|
||||
else if (type == OV_TypeId_Stimulations) { decoder = new Toolkit::TStimulationDecoder<CBoxAlgorithmMatlabScripting>(*this, i); }
|
||||
else if (type == OV_TypeId_ExperimentInfo) { decoder = new Toolkit::TExperimentInfoDecoder<CBoxAlgorithmMatlabScripting>(*this, i); }
|
||||
else { this->getLogManager() << Kernel::LogLevel_Warning << "Undefined type on input [" << i << "].\n"; }
|
||||
if (decoder != nullptr)
|
||||
{
|
||||
m_decoders.insert(std::make_pair(i, decoder));
|
||||
m_nInputHeaderSent = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < getStaticBoxContext().getOutputCount(); ++i)
|
||||
{
|
||||
CIdentifier type;
|
||||
getStaticBoxContext().getOutputType(i, type);
|
||||
Toolkit::TEncoder<CBoxAlgorithmMatlabScripting>* encoder = nullptr;
|
||||
if (type == OV_TypeId_StreamedMatrix) { encoder = new Toolkit::TStreamedMatrixEncoder<CBoxAlgorithmMatlabScripting>(*this, i); }
|
||||
else if (type == OV_TypeId_ChannelLocalisation) { encoder = new Toolkit::TChannelLocalisationEncoder<CBoxAlgorithmMatlabScripting>(*this, i); }
|
||||
else if (type == OV_TypeId_FeatureVector) { encoder = new Toolkit::TFeatureVectorEncoder<CBoxAlgorithmMatlabScripting>(*this, i); }
|
||||
else if (type == OV_TypeId_Spectrum) { encoder = new Toolkit::TSpectrumEncoder<CBoxAlgorithmMatlabScripting>(*this, i); }
|
||||
else if (type == OV_TypeId_Signal) { encoder = new Toolkit::TSignalEncoder<CBoxAlgorithmMatlabScripting>(*this, i); }
|
||||
else if (type == OV_TypeId_Stimulations) { encoder = new Toolkit::TStimulationEncoder<CBoxAlgorithmMatlabScripting>(*this, i); }
|
||||
else if (type == OV_TypeId_ExperimentInfo) { encoder = new Toolkit::TExperimentInfoEncoder<CBoxAlgorithmMatlabScripting>(*this, i); }
|
||||
else { this->getLogManager() << Kernel::LogLevel_Warning << "Undefined type on input [" << i << "].\n"; }
|
||||
if (encoder != nullptr)
|
||||
{
|
||||
m_encoders.insert(std::make_pair(i, encoder));
|
||||
m_oHeaderStates.insert(std::make_pair(i, false));
|
||||
}
|
||||
}
|
||||
|
||||
m_matlabPath = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1);
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
if (!FS::Files::directoryExists(m_matlabPath) && FS::Files::fileExists(m_matlabPath))
|
||||
{
|
||||
// The path might be pointing to the executable, try to extract the directory
|
||||
char parentPath[MAX_PATH];
|
||||
FS::Files::getParentPath(m_matlabPath, parentPath);
|
||||
m_matlabPath = CString(parentPath);
|
||||
}
|
||||
|
||||
sanitizePath(m_matlabPath);
|
||||
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "Interpreting Matlab path as '" << m_matlabPath << "'\n";
|
||||
|
||||
OV_ERROR_UNLESS_KRF(FS::Files::directoryExists(m_matlabPath), "Configured Matlab path '" << m_matlabPath << "' does not seem to be a directory",
|
||||
Kernel::ErrorType::BadConfig);
|
||||
|
||||
char* path = getenv("PATH");
|
||||
OV_ERROR_UNLESS_KRF(path, "Could not access the environment variable PATH to add Matlab path to it.", Kernel::ErrorType::BadSetting);
|
||||
|
||||
std::string strPath = std::string(path);
|
||||
size_t found = strPath.find(m_matlabPath.toASCIIString());
|
||||
if (found == std::string::npos)
|
||||
{
|
||||
CString pathModif = path + CString(";") + m_matlabPath;
|
||||
OV_ERROR_UNLESS_KRF(_putenv_s("PATH", pathModif) == 0, "Failed to modify the environment PATH with the Matlab path.",
|
||||
Kernel::ErrorType::BadProcessing);
|
||||
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "Matlab Path '" << m_matlabPath << "' added to Windows PATH environment variable.\n";
|
||||
}
|
||||
else { this->getLogManager() << Kernel::LogLevel_Trace << "No need to add matlab to PATH\n"; }
|
||||
#endif
|
||||
|
||||
if (!openMatlabEngineSafely()) { return false; }
|
||||
|
||||
m_matlabBuffer = new char[MATLAB_BUFFER + 1];
|
||||
m_matlabBuffer[MATLAB_BUFFER] = '\0';
|
||||
engOutputBuffer(MATLAB_ENGINE, m_matlabBuffer, MATLAB_BUFFER);
|
||||
m_errorDetected = false;
|
||||
|
||||
// add the openvibe toolbox to matlab path
|
||||
char curDir[FILENAME_MAX];
|
||||
OV_ERROR_UNLESS_KRF(getCurrentDir(curDir, FILENAME_MAX), "Failed to get the execution directory.", Kernel::ErrorType::BadProcessing);
|
||||
|
||||
std::string curDirString = curDir;
|
||||
std::replace(curDirString.begin(), curDirString.end(), '\\', '/');
|
||||
|
||||
this->getConfigurationManager().addOrReplaceConfigurationToken(CString("Path_Bin_Abs"), CString(curDirString.c_str()));
|
||||
|
||||
CString cmd = CString("addpath('") + Directories::getDataDir() + "/plugins/matlab');";
|
||||
engEvalString(MATLAB_ENGINE, cmd.toASCIIString());
|
||||
//if(!checkFailureRoutine(engEvalString(m_matlabEngine, (const char * )l_sOpenvibeToolboxPath) == 0, "An error occurred while adding the path to openvibe toolbox\n")) return false;
|
||||
// If there is more than 1 Matlab box in the scenario, the path is set repeatedly
|
||||
// resulting in warning messages in the buffer. We don't print them.
|
||||
// this->printOutputBufferWithFormat();
|
||||
|
||||
CString workingDir = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2);
|
||||
sanitizePath(workingDir);
|
||||
|
||||
// Try to find an unused box instance variable name
|
||||
while (true)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss.fill('0');
|
||||
ss << "OV_BOX_0x" << std::setw(8) << std::hex << System::Math::randomI() << "_0x" << std::setw(8) << std::hex << System::Math::randomI();
|
||||
m_boxInstanceVariableName = ss.str().c_str();
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "Checking if variable " << m_boxInstanceVariableName << " is in use...\n";
|
||||
mxArray* tmp = engGetVariable(MATLAB_ENGINE, m_boxInstanceVariableName.toASCIIString());
|
||||
if (!tmp)
|
||||
{
|
||||
// Found unused name
|
||||
break;
|
||||
}
|
||||
mxDestroyArray(tmp);
|
||||
}
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "Selected variable name " << m_boxInstanceVariableName << "\n";
|
||||
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "Setting working directory to " << workingDir << "\n";
|
||||
cmd = CString("cd '") + workingDir + CString("'");
|
||||
if (!checkFailureRoutine(engEvalString(MATLAB_ENGINE, cmd) == 0, "An error occurred while changing the working directory\n")) { return false; }
|
||||
|
||||
// executes the pre-run routine that defines the global identifiers for streams and stimulations codes
|
||||
cmd = CString("run '") + Directories::getDataDir() + "/plugins/matlab/OV_define.m'";
|
||||
if (!checkFailureRoutine(engEvalString(MATLAB_ENGINE, cmd) == 0, "An error occurred while calling OV_define.m")) { return false; }
|
||||
|
||||
cmd = CString("run '") + Directories::getDataDir() + "/plugins/matlab/OV_stimulations.m'";
|
||||
if (!checkFailureRoutine(engEvalString(MATLAB_ENGINE, cmd) == 0, "An error occurred while calling OV_stimulations.m")) { return false; }
|
||||
|
||||
// executes the pre-run routine that construct the ov_box object
|
||||
cmd = m_boxInstanceVariableName + " = OV_createBoxInstance(" + std::to_string(this->getStaticBoxContext().getInputCount()).c_str() + ","
|
||||
+ std::to_string(this->getStaticBoxContext().getOutputCount()).c_str() + ");";
|
||||
if (!checkFailureRoutine(engEvalString(MATLAB_ENGINE, cmd) == 0, "An error occurred while calling OV_createBoxInstance.m")) { return false; }
|
||||
|
||||
//First call to a function of the openvibe toolbox
|
||||
// if it fails, the toolbox may be not installed
|
||||
mxArray* box = engGetVariable(MATLAB_ENGINE, m_boxInstanceVariableName.toASCIIString());
|
||||
OV_ERROR_UNLESS_KRF(box, "Failed to create the box instance with OV_createBoxInstance function.", Kernel::ErrorType::BadProcessing);
|
||||
|
||||
m_initializeFunc = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 3);
|
||||
m_processFunc = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 4);
|
||||
m_uninitializeFunc = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 5);
|
||||
|
||||
// Check that the files actually exist
|
||||
CString filename;
|
||||
filename = workingDir + m_initializeFunc + ".m";
|
||||
OV_ERROR_UNLESS_KRF(FS::Files::fileExists(filename.toASCIIString()), "Cannot open '" << filename << "'", Kernel::ErrorType::BadFileRead);
|
||||
filename = workingDir + m_processFunc + ".m";
|
||||
OV_ERROR_UNLESS_KRF(FS::Files::fileExists(filename.toASCIIString()), "Cannot open '" << filename << "'", Kernel::ErrorType::BadFileRead);
|
||||
filename = workingDir + m_uninitializeFunc + ".m";
|
||||
OV_ERROR_UNLESS_KRF(FS::Files::fileExists(filename.toASCIIString()), "Cannot open '" << filename << "'", Kernel::ErrorType::BadFileRead);
|
||||
|
||||
CString names = "{";
|
||||
CString types = "{";
|
||||
CString values = "{";
|
||||
CString tmp;
|
||||
CIdentifier typeID;
|
||||
|
||||
for (size_t i = 6; i < getStaticBoxContext().getSettingCount(); ++i)
|
||||
{
|
||||
// get the setting name
|
||||
getStaticBoxContext().getSettingName(i, tmp);
|
||||
names = names + "'" + tmp + "' ";
|
||||
|
||||
//setting type
|
||||
getStaticBoxContext().getSettingType(i, typeID);
|
||||
std::stringstream ss;
|
||||
ss << typeID.id();
|
||||
types = types + "uint64(" + ss.str().c_str() + ") ";
|
||||
|
||||
//setting value, typed
|
||||
|
||||
tmp = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), i);
|
||||
if (typeID == OV_TypeId_Stimulation)
|
||||
{
|
||||
uint64_t code = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), i);
|
||||
std::stringstream ss1;
|
||||
ss1 << code;
|
||||
values = values + CString(ss1.str().c_str()) + CString(" ");
|
||||
// we keep the stimulation codes as doubles, to be able to put them in arrays with other doubles (such as timings).
|
||||
// they are still comparable with uint64_t matlab values.
|
||||
}
|
||||
else
|
||||
{
|
||||
if (typeID == OV_TypeId_Stimulation || typeID == OV_TypeId_Boolean || typeID == OV_TypeId_Integer || typeID == OV_TypeId_Float)
|
||||
{
|
||||
values = values + tmp + " "; // we store the value, these types are readable by matlab directly
|
||||
}
|
||||
else { values = values + "'" + tmp + "' "; } // we store them as matlab strings using '
|
||||
}
|
||||
}
|
||||
names += "}";
|
||||
types += "}";
|
||||
values += "}";
|
||||
|
||||
// On Windows, Matlab doesn't sometimes notice .m files have been changed, esp. if you have matlab box running while you change them
|
||||
if (!checkFailureRoutine(engEvalString(MATLAB_ENGINE, "clear functions;") == 0, "An error occurred while calling matlab 'clear functions;'\n"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
cmd = m_boxInstanceVariableName + " = OV_setSettings(" + m_boxInstanceVariableName + "," + names + "," + types + "," + values + ");";
|
||||
if (!checkFailureRoutine(engEvalString(MATLAB_ENGINE, cmd.toASCIIString()) == 0, "Error calling [OV_setSettings]\n")) { return false; }
|
||||
|
||||
// we set the box clock frequency in the box structure, so it's accessible in the user scripts if needed
|
||||
tmp = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
|
||||
cmd = m_boxInstanceVariableName + ".clock_frequency = " + tmp + ";";
|
||||
if (!checkFailureRoutine(engEvalString(MATLAB_ENGINE, cmd) == 0, "An error occurred while setting the clock frequency\n")) { return false; }
|
||||
|
||||
cmd = m_boxInstanceVariableName + " = " + m_initializeFunc + "(" + m_boxInstanceVariableName + ");";
|
||||
if (!checkFailureRoutine(engEvalString(MATLAB_ENGINE, cmd) == 0, "An error occurred while calling the initialize function\n")) { return false; }
|
||||
|
||||
m_helper->setMatlabEngine(MATLAB_ENGINE);
|
||||
m_helper->setBoxInstanceVariableName(m_boxInstanceVariableName);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmMatlabScripting::closeMatlabEngineSafely()
|
||||
{
|
||||
if (MATLAB_ENGINE == nullptr) { return true; }
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "Trying to close Matlab engine\n";
|
||||
#if defined TARGET_OS_Windows
|
||||
__try
|
||||
{
|
||||
#endif
|
||||
if (MATLAB_ENGINE) { if (engClose(MATLAB_ENGINE) != 0) { this->getLogManager() << Kernel::LogLevel_ImportantWarning << "Could not close Matlab engine.\n"; } }
|
||||
#if defined TARGET_OS_Windows
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "Closing MATLAB engine failed.\n"
|
||||
<< "\tTo use this box you must have MATLAB (32 bits version) installed on your computer.\n";
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmMatlabScripting::uninitialize()
|
||||
{
|
||||
delete m_helper;
|
||||
if (MATLAB_ENGINE != nullptr)
|
||||
{
|
||||
CString cmd = m_boxInstanceVariableName + " = " + m_uninitializeFunc + "(" + m_boxInstanceVariableName + ");";
|
||||
if (!checkFailureRoutine(engEvalString(MATLAB_ENGINE, cmd) == 0, "An error occurred while calling the uninitialize function\n")
|
||||
) { } // NOP, we still want to deallocate below
|
||||
// Remove the box from the matlab workspace
|
||||
cmd = "clear " + m_boxInstanceVariableName + ";";
|
||||
if (!checkFailureRoutine(engEvalString(MATLAB_ENGINE, cmd) == 0, "An error occurred while clearing the box\n")
|
||||
) { } // NOP, we still want to deallocate below
|
||||
}
|
||||
|
||||
closeMatlabEngineSafely();
|
||||
if (m_matlabBuffer)
|
||||
{
|
||||
delete[] m_matlabBuffer;
|
||||
m_matlabBuffer = nullptr;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < m_decoders.size(); ++i)
|
||||
{
|
||||
m_decoders[i]->uninitialize();
|
||||
delete m_decoders[i];
|
||||
}
|
||||
for (size_t i = 0; i < m_encoders.size(); ++i)
|
||||
{
|
||||
m_encoders[i]->uninitialize();
|
||||
delete m_encoders[i];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmMatlabScripting::processClock(Kernel::CMessageClock& /*msg*/)
|
||||
{
|
||||
if (!MATLAB_ENGINE) { return true; }
|
||||
const std::string cmd = std::string(m_boxInstanceVariableName) + ".clock = " + std::to_string(CTime(this->getPlayerContext().getCurrentTime()).toSeconds())
|
||||
+ ";";
|
||||
OV_ERROR_UNLESS_KRF(engEvalString(MATLAB_ENGINE, cmd.c_str()) == 0, "An error occurred while updating the box clock.", Kernel::ErrorType::BadProcessing);
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmMatlabScripting::process()
|
||||
{
|
||||
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
|
||||
// In openvibe, pointers to managers can change between the calls to process(), so we need to provide current ones every time
|
||||
m_helper->setManagers(&this->getLogManager(), &this->getErrorManager());
|
||||
|
||||
for (size_t i = 0; i < getStaticBoxContext().getInputCount(); ++i)
|
||||
{
|
||||
for (size_t j = 0; j < boxContext.getInputChunkCount(i); ++j)
|
||||
{
|
||||
m_decoders[i]->decode(j);
|
||||
|
||||
CIdentifier type;
|
||||
getStaticBoxContext().getInputType(i, type);
|
||||
bool unknownStream = true;
|
||||
bool receivedSomething = false;
|
||||
|
||||
if (m_decoders[i]->isHeaderReceived())
|
||||
{
|
||||
receivedSomething = true;
|
||||
// this->getLogManager() << Kernel::LogLevel_Debug << "Received header\n";
|
||||
|
||||
if (type == OV_TypeId_StreamedMatrix)
|
||||
{
|
||||
CMatrix* matrix = static_cast<Toolkit::TStreamedMatrixDecoder<CBoxAlgorithmMatlabScripting>*>(m_decoders[i])->getOutputMatrix();
|
||||
if (!checkFailureRoutine(m_helper->setStreamedMatrixInputHeader(i, matrix), "Error calling [OV_setStreamMatrixInputHeader]\n"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_nInputHeaderSent++;
|
||||
unknownStream = false;
|
||||
}
|
||||
|
||||
if (type == OV_TypeId_Signal)
|
||||
{
|
||||
CMatrix* matrix = static_cast<Toolkit::TSignalDecoder<CBoxAlgorithmMatlabScripting>*>(m_decoders[i])->getOutputMatrix();
|
||||
const uint64_t frequency = static_cast<Toolkit::TSignalDecoder<CBoxAlgorithmMatlabScripting>*>(m_decoders[i])->getOutputSamplingRate();
|
||||
if (!checkFailureRoutine(m_helper->setSignalInputHeader(i, matrix, frequency),
|
||||
"Error calling [OV_setSignalInputHeader]\n")) { return false; }
|
||||
|
||||
m_nInputHeaderSent++;
|
||||
unknownStream = false;
|
||||
}
|
||||
|
||||
if (type == OV_TypeId_FeatureVector)
|
||||
{
|
||||
CMatrix* matrix = static_cast<Toolkit::TFeatureVectorDecoder<CBoxAlgorithmMatlabScripting>*>(m_decoders[i])->getOutputMatrix();
|
||||
if (!checkFailureRoutine(m_helper->setFeatureVectorInputHeader(i, matrix),
|
||||
"Error calling [OV_setFeatureVectorInputHeader]\n")) { return false; }
|
||||
|
||||
m_nInputHeaderSent++;
|
||||
unknownStream = false;
|
||||
}
|
||||
|
||||
if (type == OV_TypeId_Spectrum)
|
||||
{
|
||||
CMatrix* matrix = static_cast<Toolkit::TSpectrumDecoder<CBoxAlgorithmMatlabScripting>*>(m_decoders[i])->getOutputMatrix();
|
||||
CMatrix* freqAbscissa = static_cast<Toolkit::TSpectrumDecoder<CBoxAlgorithmMatlabScripting>*>(m_decoders[i])->getOutputFrequencyAbscissa();
|
||||
const uint64_t frequency = static_cast<Toolkit::TSpectrumDecoder<CBoxAlgorithmMatlabScripting>*>(m_decoders[i])->getOutputSamplingRate();
|
||||
|
||||
if (!checkFailureRoutine(m_helper->setSpectrumInputHeader(i, matrix, freqAbscissa, frequency),
|
||||
"Error calling [OV_setSpectrumInputHeader]\n")) { return false; }
|
||||
|
||||
m_nInputHeaderSent++;
|
||||
unknownStream = false;
|
||||
}
|
||||
|
||||
if (type == OV_TypeId_ChannelLocalisation)
|
||||
{
|
||||
CMatrix* matrix = static_cast<Toolkit::TChannelLocalisationDecoder<CBoxAlgorithmMatlabScripting>*>(m_decoders[i])->getOutputMatrix();
|
||||
const bool dynamic = static_cast<Toolkit::TChannelLocalisationDecoder<CBoxAlgorithmMatlabScripting>*>(m_decoders[i])->getOutputDynamic();
|
||||
if (!checkFailureRoutine(m_helper->setChannelLocalisationInputHeader(i, matrix, dynamic),
|
||||
"Error calling [OV_setChannelLocalizationInputHeader]\n")) { return false; }
|
||||
|
||||
m_nInputHeaderSent++;
|
||||
unknownStream = false;
|
||||
}
|
||||
|
||||
if (type == OV_TypeId_ExperimentInfo)
|
||||
{
|
||||
OV_WARNING_K(
|
||||
"The Experiment Information Stream is not implemented with the Matlab Scripting Box. If this is relevant for your usage, please contact the official development Team.")
|
||||
;
|
||||
m_nInputHeaderSent++;
|
||||
unknownStream = false;
|
||||
}
|
||||
|
||||
if (type == OV_TypeId_Stimulations)
|
||||
{
|
||||
if (!checkFailureRoutine(m_helper->setStimulationsInputHeader(i), "Error calling [OV_setStimulationsInputHeader]\n")) { return false; }
|
||||
|
||||
m_nInputHeaderSent++;
|
||||
unknownStream = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_decoders[i]->isBufferReceived())
|
||||
{
|
||||
// this->getLogManager() << Kernel::LogLevel_Debug << "Received buffer\n";
|
||||
receivedSomething = true;
|
||||
//
|
||||
if (type == OV_TypeId_StreamedMatrix || this->getTypeManager().isDerivedFromStream(type, OV_TypeId_StreamedMatrix))
|
||||
{
|
||||
CMatrix* matrix = static_cast<Toolkit::TSignalDecoder<CBoxAlgorithmMatlabScripting>*>(m_decoders[i])->getOutputMatrix();
|
||||
const uint64_t start = boxContext.getInputChunkStartTime(i, j);
|
||||
const uint64_t end = boxContext.getInputChunkEndTime(i, j);
|
||||
if (!checkFailureRoutine(m_helper->addStreamedMatrixInputBuffer(i, matrix, start, end),
|
||||
"Error calling [OV_addInputBuffer (Streamed Matrix or child stream)]\n")) { return false; }
|
||||
unknownStream = false;
|
||||
}
|
||||
|
||||
if (type == OV_TypeId_Stimulations)
|
||||
{
|
||||
IStimulationSet* stimSet = static_cast<Toolkit::TStimulationDecoder<CBoxAlgorithmMatlabScripting>*>(m_decoders[i])->getOutputStimulationSet();
|
||||
const uint64_t start = boxContext.getInputChunkStartTime(i, j);
|
||||
const uint64_t end = boxContext.getInputChunkEndTime(i, j);
|
||||
if (stimSet->getStimulationCount() > 0)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "Inserting stimulation set with size " << stimSet->getStimulationCount() << "\n";
|
||||
}
|
||||
if (!checkFailureRoutine(m_helper->addStimulationsInputBuffer(i, stimSet, start, end),
|
||||
"Error calling [OV_addInputBuffer (Stimulations)]\n")) { return false; }
|
||||
unknownStream = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_decoders[i]->isEndReceived())
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Info << "Received end\n";
|
||||
receivedSomething = true;
|
||||
unknownStream = false;
|
||||
// @FIXME should something additional be done here?
|
||||
}
|
||||
|
||||
OV_ERROR_UNLESS_KRF(!receivedSomething || !unknownStream, "Unknown Stream Type " << type.str() << " on input [" << i << "].",
|
||||
Kernel::ErrorType::BadProcessing);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_nInputHeaderSent < getStaticBoxContext().getInputCount())
|
||||
{
|
||||
// not ready to process
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// CALL TO PROCESS FUNCTION
|
||||
std::string command = std::string(m_boxInstanceVariableName.toASCIIString()) + " = " + m_processFunc.toASCIIString() + "("
|
||||
+ m_boxInstanceVariableName.toASCIIString() + ");";
|
||||
if (!checkFailureRoutine(engEvalString(MATLAB_ENGINE, command.c_str()) == 0, "Error calling the Process function.\n")) { return false; }
|
||||
|
||||
// Go through every output in the matlab box and copy the data to the C++ side
|
||||
for (size_t i = 0; i < getStaticBoxContext().getOutputCount(); ++i)
|
||||
{
|
||||
// now we check for pending output chunk to be sent (output type independent call)
|
||||
command = std::string("OV_PENDING_COUNT_TMP = OV_getNbPendingOutputChunk(") + m_boxInstanceVariableName.toASCIIString() + ", "
|
||||
+ std::to_string(i + 1) + ");";
|
||||
if (!checkFailureRoutine(engEvalString(MATLAB_ENGINE, command.c_str()) == 0, "Error calling [OV_getNbPendingOutputChunk].\n")) { return false; }
|
||||
|
||||
mxArray* pending = engGetVariable(MATLAB_ENGINE, "OV_PENDING_COUNT_TMP");
|
||||
const double dPending = *mxGetPr(pending);
|
||||
|
||||
CIdentifier typeID;
|
||||
getStaticBoxContext().getOutputType(i, typeID);
|
||||
|
||||
for (size_t c = 0; c < size_t(dPending); ++c)
|
||||
{
|
||||
// If no header were ever sent, we need to extract header information in the matlab box
|
||||
// This header must have been set prior to sending the very first buffer.
|
||||
// @FIXME the practice used below of assigning to getters is nasty, it should be refactored to e.g. using getter/setter pairs
|
||||
if (!m_oHeaderStates[i])
|
||||
{
|
||||
bool unknownType = true;
|
||||
if (typeID == OV_TypeId_StreamedMatrix)
|
||||
{
|
||||
CMatrix* matrixToSend = static_cast<Toolkit::TStreamedMatrixEncoder<CBoxAlgorithmMatlabScripting>*>(m_encoders[i])->getInputMatrix();
|
||||
if (!checkFailureRoutine(m_helper->getStreamedMatrixOutputHeader(i, matrixToSend),
|
||||
"Error calling [OV_getStreamedMatrixOutputHeader]. Did you correctly set the output header in the matlab structure ?\n")
|
||||
) { return false; }
|
||||
|
||||
unknownType = false;
|
||||
}
|
||||
else if (typeID == OV_TypeId_Signal)
|
||||
{
|
||||
CMatrix* matrixToSend = static_cast<Toolkit::TSignalEncoder<CBoxAlgorithmMatlabScripting>*>(m_encoders[i])->getInputMatrix();
|
||||
uint64_t sampling = static_cast<Toolkit::TSignalEncoder<CBoxAlgorithmMatlabScripting>*>(m_encoders[i])->getInputSamplingRate();
|
||||
if (!checkFailureRoutine(m_helper->getSignalOutputHeader(i, matrixToSend, sampling),
|
||||
"Error calling [OV_getSignalOutputHeader]. Did you correctly set the output header in the matlab structure ?\n")
|
||||
) { return false; }
|
||||
|
||||
// Set the new sampling rate
|
||||
static_cast<Toolkit::TSignalEncoder<CBoxAlgorithmMatlabScripting>*>(m_encoders[i])->getInputSamplingRate() = sampling;
|
||||
|
||||
unknownType = false;
|
||||
}
|
||||
else if (typeID == OV_TypeId_FeatureVector)
|
||||
{
|
||||
CMatrix* matrixToSend = static_cast<Toolkit::TFeatureVectorEncoder<CBoxAlgorithmMatlabScripting>*>(m_encoders[i])->getInputMatrix();
|
||||
if (!checkFailureRoutine(m_helper->getFeatureVectorOutputHeader(i, matrixToSend),
|
||||
"Error calling [OV_getFeatureVectorOutputHeader]. Did you correctly set the output header in the matlab structure ?\n")
|
||||
) { return false; }
|
||||
|
||||
unknownType = false;
|
||||
}
|
||||
else if (typeID == OV_TypeId_Spectrum)
|
||||
{
|
||||
CMatrix* matrixToSend = static_cast<Toolkit::TSpectrumEncoder<CBoxAlgorithmMatlabScripting>*>(m_encoders[i])->getInputMatrix();
|
||||
CMatrix* freqAbscissa = static_cast<Toolkit::TSpectrumEncoder<CBoxAlgorithmMatlabScripting>*>(m_encoders[i])->getInputFrequencyAbscissa();
|
||||
uint64_t frequency = static_cast<Toolkit::TSpectrumEncoder<CBoxAlgorithmMatlabScripting>*>(m_encoders[i])->getInputSamplingRate();
|
||||
|
||||
if (!checkFailureRoutine(m_helper->getSpectrumOutputHeader(i, matrixToSend, freqAbscissa, frequency),
|
||||
"Error calling [OV_getSpectrumOutputHeader]. Did you correctly set the output header in the matlab structure ?\n")
|
||||
) { return false; }
|
||||
|
||||
unknownType = false;
|
||||
}
|
||||
else if (typeID == OV_TypeId_ChannelLocalisation)
|
||||
{
|
||||
CMatrix* matrixToSend = static_cast<Toolkit::TChannelLocalisationEncoder<CBoxAlgorithmMatlabScripting>*>(m_encoders[i])->getInputMatrix();
|
||||
bool dynamic = static_cast<Toolkit::TChannelLocalisationEncoder<CBoxAlgorithmMatlabScripting>*>(m_encoders[i])->getInputDynamic();
|
||||
if (!checkFailureRoutine(m_helper->getChannelLocalisationOutputHeader(i, matrixToSend, dynamic),
|
||||
"Error calling [OV_getChannelLocalizationOutputHeader]. Did you correctly set the output header in the matlab structure ?\n")
|
||||
) { return false; }
|
||||
|
||||
// Set the new channel localisation
|
||||
static_cast<Toolkit::TChannelLocalisationEncoder<CBoxAlgorithmMatlabScripting>*>(m_encoders[i])->getInputDynamic() = dynamic;
|
||||
|
||||
unknownType = false;
|
||||
}
|
||||
else if (typeID == OV_TypeId_ExperimentInfo)
|
||||
{
|
||||
OV_WARNING_K(
|
||||
"The Experiment Information Stream is not implemented with the Matlab Scripting Box. If this is relevant for your usage, please contact the official development Team.")
|
||||
;
|
||||
unknownType = false;
|
||||
}
|
||||
else if (typeID == OV_TypeId_Stimulations)
|
||||
{
|
||||
IStimulationSet* stimSet = static_cast<Toolkit::TStimulationEncoder<CBoxAlgorithmMatlabScripting>*>(m_encoders[i])->getInputStimulationSet();
|
||||
if (!checkFailureRoutine(m_helper->getStimulationsOutputHeader(i, stimSet),
|
||||
"Error calling [OV_getStimulationsOutputHeader]. Did you correctly set the output header in the matlab structure ?\n")
|
||||
) { return false; }
|
||||
|
||||
unknownType = false;
|
||||
}
|
||||
|
||||
OV_ERROR_UNLESS_KRF(!unknownType, "Unknown Stream Type on output [" << i << "].", Kernel::ErrorType::BadProcessing);
|
||||
|
||||
m_encoders[i]->encodeHeader();
|
||||
boxContext.markOutputAsReadyToSend(i, 0, 0);
|
||||
|
||||
m_oHeaderStates[i] = true;
|
||||
}
|
||||
|
||||
|
||||
bool unknownType = true;
|
||||
uint64_t start = 0;
|
||||
uint64_t end = 0;
|
||||
|
||||
if (typeID == OV_TypeId_StreamedMatrix || this->getTypeManager().isDerivedFromStream(typeID, OV_TypeId_StreamedMatrix))
|
||||
{
|
||||
CMatrix* matrixToSend = static_cast<Toolkit::TStreamedMatrixEncoder<CBoxAlgorithmMatlabScripting>*>(m_encoders[i])->getInputMatrix();
|
||||
if (!checkFailureRoutine(m_helper->popStreamedMatrixOutputBuffer(i, matrixToSend, start, end),
|
||||
"Error calling [OV_popOutputBufferReshape] for Streamed Matrix stream or child stream.\n")) { return false; }
|
||||
|
||||
unknownType = false;
|
||||
}
|
||||
|
||||
if (typeID == OV_TypeId_Stimulations)
|
||||
{
|
||||
IStimulationSet* stimSet = static_cast<Toolkit::TStimulationEncoder<CBoxAlgorithmMatlabScripting>*>(m_encoders[i])->getInputStimulationSet();
|
||||
stimSet->clear();
|
||||
if (!checkFailureRoutine(m_helper->popStimulationsOutputBuffer(i, stimSet, start, end),
|
||||
"Error calling [OV_popOutputBuffer] for Stimulation stream.\n")) { return false; }
|
||||
unknownType = false;
|
||||
}
|
||||
|
||||
OV_ERROR_UNLESS_KRF(!unknownType, "Unknown Stream Type on output [" << i << "].", Kernel::ErrorType::BadProcessing);
|
||||
|
||||
m_encoders[i]->encodeBuffer();
|
||||
boxContext.markOutputAsReadyToSend(i, start, end);
|
||||
}
|
||||
mxDestroyArray(pending);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmMatlabScripting::processInput(const size_t /*index*/)
|
||||
{
|
||||
OV_ERROR_UNLESS_KRF(getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess(),
|
||||
"Error while marking algorithm as ready to process", Kernel::ErrorType::Internal);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmMatlabScripting::printOutputBufferWithFormat()
|
||||
{
|
||||
// the buffer for the console
|
||||
|
||||
// @FIXME allow seeing more of the error message!
|
||||
|
||||
std::stringstream ss;
|
||||
ss << m_matlabBuffer;
|
||||
if (!ss.str().empty())
|
||||
{
|
||||
const size_t errIdx1 = ss.str().find("??? ");
|
||||
const size_t errIdx2 = ss.str().find("Error: ");
|
||||
const size_t errIdx3 = ss.str().find("Error ");
|
||||
|
||||
// Find the earliest error message
|
||||
size_t errIdx = std::string::npos;
|
||||
if (errIdx == std::string::npos || (errIdx1 != std::string::npos && errIdx1 < errIdx)) { errIdx = errIdx1; }
|
||||
if (errIdx == std::string::npos || (errIdx2 != std::string::npos && errIdx2 < errIdx)) { errIdx = errIdx2; }
|
||||
if (errIdx == std::string::npos || (errIdx3 != std::string::npos && errIdx3 < errIdx)) { errIdx = errIdx3; }
|
||||
|
||||
size_t warnIdx = ss.str().find("Warning: ");
|
||||
if (errIdx == std::string::npos && warnIdx == std::string::npos)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Info << "\n---- MATLAB BUFFER - INFO ----\n" << ss.str().substr(0, (warnIdx < errIdx) ? warnIdx : errIdx) << "\n";
|
||||
}
|
||||
if (warnIdx != std::string::npos)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Warning << "\n---- MATLAB BUFFER - WARNING ----\n" << ss.str().substr(warnIdx, errIdx) << "\n";
|
||||
}
|
||||
if (errIdx != std::string::npos)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "\n---- MATLAB BUFFER - ERROR ! ----\n" << ss.str().substr(errIdx) << "\n";
|
||||
m_errorDetected = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Matlab
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
#endif // TARGET_HAS_ThirdPartyMatlab
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
#pragma once
|
||||
|
||||
#if defined TARGET_HAS_ThirdPartyMatlab
|
||||
|
||||
#include "../ovp_defines.h"
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
#include "../ovpCMatlabHelper.h"
|
||||
#include <map>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Matlab {
|
||||
class CBoxAlgorithmMatlabScripting final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
|
||||
{
|
||||
public:
|
||||
void release() override { delete this; }
|
||||
uint64_t getClockFrequency() override { return m_clockFrequency << 32; }
|
||||
bool initialize() override;
|
||||
bool uninitialize() override;
|
||||
bool processClock(Kernel::CMessageClock& msg) override;
|
||||
bool process() override;
|
||||
bool processInput(const size_t index) override;
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_MatlabScripting)
|
||||
|
||||
private:
|
||||
bool openMatlabEngineSafely();
|
||||
bool closeMatlabEngineSafely();
|
||||
|
||||
uint64_t m_clockFrequency = 0;
|
||||
|
||||
std::map<size_t, Toolkit::TDecoder<CBoxAlgorithmMatlabScripting>*> m_decoders;
|
||||
size_t m_nInputHeaderSent = 0;
|
||||
|
||||
std::map<size_t, Toolkit::TEncoder<CBoxAlgorithmMatlabScripting>*> m_encoders;
|
||||
std::map<size_t, bool> m_oHeaderStates;
|
||||
|
||||
void* m_engineHandle = nullptr;
|
||||
CString m_boxInstanceVariableName; //must be unique
|
||||
|
||||
|
||||
CMatlabHelper* m_helper = nullptr;
|
||||
|
||||
CString m_matlabPath; // On Linux, path of the executable. On Windows, the executable directory.
|
||||
CString m_processFunc;
|
||||
CString m_initializeFunc;
|
||||
CString m_uninitializeFunc;
|
||||
|
||||
char* m_matlabBuffer = nullptr;
|
||||
bool m_errorDetected = false;
|
||||
bool printOutputBufferWithFormat();
|
||||
bool checkFailureRoutine(bool result, const CString& msg);
|
||||
static void sanitizePath(CString& pathToModify);
|
||||
|
||||
//void sendOutputHeader(CIdentifier idOutputType);
|
||||
//void sendOutputBuffer(CIdentifier idOutputType);
|
||||
};
|
||||
|
||||
class CBoxAlgorithmMatlabScriptingListener final : public Toolkit::TBoxListener<IBoxListener>
|
||||
{
|
||||
public:
|
||||
bool onSettingTypeChanged(Kernel::IBox& box, const size_t index) override
|
||||
{
|
||||
//we must have the first STATIC_SETTINGS_COUNT settings
|
||||
if (index < 6)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Warning << "One of the predefined setting has changed type, falling back to default.\n";
|
||||
box.setSettingType(index, OV_TypeId_String); // they are all strings
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onSettingValueChanged(Kernel::IBox& box, const size_t index) override
|
||||
{
|
||||
//we must have the first STATIC_SETTINGS_COUNT settings
|
||||
|
||||
CString str;
|
||||
box.getSettingValue(0, str);
|
||||
const uint64_t value = atoi(str.toASCIIString());
|
||||
if (index == 0 && (value < 1 || value > 128))
|
||||
{
|
||||
OV_WARNING_K("Clock Frequency must be an integer between 1 and 128 Hz. Falling back to default.");
|
||||
box.setSettingValue(index, "64");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxListener<IBoxListener>, CIdentifier::undefined())
|
||||
};
|
||||
|
||||
class CBoxAlgorithmMatlabScriptingDesc final : virtual public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
void release() override { }
|
||||
CString getName() const override { return CString("Matlab Scripting"); }
|
||||
CString getAuthorName() const override { return CString("L. Bonnet"); }
|
||||
CString getAuthorCompanyName() const override { return CString("INRIA"); }
|
||||
|
||||
CString getShortDescription() const override { return CString("Executes matlab scripts. To be used correctly, you must have Matlab installed."); }
|
||||
|
||||
CString getDetailedDescription() const override
|
||||
{
|
||||
return CString(
|
||||
"User must implement the matlab functions:\n[box_out]=bci_Initialize(box_in)\n[box_out]=bci_Process(box_in)\n[box_out]=bci_Uninitialize(box_in)\nPlease refer to the dedicated documentation <openvibe.inria.fr/tutorial-using-matlab-with-openvibe> for more information.");
|
||||
}
|
||||
|
||||
CString getCategory() const override { return CString("Scripting"); }
|
||||
CString getVersion() const override { return CString("1.0"); }
|
||||
CString getStockItemName() const override { return CString("gtk-execute"); }
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_MatlabScripting; }
|
||||
IPluginObject* create() override { return new CBoxAlgorithmMatlabScripting; }
|
||||
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
prototype.addSetting("Box clock frequency in Hz", OV_TypeId_Integer, "64");
|
||||
|
||||
#if defined TARGET_OS_Linux
|
||||
prototype.addSetting("Matlab executable (path)", OV_TypeId_Filename, "[ssh user@host] /path/to/matlab");
|
||||
#elif defined TARGET_OS_Windows
|
||||
// On Windows, the executable is not actually used, but its path is parsed from it and added to PATH.
|
||||
// Background: Matlab's engOpen() takes a different argument on Windows and on Linux. On Windows, we need to have Matlab
|
||||
// on PATH, in Linux we need to provide a full path of the executable. However, we'd like our example scenarios to give
|
||||
// correct instructions to the user on both platforms, hence we use a setting that contains the information for both use-cases.
|
||||
prototype.addSetting("Matlab executable (path)", OV_TypeId_Filename, "C:/Program Files (x86)/MATLAB/R2013b/bin/win32/matlab.exe");
|
||||
#else
|
||||
#endif
|
||||
prototype.addSetting("Matlab working directory", OV_TypeId_String, "${Player_ScenarioDirectory}");
|
||||
prototype.addSetting("Initialize function", OV_TypeId_String, "matlab_Initialize");
|
||||
prototype.addSetting("Process function", OV_TypeId_String, "matlab_Process");
|
||||
prototype.addSetting("Uninitialize function", OV_TypeId_String, "matlab_Uninitialize");
|
||||
|
||||
prototype.addFlag(Kernel::BoxFlag_CanAddInput);
|
||||
prototype.addFlag(Kernel::BoxFlag_CanModifyInput);
|
||||
prototype.addFlag(Kernel::BoxFlag_CanAddOutput);
|
||||
prototype.addFlag(Kernel::BoxFlag_CanModifyOutput);
|
||||
prototype.addFlag(Kernel::BoxFlag_CanAddSetting);
|
||||
prototype.addFlag(Kernel::BoxFlag_CanModifySetting);
|
||||
|
||||
//prototype.addFlag(OV_AttributeId_Box_FlagIsUnstable);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
IBoxListener* createBoxListener() const override { return new CBoxAlgorithmMatlabScriptingListener; }
|
||||
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_MatlabScriptingDesc)
|
||||
};
|
||||
} // namespace Matlab
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
|
||||
#endif // TARGET_HAS_ThirdPartyMatlab
|
||||
+493
@@ -0,0 +1,493 @@
|
||||
#if defined TARGET_HAS_ThirdPartyMatlab
|
||||
|
||||
#include "ovpCMatlabHelper.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <mex.h>
|
||||
//#include <engine.h>
|
||||
#include <string>
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Matlab {
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
static std::string escapeMatlabString(const char* sStringToEscape)
|
||||
{
|
||||
std::string str = std::string(sStringToEscape);
|
||||
auto it = str.begin();
|
||||
while (it != str.end())
|
||||
{
|
||||
if (*it == '\'')
|
||||
{
|
||||
str.insert(it, '\'');
|
||||
++it;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
static std::string genLabelsList(CMatrix* matrix, const size_t axis = 0)
|
||||
{
|
||||
std::string labelsList;
|
||||
for (size_t i = 0; i < matrix->getDimensionSize(axis); ++i)
|
||||
{
|
||||
labelsList += std::string("'") + escapeMatlabString(matrix->getDimensionLabel(axis, i)) + "' ";
|
||||
}
|
||||
return labelsList;
|
||||
}
|
||||
|
||||
|
||||
static uint64_t convertFromMArray(mxArray* array, const size_t index)
|
||||
{
|
||||
const double* ptr = ::mxGetPr(array);
|
||||
const double timeValue = double(ptr[index]);
|
||||
return CTime(timeValue).time();
|
||||
}
|
||||
|
||||
static uint64_t castFromMArray(mxArray* array, const size_t index)
|
||||
{
|
||||
const double* ptr = ::mxGetPr(array);
|
||||
const double value = double(ptr[index]);
|
||||
return uint64_t(value);
|
||||
}
|
||||
|
||||
static CString getNameFromCell(mxArray* names, const size_t index)
|
||||
{
|
||||
mxArray* cell = mxGetCell(names, index);
|
||||
if (!cell) { return CString(""); }
|
||||
const mwSize* cellSizes = mxGetDimensions(cell);
|
||||
char* name = new char[cellSizes[1] + 1];
|
||||
name[cellSizes[1]] = '\0';
|
||||
for (size_t cellsize = 0; cellsize < size_t(cellSizes[1]); ++cellsize) { name[cellsize] = static_cast<char*>(mxGetData(cell))[cellsize * 2]; }
|
||||
CString res = name;
|
||||
delete name;
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<CString> CMatlabHelper::getNamelist(const char* name) const
|
||||
{
|
||||
std::vector<CString> res;
|
||||
|
||||
mxArray* marray = engGetVariable(m_matlabEngine, name);
|
||||
if (!marray)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "Nonexisting variable [" << name << "]\n";
|
||||
return res;
|
||||
}
|
||||
|
||||
const mwSize nbCells = mxGetNumberOfElements(marray);
|
||||
for (size_t cell = 0; cell < nbCells; ++cell) { res.push_back(getNameFromCell(marray, cell)); }
|
||||
|
||||
mxDestroyArray(marray);
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t CMatlabHelper::getUi32FromEnv(const char* name) const
|
||||
{
|
||||
mxArray* marray = engGetVariable(m_matlabEngine, name);
|
||||
if (!marray)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "Nonexisting variable [" << name << "]\n";
|
||||
return 0;
|
||||
}
|
||||
const uint32_t res = uint32_t(*mxGetPr(marray));
|
||||
mxDestroyArray(marray);
|
||||
return res;
|
||||
}
|
||||
|
||||
uint64_t CMatlabHelper::getUi64FromEnv(const char* name) const
|
||||
{
|
||||
mxArray* marray = engGetVariable(m_matlabEngine, name);
|
||||
if (!marray)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "Nonexisting variable [" << name << "]\n";
|
||||
return 0;
|
||||
}
|
||||
const uint64_t res = uint64_t(*mxGetPr(marray));
|
||||
mxDestroyArray(marray);
|
||||
return res;
|
||||
}
|
||||
|
||||
uint64_t CMatlabHelper::genUi64FromEnvConverted(const char* name) const
|
||||
{
|
||||
mxArray* marray = engGetVariable(m_matlabEngine, name);
|
||||
if (!marray)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "Nonexisting variable [" << name << "]\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
const double value = double(*mxGetPr(marray));
|
||||
const uint64_t res = CTime(value).time();
|
||||
mxDestroyArray(marray);
|
||||
return res;
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
bool CMatlabHelper::setStreamedMatrixInputHeader(const size_t index, CMatrix* matrix) const
|
||||
{
|
||||
std::string labelList;
|
||||
std::string dimensionSizes;
|
||||
for (size_t dim = 0; dim < matrix->getDimensionCount(); ++dim)
|
||||
{
|
||||
dimensionSizes += std::to_string(matrix->getDimensionSize(dim)) + " ";
|
||||
labelList += std::string("{") + genLabelsList(matrix, dim) + "} ";
|
||||
}
|
||||
//function box_out = OV_setStreamedMatrixInputInputHeader(box_in, input_index, dimension_count, dimension_sizes, dimension_labels)
|
||||
|
||||
const std::string cmd = std::string(m_boxInstanceVariableName) + " = OV_setStreamedMatrixInputHeader(" + m_boxInstanceVariableName.toASCIIString() + ","
|
||||
+ std::to_string(index + 1) + "," + std::to_string(matrix->getDimensionCount()) + "," + "[" + dimensionSizes + "],"
|
||||
+ "{" + labelList + "});";
|
||||
|
||||
return engEvalString(m_matlabEngine, cmd.c_str()) == 0;
|
||||
}
|
||||
|
||||
bool CMatlabHelper::setFeatureVectorInputHeader(const size_t index, CMatrix* matrix) const
|
||||
{
|
||||
const std::string labelList = genLabelsList(matrix, 0);
|
||||
|
||||
//function box_out = OV_setStreamedMatrixInputInputHeader(box_in, input_index, dimension_count, dimension_sizes, dimension_labels)
|
||||
|
||||
//box_out = OV_setFeatureVectorInputHeader(box_in, input_index, nb_features, labels)
|
||||
const std::string cmd = std::string(m_boxInstanceVariableName.toASCIIString()) + " = OV_setFeatureVectorInputHeader("
|
||||
+ m_boxInstanceVariableName.toASCIIString() + "," + std::to_string(index + 1) + ","
|
||||
+ std::to_string(matrix->getDimensionSize(0)) + "," + "{" + labelList + "});";
|
||||
|
||||
return engEvalString(m_matlabEngine, cmd.c_str()) == 0;
|
||||
}
|
||||
|
||||
bool CMatlabHelper::setSignalInputHeader(const size_t index, CMatrix* matrix, const uint64_t frequency) const
|
||||
{
|
||||
const std::string labelList = genLabelsList(matrix, 0);
|
||||
//function box_out = ov_set_signal_input_header(box_in, input_index, nb_channel, nb_samples_per_buffer, channel_names, sampling_rate)
|
||||
|
||||
const std::string cmd = std::string(m_boxInstanceVariableName) + " = OV_setSignalInputHeader(" + m_boxInstanceVariableName.toASCIIString() + ","
|
||||
+ std::to_string(index + 1) + "," + std::to_string(matrix->getDimensionSize(0)) + ","
|
||||
+ std::to_string(matrix->getDimensionSize(1)) + "," + "{" + labelList + "}," + std::to_string(frequency) + ");";
|
||||
|
||||
return engEvalString(m_matlabEngine, cmd.c_str()) == 0;
|
||||
}
|
||||
|
||||
bool CMatlabHelper::setChannelLocalisationInputHeader(const size_t index, CMatrix* matrix, const bool dynamic) const
|
||||
{
|
||||
const std::string labelList = genLabelsList(matrix, 0);
|
||||
//function box_out = OV_setChannelLocalisationInputHeader(box_in, input_index, nb_channels, channel_names, dynamic)
|
||||
|
||||
const std::string cmd = std::string(m_boxInstanceVariableName) + " = OV_setChannelLocalisationInputHeader(" + m_boxInstanceVariableName.toASCIIString()
|
||||
+ "," + std::to_string(index + 1) + "," + std::to_string(matrix->getDimensionSize(0)) + "," + "{" + labelList + "},"
|
||||
+ (dynamic ? "true" : "false") + ");";
|
||||
|
||||
return engEvalString(m_matlabEngine, cmd.c_str()) == 0;
|
||||
}
|
||||
|
||||
bool CMatlabHelper::setSpectrumInputHeader(const size_t index, CMatrix* matrix, CMatrix* frequencyAbscissa, const uint64_t frequency) const
|
||||
{
|
||||
const std::string labelList = genLabelsList(matrix, 0);
|
||||
const std::string abscissaList = genLabelsList(matrix, 1);
|
||||
|
||||
// @FIXME CERT this is now one dim array
|
||||
mxArray* matlabMatrix = ::mxCreateDoubleMatrix(frequencyAbscissa->getDimensionSize(0), 1, mxREAL);
|
||||
|
||||
memcpy(mxGetPr(matlabMatrix), frequencyAbscissa->getBuffer(), frequencyAbscissa->getBufferElementCount() * sizeof(double));
|
||||
engPutVariable(m_matlabEngine, "OV_MATRIX_TMP", matlabMatrix);
|
||||
|
||||
mxDestroyArray(matlabMatrix);
|
||||
|
||||
//box_out = OV_setSpectrumInputHeader(box_in, input_index, nb_channels, channel_names, nb_bands, band_names, bands, sampling_rate)
|
||||
const std::string cmd = std::string(m_boxInstanceVariableName.toASCIIString()) + " = OV_setSpectrumInputHeader("
|
||||
+ std::string(m_boxInstanceVariableName.toASCIIString()) + ","
|
||||
+ std::to_string(index + 1) + "," // input_index
|
||||
+ std::to_string(matrix->getDimensionSize(0)) + "," // nb_channels
|
||||
+ "{" + labelList + "}," // channel_names
|
||||
+ std::to_string(matrix->getDimensionSize(1)) + "," // nb_freq abscissa
|
||||
+ "{" + abscissaList + "}," //freq abscissa names
|
||||
+ "OV_MATRIX_TMP," //bands
|
||||
+ std::to_string(frequency) + ");"; //sampling rate
|
||||
|
||||
return engEvalString(m_matlabEngine, cmd.c_str()) == 0;
|
||||
}
|
||||
|
||||
bool CMatlabHelper::setStimulationsInputHeader(const size_t index) const
|
||||
{
|
||||
//box_out = OV_setStimulationInputHeader(box_in, input_index)
|
||||
const std::string cmd = std::string(m_boxInstanceVariableName) + " = OV_setStimulationsInputHeader(" + m_boxInstanceVariableName.toASCIIString() + "," +
|
||||
std::to_string(index + 1) + ");";
|
||||
|
||||
return engEvalString(m_matlabEngine, cmd.c_str()) == 0;
|
||||
}
|
||||
|
||||
//bool setExperimentInfoInputHeader(CMatrix * pMatrix);
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
bool CMatlabHelper::addStreamedMatrixInputBuffer(const size_t index, CMatrix* matrix, const uint64_t startTime, const uint64_t endTime) const
|
||||
{
|
||||
mwSize* dims = new mwSize[matrix->getDimensionCount()];
|
||||
size_t j = matrix->getDimensionCount() - 1;
|
||||
for (size_t i = 0; i < matrix->getDimensionCount(); ++i)
|
||||
{
|
||||
dims[i] = matrix->getDimensionSize(j);
|
||||
j--;
|
||||
}
|
||||
|
||||
mxArray* matlabMatrix = ::mxCreateNumericArray(matrix->getDimensionCount(), dims, mxDOUBLE_CLASS, mxREAL);
|
||||
|
||||
//test : channel 1 samples to '10'
|
||||
//for (size_t i = 0; i < 32;i++) matrix->getBuffer()[i] = 10;
|
||||
|
||||
memcpy(mxGetPr(matlabMatrix), matrix->getBuffer(), matrix->getBufferElementCount() * sizeof(double));
|
||||
engPutVariable(m_matlabEngine, "OV_MATRIX_TMP", matlabMatrix);
|
||||
|
||||
mxDestroyArray(matlabMatrix);
|
||||
|
||||
const std::string cmd = std::string(m_boxInstanceVariableName) + " = OV_addInputBuffer(" + m_boxInstanceVariableName.toASCIIString() + ","
|
||||
+ std::to_string(index + 1) + ","
|
||||
+ std::to_string(CTime(startTime).toSeconds()) + ","
|
||||
+ std::to_string(CTime(endTime).toSeconds()) + ",OV_MATRIX_TMP');";
|
||||
// please note the transpose operator ' to put the matrix with 1 channel per line
|
||||
|
||||
delete[] dims;
|
||||
|
||||
return engEvalString(m_matlabEngine, cmd.c_str()) == 0;
|
||||
}
|
||||
|
||||
bool CMatlabHelper::addStimulationsInputBuffer(const size_t index, IStimulationSet* stimSet, const uint64_t startTime, const uint64_t endTime) const
|
||||
{
|
||||
if (stimSet->getStimulationCount() == 0 && engEvalString(m_matlabEngine, "OV_MATRIX_TMP = 0") != 0) { return false; }
|
||||
// we create a 3xN matrix for N stims (access is easier in that order)
|
||||
mxArray* matrix = ::mxCreateDoubleMatrix(3, size_t(stimSet->getStimulationCount()), mxREAL);
|
||||
|
||||
for (size_t i = 0; i < stimSet->getStimulationCount(); ++i)
|
||||
{
|
||||
::mxGetPr(matrix)[i * 3] = double(stimSet->getStimulationIdentifier(i));
|
||||
::mxGetPr(matrix)[i * 3 + 1] = CTime(stimSet->getStimulationDate(i)).toSeconds();
|
||||
::mxGetPr(matrix)[i * 3 + 2] = CTime(stimSet->getStimulationDuration(i)).toSeconds();
|
||||
}
|
||||
|
||||
engPutVariable(m_matlabEngine, "OV_MATRIX_TMP", matrix);
|
||||
|
||||
mxDestroyArray(matrix);
|
||||
|
||||
const std::string cmd = std::string(m_boxInstanceVariableName) + " = OV_addInputBuffer(" + m_boxInstanceVariableName.toASCIIString() + ","
|
||||
+ std::to_string(index + 1) + ","
|
||||
+ std::to_string(CTime(startTime).toSeconds()) + ","
|
||||
+ std::to_string(CTime(endTime).toSeconds()) + ",OV_MATRIX_TMP');";
|
||||
|
||||
return (engEvalString(m_matlabEngine, cmd.c_str()) == 0);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
bool CMatlabHelper::getStreamedMatrixOutputHeader(const size_t index, CMatrix* matrix) const
|
||||
{
|
||||
const std::string cmd = std::string("[OV_ERRNO, OV_NB_DIMENSIONS, OV_DIMENSION_SIZES, OV_DIMENSION_LABELS] = OV_getStreamedMatrixOutputHeader(")
|
||||
+ m_boxInstanceVariableName.toASCIIString() + "," + std::to_string(index + 1) + ");";
|
||||
OV_ERROR_UNLESS_KRF(engEvalString(m_matlabEngine, cmd.c_str()) == 0 && getUi32FromEnv("OV_ERRNO") == 0,
|
||||
"Could not get Streamed matrix output header", Kernel::ErrorType::BadProcessing);
|
||||
|
||||
const size_t nDimension = getUi32FromEnv("OV_NB_DIMENSIONS");
|
||||
mxArray* dimensionSizes = engGetVariable(m_matlabEngine, "OV_DIMENSION_SIZES");
|
||||
if (!dimensionSizes)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "Nonexisting variable [OV_DIMENSION_SIZES]\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<CString> nameList = getNamelist("OV_DIMENSION_LABELS");
|
||||
|
||||
matrix->setDimensionCount(nDimension);
|
||||
size_t idx = 0;
|
||||
for (size_t i = 0; i < nDimension; ++i)
|
||||
{
|
||||
matrix->setDimensionSize(i, size_t(mxGetPr(dimensionSizes)[i]));
|
||||
for (size_t x = 0; x < matrix->getDimensionSize(i) && idx < nameList.size(); ++x)
|
||||
{
|
||||
matrix->setDimensionLabel(i, x, escapeMatlabString(nameList[idx].toASCIIString()).c_str());
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
mxDestroyArray(dimensionSizes);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMatlabHelper::getFeatureVectorOutputHeader(const size_t index, CMatrix* matrix) const
|
||||
{
|
||||
const std::string cmd = std::string("[OV_ERRNO, OV_NB_FEATURES, OV_LABELS] = OV_getFeatureVectorOutputHeader(")
|
||||
+ m_boxInstanceVariableName.toASCIIString() + "," + std::to_string(index + 1) + ");";
|
||||
OV_ERROR_UNLESS_KRF(engEvalString(m_matlabEngine, cmd.c_str()) == 0 && getUi32FromEnv("OV_ERRNO") == 0,
|
||||
"Could not get Feature Vector output header",
|
||||
Kernel::ErrorType::BadProcessing);
|
||||
|
||||
const size_t nbFeatures = getUi32FromEnv("OV_NB_FEATURES");
|
||||
std::vector<CString> nameList = getNamelist("OV_LABELS");
|
||||
// Check nb features == nb names ?
|
||||
|
||||
matrix->resize(nbFeatures);
|
||||
for (size_t x = 0; x < nbFeatures; ++x) { matrix->setDimensionLabel(0, x, escapeMatlabString(nameList[x].toASCIIString()).c_str()); }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMatlabHelper::getSignalOutputHeader(const size_t index, CMatrix* matrix, uint64_t& frequency) const
|
||||
{
|
||||
const std::string cmd = std::string("[OV_ERRNO, OV_NB_CHANNELS, OV_NB_SAMPLES_PER_BUFFER, OV_CHANNEL_NAMES, OV_SAMPLING_RATE] = OV_getSignalOutputHeader(")
|
||||
+ m_boxInstanceVariableName.toASCIIString() + "," + std::to_string(index + 1) + ");";
|
||||
OV_ERROR_UNLESS_KRF(engEvalString(m_matlabEngine, cmd.c_str()) == 0 && getUi32FromEnv("OV_ERRNO") == 0, "Could not get Signal output header",
|
||||
Kernel::ErrorType::BadProcessing);
|
||||
|
||||
const size_t nbChannels = getUi32FromEnv("OV_NB_CHANNELS");
|
||||
const size_t nbSamples = getUi32FromEnv("OV_NB_SAMPLES_PER_BUFFER");
|
||||
std::vector<CString> nameList = getNamelist("OV_CHANNEL_NAMES");
|
||||
const size_t rate = getUi32FromEnv("OV_SAMPLING_RATE");
|
||||
|
||||
if (nameList.size() != nbChannels) { return false; }
|
||||
|
||||
matrix->resize(nbChannels, nbSamples);
|
||||
frequency = rate;
|
||||
|
||||
for (size_t x = 0; x < nbChannels; ++x) { matrix->setDimensionLabel(0, x, escapeMatlabString(nameList[x].toASCIIString()).c_str()); }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMatlabHelper::getChannelLocalisationOutputHeader(const size_t index, CMatrix* matrix, bool& /*dynamic*/) const
|
||||
{
|
||||
const std::string cmd = std::string("[OV_ERRNO, OV_NB_CHANNELS, OV_CHANNEL_NAMES, OV_DYNAMIC] = OV_getChannelLocalisationOutputHeader(")
|
||||
+ m_boxInstanceVariableName.toASCIIString() + "," + std::to_string(index + 1) + ");";
|
||||
OV_ERROR_UNLESS_KRF(engEvalString(m_matlabEngine, cmd.c_str()) == 0 && getUi32FromEnv("OV_ERRNO") == 0,
|
||||
"Could not get Channel Localisation output header", Kernel::ErrorType::BadProcessing);
|
||||
|
||||
const size_t nChannel = getUi32FromEnv("OV_NB_CHANNELS");
|
||||
std::vector<CString> nameList = getNamelist("OV_CHANNEL_NAMES");
|
||||
mxArray* dynamic = engGetVariable(m_matlabEngine, "OV_DYNAMIC");
|
||||
if (!dynamic)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "Nonexisting variable [OV_DYNAMIC]\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nameList.size() != nChannel) { return false; }
|
||||
|
||||
matrix->resize(nChannel, 3);
|
||||
|
||||
for (size_t x = 0; x < nChannel; ++x) { matrix->setDimensionLabel(0, x, escapeMatlabString(nameList[x].toASCIIString()).c_str()); }
|
||||
|
||||
mxDestroyArray(dynamic);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMatlabHelper::getSpectrumOutputHeader(const size_t index, CMatrix* matrix, CMatrix* frequencyAbscissa, uint64_t& frequency) const
|
||||
{
|
||||
const std::string command = std::string(
|
||||
"[OV_ERRNO, OV_NB_CHANNELS, OV_CHANNEL_NAMES, OV_NB_BANDS, OV_BANDS_NAME, OV_BANDS_LINEAR, OV_SAMPLING_RATE] = OV_getSpectrumOutputHeader(")
|
||||
+ m_boxInstanceVariableName.toASCIIString() + "," + std::to_string(index + 1) + ");";
|
||||
OV_ERROR_UNLESS_KRF(engEvalString(m_matlabEngine, command.c_str()) == 0 && getUi32FromEnv("OV_ERRNO") == 0,
|
||||
"Could not get Spectrum output header", Kernel::ErrorType::BadProcessing);
|
||||
|
||||
const size_t nChannel = getUi32FromEnv("OV_NB_CHANNELS");
|
||||
std::vector<CString> nameList = getNamelist("OV_CHANNEL_NAMES");
|
||||
const size_t nAbscissa = getUi32FromEnv("OV_NB_ABSCISSAS");
|
||||
std::vector<CString> freqAbscissaNames = getNamelist("OV_ABSCISSAS_NAME");
|
||||
mxArray* freqAbscissa = engGetVariable(m_matlabEngine, "OV_ABSCISSAS_LINEAR");
|
||||
if (!freqAbscissa)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "Nonexisting variable [OV_ABSCISSAS_LINEAR]\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
frequency = getUi64FromEnv("OV_SAMPLING_RATE");
|
||||
|
||||
//The Frequency abscissa list has dimensions nb_bands
|
||||
frequencyAbscissa->resize(nAbscissa);
|
||||
for (size_t x = 0; x < nAbscissa; ++x) { frequencyAbscissa->setDimensionLabel(0, x, escapeMatlabString(freqAbscissaNames[x].toASCIIString()).c_str()); }
|
||||
|
||||
// Adding the bands:
|
||||
memcpy(frequencyAbscissa->getBuffer(), ::mxGetPr(freqAbscissa), nAbscissa * sizeof(double));
|
||||
|
||||
matrix->resize(nChannel, nAbscissa);
|
||||
for (size_t x = 0; x < nChannel; ++x) { matrix->setDimensionLabel(0, x, escapeMatlabString(nameList[x].toASCIIString()).c_str()); }
|
||||
for (size_t x = 0; x < nAbscissa; ++x) { matrix->setDimensionLabel(1, x, escapeMatlabString(freqAbscissaNames[x].toASCIIString()).c_str()); }
|
||||
// @FIXME CERT is it me or it never copy data to matrix ?
|
||||
|
||||
mxDestroyArray(freqAbscissa);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMatlabHelper::getStimulationsOutputHeader(size_t /*index*/, IStimulationSet* /*stimulationSet*/)
|
||||
{
|
||||
// Nothing to do, the stimulation header is empty.
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
bool CMatlabHelper::popStreamedMatrixOutputBuffer(const size_t index, CMatrix* matrix, uint64_t& startTime, uint64_t& endTime) const
|
||||
{
|
||||
const std::string buf = std::string("[") + m_boxInstanceVariableName.toASCIIString()
|
||||
+ ", OV_START_TIME, OV_END_TIME, OV_LINEAR_DATA_SIZE, OV_LINEAR_DATA] = OV_popOutputBufferReshape("
|
||||
+ m_boxInstanceVariableName.toASCIIString() + ", " + std::to_string(index + 1) + ");";
|
||||
const size_t res = engEvalString(m_matlabEngine, buf.c_str());
|
||||
if (res != 0) { return false; }
|
||||
|
||||
startTime = genUi64FromEnvConverted("OV_START_TIME");
|
||||
endTime = genUi64FromEnvConverted("OV_END_TIME");
|
||||
const uint64_t size = getUi64FromEnv("OV_LINEAR_DATA_SIZE");
|
||||
mxArray* data = engGetVariable(m_matlabEngine, "OV_LINEAR_DATA");
|
||||
if (!data)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "Nonexisting variable [OV_LINEAR_DATA]\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// ti be copied direclty in openvibe buffer, the linear matrix must be ordered line by line
|
||||
memcpy(matrix->getBuffer(), ::mxGetPr(data), size * sizeof(double));
|
||||
mxDestroyArray(data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMatlabHelper::popStimulationsOutputBuffer(const size_t index, IStimulationSet* stimSet, uint64_t& startTime, uint64_t& endTime) const
|
||||
{
|
||||
const std::string buf = std::string("[") + m_boxInstanceVariableName.toASCIIString()
|
||||
+ ", OV_START_TIME, OV_END_TIME, OV_LINEAR_MATRIX_SIZE, OV_LINEAR_DATA] = OV_popOutputBuffer("
|
||||
+ m_boxInstanceVariableName.toASCIIString() + ", " + std::to_string(index + 1) + ");";
|
||||
const size_t res = engEvalString(m_matlabEngine, buf.c_str());
|
||||
if (res != 0) { return false; }
|
||||
startTime = genUi64FromEnvConverted("OV_START_TIME");
|
||||
endTime = genUi64FromEnvConverted("OV_END_TIME");
|
||||
const size_t size = getUi32FromEnv("OV_LINEAR_MATRIX_SIZE");
|
||||
mxArray* data = engGetVariable(m_matlabEngine, "OV_LINEAR_DATA");
|
||||
if (!data)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "Nonexisting variable [OV_LINEAR_DATA]\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size; i += 3)
|
||||
{
|
||||
const uint64_t id = castFromMArray(data, i + 0);
|
||||
const uint64_t date = convertFromMArray(data, i + 1);
|
||||
const uint64_t duration = convertFromMArray(data, i + 2);
|
||||
stimSet->appendStimulation(id, date, duration);
|
||||
}
|
||||
|
||||
mxDestroyArray(data);
|
||||
|
||||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
|
||||
} // namespace Matlab
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
#endif // TARGET_HAS_ThirdPartyMatlab
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#if defined TARGET_HAS_ThirdPartyMatlab
|
||||
|
||||
#include "ovp_defines.h"
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
#include <engine.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Matlab {
|
||||
class CMatlabHelper
|
||||
{
|
||||
public:
|
||||
CMatlabHelper(Kernel::ILogManager& /*logManager*/, Kernel::IErrorManager& /*errorManager*/) { }
|
||||
|
||||
bool setManagers(Kernel::ILogManager* logManager, Kernel::IErrorManager* errorManager)
|
||||
{
|
||||
m_logManager = logManager;
|
||||
m_errorManager = errorManager;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool setStreamedMatrixInputHeader(size_t index, CMatrix* matrix) const;
|
||||
bool setFeatureVectorInputHeader(size_t index, CMatrix* matrix) const;
|
||||
bool setSignalInputHeader(size_t index, CMatrix* matrix, uint64_t frequency) const;
|
||||
bool setChannelLocalisationInputHeader(size_t index, CMatrix* matrix, bool dynamic) const;
|
||||
bool setSpectrumInputHeader(size_t index, CMatrix* matrix, CMatrix* frequencyAbscissa, uint64_t frequency) const;
|
||||
bool setStimulationsInputHeader(size_t index) const;
|
||||
|
||||
// The input buffers for streamed matrix and its children streams are the same.
|
||||
bool addStreamedMatrixInputBuffer(size_t index, CMatrix* matrix, uint64_t startTime, uint64_t endTime) const;
|
||||
bool addStimulationsInputBuffer(size_t index, IStimulationSet* stimSet, uint64_t startTime, uint64_t endTime) const;
|
||||
|
||||
bool getStreamedMatrixOutputHeader(size_t index, CMatrix* matrix) const;
|
||||
bool getFeatureVectorOutputHeader(size_t index, CMatrix* matrix) const;
|
||||
bool getSignalOutputHeader(size_t index, CMatrix* matrix, uint64_t& frequency) const;
|
||||
bool getChannelLocalisationOutputHeader(size_t index, CMatrix* matrix, bool& dynamic) const;
|
||||
bool getSpectrumOutputHeader(size_t index, CMatrix* matrix, CMatrix* frequencyAbscissa, uint64_t& frequency) const;
|
||||
static bool getStimulationsOutputHeader(size_t index, IStimulationSet* stimSet);
|
||||
|
||||
// The output buffers for streamed matrix and its children streams are the same.
|
||||
bool popStreamedMatrixOutputBuffer(size_t index, CMatrix* matrix, uint64_t& startTime, uint64_t& endTime) const;
|
||||
bool popStimulationsOutputBuffer(size_t index, IStimulationSet* stimSet, uint64_t& startTime, uint64_t& endTime) const;
|
||||
|
||||
void setMatlabEngine(Engine* engine) { m_matlabEngine = engine; }
|
||||
void setBoxInstanceVariableName(const CString& name) { m_boxInstanceVariableName = name; }
|
||||
|
||||
|
||||
uint32_t getUi32FromEnv(const char* name) const;
|
||||
uint64_t getUi64FromEnv(const char* name) const;
|
||||
uint64_t genUi64FromEnvConverted(const char* name) const;
|
||||
std::vector<CString> getNamelist(const char* name) const;
|
||||
|
||||
|
||||
Kernel::ILogManager& getLogManager() const { return *m_logManager; }
|
||||
Kernel::IErrorManager& getErrorManager() const { return *m_errorManager; }
|
||||
|
||||
private:
|
||||
Engine* m_matlabEngine = nullptr;
|
||||
|
||||
// Need to be very careful that these pointers are still valid when the Helper will try to use them
|
||||
Kernel::ILogManager* m_logManager = nullptr;
|
||||
Kernel::IErrorManager* m_errorManager = nullptr;
|
||||
|
||||
CString m_boxInstanceVariableName; //must be unique
|
||||
};
|
||||
} // namespace Matlab
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
|
||||
#endif // TARGET_HAS_ThirdPartyMatlab
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
// Boxes
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
#define OVP_ClassId_BoxAlgorithm_MatlabScripting OpenViBE::CIdentifier(0x03303E0E, 0x39FE10DF)
|
||||
#define OVP_ClassId_BoxAlgorithm_MatlabScriptingDesc OpenViBE::CIdentifier(0x46130E2F, 0x34F90BA1)
|
||||
|
||||
// Global defines
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
#ifdef TARGET_HAS_ThirdPartyOpenViBEPluginsGlobalDefines
|
||||
#include "ovp_global_defines.h"
|
||||
#endif // TARGET_HAS_ThirdPartyOpenViBEPluginsGlobalDefines
|
||||
|
||||
#define OV_AttributeId_Box_FlagIsUnstable OpenViBE::CIdentifier(0x666FFFFF, 0x666FFFFF)
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
#include <openvibe/ov_all.h>
|
||||
|
||||
#include "ovp_defines.h"
|
||||
|
||||
#include "box-algorithms/ovpCBoxAlgorithmMatlabScripting.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Matlab {
|
||||
|
||||
OVP_Declare_Begin()
|
||||
#if defined TARGET_HAS_ThirdPartyMatlab
|
||||
|
||||
OVP_Declare_New(CBoxAlgorithmMatlabScriptingDesc);
|
||||
context.getTypeManager().registerEnumerationEntry(OV_TypeId_BoxAlgorithmFlag, OV_AttributeId_Box_FlagIsUnstable.toString(),
|
||||
OV_AttributeId_Box_FlagIsUnstable.id());
|
||||
|
||||
#endif // TARGET_HAS_ThirdPartyMatlab
|
||||
|
||||
OVP_Declare_End()
|
||||
|
||||
} // namespace Matlab
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
Reference in New Issue
Block a user