Tuesday, May 3, 2016

Android AudioTrack does not play all samples

Leave a Comment

I'm using AudioTrack to play a sequence of sine waves, but when I run it on my HTC M9, it plays only part of the samples, and how long it will play is random. e. g. I have 20 tones to play, but it only plays like 2 to 17.5 tones of them. And yes it even will stop in middle of a tone.

Here is my code, from another answer:

    ArrayList<double[]> samples = new ArrayList<>();     int numSamples = 0;     for (final ToneSegment seg : sequence) {         int num =  seg.getDuration() * sampleRate / 1000;         double[] sample = new double[num];         for (int i = 0; i < num; ++i) {             sample[i] = Math.sin(2 * Math.PI * i * seg.getPitch() / sampleRate);         }         samples.add(sample);         numSamples += num;     }      byte generatedSnd[] = new byte[2 * numSamples];     int idx = 0;     for (double[] sample : samples) {         for (final double dVal : sample) {             final short val = (short) ((dVal * 32767));             generatedSnd[idx++] = (byte) (val & 0x00ff);             generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);         }     }      audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,             sampleRate, AudioFormat.CHANNEL_OUT_MONO,             AudioFormat.ENCODING_PCM_16BIT, generatedSnd.length,             AudioTrack.MODE_STATIC);     audioTrack.write(generatedSnd, 0, generatedSnd.length);     audioTrack.play(); 

Does anyone have any idea? Thanks!

1 Answers

Answers 1

You are using AudioTrack.MODE_STATIC that is meant for short sounds and low-latency requirements while you should use AudioTrack.MODE_STREAM. AudioTrack.MODE_STREAM is meant for longer streams, but I do not know how long your samples are. So you can try and change AudioTrack:

audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,         sampleRate, AudioFormat.CHANNEL_OUT_MONO,         AudioFormat.ENCODING_PCM_16BIT, generatedSnd.length,         AudioTrack.MODE_STREAM); 

Also The AudioTrack requires the buffer size in bytes, a short needs to be multiplied by two to calculate the correct amount of required bytes. You could hack it in like this :

audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,         sampleRate, AudioFormat.CHANNEL_OUT_MONO,         AudioFormat.ENCODING_PCM_16BIT, generatedSnd.length*2,         AudioTrack.MODE_STREAM); 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment