[MPlayer-dev-eng] [PATCH] Audio balance feature

Zuxy Meng zuxy.meng at gmail.com
Wed May 30 16:53:19 CEST 2007


Hi,

Attached patch implements the audio balance feature commonly present
in other players by using the pan audio filter. With this patch a user
can adjust the balance between the two front channels during play with
'(' and ')'.

Comments and testing welcome!
-- 
Zuxy
Beauty is truth,
While truth is beauty.
PGP KeyID: E8555ED6
-------------- next part --------------
Index: input/input.c
===================================================================
--- input/input.c	?????? 23404??
+++ input/input.c	????????????
@@ -71,6 +71,7 @@
   { MP_CMD_OSD_SHOW_TEXT, "osd_show_text", 1, { {MP_CMD_ARG_STRING, {0}}, {MP_CMD_ARG_INT,{-1}}, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
   { MP_CMD_OSD_SHOW_PROPERTY_TEXT, "osd_show_property_text",1, { {MP_CMD_ARG_STRING, {0}}, {MP_CMD_ARG_INT,{-1}}, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
   { MP_CMD_VOLUME, "volume", 1, { { MP_CMD_ARG_FLOAT,{0} }, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
+  { MP_CMD_BALANCE, "balance", 1, { { MP_CMD_ARG_FLOAT,{0} }, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
   { MP_CMD_MIXER_USEMASTER, "use_master", 0, { {-1,{0}} } },
   { MP_CMD_MUTE, "mute", 0, { {MP_CMD_ARG_INT,{-1}}, {-1,{0}} } },
   { MP_CMD_CONTRAST, "contrast",1,  { {MP_CMD_ARG_INT,{0}}, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
@@ -359,6 +360,8 @@
   { { '/', 0 }, "volume -1" },
   { { '0', 0 }, "volume 1" },
   { { '*', 0 }, "volume 1" },
+  { { '(', 0 }, "balance -0.1" },
+  { { ')', 0 }, "balance 0.1" },
   { { 'm', 0 }, "mute" },
   { { '1', 0 }, "contrast -1" },
   { { '2', 0 }, "contrast 1" },
Index: input/input.h
===================================================================
--- input/input.h	?????? 23404??
+++ input/input.h	????????????
@@ -93,6 +93,7 @@
 #define MP_CMD_STEP_PROPERTY 91
 #define MP_CMD_RADIO_STEP_FREQ 92
 #define MP_CMD_TV_STEP_FREQ 93
+#define MP_CMD_BALANCE 94
 
 #define MP_CMD_GUI_EVENTS       5000
 #define MP_CMD_GUI_LOADFILE     5001
Index: command.c
===================================================================
--- command.c	?????? 23404??
+++ command.c	????????????
@@ -483,6 +483,40 @@
     return m_property_int_ro(prop, action, arg, mpctx->sh_audio->channels);
 }
 
+/// Balance (RW)
+static int mp_property_balance(m_option_t * prop, int action, void *arg,
+			      MPContext * mpctx)
+{
+    float bal;
+
+    if (!arg)
+	return M_PROPERTY_ERROR;
+    if (!mpctx->sh_audio || mpctx->sh_audio->channels < 2)
+	return M_PROPERTY_UNAVAILABLE;
+
+    switch (action) {
+    case M_PROPERTY_GET:
+	mixer_getbalance(&mpctx->mixer, arg);
+	return M_PROPERTY_OK;
+    case M_PROPERTY_PRINT:{
+	    mixer_getbalance(&mpctx->mixer, &bal);
+	    return m_property_float_range(prop, action, arg, &bal);
+	}
+    case M_PROPERTY_STEP_UP:
+        *(float*)arg = -*(float*)arg;
+	// falling thru
+    case M_PROPERTY_STEP_DOWN:
+	mixer_getbalance(&mpctx->mixer, &bal);
+	bal -= *(float*)arg;
+	// falling thru
+    case M_PROPERTY_SET:
+	M_PROPERTY_CLAMP(prop, bal);
+	mixer_setbalance(&mpctx->mixer, bal);
+	return M_PROPERTY_OK;
+    }
+    return M_PROPERTY_NOT_IMPLEMENTED;
+}
+
 /// Selected audio id (RW)
 static int mp_property_audio(m_option_t * prop, int action, void *arg,
 			     MPContext * mpctx)
@@ -1336,6 +1370,8 @@
      0, 0, 0, NULL },
     { "switch_audio", mp_property_audio, CONF_TYPE_INT,
      CONF_RANGE, -2, MAX_A_STREAMS - 1, NULL },
+    { "balance", mp_property_balance, CONF_TYPE_FLOAT,
+     M_OPT_RANGE, -1, 1, NULL },
 
     // Video
     { "fullscreen", mp_property_fullscreen, CONF_TYPE_FLAG,
@@ -1477,6 +1513,7 @@
     { "mute", MP_CMD_MUTE, 1, 0, -1, MSGTR_MuteStatus },
     { "audio_delay", MP_CMD_AUDIO_DELAY, 0, 0, -1, MSGTR_AVDelayStatus },
     { "switch_audio", MP_CMD_SWITCH_AUDIO, 1, 0, -1, MSGTR_OSDAudio },
+    { "balance", MP_CMD_BALANCE, 0, OSD_BALANCE, -1, MSGTR_Balance },
     // video
     { "fullscreen", MP_CMD_VO_FULLSCREEN, 1, 0, -1, NULL },
     { "panscan", MP_CMD_PANSCAN, 0, OSD_PANSCAN, -1, MSGTR_Panscan },
Index: mixer.c
===================================================================
--- mixer.c	?????? 23404??
+++ mixer.c	????????????
@@ -17,6 +17,7 @@
 char * mixer_channel=NULL;
 int soft_vol = 0;
 float soft_vol_max = 110.0;
+static af_instance_t* af_pan_balance;
 
 void mixer_getvolume(mixer_t *mixer, float *l, float *r)
 {
@@ -118,3 +119,86 @@
     mixer->muted=1;
    }
 }
+
+void mixer_getbalance(mixer_t *mixer, float *val)
+{
+    float level[AF_NCH];
+    af_control_ext_t arg_ext = { .arg = level };
+    *val = 0.f;
+
+    if (!af_pan_balance)
+	return;
+
+    arg_ext.ch = 0;
+    if (!af_pan_balance->control(af_pan_balance,
+		AF_CONTROL_PAN_LEVEL | AF_CONTROL_GET, &arg_ext))
+	return;
+    if (level[1]) {
+	*val = level[1];
+	return;
+    }
+
+    arg_ext.ch = 1;
+    if (!af_pan_balance->control(af_pan_balance,
+		AF_CONTROL_PAN_LEVEL | AF_CONTROL_GET, &arg_ext))
+	return;
+    if (level[0])
+	*val = -level[0];
+}
+
+void mixer_setbalance(mixer_t *mixer, float val)
+{
+    float level[AF_NCH];
+    af_control_ext_t arg_ext = { .arg = level };
+
+    if(!mixer->audio_out)
+	return;
+    if (!mixer->afilter)
+	return;
+
+    if (!af_pan_balance) {
+	if (af_pan_balance = af_get(mixer->afilter, "pan")) {
+	    int nout;
+	    af_pan_balance->control(af_pan_balance,
+		    AF_CONTROL_PAN_NOUT | AF_CONTROL_GET, &nout);
+	    if (nout >= 2)
+		mp_msg(MSGT_GLOBAL, MSGL_WARN, MSGTR_PanSettingsLost);
+	    else {
+		mp_msg(MSGT_GLOBAL, MSGL_WARN, MSGTR_MonoPan);
+		/* keep trying next time in case of audio switch */
+		af_pan_balance = NULL;
+		return;
+	    }
+	} else if (af_pan_balance = af_add(mixer->afilter, "pan")) { 
+	    /* identi-mapping will be performed once if there are no previous
+	       af pan settings */
+	    int i;
+	    af_init(mixer->afilter);
+	    for (i = 2; i < AF_NCH; i++) {
+		arg_ext.ch = i;
+		memset(level, 0, sizeof(level));
+		level[i] = 1.f;
+		af_pan_balance->control(af_pan_balance,
+			AF_CONTROL_PAN_LEVEL | AF_CONTROL_SET, &arg_ext);
+	    }
+	} else {
+	    mp_msg(MSGT_GLOBAL, MSGL_ERR, MSGTR_NoPan);
+	    return;
+	}
+    }
+
+    arg_ext.ch = 0;
+    memset(level, 0, sizeof(level));
+    level[0] = min(1.f, 1.f - val);
+    level[1] = max(0.f, val);
+    af_pan_balance->control(af_pan_balance,
+	    AF_CONTROL_PAN_LEVEL | AF_CONTROL_SET, &arg_ext);
+
+    arg_ext.ch = 1;
+    memset(level, 0, sizeof(level));
+    level[0] = max(0.f, -val);
+    level[1] = min(1.f, 1 + val);
+    af_pan_balance->control(af_pan_balance,
+	    AF_CONTROL_PAN_LEVEL | AF_CONTROL_SET, &arg_ext);
+}
+
Index: libvo/sub.h
===================================================================
--- libvo/sub.h	?????? 23404??
+++ libvo/sub.h	????????????
@@ -81,6 +81,7 @@
 #define OSD_VOLUME 0x09
 #define OSD_BRIGHTNESS 0x0A
 #define OSD_HUE 0x0B
+#define OSD_BALANCE 0x0C
 #define OSD_PANSCAN 0x50
 
 #define OSD_PB_START 0x10
Index: libvo/sub.c
===================================================================
--- libvo/sub.c	?????? 23404??
+++ libvo/sub.c	????????????
@@ -58,9 +58,10 @@
     MSGTR_VO_SUB_Saturation,
     MSGTR_VO_SUB_Volume,
     MSGTR_VO_SUB_Brightness,
-    MSGTR_VO_SUB_Hue
+    MSGTR_VO_SUB_Hue,
+    MSGTR_VO_SUB_Balance
 };
-char * __sub_osd_names_short[] ={ "", "|>", "||", "[]", "<<" , ">>", "", "", "", "", "", ""};
+char * __sub_osd_names_short[] ={ "", "|>", "||", "[]", "<<" , ">>", "", "", "", "", "", "", "" };
 
 //static int vo_font_loaded=-1;
 font_desc_t* vo_font=NULL;
Index: help/help_mp-en.h
===================================================================
--- help/help_mp-en.h	?????? 23404??
+++ help/help_mp-en.h	????????????
@@ -231,6 +231,7 @@
 #define MSGTR_Contrast "Contrast"
 #define MSGTR_Saturation "Saturation"
 #define MSGTR_Hue "Hue"
+#define MSGTR_Balance "Balance"
 
 // property state
 #define MSGTR_MuteStatus "Mute: %s"
@@ -706,6 +707,9 @@
 
 #define MSGTR_InsertingAfVolume "[Mixer] No hardware mixing, inserting volume filter.\n"
 #define MSGTR_NoVolume "[Mixer] No volume control available.\n"
+#define MSGTR_NoPan "[Mixer] No balance control available.\n"
+#define MSGTR_PanSettingsLost "[Mixer] Previous pan filter settings for front channels irreversibly lost.\n"
+#define MSGTR_MonoPan "[Mixer] Existing pan filter has mono output; no balance available.\n"
 
 // ====================== GUI messages/buttons ========================
 
@@ -1077,6 +1081,7 @@
 #define MSGTR_VO_SUB_Volume "Volume"
 #define MSGTR_VO_SUB_Brightness "Brightness"
 #define MSGTR_VO_SUB_Hue "Hue"
+#define MSGTR_VO_SUB_Balance "Balance"
 
 // vo_xv.c
 #define MSGTR_VO_XV_ImagedimTooHigh "Source image dimensions are too high: %ux%u (maximum is %ux%u)\n"
Index: DOCS/man/en/mplayer.1
===================================================================
--- DOCS/man/en/mplayer.1	?????? 23404??
+++ DOCS/man/en/mplayer.1	????????????
@@ -238,6 +238,8 @@
 Decrease/\:increase volume.
 .IPs "9 and 0"
 Decrease/\:increase volume.
+.IPs "( and )"
+Adjust audio balance in favor of left/\:right channel.
 .IPs "m\ \ \ \ "
 Mute sound.
 .IPs "_ (MPEG-TS and libavformat only)"
Index: mixer.h
===================================================================
--- mixer.h	?????? 23404??
+++ mixer.h	????????????
@@ -23,6 +23,8 @@
 void mixer_decvolume(mixer_t *mixer);
 void mixer_getbothvolume(mixer_t *mixer, float *b);
 void mixer_mute(mixer_t *mixer);
+void mixer_getbalance(mixer_t *mixer, float *bal);
+void mixer_setbalance(mixer_t *mixer, float bal);
 
 //extern void mixer_setbothvolume( int v );
 #define mixer_setbothvolume(m, v) mixer_setvolume(m, v, v)
Index: etc/input.conf
===================================================================
--- etc/input.conf	?????? 23404??
+++ etc/input.conf	????????????
@@ -51,6 +51,8 @@
 6 hue 1
 7 saturation -1
 8 saturation 1
+( balance -0.1          # adjust audio balance in favor of left
+) balance +0.1          #                                  right
 d frame_drop
 r sub_pos -1            # move subtitles up
 t sub_pos +1            #                down


More information about the MPlayer-dev-eng mailing list