110
static int volume_set_sample_rate(MSFilter *f, void *arg){
111
Volume *v=(Volume*)f->data;
112
v->sample_rate=*(int*)arg;
66
116
static int volume_get_linear(MSFilter *f, void *arg){
67
117
float *farg=(float*)arg;
68
118
Volume *v=(Volume*)f->data;
69
119
*farg=(v->energy+1)/max_e;
123
static void volume_agc_process(Volume *v, mblk_t *om){
124
speex_preprocess_run(v->speex_pp,(int16_t*)om->b_rptr);
128
static void volume_agc_process(Volume *v, mblk_t *om){
73
134
static inline float compute_gain(float static_gain, float energy, float weight){
74
135
float ret=static_gain*(1 - (energy*weight));
99
170
v->ea_active=TRUE;
103
v->gain=(v->gain*(1-v->gain_k)) + (v->gain_k*gain);
173
if (curtime!=0 && (curtime-v->sustain_start)<v->sustain_time){
175
}else{/*restore normal gain*/
181
v->last_peer_en=peer_e;
107
183
ms_message("ea_active=%i, peer_e=%f gain=%f gain_k=%f force=%f",v->ea_active,peer_e,v->gain, v->gain_k,v->force);
186
static void volume_noise_gate_process(Volume *v , float energy, mblk_t *om){
187
int nsamples=((om->b_wptr-om->b_rptr)/2);
188
if ((energy/max_e)<v->ng_threshold){
189
v->ng_noise_dur+=(nsamples*1000)/v->sample_rate;
190
if (v->ng_noise_dur>v->ng_cut_time){
195
/*let the target gain unchanged, ie let the echo-limiter choose the gain*/
110
199
static int volume_set_gain(MSFilter *f, void *arg){
111
200
float *farg=(float*)arg;
112
201
Volume *v=(Volume*)f->data;
113
v->gain=v->static_gain=*farg;
202
v->gain=v->static_gain=v->target_gain=*farg;
256
static int volume_set_ea_sustain(MSFilter *f, void *arg){
257
Volume *v=(Volume*)f->data;
258
v->sustain_time=*(int*)arg;
262
static int volume_enable_noise_gate(MSFilter *f, void *arg){
263
Volume *v=(Volume*)f->data;
264
v->noise_gate_enabled=*(int*)arg;
268
static int volume_set_noise_gate_threshold(MSFilter *f, void *arg){
269
Volume *v=(Volume*)f->data;
270
v->ng_threshold=*(float*)arg;
161
274
static inline int16_t saturate(float val){
162
275
return (val>32767) ? 32767 : ( (val<-32767) ? -32767 : val);
278
static float update_energy(int16_t *signal, int numsamples, float last_energy_value){
280
float en=last_energy_value;
281
for (i=0;i<numsamples;++i){
282
float s=(float)signal[i];
283
en=(s*s*coef) + (1.0-coef)*en;
288
static void apply_gain(Volume *v, mblk_t *m){
290
float gain=v->target_gain;
292
if (gain==1 && v->gain==1) return;
293
v->gain=(v->gain*(1-v->gain_k)) + (v->gain_k*gain);
294
for ( sample=(int16_t*)m->b_rptr;
295
sample<(int16_t*)m->b_wptr;
298
*sample=saturate(s*v->gain);
302
static void volume_preprocess(MSFilter *f){
303
Volume *v=(Volume*)f->data;
304
/*process agc by chunks of 10 ms*/
305
v->nsamples=(int)(0.01*(float)v->sample_rate);
307
ms_message("AGC is enabled.");
309
if (v->speex_pp==NULL){
311
v->speex_pp=speex_preprocess_state_init(v->nsamples,v->sample_rate);
312
if (speex_preprocess_ctl(v->speex_pp,SPEEX_PREPROCESS_SET_AGC,&tmp)==-1){
313
ms_warning("Speex AGC is not available.");
316
speex_preprocess_ctl(v->speex_pp,SPEEX_PREPROCESS_SET_VAD,&tmp);
317
speex_preprocess_ctl(v->speex_pp,SPEEX_PREPROCESS_SET_DENOISE,&tmp);
318
speex_preprocess_ctl(v->speex_pp,SPEEX_PREPROCESS_SET_DEREVERB,&tmp);
321
ms_error("No AGC possible, mediastreamer2 was compiled without libspeexdsp.");
165
328
static void volume_process(MSFilter *f){
168
330
Volume *v=(Volume*)f->data;
169
331
float en=v->energy;
170
while((m=ms_queue_get(f->inputs[0]))!=NULL){
171
for ( sample=(int16_t*)m->b_rptr;
172
sample<(int16_t*)m->b_wptr;
175
en=(s*s*coef) + (1.0-coef)*en;
178
volume_echo_avoider_process(v);
181
for ( sample=(int16_t*)m->b_rptr;
182
sample<(int16_t*)m->b_wptr;
185
*sample=saturate(s*v->gain);
188
ms_queue_put(f->outputs[0],m);
335
int nbytes=v->nsamples*2;
336
ms_bufferizer_put_from_queue(v->buffer,f->inputs[0]);
337
while(ms_bufferizer_get_avail(v->buffer)>=nbytes){
339
ms_bufferizer_read(v->buffer,om->b_wptr,nbytes);
341
en=update_energy((int16_t*)om->b_rptr,v->nsamples,en);
342
volume_agc_process(v,om);
345
volume_echo_avoider_process(v,f->ticker->time);
346
}else v->target_gain=v->static_gain;
348
if (v->noise_gate_enabled)
349
volume_noise_gate_process(v,en,om);
351
ms_queue_put(f->outputs[0],om);
354
/*light processing: no agc. Work in place in the input buffer*/
355
while((m=ms_queue_get(f->inputs[0]))!=NULL){
356
en=update_energy((int16_t*)m->b_rptr,(m->b_wptr-m->b_rptr)/2,en);
358
volume_echo_avoider_process(v,f->ticker->time);
359
}else v->target_gain=v->static_gain;
361
if (v->noise_gate_enabled)
362
volume_noise_gate_process(v,en,m);
364
ms_queue_put(f->outputs[0],m);
199
376
{ MS_VOLUME_SET_EA_THRESHOLD , volume_set_ea_threshold },
200
377
{ MS_VOLUME_SET_EA_SPEED , volume_set_ea_speed },
201
378
{ MS_VOLUME_SET_EA_FORCE , volume_set_ea_force },
379
{ MS_VOLUME_SET_EA_SUSTAIN, volume_set_ea_sustain },
380
{ MS_FILTER_SET_SAMPLE_RATE, volume_set_sample_rate },
381
{ MS_VOLUME_ENABLE_AGC , volume_set_agc },
382
{ MS_VOLUME_ENABLE_NOISE_GATE, volume_enable_noise_gate},
383
{ MS_VOLUME_SET_NOISE_GATE_THRESHOLD, volume_set_noise_gate_threshold},
206
388
MSFilterDesc ms_volume_desc={
207
389
.name="MSVolume",
208
.text=N_("A filter to make level measurements on 16 bits pcm audio stream"),
390
.text=N_("A filter that controls and measure sound volume"),
209
391
.id=MS_VOLUME_ID,
210
392
.category=MS_FILTER_OTHER,
213
395
.init=volume_init,
214
396
.uninit=volume_uninit,
397
.preprocess=volume_preprocess,
215
398
.process=volume_process,