This commit is contained in:
2021-10-14 13:47:35 +02:00
commit 6625a8dfaa
4026 changed files with 844291 additions and 0 deletions
@@ -0,0 +1,101 @@
#include "CBoxAlgorithmASRProcessor.hpp"
//@todo put functions in this file in sdk it's duplication of file in riemann module
#include "utils/misc.hpp" // For conversion Openvibe to Eigen
namespace OpenViBE {
namespace Plugins {
namespace Artifact {
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmASRProcessor::initialize()
{
//***** Codecs *****
m_SignalDecoder.initialize(*this, 0);
m_stimulationEncoder.initialize(*this, 0);
m_signalEncoder.initialize(*this, 1);
m_signalEncoder.getInputSamplingRate().setReferenceTarget(m_SignalDecoder.getOutputSamplingRate()); // Link Sampling
m_signalEncoder.getInputMatrix().setReferenceTarget(m_SignalDecoder.getOutputMatrix()); // Link Matrix
//***** Pointers *****
m_iMatrix = m_SignalDecoder.getOutputMatrix();
m_oStimulation = m_stimulationEncoder.getInputStimulationSet();
m_oMatrix = m_signalEncoder.getInputMatrix();
// Settings
m_filename = CString(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0)).toASCIIString();
OV_ERROR_UNLESS_KRF(!m_filename.empty(), "Invalid empty model filename", Kernel::ErrorType::BadSetting);
OV_ERROR_UNLESS_KRF(m_asr.loadXML(m_filename), "Loading XML Error", Kernel::ErrorType::BadFileRead);
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmASRProcessor::uninitialize()
{
m_SignalDecoder.uninitialize();
m_stimulationEncoder.uninitialize();
m_signalEncoder.uninitialize();
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmASRProcessor::processInput(const size_t /*index*/)
{
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmASRProcessor::process()
{
Kernel::IBoxIO& boxCtx = this->getDynamicBoxContext();
for (size_t i = 0; i < boxCtx.getInputChunkCount(0); ++i)
{
m_SignalDecoder.decode(i); // Decode the chunk
OV_ERROR_UNLESS_KRF(m_iMatrix->getDimensionCount() == 2, "Invalid Input Signal", Kernel::ErrorType::BadInput);
const uint64_t start = boxCtx.getInputChunkStartTime(0, i), // Time Code Chunk Start
end = boxCtx.getInputChunkEndTime(0, i); // Time Code Chunk End
if (m_SignalDecoder.isHeaderReceived()) // Header received
{
m_signalEncoder.encodeHeader();
m_stimulationEncoder.encodeHeader();
boxCtx.markOutputAsReadyToSend(0, start, end);
}
if (m_SignalDecoder.isBufferReceived()) // Buffer received
{
const bool prevTrivial = m_asr.getTrivial();
Eigen::MatrixXd in, out;
MatrixConvert(*m_iMatrix, in);
OV_ERROR_UNLESS_KRF(m_asr.process(in, out), "ASR Process Error", Kernel::ErrorType::BadProcessing);
MatrixConvert(out, *m_oMatrix);
m_signalEncoder.encodeBuffer();
const bool newTrivial = m_asr.getTrivial();
if (!newTrivial && !prevTrivial) // We have reconstruct signal
{
m_oStimulation->appendStimulation(OVTK_StimulationId_Artifact, start, 0);
m_stimulationEncoder.encodeBuffer();
boxCtx.markOutputAsReadyToSend(0, start, end);
}
}
if (m_SignalDecoder.isEndReceived()) // Buffer received
{
m_signalEncoder.encodeEnd();
m_stimulationEncoder.encodeEnd();
boxCtx.markOutputAsReadyToSend(0, start, end);
}
boxCtx.markOutputAsReadyToSend(1, start, end);
}
return true;
}
//---------------------------------------------------------------------------------------------------
} // namespace Artifact
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,88 @@
///-------------------------------------------------------------------------------------------------
///
/// \file CBoxAlgorithmASRProcessor.hpp
/// \brief Classes of the box ASR Processor.
/// \author Thibaut Monseigne (Inria).
/// \version 1.0.
/// \date 08/12/2020.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
///
///-------------------------------------------------------------------------------------------------
#pragma once
#include "defines.hpp"
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
#include <geometry/artifacts/CASR.hpp>
namespace OpenViBE {
namespace Plugins {
namespace Artifact {
//-------------------------------------------------------------------------------------------------
/// <summary> The class CBoxAlgorithmASRProcessor describes the box Artifact Subspace Reconstruction (ASR) Processor. </summary>
class CBoxAlgorithmASRProcessor final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
{
public:
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool processInput(const size_t index) override;
bool process() override;
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, ClassId_Box_ASR_Processor)
protected:
//***** Codecs *****
Toolkit::TSignalDecoder<CBoxAlgorithmASRProcessor> m_SignalDecoder; ///< Input Signal Decoder
Toolkit::TStimulationEncoder<CBoxAlgorithmASRProcessor> m_stimulationEncoder; ///< Output Stimulation Encoder
Toolkit::TSignalEncoder<CBoxAlgorithmASRProcessor> m_signalEncoder; ///< Output Signal Encoder
//***** Pointers *****
CMatrix *m_iMatrix = nullptr, ///< Input Matrix Pointer
*m_oMatrix = nullptr; ///< Output Matrix Pointer
IStimulationSet* m_oStimulation = nullptr; ///< Output Stimulation Pointer
//***** ASR *****
std::string m_filename; ///< ASR Model Path
Geometry::CASR m_asr; ///< ASR Model
};
//-------------------------------------------------------------------------------------------------
/// <summary> Descriptor of the box Artifact Subspace Reconstruction (ASR) Processor. </summary>
class CBoxAlgorithmASRProcessorDesc final : virtual public IBoxAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return "ASR Processor"; }
CString getAuthorName() const override { return "Thibaut Monseigne"; }
CString getAuthorCompanyName() const override { return "Inria"; }
CString getShortDescription() const override { return "Artifact Subspace Reconstruction (ASR) Processor."; }
CString getDetailedDescription() const override { return "Artifact Subspace Reconstruction (ASR) Processor."; }
CString getCategory() const override { return "Artifact"; }
CString getVersion() const override { return "0.1"; }
CString getStockItemName() const override { return "gtk-execute"; }
CIdentifier getCreatedClass() const override { return ClassId_Box_ASR_Processor; }
IPluginObject* create() override { return new CBoxAlgorithmASRProcessor; }
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
{
prototype.addInput("Input Signal", OV_TypeId_Signal);
prototype.addOutput("Signal Reconstructed",OV_TypeId_Stimulations);
prototype.addOutput("Output Signal", OV_TypeId_Signal);
prototype.addSetting("Filename to load model", OV_TypeId_Filename, "${Player_ScenarioDirectory}/ASR-model.xml");
return true;
}
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, ClassId_Box_ASR_Processor_Desc)
};
} // namespace Artifact
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,182 @@
#include "CBoxAlgorithmASRTrainer.hpp"
//@todo put functions in this file in sdk it's duplication of file in riemann module
#include "utils/misc.hpp" // For conversion Openvibe to Eigen
namespace OpenViBE {
namespace Plugins {
namespace Artifact {
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmASRTrainer::initialize()
{
// Stimulations
m_stimulationDecoder.initialize(*this, 0);
m_iStimulation = m_stimulationDecoder.getOutputStimulationSet();
m_stimulationEncoder.initialize(*this, 0);
m_oStimulation = m_stimulationEncoder.getInputStimulationSet();
// Classes
m_signalEncoder.initialize(*this, 1);
m_iMatrix = m_signalEncoder.getOutputMatrix();
// Settings
m_filename = CString(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0)).toASCIIString();
m_stimulationName = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1);
m_metric = Geometry::EMetric(uint64_t(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2)));
m_ratio = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 3);
m_rejection = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 4);
OV_ERROR_UNLESS_KRF(!m_filename.empty(), "Invalid empty model filename", Kernel::ErrorType::BadSetting);
OV_ERROR_UNLESS_KRF(Geometry::InRange(m_ratio, 0, 1), "Channel ratio must be in [0;1], actual : " + std::to_string(m_ratio), Kernel::ErrorType::BadSetting);
OV_ERROR_UNLESS_KRF(m_rejection >= 0, "Rejection limit must be positive, actual : " + std::to_string(m_rejection), Kernel::ErrorType::BadSetting);
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmASRTrainer::uninitialize()
{
m_stimulationDecoder.uninitialize();
m_signalEncoder.uninitialize();
m_stimulationEncoder.uninitialize();
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmASRTrainer::processInput(const size_t /*index*/)
{
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmASRTrainer::process()
{
if (!m_isTrain)
{
Kernel::IBoxIO& boxCtx = this->getDynamicBoxContext();
//***** Stimulations *****
for (size_t i = 0; i < boxCtx.getInputChunkCount(0); ++i)
{
m_stimulationDecoder.decode(i); // Decode the chunk
const uint64_t start = boxCtx.getInputChunkStartTime(0, i), // Time Code Chunk Start
end = boxCtx.getInputChunkEndTime(0, i); // Time Code Chunk End
if (m_stimulationDecoder.isHeaderReceived())
{
m_stimulationEncoder.encodeHeader();
boxCtx.markOutputAsReadyToSend(0, 0, 0);
}
if (m_stimulationDecoder.isBufferReceived()) // Buffer received
{
for (size_t j = 0; j < m_iStimulation->getStimulationCount(); ++j)
{
if (m_iStimulation->getStimulationIdentifier(j) == m_stimulationName)
{
OV_ERROR_UNLESS_KRF(train(), "Train or Save failed", Kernel::ErrorType::BadProcessing);
m_oStimulation->appendStimulation(OVTK_StimulationId_TrainCompleted, m_iStimulation->getStimulationDate(j), 0);
m_isTrain = true;
}
}
m_stimulationEncoder.encodeBuffer();
boxCtx.markOutputAsReadyToSend(0, start, end);
}
if (m_stimulationDecoder.isEndReceived())
{
m_stimulationEncoder.encodeEnd();
boxCtx.markOutputAsReadyToSend(0, start, end);
}
}
//***** Signal *****
for (size_t i = 0; i < boxCtx.getInputChunkCount(1); ++i)
{
m_signalEncoder.decode(i); // Decode the chunk
OV_ERROR_UNLESS_KRF(m_iMatrix->getDimensionCount() == 2, "Invalid Input Signal", Kernel::ErrorType::BadInput);
if (m_signalEncoder.isBufferReceived()) // Buffer received
{
Eigen::MatrixXd m;
MatrixConvert(*m_iMatrix, m);
m_dataset.push_back(m);
}
}
}
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmASRTrainer::train()
{
Geometry::CASR asr(m_metric);
asr.setMaxChannel(m_ratio);
this->getLogManager() << Kernel::LogLevel_Info << "Train Beginning...\n";
OV_ERROR_UNLESS_KRF(asr.train(m_dataset, m_rejection), "Train failed", Kernel::ErrorType::BadProcessing);
getLogManager() << Kernel::LogLevel_Info << "Train Finished. Save Beginning...\n";
OV_ERROR_UNLESS_KRF(asr.saveXML(m_filename), "Save failed", Kernel::ErrorType::BadProcessing);
this->getLogManager() << Kernel::LogLevel_Info << "Save Finished.\n";
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmASRTrainerListener::onSettingValueChanged(Kernel::IBox& box, const size_t index)
{
if (index == 2)
{
CString tmp;
box.getSettingValue(index, tmp);
const Geometry::EMetric m = Geometry::StringToMetric(tmp.toASCIIString());
if (m != Geometry::EMetric::Euclidian && m != Geometry::EMetric::Riemann)
{
const std::string s1 = toString(Geometry::EMetric::Euclidian), s2 = toString(Geometry::EMetric::Riemann);
getLogManager() << Kernel::LogLevel_Warning << "Metric must be " << s1 << " or " << s2 << ". Setting is set to " << s1 << "\n";
box.setSettingValue(index, s1.c_str());
}
}
else if (index == 3)
{
CString tmp;
box.getSettingValue(index, tmp);
double ratio = 0.0;
std::stringstream ss(tmp.toASCIIString());
ss >> ratio;
if (ratio < 0.0)
{
getLogManager() << Kernel::LogLevel_Warning <<
"Channel ratio must be in [0;1] (0 for no reconstruction, 1 for no limit). Setting is set to 0. \n";
box.setSettingValue(index, "0");
}
else if (ratio > 1.0)
{
getLogManager() << Kernel::LogLevel_Warning <<
"Channel ratio must be in [0;1] (0 for no reconstruction, 1 for no limit). Setting is set to 1. \n";
box.setSettingValue(index, "1");
}
}
else if (index == 4)
{
CString tmp;
box.getSettingValue(index, tmp);
double rejection = 0.0;
std::stringstream ss(tmp.toASCIIString());
ss >> rejection;
if (rejection < 0.0)
{
getLogManager() << Kernel::LogLevel_Warning << "Rejection limit must be positive. Setting is set to 0. \n";
box.setSettingValue(index, "0");
}
}
return true;
}
//---------------------------------------------------------------------------------------------------
} // namespace Artifact
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,117 @@
///-------------------------------------------------------------------------------------------------
///
/// \file CBoxAlgorithmASRProcessor.hpp
/// \brief Classes of the box ASR Processor.
/// \author Thibaut Monseigne (Inria).
/// \version 1.0.
/// \date 08/12/2020.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
///
///-------------------------------------------------------------------------------------------------
#pragma once
#include "defines.hpp"
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
#include <geometry/artifacts/CASR.hpp>
namespace OpenViBE {
namespace Plugins {
namespace Artifact {
//-------------------------------------------------------------------------------------------------
/// <summary> The class CBoxAlgorithmASRTrainer describes the box Artifact Subspace Reconstruction (ASR) Trainer. </summary>
class CBoxAlgorithmASRTrainer final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
{
public:
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool processInput(const size_t index) override;
bool process() override;
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, ClassId_Box_ASR_Trainer)
protected:
//***** Codecs *****
Toolkit::TStimulationDecoder<CBoxAlgorithmASRTrainer> m_stimulationDecoder; ///< Input Stimulation Decoder
Toolkit::TSignalDecoder<CBoxAlgorithmASRTrainer> m_signalEncoder; ///< Input Signal Encoder
Toolkit::TStimulationEncoder<CBoxAlgorithmASRTrainer> m_stimulationEncoder; ///< Output Stimulation Encoder
//***** Pointers *****
CMatrix* m_iMatrix = nullptr; ///< Input Matrix pointer
IStimulationSet *m_iStimulation = nullptr, ///< Stimulation receiver
*m_oStimulation = nullptr; ///< Stimulation sender
//***** Settings *****
std::string m_filename; ///< Filename of ASR Model
uint64_t m_stimulationName = OVTK_StimulationId_Train; ///< Name of stimulation to check for train launch
Geometry::EMetric m_metric = Geometry::EMetric::Euclidian; ///< Metric for ASR
double m_ratio = 1.0; ///< Ratio of channel to reconstruct for ASR
double m_rejection = 5.0; ///< Rejection limit of threshold for ASR
//***** Misc *****
std::vector<Eigen::MatrixXd> m_dataset; ///< Dataset stack
bool m_isTrain = false; ///< <c>True</c> if train is already done, <c>False</c> otherwise
bool train();
};
//-------------------------------------------------------------------------------------------------
/// <summary> Listener of the box Artifact Subspace Reconstruction (ASR) Trainer. </summary>
class CBoxAlgorithmASRTrainerListener final : public Toolkit::TBoxListener<IBoxListener>
{
public:
bool onSettingValueChanged(Kernel::IBox& box, const size_t index) override;;
_IsDerivedFromClass_Final_(Toolkit::TBoxListener<IBoxListener>, OV_UndefinedIdentifier)
};
//-------------------------------------------------------------------------------------------------
/// <summary> Descriptor of the box Artifact Subspace Reconstruction (ASR) Trainer. </summary>
class CBoxAlgorithmASRTrainerDesc final : virtual public IBoxAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return "ASR Trainer"; }
CString getAuthorName() const override { return "Thibaut Monseigne"; }
CString getAuthorCompanyName() const override { return "Inria"; }
CString getShortDescription() const override { return "Artifact Subspace Reconstruction (ASR) Trainer."; }
CString getDetailedDescription() const override { return "Artifact Subspace Reconstruction (ASR) Trainer."; }
CString getCategory() const override { return "Artifact"; }
CString getVersion() const override { return "0.1"; }
CString getStockItemName() const override { return "gtk-execute"; }
CIdentifier getCreatedClass() const override { return ClassId_Box_ASR_Trainer; }
IPluginObject* create() override { return new CBoxAlgorithmASRTrainer; }
IBoxListener* createBoxListener() const override { return new CBoxAlgorithmASRTrainerListener; }
void releaseBoxListener(IBoxListener* listener) const override { delete listener; }
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
{
prototype.addInput("Stimulations",OV_TypeId_Stimulations);
prototype.addInput("Input Signal", OV_TypeId_Signal);
prototype.addOutput("Train-completed Flag",OV_TypeId_Stimulations);
prototype.addSetting("Filename to save model", OV_TypeId_Filename, "${Player_ScenarioDirectory}/ASR-model.xml");
prototype.addSetting("Train trigger", OV_TypeId_Stimulation, "OVTK_StimulationId_Train");
prototype.addSetting("Metric", TypeId_Metric, toString(Geometry::EMetric::Euclidian).c_str());
prototype.addSetting("Channel ratio to reconstruct", OV_TypeId_Float, "1");
prototype.addSetting("Rejection limit", OV_TypeId_Float, "5");
return true;
}
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, ClassId_Box_ASR_Trainer_Desc)
};
} // namespace Artifact
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,92 @@
#include "CBoxAlgorithmArtifactAmplitude.hpp"
#include <cmath> // Floor
#include <sstream>
namespace OpenViBE {
namespace Plugins {
namespace Artifact {
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmArtifactAmplitude::initialize()
{
//***** Codecs *****
m_decoder.initialize(*this, 0);
m_iMatrix = m_decoder.getOutputMatrix();
//***** Settings *****
m_max = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
//***** Assert *****
OV_ERROR_UNLESS_KRF(m_max > 0, "Invalid Maximum [" << m_max << "] (expected value > 0)\n", Kernel::ErrorType::BadSetting);
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmArtifactAmplitude::uninitialize()
{
m_decoder.uninitialize();
std::stringstream ss;
ss << m_nArtifact << " artifacts detected in " << m_nSamples << " samples (";
ss.precision(2);
ss << std::fixed << 100.0 * double(m_nArtifact) / double(m_nSamples) << "%)" << std::endl;
this->getLogManager() << Kernel::LogLevel_Info << ss.str();
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmArtifactAmplitude::processInput(const size_t /*index*/)
{
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
return true;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
bool CBoxAlgorithmArtifactAmplitude::process()
{
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
for (size_t i = 0; i < boxContext.getInputChunkCount(0); ++i)
{
bool artifact = false;
m_decoder.decode(i); // Decode chunk
OV_ERROR_UNLESS_KRF(m_iMatrix->getDimensionCount() == 2, "Invalid Input Signal", Kernel::ErrorType::BadInput);
m_nSamples++;
//if (m_decoder.isHeaderReceived()) {} // Header
if (m_decoder.isBufferReceived()) // Buffer
{
const size_t size = m_iMatrix->getDimensionSize(0) * m_iMatrix->getDimensionSize(1); // get buffer size
const double* iBuffer = m_iMatrix->getBuffer(); // input buffer
for (size_t idx = 0; idx < size; ++idx)
{
if (abs(iBuffer[idx]) >= m_max) // Amplitude comparison
{
this->getLogManager() << Kernel::LogLevel_Trace << "Artifact detected in channel (" << floor(idx / m_iMatrix->getDimensionSize(1)) << ")\n";
artifact = true;
m_nArtifact++;
break;
}
}
}
//if (m_decoder.isEndReceived()) {} // End
// We don't need output codec we copy just the input to the output if there is no amplitude artifact
if (!artifact)
{
uint64_t tStart = 0, tEnd = 0;
size_t size = 0;
const uint8_t* buffer = nullptr;
boxContext.getInputChunk(0, i, tStart, tEnd, size, buffer);
boxContext.appendOutputChunkData(0, buffer, size);
boxContext.markOutputAsReadyToSend(0, tStart, tEnd);
boxContext.markInputAsDeprecated(0, i);
}
}
return true;
}
//---------------------------------------------------------------------------------------------------
} // namespace Artifact
} // namespace Plugins
} // namespace OpenViBE
@@ -0,0 +1,82 @@
///-------------------------------------------------------------------------------------------------
///
/// \file CBoxAlgorithmArtifactAmplitude.hpp
/// \brief Classes of the box Artifact Amplitude.
/// \author Thibaut Monseigne (Inria).
/// \version 1.0.
/// \date 12/08/2019.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
///
///-------------------------------------------------------------------------------------------------
#pragma once
#include "defines.hpp"
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
namespace OpenViBE {
namespace Plugins {
namespace Artifact {
//-------------------------------------------------------------------------------------------------
/// <summary> The class CBoxAlgorithmArtifactAmplitude describes the box Artifact Amplitude. </summary>
class CBoxAlgorithmArtifactAmplitude final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
{
public:
void release() override { delete this; }
bool initialize() override;
bool uninitialize() override;
bool processInput(const size_t index) override;
bool process() override;
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, ClassId_Box_Artifact_Amplitude)
protected:
Toolkit::TSignalDecoder<CBoxAlgorithmArtifactAmplitude> m_decoder; ///< Input Signal decoder
CMatrix* m_iMatrix = nullptr; ///< Input Matrix pointer
double m_max = 0; ///< Amplitude max
size_t m_nSamples = 0, ///< Sample checked
m_nArtifact = 0; ///< Artifact found
};
//-------------------------------------------------------------------------------------------------
/// <summary> Descriptor of the box Artifact Detector. </summary>
class CBoxAlgorithmArtifactAmplitudeDesc final : virtual public IBoxAlgorithmDesc
{
public:
void release() override { }
CString getName() const override { return "Artifact Amplitude"; }
CString getAuthorName() const override { return "Thibaut Monseigne"; }
CString getAuthorCompanyName() const override { return "Inria"; }
CString getShortDescription() const override { return "Simple Artifact Detection"; }
CString getDetailedDescription() const override
{
return "Check if one element is higher than Max setting.\nThe signal is returned if no element exceeds the defined value.";
}
CString getCategory() const override { return "Artifact"; }
CString getVersion() const override { return "1.0"; }
CString getStockItemName() const override { return "gtk-no"; }
CIdentifier getCreatedClass() const override { return ClassId_Box_Artifact_Amplitude; }
IPluginObject* create() override { return new CBoxAlgorithmArtifactAmplitude; }
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
{
prototype.addInput("Signal",OV_TypeId_Signal);
prototype.addOutput("Non-artifact signal",OV_TypeId_Signal);
prototype.addSetting("Max (mV)",OV_TypeId_Float, "100");
return true;
}
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, ClassId_Box_Artifact_Amplitude_Desc)
};
} // namespace Artifact
} // namespace Plugins
} // namespace OpenViBE