Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将FFT转换为spectrogram_C++_Fft_Spectrogram_Intel Ipp - Fatal编程技术网

C++ 将FFT转换为spectrogram

C++ 将FFT转换为spectrogram,c++,fft,spectrogram,intel-ipp,C++,Fft,Spectrogram,Intel Ipp,我有一个音频文件,我在文件中迭代,每一步采集512个样本,然后通过FFT传递它们 我将数据输出为块514长浮动(使用IPP的IPPSFFTFFWD_RToCCS_32f_I),实部和虚部交错 我的问题是,一旦我有了这些复数,我该怎么处理它们呢?目前我正在为每一个值做准备 const float realValue = buffer[(y * 2) + 0]; const float imagValue = buffer[(y * 2) + 1]; const float value

我有一个音频文件,我在文件中迭代,每一步采集512个样本,然后通过FFT传递它们

我将数据输出为块514长浮动(使用IPP的IPPSFFTFFWD_RToCCS_32f_I),实部和虚部交错

我的问题是,一旦我有了这些复数,我该怎么处理它们呢?目前我正在为每一个值做准备

const float realValue   = buffer[(y * 2) + 0];
const float imagValue   = buffer[(y * 2) + 1];
const float value       = sqrt( (realValue * realValue) + (imagValue * imagValue) );
这提供了一些稍微有用的东西,但我更愿意以某种方式获得0到1范围内的值。上面提到的问题是,峰值最终会回到大约9或更多。这意味着,当我通过海选的声谱图播放音频时,声谱图的其他部分几乎没有显示出来,尽管它们看起来很强。我完全承认,我不能100%确定FFT返回的数据是什么(除了它代表我传入的512个样本长块的频率值)。尤其是我对compex数字的确切含义缺乏了解

任何建议和帮助都将不胜感激

编辑:只是澄清一下。我最大的问题是,如果不知道尺度是什么,返回的FFT值是没有意义的。有人能告诉我如何计算那个比例吗

Edit2:通过执行以下操作,我得到了非常好看的结果:

size_t count2   = 0;
size_t max2     = kFFTSize + 2;
while( count2 < max2 )
{
    const float realValue   = buffer[(count2) + 0];
    const float imagValue   = buffer[(count2) + 1];
    const float value   = (log10f( sqrtf( (realValue * realValue) + (imagValue * imagValue) ) * rcpVerticalZoom ) + 1.0f) * 0.5f;
    buffer[count2 >> 1] = value;
    count2 += 2;
}
size\u t count2=0;
大小\u t max2=kffsize+2;
while(count2>1]=值;
count2+=2;
}
在我看来,这甚至比我看过的大多数其他光谱图实现都要好


我所做的有什么主要错误吗?

如果你得到奇怪的结果,那么需要检查的一件事是FFT库的文档,以查看输出是如何打包的。一些例程使用压缩格式,其中实/虚值交错,或者它们可能从N/2元素开始并环绕

对于健全性检查,我建议创建具有已知特征的样本数据,例如Fs/2、Fs/4(Fs=样本频率),并将FFT例程的输出与您期望的结果进行比较。尝试以相同的频率创建正弦和余弦,因为它们在频谱中应具有相同的幅值,但具有不同的相位(即realValue/imagValue将不同,但平方和应相同)


如果您打算使用FFT,那么您真的需要知道它在数学上是如何工作的,否则您可能会遇到其他奇怪的问题,例如混叠。

要使所有FFT可见,通常要做的是取幅值的对数


因此,输出缓冲区的位置告诉您检测到的频率。复数的大小(L2范数)告诉您检测到的频率有多强,相位(反正切)给你的信息在图像空间比音频空间重要得多。因为FFT是离散的,频率从0到奈奎斯特频率。在图像中,第一项(DC)通常是最大的,因此如果这是你的目标,它是用于标准化的一个很好的候选者。我不知道这是否也适用于音频(我对此表示怀疑)

对于512个样本的每个窗口,您都会像计算一样计算FFT的幅度。每个值表示信号中存在的相应频率的幅度

mag
 /\
 |
 |      !         !
 |      !    !    !
 +--!---!----!----!---!--> freq
 0          Fs/2      Fs
现在我们需要计算出频率

由于输入信号为实数,FFT在中间(奈奎斯特分量)对称,第一项为直流分量。已知信号采样频率
Fs
,奈奎斯特频率为Fs/2。因此对于索引
k
,相应的频率为
k*Fs/512


因此,对于长度为512的每个窗口,我们得到指定频率下的震级。连续窗口上的一组震级构成了频谱图。

我认为有一些东西对您会有所帮助

前向FT在输出中给出的数字往往比在输入中给出的数字大。你可以将其视为某个频率下的所有强度都显示在一个位置,而不是分布在数据集中。这有关系吗?可能不是因为你总是可以根据需要缩放数据。我曾经写过一篇基于整数的文章FFT/IFFT对和每个过程都需要重新缩放以防止整数溢出

您输入的真实数据被转换为几乎复杂的数据。事实证明,缓冲区[0]和缓冲区[n/2]是真实的、独立的。对此有很好的讨论

输入数据是随时间变化的等间距声强值。它们被称为在时域中。FT的输出被称为在频域中,因为水平轴是频率。垂直标度保持强度。虽然从输入数据看不明显,但存在相位信息输入中也存在相位。虽然所有声音都是正弦的,但没有任何东西可以固定正弦波的相位。该相位信息在频域中显示为单个复数的相位,但我们通常不关心它(我们也经常关心!)。它只取决于你在做什么。计算

const float value = sqrt((realValue * realValue) + (imagValue * imagValue));
检索强度信息,但丢弃相位信息。取对数基本上只是抑制大峰值


希望这会有帮助。

让人们知道我在整个问题上做了很多工作。我发现的主要问题是FFT在完成后需要归一化

要做到这一点,您需要平均窗口向量的所有值