首页 文章

来自wav的Audio Visualizer看起来不对劲

提问于
浏览
1

我在制作视听器看起来很准确方面遇到了麻烦 . 具有大量声音的音箱倾向于正确绘制,但我遇到的问题是没有明显声音的所有频率似乎都会返回,其值通常在-60dB和-40dB之间反弹 . 这形成了扁平的弹跳线(通常在较高的频率中) .

我希望以每秒30帧的速度显示512个或更少的分档 . 我一直在读FFT和音频不停几个星期了,到目前为止我的过程是:

  • 从wav文件加载pcm数据 . 这是每秒44100个样本,范围为 - / 32767.我假设我将它们作为实数传递给FFT时 .

  • 将这些样本分成每帧1470个 . (446被忽略)

  • 取1024个样本并应用Hann窗口 .

  • 将样本传递给FFT,作为实数[1024]的数组以及另一个相同大小的数组,用虚部填充零 .

  • 通过循环遍历(samples / 2)二进制位并获得一个sqrt(real [i] * real [i] img [i] * img [i])来获得幅度 .

  • 取20 * log(幅度)来获得每个bin的分贝级别

  • 为每个箱子绘制一个矩形 . 为每个帧绘制这些箱子 .

我用几首歌测试了它,我生成的一个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 - 带日志(mag)

Song playing low sounds - 与log(mag / maxMag)相同但相同

同样,log(mag)和log(mag / maxMag)通常看起来相同,但值为负数 . 就像MSalters所说的那样,分贝可以接近 - 无限,因此我可以将这些值钳制到-100dB . 然后取log(mag / maxMag)并添加100.这样矩形的高度范围从0到100而不是-100到0 .

这是我应该做的吗?我试过这个,但看起来仍然不对劲 . 也许这只是一个扩展问题?当我这样做的时候,当它听起来应该是这样的时候,很多条都不会让它在线上方 . 如果他们确实超过0,他们就这么做了 .

2 回答

  • 2

    由长度为1024的量子化Von Hann窗口产生的噪声(阻带纹波)可能在-40到-60dB左右 . 因此,一种策略是仅设置阈值,并忽略(不绘制)低于该阈值的所有值 .

    此外,尝试删除重新缩放(实际)功能,因为这可能会在您获取对数幅度之前扭曲复杂矢量 .

    此外,请确保您实际上正确地将音频样本加载到您的真实向量中(符号,位数和字节顺序) .

  • 0

    你必须明白,你没有采用无限信号的傅里叶变换,而是采用窗口版本的FT . 你的窗户甚至都不是简单的汉恩窗户 . 丢弃446点实际上是矩形窗函数 . 窗口函数的FT将显示在输出中 .

    其次,dB标度是对数的 . 这确实意味着它可以在没有信号的情况下变得非常低 . 你提到-60 dB,但它实际上可以达到负无穷大 . 唯一可以挽救你的是窗口功能,它会引入约-110 dB的拖影 .

相关问题