原生安卓系统只能调出15级音量,而市面上很多已上传的音量APP也只能调整这15级音量,这样的调整方式,级别粗糙,不够贴心。
而许多大厂音乐类APP都只支持这十几级系统音量,不支持APP内部(MediaPlayer)的音量调整。
可以用全局均衡器来进一步微调音量,相当于为15个音量级别的每一级额外增加数千个微调等级。
构造全局均衡器(应用于系统级别)与构造一般均衡器(APP内部有效)一样,无需 context,区别是为全局均衡器传入的 session id 为零:
mEqualizer = new Equalizer(999, 0);
全局均衡器被官方标注为不推荐,甚至废弃,但没有替代方案,也未被彻底舍弃,在较新的设备商仍然能够使用。
全局均衡器会因被其他APP的一般均衡器干扰而失效,两个构造参数(优先级、session id)全部被无视了。
安卓的声音系统较弱,某些设备在调节、切换时会有爆音现象(完全静音了但是偶然会很响地噗一下刺耳朵)。
全局均衡器有着如此的缺陷,不是很健壮,但仍然有其使用武之地。
Precise volume 这款应用也支持全局均衡器,不过界面复杂,调节费手,一共五个推杆,需要一个个推杆推过去地调。
所以,我决定在我的浏览器项目中加入调节系统音量的功能,只用一个进度条就可以控制全部。
稍后,我有将两三年前为播放器项目写的、可以用一次滑动触摸修改所有推杆的均衡器界面搬到了这个浏览器项目上面。
抛开界面,设置全局均衡器的代码如下:
Utils.java
public static int mGlobalEqShift = Integer.MAX_VALUE;
public static Equalizer mEqualizer;
public static int[] bandLevels;
public static void setSystemEqualizer(Options opt, boolean prepareUI) {
boolean adjust = opt.getAdjustSystemVolume();
Equalizer mEqualizer = Utils.mEqualizer;
if (adjust || prepareUI) {
if (mEqualizer==null) {
try {
Utils.mEqualizer = mEqualizer = new Equalizer(999, 0);
} catch (Exception ignored) { }
if (bandLevels==null) {
bandLevels = new int[mEqualizer.getNumberOfBands()];
}
if (mGlobalEqShift==Integer.MAX_VALUE) {
opt.getBandLevels(bandLevels);
mGlobalEqShift = opt.getGlobalEqShift();
}
}
if (!prepareUI && mEqualizer!=null) {
int min = mEqualizer.getBandLevelRange()[0];
int max = mEqualizer.getBandLevelRange()[1];
float shiftGlobal = (mGlobalEqShift-5000)/10000.f*(max-min);
int count = bandLevels.length;
for (int i = 0; i < count; i++) {
int modified = (int) Math.max(min, Math.min(max, bandLevels[i]+shiftGlobal));
//CMN.Log("modified::", modified, i);
mEqualizer.setBandLevel((short) i, (short) modified);
}
mEqualizer.setEnabled(true);
}
} else if (mEqualizer!=null) {
mEqualizer.setEnabled(false);
}
}
opt 是我的设置类。其中处理五个推杆数值、整体偏移数值的保存,也很简单:
Options.java
public final SharedPreferences defaultReader;
public int getGlobalEqShift() {
return defaultReader.getInt("eqSft", 5000);
}
public void putGlobalEqShift(int val) {
defaultReader.edit().putInt("eqSft", val).apply();
}
public void getBandLevels(int[] levels) {
String[] bands = defaultReader.getString("bands", "").split(";");
for (int i = 0, len=Math.min(levels.length, bands.length); i < len; i++) {
levels[i] = IU.parsint(bands[i]);
}
}
public void putBandLevels(int[] levels) {
StringBuilder str= new StringBuilder(32);
for (int i = 0, len=levels.length; i < len; i++) {
str.append(levels[i]);
if (i
或许需要权限:
这些写起来很容易,不过界面就不简单了。要为五个推杆写界面,需要用到垂直进度条。若要用一次滑动手势修改全部推杆,就需要更多的技巧。
有关均衡器的这些种种我已在几年前玩过了,当年还整合了vlc、exoplayer、mediaplayer、ijkplayer到一个App内,低版本安卓设备自带的解码器不全,可以切换VLC播放组件,支持的格式更全。切换至 exoplayer 或者 ijkplayer,则功能更多、切换视频速度更快。而这些播放器组件均支持均衡器,其中vlc支持更多的均衡器推杆,记得好像是二十个。
时过境迁,现在看看搬过来的效果也还不错:
好用的均衡器控制面板
控制系统全局音量