Android AudioTrack does not play all samples

I use 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. I have 20 tones, but it only plays from 2 to 17.5 tones. And yes, it even stops in the 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 ideas? Thanks!

+8
android audiotrack
source share
2 answers

Garbage collection probably causes this problem. I wrote this code in a method that returns immediately, since the audioTrack object will lose a reference to it. If garbage collection occurs during playback, audioTrack will complete and tones will stop playing. Thus, this problem sometimes occurs, depending on how active the GC is when playing tones.

Therefore, I need to save the reference to the audioTrack object until the end of playback. I think there are many ways to do this, but finally I use the simplest way:

 class Player { private static AudioTrack sAudioTrack; } 

MediaPlayer also has this error, and that’s how I found the problem, since it will record the log that it completed before the release.

0
source share

You are using AudioTrack.MODE_STATIC, designed for short sounds and low-latency requirements, while you should use AudioTrack.MODE_STREAM. AudioTrack.MODE_STREAM is for longer streams, but I don't know how long your samples are. So you can try changing AudioTrack:

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

In addition, AudioTrack requires a buffer size in bytes, the multiplicity must be multiplied by two in order to calculate the correct number of bytes needed. You can hack it like this:

 audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, generatedSnd.length*2, AudioTrack.MODE_STREAM); 
+2
source share

All Articles