Java 将频谱乘以常数后,声音会失真

Java 将频谱乘以常数后,声音会失真,java,audio,signal-processing,fft,audio-processing,Java,Audio,Signal Processing,Fft,Audio Processing,我做了一个简单的声音均衡器,在频域工作,让用户通过使用4个滑块来调整声音的频率。第一个负责0-5kHz,第四个负责15-20kHz 步骤如下: 我读取wav文件并将其存储在浮点数组中 我在该阵列上执行复数fft(分别用于左通道和右通道) 我将代表0-5kHz频率(正和负)的桶的实部和虚部乘以1.13.981,以在最终声音中将这些低频增加10%12dB 我在数组上执行ifft 我交替使用左声道和右声道的实部(由ifft返回)来创建最终音频 问题是,经过这个过程后,声音会失真。听起来好像扬声器没有正

我做了一个简单的声音均衡器,在频域工作,让用户通过使用4个滑块来调整声音的频率。第一个负责0-5kHz,第四个负责15-20kHz

步骤如下:

  • 我读取wav文件并将其存储在浮点数组中
  • 我在该阵列上执行复数fft(分别用于左通道和右通道)
  • 我将代表0-5kHz频率(正和负)的桶的实部和虚部乘以1.13.981,以在最终声音中将这些低频增加10%12dB
  • 我在数组上执行ifft
  • 我交替使用左声道和右声道的实部(由ifft返回)来创建最终音频
  • 问题是,经过这个过程后,声音会失真。听起来好像扬声器没有正确插入。我发现,如果我将ifft返回的值除以任意常数,那么最终的声音是正确的,但要安静得多。我根据ifft的结果在时域中进行划分

    如果我将频率乘以小于1的数字,问题就不会出现。因此,如果频率被衰减,则不需要在时域中进一步划分

    我想整个过程中都有错误。但如果所有步骤都很好,我应该如何处理失真的声音?时域分割是一个合适的解决方案吗?我应该用什么数字来划分结果,这样声音就不会失真

    编辑

    这是我用来执行介绍的步骤的代码。我使用ApacheCommons的FFT数学实现和从中获取的
    SimpleAudioConversion

    //读取文件并将可播放内容存储在字节数组中
    File File=新文件(“/home/kamil/Downloads/glori.wav”);
    AudioInputStream in=AudioSystem.getAudioInputStream(文件);
    AudioFormat fmt=in.getFormat();
    byte[]bytes=新字节[in.available()];
    int result=in.read(字节);
    //将字节转换为浮点数组
    float[]samples=new float[bytes.length*8/fmt.getSampleSizeInBits()];
    int validSamples=simpleudioconversion.decode(字节、样本、结果、fmt);
    //为了使用fft,找到2到0焊盘阵列的最近幂
    整数幂=0;
    while(数学功率(2,功率)
    你可以听这里的声音

    如果在任何一个域中进行放大,最终都可能会截断信号(听起来很可怕)

    因此,您可能需要检查ifft结果,以查看是否有任何采样值超出了音频系统允许的范围(通常为-32768到32768,或-1.0到1.0)。避免任何发现的限幅的方法是降低应用于fft单元的增益,或降低原始输入信号的幅度或总ifft结果

    动态增益控制过程的搜索词是AGC(自动增益控制),这是非常重要的


    e、 g.如果任何特定频率箱的音量已经为“10”,则计算机的旋钮没有“11”。

    根据您使用的FFT库,您可能需要除以N,其中N是FFT的大小。我使用Appache Commons数学库执行规范化。您可能应该在问题中提到这一点,然后点击上面的链接以包含此信息。我更新了问题并发布了代码。你能看看这个吗?
    newdouble[2][(int)Math.pow(2,power)]零初始化Hava中的数组?它不在C++中,所以我问。