我在制作视听器看起来很准确方面遇到了麻烦。具有大量声音的音箱倾向于正确绘制,但我遇到的问题是没有明显声音的所有频率似乎都会返回,其值通常在-60dB和-40dB之间反弹。这形成了扁平的弹跳线(通常在较高的频率中)。
我希望以每秒30帧的速度显示512个或更少的分档。我已经阅读了FFT和音频非停止几周了,到目前为止我的过程一直是:
我用几首歌测试了它,我生成的wav文件只播放440Hz的音调。使用wav文件,我确实在440 bin处获得了一个尖峰,但是所有其他的bin都形成了一个不比440 bin短的行。除了每隔一个框架,除了440之外的垃圾箱看起来像一个图形化的日志功能,还可以放在其他垃圾箱上。
我用c ++写这个。使用STK仅从音频文件加载左声道:
//put every sample in the song into a temporary vector
for (int i = 0; i < stkObject->getSize(); i++)
{
standardVector.push_back(stkObject->tick(LEFT));
}
我正在使用FFTReal来执行FFT:
std::vector<std::vector <double> > leftChannelData;
int numberOfFrames = stkObject->getSize()/samplesPerFrame;
leftChannelData.resize(numberOfFrames);
for(int i = 0; i < numberOfFrames; i++)
{
for(int j = 0; j < FFT_SAMPLE_LENGTH; j++)
{
real[j] = standardVector[j + (i*samplesPerFrame)];
}
applyHannWindow(real, FFT_SAMPLE_LENGTH);
fft_object.do_fft(imaginary,real);
//FFTReal instructions say to run this after an fft
fft_object.rescale(real);
leftChannelData[i].resize(FFT_SAMPLE_LENGTH/2);
for (int j = 0; j < FFT_SAMPLE_LENGTH/2; j++)
{
double magnitude = sqrt(real[j]*real[j] + imaginary[j]*imaginary[j]);
double dbValue = 20 * log(magnitude/maxMagnitude);
leftChannelData[i].at(j) = dbValue;
}
}
我不知道造成这种情况的原因。我已经尝试了各种方法来拉取我忽略的446个样本,但结果似乎没有改变。我想我可能会做一些根本错误的事情。我已经尝试将pcm数据标准化,然后将其交给fft,我已经尝试在找到分贝之前对幅度进行标准化,但它似乎没有起作用。有什么想法吗?
编辑:我没有看到log(幅度)和log(幅度/ maxMagnitude)之间有任何区别。它似乎只是将所有bin的值均匀地向下移动。
EDIT2: 这是他们看起来像是一个视觉效果:
Song playing low sounds - 使用log(mag)
Song playing low sounds - 同样但有log(mag / maxMag)
同样,log(mag)和log(mag / maxMag)通常看起来相同,但值为负数。就像MSalters所说的那样,分贝可以接近 - 无限,因此我可以将这些值钳制到-100dB。然后取log(mag / maxMag)并添加100.这样矩形的高度范围从0到100而不是-100到0.
这是我应该做的吗?我试过这个,但看起来仍然不对劲。也许这只是一个扩展问题?当我这样做的时候,当它听起来应该是这样的时候,很多条都不会让它在线上方。如果他们确实使它高于0,那么他们就这么做了。
答案 0 :(得分:2)
你必须明白,你没有采用无限信号的傅立叶变换,而是采用窗口版本的FT。你的窗户甚至不是一个普通的汉恩窗户。丢弃446个点实际上是矩形窗函数。窗函数的FT将显示在输出中。
其次,dB标度是对数的。这确实意味着它可以在没有信号的情况下变得非常低。你提到-60 dB,但它实际上可以达到负无穷大。唯一可以挽救你的是窗口功能,它会引入大约-110 dB的拖影。
答案 1 :(得分:0)
长度为1024的量子化Von Hann窗口产生的噪声(阻带波纹)可能在-40到-60 dB左右。因此,一种策略是设置一个阈值,并忽略(不要绘制)低于该阈值的所有值。
另外,请尝试删除rescale(real)函数,因为这可能会在您获取对数幅度之前扭曲复杂向量。
另外,请确保您实际上正确地将音频样本加载到真实矢量中(符号,位数和字节)。