如何在Java中将音频从一种格式转换为wav或raw格式?

如何在Java中将音频从一种格式转换为wav或raw格式?,java,audio,wav,pcm,Java,Audio,Wav,Pcm,我正在尝试找出如何使用将WAV文件转换为RAW/PCM格式。我需要将WAV文件从某些给定的音频格式转换为如下编码的原始文件: 16千赫 16位 单声道 签名 小恩迪亚 我在这里找到的许多帖子都是针对另一种方式的,即如何从原始状态获得WAV。作为一名音频新手,我希望有人能发布一个示例来展示如何做到这一点。据我所知,Java sound api不会转换为原始音频。它确实转换为WAV,即。了解这一点后,您可以将问题分为两部分: 1。将音频从任何格式转换为WAV格式。 public byte[

我正在尝试找出如何使用将WAV文件转换为RAW/PCM格式。我需要将WAV文件从某些给定的音频格式转换为如下编码的原始文件:

  • 16千赫
  • 16位
  • 单声道
  • 签名
  • 小恩迪亚

我在这里找到的许多帖子都是针对另一种方式的,即如何从原始状态获得WAV。作为一名音频新手,我希望有人能发布一个示例来展示如何做到这一点。

据我所知,Java sound api不会转换为原始音频。它确实转换为WAV,即。了解这一点后,您可以将问题分为两部分:

1。将音频从任何格式转换为WAV格式。

   public byte[] formatWavToRaw(@NotNull final byte[] audioFileContent) {
        return Arrays.copyOfRange(audioFileContent, 44, audioFileContent.length);
    }
下面的代码示例仅从WAV到WAV(不同的音频格式)进行了测试,但理论上是对
AudioSystem.getAudioInputStream(audioFormat,originalAudioStream)的调用
应该找到合适的编解码器(如果有)

此方法将音频字节转换为给定格式,并生成字节[]结果作为WAV

 private static final AudioFormat EXAMPLE_FORMAT = new AudioFormat(
        16_000,
        16,
        1,
        true,
        false
    );

    public byte[] formatAudioToWav(@NotNull final byte[] audioFileContent,
                                   @NotNull final AudioFormat audioFormat) throws
                                                                           IOException,
                                                                           UnsupportedAudioFileException {

        try (
            final AudioInputStream originalAudioStream = AudioSystem.getAudioInputStream(new ByteArrayInputStream(audioFileContent));
            final AudioInputStream formattedAudioStream = AudioSystem.getAudioInputStream(audioFormat, originalAudioStream);
            final AudioInputStream lengthAddedAudioStream = new AudioInputStream(formattedAudioStream, audioFormat, audioFileContent.length);
            final ByteArrayOutputStream convertedOutputStream = new ByteArrayOutputStream()
        ) {
            AudioSystem.write(lengthAddedAudioStream, AudioFileFormat.Type.WAVE, convertedOutputStream);
            return convertedOutputStream.toByteArray();
        }
    }
2。从步骤1中创建的WAV文件中删除标题。

   public byte[] formatWavToRaw(@NotNull final byte[] audioFileContent) {
        return Arrays.copyOfRange(audioFileContent, 44, audioFileContent.length);
    }
注释

  • 该代码的优点是可以正确地关闭所有流,但缺点是直接使用byte[],因此无法很好地处理大型文件。它可以转换为纯流,但请注意,在调用
    newaudioinputstream(formattedAudioStream、audioFormat、audioFileContent.length)时,您需要其中一个流的长度
    
  • 另一个缺点是,即使代码清晰可辨,也需要创建/包装3个AudioInputStream来完成这项工作,这有点复杂。我找不到更好的解决办法
进一步阅读

  • 如果我们增加采样/减少采样,是否会失去精度

您可以通过使用
音频输入流
读取WAV文件,并将数据存储在
字节缓冲区
中,从而轻松地从WAV文件中获取PCM数据(以原始字节为单位)

Java确实有一些内置的格式转换器。我不确定是否支持您想要的特定转换。有关支持的格式转换的文档位于

如果你必须进行某种抽取,例如,从采样率为44.1kHz的wav到16kHz,我想使用线性插值是可以的

  • 将传入字节转换为PCM数据值(可能会规范化为浮点)
  • 以2.76625(源自44.1/16)的增量迭代生成的数组,使用线性插值获得新值
  • 将新的PCM值转换回字节
  • 如果没有任何头信息,则可以使用
    FileOutputStream
    将生成的字节数组写入文件


    具有浮点精度的线性插值通常被认为足以保持音频保真度

    你能用一句话说出你的问题是什么或者你到底在绞尽脑汁想什么吗?如果你说你已经解决了自己的问题,你能把解决方案作为答案发布,而不是在问题中发布吗?(我理解得对吗?)你是否在问如何创建一个文件,它是另一个文件的副本,但删除了前44个字节?@andrewjames我还不太熟悉如何发布堆栈溢出问题。现在好点了吗?我添加这篇文章是为了帮助那些遇到与我相同问题的人,因为我找不到一篇文章解释如何做到这一点。当然,我自己的解决方案对我的情况非常有效。