[DEV] add supressor of echo
This commit is contained in:
parent
f15b42e6e9
commit
c5411217fd
201
audio/algo/river/Suppressor.cpp
Normal file
201
audio/algo/river/Suppressor.cpp
Normal file
@ -0,0 +1,201 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @author Fatima MARFOUQ
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <audio/algo/river/debug.h>
|
||||
#include <audio/algo/river/Suppressor.h>
|
||||
|
||||
namespace audio {
|
||||
namespace algo {
|
||||
namespace river {
|
||||
class SupressorPrivate {
|
||||
private:
|
||||
int8_t m_nbChannel;
|
||||
float m_sampleRate;
|
||||
enum audio::format m_format;
|
||||
float m_attaqueStep;
|
||||
float m_releaseStep;
|
||||
size_t m_nbSampleDelay;
|
||||
float m_minGain;
|
||||
float m_threashold;
|
||||
int32_t m_sampleCount;
|
||||
float m_currentGain;
|
||||
public:
|
||||
SupressorPrivate() :
|
||||
m_nbChannel(1),
|
||||
m_sampleRate(48000),
|
||||
m_format(audio::format_float),
|
||||
m_attaqueStep(0.01),
|
||||
m_releaseStep(0.01),
|
||||
m_nbSampleDelay(0),
|
||||
m_minGain(0.0),
|
||||
m_threashold(0.0),
|
||||
m_sampleCount(0),
|
||||
m_currentGain(1.0) {
|
||||
|
||||
}
|
||||
|
||||
~SupressorPrivate(void) {
|
||||
|
||||
}
|
||||
|
||||
void reset(void) {
|
||||
// simply reset filters.
|
||||
|
||||
}
|
||||
|
||||
void init(int8_t _nbChannel, float _sampleRate, enum audio::format _format) {
|
||||
m_nbChannel = _nbChannel;
|
||||
m_sampleRate = _sampleRate;
|
||||
m_format = _format;
|
||||
|
||||
}
|
||||
|
||||
void process(void* _output, const void* _input, const void* _inputFeedback, size_t _nbChunk) {
|
||||
float* output = reinterpret_cast<float*>(_output);
|
||||
const float* input = reinterpret_cast<const float*>(_input);
|
||||
const float* feedback = reinterpret_cast<const float*>(_inputFeedback);
|
||||
for (size_t iii=0; iii<_nbChunk; ++iii) {
|
||||
if (feedback[iii] > m_threashold) {
|
||||
m_sampleCount = 0;
|
||||
} else {
|
||||
m_sampleCount++;
|
||||
}
|
||||
if (m_sampleCount > m_nbSampleDelay) {
|
||||
m_currentGain += m_releaseStep;
|
||||
if (m_currentGain >= 1.0) {
|
||||
m_currentGain = 1.0;
|
||||
}
|
||||
} else {
|
||||
m_currentGain -= m_attaqueStep;
|
||||
if (m_currentGain <= 0.0) {
|
||||
m_currentGain = 0.0;
|
||||
}
|
||||
}
|
||||
if (m_currentGain < m_minGain) {
|
||||
m_currentGain = m_minGain;
|
||||
}
|
||||
for (int8_t kkk=0; kkk<m_nbChannel; ++kkk) {
|
||||
output[iii*m_nbChannel + kkk] = output[iii*m_nbChannel + kkk] * m_currentGain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the algo attaque time.
|
||||
* @param[in] _time Time of the attaque gain.
|
||||
*/
|
||||
virtual void setAttaqueTime(std11::chrono::microseconds _time) {
|
||||
m_attaqueStep = 1.0 / float(int64_t(m_sampleRate) * 1000000LL / _time.count());
|
||||
}
|
||||
/**
|
||||
* @brief Set the algo release time.
|
||||
* @param[in] _time Time of the release gain.
|
||||
*/
|
||||
virtual void setReleaseTime(std11::chrono::microseconds _time) {
|
||||
m_releaseStep = 1.0 / float(int64_t(m_sampleRate) * 1000000LL / _time.count());
|
||||
}
|
||||
/**
|
||||
* @brief Set the minimum Gain.
|
||||
* @param[in] _gain dB gain to apply for minimum.
|
||||
*/
|
||||
virtual void setMinimumGain(float _gain) {
|
||||
m_minGain = std::pow(10.0f, _gain/20.0f);
|
||||
}
|
||||
/**
|
||||
* @brief Set the threashold Gain.
|
||||
* @param[in] _gain dB gain to start removing data.
|
||||
*/
|
||||
virtual void setThreshold(float _gain) {
|
||||
m_threashold = std::pow(10.0f, _gain/20.0f);
|
||||
}
|
||||
/**
|
||||
* @brief Set the delay befor releasing time.
|
||||
* @param[in] _time Time of the dalay release.
|
||||
*/
|
||||
virtual void setReleaseDelay(std11::chrono::microseconds _time) {
|
||||
m_nbSampleDelay = int64_t(m_sampleRate) * 1000000LL / _time.count();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
audio::algo::river::Supressor::Supressor(void) {
|
||||
|
||||
}
|
||||
|
||||
audio::algo::river::Supressor::~Supressor(void) {
|
||||
|
||||
}
|
||||
|
||||
void audio::algo::river::Supressor::reset(void) {
|
||||
if (m_private == nullptr) {
|
||||
AA_RIVER_ERROR("Algo is not initialized...");
|
||||
}
|
||||
m_private->reset();
|
||||
}
|
||||
|
||||
void audio::algo::river::Supressor::init(int8_t _nbChannel, float _sampleRate, enum audio::format _format) {
|
||||
if (m_private == nullptr) {
|
||||
m_private = std::make_shared<audio::algo::river::SupressorPrivate>();
|
||||
}
|
||||
m_private->init(_nbChannel, _sampleRate, _format);
|
||||
}
|
||||
|
||||
std::vector<enum audio::format> audio::algo::river::Supressor::getSupportedFormat() {
|
||||
std::vector<enum audio::format> out = getNativeSupportedFormat();
|
||||
return out;
|
||||
}
|
||||
|
||||
std::vector<enum audio::format> audio::algo::river::Supressor::getNativeSupportedFormat() {
|
||||
std::vector<enum audio::format> out;
|
||||
out.push_back(audio::format_float);
|
||||
return out;
|
||||
}
|
||||
|
||||
void audio::algo::river::Supressor::process(void* _output, const void* _input, const void* _inputFeedback, size_t _nbChunk) {
|
||||
if (m_private == nullptr) {
|
||||
AA_RIVER_ERROR("Algo is not initialized...");
|
||||
}
|
||||
m_private->process(_output, _input, _inputFeedback, _nbChunk);
|
||||
}
|
||||
|
||||
|
||||
void audio::algo::river::Supressor::setAttaqueTime(std11::chrono::microseconds _time) {
|
||||
if (m_private == nullptr) {
|
||||
AA_RIVER_ERROR("Algo is not initialized...");
|
||||
}
|
||||
m_private->setAttaqueTime(_time);
|
||||
}
|
||||
|
||||
void audio::algo::river::Supressor::setReleaseTime(std11::chrono::microseconds _time) {
|
||||
if (m_private == nullptr) {
|
||||
AA_RIVER_ERROR("Algo is not initialized...");
|
||||
}
|
||||
m_private->setReleaseTime(_time);
|
||||
}
|
||||
|
||||
void audio::algo::river::Supressor::setMinimumGain(float _gain) {
|
||||
if (m_private == nullptr) {
|
||||
AA_RIVER_ERROR("Algo is not initialized...");
|
||||
}
|
||||
m_private->setMinimumGain(_gain);
|
||||
}
|
||||
|
||||
void audio::algo::river::Supressor::setThreshold(float _gain) {
|
||||
if (m_private == nullptr) {
|
||||
AA_RIVER_ERROR("Algo is not initialized...");
|
||||
}
|
||||
m_private->setThreshold(_gain);
|
||||
}
|
||||
|
||||
void audio::algo::river::Supressor::setReleaseDelay(std11::chrono::microseconds _time) {
|
||||
if (m_private == nullptr) {
|
||||
AA_RIVER_ERROR("Algo is not initialized...");
|
||||
}
|
||||
m_private->setReleaseDelay(_time);
|
||||
}
|
97
audio/algo/river/Suppressor.h
Normal file
97
audio/algo/river/Suppressor.h
Normal file
@ -0,0 +1,97 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @author Fatima MARFOUQ
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __AUDIO_ALGO_RIVER_LMS_H__
|
||||
#define __AUDIO_ALGO_RIVER_LMS_H__
|
||||
|
||||
#include <etk/types.h>
|
||||
#include <etk/chrono.h>
|
||||
#include <audio/format.h>
|
||||
#include <etk/memory.h>
|
||||
|
||||
namespace audio {
|
||||
namespace algo {
|
||||
namespace river {
|
||||
class SupressorPrivate;
|
||||
/**
|
||||
* @brief Supressor is a simple Algo that remove data from the microphone when the speaker is active.
|
||||
*/
|
||||
class Supressor {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
Supressor();
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~Supressor();
|
||||
public:
|
||||
/**
|
||||
* @brief Reset algorithm
|
||||
*/
|
||||
virtual void reset();
|
||||
/**
|
||||
* @brief Initialize the Algorithm
|
||||
* @param[in] _nbChannel Number of channel in the stream.
|
||||
* @param[in] _sampleRate Sample rate.
|
||||
* @param[in] _format Input/output data format.
|
||||
*/
|
||||
virtual void init(int8_t _nbChannel, float _sampleRate, enum audio::format _format = audio::format_float);
|
||||
/**
|
||||
* @brief Get list of format suported in input.
|
||||
* @return list of supported format
|
||||
*/
|
||||
virtual std::vector<enum audio::format> getSupportedFormat();
|
||||
/**
|
||||
* @brief Get list of algorithm format suported. No format convertion.
|
||||
* @return list of supported format
|
||||
*/
|
||||
virtual std::vector<enum audio::format> getNativeSupportedFormat();
|
||||
/**
|
||||
* @brief Main input algo process.
|
||||
* @param[in,out] _output Output data.
|
||||
* @param[in] _input Input data.
|
||||
* @param[in] _inputFeedback Input feedback data (all time MONO).
|
||||
* @param[in] _nbChunk Number of chunk in the input buffer.
|
||||
* @param[in] _nbChannel Number of channel in the stream.
|
||||
*/
|
||||
virtual void process(void* _output, const void* _input, const void* _inputFeedback, size_t _nbChunk);
|
||||
protected:
|
||||
std11::shared_ptr<SupressorPrivate> m_private; // private data.
|
||||
public: // parameter area:
|
||||
/**
|
||||
* @brief Set the algo attaque time.
|
||||
* @param[in] _time Time of the attaque gain.
|
||||
*/
|
||||
virtual void setAttaqueTime(std11::chrono::microseconds _time);
|
||||
/**
|
||||
* @brief Set the algo release time.
|
||||
* @param[in] _time Time of the release gain.
|
||||
*/
|
||||
virtual void setReleaseTime(std11::chrono::microseconds _time);
|
||||
/**
|
||||
* @brief Set the minimum Gain.
|
||||
* @param[in] _gain dB gain to apply for minimum.
|
||||
*/
|
||||
virtual void setMinimumGain(float _gain);
|
||||
/**
|
||||
* @brief Set the threashold Gain.
|
||||
* @param[in] _gain dB gain to start removing data.
|
||||
*/
|
||||
virtual void setThreshold(float _gain);
|
||||
/**
|
||||
* @brief Set the delay befor releasing time.
|
||||
* @param[in] _time Time of the dalay release.
|
||||
*/
|
||||
virtual void setReleaseDelay(std11::chrono::microseconds _time);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -15,7 +15,8 @@ def create(target):
|
||||
'audio/algo/river/power.cpp',
|
||||
'audio/algo/river/updateFilter.cpp',
|
||||
'audio/algo/river/Lms.cpp',
|
||||
'audio/algo/river/Nlms.cpp'
|
||||
'audio/algo/river/Nlms.cpp',
|
||||
'audio/algo/river/Suppressor.cpp'
|
||||
])
|
||||
myModule.add_module_depend(['etk', 'audio'])
|
||||
myModule.add_export_path(tools.get_current_path(__file__))
|
||||
|
Loading…
Reference in New Issue
Block a user