维基百科说我们可以用等式近似巴克规模:
b(f) = 13*atan(0.00076*f)+3.5*atan(power(f/7500,2))
如何在Bark标度上将频谱划分为相同长度的n
区间(区间分割点在Bark标度上是等距的)?
最好的方法是分析反函数(用x
的函数表达y
)。我试图在纸上做但却失败了。 WolframAlpha搜索栏也无法做到。我尝试了Octave finverse
函数,但是我收到了错误。
Octave说(更简单的例子):
octave:2> x = sym('x');
octave:3> finverse(2*x)
error: `finverse' undefined near line 3 column 1
这是来自Matlab的finverse
描述:http://www.mathworks.com/help/symbolic/finverse.html
也可以通过数字方式来做到这一点。我可以想象你只是从平均分割y
轴开始,通过二分搜索搜索理想的除法。但也许有一些现有的工具可以做到这一点?
答案 0 :(得分:1)
此功能无法通过分析反转。你必须使用一些数字程序。二进制搜索会很好,但有更有效的方法可以做这些事情:查看root-finding algorithms。对于每个频率间隔端点b(f) = f_n
,您可以将选择的算法应用于等式f_n
。
答案 1 :(得分:1)
你需要在数值上求解这个方程(没有解析反函数)。设置等间距b
的值并求解等式以找到各种f
。 Bissection有点慢,但布伦特的方法是一个非常好的选择。见http://en.wikipedia.org/wiki/Brent%27s_method
答案 2 :(得分:1)
我最终决定不使用Bark值近似,而是使用关键波段中心的理想值(为n=1..24
定义)。我用gnuplot
绘制它们,并在同一图表上绘制了任意选择的密度较大的点的值(对于所需的n>24
)。我调整了Hz
中的点值,直到两条曲线大致相同。
当然 rpsmi 和 David Zaslavsky 的答案更为通用和可扩展。
答案 3 :(得分:1)
就像你知道的那样,在(比方说)octave中实现rpsmi或David Zaslavsky的答案,你会做这样的事情:
global x0 = 0.
function res = b(f)
global x0
res = 13*atan(0.00076*f)+3.5*atan(power(f/7500,2)) - x0
end
function [intervals, barks] = barkintervals(left, right, n)
global x0
intervals = linspace(left, right, n);
barks = intervals;
for i = 1:n
x0 = intervals(i);
# 125*x0 is just a crude guess starting point given the values
[barks(i), fval, info] = fsolve('b', 125*x0);
endfor
end
然后像这样运行:
octave:1> barks
octave:2> [i,bx] = barkintervals(0, 10, 10)
[... lots of output from fsolve deleted...]
i =
Columns 1 through 8:
0.00000 1.11111 2.22222 3.33333 4.44444 5.55556 6.66667 7.77778
Columns 9 and 10:
8.88889 10.00000
bx =
Columns 1 through 6:
0.0000e+00 1.1266e+02 2.2681e+02 3.4418e+02 4.6668e+02 5.9653e+02
Columns 7 through 10:
7.3639e+02 8.8960e+02 1.0605e+03 1.2549e+03