Sliding DFT:我认为我的结果是准确的,但我买不到swap-swap IDFT

信息处理 自由度 无限脉冲响应
2022-02-23 22:59:01

我有一个似乎正在工作的滑动 DFT 实现(从输出图判断)。我希望能够使用交换实部和虚部或结合我的数据的标准技巧来反转这个实现。但是,当我尝试这样做时,我的输出看起来与原始输出完全不同。我也最终得到了一个意想不到的强大的虚构成分。(我不完全确定每次通过这个过滤器的正确输出范围。)你能看出这段代码有什么明显的错误吗?谢谢你的时间。

    [TestMethod]
    public void TestInverseDft()
    {
        var rand = new Random(42);
        var dataSize = 50000;
        var data = new List<Complex>(dataSize);
        for(int i = 0; i < dataSize; i++)
            data.Add(new Complex(rand.NextDouble() * 2.0 - 1.0, 0.0));

        var clone = new List<Complex>(data);

        var n = SlidingDFT(data, 44100, 12, 55, 13);

        Swap(data);
        SlidingDFT(data, 44100, 12, 55, 13);
        Swap(data);

        for(int i = 15000; i < dataSize - 15000; i++)
            Assert.AreEqual(clone[i].Real, data[i].Real / n, 0.00001);
    }

    public static int SlidingDFT(IList<Complex> data, int sampleRate, int binsPerOctave, double minFrequency, int stepsFromMin)
    {
        var Q = 1.0 / (Math.Pow(2.0, 1.0 / binsPerOctave) - 1.0); // denominator * Fk gives size of bin 
        var k = (int)(Q + 0.5);

        // frequency at k:
        var Fk = minFrequency * Math.Pow(2.0, (double)stepsFromMin / binsPerOctave);
        var Nk = (int)(Q * sampleRate / Fk + 0.5);
        Complex exp = Complex.Exp(new Complex(0.0, 2.0 * Math.PI * k / Nk));
        var current = data[0];
        for(int x = 0; x < data.Count - 1; x++)
        {
            var lookahead = x + Nk >= data.Count ? new Complex() : data[x + Nk];
            var fx = (lookahead - current) + data[x]; //  * 0.9999999 if unstable?
            current = data[x + 1];
            data[x + 1] = fx * exp;
        }
        return Nk;
    }

    public static void Conjugate(IList<Complex> data)
    {
        for(int i = 0; i < data.Count; i++)
            data[i] = Complex.Conjugate(data[i]);
    }

    public static void Swap(IList<Complex> data)
    {
        for(int i = 0; i < data.Count; i++)
            data[i] = new Complex(data[i].Imaginary, data[i].Real);
    }
1个回答

我没有尝试运行您的代码(那是 C# 吗?)或详细查看它,但在我SlidingDFT()看来更像是Goertzel 算法实现。对您来说,您能够就地执行计算应该是一个危险信号。如果您真的在进行滑动 DFT,那么您的数据速率将扩展 1 倍N,变换的长度;对于每个输入时域样本,您会生成完整的 DFT 输出。

Goertzel 算法是一种高效的递归结构,用于在任意中心频率实现单个 DFT bin,这对于DTMF解码等应用非常有用。但是,您不能在尝试的意义上“反转”它;它更像是一种过滤操作,而不是可逆变换。

对我来说,甚至尝试以您展示的方式反转滑动 DFT 似乎没有意义;滑动 DFT 的输出不会像时域输入那样逐个样本“滑动”。我会阅读更多关于 DFT 及其滑动版本如何工作的内容。