Projects

New Music



Blog Roll



Support This Site

Reading and Writing Wav Files in Java

Earlier this year, we looked at how to read and write wav files in C++ and VB.Net, and C/C++ is really the natural choice for this kind of file IO (for a number of reasons that we won't go into here). Nonetheless, it is important to understand the process in other languages, if you want to be the type of language-agnostic programmer who can approach computer music in any environment.

So today we are looking at reading and writing wav files in Java. Surprisingly, this is the trickiest one of them all.

Java Numbers

The problem is that Java has no unsigned types. In other words, all numerical types in java can hold either positive or negative numbers. There are no types that are designed for only positibe numbers.

This doesn't sound like a big deal unless you know a little bit about how negative numbers are represented in most programming languages. The most important thing to know is that most languages represent negative numbers, in a way that is incompatible with the way they represent only positive numbers. More specifically, wav file headers represent numbers as unsigned bytes, whereas java represents numbers using a format called Two's Complement.

The practical implications of this are simple: you can't use java's built-in IO functions for reading wav headers. You have to read the data as bytes, then do the conversion in a subroutine.

Understanding this problem is hard, but luckily, working around it is relatively easy. In our solution, we made 2 changes. First, we stored all of our numbers with more bytes than are necessary in other languages (to ensure that we are storing the correct numbers). So for each 2-byte number, which would usually be stored by a short, we used an int, and for each 4-byte number, we used a long. Then we added 4 extra subroutines to do the conversions for us. These routines are at the bottom of wavIO.java.

// these two routines convert a byte array to a unsigned short
public static int byteArrayToInt(byte[] b)
{
  int start = 0;
  int low = b[start] & 0xff;
  int high = b[start+1] & 0xff;
  return (int)( high << 8 | low );
}

// these two routines convert a byte array to an unsigned integer
public static long byteArrayToLong(byte[] b)
{
  int start = 0;
  int i = 0;
  int len = 4;
  int cnt = 0;
  byte[] tmp = new byte[len];
  for (i = start; i < (start + len); i++)
  {
    tmp[cnt] = b[i];
    cnt++;
  }
  long accum = 0;
  i = 0;
  for ( int shiftBy = 0; shiftBy < 32; shiftBy += 8 )
  {
    accum |= ( (long)( tmp[i] & 0xff ) ) << shiftBy;
    i++;
  }
  return accum;
}

// returns a byte array of length 4
private static byte[] intToByteArray(int i)
{
  byte[] b = new byte[4];
  b[0] = (byte) (i & 0x00FF);
  b[1] = (byte) ((i >> 8) & 0x000000FF);
  b[2] = (byte) ((i >> 16) & 0x000000FF);
  b[3] = (byte) ((i >> 24) & 0x000000FF);
  return b;
}

// convert a short to a byte array
public static byte[] shortToByteArray(short data)
{
  return new byte[]{(byte)(data & 0xff),(byte)((data >>> 8) & 0xff)};
}

WAV File Specification

Again, we are using a VERY basic version of the wav file format for this example. This won't read many wav files, it will only read what are referred to here as canonical wave files. Basically, old fashioned wav files (before the chaos introduced by 24 and 32 bit recording).

If you want to read more complicated wav files, you may want to check out what's written here and here, although you really need to look at the actual specification (and you had better have some free time).

The Source Code

To use the source code, just unzip all the files into the same directory, and then use the batch files I created called compile.bat and run.bat. Of course, I am assuming that you have the latest version of java installed.

Download the source code for reading and writing wav files in java here.


Posted by Evan on August 29, 2008
Sharing:
lebeth at 2008-02-25 23:49:47team audiosurf
Thanks so much for this! I really enjoy it.
vogelap at 2008-02-26 07:04:31IRON CHEF fan
Thanks! Very cool!!!
Zelda Duck at 2008-02-26 11:11:12BADASS
Awesome work! We really need a community of -composers- level designers for audiosurf! :D
Evan at 2008-02-26 11:30:13
That's a great idea, Zelda Duck. If you, or anyone else, writes something for AudioSurf, send me a link: evan (at) thisisnotalabel (dot) com

One problem with that is that it's tough to distinguish between music written for AudioSurf, and just music in general. That's part of the reason why I tried to make a lot of Surf-related references in the suite above. From the titles, to the samples used, to the actual contour in Dunes, I tried to saturate the music with beach images.

Patrick Alexander at 2008-02-26 22:06:10Plugged!
Here you go: http://www.eegra.com/pages/show/title/26_02_2008_Speaking_of_Audiosurf___/ Hope it sends at least a handful of hits your way. Well done on being the first person to do this, and thanks! I'm very curious to see (hear, rather) all the variations on the same concept, that I expect will appear before too long.
Matt Burris at 2008-03-01 07:00:27Audiosurf Video
Just to let you know, I've posted a video of me playing Horizon on AudioSurfBoard: http://audiosurfboard.com/2008/03/01/evan-x-merz-horizon/ Great job, I enjoy all 5 songs, they create fun tracks in Audiosurf.
evan at 2008-03-01 11:35:34Posted
Thanks for the video. I posted it in an update.
at 2008-03-15 20:36:20fedemacloiner
hola soy de argentina..este juego esta buenisimo...puedo ganarles a todos..
Frosty Stillwell at 2008-03-16 02:13:38cool
goos music guys! FAAAABulous
iusfiu at 2008-03-17 03:06:03kuyioerug
loihnvj ioujegkj oiieurtlkj n
at 2008-04-05 12:05:05Loved every second of it.
This is a random person saying Hello to you! I could not have enjoyed music any better than your fantastic suite. Absolute favorite has to be "Sunrise" but all of them were fantastic. I honestly do look forward to anything new you come up with. I know this is rather late, but it's things like this that make me want to yell "This is what Music is!" Good day.
Speak
Handle:
Title:
Comment:
Enter this text:
username: password: