

Join them; it only takes a minute:

Sign up
Join the Stack Overflow community to:
  1. Ask programming questions
  2. Answer and help your peers
  3. Get recognized for your expertise

In a Java program, what is the best way to read an audio file (WAV file) to an array of numbers (float[], short[], ...), and to write a WAV file from an array of numbers?

share|improve this question

Some more detail on what you'd like to achieve would be helpful. If raw WAV data is okay for you, simply use a FileInputStream and probably a Scanner to turn it into numbers. But let me try to give you some meaningful sample code to get you started:

There is a class called for this purpose.

InputStream in = ...;
OutputStream out = ...;

AudioInputStream in = AudioSystem.getAudioInputStream(in);

WaveFileWriter writer = new WaveFileWriter();
writer.write(in, AudioFileFormat.Type.WAVE, outStream);

You could implement your own AudioInputStream that does whatever voodoo to turn your number arrays into audio data.

writer.write(new VoodooAudioInputStream(numbers), AudioFileFormat.Type.WAVE, outStream);

As @stacker mentioned, you should get yourself familiar with the API of course.

share|improve this answer
My main problem was that voodoo itself. I wanted to see if there was ready code/class that did it. I think I succeeded now, using AudioSystem and AudioInputStream. The trick was to reverse the order of bytes in each sound sample before I convert it to short, since WAV encodes the numeric values in little-Endian manner. Thank you, Yonatan. – yonatan Jul 22 '10 at 10:48

The javax.sound.sample package is not suitable for processing WAV files if you need to have access to the actual sample values. The package lets you change volume, sample rate, etc., but if you want other effects (say, adding an echo), you are on your own. (The Java tutorial hints that it should be possible to process the sample values directly, but the tech writer overpromised.)

This site has a simple class for processing WAV files:

share|improve this answer
+1 for the link to the WavFile class. It really does not get much simpler than that. – Grodriguez Sep 12 '13 at 17:50

I read WAV files via an AudioInputStream. The following snippet from the Java Sound Tutorials works well.

