diff --git a/drain/echoCanceller/Lms.cpp b/drain/echoCanceller/Lms.cpp index bd0feae..e0c0bb4 100644 --- a/drain/echoCanceller/Lms.cpp +++ b/drain/echoCanceller/Lms.cpp @@ -10,7 +10,7 @@ drain::Lms::Lms(void) : m_filtre(), m_feedBack(), - m_micro(0.1f) { + m_mu(0.08f) { setFilterSize(256); } @@ -23,7 +23,7 @@ void drain::Lms::reset(void) { setFilterSize(m_filtre.size()); } -bool drain::Lms::process(int16_t* _output, int16_t* _feedback, int16_t* _microphone, int32_t _nbSample) { +bool drain::Lms::process(int16_t* _output, const int16_t* _feedback, const int16_t* _microphone, int32_t _nbSample) { float output[_nbSample]; float feedback[_nbSample]; float microphone[_nbSample]; @@ -38,7 +38,7 @@ bool drain::Lms::process(int16_t* _output, int16_t* _feedback, int16_t* _microph return ret; } -bool drain::Lms::process(float* _output, float* _feedback, float* _microphone, int32_t _nbSample) { +bool drain::Lms::process(float* _output, const float* _feedback, const float* _microphone, int32_t _nbSample) { // add sample in the feedback history: m_feedBack.resize(m_filtre.size(), 0.0f); memcpy(&m_feedBack[m_filtre.size()], _feedback, _nbSample*sizeof(float)); @@ -70,7 +70,7 @@ float drain::Lms::processValue(float* _feedback, float _microphone) { float convolutionValue = convolution(_feedback, &m_filtre[0], m_filtre.size()); float error = _microphone - convolutionValue; float out = std::avg(-1.0f, error, 1.0f); - updateFilter(&m_filtre[0], _feedback, 2.0f*m_micro, m_filtre.size()); + updateFilter(&m_filtre[0], _feedback, error*m_mu, m_filtre.size()); return out; } diff --git a/drain/echoCanceller/Lms.h b/drain/echoCanceller/Lms.h index 1127d26..2a3558b 100644 --- a/drain/echoCanceller/Lms.h +++ b/drain/echoCanceller/Lms.h @@ -12,24 +12,109 @@ namespace drain { // Least Mean Square (LMS) algorithm "echo canceller" + /* + Shcématic description: + / + o---o /| + _feedback | |/ | + >---------------->| | | >~~~~~~~~o + x(n) | |\ | | + o---o \| | + \ o--------0 + | | Environement + | u(n) | transfert fonction + | | + o--------o + | + | + o---o ___ | + _microphone | |/ \ <~~~~~~o + <----------------<| | | <~~~~~~~~~~~~< Noise + d(n) | |\___/ <~~~~~~0 + o---o | + | + o~~~~~< Usefull signal + s(n) + + LMS Algorithm: + + _microphone -----------------------------o + d(n) | + | + o--------o | o-------------o + o---> filter --------->| | o--->| | + | û(n) | convol-| | d(n) - y(n) |----> e(n) -------> echo-cancelled output + | | -ution |----> y(n) ---->| | | + | _feedback -----o--->| | o-------------o | + | x(n) | o--------o | + | | | + | | o----------------------------------o | + | | | | | + | o-------->| |<-------o + | | û(n+1) = û(n) | + | | + 2 * mu * e(n) * x(n) | + | | | + | o----------------------------------o + | | + | | + o--------------------------------------------o + + + + */ class Lms { public: + /** + * @brief Constructor + */ Lms(void); + /** + * @brief Destructor + */ ~Lms(void); public: + /** + * @brief Reset filter history and filter + */ void reset(void); - bool process(int16_t* _output, int16_t* _feedback, int16_t* _microphone, int32_t _nbSample); - bool process(float* _output, float* _feedback, float* _microphone, int32_t _nbSample); + /** + * @brief Process 16 bit LMS (input 16 bits) + * @param[in,out] _output output data of the LMS + * @param[in] _feedback Input feedback of the signal: x(n) + * @param[in] _microphone Input Microphone data: d(n) + */ + bool process(int16_t* _output, const int16_t* _feedback, const int16_t* _microphone, int32_t _nbSample); + /** + * @brief Process float LMS + * @param[in,out] _output output data of the LMS + * @param[in] _feedback Input feedback of the signal: x(n) + * @param[in] _microphone Input Microphone data: d(n) + */ + bool process(float* _output, const float* _feedback, const float* _microphone, int32_t _nbSample); protected: + /** + * @brief Process a single value of the LMS + * @param[in] _feedback Pointer on the feedback data (with history and at the n(th) position + * @param[in] _microphone Microphone single sample [-1..1] + * @return New output value [-1..1] + */ float processValue(float* _feedback, float _microphone); - private: - std::vector m_filtre; - std::vector m_feedBack; public: + /** + * @brief Set filter size with specifing the filter temporal size and his samplerate + * @param[in] _sampleRate Current sample rate to apply filter + * @param[in] _time Time of the filter size + */ void setFilterSize(size_t _sampleRate, std11::chrono::microseconds _time); + /** + * @brief Set filter size in number of sample + * @param[in] _nbSample Sample size of the filter + */ void setFilterSize(size_t _nbSample); - protected: - float m_micro; //!< µ step size + private: + std::vector m_filtre; //!< Current filter + std::vector m_feedBack; //!< Feedback history + float m_mu; //!< mu step size }; }