Commit c484694f authored by Alexandre Savard's avatar Alexandre Savard

[#1966] Make echo canceller and noise suppressor optional

parent 34dd2ffe
......@@ -47,6 +47,7 @@ GtkWidget *codecTreeView; // View used instead of store to get access to select
GtkWidget *pulse;
GtkWidget *alsabox;
GtkWidget *alsa_conf;
GtkWidget *noisebox;
GtkWidget *noise_conf;
// Codec properties ID
......@@ -776,6 +777,48 @@ select_audio_manager( void )
}
void
active_echo_cancel(void) {
gchar* state;
gchar* newstate;
DEBUG("Audio: Active echo cancel clicked");
state = dbus_get_echo_cancel_state();
DEBUG("Audio: Get echo cancel state %s", state);
if(strcmp(state, "enabled") == 0)
newstate = "disabled";
else
newstate = "enabled";
dbus_set_echo_cancel_state(newstate);
}
void
active_noise_suppress(void) {
gchar *state;
gchar *newstate;
DEBUG("Audio: Active noise suppress clicked");
state = dbus_get_noise_suppress_state();
DEBUG("Audio: Get echo cancel state %s", state);
if(strcmp(state, "enabled") == 0)
newstate = "disabled";
else
newstate = "enabled";
dbus_set_noise_suppress_state(newstate);
}
GtkWidget* alsa_box()
{
GtkWidget *ret;
......@@ -886,30 +929,37 @@ GtkWidget* alsa_box()
GtkWidget* noise_box()
{
GtkWidget *ret;
GtkWidget *enableVoiceActivity;
GtkWidget *enableEchoCancel;
GtkWidget *enableNoiseReduction;
gboolean echocancelActive, noisesuppressActive;
gchar *state;
// check button to enable ringtones
ret = gtk_hbox_new( TRUE , 1);
enableEchoCancel = gtk_check_button_new_with_mnemonic( _("_Echo Suppression"));
state = dbus_get_echo_cancel_state();
echocancelActive = FALSE;
if(strcmp(state, "enabled") == 0)
echocancelActive = TRUE;
else
echocancelActive = FALSE;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enableEchoCancel), echocancelActive);
g_signal_connect(G_OBJECT(enableEchoCancel), "clicked", active_echo_cancel, NULL);
enableVoiceActivity = gtk_check_button_new_with_mnemonic( _("_Voice Activity Detection"));
//TODO Use the value from D-BUS
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(enableVoiceActivity), FALSE );
gtk_box_pack_start( GTK_BOX(ret) , enableVoiceActivity , TRUE , TRUE , 1);
//TODO Enable it
//gtk_widget_set_sensitive(GTK_WIDGET(noise_conf), FALSE);
//TODO Add a callback function
//g_signal_connect(G_OBJECT( enableNoiseReduction) , "clicked" , NULL , NULL);
gtk_box_pack_start( GTK_BOX(ret), enableEchoCancel, TRUE , TRUE , 1);
enableNoiseReduction = gtk_check_button_new_with_mnemonic( _("_Noise Reduction (Narrow-Band Companding)"));
//TODO Use the value from D-BUS
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(enableNoiseReduction), FALSE );
enableNoiseReduction = gtk_check_button_new_with_mnemonic( _("_Noise Reduction"));
state = dbus_get_noise_suppress_state();
noisesuppressActive = FALSE;
if(strcmp(state, "enabled") == 0)
noisesuppressActive = TRUE;
else
noisesuppressActive = FALSE;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enableNoiseReduction), noisesuppressActive);
gtk_box_pack_start( GTK_BOX(ret) , enableNoiseReduction , TRUE , TRUE , 1);
//TODO Enable it
// gtk_widget_set_sensitive(GTK_WIDGET(noise_conf), FALSE);
//TODO Add a callback function
//g_signal_connect(G_OBJECT( enableNoiseReduction) , "clicked" , NULL , NULL);
g_signal_connect(G_OBJECT(enableNoiseReduction), "clicked", active_noise_suppress, NULL);
return ret;
}
......@@ -1017,6 +1067,15 @@ GtkWidget* create_audio_configuration()
gtk_file_chooser_add_filter( GTK_FILE_CHOOSER( fileChooser ) , filter);
gtk_table_attach ( GTK_TABLE( table ), fileChooser, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
gnome_main_section_new (_("Voice enhancement settings"), &noise_conf);
gtk_box_pack_start(GTK_BOX(ret), noise_conf, FALSE, FALSE, 0);
gtk_widget_show( noise_conf );
// Box for the voice enhancement configuration
noisebox = noise_box();
gtk_container_add( GTK_CONTAINER(noise_conf) , noisebox );
gtk_widget_show_all(ret);
if(!pulse_audio) {
......
......@@ -574,6 +574,36 @@
</arg>
</method>
<method name="getEchoCancelState" tp:name-for-bindings="getEchoCancelState">
<tp:docstring>
</tp:docstring>
<arg type="s" name="state" direction="out">
<tp:docstring>
</tp:docstring>
</arg>
</method>
<method name="setEchoCancelState" tp:name-for-bindings="setEchoCancelState">
<tp:docstring>
</tp:docstring>
<arg type="s" name="state" direction="in">
</arg>
</method>
<method name="getNoiseSuppressState" tp:name-for-bindings="getNoiseSuppressState">
<tp:docstring>
</tp:docstring>
<arg type="s" name="state" direction="out">
<tp:docstring>
</tp:docstring>
</arg>
</method>
<method name="setNoiseSuppressState" tp:name-for-binding="setNoiseSuppressState">
<arg type="s" name="state" direction="in">
</arg>
</method>
<!-- General Settings Panel -->
<method name="isMd5CredentialHashing" tp:name-for-bindings="isMd5CredentialHashing">
......
......@@ -1503,6 +1503,72 @@ dbus_get_current_audio_output_plugin()
return plugin;
}
/**
* Get echo canceller state
*/
gchar*
dbus_get_echo_cancel_state()
{
gchar* state = "";
GError* error = NULL;
org_sflphone_SFLphone_ConfigurationManager_get_echo_cancel_state(configurationManagerProxy, &state, &error);
if(error) {
ERROR("DBus: Failed to call get_echo_cancel_state() on ConfigurationManager: %s", error->message);
g_error_free(error);
}
return state;
}
/**
* Set echo canceller state
*/
void
dbus_set_echo_cancel_state(gchar* state)
{
GError* error = NULL;
org_sflphone_SFLphone_ConfigurationManager_set_echo_cancel_state(
configurationManagerProxy, state, &error);
if (error)
{
ERROR("Failed to call set_echo_cancel_state() on ConfigurationManager: %s", error->message);
g_error_free(error);
}
}
/**
* Get noise reduction state
*/
gchar*
dbus_get_noise_suppress_state()
{
gchar* state = "";
GError* error = NULL;
org_sflphone_SFLphone_ConfigurationManager_get_noise_suppress_state(configurationManagerProxy, &state, &error);
if(error) {
ERROR("DBus: Failed to call get_noise_suppress_state() on ConfigurationManager: %s", error->message);
g_error_free(error);
}
return state;
}
/**
* Set echo canceller state
*/
void
dbus_set_noise_suppress_state(gchar* state)
{
GError* error = NULL;
org_sflphone_SFLphone_ConfigurationManager_set_noise_suppress_state(
configurationManagerProxy, state, &error);
if (error)
{
ERROR("Failed to call set_noise_suppress_state() on ConfigurationManager: %s", error->message);
g_error_free(error);
}
}
gchar*
dbus_get_ringtone_choice()
{
......
......@@ -315,6 +315,32 @@ int dbus_get_audio_device_index(const gchar* name);
*/
gchar* dbus_get_current_audio_output_plugin();
/**
* ConfigurationManager - Get the current state of echo canceller
* @return gchar* The state (enabled/disabled)
*/
gchar *dbus_get_echo_cancel_state(void);
/**
* ConfigurationManager - Set the crrent state of echo canceller
* @param gchar* The state (enabled/disabled)
*/
void dbus_set_echo_cancel_state(gchar *state);
/**
* ConfigurationManager - Get the current noise suppressor state
* @return gchar* The state (enabled/disabled)
*/
gchar *dbus_get_noise_suppress_state(void);
/**
* ConfigurationManager - Set the current noise suppressor state
* @param gchar* The state (enabled/disabled)
*/
void dbus_set_noise_suppress_state(gchar *state);
/**
* ConfigurationManager - Query to server to
* know if MD5 credential hashing is enabled.
......
......@@ -59,6 +59,9 @@ AlsaLayer::AlsaLayer (ManagerImpl* manager)
// _audioThread = new AudioThread (this);
// _audioThread = NULL;
_urgentRingBuffer.createReadPointer();
AudioLayer::_echocancelstate = true;
AudioLayer::_noisesuppressstate = true;
}
// Destructor
......@@ -71,12 +74,6 @@ AlsaLayer::~AlsaLayer (void)
delete _converter;
_converter = NULL;
}
delete AudioLayer::_echoCancel;
AudioLayer::_echoCancel = NULL;
delete AudioLayer::_echoCanceller;
AudioLayer::_echoCanceller = NULL;
}
bool
......@@ -141,6 +138,9 @@ AlsaLayer::openDevice (int indexIn, int indexOut, int indexRing, int sampleRate,
AudioLayer::_echoCancel = new EchoCancel();
AudioLayer::_echoCanceller = new AudioProcessing(static_cast<Algorithm *>(_echoCancel));
AudioLayer::_echoCancel->setEchoCancelState(AudioLayer::_echocancelstate);
AudioLayer::_echoCancel->setNoiseSuppressState(AudioLayer::_noisesuppressstate);
AudioLayer::_dcblocker = new DcBlocker();
AudioLayer::_audiofilter = new AudioProcessing(static_cast<Algorithm *>(_dcblocker));
......@@ -254,6 +254,27 @@ bool AlsaLayer::isCaptureActive (void)
return false;
}
void AlsaLayer::setEchoCancelState(bool state)
{
// if a stream already running
if(AudioLayer::_echoCancel)
_echoCancel->setEchoCancelState(state);
AudioLayer::_echocancelstate = state;
}
void AlsaLayer::setNoiseSuppressState(bool state)
{
// if a stream already opened
if(AudioLayer::_echoCancel)
_echoCancel->setNoiseSuppressState(state);
AudioLayer::_noisesuppressstate = state;
}
//////////////////////////////////////////////////////////////////////////////////////////////
///////////////// ALSA PRIVATE FUNCTIONS ////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
......
......@@ -154,6 +154,30 @@ class AlsaLayer : public AudioLayer {
bool isCaptureActive (void);
/**
* Get the echo canceller state
* @return true if echo cancel activated
*/
virtual bool getEchoCancelState(void) { return AudioLayer::_echocancelstate; }
/**
* Set the echo canceller state
* @param state true if echocancel active, false elsewhere
*/
virtual void setEchoCancelState(bool state);
/**
* Get the noise suppressor state
* @return true if noise suppressor activated
*/
virtual bool getNoiseSuppressState(void) { return AudioLayer::_noisesuppressstate; }
/**
* Set the noise suppressor state
* @param state true if noise suppressor active, false elsewhere
*/
virtual void setNoiseSuppressState(bool state);
private:
// Copy Constructor
......
......@@ -232,6 +232,30 @@ class AudioLayer {
*/
inline Recordable* getRecorderInstance (void) {return _recorder;}
/**
* Get the echo canceller state
* @return true if echo cancel activated
*/
virtual bool getEchoCancelState(void) = 0;
/**
* Set the echo canceller state
* @param state true if echocancel active, false elsewhere
*/
virtual void setEchoCancelState(bool state) = 0;
/**
* Get the noise suppressor state
* @return true if noise suppressor activated
*/
virtual bool getNoiseSuppressState(void) = 0;
/**
* Set the noise suppressor state
* @param state true if noise suppressor active, false elsewhere
*/
virtual void setNoiseSuppressState(bool state) = 0;
/**
* Get the mutex lock for the entire audio layer
*/
......@@ -325,6 +349,10 @@ class AudioLayer {
DcBlocker *_dcblocker;
AudioProcessing *_audiofilter;
bool _echocancelstate;
bool _noisesuppressstate;
};
#endif // _AUDIO_LAYER_H_
......@@ -55,7 +55,9 @@ EchoCancel::EchoCancel(int smplRate, int frameLength) : _samplingRate(smplRate),
_spkrAdaptSize(SPKR_ADAPT_SIZE),
_micAdaptSize(MIC_ADAPT_SIZE),
_correlationSize(0),
_processedByte(0)
_processedByte(0),
_echoActive(true),
_noiseActive(true)
{
_debug("EchoCancel: Instantiate echo canceller");
......@@ -265,7 +267,8 @@ int EchoCancel::process(SFLDataFormat *inputData, SFLDataFormat *outputData, int
// spkrFile->write((const char *)_tmpSpkr, byteSize);
// Remove noise
speex_preprocess_run(_noiseState, _tmpMic);
if(_noiseActive)
speex_preprocess_run(_noiseState, _tmpMic);
// Processed echo cancellation
performEchoCancel(_tmpMic, _tmpSpkr, _tmpOut);
......@@ -284,8 +287,6 @@ int EchoCancel::process(SFLDataFormat *inputData, SFLDataFormat *outputData, int
++nbFrame;
}
// _event.reset();
return nbFrame * _smplPerFrame;
}
......@@ -337,10 +338,11 @@ void EchoCancel::performEchoCancel(SFLDataFormat *micData, SFLDataFormat *spkrDa
// lowpass filtering
float amplify = (_lastAmplFactor + _amplFactor) / 2;
_lastAmplFactor = _amplFactor;
amplifySignal(micData+(k*_smplPerSeg), outputData+(k*_smplPerSeg), amplify);
if(!_echoActive)
amplify = 1.0;
// amplifySignal(micData+(k*_smplPerSeg), outputData+(k*_smplPerSeg), 1.0);
amplifySignal(micData+(k*_smplPerSeg), outputData+(k*_smplPerSeg), amplify);
}
......@@ -353,7 +355,7 @@ void EchoCancel::performEchoCancel(SFLDataFormat *micData, SFLDataFormat *spkrDa
void EchoCancel::updateEchoCancel(SFLDataFormat *micData, SFLDataFormat *spkrData) {
// TODO: we should find a way to normalize signal at this point
int micLvl = computeAmplitudeLevel(micData, _smplPerSeg) / 10;
int micLvl = computeAmplitudeLevel(micData, _smplPerSeg) / 6;
int spkrLvl = computeAmplitudeLevel(spkrData, _smplPerSeg);
// Add 1 to make sure we are not dividing by 0
......
......@@ -116,6 +116,14 @@ class EchoCancel : public Algorithm {
*/
void setSamplingRate(int smplRate);
void setEchoCancelState(bool state) { _echoActive = state; }
bool getEchoCancelState(void) { return _echoActive; }
void setNoiseSuppressState(bool state) { _noiseActive = state; }
bool getNoiseSuppressState(void) { return _noiseActive; }
private:
/**
......@@ -311,7 +319,15 @@ class EchoCancel : public Algorithm {
*/
SpeexPreprocessState *_noiseState;
ost::Event _event;
/**
* true if noise suppressor is active, false elsewhere
*/
bool _echoActive;
/**
* true if noise suppressor is active, false elsewhere
*/
bool _noiseActive;
};
......
......@@ -244,7 +244,7 @@ void MainBuffer::unBindCallID (CallID call_id1, CallID call_id2)
void MainBuffer::unBindAll (CallID call_id)
{
// ost::MutexLock guard (_mutex);
// ost::MutexLock guard (_mutex);
CallIDSet* callid_set = getCallIDSet (call_id);
......@@ -271,7 +271,7 @@ void MainBuffer::unBindAll (CallID call_id)
int MainBuffer::putData (void *buffer, int toCopy, unsigned short volume, CallID call_id)
{
// ost::MutexLock guard (_mutex);
// ost::MutexLock guard (_mutex);
RingBuffer* ring_buffer = getRingBuffer (call_id);
......@@ -298,7 +298,7 @@ int MainBuffer::putData (void *buffer, int toCopy, unsigned short volume, CallID
int MainBuffer::availForPut (CallID call_id)
{
// ost::MutexLock guard (_mutex);
// ost::MutexLock guard (_mutex);
RingBuffer* ringbuffer = getRingBuffer (call_id);
......
......@@ -257,6 +257,9 @@ PulseLayer::PulseLayer (ManagerImpl* manager)
is_started = false;
AudioLayer::_echocancelstate = true;
AudioLayer::_noisesuppressstate = true;
/*
captureFile = new ofstream("captureFile", ofstream::binary);
captureRsmplFile = new ofstream("captureRsmplFile", ofstream::binary);
......@@ -760,6 +763,25 @@ void PulseLayer::processData (void)
}
void PulseLayer::setEchoCancelState(bool state)
{
// if a stream already running
if(AudioLayer::_echoCancel)
_echoCancel->setEchoCancelState(state);
AudioLayer::_echocancelstate = state;
}
void PulseLayer::setNoiseSuppressState(bool state)
{
// if a stream already opened
if(AudioLayer::_echoCancel)
_echoCancel->setNoiseSuppressState(state);
AudioLayer::_noisesuppressstate = state;
}
void PulseLayer::writeToSpeaker (void)
{
......
......@@ -177,6 +177,30 @@ class PulseLayer : public AudioLayer {
void processRingtoneData( void );
void processData(void);
/**
* Get the echo canceller state
* @return true if echo cancel activated
*/
bool getEchoCancelState(void) { return AudioLayer::_echocancelstate; }
/**
* Set the echo canceller state
* @param state true if echocancel active, false elsewhere
*/
void setEchoCancelState(bool state);
/**
* Get the noise suppressor state
* @return true if noise suppressor activated
*/
bool getNoiseSuppressState(void) { return AudioLayer::_noisesuppressstate; }
/**
* Set the noise suppressor state
* @param state true if noise suppressor active, false elsewhere
*/
void setNoiseSuppressState(bool state);
private:
// Copy Constructor
......
......@@ -574,6 +574,36 @@
</arg>
</method>
<method name="getEchoCancelState" tp:name-for-bindings="getEchoCancelState">
<tp:docstring>
</tp:docstring>
<arg type="s" name="state" direction="out">
<tp:docstring>
</tp:docstring>
</arg>
</method>
<method name="setEchoCancelState" tp:name-for-bindings="setEchoCancelState">
<tp:docstring>
</tp:docstring>
<arg type="s" name="state" direction="in">
</arg>
</method>
<method name="getNoiseSuppressState" tp:name-for-bindings="getNoiseSuppressState">
<tp:docstring>
</tp:docstring>
<arg type="s" name="state" direction="out">
<tp:docstring>
</tp:docstring>
</arg>
</method>
<method name="setNoiseSuppressState" tp:name-for-binding="setNoiseSuppressState">
<arg type="s" name="state" direction="in">
</arg>
</method>
<!-- General Settings Panel -->
<method name="isMd5CredentialHashing" tp:name-for-bindings="isMd5CredentialHashing">
......
......@@ -568,6 +568,22 @@ std::string ConfigurationManager::getCurrentAudioOutputPlugin(void) {
return Manager::instance().getCurrentAudioOutputPlugin();
}
std::string ConfigurationManager::getEchoCancelState(void) {
return Manager::instance().getEchoCancelState();
}
void ConfigurationManager::setEchoCancelState(const std::string& state) {
Manager::instance().setEchoCancelState(state);
}
std::string ConfigurationManager::getNoiseSuppressState(void) {
return Manager::instance().getNoiseSuppressState();
}
void ConfigurationManager::setNoiseSuppressState(const std::string& state) {
Manager::instance().setNoiseSuppressState(state);
}
std::vector<std::string> ConfigurationManager::getPlaybackDeviceList() {
std::vector<std::string> ret;
return ret;
......
......@@ -86,6 +86,10 @@ public:
std::vector< std::string > getCurrentAudioDevicesIndex();
int32_t getAudioDeviceIndex(const std::string& name);
std::string getCurrentAudioOutputPlugin( void );
std::string getEchoCancelState(void);
void setEchoCancelState(const std::string& state);
std::string getNoiseSuppressState(void);
void setNoiseSuppressState(const std::string& state);
std::vector< std::string > getToneLocaleList( );
......
......@@ -2711,6 +2711,74 @@ std::string ManagerImpl::getCurrentAudioOutputPlugin (void) {
return getConfigString(AUDIO, ALSA_PLUGIN);
}
std::string ManagerImpl::getEchoCancelState(void) {
// echo canceller is disabled by default
bool isEnabled = false;
if(_audiodriver) {
isEnabled = _audiodriver->getEchoCancelState();
}
std::string state("");
if(isEnabled)
state = "enabled";
else
state = "disabled";
return state;
}
void ManagerImpl::setEchoCancelState(std::string state) {
_debug("Manager: Set echo suppress state: %s", state.c_str());
bool isEnabled = false;
if(state.compare("enabled") == 0)
isEnabled = true;
else
isEnabled = false;
if(_audiodriver) {
_audiodriver->setEchoCancelState(isEnabled);
}
}
std::string ManagerImpl::getNoiseSuppressState(void) {
// noise suppress disabled by default
bool isEnabled = false;
if(_audiodriver) {
isEnabled = _audiodriver->getNoiseSuppressState();
}
std::string state("");
if(isEnabled)
state = "enabled";
else
state = "disabled";
return state;
}
void ManagerImpl::setNoiseSuppressState(std::string state) {
_debug("Manager: Set noise suppress state: %s", state.c_str());
bool isEnabled = false;
if(state.compare("enabled") == 0)
isEnabled = true;
else
isEnabled = false;