简体   繁体   中英

How do I convert audio from one format to wav or raw in Java?

I am trying to figure out how to use the java.sound api to convert a WAV file to RAW/PCM format. I need to convert the WAV file from some given audio format to a RAW file encoded as follows:

  • 16 kHz
  • 16 bits
  • Mono
  • Signed
  • Little endian

Many of the posts I found here are for the other way around, how to go from RAW and get a WAV. Being new to audio, I was hoping someone could post an example showing how to do this.

The Java sound api does not convert to RAW audio as far as I know. It does convert to WAV, which is RAW audio with a 44-byte header . Once you understand this, you can break the problem down into 2 parts:

1. Convert audio from any format to a WAV format.

The code example below has only been tested from WAV to WAV (different audio format), but in theory the call to AudioSystem.getAudioInputStream(audioFormat, originalAudioStream); should find the appropriate codec if it has it.

This method will convert audio bytes to the given format and produce a byte[] result as a 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. Strip the header from the WAV file created in step 1.

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

Notes

  • The code has the advantage of properly closing all the streams, but it has the disadvantage of working with byte[] directly, so it won't work well with large files. It can be converted to pure streams, but notice you need the length of one of the streams in the call to new AudioInputStream(formattedAudioStream, audioFormat, audioFileContent.length); .
  • Another disadvantage is that even if the code is legible, there are 3 AudioInputStream's that need to be created/wrapped to make this work, which is somewhat convoluted. I was unable to find a better solution.

Further Reading

You can easily obtain the PCM data (in raw bytes) from a WAV file by reading it with an AudioInputStream , storing the data in a ByteBuffer perhaps.

Java does have some built in format converters. I'm not sure if the particular conversions you want are supported. Documentation about supported format conversions is at Audio Trail: Using Files and Format Converters

If you have to do some sort of decimation, for example, to go from a wav with 44.1kHz sample rate to 16kHz, I would guess using linear interpolation would be fine.

  1. convert the incoming bytes to PCM data values (perhaps normalizing to floats)
  2. iterate through the resulting array by increments of 2.76625 (derived from 44.1 / 16), using linear interpolation to get your new values
  3. convert the new PCM values back to bytes

The resulting byte array can be written to a file using a FileOutputStream , if there isn't any header info. Java Tutorials: Byte Streams

Linear interpolation with float precision is generally considered good enough for preserving audio fidelity.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM