Home Reading a .wav file in java
Reply: 0

Reading a .wav file in java

user4682
1#
user4682 Published in July 23, 2018, 1:26 pm

I am working on an audio project and am using this audio library. It has a method that reads wav files and returns a double array with values from -1 to 1 (44100 values per second of audio). All the methods in this library seem to use the same double array format for saving audio.

The method, however, just doesn't work. Here is a sample of a wav file I fed it, and here is a recording of what the program read that file as (turn down volume before listening).
It is not the same length as the original file and is distorted. Here is the code behind that method (TL;DR read my comment below before reading through):

public static double[] read(String filename) {
        byte[] data = readByte(filename);
        int n = data.length;
        double[] d = new double[n/2];
        for (int i = 0; i < n/2; i++) {
            d[i] = ((short) (((data[2*i+1] & 0xFF) << 8) + (data[2*i] & 0xFF))) / ((double) Short.MAX_VALUE);
        }
        return d;
    }

    // return data as a byte array
    private static byte[] readByte(String filename) {
        byte[] data = null;
        AudioInputStream ais = null;
        try {

            // try to read from file
            File file = new File(filename);
            if (file.exists()) {
                ais = AudioSystem.getAudioInputStream(file);
                int bytesToRead = ais.available();
                data = new byte[bytesToRead];
                int bytesRead = ais.read(data);
                if (bytesToRead != bytesRead)
                    throw new IllegalStateException("read only " + bytesRead + " of " + bytesToRead + " bytes"); 
            }

            // try to read from URL
            else {
                URL url = StdAudio.class.getResource(filename);
                ais = AudioSystem.getAudioInputStream(url);
                int bytesToRead = ais.available();
                data = new byte[bytesToRead];
                int bytesRead = ais.read(data);
                if (bytesToRead != bytesRead)
                    throw new IllegalStateException("read only " + bytesRead + " of " + bytesToRead + " bytes"); 
            }
        }
        catch (IOException e) {
            throw new IllegalArgumentException("could not read '" + filename + "'", e);
        }

        catch (UnsupportedAudioFileException e) {
            throw new IllegalArgumentException("unsupported audio format: '" + filename + "'", e);
        }

        return data;
    }

I tested the length of the byte array that the readByte() method returns (that the read() method uses) and it is 49016 places. The original clip is 4 seconds, and at a 44100 sample rate the array should be around 44100*4 places. The distorted audio is a little bit over a second duration which matches the length of the distorted wav file so I think the problem is in the readByte() method. I could be wrong (someone let me know if so), but because of that I think the problem is in this code. Eliminating the exception handlers here is that code (which returns an array of bytes):

    byte[] data = null;
    AudioInputStream ais = null;
    try {

        // try to read from file
        File file = new File(filename);
        if (file.exists()) {
            ais = AudioSystem.getAudioInputStream(file);
            int bytesToRead = ais.available();
            data = new byte[bytesToRead];
            int bytesRead = ais.read(data);
            if (bytesToRead != bytesRead)
                throw new IllegalStateException("read only " + bytesRead + " of " + bytesToRead + " bytes"); 
        }

        // try to read from URL
        else {
            URL url = StdAudio.class.getResource(filename);
            ais = AudioSystem.getAudioInputStream(url);
            int bytesToRead = ais.available();
            data = new byte[bytesToRead];
            int bytesRead = ais.read(data);
            if (bytesToRead != bytesRead)
                throw new IllegalStateException("read only " + bytesRead + " of " + bytesToRead + " bytes"); 
        }
    } 

...

    return data;

Why is the data that this byte array fetches distorted?

EDIT: I tried converting the wav file I'm trying to play to around half the sample rate and it seemed to play normally (still a bit off). Here is the resultant recording. Any ideas how to change the code to get it to read 44100 sample rate files? Does the "getAudioInputStream" method assume a lower sample rate than 44100? This library says that it "Assumes the audio is monaural, with sampling rate of 44,100" so this seems like a bug.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.313633 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO