mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-21 21:28:08 +00:00
equalizer mostly works.
git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@538 3f6dc0c8-ddfe-455d-9043-3cd528dc4637
This commit is contained in:
parent
233057823b
commit
769e7d10d8
8 changed files with 271 additions and 69 deletions
|
|
@ -54,6 +54,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
#include <mediastreamer2/mscommon.h>
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 (x<SHL32(EXTEND32(1), 15))
|
||||
{
|
||||
return _spx_cos_pi_2(EXTRACT16(x));
|
||||
return _ms_cos_pi_2(EXTRACT16(x));
|
||||
} else {
|
||||
return NEG32(_spx_cos_pi_2(EXTRACT16(65536-x)));
|
||||
return NEG32(_ms_cos_pi_2(EXTRACT16(65536-x)));
|
||||
}
|
||||
} else {
|
||||
if (x&0x0000ffff)
|
||||
|
|
@ -190,13 +190,13 @@ static inline spx_word16_t spx_cos_norm(spx_word32_t x)
|
|||
}
|
||||
|
||||
#else
|
||||
#define spx_cos_norm(x) (cos((.5f*M_PI)*(x)))
|
||||
#define ms_cos_norm(x) (cos((.5f*M_PI)*(x)))
|
||||
#endif
|
||||
|
||||
#define kf_cexp2(x,phase) \
|
||||
do{ \
|
||||
(x)->r = 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)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <sys/types.h>
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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<N;++i){
|
||||
xi=x[i];
|
||||
mem[0]=xi;
|
||||
/* accumulate and shift within the same loop*/
|
||||
acc=mem[ord-1]*num[ord-1];
|
||||
for(j=ord-2;j>=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<N;++i){
|
||||
xi=x[i];
|
||||
mem[0]=xi;
|
||||
/* accumulate and shift memories within the same loop*/
|
||||
acc=(mem[ord-1]*(ms_word32_t)num[ord-1])>>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;i<len;i++)
|
||||
{
|
||||
if (in[i]>max_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<len;i++)
|
||||
{
|
||||
out[i] = SHL16(in[i], shift);
|
||||
}
|
||||
return shift;
|
||||
}
|
||||
|
||||
static void renorm_range(ms_word16_t *in, ms_word16_t *out, int shift, int len)
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<len;i++)
|
||||
{
|
||||
out[i] = PSHR16(in[i], shift);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "kiss_fftr.h"
|
||||
#include "kiss_fft.h"
|
||||
|
|
|
|||
|
|
@ -22,7 +22,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
#include <math.h>
|
||||
|
||||
#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;i<s->nfft;i+=2)
|
||||
s->fft_cpx[i]=GAIN_ZERODB;
|
||||
ms_word16_t val=GAIN_ZERODB/s->nfft;
|
||||
s->fft_cpx[0]=val;
|
||||
for(i=1;i<s->nfft;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;i<half;++i){
|
||||
tmp=s[i];
|
||||
s[i]=s[i+half];
|
||||
s[i+half]=tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*hamming:
|
||||
* 0.54 - 0.46*cos(2*M_PI*t/T)
|
||||
|
|
@ -127,7 +153,7 @@ static void dump_table(ms_word16_t *t, int len){
|
|||
* 0.42 - 0.5*cos(2*M_PI*t/T) + 0.08*cos(4*M_PI*t/T)
|
||||
*/
|
||||
|
||||
static void apodize(ms_word16_t *s, int len){
|
||||
static void norm_and_apodize(ms_word16_t *s, int len){
|
||||
int i;
|
||||
float x;
|
||||
float w;
|
||||
|
|
@ -140,10 +166,16 @@ static void apodize(ms_word16_t *s, int len){
|
|||
|
||||
static void equalizer_state_compute_impulse_response(EqualizerState *s){
|
||||
void *fft_handle=ms_fft_init(s->nfft);
|
||||
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 }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ const char *usage="mediastream --local <port> --remote <ip:port> --payload <payl
|
|||
"[ --bitrate <bits per seconds>]\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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue