【问题标题】:Inverse of logarithmic function for an microphone input level麦克风输入电平的对数函数的倒数
【发布时间】:2020-03-01 17:26:48
【问题描述】:

我正在尝试编写一个具有对数缩放的滑块来控制麦克风 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

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

【问题讨论】:

  • 要明确一点,您知道* max 部分在除法后完成,对吧?不是blah / (100 * max),而是(blah / 100) * max。话虽如此,不需要数学家,只要让Wolfram Alpha为你做。
  • 我给了你链接,该链接从字面上解决了“映射回”的数学问题,因此该部分已排序。是否有 XY 问题是另一回事:最明显的问题当然是“你为什么要编写自己的代码?”因为在过去 25 年的 JS 和 5 年的 Node 中似乎没有人用 JS 编写过 DSP 包。
  • 对数的反函数是对应的指数。
  • 你应该先简化为const log = -Math.log(1 - value) / Math.log(100) * max;
  • @Bergi 感谢您的链接,我仍然不明智。我了解代码,并且几乎可以根据需要使用数学。我真的很难阅读方程式,这是我生活的祸根。看起来我可以使用您建议的简化版本并设法自己计算出逆向,所以我对此非常满意。感谢大家的帮助。

标签: javascript math logarithm


【解决方案1】:

在@Bergi 建议我尝试简化我的原始函数之后,我以@Andy 的风格重写了该函数,并设法将其反转。

您应该首先简化为 const log = -Math.log(1 - value) / Math.log(100) * max; — 贝尔吉

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)));

Terser 版本

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);

【讨论】:

  • y = Math.log(x) / Math.log(100)y = log(100, x),它的倒数是x = Math.pow(100, y)
  • @Bergi 再次感谢。看来我到了。现在我只需要弄清楚这是否真的是我首先需要做的。无论如何,工作很有趣。非常感谢您的指导和耐心。
【解决方案2】:

答案是用 Java 提供的,JavaScript 示例在原文下面

这是以中间形式表示的计算的倒数。

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

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;
}

JavaScript

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));

【讨论】:

  • 请注意,问题是关于 JavaScript 的。不是Java。 JS 中只有小数,所以在任何数字的末尾都不需要 .,也不需要函数返回类型,也不需要变量类型(尽管在现代 JS 中,您可能希望为每个分配的 var 使用 const在那些函数中)
  • 其实问题是用javascript表示的数学和用java表示的答案之一。
  • Java 很好,任何语言都很好,哈哈。非常感谢。
  • 一旦我让它工作,我将更新答案以包含一个 JavaScript 示例。
  • 更新到:double x0 = 1 - ((x1) / 100.);。看起来很完美,非常感谢。下次我会像这样列出我的计算。以这种方式更容易看到相反的情况。
猜你喜欢
  • 2012-11-16
  • 1970-01-01
  • 1970-01-01
  • 2017-06-28
  • 2011-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多