我目前正在尝试使用FFTW3和SFML显示音频频谱。我按照here找到的指示,查看了有关FFT和频谱以及FFTW的大量参考资料,但我的条形图几乎全部与左边对齐,如下所示。我遇到的另一个问题是我无法找到有关FFT输出范围的信息。目前我将它除以64,但它仍然偶尔超过它。而且我还没有找到关于为什么来自FFTW的输出必须与输入大小相同的信息。所以我的问题是:
我得到了什么:
我在寻找:
const int bufferSize = 256 * 8;
void init() {
sampleCount = (int)buffer.getSampleCount();
channelCount = (int)buffer.getChannelCount();
for (int i = 0; i < bufferSize; i++) {
window.push_back(0.54f - 0.46f * cos(2.0f * GMath::PI * (float)i / (float)bufferSize));
}
plan = fftwf_plan_dft_1d(bufferSize, signal, results, FFTW_FORWARD, FFTW_ESTIMATE);
}
void update() {
int mark = (int)(sound.getPlayingOffset().asSeconds() * sampleRate);
for (int i = 0; i < bufferSize; i++) {
float s = 0.0f;
if (i + mark < sampleCount) {
s = (float)buffer.getSamples()[(i + mark) * channelCount] / (float)SHRT_MAX * window[i];
}
signal[i][0] = s;
signal[i][1] = 0.0f;
}
}
void draw() {
int inc = bufferSize / 2 / size.x;
int y = size.y - 1;
int max = size.y;
for (int i = 0; i < size.x; i ++) {
float total = 0.0f;
for (int j = 0; j < inc; j++) {
int index = i * inc + j;
total += std::sqrt(results[index][0] * results[index][0] + results[index][1] * results[index][1]);
}
total /= (float)(inc * 64);
Rectangle2I rect = Rectangle2I(i, y, 1, -(int)(total * max)).absRect();
g->setPixel(rect, Pixel(254, toColor(BLACK, GREEN)));
}
}
答案 0 :(得分:0)
您的所有问题都与FFT理论有关。从任何标准文本/参考书中研究FFT的属性,您只能自己回答问题。
至少你可以从这里开始: https://en.wikipedia.org/wiki/Fast_Fourier_transform。
答案 1 :(得分:0)
许多FFT实现都是能量保留。这意味着输出的比例与输入的比例和/或大小线性相关。
FFT是DFT是方矩阵变换。因此,输出的数量将始终等于输入的数量(或者通过忽略严格实际输入的冗余复共轭半部分的一半),除非丢弃某些输出。如果没有,它不是FFT。如果您想要更少的输出,可以通过其他方式对FFT输出进行下采样或后处理。