2

I'm trying to write a Java application that manipulates high resolution .wav files. I'm having trouble importing the audio data, i.e. converting the .wav file into an array of doubles.

When I use a standard approach an exception is thrown.

AudioFileFormat as = AudioSystem.getAudioFileFormat(new File("orig.wav"));
-->
javax.sound.sampled.UnsupportedAudioFileException: file is not a supported file type

Here's the file format info according to soxi:


dB$ soxi orig.wav
soxi WARN wav: wave header missing FmtExt chunk

Input File : 'orig.wav' Channels : 8 Sample Rate : 96000 Precision : 24-bit Duration : 00:00:03.16 = 303526 samples ~ 237.13 CDDA sectors File Size : 9.71M Bit Rate : 24.6M Sample Encoding: 32-bit Floating Point PCM

Can anyone suggest the simplest method for getting this audio into Java?

I've tried using a few techniques. As stated above, I've experimented with the Java AudioSystem (on both Mac and Windows). I've also tried using Andrew Greensted's WavFile class, but this also fails (WavFileException: Compression Code 3 not supported). One workaround is to convert the audio to 16 bits using sox (with the -b 16 flag), but this is suboptimal since it increases the noise floor.

Incidentally, I've noticed that the file CAN be read by libsndfile. Is my best bet to write a jni wrapper around libsndfile, or can you suggest something quicker?

Note that I don't need to play the audio, I just need to analyze it, manipulate it, and then write it out to a new .wav file.

* UPDATE *

I solved this problem by modifying Andrew Greensted's WavFile class. His original version only read files encoded as integer values ("format code 1"); my files were encoded as floats ("format code 3"), and that's what was causing the problem.

I'll post the modified version of Greensted's code when I get a chance. In the meantime, if anyone wants it, send me a message.

dB'
  • 7,838
  • 15
  • 58
  • 101

2 Answers2

2

Very late reply but others might benefit from this.

A libsndfile java wrapper now exists, which should help with audio read/write/conversion issues like this. The wrapper (generated by swig) is true to the libsndfile API, so the structure is a little different from typical Java style, but entirely usable.

In your particular case, usage would look something like this:

String filePath = "path/to/some/audio_8_channels.wav";

// open the sound file
SF_INFO sndInfo = new SF_INFO();
SWIGTYPE_p_SNDFILE_tag sndFile = libsndfile.sf_open(filePath, libsndfile.SFM_READ, sndInfo);

// create a buffer array large enough to hold all channels (double per channel) of all frames
int arraySize = sndInfo.getFrames() * sndInfo.getChannels();
CArrayDouble darray = new CArrayDouble(arraySize);

// read every frame (includes all channels) into the buffer array
long count = libsndfile.sf_readf_double(sndFile, darray.cast(), sndInfo.getFrames());

// iterate over the doubles that make up the audio
for (int i=0; i < arraySize; i++) {
    // every 8 doubles is a frame..
    double d = darray.getitem(i);
}

The google code project, including a compiled 'usable' version for JDK1.7 on Windows7 exists here:

http://code.google.com/p/libsndfile-java/

Matt M
  • 751
  • 1
  • 9
  • 19
1

You could read the wav data in yourself, it's actually not that hard to do. Just search for the WAV file format information.

Rocky Pulley
  • 22,531
  • 20
  • 68
  • 106
  • Ok, I'll give this a try. Thanks. :) I'll post my solution here once I figure it out. – dB' Jun 24 '11 at 22:18