Commit 2a54c9f8 authored by François Grisez's avatar François Grisez

Reworking of mediastreamer's equalizer

In order to be able to apply equlization at once on the mouth output and
the speaker input, two MSEqualizer filters are instancited at audiostream
starting.

The old 'eq_active' and 'eq_gains' linphonerc parameters have been disabled
as they are no more sufficient to set different parameters on the speaker and
microphone equalizers. Those have been replaced by four parameters that
explicitly specify the equalizer to set up.

These new parameters are 'mic_eq_active' and 'mic_eq_gains' for the microphone equalizer and
'spk_eq_active' and 'spk_eq_gains' for the speaker equalizer.

An extra parameter has also been added in audio_stream_enable_equalizer() and
audio_stream_equalizer_set_gain() in order to indicate which equalizer is
concerned by the modification.
parent e03ee356
......@@ -36,6 +36,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <mediastreamer2/zrtp.h>
#include <mediastreamer2/dtls_srtp.h>
#include <mediastreamer2/ms_srtp.h>
#include <mediastreamer2/msequalizer.h>
#define PAYLOAD_TYPE_FLAG_CAN_RECV PAYLOAD_TYPE_USER_FLAG_1
......@@ -366,7 +367,8 @@ struct _AudioStream
MSFilter *write_encoder; /* Used when the output is done via RTP */
MSFilter *read_resampler;
MSFilter *write_resampler;
MSFilter *equalizer;
MSFilter *mic_equalizer;
MSFilter *spk_equalizer;
MSFilter *dummy;
MSFilter *recv_tee;
MSFilter *recorder_mixer;
......@@ -402,7 +404,8 @@ struct _AudioStream
bool_t use_gc;
bool_t use_agc;
bool_t eq_active;
bool_t mic_eq_active;
bool_t spk_eq_active;
bool_t use_ng;/*noise gate*/
bool_t is_ec_delay_set;
};
......@@ -671,11 +674,20 @@ MS2_PUBLIC float audio_stream_get_sound_card_output_gain(const AudioStream *stre
MS2_PUBLIC void audio_stream_enable_noise_gate(AudioStream *stream, bool_t val);
/**
* enable parametric equalizer in the stream that goes to the speaker
* */
MS2_PUBLIC void audio_stream_enable_equalizer(AudioStream *stream, bool_t enabled);
* Enable a parametric equalizer
* @param[in] stream An AudioStream
* @param[in] location Location of the equalizer to enable (speaker or microphone)
* @param[in] enabled Whether the equalizer must be enabled
*/
MS2_PUBLIC void audio_stream_enable_equalizer(AudioStream *stream, EqualizerLocation location, bool_t enabled);
MS2_PUBLIC void audio_stream_equalizer_set_gain(AudioStream *stream, int frequency, float gain, int freq_width);
/**
* Apply a gain on a given frequency band.
* @param[in] stream An AudioStream
* @param[in] location Location of the concerned equalizer (speaker or microphone)
* @param[in] gain Description of the band and the gain to apply.
*/
MS2_PUBLIC void audio_stream_equalizer_set_gain(AudioStream *stream, EqualizerLocation location, const MSEqualizerGain *gain);
/**
* stop the audio streaming thread and free everything
......
......@@ -64,7 +64,8 @@ static void audio_stream_free(AudioStream *stream) {
if (stream->ec!=NULL) ms_filter_destroy(stream->ec);
if (stream->volrecv!=NULL) ms_filter_destroy(stream->volrecv);
if (stream->volsend!=NULL) ms_filter_destroy(stream->volsend);
if (stream->equalizer!=NULL) ms_filter_destroy(stream->equalizer);
if (stream->mic_equalizer) ms_filter_destroy(stream->mic_equalizer);
if (stream->spk_equalizer) ms_filter_destroy(stream->spk_equalizer);
if (stream->read_decoder != NULL) ms_filter_destroy(stream->read_decoder);
if (stream->write_encoder != NULL) ms_filter_destroy(stream->write_encoder);
if (stream->read_resampler!=NULL) ms_filter_destroy(stream->read_resampler);
......@@ -1026,36 +1027,40 @@ int audio_stream_start_from_io(AudioStream *stream, RtpProfile *profile, const c
/*create the equalizer*/
if ((stream->features & AUDIO_STREAM_FEATURE_EQUALIZER) != 0){
stream->equalizer=ms_factory_create_filter(stream->ms.factory, MS_EQUALIZER_ID);
if(stream->equalizer) {
tmp=stream->eq_active;
ms_filter_call_method(stream->equalizer,MS_EQUALIZER_SET_ACTIVE,&tmp);
ms_filter_call_method(stream->equalizer,MS_FILTER_SET_SAMPLE_RATE, &sample_rate);
stream->mic_equalizer = ms_factory_create_filter(stream->ms.factory, MS_EQUALIZER_ID);
stream->spk_equalizer = ms_factory_create_filter(stream->ms.factory, MS_EQUALIZER_ID);
if(stream->mic_equalizer) {
tmp = stream->mic_eq_active;
ms_filter_call_method(stream->mic_equalizer,MS_EQUALIZER_SET_ACTIVE,&tmp);
ms_filter_call_method(stream->mic_equalizer,MS_FILTER_SET_SAMPLE_RATE, &sample_rate);
}
}else
stream->equalizer=NULL;
if(stream->spk_equalizer) {
tmp = stream->spk_eq_active;
ms_filter_call_method(stream->spk_equalizer,MS_EQUALIZER_SET_ACTIVE,&tmp);
ms_filter_call_method(stream->spk_equalizer,MS_FILTER_SET_SAMPLE_RATE, &sample_rate);
}
}else {
stream->mic_equalizer=NULL;
stream->spk_equalizer=NULL;
}
#ifdef ANDROID
/*configure equalizer if needed*/
audio_stream_set_mic_gain_db(stream, 0);
if (stream->equalizer) {
if (stream->mic_equalizer) {
SoundDeviceDescription *device = sound_device_description_get();
if (device && device->hacks) {
const char *gains = device->hacks->equalizer;
if (gains) {
MSList *gains_list;
stream->eq_loc = MSEqualizerMic;
MSList *gains_list = ms_parse_equalizer_string(gains);
MSList *it;
ms_message("Found equalizer configuration in the devices table");
gains_list = ms_parse_equalizer_string(gains);
if (gains_list) {
MSList *it;
for (it=gains_list; it; it++) {
MSEqualizerGain *g = (MSEqualizerGain *)it->data;
ms_message("Read equalizer gains: %f(~%f) --> %f", g->frequency, g->width, g->gain);
ms_filter_call_method(stream->equalizer, MS_EQUALIZER_SET_GAIN, g);
}
ms_list_free_with_data(gains_list, ms_free);
for (it=gains_list; it; it++) {
MSEqualizerGain *g = (MSEqualizerGain *)it->data;
ms_message("Read equalizer gains: %f(~%f) --> %f", g->frequency, g->width, g->gain);
ms_filter_call_method(stream->mic_equalizer, MS_EQUALIZER_SET_GAIN, g);
}
if(gains_list) ms_list_free_with_data(gains_list, ms_free);
}
}
}
......@@ -1139,8 +1144,8 @@ int audio_stream_start_from_io(AudioStream *stream, RtpProfile *profile, const c
ms_connection_helper_link(&h, stream->read_decoder, 0, 0);
if (stream->read_resampler)
ms_connection_helper_link(&h,stream->read_resampler,0,0);
if( stream->equalizer && stream->eq_loc == MSEqualizerMic )
ms_connection_helper_link(&h,stream->equalizer, 0, 0);
if( stream->mic_equalizer)
ms_connection_helper_link(&h,stream->mic_equalizer, 0, 0);
if (stream->ec)
ms_connection_helper_link(&h,stream->ec,1,1);
if (stream->volsend)
......@@ -1166,8 +1171,8 @@ int audio_stream_start_from_io(AudioStream *stream, RtpProfile *profile, const c
ms_connection_helper_link(&h,stream->volrecv,0,0);
if (stream->recv_tee)
ms_connection_helper_link(&h,stream->recv_tee,0,0);
if (stream->equalizer && stream->eq_loc == MSEqualizerHP)
ms_connection_helper_link(&h,stream->equalizer,0,0);
if (stream->spk_equalizer)
ms_connection_helper_link(&h,stream->spk_equalizer,0,0);
if (stream->local_mixer){
ms_connection_helper_link(&h,stream->local_mixer,0,0);
setup_local_player(stream,sample_rate, nchannels);
......@@ -1569,21 +1574,51 @@ float audio_stream_get_sound_card_output_gain(const AudioStream *stream) {
return volume;
}
void audio_stream_enable_equalizer(AudioStream *stream, bool_t enabled){
stream->eq_active=enabled;
if (stream->equalizer){
int tmp=enabled;
ms_filter_call_method(stream->equalizer,MS_EQUALIZER_SET_ACTIVE,&tmp);
void audio_stream_enable_equalizer(AudioStream *stream, EqualizerLocation location, bool_t enabled) {
switch(location) {
case MSEqualizerHP:
stream->spk_eq_active = enabled;
if (stream->spk_equalizer) {
int tmp = enabled;
ms_filter_call_method(stream->spk_equalizer, MS_EQUALIZER_SET_ACTIVE, &tmp);
}
break;
case MSEqualizerMic:
stream->mic_eq_active = enabled;
if (stream->mic_equalizer) {
int tmp = enabled;
ms_filter_call_method(stream->mic_equalizer, MS_EQUALIZER_SET_ACTIVE, &tmp);
}
break;
default:
ms_error("%s(): bad equalizer location [%d]", __FUNCTION__, location);
break;
}
}
void audio_stream_equalizer_set_gain(AudioStream *stream, int frequency, float gain, int freq_width){
if (stream->equalizer){
MSEqualizerGain d;
d.frequency=(float)frequency;
d.gain=gain;
d.width=(float)freq_width;
ms_filter_call_method(stream->equalizer,MS_EQUALIZER_SET_GAIN,&d);
void audio_stream_equalizer_set_gain(AudioStream *stream, EqualizerLocation location, const MSEqualizerGain *gain){
switch(location) {
case MSEqualizerHP:
if (stream->spk_equalizer) {
MSEqualizerGain d;
d.frequency = gain->frequency;
d.gain = gain->gain;
d.width = gain->width;
ms_filter_call_method(stream->spk_equalizer, MS_EQUALIZER_SET_GAIN, &d);
}
break;
case MSEqualizerMic:
if (stream->mic_equalizer) {
MSEqualizerGain d;
d.frequency = gain->frequency;
d.gain = gain->gain;
d.width = gain->width;
ms_filter_call_method(stream->mic_equalizer, MS_EQUALIZER_SET_GAIN, &d);
}
break;
default:
ms_error("%s(): bad equalizer location [%d]", __FUNCTION__, location);
break;
}
}
......@@ -1624,8 +1659,8 @@ void audio_stream_stop(AudioStream * stream){
ms_connection_helper_unlink(&h, stream->read_decoder, 0, 0);
if (stream->read_resampler!=NULL)
ms_connection_helper_unlink(&h,stream->read_resampler,0,0);
if( stream->equalizer && stream->eq_loc == MSEqualizerMic)
ms_connection_helper_unlink(&h, stream->equalizer, 0,0);
if( stream->mic_equalizer)
ms_connection_helper_unlink(&h, stream->mic_equalizer, 0,0);
if (stream->ec!=NULL)
ms_connection_helper_unlink(&h,stream->ec,1,1);
if (stream->volsend!=NULL)
......@@ -1651,8 +1686,8 @@ void audio_stream_stop(AudioStream * stream){
ms_connection_helper_unlink(&h,stream->volrecv,0,0);
if (stream->recv_tee)
ms_connection_helper_unlink(&h,stream->recv_tee,0,0);
if (stream->equalizer!=NULL && stream->eq_loc == MSEqualizerHP)
ms_connection_helper_unlink(&h,stream->equalizer,0,0);
if (stream->spk_equalizer!=NULL)
ms_connection_helper_unlink(&h,stream->spk_equalizer,0,0);
if (stream->local_mixer){
ms_connection_helper_unlink(&h,stream->local_mixer,0,0);
dismantle_local_player(stream);
......
......@@ -995,27 +995,34 @@ static void mediastream_tool_iterate(MediastreamDatas* args) {
ms_message("\nPlease enter equalizer requests, such as 'eq active 1', 'eq active 0', 'eq 1200 0.1 200'\n");
if (fgets(commands,sizeof(commands)-1,stdin)!=NULL){
int active,freq,freq_width;
float gain;
MSEqualizerGain d = {0};
int active;
if (sscanf(commands,"eq active %i",&active)==1){
audio_stream_enable_equalizer(args->audio,active);
audio_stream_enable_equalizer(args->audio, args->audio->eq_loc, active);
ms_message("OK\n");
}else if (sscanf(commands,"eq %i %f %i",&freq,&gain,&freq_width)==3){
audio_stream_equalizer_set_gain(args->audio,freq,gain,freq_width);
}else if (sscanf(commands,"eq %f %f %f",&d.frequency,&d.gain,&d.width)==3){
audio_stream_equalizer_set_gain(args->audio, args->audio->eq_loc, &d);
ms_message("OK\n");
}else if (sscanf(commands,"eq %i %f",&freq,&gain)==2){
audio_stream_equalizer_set_gain(args->audio,freq,gain,0);
}else if (sscanf(commands,"eq %f %f",&d.frequency,&d.gain)==2){
audio_stream_equalizer_set_gain(args->audio, args->audio->eq_loc, &d);
ms_message("OK\n");
}else if (strstr(commands,"dump")){
int n=0,i;
float *t;
ms_filter_call_method(args->audio->equalizer,MS_EQUALIZER_GET_NUM_FREQUENCIES,&n);
t=(float*)alloca(sizeof(float)*n);
ms_filter_call_method(args->audio->equalizer,MS_EQUALIZER_DUMP_STATE,t);
for(i=0;i<n;++i){
if (fabs(t[i]-1)>0.01){
ms_message("%i:%f:0 ",(i*args->pt->clock_rate)/(2*n),t[i]);
MSFilter *equalizer = NULL;
if(args->audio->eq_loc == MSEqualizerHP) {
equalizer = args->audio->spk_equalizer;
} else if(args->audio->eq_loc == MSEqualizerMic) {
equalizer = args->audio->mic_equalizer;
}
if(equalizer) {
ms_filter_call_method(equalizer,MS_EQUALIZER_GET_NUM_FREQUENCIES,&n);
t=(float*)alloca(sizeof(float)*n);
ms_filter_call_method(equalizer,MS_EQUALIZER_DUMP_STATE,t);
for(i=0;i<n;++i){
if (fabs(t[i]-1)>0.01){
ms_message("%i:%f:0 ",(i*args->pt->clock_rate)/(2*n),t[i]);
}
}
}
ms_message("\nOK\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment