[DEV] NLMS that not work so good...
This commit is contained in:
parent
e08d0888a8
commit
b3ddc41dae
@ -1,11 +1,16 @@
|
|||||||
/** @file
|
/** @file
|
||||||
* @author Edouard DUPIN
|
* @author Edouard DUPIN
|
||||||
|
* @author Fatima MARFOUQ
|
||||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
* @license APACHE v2.0 (see license file)
|
* @license APACHE v2.0 (see license file)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <audio/algo/aec/debug.h>
|
#include <audio/algo/aec/debug.h>
|
||||||
#include <audio/algo/aec/Lms.h>
|
#include <audio/algo/aec/Lms.h>
|
||||||
|
#include <audio/algo/aec/updateFilter.h>
|
||||||
|
#include <audio/algo/aec/convolution.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
audio::algo::aec::Lms::Lms(void) :
|
audio::algo::aec::Lms::Lms(void) :
|
||||||
m_filter(),
|
m_filter(),
|
||||||
@ -50,27 +55,12 @@ bool audio::algo::aec::Lms::process(float* _output, const float* _feedback, cons
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static float convolution(float* _dataMinus, float* _dataPlus, size_t _count) {
|
|
||||||
float out = 0.0f;
|
|
||||||
for (size_t iii = 0; iii < _count; ++iii) {
|
|
||||||
out += *_dataMinus-- * *_dataPlus++;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void updateFilter(float* _filter, float* _data, float _value, int32_t _count) {
|
|
||||||
for (size_t iii = 0; iii < _count; ++iii) {
|
|
||||||
*(_filter++) += *_data-- * _value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float audio::algo::aec::Lms::processValue(float* _feedback, float _microphone) {
|
float audio::algo::aec::Lms::processValue(float* _feedback, float _microphone) {
|
||||||
// Error calculation.
|
// Error calculation.
|
||||||
float convolutionValue = convolution(_feedback, &m_filter[0], m_filter.size());
|
float convolutionValue = audio::algo::aec::convolution(_feedback, &m_filter[0], m_filter.size());
|
||||||
float error = _microphone - convolutionValue;
|
float error = _microphone - convolutionValue;
|
||||||
float out = std::avg(-1.0f, error, 1.0f);
|
float out = std::avg(-1.0f, error, 1.0f);
|
||||||
updateFilter(&m_filter[0], _feedback, error*m_mu, m_filter.size());
|
audio::algo::aec::updateFilter(&m_filter[0], _feedback, error*m_mu, m_filter.size());
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
/** @file
|
/** @file
|
||||||
* @author Edouard DUPIN
|
* @author Edouard DUPIN
|
||||||
|
* @author Fatima MARFOUQ
|
||||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
* @license APACHE v2.0 (see license file)
|
* @license APACHE v2.0 (see license file)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __DRAIN_LMS_H__
|
#ifndef __AUDIO_ALGO_AEC_LMS_H__
|
||||||
#define __DRAIN_LMS_H__
|
#define __AUDIO_ALGO_AEC_LMS_H__
|
||||||
|
|
||||||
#include <etk/types.h>
|
#include <etk/types.h>
|
||||||
#include <etk/chrono.h>
|
#include <etk/chrono.h>
|
||||||
@ -44,8 +45,8 @@ namespace audio {
|
|||||||
d(n) |
|
d(n) |
|
||||||
|
|
|
|
||||||
o--------o | o-------------o
|
o--------o | o-------------o
|
||||||
o---> filter --------->| | o--->| |
|
o---> filter --------->| | o--->| | _output
|
||||||
| û(n) | convol-| | d(n) - y(n) |----> e(n) -------> echo-cancelled output
|
| û(n) | convol-| | d(n) - y(n) |----> e(n) -------> echo-cancelled
|
||||||
| | -ution |----> y(n) ---->| | |
|
| | -ution |----> y(n) ---->| | |
|
||||||
| _feedback -----o--->| | o-------------o |
|
| _feedback -----o--->| | o-------------o |
|
||||||
| x(n) | o--------o |
|
| x(n) | o--------o |
|
||||||
@ -54,7 +55,7 @@ namespace audio {
|
|||||||
| | | | |
|
| | | | |
|
||||||
| o-------->| |<-------o
|
| o-------->| |<-------o
|
||||||
| | û(n+1) = û(n) |
|
| | û(n+1) = û(n) |
|
||||||
| | + 2 * mu * e(n) * x(n) |
|
| | + mu * e(n) * x(n) |
|
||||||
| | |
|
| | |
|
||||||
| o----------------------------------o
|
| o----------------------------------o
|
||||||
| |
|
| |
|
||||||
|
85
audio/algo/aec/Nlms.cpp
Normal file
85
audio/algo/aec/Nlms.cpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @author Fatima MARFOUQ
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <audio/algo/aec/debug.h>
|
||||||
|
#include <audio/algo/aec/Nlms.h>
|
||||||
|
#include <audio/algo/aec/updateFilter.h>
|
||||||
|
#include <audio/algo/aec/convolution.h>
|
||||||
|
#include <audio/algo/aec/power.h>
|
||||||
|
|
||||||
|
audio::algo::aec::Nlms::Nlms(void) :
|
||||||
|
m_filter(),
|
||||||
|
m_feedBack() {
|
||||||
|
setFilterSize(256);
|
||||||
|
}
|
||||||
|
|
||||||
|
audio::algo::aec::Nlms::~Nlms(void) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio::algo::aec::Nlms::reset(void) {
|
||||||
|
// simply reset filters.
|
||||||
|
setFilterSize(m_filter.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool audio::algo::aec::Nlms::process(int16_t* _output, const int16_t* _feedback, const int16_t* _microphone, int32_t _nbSample) {
|
||||||
|
float output[_nbSample];
|
||||||
|
float feedback[_nbSample];
|
||||||
|
float microphone[_nbSample];
|
||||||
|
for (size_t iii=0; iii<_nbSample; ++iii) {
|
||||||
|
microphone[iii] = float(_microphone[iii])/32767.0f;
|
||||||
|
feedback[iii] = float(_feedback[iii])/32767.0f;
|
||||||
|
}
|
||||||
|
bool ret = process(output, feedback, microphone, _nbSample);
|
||||||
|
for (size_t iii=0; iii<_nbSample; ++iii) {
|
||||||
|
_output[iii] = int16_t(float(output[iii])*32767.0f);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool audio::algo::aec::Nlms::process(float* _output, const float* _feedback, const float* _microphone, int32_t _nbSample) {
|
||||||
|
// add sample in the feedback history:
|
||||||
|
m_feedBack.resize(m_filter.size()+_nbSample, 0.0f);
|
||||||
|
memcpy(&m_feedBack[m_filter.size()], _feedback, _nbSample*sizeof(float));
|
||||||
|
for (int32_t iii=0; iii < _nbSample; iii++) {
|
||||||
|
_output[iii] = processValue(&m_feedBack[m_filter.size()+iii], _microphone[iii]);
|
||||||
|
}
|
||||||
|
// remove old value:
|
||||||
|
m_feedBack.erase(m_feedBack.begin(), m_feedBack.begin() + (m_feedBack.size()-m_filter.size()) );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
float audio::algo::aec::Nlms::processValue(float* _feedback, float _microphone) {
|
||||||
|
// Error calculation.
|
||||||
|
float convolutionValue = audio::algo::aec::convolution(_feedback, &m_filter[0], m_filter.size());
|
||||||
|
float error = _microphone - convolutionValue;
|
||||||
|
float out = std::avg(-1.0f, error, 1.0f);
|
||||||
|
// calculate mu:
|
||||||
|
float mu = audio::algo::aec::power(_feedback, m_filter.size());
|
||||||
|
//mu = *_feedback * *_feedback;
|
||||||
|
//AA_AEC_WARNING("Mu =" << mu);
|
||||||
|
if (mu <= 1.5f) {
|
||||||
|
// Not enought power in output
|
||||||
|
mu = 0.0001; // arbitrary
|
||||||
|
} else {
|
||||||
|
mu = 1.0f/mu;
|
||||||
|
//AA_AEC_WARNING("Mu =" << mu);
|
||||||
|
}
|
||||||
|
audio::algo::aec::updateFilter(&m_filter[0], _feedback, error*mu, m_filter.size());
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio::algo::aec::Nlms::setFilterSize(size_t _sampleRate, std11::chrono::microseconds _time) {
|
||||||
|
setFilterSize((_sampleRate*_time.count())/1000000LL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio::algo::aec::Nlms::setFilterSize(size_t _nbSample) {
|
||||||
|
m_filter.clear();
|
||||||
|
m_feedBack.clear();
|
||||||
|
m_filter.resize(_nbSample, 0.0f);
|
||||||
|
m_feedBack.resize(_nbSample, 0.0f);
|
||||||
|
}
|
130
audio/algo/aec/Nlms.h
Normal file
130
audio/algo/aec/Nlms.h
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @author Fatima MARFOUQ
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __AUDIO_ALGO_AEC_NLMS_H__
|
||||||
|
#define __AUDIO_ALGO_AEC_NLMS_H__
|
||||||
|
|
||||||
|
#include <etk/types.h>
|
||||||
|
#include <etk/chrono.h>
|
||||||
|
namespace audio {
|
||||||
|
namespace algo {
|
||||||
|
namespace aec {
|
||||||
|
/**
|
||||||
|
* @brief Least Mean Square (LMS) algorithm "echo canceller"
|
||||||
|
* base on publication: http://www.arpapress.com/Volumes/Vol7Issue1/IJRRAS_7_1_05.pdf
|
||||||
|
Electronic 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--->| | _output
|
||||||
|
| û(n) | convol-| | d(n) - y(n) |----> e(n) -------> echo-cancelled
|
||||||
|
| | -ution |----> y(n) ---->| | |
|
||||||
|
| _feedback -----o--->| | o-------------o |
|
||||||
|
| x(n) | o--------o |
|
||||||
|
| | |
|
||||||
|
| | o----------------------------------o |
|
||||||
|
| | | | |
|
||||||
|
| o-------->| |<-------o
|
||||||
|
| | û(n+1) = û(n) |
|
||||||
|
| | + mu * e(n) * x(n) |
|
||||||
|
| | |
|
||||||
|
| o----------------------------------o
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
o--------------------------------------------o
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
class Nlms {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructor
|
||||||
|
*/
|
||||||
|
Nlms(void);
|
||||||
|
/**
|
||||||
|
* @brief Destructor
|
||||||
|
*/
|
||||||
|
~Nlms(void);
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Reset filter history and filter
|
||||||
|
*/
|
||||||
|
void reset(void);
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
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);
|
||||||
|
private:
|
||||||
|
std::vector<float> m_filter; //!< Current filter
|
||||||
|
std::vector<float> m_feedBack; //!< Feedback history
|
||||||
|
public:
|
||||||
|
// for debug only:
|
||||||
|
std::vector<float> getFilter() {
|
||||||
|
return m_filter;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
17
audio/algo/aec/convolution.cpp
Normal file
17
audio/algo/aec/convolution.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @author Fatima MARFOUQ
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <audio/algo/aec/convolution.h>
|
||||||
|
|
||||||
|
float audio::algo::aec::convolution(float* _dataMinus, float* _dataPlus, size_t _count) {
|
||||||
|
float out = 0.0f;
|
||||||
|
for (size_t iii = 0; iii < _count; ++iii) {
|
||||||
|
out += *_dataMinus-- * *_dataPlus++;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
21
audio/algo/aec/convolution.h
Normal file
21
audio/algo/aec/convolution.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @author Fatima MARFOUQ
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __AUDIO_ALGO_AEC_CONVOLUTION_H__
|
||||||
|
#define __AUDIO_ALGO_AEC_CONVOLUTION_H__
|
||||||
|
|
||||||
|
#include <etk/types.h>
|
||||||
|
|
||||||
|
namespace audio {
|
||||||
|
namespace algo {
|
||||||
|
namespace aec {
|
||||||
|
float convolution(float* _dataMinus, float* _dataPlus, size_t _count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
19
audio/algo/aec/power.cpp
Normal file
19
audio/algo/aec/power.cpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @author Fatima MARFOUQ
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <audio/algo/aec/power.h>
|
||||||
|
|
||||||
|
|
||||||
|
float audio::algo::aec::power(float* _data, int32_t _count) {
|
||||||
|
float out = 0;
|
||||||
|
for (size_t iii = 0; iii < _count; ++iii) {
|
||||||
|
out += *_data * *_data;
|
||||||
|
_data--;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
21
audio/algo/aec/power.h
Normal file
21
audio/algo/aec/power.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @author Fatima MARFOUQ
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __AUDIO_ALGO_AEC_POWER_H__
|
||||||
|
#define __AUDIO_ALGO_AEC_POWER_H__
|
||||||
|
|
||||||
|
#include <etk/types.h>
|
||||||
|
|
||||||
|
namespace audio {
|
||||||
|
namespace algo {
|
||||||
|
namespace aec {
|
||||||
|
float power(float* _data, int32_t _count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
16
audio/algo/aec/updateFilter.cpp
Normal file
16
audio/algo/aec/updateFilter.cpp
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @author Fatima MARFOUQ
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <audio/algo/aec/updateFilter.h>
|
||||||
|
|
||||||
|
|
||||||
|
void audio::algo::aec::updateFilter(float* _filter, float* _data, float _value, int32_t _count) {
|
||||||
|
for (size_t iii = 0; iii < _count; ++iii) {
|
||||||
|
*(_filter++) += *_data-- * _value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
21
audio/algo/aec/updateFilter.h
Normal file
21
audio/algo/aec/updateFilter.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @author Fatima MARFOUQ
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __AUDIO_ALGO_AEC_UPDATE_FILTER_H__
|
||||||
|
#define __AUDIO_ALGO_AEC_UPDATE_FILTER_H__
|
||||||
|
|
||||||
|
#include <etk/types.h>
|
||||||
|
|
||||||
|
namespace audio {
|
||||||
|
namespace algo {
|
||||||
|
namespace aec {
|
||||||
|
void updateFilter(float* _filter, float* _data, float _value, int32_t _count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -11,7 +11,11 @@ def create(target):
|
|||||||
myModule = module.Module(__file__, 'audio_algo_aec', 'LIBRARY')
|
myModule = module.Module(__file__, 'audio_algo_aec', 'LIBRARY')
|
||||||
myModule.add_src_file([
|
myModule.add_src_file([
|
||||||
'audio/algo/aec/debug.cpp',
|
'audio/algo/aec/debug.cpp',
|
||||||
'audio/algo/aec/Lms.cpp'
|
'audio/algo/aec/convolution.cpp',
|
||||||
|
'audio/algo/aec/power.cpp',
|
||||||
|
'audio/algo/aec/updateFilter.cpp',
|
||||||
|
'audio/algo/aec/Lms.cpp',
|
||||||
|
'audio/algo/aec/Nlms.cpp'
|
||||||
])
|
])
|
||||||
myModule.add_module_depend(['etk'])
|
myModule.add_module_depend(['etk'])
|
||||||
myModule.add_export_path(tools.get_current_path(__file__))
|
myModule.add_export_path(tools.get_current_path(__file__))
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <test/debug.h>
|
#include <test/debug.h>
|
||||||
#include <etk/etk.h>
|
#include <etk/etk.h>
|
||||||
#include <audio/algo/aec/Lms.h>
|
#include <audio/algo/aec/Lms.h>
|
||||||
|
#include <audio/algo/aec/Nlms.h>
|
||||||
#include <etk/os/FSNode.h>
|
#include <etk/os/FSNode.h>
|
||||||
|
|
||||||
|
|
||||||
@ -56,6 +57,7 @@ int main(int _argc, const char** _argv) {
|
|||||||
std::string micName = "";
|
std::string micName = "";
|
||||||
int32_t filterSize = 0;
|
int32_t filterSize = 0;
|
||||||
float mu = 0.0f;
|
float mu = 0.0f;
|
||||||
|
bool nlms = false;
|
||||||
for (int32_t iii=0; iii<_argc ; ++iii) {
|
for (int32_t iii=0; iii<_argc ; ++iii) {
|
||||||
std::string data = _argv[iii];
|
std::string data = _argv[iii];
|
||||||
if (etk::start_with(data,"--fb=")) {
|
if (etk::start_with(data,"--fb=")) {
|
||||||
@ -68,14 +70,17 @@ int main(int _argc, const char** _argv) {
|
|||||||
} else if (etk::start_with(data,"--mu=")) {
|
} else if (etk::start_with(data,"--mu=")) {
|
||||||
data = &data[5];
|
data = &data[5];
|
||||||
mu = etk::string_to_float(data);
|
mu = etk::string_to_float(data);
|
||||||
|
} else if (data == "--nlms") {
|
||||||
|
nlms = true;
|
||||||
} else if ( data == "-h"
|
} else if ( data == "-h"
|
||||||
|| data == "--help") {
|
|| data == "--help") {
|
||||||
APPL_INFO("Help : ");
|
APPL_INFO("Help : ");
|
||||||
APPL_INFO(" ./xxx --fb=file.raw --mic=file.raw");
|
APPL_INFO(" ./xxx --fb=file.raw --mic=file.raw");
|
||||||
APPL_INFO(" --fb Feedback file");
|
APPL_INFO(" --fb=YYY.raw Feedback file");
|
||||||
APPL_INFO(" --mic Microphone file");
|
APPL_INFO(" --mic=XXX.raw Microphone file");
|
||||||
APPL_INFO(" --filter-size Size of the filter");
|
APPL_INFO(" --filter-size=xxx Size of the filter");
|
||||||
APPL_INFO(" --mu Mu value -1.0< mu < -1.0");
|
APPL_INFO(" --mu=0.xx Mu value -1.0< mu < -1.0");
|
||||||
|
APPL_INFO(" --nlms NLMS version");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,7 +95,17 @@ int main(int _argc, const char** _argv) {
|
|||||||
APPL_INFO("Read Microphone:");
|
APPL_INFO("Read Microphone:");
|
||||||
std::vector<int16_t> micData = read(micName);
|
std::vector<int16_t> micData = read(micName);
|
||||||
APPL_INFO(" " << micData.size() << " samples");
|
APPL_INFO(" " << micData.size() << " samples");
|
||||||
|
// resize output :
|
||||||
|
std::vector<int16_t> output;
|
||||||
|
output.resize(std::min(fbData.size(), micData.size()), 0);
|
||||||
|
// process in chunk of 256 samples
|
||||||
|
int32_t blockSize = 256;
|
||||||
|
// end filter :
|
||||||
|
std::vector<float> filter;
|
||||||
|
if (nlms == false) {
|
||||||
|
APPL_INFO("***********************");
|
||||||
|
APPL_INFO("** LMS **");
|
||||||
|
APPL_INFO("***********************");
|
||||||
audio::algo::aec::Lms algo;
|
audio::algo::aec::Lms algo;
|
||||||
if (filterSize != 0) {
|
if (filterSize != 0) {
|
||||||
algo.setFilterSize(filterSize);
|
algo.setFilterSize(filterSize);
|
||||||
@ -98,16 +113,39 @@ int main(int _argc, const char** _argv) {
|
|||||||
if (mu != 0.0f) {
|
if (mu != 0.0f) {
|
||||||
algo.setMu(mu);
|
algo.setMu(mu);
|
||||||
}
|
}
|
||||||
std::vector<int16_t> output;
|
int32_t lastPourcent = -1;
|
||||||
output.resize(std::min(fbData.size(), micData.size()), 0);
|
|
||||||
// process in chunk of 256 samples
|
|
||||||
int32_t blockSize = 256;
|
|
||||||
for (int32_t iii=0; iii<output.size()/blockSize; ++iii) {
|
for (int32_t iii=0; iii<output.size()/blockSize; ++iii) {
|
||||||
APPL_INFO("Process : " << iii*blockSize << "/" << int32_t(output.size()/blockSize)*blockSize);
|
if (lastPourcent != 100*iii / (output.size()/blockSize)) {
|
||||||
|
lastPourcent = 100*iii / (output.size()/blockSize);
|
||||||
|
APPL_INFO("Process : " << iii*blockSize << "/" << int32_t(output.size()/blockSize)*blockSize << " " << lastPourcent << "/100");
|
||||||
|
} else {
|
||||||
|
APPL_VERBOSE("Process : " << iii*blockSize << "/" << int32_t(output.size()/blockSize)*blockSize);
|
||||||
|
}
|
||||||
algo.process(&output[iii*blockSize], &fbData[iii*blockSize], &micData[iii*blockSize], blockSize);
|
algo.process(&output[iii*blockSize], &fbData[iii*blockSize], &micData[iii*blockSize], blockSize);
|
||||||
}
|
}
|
||||||
|
filter = algo.getFilter();
|
||||||
|
} else {
|
||||||
|
APPL_INFO("***********************");
|
||||||
|
APPL_INFO("** NLMS (power) **");
|
||||||
|
APPL_INFO("***********************");
|
||||||
|
audio::algo::aec::Nlms algo;
|
||||||
|
if (filterSize != 0) {
|
||||||
|
algo.setFilterSize(filterSize);
|
||||||
|
}
|
||||||
|
int32_t lastPourcent = -1;
|
||||||
|
for (int32_t iii=0; iii<output.size()/blockSize; ++iii) {
|
||||||
|
if (lastPourcent != 100*iii / (output.size()/blockSize)) {
|
||||||
|
lastPourcent = 100*iii / (output.size()/blockSize);
|
||||||
|
APPL_INFO("Process : " << iii*blockSize << "/" << int32_t(output.size()/blockSize)*blockSize << " " << lastPourcent << "/100");
|
||||||
|
} else {
|
||||||
|
APPL_VERBOSE("Process : " << iii*blockSize << "/" << int32_t(output.size()/blockSize)*blockSize);
|
||||||
|
}
|
||||||
|
algo.process(&output[iii*blockSize], &fbData[iii*blockSize], &micData[iii*blockSize], blockSize);
|
||||||
|
}
|
||||||
|
filter = algo.getFilter();
|
||||||
|
}
|
||||||
write("output.raw", output);
|
write("output.raw", output);
|
||||||
write("filter.raw", algo.getFilter());
|
write("filter.raw", filter);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user