mirror of https://github.com/mpv-player/mpv
new smoothing method ('#define AVG 2' to enable'n'test it)
should be better and smoother but still some glitches in it :/ git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@5026 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
0b980e55aa
commit
85aedd0005
|
@ -7,12 +7,21 @@
|
||||||
* License: GPLv2
|
* License: GPLv2
|
||||||
* Author: pl <p_l@gmx.fr> (c) 2002 and beyond...
|
* Author: pl <p_l@gmx.fr> (c) 2002 and beyond...
|
||||||
*
|
*
|
||||||
* Sources: some ideas from volnorm for xmms
|
* Sources: some ideas from volnorm plugin for xmms
|
||||||
*
|
*
|
||||||
* */
|
* */
|
||||||
|
|
||||||
#define PLUGIN
|
#define PLUGIN
|
||||||
|
|
||||||
|
/* Values for AVG:
|
||||||
|
* 1: uses a 1 value memory and coefficients new=a*old+b*cur (with a+b=1)
|
||||||
|
*
|
||||||
|
* 2: uses several samples to smooth the variations (standard weighted mean
|
||||||
|
* on past samples)
|
||||||
|
*
|
||||||
|
* */
|
||||||
|
#define AVG 1
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
@ -36,9 +45,11 @@ LIBAO_PLUGIN_EXTERN(volnorm)
|
||||||
// and has to be in [MUL_MIN, MUL_MAX]
|
// and has to be in [MUL_MIN, MUL_MAX]
|
||||||
#define MUL_INIT 1.0
|
#define MUL_INIT 1.0
|
||||||
#define MUL_MIN 0.1
|
#define MUL_MIN 0.1
|
||||||
#define MUL_MAX 15.0
|
#define MUL_MAX 5.0
|
||||||
static float mul;
|
static float mul;
|
||||||
|
|
||||||
|
|
||||||
|
#if AVG==1
|
||||||
// "history" value of the filter
|
// "history" value of the filter
|
||||||
static float lastavg;
|
static float lastavg;
|
||||||
|
|
||||||
|
@ -47,17 +58,44 @@ static float lastavg;
|
||||||
#define SMOOTH_MUL 0.06
|
#define SMOOTH_MUL 0.06
|
||||||
#define SMOOTH_LASTAVG 0.06
|
#define SMOOTH_LASTAVG 0.06
|
||||||
|
|
||||||
|
|
||||||
|
#elif AVG==2
|
||||||
|
// Size of the memory array
|
||||||
|
// FIXME: should depend on the frequency of the data (should be a few seconds)
|
||||||
|
#define NSAMPLES 128
|
||||||
|
|
||||||
|
// Indicates where to write (in 0..NSAMPLES-1)
|
||||||
|
static int idx;
|
||||||
|
// The array
|
||||||
|
static struct {
|
||||||
|
float avg; // average level of the sample
|
||||||
|
int32_t len; // sample size (weight)
|
||||||
|
} mem[NSAMPLES];
|
||||||
|
|
||||||
|
// If summing all the mem[].len is lower than MIN_SAMPLE_SIZE bytes, then we
|
||||||
|
// choose to ignore the computed value as it's not significant enough
|
||||||
|
// FIXME: should depend on the frequency of the data (0.5s maybe)
|
||||||
|
#define MIN_SAMPLE_SIZE 32000
|
||||||
|
|
||||||
|
#else
|
||||||
|
// Kab00m !
|
||||||
|
#error "Unknown AVG"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Some limits
|
// Some limits
|
||||||
#define MIN_S16 -32768
|
#define MIN_S16 -32768
|
||||||
#define MAX_S16 32767
|
#define MAX_S16 32767
|
||||||
|
|
||||||
// ideal average level
|
// "Ideal" level
|
||||||
#define MID_S16 (MAX_S16 * 0.25)
|
#define MID_S16 (MAX_S16 * 0.25)
|
||||||
|
|
||||||
// silence level
|
// Silence level
|
||||||
#define SIL_S16 (MAX_S16 * 0.02)
|
// FIXME: should be relative to the level of the samples
|
||||||
|
#define SIL_S16 (MAX_S16 * 0.01)
|
||||||
|
|
||||||
// local data
|
|
||||||
|
// Local data
|
||||||
static struct {
|
static struct {
|
||||||
int inuse; // This plugin is in use TRUE, FALSE
|
int inuse; // This plugin is in use TRUE, FALSE
|
||||||
int format; // sample fomat
|
int format; // sample fomat
|
||||||
|
@ -101,13 +139,23 @@ static void uninit(){
|
||||||
|
|
||||||
// empty buffers
|
// empty buffers
|
||||||
static void reset(){
|
static void reset(){
|
||||||
|
int i;
|
||||||
mul = MUL_INIT;
|
mul = MUL_INIT;
|
||||||
switch(ao_plugin_data.format) {
|
switch(ao_plugin_data.format) {
|
||||||
case(AFMT_S16_LE):
|
case(AFMT_S16_LE):
|
||||||
|
#if AVG==1
|
||||||
lastavg = MID_S16;
|
lastavg = MID_S16;
|
||||||
|
#elif AVG==2
|
||||||
|
for(i=0; i < NSAMPLES; ++i) {
|
||||||
|
mem[i].len = 0;
|
||||||
|
mem[i].avg = 0;
|
||||||
|
}
|
||||||
|
idx = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr,"[pl_volnorm] internal inconsistency - please bugreport.\n");
|
fprintf(stderr,"[pl_volnorm] internal inconsistency - bugreport !\n");
|
||||||
*(char *) 0 = 0;
|
*(char *) 0 = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,13 +172,17 @@ static int play(){
|
||||||
int16_t* data=(int16_t*)ao_plugin_data.data;
|
int16_t* data=(int16_t*)ao_plugin_data.data;
|
||||||
int len=ao_plugin_data.len / 2; // 16 bits samples
|
int len=ao_plugin_data.len / 2; // 16 bits samples
|
||||||
|
|
||||||
int32_t i;
|
int32_t i, tmp;
|
||||||
register int32_t tmp;
|
float curavg, newavg;
|
||||||
register float curavg;
|
|
||||||
float newavg;
|
|
||||||
float neededmul;
|
|
||||||
|
|
||||||
// average of the current samples
|
#if AVG==1
|
||||||
|
float neededmul;
|
||||||
|
#elif AVG==2
|
||||||
|
float avg;
|
||||||
|
int32_t totallen;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Evaluate current samples average level
|
||||||
curavg = 0.0;
|
curavg = 0.0;
|
||||||
for (i = 0; i < len ; ++i) {
|
for (i = 0; i < len ; ++i) {
|
||||||
tmp = data[i];
|
tmp = data[i];
|
||||||
|
@ -138,6 +190,9 @@ static int play(){
|
||||||
}
|
}
|
||||||
curavg = sqrt(curavg / (float) len);
|
curavg = sqrt(curavg / (float) len);
|
||||||
|
|
||||||
|
// Evaluate an adequate 'mul' coefficient based on previous state, current
|
||||||
|
// samples level, etc
|
||||||
|
#if AVG==1
|
||||||
if (curavg > SIL_S16) {
|
if (curavg > SIL_S16) {
|
||||||
neededmul = MID_S16 / ( curavg * mul);
|
neededmul = MID_S16 / ( curavg * mul);
|
||||||
mul = (1.0 - SMOOTH_MUL) * mul + SMOOTH_MUL * neededmul;
|
mul = (1.0 - SMOOTH_MUL) * mul + SMOOTH_MUL * neededmul;
|
||||||
|
@ -145,10 +200,27 @@ static int play(){
|
||||||
// Clamp the mul coefficient
|
// Clamp the mul coefficient
|
||||||
CLAMP(mul, MUL_MIN, MUL_MAX);
|
CLAMP(mul, MUL_MIN, MUL_MAX);
|
||||||
}
|
}
|
||||||
|
#elif AVG==2
|
||||||
|
avg = 0.0;
|
||||||
|
totallen = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < NSAMPLES; ++i) {
|
||||||
|
avg += mem[i].avg * (float) mem[i].len;
|
||||||
|
totallen += mem[i].len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totallen > MIN_SAMPLE_SIZE) {
|
||||||
|
avg /= (float) totallen;
|
||||||
|
if (avg >= SIL_S16) {
|
||||||
|
mul = (float) MID_S16 / avg;
|
||||||
|
CLAMP(mul, MUL_MIN, MUL_MAX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Scale & clamp the samples
|
// Scale & clamp the samples
|
||||||
for (i=0; i < len ; ++i) {
|
for (i = 0; i < len ; ++i) {
|
||||||
tmp = data[i] * mul;
|
tmp = mul * data[i];
|
||||||
CLAMP(tmp, MIN_S16, MAX_S16);
|
CLAMP(tmp, MIN_S16, MAX_S16);
|
||||||
data[i] = tmp;
|
data[i] = tmp;
|
||||||
}
|
}
|
||||||
|
@ -156,13 +228,17 @@ static int play(){
|
||||||
// Evaluation of newavg (not 100% accurate because of values clamping)
|
// Evaluation of newavg (not 100% accurate because of values clamping)
|
||||||
newavg = mul * curavg;
|
newavg = mul * curavg;
|
||||||
|
|
||||||
#if 0
|
// Stores computed values for future smoothing
|
||||||
printf("time = %d len = %d curavg = %6.0f lastavg = %6.0f newavg = %6.0f\n"
|
#if AVG==1
|
||||||
" needed_m = %2.2f m = %2.2f\n\n",
|
|
||||||
time(NULL), len, curavg, lastavg, newavg, neededmul, mul);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
lastavg = (1.0 - SMOOTH_LASTAVG) * lastavg + SMOOTH_LASTAVG * newavg;
|
lastavg = (1.0 - SMOOTH_LASTAVG) * lastavg + SMOOTH_LASTAVG * newavg;
|
||||||
|
//printf("\rmul=%02.1f ", mul);
|
||||||
|
#elif AVG==2
|
||||||
|
mem[idx].len = len;
|
||||||
|
mem[idx].avg = newavg;
|
||||||
|
idx = (idx + 1) % NSAMPLES;
|
||||||
|
//printf("\rmul=%02.1f (%04dKiB) ", mul, totallen/1024);
|
||||||
|
#endif
|
||||||
|
//fflush(stdout);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue