最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

math - Discrete Fourier Transforms in Javascript - Stack Overflow

programmeradmin1浏览0评论

I want to present the pulse wave using Highcharts. With idea data, the chart is fine as image

However, when there are noises, the algorithm does not work image with bad points

so I decided to do with Fourier transform.

Is there any library can do the DFT? or I have to write it myself.

please tell me the library name or way to solve this question and how do you get the idea.

Thanks a lot!

I want to present the pulse wave using Highcharts. With idea data, the chart is fine as image

However, when there are noises, the algorithm does not work image with bad points

so I decided to do with Fourier transform.

Is there any library can do the DFT? or I have to write it myself.

please tell me the library name or way to solve this question and how do you get the idea.

Thanks a lot!

Share Improve this question edited Jun 20, 2020 at 9:12 CommunityBot 11 silver badge asked Jun 3, 2017 at 12:13 邓启凡邓启凡 491 silver badge4 bronze badges 3
  • github./scijs/fourier-transform/blob/master/benchmark.md gives a nice list to start with, or search npm – ccprog Commented Jun 3, 2017 at 13:58
  • Due to my poor math and eng... although I had read the repository fourier days ago, I didn't get how to use it to do 1d fft... can you just show me about how to transform the 'sin(x)' with it? thanks! – 邓启凡 Commented Jun 3, 2017 at 14:51
  • I have coded another function to solve this problem and it works well to replace the thorns of the wave. and here it is (you need to set proper two value at the very begin)Array.prototype.smooth = function (strength) { var len = this.length; var dis_arg, dis, dis_sum = 0; for (var i = 0; i < len - 1; i++) { dis_sum += Math.abs((this[i + 1] - this[i])); dis_arg = dis_sum / i; dis = Math.abs(this[i + 1] - this[i]); if (dis / dis_arg > strength) { this[i + 1] = 2 * this[i] - this[i - 1]; } } }; – 邓启凡 Commented Jun 7, 2017 at 9:14
Add a ment  | 

2 Answers 2

Reset to default 5

You may implement it by yourself if you want. Here is an example of how Discrete Fourier Transform function may be implemented in ES6:

import ComplexNumber from '../plex-number/ComplexNumber';

const CLOSE_TO_ZERO_THRESHOLD = 1e-10;

/**
 * Discrete Fourier Transform (DFT): time to frequencies.
 *
 * Time plexity: O(N^2)
 *
 * @param {number[]} inputAmplitudes - Input signal amplitudes over time (plex
 * numbers with real parts only).
 * @param {number} zeroThreshold - Threshold that is used to convert real and imaginary numbers
 * to zero in case if they are smaller then this.
 *
 * @return {ComplexNumber[]} - Array of plex number. Each of the number represents the frequency
 * or signal. All signals together will form input signal over discrete time periods. Each signal's
 * plex number has radius (amplitude) and phase (angle) in polar form that describes the signal.
 *
 * @see https://gist.github./anonymous/129d477ddb1c8025c9ac
 * @see https://betterexplained./articles/an-interactive-guide-to-the-fourier-transform/
 */
export default function dft(inputAmplitudes, zeroThreshold = CLOSE_TO_ZERO_THRESHOLD) {
  const N = inputAmplitudes.length;
  const signals = [];

  // Go through every discrete frequency.
  for (let frequency = 0; frequency < N; frequency += 1) {
    // Compound signal at current frequency that will ultimately
    // take part in forming input amplitudes.
    let frequencySignal = new ComplexNumber();

    // Go through every discrete point in time.
    for (let timer = 0; timer < N; timer += 1) {
      const currentAmplitude = inputAmplitudes[timer];

      // Calculate rotation angle.
      const rotationAngle = -1 * (2 * Math.PI) * frequency * (timer / N);

      // Remember that e^ix = cos(x) + i * sin(x);
      const dataPointContribution = new ComplexNumber({
        re: Math.cos(rotationAngle),
        im: Math.sin(rotationAngle),
      }).multiply(currentAmplitude);

      // Add this data point's contribution.
      frequencySignal = frequencySignal.add(dataPointContribution);
    }

    // Close to zero? You're zero.
    if (Math.abs(frequencySignal.re) < zeroThreshold) {
      frequencySignal.re = 0;
    }

    if (Math.abs(frequencySignal.im) < zeroThreshold) {
      frequencySignal.im = 0;
    }

    // Average contribution at this frequency.
    // The 1/N factor is usually moved to the reverse transform (going from frequencies
    // back to time). This is allowed, though it would be nice to have 1/N in the forward
    // transform since it gives the actual sizes for the time spikes.
    frequencySignal = frequencySignal.divide(N);

    // Add current frequency signal to the list of pound signals.
    signals[frequency] = frequencySignal;
  }

  return signals;
}

This function is just directly implements the formula:

The function is pretty slow and has O(n^2) time plexity. If speed does matter to you you may go with Fast Fourier Transform instead:

More details with descriptions here https://github./trekhleb/javascript-algorithms/tree/master/src/algorithms/math/fourier-transform

I made a suggestion in another thread on Stack Overflow: Fast Fourier Transform Javascript .
It accepts entry of a 1D array, assumes they are equally spaced, and outputs the DFT. Perhaps this is what you are looking for?

发布评论

评论列表(0)

  1. 暂无评论