【问题标题】:Odd function used for signal processing?用于信号处理的奇函数?
【发布时间】:2018-09-18 06:51:05
【问题描述】:

你好!我希望这是一个可以接受的问题。

通过一些用于信号处理的代码,我发现了一个奇怪的函数:

let kInd = (k1, pow) => {

  let k2 = 0;
  let k3 = 0;

  for (let i = 0; i < pow; i++) {
    k3 = k1 >> 1;
    k2 = 2 * (k2 - k3) + k1;
    k1 = k3;
  }

  return k2;

};

在傅立叶变换计算结束时调用此函数,以交换实数+虚数数组对中的索引:

let fft = samples => {

  let pow = Math.log2(samples.length); // `samples.length` is expected to be 2^int

  // ... a bunch of code to generate `rBuff` and `iBuff` arrays representing 
  // real and imaginary components of fourier values

  // Now make use of `kInd`; conditionally swap some indexes in `rBuff` and `iBuff`:
  for (let i = 0; i < rBuff.length; i++) {
    let k = kInd(i, pow);
    if (k >= i) continue;
    [ rBuff[i], rBuff[k] ] = [ rBuff[k], rBuff[i] ];
    [ iBuff[i], iBuff[k] ] = [ iBuff[k], iBuff[i] ];
  }

  // ... A bit of code to convert to power spectrum and return result

};

我的问题是:kInd 到底在做什么? 我已经运行它来输出一些示例值;随着 k1 参数的增加,它看起来以几乎随机的顺序输出 2 的幂和。对kInd 的小改动会导致来自fft 的结果完全错误。

谢谢!

(注意:如果更多代码有帮助,请告诉我。为了读者的利益,尽量保持简短!)

【问题讨论】:

  • 为什么不问问写它的程序员呢?
  • 我愿意!不再可用。
  • 只看代码,从右到左遍历k1的每一位,然后设置k2 = k2*2为0,k2 = k2*2+1为1,不知道为什么这个数字是相关的。
  • 它看起来像位反转的(一种变体),例如en.wikipedia.org/wiki/Bit-reversal_permutation

标签: javascript signal-processing fft


【解决方案1】:

这实现了FFT算法的butterfly操作。

例如,运行...

console.log([0,1,2,3,4,5,6,7].map(i => kInd(i, 3)))

...打印...

[ 0, 4, 2, 6, 1, 5, 3, 7 ]

...这是图中的映射:

http://www.alwayslearn.com/DFT%20and%20FFT%20Tutorial/DFTandFFT_FFT_Butterfly_8_Input.html

【讨论】:

  • 啊哈!!这就是我要找的东西!
  • 这应该是公认的答案,因为它直接回答你的问题比我的好!
【解决方案2】:

看起来像是某种重新排序。

let kInd = (k1, pow) =>{
  let k2 = 0;
  let k3 = 0;

  for (let i = 0; i < pow; i++) {
    k3 = k1 >> 1;
    k2 = 2 * (k2 - k3) + k1;
    k1 = k3;
  }
  return k2;
};

const format = (s, p = 5) => s.toString().padStart(p);

var i,
    l = 16,
    pow = Math.log2(l);
    
for (i = 0; i < l; i++) {
    document.getElementById('out').innerHTML += `${format(i)} ${format(kInd(i, pow))}<br>`;
}
&lt;pre id="out"&gt;&lt;/pre&gt;

【讨论】:

    【解决方案3】:

    对于任何给定的pow,输入递增的i 会产生ks 的循环。循环的长度是2^pow 下面的代码将显示两个循环,每个pow 增加一个i。有趣的是is 的模式导致ks 大于或等于i(在下面的输出中以粗体显示)。

    对于每个 pow,k(i) &gt;= ii=0 开头的模式是什么:

    战俘 0:TFFF...

    战俘 1:TTFFF...

    战俘 2:TTFTFTFFF...

    战俘 3:TTTTFTFTFFF...

    战俘 4:TTTTFTTTFTFTFFFTFFF...

    战俘 5:TTTTTTTTFTTTFTTTFTFTFTFTFFFTFFFTFFF...

    let kInd = (k1, pow) => {
      let k2 = 0;
      let k3 = 0;
    
      for (let i = 0; i < pow; i++) {
        k3 = k1 >> 1;
        k2 = 2 * (k2 - k3) + k1;
        k1 = k3;
      }
      return k2;
    };
    
    for (let p = 0; p < 7; p++) {
      for (let i = 0; i < Math.pow(2, p) * 2; i++) {
        let k = kInd(i, p)
        if (k >= i) {
          $('#output').append("<p><b>" + i + "&nbsp;&nbsp;&nbsp;" + p + "->" + k + "</b></p>");
        } else {
          $('#output').append("<p>" + i + "&nbsp;&nbsp;&nbsp;" + p + "->" + k + "</p>");
        }
      }
      $('#output').append("<p>----------------</p>");
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div id="output"></div>

    我知道这不是答案,但我想提供帮助,但评论不适合我想放在这里的格式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-03
      • 2012-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-12
      • 1970-01-01
      相关资源
      最近更新 更多