Android AudioTrack playing .wav file, getting only white noise
Asked Answered
M

3

7

When I play a file with the following code:

private void PlayAudioFileViaAudioTrack(int ResId) throws IOException {

    int intSize = android.media.AudioTrack.getMinBufferSize(11025, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);

    AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 11025, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, intSize,
            AudioTrack.MODE_STREAM);

    int count = 256 * 1024; // 256 kb
    byte[] byteData = null;
    byteData = new byte[(int) count];
    InputStream in = null;
    AssetFileDescriptor fd = null;
    fd = mResources.openRawResourceFd(ResId);
    in = mResources.openRawResource(ResId);

    int bytesRead = 0, amount = 0;
    int size = (int) fd.getLength();
    at.play();
    while (bytesRead < size) {
        amount = in.read(byteData, 0, count);
        if (amount != -1) {
            at.write(byteData, 0, amount);
        }
    }
    in.close();
    at.stop();
    at.release();

}

The only thing I hear is static, white noise. I've checked that my .wav file has the same properties (samplerate,bitrate). I don't have to much knowledge about raw audio data(PCM), so I was wondering if anyone could see what's wrong with my code.

Millar answered 10/9, 2011 at 15:45 Comment(0)
D
8

from your code i can see that you just read data from the wav file and just import them to the AudioTrack. Wav files have a small header as you can see here https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ So you have to skip the header and point your file descriptor at the right place where the actual audio data are.

Also when you playing an audio file and you are dealing with byte operations you should take care of the Endianess. Take a look here Using AudioTrack in Android to play a WAV file

Below my code (some checks and the WAV header skip are missing) that works in both Nexus One and Galaxy S with a wav file with frequency 8000Hz and 16 bit encoding.

public void playWav(){
    int minBufferSize = AudioTrack.getMinBufferSize(8000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
    int bufferSize = 512;
    AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM);
    String filepath = Environment.getExternalStorageDirectory().getAbsolutePath();

    int i = 0;
    byte[] s = new byte[bufferSize];
    try {
        FileInputStream fin = new FileInputStream(filepath + "/REFERENCE.wav");
        DataInputStream dis = new DataInputStream(fin);

        at.play();
        while((i = dis.read(s, 0, bufferSize)) > -1){
            at.write(s, 0, i);

        }
        at.stop();
        at.release();
        dis.close();
        fin.close();

    } catch (FileNotFoundException e) {
        // TODO
        e.printStackTrace();
    } catch (IOException e) {
        // TODO
        e.printStackTrace();
    }       
}
Duston answered 14/9, 2011 at 21:52 Comment(6)
The header would just be enough for a few milliseconds of sound, it should play normal after that. Could you explain to me what you mean with 'take care of the Endianess'?Millar
Oh, sorry my mistake about Endianess. I thought that you were reading the data as shorts but you are reading as bytes so endianess it's not a problem here. To be sure I wrote a small program (i can provide the source code) that reads the .wav file and writes it to AudioTrack. It plays the wav file normally at my phone. Perhaps your configuration parameters at the constructor of AudioTrack may be wrong. Have you checked the properties of your wav file? Maybe it has different sampling frequency or encoding.Duston
Hmmm, quite strange... I added at my first answer my code. As you can see the way that I handle AudioTrack is the same. The only difference is the file opening and reading. Add some debug messages to logcat to see if something goes wrong at these operations.Duston
I'd suggest two more experiments: 1) try zeroing out the buffer and writing it - no white noise must be present in this case; 2) try reversing the shorts (that is, force endian conversion)Clackmannan
@Manos: Nice code. Is it possible to change byte[] s to short[] s? Because I want to compute RMS from that data but it only correct for short[] type. ThanksPneumonia
@user8264, yeah that it is possible. You have to use the write() function of AudioTrack that takes as parameter a vector of shorts.Duston
N
-1

That looks WAY more complicated than what I did. I played sounds using this. I think .wav files would work just as well.

MediaPlayer mpPlayProgram = new MediaPlayer();
mpPlayProgram.setDataSource("/sdcard/file.mp3");
mpPlayProgram.prepare();
mpPlayProgram.start();
mpPlayProgram.release();

For static resources, it's even easier:

MediaPlayer mpStart = MediaPlayer.create(this, resID);
mpStart.start();
mpStart.release();
Non answered 13/9, 2011 at 16:8 Comment(1)
I'm not using the MediaPlayer class because it's very high level. I'm using AudioTrack, wich is better for what i'm doing.Millar
M
-1

If you have saved file in wav format and want to play it using AudioTrack then follow this code:

             File file=new File(Environment.getExternalStorageDirectory()+"/AudioRecorder/fahim.wav");

               InputStream is;
             DataInputStream         dis = null ;
             BufferedInputStream     bis;

            try 
            {
                is = new FileInputStream(file);
                bis = new BufferedInputStream(is, 8000);
                dis  = new DataInputStream(bis);      //  Create a DataInputStream to read the audio data from the saved file

            }
            catch (FileNotFoundException e1) 
            {
                ShowToast("fILE NOT FOUND:"+e1.getMessage());
            }

            int i = 0;                                                          //  Read the file into the "music" array
            music=new byte[(int) file.length()];
            try 
            {
                while (dis.available() > 0)
                {
                    music[i] = dis.readByte();                                      //  This assignment does not reverse the order
                    i++;
                }
            } 
            catch (IOException e) 
            {
                ShowToast("I/O Exception:"+e.getMessage());
            }

            try {dis.close();} catch (IOException e) {e.printStackTrace();}

            int minBufferSize = AudioTrack.getMinBufferSize(11025, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);

            AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 11025, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM);
            at.play();

            ShowToast("size:"+music.length);
            //*/
            at.write(music, 0, music.length);
Modesta answered 6/9, 2015 at 7:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.