int totalFramesRead = 0;
File fileIn = new File(somePathName);
// somePathName is a pre-existing string whose value was
// based on a user selection.
try {
  AudioInputStream audioInputStream = 
  int bytesPerFrame = 
    if (bytesPerFrame == AudioSystem.NOT_SPECIFIED) {
    // some audio formats may have unspecified frame size
    // in that case we may read any amount of bytes
    bytesPerFrame = 1;
  // Set an arbitrary buffer size of 1024 frames.
  int numBytes = 1024 * bytesPerFrame; 
  byte[] audioBytes = new byte[numBytes];
  try {
    int numBytesRead = 0;
    int numFramesRead = 0;
    // Try to read numBytes bytes from the file.
    while ((numBytesRead = != -1) {
      // Calculate the number of frames actually read.
      numFramesRead = numBytesRead / bytesPerFrame;
      totalFramesRead += numFramesRead;
      // Here, do something useful with the audio data that's 
      // now in the audioBytes array...
  } catch (Exception ex) { 
    // Handle the error...
} catch (Exception e) {
  // Handle the error...

To write a WAV, I found that quite tricky. On the surface it seems like a circular problem, the command that writes relies on an AudioInputStream as a parameter. But how do you write bytes to an AudioInputStream? Shouldn't there be an AudioOutputStream?

What I found was that one can take define an object that has access to the raw audio byte data to implement TargetDataLine. This requires a lot of methods be implemented, but most can stay in dummy form as they are not required for writing data to a file. The key method to implement is "read(byte[] buffer, int bufferoffset, int numberofbytestoread)". As this method will probably be called multiple times, there should also be an instance variable that indicates how far through the data one has progressed, and update that as part of the above "read" method.

If you can implement this method, then your object can be used in the creation of a new AudioInputStream which in turn can be used with:

AudioSystem.write(yourAudioInputStream, AudioFileFormat.WAV, yourFileDestination)

As a reminder, an AudioInputStream can be created with a TargetDataLine as a source.

As to the direct manipulating the data, I have had good success acting on the data in the buffer in the innermost loop of the snippet example above, "audioBytes". While you are in that inner loop, you can convert the bytes to ints or floats and multiply a 'volume' value (ranging from 0.0 to 1.0) then convert them back to little endian bytes. I believe since one has access to a series of samples in that buffer one can also engage various forms of DSP filtering algorithms at that stage. I will say, I find it is better to do volume changes directly on data in this buffer because you can make the smallest possible increment: one delta per sample, minimizing the chance of clicks due to volume-induced discontinuities. I find the "control lines" for volume provided by Java tend to situations where the jumps in volume will cause clicks, and I believe this is because the deltas are only implemented at the granularity of a single buffer read (often in the range of one change per 1024 samples) rather than dividing the change into smaller pieces and adding them one per sample. But I'm not at all privvy to how the Volume Controls were implemented, so please take that conjecture with a grain of salt.

All and all, Java.Sound has been a real headache to figure out. I fault the Tutorial for not including an explicit example of writing a file directly from bytes. I fault the Tutorial for burying the best example of Play a File coding in the "How to Convert..." section. However, there's a LOT of valuable FREE info in that tutorial for which I am very grateful! Ah, the life of a programmer. Forums like these, and friendly helpful people have been tremendous, and that is part of what is so great about Java, this community.

PS, Kay, thank you for an awesome book! I consult Core Java as regularly as I consult the Tutorials.

share|improve this answer

WAV File Specification

There is an API for your purpose

share|improve this answer

First of all, you may need to know the headers and data positions of a WAVE structure, you can find the spec here. Be aware that the data are little endian.

There's an API which may helps you to achieve your goal.

share|improve this answer

Wave files are supported by the javax.sound.sample package

Since isn't a trivial API you should read an article / tutorial which introduces the API like

Java Sound, An Introduction

share|improve this answer

This is the source code to write directly to a wav file. You just need to know the mathematics and sound engineering to produce the sound you want. In this example the equation calculates a binaural beat.

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;

public class Example 

    double sampleRate = 44100.0;
    double frequency = 440;
    double frequency2 = 90;
    double amplitude = 1.0;
    double seconds = 2.0;
    double twoPiF = 2 * Math.PI * frequency;
    double piF = Math.PI * frequency2;
    float[] buffer = new float[(int) (seconds * sampleRate)];
    for (int sample = 0; sample < buffer.length; sample++) 
        double time = sample / sampleRate;
        buffer[sample] = (float) (amplitude * Math.cos((double)piF *time)* Math.sin(twoPiF * time));
    final byte[] byteBuffer = new byte[buffer.length * 2];
    int bufferIndex = 0;
    for (int i = 0; i < byteBuffer.length; i++) {
    final int x = (int) (buffer[bufferIndex++] * 32767.0);
    byteBuffer[i] = (byte) x;
    byteBuffer[i] = (byte) (x >>> 8);
    File out = new File("out10.wav");
    boolean bigEndian = false;
    boolean signed = true;
    int bits = 16;
    int channels = 1;
    AudioFormat format;
    format = new AudioFormat((float)sampleRate, bits, channels, signed, bigEndian);
    ByteArrayInputStream bais = new ByteArrayInputStream(byteBuffer);
    AudioInputStream audioInputStream;
    audioInputStream = new AudioInputStream(bais, format,buffer.length);
    AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, out);


If you could modify this to create a hip hop sub bass that would be cool because that's currently what I am trying to modify this program to do.

share|improve this answer

I use FileInputStream with some magic:

    byte[] byteInput = new byte[(int)file.length() - 44];
    short[] input = new short[(int)(byteInput.length / 2f)];


        FileInputStream fis = new FileInputStream(file);, 44, byteInput.length - 45);

    }catch(Exception e  ){

Your sample values are in short[] input!

share|improve this answer
what means: file.length() - 44 did you get to those numbers – To Kra Feb 23 '15 at 18:53
what size would be than int[] ??? – To Kra Feb 23 '15 at 18:55

Your Answer


