如何将一组离散数据传输到频域并返回(最好是无损耗) [英] How can I transfer a discrete set of data into the frequency domain and back (preferrably losslessly)

查看:194
本文介绍了如何将一组离散数据传输到频域并返回(最好是无损耗)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想获取大小为70-80k的字节数组,并将它们从时域转换到频域(可能使用DFT)。到目前为止,我一直关注wiki并获得此代码。

I would like to take an array of bytes of roughly size 70-80k and transform them from the time domain to the frequency domain (probably using a DFT). I have been following wiki and gotten this code so far.

for (int k = 0; k < windows.length; k++) {
        double imag = 0.0;
        double real = 0.0;
        for (int n = 0; n < data.length; n++) {
            double val = (data[n])
                    * Math.exp(-2.0 * Math.PI * n * k / data.length)
                    / 128;
            imag += Math.cos(val);
            real += Math.sin(val);
        }
        windows[k] = Math.sqrt(imag * imag + real
                * real);
}

据我所知,找到每个频率窗口的幅度/完事。然后我穿过窗户找到最高等级的窗户。我在重建信号时为该频率添加一个标志。我检查重建的信号是否与我的原始数据集匹配。如果它没有找到下一个最高频率窗口并标记在重建信号时要使用的窗口。

and as far as I know, that finds the magnitude of each frequency window/bin. I then go through the windows and find the one with the highest magnitude. I add a flag to that frequency to be used when reconstructing the signal. I check to see if the reconstructed signal matches my original data set. If it doesn't find the next highest frequency window and flag that to be used when reconstructing the signal.

这是我重建信号的代码,我大多肯定这是错误的(它应该执行IDFT):

Here is the code I have for reconstructing the signal which I'm mostly certain is very wrong (it is supposed to perform an IDFT):

for (int n = 0; n < data.length; n++) {
        double imag = 0.0;
        double real = 0.0;
        sinValue[n] = 0;
        for (int k = 0; k < freqUsed.length; k++) {
            if (freqUsed[k]) {
                double val = (windows[k] * Math.exp(2.0 * Math.PI * n
                        * k / data.length));
                imag += Math.cos(val);
                real += Math.sin(val);
            }
        }
        sinValue[n] = imag* imag + real * real;
        sinValue[n] /= data.length;
        newData[n] = (byte) (127 * sinValue[n]);
}

freqUsed是一个布尔数组,用于标记频率窗口是否应该是在重建信号时使用。

freqUsed is a boolean array used to mark whether or not a frequency window should be used when reconstructing the signal.

无论如何,出现以下问题:

Anyway, here are the problems that arise:


  1. 即使全部使用频率窗口,不重建信号。这可能是因为...

  2. 有时,Math.exp()的值太高,因此返回无穷大。这使得很难得到准确的计算。

  3. 虽然我一直关注维基作为指南,但我很难判断我的数据是否有意义。这使得很难测试和识别问题。

问题的解决:

我对此很新,并不完全理解一切。因此,任何帮助或见解都表示赞赏。感谢您花时间阅读所有内容,并提前感谢您提供的任何帮助。任何帮助真的会很好,即使你认为我这样做是最糟糕的可能方式,我想知道。再次感谢。

I am fairly new to this and do not fully understand everything. Thus, any help or insight is appreciated. Thanks for even taking the time to read all of that and thanks ahead of time for any help you can provide. Any help really would be good, even if you think I'm doing this the most worst awful way possible, I'd like to know. Thanks again.

-

编辑:

所以我更新了我的代码:

So I updated my code to look like:

for (int k = 0; k < windows.length; k++) {
        double imag = 0.0;
        double real = 0.0;
        for (int n = 0; n < data.length; n++) {
            double val = (-2.0 * Math.PI * n * k / data.length);
            imag += data[n]*-Math.sin(val);
            real += data[n]*Math.cos(val);
        }
        windows[k] = Math.sqrt(imag * imag + real
                * real);
}

原始转换和:

for (int n = 0; n < data.length; n++) {
    double imag = 0.0;
    double real = 0.0;
    sinValue[n] = 0;
    for (int k = 0; k < freqUsed.length; k++) {
        if (freqUsed[k]) {
            double val = (2.0 * Math.PI * n
                    * k / data.length);
            imag += windows[k]*-Math.sin(val);
            real += windows[k]*Math.cos(val);
        }
    }
    sinValue[n] = Math.sqrt(imag* imag + real * real);
    sinValue[n] /= data.length;
    newData[n] = (byte) (Math.floor(sinValue[n]));
}

用于逆变换。虽然我仍然担心它不能正常工作。我生成了一个包含单个正弦波的数组,它甚至无法分解/重建。关于我缺少什么的任何见解?

for the inverse transform. Though I am still concerned that it isn't quite working correctly. I generated an array holding a single sine wave and it can't even decompose/reconstruct that. Any insight as to what I'm missing?

推荐答案

是的,您的代码(对于DFT和IDFT)都已损坏。您对如何使用指数的问题感到困惑。 DFT可以写成:

Yes, your code (for both DFT and IDFT) is broken. You are confusing the issue of how to use the exponential. The DFT can be written as:

       N-1
X[k] = SUM { x[n] . exp(-j * 2 * pi * n * k / N) }
       n=0

其中 j 是sqrt(-1)。这可以表示为:

where j is sqrt(-1). That can be expressed as:

       N-1
X[k] = SUM {   (x_real[n] * cos(2*pi*n*k/N) + x_imag[n] * sin(2*pi*n*k/N))
       n=0  +j.(x_imag[n] * cos(2*pi*n*k/N) - x_real[n] * sin(2*pi*n*k/N)) }

又可拆分为:

            N-1
X_real[k] = SUM { x_real[n] * cos(2*pi*n*k/N) + x_imag[n] * sin(2*pi*n*k/N) }
            n=0

            N-1
X_imag[k] = SUM { x_imag[n] * cos(2*pi*n*k/N) - x_real[n] * sin(2*pi*n*k/N) }
            n=0

如果你的输入数据是真实的,这简化为:

If your input data is real-only, this simplifies to:

            N-1
X_real[k] = SUM { x[n] * cos(2*pi*n*k/N) }
            n=0

            N-1
X_imag[k] = SUM { x[n] * -sin(2*pi*n*k/N) }
            n=0

总而言之,你不需要两者兼顾 exp cos / sin

So in summary, you don't need both the exp and the cos/sin.

这篇关于如何将一组离散数据传输到频域并返回(最好是无损耗)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