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!
However, most low-level audio APIs including Android’s AudioTrack can only accept linear PCM. That’s why if we can’t keep the entire sample in memory, we have to deal with streaming, circular buffers and other clever ways to feed audio to the API.
There may be various reasons why you want to play WAV audio on an AudioTrack. Sometimes the size limitations of SoundPool or the latency and high resource usage of MediaPlayer will make you consider going that way. Sometimes you need to modify the audio or mix it on the fly.
However, the problem now is getting that data from a source. Many applications that need to use AudioTrack do not generate PCM audio from scratch (an example of an app that does that would be Ethereal Dialpad and other similar apps).
When changing sample rates after an audio track is created, differences of around 5 to 10 percent from the original rate may trigger a filter recomputation when downsampling (to properly suppress aliasing). This can consume computing resources and may cause an audible click if the filter is replaced in real time.
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 love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With