麦克风输入电平的对数函数的倒数

Inverse of logarithmic function for an microphone input level

我正在尝试编写一个具有对数缩放比例的滑块来控制麦克风 RMS 阈值。

我写了下面的函数,它可能很糟糕(数学不是我的强项),但似乎确实做了我想要的对数缩放。但是,我现在需要在使用刻度的条形图中显示 RMS 电平,因此我需要反转此函数。

const rmsLogarithmicScale = (value, max) => {
    const log = ((100 - (Math.log((1 - value) * 100) / 4.605170185988092) * 100) / 100) * max;
    return log === Infinity ? max : log;
};

console.log(rmsLogarithmicScale(0.5, 0.05)); // Result: 0.007525749891599539
console.log(rmsLogarithmicScale(0.5, 300)); // Result: 45.15449934959723
const rmsLogarithmicScaleInverse = (rms, max) => {
    // I have literally no idea where to start...
}

rmsLogarithmicScaleInverse(0.007525749891599539, 0.05); // Result: 0.5

有好心的数学家可以帮我解决这个问题吗?

答案已在Java中提供,Java脚本示例在原文下方

这是用中间形式表示的计算的逆运算。

(但我更喜欢你在评论中的讨论 - 只是添加这个因为它很有趣。)

public static void main(String[] args) {
    double v = rmsLogScale(0.5,0.05);
    System.out.println("v = " + v);                // prints 0.007525749891599539
    double iv = invRmsLogScale(v, 0.05);
    System.out.println("iv = "+iv);                // 0.499999999999999994

}

static double rmsLogScale(double v, double m) {
    double x1 = (1 - v) * 100.;
    double x2 = Math.log(x1);
    double x3 = x2 / 4.605170185988092;
    double x4 = x3 * 100.;
    double x5 = 100. - x4;
    double x6 = x5 / 100. * m;

    return x6;
}

static double invRmsLogScale(double lg, double m) {
    double x5 = (lg * 100) / m;
    double x4 = (100. - x5);
    double x3 = x4 / 100.;
    double x2 = x3 * 4.605170185988092;
    double x1 = Math.exp(x2);
    double x0 = 1 - ((x1) / 100.);
    return x0;
}

Java脚本

const rmsLogScale = (v, m) => {
    const x1 = (1 - v) * 100.0;
    const x2 = Math.log(x1);
    const x3 = x2 / 4.605170185988092;
    const x4 = x3 * 100.0;
    const x5 = 100.0 - x4;
    return x5 / 100.0 * m;
};

const inverseRmsLogScale = (lg, m) => {
    const x5 = (lg * 100) / m;
    const x4 = (100.0 - x5);
    const x3 = x4 / 100.0;
    const x2 = x3 * 4.605170185988092;
    const x1 = Math.exp(x2);
    return 1 - ((x1) / 100.0);
};

console.log(rmsLogScale(0.5, 0.5));
console.log(rmsLogScale(0.5, 300));

console.log(inverseRmsLogScale(rmsLogScale(0.5, 0.5), 0.5));
console.log(inverseRmsLogScale(rmsLogScale(0.3, 300), 300));

在@Bergi 建议我尝试简化我的原始函数后,我按照@Andy 的风格重写了该函数,并且也成功地反转了它。

You should start by simplifying to const log = -Math.log(1 - value) / Math.log(100) * max; — Bergi

const logScale = (value, max) => {
    const x1 = 1 - value;
    const x2 = -Math.log(x1);
    const x3 = x2 / Math.log(100);
    const x4 = x3 * max;
    return x4;
};

const altInverseRmsLogScale = (lg, max) => {
    const x4 = lg / max;
    const x3 = x4 * Math.log(100);
    const x2 = Math.exp(-x3);
    const x1 = 1 - x2;
    return x1;
};

console.log(logScale(0.7, 300)); // 4.727557716909737
console.log(inverseLogScale(logScale(0.7, 300), 300)); // 0.07000000000000006

精简版

const logScale = (value, max) => (-Math.log(1 - value) / Math.log(100)) * max;

const inverseLogScale = (lg, max) => 1 - Math.exp(-(lg / max * Math.log(100)));

精简版

const logScale = (value, max) => (-Math.log(1 - value) / Math.log(100)) * max;
const inverseLogScale = (lg, max) => 1 - Math.pow(100, -lg / max);

console.log(logScale(0.6, 300));
console.log(inverseLogScale(logScaleTwo(0.6, 300), 300));

https://repl.it/@sarcoma/log-scale

最终函数

我还需要处理在 value === max 时返回的 Infinity

const logScale = (value, max) => {
    const log = (-Math.log(1 - value) / Math.log(100)) * max;
    return log === Infinity ? max : log;
};
const inverseLogScale = (lg, max) => 1 - Math.pow(100, -lg / max);