[MPlayer-dev-eng] [PATCH] Audio balance feature
Zuxy Meng
zuxy.meng at gmail.com
Thu May 31 15:45:04 CEST 2007
Hi,
2007/5/31, Alban Bedel <albeu at free.fr>:
> On Thu, 31 May 2007 20:13:53 +0800
> "Zuxy Meng" <zuxy.meng at gmail.com> wrote:
>
> > + case M_PROPERTY_STEP_UP:
> > + step = .1f;
> > + // falling thru
> > + case M_PROPERTY_STEP_DOWN:
> > + step = -.1f;
> > + // falling thru
>
> Both cases will get step = -.1
Ooops....
>
> > + case M_PROPERTY_SET:
> > + if (action == M_PROPERTY_SET) {
> > + if (!arg)
> > + return M_PROPERTY_ERROR;
> > + bal = *(float*)arg;
>
> SET should return the value set if possible.
>
> > + } else {
> > + if (arg)
> > + step = *(float*)arg;
> > + mixer_getbalance(&mpctx->mixer, &bal);
> > + bal += step;
> > + }
> > + M_PROPERTY_CLAMP(prop, bal);
> > + mixer_setbalance(&mpctx->mixer, bal);
> > + return M_PROPERTY_OK;
> > + }
>
> Better simply do something like:
>
> 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;
>
> case M_PROPERTY_STEP_UP:
> case M_PROPERTY_STEP_DOWN:
> mixer_getbalance(&mpctx->mixer, &bal);
> bal += (arg ? *(float*)arg : 0.1) *
> (action == M_PROPERTY_STEP_UP ? 1.0 : -1.0);
> M_PROPERTY_CLAMP(prop, bal);
> mixer_setbalance(&mpctx->mixer, bal);
> return M_PROPERTY_OK;
>
> and you'll get correct behaviour everywhere.
Thanks! See if this one's better.
--
Zuxy
Beauty is truth,
While truth is beauty.
PGP KeyID: E8555ED6
-------------- next part --------------
Index: input/input.h
===================================================================
--- input/input.h ?????? 23436??
+++ 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 ?????? 23436??
+++ 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 ?????? 23436??
+++ 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 ?????? 23436??
+++ 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 ?????? 23436??
+++ 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 ?????? 23436??
+++ 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 ?????? 23436??
+++ 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 ?????? 23436??
+++ 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 ?????? 23436??
+++ 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 ?????? 23436??
+++ 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 ?????? 23436??
+++ 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)"
More information about the MPlayer-dev-eng
mailing list