LUA中(或者一般情况下)如何非线性地映射两个数字范围?

我正在编写一个LUA脚本,以便我可以同时控制两个音轨的音频EQ,这样当一个上升时,另一个下降。

在EQ界面中,用户看到0dB到36 dB的正增益和0dB到-inf的负增益。

插件本身将正值处理为0.25-16.0的浮点数。这个范围映射到用户在EQ界面中看到的0dB-36dB范围内。

负值在内部处理为0.2499999到0.0000002,这涵盖了EQ接口中从0dB到-inf dB的范围。

大多数使用EQ的人不会增加或减少超过16dB左右。因此,我需要一个范围映射,使得0.25到1.5773934(在EQ应用程序中为0dB到16dB)在一个EQ中镜像/映射到另一个EQ中的0.2499999到0.044457(即为0 到-16dB)。

这样,一个EQ为4dB时,另一个为-4dB。当一个EQ为12 dB时,另一个为-12 dB,等等直到+-16 dB。之后,由于正负EQ范围的不对称性,它们必然会发散。

在那之后(超过+-16dB点),我只需要进行映射,使得一个EQ的36dB极端情况映射到另一个EQ的-inf(也就是说,在内部,一个EQ上的16.0将映射到另一个0.0000002)。我知道这种映射不会是线性的。

我解释清楚了吗?

最初,我只是使用了一个简单的线性映射:

function map(x, in_min, in_max, out_min, out_max)
  return out_min + (x - in_min)*(out_max - out_min)/(in_max - in_min)
end

我在Mapping a numeric range onto another中看到了这个函数。

然后,当我在调整的EQ上收到一个内部的EQ增益值时,我计算要在另一个EQ上镜像的值为

if val >= 0.25 then
    mappedval = map(val, nogain, maxgain, nogain, mingain)
else
    mappedval = map(val, nogain, mingain, nogain, maxgain)
end

这根本行不通,因为一个EQ上的大幅变化可以映射到另一个EQ上非常小的变化。

所以,这就是我试图让这两个EQ在+-16dB范围内以非常相似的数值反向移动的方式运作。

有什么想法吗?

谢谢!

编辑: 我深入研究了一下,发现这些值在某种对数尺度上被映射到dB上,只是这不是典型的尺度。通常,dB的十进制值为1映射为0 dB。

在我的情况下,从十进制到dB的转换具有域[0 1],范围[-120 12]。

因此,我只是尝试解决方程...这样我就可以在所有值上精确地进行映射。

点赞
用户3342050
用户3342050

如果您预计增益会将浮点数的值超出其预期范围,可以将最小/最大值夹紧。然而,这将使您的表盘颠倒。

如果 val >= 0.25 then
    local norm = val -0.25  --  归一化到零
    --  15.75 *2.2857142857143 = 36

    dB = norm *2.2857142857143  --  正表盘
    inverse_dB = -( norm /norm /norm /norm )  --  负
else
    dB = 16 -( val /val /val /val )  --  负
    inverse_dB = 144 *val  --  正表盘
end
2020-11-09 18:24:35
用户4240647
用户4240647

好的,将其转化为中文及保持原有的 markdown 格式,

function VAL2DB(x)
如果 x < 0.0000002,则
   x = -120
否则,
   x = 20 * math.log(x / nogain,10)
结束
   返回 x
结束

function DB2VAL(x)
   返回 (10^(x*0.05))*nogain
结束

这里的 nogain 为 0.25。

然后,在主程序中,我有:

mappedval = val

如果 this_track_number ~= track_number then

    dBval = VAL2DB(val)

    如果 dBval < -120,则
       mappedval = 1.0
    否则,如果 dBval >= 12,则
       mappedval = 0
    否则,
       mappeddB = -(dBval)
       mappedval = DB2VAL(mappeddB)
    结束

结束

我决定将 12dB 作为最大值,并在 EQ 插件中注意到 -120 dB 被用作 -inf。

所以这就得到了我想要的行为。

2020-11-10 08:57:25