Commit c484694f authored by Alexandre Savard's avatar Alexandre Savard
Browse files

[#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 ...@@ -47,6 +47,7 @@ GtkWidget *codecTreeView; // View used instead of store to get access to select
GtkWidget *pulse; GtkWidget *pulse;
GtkWidget *alsabox; GtkWidget *alsabox;
GtkWidget *alsa_conf; GtkWidget *alsa_conf;
GtkWidget *noisebox;
GtkWidget *noise_conf; GtkWidget *noise_conf;
// Codec properties ID // Codec properties ID
...@@ -776,6 +777,48 @@ select_audio_manager( void ) ...@@ -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* alsa_box()
{ {
GtkWidget *ret; GtkWidget *ret;
...@@ -886,30 +929,37 @@ GtkWidget* alsa_box() ...@@ -886,30 +929,37 @@ GtkWidget* alsa_box()
GtkWidget* noise_box() GtkWidget* noise_box()
{ {
GtkWidget *ret; GtkWidget *ret;
GtkWidget *enableVoiceActivity; GtkWidget *enableEchoCancel;
GtkWidget *enableNoiseReduction; GtkWidget *enableNoiseReduction;
gboolean echocancelActive, noisesuppressActive;
gchar *state;
// check button to enable ringtones
ret = gtk_hbox_new( TRUE , 1); 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")); gtk_box_pack_start( GTK_BOX(ret), enableEchoCancel, TRUE , TRUE , 1);
//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);
enableNoiseReduction = gtk_check_button_new_with_mnemonic( _("_Noise Reduction (Narrow-Band Companding)")); enableNoiseReduction = gtk_check_button_new_with_mnemonic( _("_Noise Reduction"));
//TODO Use the value from D-BUS state = dbus_get_noise_suppress_state();
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(enableNoiseReduction), FALSE ); 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); gtk_box_pack_start( GTK_BOX(ret) , enableNoiseReduction , TRUE , TRUE , 1);
//TODO Enable it
// gtk_widget_set_sensitive(GTK_WIDGET(noise_conf), FALSE); g_signal_connect(G_OBJECT(enableNoiseReduction), "clicked", active_noise_suppress, NULL);
//TODO Add a callback function
//g_signal_connect(G_OBJECT( enableNoiseReduction) , "clicked" , NULL , NULL);
return ret; return ret;
} }
...@@ -1017,6 +1067,15 @@ GtkWidget* create_audio_configuration() ...@@ -1017,6 +1067,15 @@ GtkWidget* create_audio_configuration()
gtk_file_chooser_add_filter( GTK_FILE_CHOOSER( fileChooser ) , filter); 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); 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); gtk_widget_show_all(ret);
if(!pulse_audio) { if(!pulse_audio) {
......
...@@ -574,6 +574,36 @@ ...@@ -574,6 +574,36 @@
</arg> </arg>
</method> </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 --> <!-- General Settings Panel -->
<method name="isMd5CredentialHashing" tp:name-for-bindings="isMd5CredentialHashing"> <method name="isMd5CredentialHashing" tp:name-for-bindings="isMd5CredentialHashing">
......
...@@ -1503,6 +1503,72 @@ dbus_get_current_audio_output_plugin() ...@@ -1503,6 +1503,72 @@ dbus_get_current_audio_output_plugin()
return 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* gchar*
dbus_get_ringtone_choice() dbus_get_ringtone_choice()
{ {
......
...@@ -315,6 +315,32 @@ int dbus_get_audio_device_index(const gchar* name); ...@@ -315,6 +315,32 @@ int dbus_get_audio_device_index(const gchar* name);
*/ */
gchar* dbus_get_current_audio_output_plugin(); 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 * ConfigurationManager - Query to server to
* know if MD5 credential hashing is enabled. * know if MD5 credential hashing is enabled.
......
...@@ -59,6 +59,9 @@ AlsaLayer::AlsaLayer (ManagerImpl* manager) ...@@ -59,6 +59,9 @@ AlsaLayer::AlsaLayer (ManagerImpl* manager)
// _audioThread = new AudioThread (this); // _audioThread = new AudioThread (this);
// _audioThread = NULL; // _audioThread = NULL;
_urgentRingBuffer.createReadPointer(); _urgentRingBuffer.createReadPointer();
AudioLayer::_echocancelstate = true;
AudioLayer::_noisesuppressstate = true;
} }
// Destructor // Destructor
...@@ -71,12 +74,6 @@ AlsaLayer::~AlsaLayer (void) ...@@ -71,12 +74,6 @@ AlsaLayer::~AlsaLayer (void)
delete _converter; delete _converter;
_converter = NULL; _converter = NULL;
} }
delete AudioLayer::_echoCancel;
AudioLayer::_echoCancel = NULL;
delete AudioLayer::_echoCanceller;
AudioLayer::_echoCanceller = NULL;
} }
bool bool
...@@ -141,6 +138,9 @@ AlsaLayer::openDevice (int indexIn, int indexOut, int indexRing, int sampleRate, ...@@ -141,6 +138,9 @@ AlsaLayer::openDevice (int indexIn, int indexOut, int indexRing, int sampleRate,
AudioLayer::_echoCancel = new EchoCancel(); AudioLayer::_echoCancel = new EchoCancel();
AudioLayer::_echoCanceller = new AudioProcessing(static_cast<Algorithm *>(_echoCancel)); AudioLayer::_echoCanceller = new AudioProcessing(static_cast<Algorithm *>(_echoCancel));
AudioLayer::_echoCancel->setEchoCancelState(AudioLayer::_echocancelstate);
AudioLayer::_echoCancel->setNoiseSuppressState(AudioLayer::_noisesuppressstate);
AudioLayer::_dcblocker = new DcBlocker(); AudioLayer::_dcblocker = new DcBlocker();
AudioLayer::_audiofilter = new AudioProcessing(static_cast<Algorithm *>(_dcblocker)); AudioLayer::_audiofilter = new AudioProcessing(static_cast<Algorithm *>(_dcblocker));
...@@ -254,6 +254,27 @@ bool AlsaLayer::isCaptureActive (void) ...@@ -254,6 +254,27 @@ bool AlsaLayer::isCaptureActive (void)
return false; 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 //////////////////////////////////////////////// ///////////////// ALSA PRIVATE FUNCTIONS ////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////
......
...@@ -154,6 +154,30 @@ class AlsaLayer : public AudioLayer { ...@@ -154,6 +154,30 @@ class AlsaLayer : public AudioLayer {
bool isCaptureActive (void); 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: private:
// Copy Constructor // Copy Constructor
......
...@@ -232,6 +232,30 @@ class AudioLayer { ...@@ -232,6 +232,30 @@ class AudioLayer {
*/ */
inline Recordable* getRecorderInstance (void) {return _recorder;} 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 * Get the mutex lock for the entire audio layer
*/ */
...@@ -325,6 +349,10 @@ class AudioLayer { ...@@ -325,6 +349,10 @@ class AudioLayer {
DcBlocker *_dcblocker; DcBlocker *_dcblocker;
AudioProcessing *_audiofilter; AudioProcessing *_audiofilter;
bool _echocancelstate;
bool _noisesuppressstate;
}; };
#endif // _AUDIO_LAYER_H_ #endif // _AUDIO_LAYER_H_
...@@ -55,7 +55,9 @@ EchoCancel::EchoCancel(int smplRate, int frameLength) : _samplingRate(smplRate), ...@@ -55,7 +55,9 @@ EchoCancel::EchoCancel(int smplRate, int frameLength) : _samplingRate(smplRate),
_spkrAdaptSize(SPKR_ADAPT_SIZE), _spkrAdaptSize(SPKR_ADAPT_SIZE),
_micAdaptSize(MIC_ADAPT_SIZE), _micAdaptSize(MIC_ADAPT_SIZE),
_correlationSize(0), _correlationSize(0),
_processedByte(0) _processedByte(0),
_echoActive(true),
_noiseActive(true)
{ {
_debug("EchoCancel: Instantiate echo canceller"); _debug("EchoCancel: Instantiate echo canceller");
...@@ -265,7 +267,8 @@ int EchoCancel::process(SFLDataFormat *inputData, SFLDataFormat *outputData, int ...@@ -265,7 +267,8 @@ int EchoCancel::process(SFLDataFormat *inputData, SFLDataFormat *outputData, int
// spkrFile->write((const char *)_tmpSpkr, byteSize); // spkrFile->write((const char *)_tmpSpkr, byteSize);
// Remove noise // Remove noise
speex_preprocess_run(_noiseState, _tmpMic); if(_noiseActive)
speex_preprocess_run(_noiseState, _tmpMic);
// Processed echo cancellation // Processed echo cancellation
performEchoCancel(_tmpMic, _tmpSpkr, _tmpOut); performEchoCancel(_tmpMic, _tmpSpkr, _tmpOut);
...@@ -284,8 +287,6 @@ int EchoCancel::process(SFLDataFormat *inputData, SFLDataFormat *outputData, int ...@@ -284,8 +287,6 @@ int EchoCancel::process(SFLDataFormat *inputData, SFLDataFormat *outputData, int
++nbFrame; ++nbFrame;
} }
// _event.reset();
return nbFrame * _smplPerFrame; return nbFrame * _smplPerFrame;
} }
...@@ -337,10 +338,11 @@ void EchoCancel::performEchoCancel(SFLDataFormat *micData, SFLDataFormat *spkrDa ...@@ -337,10 +338,11 @@ void EchoCancel::performEchoCancel(SFLDataFormat *micData, SFLDataFormat *spkrDa
// lowpass filtering // lowpass filtering
float amplify = (_lastAmplFactor + _amplFactor) / 2; float amplify = (_lastAmplFactor + _amplFactor) / 2;
_lastAmplFactor = _amplFactor; _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 ...@@ -353,7 +355,7 @@ void EchoCancel::performEchoCancel(SFLDataFormat *micData, SFLDataFormat *spkrDa
void EchoCancel::updateEchoCancel(SFLDataFormat *micData, SFLDataFormat *spkrData) { void EchoCancel::updateEchoCancel(SFLDataFormat *micData, SFLDataFormat *spkrData) {
// TODO: we should find a way to normalize signal at this point // 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); int spkrLvl = computeAmplitudeLevel(spkrData, _smplPerSeg);
// Add 1 to make sure we are not dividing by 0 // Add 1 to make sure we are not dividing by 0
......
...@@ -116,6 +116,14 @@ class EchoCancel : public Algorithm { ...@@ -116,6 +116,14 @@ class EchoCancel : public Algorithm {
*/ */
void setSamplingRate(int smplRate); 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: private:
/** /**
...@@ -311,7 +319,15 @@ class EchoCancel : public Algorithm { ...@@ -311,7 +319,15 @@ class EchoCancel : public Algorithm {
*/ */
SpeexPreprocessState *_noiseState; 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) ...@@ -244,7 +244,7 @@ void MainBuffer::unBindCallID (CallID call_id1, CallID call_id2)
void MainBuffer::unBindAll (CallID call_id) void MainBuffer::unBindAll (CallID call_id)
{ {
// ost::MutexLock guard (_mutex); // ost::MutexLock guard (_mutex);
CallIDSet* callid_set = getCallIDSet (call_id); CallIDSet* callid_set = getCallIDSet (call_id);
...@@ -271,7 +271,7 @@ void MainBuffer::unBindAll (CallID 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) int MainBuffer::putData (void *buffer, int toCopy, unsigned short volume, CallID call_id)
{