将音频样本的字节数组转换为频率。

3

首先,我有一个项目需要在Java中更改WAVE文件的频率。

我使用了Java中的AudioSystem来获取音频数据的字节(不包括文件头)。现在我得到了数据的字节数组,我想把它从时间域转换为频率域,并在操作频率后,将其重新转换为时间域。以下是代码:

public byte[] getWAVByte(){
    ByteArrayOutputStream out = new ByteArrayOutputStream();

    try{
        File f = new File("audio.wav");
        AudioInputStream in = AudioSystem.getAudioInputStream(f);

        int read;

        byte[] buff = new byte[(int)f.length()];
        while ((read = in.read(buff)) > 0)
        {
            out.write(buff, 0, read);
        }
        out.flush();
        byte[] audioBytes = out.toByteArray();

        return audioBytes;
    }catch(Exception e){
        e.printStackTrace();
    }

}

现在我有一个音频字节数组audioBytes,我想将它转换为另一个频域字节数组。我读到可以使用傅里叶变换来实现,但我的老师说这非常复杂,而且不在我的项目范围内。那么有没有其他方法可以实现呢?或者有没有Java库可以帮助我获得频域字节数组?


2
可能是在Java中使用傅里叶变换处理音频数据的重复问题。 - Bludzee
1
你说:“我有一个项目需要改变WAVE文件的频率”,正确的方法并不简单。你似乎想要进行音高转换,简单但不正确的方法是在不同的采样率下播放音频,但这会改变音频的速度。你可以在频域中完成它,必须计算FFT... - ederwander
是的,我已经尝试过更改采样率,但它变得更快了,对我来说变得相当嘈杂。 我还尝试通过将每两个字节更改为短类型并操纵数据字节来进行操作,然后将其转换回字节,但似乎会改变振幅(如果我将其乘以二,则声音变得更响亮,如果我将其除以二,则声音变得更弱)。 - catherine
2个回答

0

感谢ederwander在音高转换方面的指导。

TarsosDSP将Stephan M. Bernsee的代码移植到了Java 这里,他们还提供了使用另一种方法的示例这里

最终我使用了Superpowered AdvancedAudioPlayer类,因为我已经在其他用途中使用它了。你只需要在audioProcessing回调的开头添加两行代码,就可以使用PlayerExample项目了:

player->setTempo(1.0, true); // Needed for the pitch shifting to work
player->setPitchShift(-12); // Pitch shift one octave down

0

Stephan M. Bernsee写了如何在频域中实现它,你可以找到源代码以C为基础进行下载,还有一个人将其移植到Java,祝你好运!

http://svn.assembla.com/svn/mm1ws08/Abgabe2/src/Effects/PitchShift.java

如果你将一个值乘以或除以字节数组,那么你只是增加或减小振幅信号,要在时间域中改变频率,你需要找到声门位置点击,对每个声门位置应用一个居中的窗口,然后将每个窗口移动到一个新的时间位置,在这一步中,你可以添加或排除一些窗口,这会改变信号的频率,并最终对所有窗口化的声门进行重叠添加,这种方法称为PSOLA


这段Java代码似乎无法正常工作(看起来像是一个从未完成的学校项目)。您可以链接到此处:https://github.com/JorenSix/TarsosDSP/blob/master/src/core/be/tarsos/dsp/PitchShifter.java - Alexis R

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接