From 769e7d10d85c7eafae789aa5d1dbd5faacb9a48b Mon Sep 17 00:00:00 2001 From: smorlat Date: Wed, 15 Jul 2009 16:28:42 +0000 Subject: [PATCH] equalizer mostly works. git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@538 3f6dc0c8-ddfe-455d-9043-3cd528dc4637 --- .../include/mediastreamer2/dsptools.h | 36 ++++---- .../include/mediastreamer2/mediastream.h | 7 ++ .../include/mediastreamer2/msequalizer.h | 7 ++ linphone/mediastreamer2/src/_kiss_fft_guts.h | 18 ++-- linphone/mediastreamer2/src/audiostream.c | 27 ++++++ linphone/mediastreamer2/src/dsptools.c | 87 ++++++++++++++++++- linphone/mediastreamer2/src/equalizer.c | 74 +++++++++++++--- linphone/mediastreamer2/tests/mediastream.c | 84 +++++++++++------- 8 files changed, 271 insertions(+), 69 deletions(-) diff --git a/linphone/mediastreamer2/include/mediastreamer2/dsptools.h b/linphone/mediastreamer2/include/mediastreamer2/dsptools.h index dcca00d2a..711e075b7 100644 --- a/linphone/mediastreamer2/include/mediastreamer2/dsptools.h +++ b/linphone/mediastreamer2/include/mediastreamer2/dsptools.h @@ -54,6 +54,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include +typedef int32_t ms_int32_t; + #ifdef MS_FIXED_POINT typedef short ms_word16_t; @@ -61,13 +63,13 @@ typedef int ms_word32_t; typedef int ms_mem_t; typedef short ms_coef_t; -#define QCONST16(x,bits) ((spx_word16_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) -#define QCONST32(x,bits) ((spx_word32_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) +#define QCONST16(x,bits) ((ms_word16_t)(.5+(x)*(((ms_word32_t)1)<<(bits)))) +#define QCONST32(x,bits) ((ms_word32_t)(.5+(x)*(((ms_word32_t)1)<<(bits)))) #define NEG16(x) (-(x)) #define NEG32(x) (-(x)) -#define EXTRACT16(x) ((spx_word16_t)(x)) -#define EXTEND32(x) ((spx_word32_t)(x)) +#define EXTRACT16(x) ((ms_word16_t)(x)) +#define EXTEND32(x) ((ms_word32_t)(x)) #define SHR16(a,shift) ((a) >> (shift)) #define SHL16(a,shift) ((a) << (shift)) #define SHR32(a,shift) ((a) >> (shift)) @@ -79,22 +81,22 @@ typedef short ms_coef_t; #define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) #define SHR(a,shift) ((a) >> (shift)) -#define SHL(a,shift) ((spx_word32_t)(a) << (shift)) +#define SHL(a,shift) ((ms_word32_t)(a) << (shift)) #define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift)) #define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) -#define ADD16(a,b) ((spx_word16_t)((spx_word16_t)(a)+(spx_word16_t)(b))) -#define SUB16(a,b) ((spx_word16_t)(a)-(spx_word16_t)(b)) -#define ADD32(a,b) ((spx_word32_t)(a)+(spx_word32_t)(b)) -#define SUB32(a,b) ((spx_word32_t)(a)-(spx_word32_t)(b)) +#define ADD16(a,b) ((ms_word16_t)((ms_word16_t)(a)+(ms_word16_t)(b))) +#define SUB16(a,b) ((ms_word16_t)(a)-(ms_word16_t)(b)) +#define ADD32(a,b) ((ms_word32_t)(a)+(ms_word32_t)(b)) +#define SUB32(a,b) ((ms_word32_t)(a)-(ms_word32_t)(b)) /* result fits in 16 bits */ -#define MULT16_16_16(a,b) ((((spx_word16_t)(a))*((spx_word16_t)(b)))) +#define MULT16_16_16(a,b) ((((ms_word16_t)(a))*((ms_word16_t)(b)))) -/* (spx_word32_t)(spx_word16_t) gives TI compiler a hint that it's 16x16->32 multiply */ -#define MULT16_16(a,b) (((spx_word32_t)(spx_word16_t)(a))*((spx_word32_t)(spx_word16_t)(b))) +/* (ms_word32_t)(ms_word16_t) gives TI compiler a hint that it's 16x16->32 multiply */ +#define MULT16_16(a,b) (((ms_word32_t)(ms_word16_t)(a))*((ms_word32_t)(ms_word16_t)(b))) #define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b)))) #define MULT16_32_Q12(a,b) ADD32(MULT16_16((a),SHR((b),12)), SHR(MULT16_16((a),((b)&0x00000fff)),12)) @@ -124,10 +126,10 @@ typedef short ms_coef_t; #define MUL_16_32_R15(a,bh,bl) ADD32(MULT16_16((a),(bh)), SHR(MULT16_16((a),(bl)),15)) -#define DIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a))/((spx_word16_t)(b)))) -#define PDIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word16_t)(b)))) -#define DIV32(a,b) (((spx_word32_t)(a))/((spx_word32_t)(b))) -#define PDIV32(a,b) (((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word32_t)(b))) +#define DIV32_16(a,b) ((ms_word16_t)(((ms_word32_t)(a))/((ms_word16_t)(b)))) +#define PDIV32_16(a,b) ((ms_word16_t)(((ms_word32_t)(a)+((ms_word16_t)(b)>>1))/((ms_word16_t)(b)))) +#define DIV32(a,b) (((ms_word32_t)(a))/((ms_word32_t)(b))) +#define PDIV32(a,b) (((ms_word32_t)(a)+((ms_word16_t)(b)>>1))/((ms_word32_t)(b))) #ifdef ARM5E_ASM #error "Fix me" @@ -356,6 +358,8 @@ typedef float ms_word32_t; #endif +#define MIN16(a,b) ((a) < (b) ? (a) : (b)) /**< Maximum 16-bit value. */ + #ifdef __cplusplus extern "C"{ #endif diff --git a/linphone/mediastreamer2/include/mediastreamer2/mediastream.h b/linphone/mediastreamer2/include/mediastreamer2/mediastream.h index 3066d9e11..73335a9d3 100644 --- a/linphone/mediastreamer2/include/mediastreamer2/mediastream.h +++ b/linphone/mediastreamer2/include/mediastreamer2/mediastream.h @@ -49,12 +49,14 @@ struct _AudioStream MSFilter *ec;/*echo canceler*/ MSFilter *volsend,*volrecv; /*MSVolumes*/ MSFilter *resampler; + MSFilter *equalizer; uint64_t last_packet_count; time_t last_packet_time; EchoLimiterType el_type; /*use echo limiter: two MSVolume, measured input level controlling local output level*/ bool_t play_dtmfs; bool_t use_gc; bool_t use_agc; + bool_t eq_active; }; #ifdef __cplusplus @@ -112,6 +114,11 @@ void audio_stream_enable_automatic_gain_control(AudioStream *stream, bool_t val) void audio_stream_set_mic_gain(AudioStream *stream, float gain); +/*enable parametric equalizer in the stream that goes to the speaker*/ +void audio_stream_enable_equalizer(AudioStream *stream, bool_t enabled); + +void audio_stream_equalizer_set_gain(AudioStream *stream, int frequency, float gain); + /* stop the audio streaming thread and free everything*/ void audio_stream_stop (AudioStream * stream); diff --git a/linphone/mediastreamer2/include/mediastreamer2/msequalizer.h b/linphone/mediastreamer2/include/mediastreamer2/msequalizer.h index 2f9007352..1ebcae437 100644 --- a/linphone/mediastreamer2/include/mediastreamer2/msequalizer.h +++ b/linphone/mediastreamer2/include/mediastreamer2/msequalizer.h @@ -29,6 +29,13 @@ typedef struct _MSEqualizerGain{ #define MS_EQUALIZER_SET_GAIN MS_FILTER_METHOD(MS_EQUALIZER_ID,0,MSEqualizerGain) #define MS_EQUALIZER_GET_GAIN MS_FILTER_METHOD(MS_EQUALIZER_ID,1,MSEqualizerGain) +#define MS_EQUALIZER_SET_ACTIVE MS_FILTER_METHOD(MS_EQUALIZER_ID,2,int) +/** + * Sets the coeficient for computing how large is the frequency band around a gain setting. + * For example, setting this value to 0.4 will result in a frequency range of 800-1200 when setting + * a gain for frequency 1000 Hz. +**/ +#define MS_EQUALIZER_SET_FREQ_WIDTH_COEF MS_FILTER_METHOD(MS_EQUALIZER_ID,3,float) #endif diff --git a/linphone/mediastreamer2/src/_kiss_fft_guts.h b/linphone/mediastreamer2/src/_kiss_fft_guts.h index 9cac1a223..02ad5471f 100644 --- a/linphone/mediastreamer2/src/_kiss_fft_guts.h +++ b/linphone/mediastreamer2/src/_kiss_fft_guts.h @@ -49,7 +49,7 @@ struct kiss_fft_state{ * */ #ifdef MS_FIXED_POINT # define FRACBITS 15 -# define SAMPPROD spx_int32_t +# define SAMPPROD ms_int32_t #define SAMP_MAX 32767 #define SAMP_MIN -SAMP_MAX @@ -158,15 +158,15 @@ struct kiss_fft_state{ #define L3 8277 #define L4 -626 -static inline spx_word16_t _spx_cos_pi_2(spx_word16_t x) +static inline ms_word16_t _ms_cos_pi_2(ms_word16_t x) { - spx_word16_t x2; + ms_word16_t x2; x2 = MULT16_16_P15(x,x); return ADD16(1,MIN16(32766,ADD32(SUB16(L1,x2), MULT16_16_P15(x2, ADD32(L2, MULT16_16_P15(x2, ADD32(L3, MULT16_16_P15(L4, x2)))))))); } -static inline spx_word16_t spx_cos_norm(spx_word32_t x) +static inline ms_word16_t ms_cos_norm(ms_word32_t x) { x = x&0x0001ffff; if (x>SHL32(EXTEND32(1), 16)) @@ -175,9 +175,9 @@ static inline spx_word16_t spx_cos_norm(spx_word32_t x) { if (xr = spx_cos_norm((phase));\ - (x)->i = spx_cos_norm((phase)-32768);\ + (x)->r = ms_cos_norm((phase));\ + (x)->i = ms_cos_norm((phase)-32768);\ }while(0) diff --git a/linphone/mediastreamer2/src/audiostream.c b/linphone/mediastreamer2/src/audiostream.c index e3ae90a78..b67edadf8 100644 --- a/linphone/mediastreamer2/src/audiostream.c +++ b/linphone/mediastreamer2/src/audiostream.c @@ -30,6 +30,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "mediastreamer2/msfileplayer.h" #include "mediastreamer2/msfilerec.h" #include "mediastreamer2/msvolume.h" +#include "mediastreamer2/msequalizer.h" #ifdef INET6 #include @@ -283,6 +284,11 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char if (pt->send_fmtp!=NULL) ms_filter_call_method(stream->encoder,MS_FILTER_ADD_FMTP, (void*)pt->send_fmtp); if (pt->recv_fmtp!=NULL) ms_filter_call_method(stream->decoder,MS_FILTER_ADD_FMTP,(void*)pt->recv_fmtp); + /*create the equalizer*/ + stream->equalizer=ms_filter_new(MS_EQUALIZER_ID); + tmp=stream->eq_active; + ms_filter_call_method(stream->equalizer,MS_EQUALIZER_SET_ACTIVE,&tmp); + /* and then connect all */ /* tip: draw yourself the picture if you don't understand */ @@ -303,6 +309,8 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char ms_connection_helper_link(&h,stream->rtprecv,-1,0); ms_connection_helper_link(&h,stream->decoder,0,0); ms_connection_helper_link(&h,stream->dtmfgen,0,0); + if (stream->equalizer) + ms_connection_helper_link(&h,stream->equalizer,0,0); if (stream->volrecv) ms_connection_helper_link(&h,stream->volrecv,0,0); if (stream->ec) @@ -435,6 +443,23 @@ void audio_stream_set_mic_gain(AudioStream *stream, float gain){ "Use audio_stream_enable_gain_control() before starting the stream."); } +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_equalizer_set_gain(AudioStream *stream, int frequency, float gain){ + if (stream->equalizer){ + MSEqualizerGain d; + d.frequency=frequency; + d.gain=gain; + ms_filter_call_method(stream->equalizer,MS_EQUALIZER_SET_GAIN,&d); + } +} + void audio_stream_stop(AudioStream * stream) { if (stream->ticker){ @@ -461,6 +486,8 @@ void audio_stream_stop(AudioStream * stream) ms_connection_helper_unlink(&h,stream->rtprecv,-1,0); ms_connection_helper_unlink(&h,stream->decoder,0,0); ms_connection_helper_unlink(&h,stream->dtmfgen,0,0); + if (stream->equalizer) + ms_connection_helper_unlink(&h,stream->equalizer,0,0); if (stream->volrecv!=NULL) ms_connection_helper_unlink(&h,stream->volrecv,0,0); if (stream->ec!=NULL) diff --git a/linphone/mediastreamer2/src/dsptools.c b/linphone/mediastreamer2/src/dsptools.c index d06a7ebdb..0aff106d8 100644 --- a/linphone/mediastreamer2/src/dsptools.c +++ b/linphone/mediastreamer2/src/dsptools.c @@ -62,7 +62,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define ALLOC(var,size,type) var = alloca(sizeof(type)*(size)) -#ifdef ARCH_BFIN +#if 0 +//#ifdef ARCH_BFIN static void filter_mem16(const ms_word16_t *_x, const ms_coef_t *num, const ms_coef_t *den, ms_word16_t *_y, int N, int ord, ms_mem_t *mem) { @@ -220,7 +221,8 @@ void ms_fir_mem16(const ms_word16_t *x, const ms_coef_t *num, ms_word16_t *y, in #else - +#if 0 +/* this one comes from speex but unfortunately does not make the expected result, maybe it is mis-used.*/ void ms_fir_mem16(const ms_word16_t *x, const ms_coef_t *num, ms_word16_t *y, int N, int ord, ms_mem_t *mem) { int i,j; @@ -238,8 +240,89 @@ void ms_fir_mem16(const ms_word16_t *x, const ms_coef_t *num, ms_word16_t *y, in y[i] = yi; } } +#else + +#ifndef MS_FIXED_POINT + +void ms_fir_mem16(const ms_word16_t *x, const ms_coef_t *num, ms_word16_t *y, int N, int ord, ms_mem_t *mem){ + int i,j; + ms_word16_t xi; + ms_word32_t acc; + for(i=0;i=0;--j){ + acc+=num[j]*mem[j]; + mem[j+1]=mem[j]; + } + y[i]=acc; + } +} + +#else + +void ms_fir_mem16(const ms_word16_t *x, const ms_coef_t *num, ms_word16_t *y, int N, int ord, ms_mem_t *mem){ + int i,j; + ms_word16_t xi; + ms_word32_t acc; + int shift=0; /* REVISIT: empiric value...*/ + + for(i=0;i>shift; + for(j=ord-2;j>=0;--j){ + acc+=(((ms_word32_t)num[j])*mem[j])>>shift; + mem[j+1]=mem[j]; + } + y[i]=(ms_word16_t)SATURATE16(acc>>14,32767); + } +} + + #endif +#endif + +#endif + +#ifdef MS_FIXED_POINT +static int maximize_range(ms_word16_t *in, ms_word16_t *out, ms_word16_t bound, int len) +{ + int i, shift; + ms_word16_t max_val = 0; + for (i=0;imax_val) + max_val = in[i]; + if (-in[i]>max_val) + max_val = -in[i]; + } + shift=0; + while (max_val <= (bound>>1) && max_val != 0) + { + max_val <<= 1; + shift++; + } + for (i=0;i -#define GAIN_ZERODB 22000 +#define ABS_GAIN_ZERODB 22000 + +#ifdef MS_FIXED_POINT +#define GAIN_ZERODB ABS_GAIN_ZERODB +#else +#define GAIN_ZERODB (((float)ABS_GAIN_ZERODB)/32767.0) +#endif + + typedef struct _EqualizerState{ @@ -32,13 +40,17 @@ typedef struct _EqualizerState{ int fir_len; ms_word16_t *fir; ms_mem_t *mem; /*memories for filtering computations*/ + float width_coef; bool_t needs_update; + bool_t active; } EqualizerState; static void equalizer_state_flatten(EqualizerState *s){ int i; - for(i=0;infft;i+=2) - s->fft_cpx[i]=GAIN_ZERODB; + ms_word16_t val=GAIN_ZERODB/s->nfft; + s->fft_cpx[0]=val; + for(i=1;infft;i+=2) + s->fft_cpx[i]=val; } static EqualizerState * equalizer_state_new(int nfft){ @@ -50,7 +62,9 @@ static EqualizerState * equalizer_state_new(int nfft){ s->fir_len=s->nfft; s->fir=ms_new(ms_word16_t,s->fir_len); s->mem=ms_new0(ms_mem_t,s->fir_len); + s->width_coef=0.4; /* when setting a gain at 1000hz, we will affect 800-1200 frequency band*/ s->needs_update=TRUE; + s->active=TRUE; return s; } @@ -70,30 +84,31 @@ static int equalizer_state_hz_to_index(EqualizerState *s, int hz){ if (hz>(s->rate/2)){ hz=(s->rate/2); } - ret=hz*s->nfft/s->rate; - if (ret==s->nfft/2) ret--; + /*round to nearest integer*/ + ret=((hz*s->nfft)+(hz/2))/s->rate; + if (ret==s->nfft/2) ret=(s->nfft/2)-1; return ret; } static float gain_float(ms_word16_t val){ - return (float)val/22000.0; + return (float)val/GAIN_ZERODB; } static ms_word16_t gain_int16(float val){ - int ret=(int)(val*22000.0); + ms_word16_t ret=(val*GAIN_ZERODB); if (ret>=32767) ret=32767; return (ms_word16_t)ret; } static float equalizer_state_get(EqualizerState *s, int freqhz){ int idx=equalizer_state_hz_to_index(s,freqhz); - if (idx>=0) return gain_float(s->fft_cpx[idx*2]); + if (idx>=0) return gain_float(s->fft_cpx[idx*2])*s->nfft; return 0; } /* return the frequency band width we want to control around hz*/ static void equalizer_state_get_band(EqualizerState *s, int hz, int *low_index, int *high_index){ - int half_band=(int)((float)hz*0.1); + int half_band=(int)((float)hz*s->width_coef*0.5); *low_index=equalizer_state_hz_to_index(s,hz-half_band); *high_index=equalizer_state_hz_to_index(s,hz+half_band); } @@ -104,7 +119,7 @@ static void equalizer_state_set(EqualizerState *s, int freqhz, float gain){ equalizer_state_get_band(s,freqhz,&low,&high); for(i=low;i<=high;++i){ ms_message("Setting gain %f for freq_index %i (freqhz=%i)",gain,i,freqhz); - s->fft_cpx[i*2]=gain_int16(gain); + s->fft_cpx[1+(i*2)]=gain_int16(gain)/s->nfft; } s->needs_update=TRUE; } @@ -119,6 +134,17 @@ static void dump_table(ms_word16_t *t, int len){ #endif } +static void time_shift(ms_word16_t *s, int len){ + int i; + int half=len/2; + ms_word16_t tmp; + for (i=0;infft); + ms_message("Spectral domain:"); + dump_table(s->fft_cpx,s->nfft); ms_ifft(fft_handle,s->fft_cpx,s->fir); + ms_fft_destroy(fft_handle); ms_message("Inverse fft result:"); dump_table(s->fir,s->fir_len); - apodize(s->fir,s->fir_len); + time_shift(s->fir,s->fir_len); + ms_message("Time shifted:"); + dump_table(s->fir,s->fir_len); + norm_and_apodize(s->fir,s->fir_len); ms_message("Apodized impulse response:"); dump_table(s->fir,s->fir_len); s->needs_update=FALSE; @@ -195,7 +227,9 @@ void equalizer_process(MSFilter *f){ mblk_t *m; EqualizerState *s=(EqualizerState*)f->data; while((m=ms_queue_get(f->inputs[0]))!=NULL){ - equalizer_state_run(s,(int16_t*)m->b_rptr,(m->b_wptr-m->b_rptr)/2); + if (s->active){ + equalizer_state_run(s,(int16_t*)m->b_rptr,(m->b_wptr-m->b_rptr)/2); + } ms_queue_put(f->outputs[0],m); } } @@ -220,10 +254,24 @@ int equalizer_set_rate(MSFilter *f, void *data){ return 0; } +int equalizer_set_active(MSFilter *f, void *data){ + EqualizerState *s=(EqualizerState*)f->data; + s->active=*(int*)data; + return 0; +} + +int equalizer_set_freq_width_coef(MSFilter *f, void *data){ + EqualizerState *s=(EqualizerState*)f->data; + s->width_coef=*(float*)data; + return 0; +} + static MSFilterMethod equalizer_methods[]={ { MS_EQUALIZER_SET_GAIN , equalizer_set_gain }, { MS_EQUALIZER_GET_GAIN , equalizer_get_gain }, + { MS_EQUALIZER_SET_ACTIVE , equalizer_set_active }, { MS_FILTER_SET_SAMPLE_RATE , equalizer_set_rate }, + { MS_EQUALIZER_SET_FREQ_WIDTH_COEF, equalizer_set_freq_width_coef}, { 0 , NULL } }; diff --git a/linphone/mediastreamer2/tests/mediastream.c b/linphone/mediastreamer2/tests/mediastream.c index 065113fba..1c8dfab28 100644 --- a/linphone/mediastreamer2/tests/mediastream.c +++ b/linphone/mediastreamer2/tests/mediastream.c @@ -125,7 +125,7 @@ const char *usage="mediastream --local --remote --payload ]\n" "[ --ec (enable echo canceller)]\n" "[ --agc (enable automatic gain control)]\n"; -static void run_media_streams(int localport, const char *remote_ip, int remoteport, int payload, const char *fmtp, int jitter, bool_t ec, int bitrate, MSVideoSize vs, bool_t agc); +static void run_media_streams(int localport, const char *remote_ip, int remoteport, int payload, const char *fmtp, int jitter, bool_t ec, int bitrate, MSVideoSize vs, bool_t agc, bool_t eq); int main(int argc, char * argv[]) @@ -139,6 +139,7 @@ int main(int argc, char * argv[]) MSVideoSize vs; bool_t ec=FALSE; bool_t agc=FALSE; + bool_t eq=FALSE; /*create the rtp session */ ortp_init(); ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL); @@ -193,14 +194,16 @@ int main(int argc, char * argv[]) ec=TRUE; }else if (strcmp(argv[i],"--agc")==0){ agc=TRUE; + }else if (strcmp(argv[i],"--eq")==0){ + eq=TRUE; } } - run_media_streams(localport,ip,remoteport,payload,fmtp,jitter,ec,bitrate,vs, agc); + run_media_streams(localport,ip,remoteport,payload,fmtp,jitter,ec,bitrate,vs, agc,eq); return 0; } -void run_media_streams(int localport, const char *remote_ip, int remoteport, int payload, const char *fmtp, int jitter, bool_t ec, int bitrate, MSVideoSize vs, bool_t agc) +void run_media_streams(int localport, const char *remote_ip, int remoteport, int payload, const char *fmtp, int jitter, bool_t ec, int bitrate, MSVideoSize vs, bool_t agc, bool_t eq) { AudioStream *audio=NULL; #ifdef VIDEO_ENABLED @@ -233,6 +236,10 @@ void run_media_streams(int localport, const char *remote_ip, int remoteport, in if (audio) session=audio->session; }else{ #ifdef VIDEO_ENABLED + if (eq){ + ms_fatal("Cannot put an audio equalizer in a video stream !"); + exit(-1); + } printf("Starting video stream.\n"); video=video_stream_new(localport, ms_is_ipv6(remote_ip)); video_stream_set_sent_video_size(video,vs); @@ -247,34 +254,53 @@ void run_media_streams(int localport, const char *remote_ip, int remoteport, in printf("Error: video support not compiled.\n"); #endif } - rtp_session_register_event_queue(session,q); - while(cond) - { - int n; - for(n=0;n<100;++n){ -#ifdef WIN32 - MSG msg; - Sleep(10); - while (PeekMessage(&msg, NULL, 0, 0,1)){ - TranslateMessage(&msg); - DispatchMessage(&msg); + if (!eq){ + rtp_session_register_event_queue(session,q); + while(cond) + { + int n; + for(n=0;n<100;++n){ + #ifdef WIN32 + MSG msg; + Sleep(10); + while (PeekMessage(&msg, NULL, 0, 0,1)){ + TranslateMessage(&msg); + DispatchMessage(&msg); + } + #else + struct timespec ts; + ts.tv_sec=0; + ts.tv_nsec=10000000; + nanosleep(&ts,NULL); + #endif + #if defined(VIDEO_ENABLED) + if (video) video_stream_iterate(video); + #endif + } + ortp_global_stats_display(); + if (session){ + printf("Bandwidth usage: download=%f kbits/sec, upload=%f kbits/sec\n", + rtp_session_compute_recv_bandwidth(session)*1e-3, + rtp_session_compute_send_bandwidth(session)*1e-3); + parse_events(q); } -#else - struct timespec ts; - ts.tv_sec=0; - ts.tv_nsec=10000000; - nanosleep(&ts,NULL); -#endif -#if defined(VIDEO_ENABLED) - if (video) video_stream_iterate(video); -#endif } - ortp_global_stats_display(); - if (session){ - printf("Bandwidth usage: download=%f kbits/sec, upload=%f kbits/sec\n", - rtp_session_compute_recv_bandwidth(session)*1e-3, - rtp_session_compute_send_bandwidth(session)*1e-3); - parse_events(q); + }else{/*read from stdin equalizer commands */ + char commands[128]; + commands[127]='\0'; + printf("Please enter equalizer requests, such as 'eq active 1', 'eq active 0', 'eq 1200 0.1'\n"); + while(fgets(commands,sizeof(commands)-1,stdin)!=NULL){ + int active,freq; + float gain; + if (sscanf(commands,"eq active %i",&active)==1){ + audio_stream_enable_equalizer(audio,active); + printf("OK\n"); + }else if (sscanf(commands,"eq %i %f",&freq,&gain)==2){ + audio_stream_equalizer_set_gain(audio,freq,gain); + printf("OK\n"); + }else if (strstr(commands,"quit")){ + break; + }else printf("Cannot understand this.\n"); } }