如何将音频从一种格式转换为 Java 中的 wav 或 raw?
How do I convert audio from one format to wav or raw in Java?
我想知道如何使用 java.sound api 将 WAV 文件转换为 RAW/PCM 格式。我需要将 WAV 文件从一些给定的音频格式转换为编码如下的 RAW 文件:
- 16 kHz
- 16 位
- 单声道
- 已签名
- 小端
我在这里找到的许多 posts 都是相反的,如何从 RAW 转换为 WAV。作为音频新手,我希望有人可以 post 展示如何执行此操作的示例。
据我所知,Java 声音 api 不会转换为 RAW 音频。它确实转换为 WAV,即 RAW audio with a 44-byte header。了解这一点后,您可以将问题分解为两部分:
1.将音频从任何格式转换为 WAV 格式。
下面的代码示例仅从 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 文件中删除 header。
public byte[] formatWavToRaw(@NotNull final byte[] audioFileContent) {
return Arrays.copyOfRange(audioFileContent, 44, audioFileContent.length);
}
备注
- 该代码的优点是可以正确关闭所有流,但缺点是直接使用 byte[],因此不能很好地处理大文件。它可以转换为纯流,但请注意,在对
new AudioInputStream(formattedAudioStream, audioFormat, audioFileContent.length);
的调用中,您需要其中一个流的长度。
- 另一个缺点是,即使代码清晰易读,也有 3 个 AudioInputStream 需要 created/wrapped 才能工作,这有点令人费解。我找不到更好的解决方案。
进一步阅读
- What is raw audio?
- Are there usage examples?
- 如果我们upsample/downsample我们会失去精度吗? A, B
- Is there an online converter to compare results with?
您可以轻松地从 WAV 文件中获取 PCM 数据(以原始字节为单位),方法是使用 AudioInputStream
读取 WAV 文件,将数据存储在 ByteBuffer
中。
Java 确实有一些内置的格式转换器。我不确定是否支持您想要的特定转换。有关支持的格式转换的文档位于 Audio Trail: Using Files and Format Converters
如果您必须进行某种抽取,例如,从 44.1kHz 采样率的 wav 变为 16kHz,我想使用线性插值会很好。
- 将传入字节转换为 PCM 数据值(可能标准化为浮点数)
- 以 2.76625 为增量(从 44.1 / 16 派生)迭代结果数组,使用线性插值获得新值
- 将新的 PCM 值转换回字节
如果没有任何头信息,可以使用 FileOutputStream
将生成的字节数组写入文件。 Java Tutorials: Byte Streams
具有浮点精度的线性插值通常被认为足以保持音频保真度。
我想知道如何使用 java.sound api 将 WAV 文件转换为 RAW/PCM 格式。我需要将 WAV 文件从一些给定的音频格式转换为编码如下的 RAW 文件:
- 16 kHz
- 16 位
- 单声道
- 已签名
- 小端
我在这里找到的许多 posts 都是相反的,如何从 RAW 转换为 WAV。作为音频新手,我希望有人可以 post 展示如何执行此操作的示例。
据我所知,Java 声音 api 不会转换为 RAW 音频。它确实转换为 WAV,即 RAW audio with a 44-byte header。了解这一点后,您可以将问题分解为两部分:
1.将音频从任何格式转换为 WAV 格式。
下面的代码示例仅从 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 文件中删除 header。
public byte[] formatWavToRaw(@NotNull final byte[] audioFileContent) {
return Arrays.copyOfRange(audioFileContent, 44, audioFileContent.length);
}
备注
- 该代码的优点是可以正确关闭所有流,但缺点是直接使用 byte[],因此不能很好地处理大文件。它可以转换为纯流,但请注意,在对
new AudioInputStream(formattedAudioStream, audioFormat, audioFileContent.length);
的调用中,您需要其中一个流的长度。 - 另一个缺点是,即使代码清晰易读,也有 3 个 AudioInputStream 需要 created/wrapped 才能工作,这有点令人费解。我找不到更好的解决方案。
进一步阅读
- What is raw audio?
- Are there usage examples?
- 如果我们upsample/downsample我们会失去精度吗? A, B
- Is there an online converter to compare results with?
您可以轻松地从 WAV 文件中获取 PCM 数据(以原始字节为单位),方法是使用 AudioInputStream
读取 WAV 文件,将数据存储在 ByteBuffer
中。
Java 确实有一些内置的格式转换器。我不确定是否支持您想要的特定转换。有关支持的格式转换的文档位于 Audio Trail: Using Files and Format Converters
如果您必须进行某种抽取,例如,从 44.1kHz 采样率的 wav 变为 16kHz,我想使用线性插值会很好。
- 将传入字节转换为 PCM 数据值(可能标准化为浮点数)
- 以 2.76625 为增量(从 44.1 / 16 派生)迭代结果数组,使用线性插值获得新值
- 将新的 PCM 值转换回字节
如果没有任何头信息,可以使用 FileOutputStream
将生成的字节数组写入文件。 Java Tutorials: Byte Streams
具有浮点精度的线性插值通常被认为足以保持音频保真度。