
0. 引言
不知道大家是否因为不同音乐/视频播放器的均衡器(EQ)设置不能通用而苦恼过?笔者就遇到过这样的问题。
PC上的foobar2000是笔者的挚爱。笔者发现,foobar2000上一个名为premaster的均衡器预设参数非常适合我,在默认设置的基础上只微调了少量参数,就能在背景音乐基本不失真的情况下改善人声的表现(玄学轻喷),简而言之就是听着更爽了。经过笔者极其不严谨的主观测试,这套参数在IE40 Pro、WH1000-XM3和SHP9500都能获得可感知的提升。一个字,好!
获得了这么个宝贝,笔者当然想把它用在其他平台的播放器上,比如iOS上的nplayer和安卓上的poweramp。不试不知道,这一试才发现,不同播放器的EQ设置是不能直接通用的。例如,foobar2000的均衡器有多达18个参数可调。频率覆盖55至20000Hz,相比之下,poweramp的均衡器只有10个可调参数,覆盖31Hz至16000Hz。两者的频率设置正好错开,直接硬上得不偿失。
最近笔者使用MATLAB时突然想起这事,尝试使用简单的插值法后找到了一个近似可行的解决方案,遂分享出来和大家共同交流。如果大家有其他的实现方法或是发现了本文的错误,还请在评论区对小弟我不吝赐教。下面以foobar2000的premaster EQ设置转换为poweramp可用的EQ设置为例,阐述我的大致思路。

1. 基础数据准备及处理
数据准备:已知的foobar2000均衡器,待调整的poweramp均衡器;使用工具:MATLAB;
在我的理解里,一个简单的理想均衡器本质上就是频率与对应增益的连续函数曲线,而实际均衡器使用有限个离散的频率点和对应频率的增益数据进行设置。笔者猜测,播放器软件自身应该有一套算法可以将离散的频率-增益数据点拟合成连续曲线。我们的工作,就是尝试找出premaster的离散点可能对应的连续曲线。为此,我们需要将premaster的离散数据整理成矩阵储存在某个文件中(例如我存在 premaster_set.txt中)并导入MATLAB。
EQ0 = textread('premaster_set.txt');
可以看到,第1列是频率,单位是Hz,第2列是增益,单位是dB。

直接让这些点连成线的结果是惨烈的。首先是离散的频率数据按指数分布,这将导致数据点前期分布密集、后期松散,不便观察;其次是数据点实际只有20个,只凭这些点远不足以确定一条连续曲线。

为了解决这一问题,我们需要将横坐标即频率对数化后,再对整体数据进行插值处理。
2. 程序准备
分别获取 EQ0 矩阵的列向量,存储为初始频率向量 f0 和初始增益向量 gain0 。对频率向量取关于10的对数,存储在对数化后的初始向量 flg0 中。
f0 = EQ0(:,1);
gain0 = EQ0(:,2);
flg0 = log10(f0);
设置插值后的总数据点数。先定个小目标,比如插ta个100000个点。
flg = linspace(flg0(1),flg0(end),100000);
用 interp1 插值函数根据已有的数据点 ( flg0(i), gain0(i) ) 和设置的总数据点数 flg 去插值,分别设置样条插值 spline 和立方插值 cubic 两种方式。获得插值后的增益向量 gain1 和 gain2 。
gain1 = interp1(flg0,gain0,flg,'spline');
gain2 = interp1(flg0,gain0,flg,'cubic');
将经过插值后的数据点连成连续曲线并画图,可以看到还是挺像那么回事的。又不是不能用.jpg(捂脸)

3. 结果输出
现在,我们已经获得了foobar2000的premaster均衡器插值后的数据(同样是离散数据点)。已知poweramp的EQ设置对应频率点如 F_poweramp 向量所示。为了在这组数据中找到与poweramp可设置的频率 F_poweramp 对应的增益,同样也需要对数化poweramp EQ设置的频率节点。
F_poweramp = [31 62 125 250 500 1000 2000 4000 8000 16000];
flg_pow = log10(F_poweramp);
在 flg 中查找与 flg_pow 中各频率对数最为接近的数据点,找到其对应的增益数据,储存在 gain1_pow 和 gain2_pow 向量中。由于poweramp最精确支持0.1dB的增益调整,因此将增益精度设置为保留1位小数。
for i=1:size(flg_pow,2)
[value(i),index(i)] = min(abs(flg(:)-flg_pow(i)));
gain1_pow(i) = round(gain1(index(i)),1);
gain2_pow(i) = round(gain2(index(i)),1);
end
运行程序,获得对应增益结果如下:
poweramp 样条插值法的增益:
[0 -0.3 2.3 -3.5 0.4 0.9 -0.5 2.0 2.6 3.8];
poweramp 立方插值法的增益:
[0 0.3 2.3 -3.0 0 0.7 0 2.1 2.4 2.9];
将这些数据点标注在上述图4中,获得结果如下:

观察图像可知,两种插值方式产生的增益数据差异并不大。相对而言,立方插值的结果更为保守,而样条插值追求曲线在原始数据点之间更为平滑的过渡,因此曲线形状更为大胆,对应的增益数据也更大。两组结果并没有绝对的孰优孰劣,大家可以自行尝试其中的区别,并选择适合自己的方案。
4. 结语
本文以EQ设置的通用化为问题出发点,以foobar2000的premaster设置向poweramp优化为例,展示了将一个播放器的EQ设置进行合理变化后套用到另一个播放器的EQ设置上的过程。其实现过程非常简单。大家可以根据自己的情况进行相应的修改和尝试。