aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar anders <anders@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-03-13 12:32:42 +0000
committerGravatar anders <anders@b3059339-0415-0410-9bf9-f77b7e298cf2>2002-03-13 12:32:42 +0000
commitead9372b404a31ec231796338aed148e63ff3d77 (patch)
tree5725e31b092a5b37e4fc55594e8b13b6aa28149e
parent54610a5997817c34b51c5c25342b502438b4fa7f (diff)
Added soft clipping for software volume control
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@5064 b3059339-0415-0410-9bf9-f77b7e298cf2
-rw-r--r--cfg-mplayer.h1
-rw-r--r--libao2/audio_plugin.h6
-rw-r--r--libao2/pl_volume.c57
3 files changed, 50 insertions, 14 deletions
diff --git a/cfg-mplayer.h b/cfg-mplayer.h
index 172b49ff53..46906c4110 100644
--- a/cfg-mplayer.h
+++ b/cfg-mplayer.h
@@ -112,6 +112,7 @@ struct config ao_plugin_conf[]={
{"fout", &ao_plugin_cfg.pl_resample_fout, CONF_TYPE_INT, CONF_MIN, 0, 0, NULL},
{"volume", &ao_plugin_cfg.pl_volume_volume, CONF_TYPE_INT, CONF_RANGE, 0, 255, NULL},
{"mul", &ao_plugin_cfg.pl_extrastereo_mul, CONF_TYPE_FLOAT, CONF_MIN, 0, 0, NULL},
+ {"softclip", &ao_plugin_cfg.pl_volume_softclip, CONF_TYPE_FLAG, 0, 0, 1, NULL},
{NULL, NULL, 0, 0, 0, 0, NULL}
};
diff --git a/libao2/audio_plugin.h b/libao2/audio_plugin.h
index 4d31c19bf2..2ff06591b5 100644
--- a/libao2/audio_plugin.h
+++ b/libao2/audio_plugin.h
@@ -37,6 +37,7 @@ typedef struct ao_plugin_cfg_s
int pl_resample_fout; // Output frequency from resampling
int pl_volume_volume; // Initial volume setting
float pl_extrastereo_mul; // Stereo enhancer multiplier
+ int pl_volume_softclip; // Enable soft clipping
} ao_plugin_cfg_t;
extern ao_plugin_cfg_t ao_plugin_cfg;
@@ -47,8 +48,9 @@ extern ao_plugin_cfg_t ao_plugin_cfg;
AFMT_S16_LE, \
0, \
48000, \
- 255, \
- 2.5 \
+ 101, \
+ 2.5, \
+ 0 \
};
// This block should not be available in the pl_xxxx files
diff --git a/libao2/pl_volume.c b/libao2/pl_volume.c
index 8c31cae92f..a6590cce16 100644
--- a/libao2/pl_volume.c
+++ b/libao2/pl_volume.c
@@ -4,6 +4,14 @@
#define PLUGIN
+// Some limits
+#define MIN_S16 -32650
+#define MAX_S16 32650
+#define MIN_U8 0
+#define MAX_U8 255
+#define MIN_S8 -128
+#define MAX_S8 127
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -87,7 +95,7 @@ static int init(){
of wether this plugin is in use or not. */
pl_volume.inuse=1;
// Tell the world what we are up to
- printf("[pl_volume] Software volume control in use.\n");
+ printf("[pl_volume] Software volume control in use%s.\n",ao_plugin_cfg.pl_volume_softclip?", soft clipping enabled":"");
return 1;
}
@@ -100,24 +108,54 @@ static void uninit(){
static void reset(){
}
+#define SIGN(x) (x>0?1:-1)
// processes 'ao_plugin_data.len' bytes of 'data'
// called for every block of data
static int play(){
register int i=0;
+ register int vol=pl_volume.volume; // Logarithmic control sounds more natural
+ vol=(vol*vol*vol)>>12;
// Change the volume.
switch(pl_volume.format){
case(AFMT_U8):{
register uint8_t* data=(uint8_t*)ao_plugin_data.data;
- for(i=0;i<ao_plugin_data.len;i++){
- data[i]=(((data[i]-128) * pl_volume.volume) >> 8) + 128;
- }
- break;
+ register int x;
+ for(i=0;i<ao_plugin_data.len;i++){
+ x=((data[i]-128) * vol) >> 8;
+ if(x>MAX_S8)
+ data[i]=MAX_U8;
+ else if(x<MIN_S8)
+ data[i]=MIN_U8;
+ else{
+ if(ao_plugin_cfg.pl_volume_softclip)
+ data[i] = ((3*x - ((x*x*x) >> 14)) >> 1) + 128;
+ else
+ data[i] = x + 128;
+ }
+ }
+ break;
}
case(AFMT_S16_LE):{
register int len=ao_plugin_data.len>>1;
register int16_t* data=(int16_t*)ao_plugin_data.data;
- for(i=0;i<len;i++)
- data[i]=(data[i]* pl_volume.volume)>>8;
+ register int x;
+ for(i=0;i<len;i++){
+ x=(data[i] * vol) >> 8;
+ if(x>MAX_S16)
+ data[i]=MAX_S16;
+ else if(x<MIN_S16)
+ data[i]=MIN_S16;
+ else{
+ if(ao_plugin_cfg.pl_volume_softclip){
+ int64_t t=x*x;
+ t=(t*x) >> 30;
+ data[i] = (3*x - (int)t) >> 1;
+ //data[i] = 2*x - SIGN(x)*((x*x)>>15);
+ }
+ else
+ data[i] = x;
+ }
+ }
break;
}
default:
@@ -126,8 +164,3 @@ static int play(){
return 1;
}
-
-
-
-
-