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

Zuxy Meng zuxy.meng at gmail.com
Wed Jun 6 05:14:39 CEST 2007


Hi,

2007/6/6, Diego Biurrun <diego at biurrun.de>:
> On Tue, Jun 05, 2007 at 08:13:26PM +0800, Zuxy Meng wrote:
> >
> > 2007/6/5, Diego Biurrun <diego at biurrun.de>:
> > > On Tue, Jun 05, 2007 at 05:38:15PM +0800, Zuxy Meng wrote:
> > > >
> > > > 2007/6/5, Reimar Doeffinger <Reimar.Doeffinger at stud.uni-karlsruhe.de>:
> > > > >On Tue, Jun 05, 2007 at 09:13:28AM +0800, Zuxy Meng wrote:
> > > > >> Will apply this weekend of no one objects.
> > > > >
> > > > >The indentation seems inconsistent, please check it before applying.
> > > >
> > > > See if this is better.
> > >
> > > No, it's horrible, you are mixing tabs and spaces.  Also, not adding
> > > trailing whitespace is a plus.
> >
> > Tabs are used only if the original file used them already. Doesn't the
> > rule say that we shall try to follow existing coding style?
>
> When you are adding complete functions, I don't see why you should be
> mixing tabs and spaces.

OK. Then I'll use spaces only for mixer.c since there's only one
occurance of tab in the original file and my code is appended at the
end. But in command.c, tabs are used to indent 8-spaces whenever
possible and I've inserted new code in the middle. I guess I'd better
stick to the old style in this case.
-- 
Zuxy
Beauty is truth,
While truth is beauty.
PGP KeyID: E8555ED6
-------------- next part --------------
Index: input/input.h
===================================================================
--- input/input.h	?????? 23483??
+++ 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: input/input.c
===================================================================
--- input/input.c	?????? 23483??
+++ 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: etc/input.conf
===================================================================
--- etc/input.conf	?????? 23483??
+++ 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
Index: etc/menu.conf
===================================================================
--- etc/menu.conf	?????? 23483??
+++ etc/menu.conf	????????????
@@ -33,6 +33,7 @@
 
 <pref name="audio_pref" title="Audio">
       <e property="volume" name="Volume"/>
+      <e property="balance" name="Balance"/>
       <e property="mute" name="Mute"/>
       <e property="audio_delay" name="Delay"/>
 </pref>
Index: command.c
===================================================================
--- command.c	?????? 23483??
+++ command.c	????????????
@@ -571,6 +571,57 @@
     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 (!mpctx->sh_audio || mpctx->sh_audio->channels < 2)
+	return M_PROPERTY_UNAVAILABLE;
+
+    switch (action) {
+    case M_PROPERTY_GET:
+	if (!arg)
+	    return M_PROPERTY_ERROR;
+	mixer_getbalance(&mpctx->mixer, arg);
+	return M_PROPERTY_OK;
+    case M_PROPERTY_PRINT: {
+	    char** str = arg;
+	    if (!arg)
+		return M_PROPERTY_ERROR;
+	    mixer_getbalance(&mpctx->mixer, &bal);
+	    if (bal == 0.f)
+		*str = strdup("center");
+	    else if (bal == -1.f)
+		*str = strdup("left only");
+	    else if (bal == 1.f)
+		*str = strdup("right only");
+	    else {
+		unsigned right = (bal + 1.f) / 2.f * 100.f;
+		*str = malloc(sizeof("left xxx%, right xxx%"));
+		sprintf(*str, "left %d%%, right %d%%", 100 - right, right);
+	    }
+	    return M_PROPERTY_OK;
+	}
+    case M_PROPERTY_STEP_UP:
+    case M_PROPERTY_STEP_DOWN:
+	mixer_getbalance(&mpctx->mixer, &bal);
+	bal += (arg ? *(float*)arg : .1f) *
+	    (action == M_PROPERTY_STEP_UP ? 1.f : -1.f);
+	M_PROPERTY_CLAMP(prop, bal);
+	mixer_setbalance(&mpctx->mixer, bal);
+	return M_PROPERTY_OK;
+    case M_PROPERTY_SET:
+	if (!arg)
+	    return M_PROPERTY_ERROR;
+	M_PROPERTY_CLAMP(prop, *(float*)arg);
+	mixer_setbalance(&mpctx->mixer, *(float*)arg);
+	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)
@@ -1468,6 +1519,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,
@@ -1611,6 +1664,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.h
===================================================================
--- mixer.h	?????? 23483??
+++ 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: mixer.c
===================================================================
--- mixer.c	?????? 23483??
+++ 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,84 @@
     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 || !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	?????? 23483??
+++ 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	?????? 23483??
+++ 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	?????? 23483??
+++ 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	?????? 23483??
+++ 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: DOCS/tech/slave.txt
===================================================================
--- DOCS/tech/slave.txt	?????? 23483??
+++ DOCS/tech/slave.txt	????????????
@@ -406,6 +406,7 @@
 metadata           str list                  X            list of metadata key/value
 metadata/*         string                    X            metadata values
 volume             float     0       100     X   X   X    change volume
+balance            float     -1      1       X   X   X    change audio balance
 mute               flag      0       1       X   X   X
 audio_delay        float     -100    100     X   X   X
 audio_format       int                       X


More information about the MPlayer-dev-eng mailing list