我一直在从Apple的示例代码(found here)看aurioTouch 2。归根结底,我想自己分析一下频率。现在,我试图了解这里发生的一些情况。如果这是微不足道的,我深表歉意,只是想了解一些未注释的魔术数字,这些数字在某些来源中四处飘荡。我目前的主要困惑是:

  • 为什么它们将FFTBufferManager::ComputeFFT中的nyquist值归零?真的可以丢掉这个值吗? (〜FFTBufferManager.cpp的第112行)。
  • 他们将所有内容按比例缩小-128db,因此我假设结果在(-128,0)范围内。但是,稍后在aurioTouchAppDelegate.mm中(〜第807行),他们通过加80并除以64,然后钳位为0和1,将其转换为0和1之间的值。另外,我是否可以假设值将在(-128,0)附近?
  • 最佳答案

    好吧,这对我来说也不是小事,但这就是我的理解。如果我过于简化,那纯粹是为了我的利益,我并不是要光顾。

    将与奈奎斯特频率相对应的结果归零:

    我假设我们正在计算1024个输入样本的正向FFT。在我的情况下,输入为44100hz通常是正确的(但不是AurioTouch所做的,我觉得有点奇怪,但我不是专家)。对于我来说,使用特定的值更容易理解。

    给定1024(n)个输入样本,根据需要进行排列(偶数索引首先,然后是奇数索引{{in [0],in [2],in [4],…,1,in [3],in [5] ,…})(使用vDSP_ctoz()来订购您的输入)

    FFT 1024 (n)输入样本的输出是 513 ((n/2)+1)个复数值。即 513个实际组件和 513个虚构的组件,总共 1026个值。

    但是,虚数[0] 虚数[512] (n/2)始终是。因此,通过在虚数[0] 处放置实数[512] (奈奎斯特频率仓的实部),并忽略虚数[512] -始终为零且可以推断出,结果被打包为 1024个(n)长度缓冲区。

    因此,为使返回的结果有效,您必须至少将 imaginary [0] 设置回零。如果您需要所有 513 ((n/2)+1)个频点,则需要向结果附加另一个复数值并进行设置。

    unpackedVal = imaginary[0]
    real[512]=unpackedVal, imaginary[512]=0
    imaginary[0] = 0
    

    在AurioTouch中,我一直以为他们不会打扰。 n/2结果显然更方便使用,并且您无法从可视化器中看出:“哦,它在Nyquist频率上丢失了一个量级”

    The UsingFourierTransforms docs explain the packing

    注意,特定值1024、513、512等仅为示例,而不是AurioTouch的n,(n/2)+ 1,n/2的实际值。

    他们将所有内容缩减了-128db

    不完全是,输出值的范围是相对于输入样本数的,因此必须对其进行归一化。比例为1.0/(2 * inNumberFrames)。

    缩放后,范围为 -1.0 –> +1.0 。然后获取复数矢量的大小(忽略相位),从而为 0到1.0 之间的每个频点提供标量值

    然后将此值解释为 -128和0 之间的分贝值

    绘图内容…+80/64。…* 120……我不确定。我可能完全错了,或者可能是……艺术许可?

    10-06 13:26