Multiple AudioTracks, Single Thread or Multiple?
In my application, I will be creating multiple Audio Tracks, some of which will need to play simultaneously. I'm going to use MODE_STREAM
and write data in as the app runs. Sounds are going to be dynamically generated, which is why I use Audio Track as op开发者_如何学编程posed to anything else.
I have 4 options, I believe:
- AsyncTask
- One UI thread and one thread that manages all the AudioTrack playing
- One UI thread and one thread for each AudioTrack
- One UI thread and a Thread Pool
Which of the four methods would be the best way to manage multiple AudioTracks?
I think Thread Pool is the way to go, but I'm not positive as I haven't actually used it.
Any advice would be greatly appreciated
For simplicity, I was just creating a new thread every time I played an AudioTrack.
But, regardless it really doesn't matter. I found that when trying to play more than one AudioTrack at a time, there's a crackling/choppy sound. I believe this is just an issue with the Android system, not with my app.
As of API level 9 (gingerbread) I can apply a session id to an audio track, which I believe would let me play it with SoundPool, which should make the playing of multiple AudioTracks at once much smoother.
Right now, due to how many users are still on 2.2 and the fact that I don't have a gingerbread device, I will put this project aside until later.
I think your best bet for this would be AsyncTask.
Create an AsyncTask for every AudioTrack, and execute them with an Excecutor (on my Android 4.4, only the first task will be executed, if no Excecutor is used). Here is an example of streaming a microphone signal to AudioTrack and a audio file stream to an other AudioTrack in parallel.
/** Task for streaming file recording to speaker. */
private class PlayerTask extends AsyncTask<Null, Null, Null> {
private short[] buffer;
private int bufferSize;
private final AudioTrack audioTrack;
...
@Override
protected Null doInBackground(final Null... params) {
...
while (!isCancelled()) {
audioTrack.write(buffer, 0, bufferSize);
}
...
}
}
/** Task for streaming microphone to speaker. */
private class MicTask extends AsyncTask<Null, Null, Null> {
private short[] buffer;
private int bufferSize;
private final AudioTrack audioTrack;
...
@Override
protected Null doInBackground(final Null... params) {
...
while (!isCancelled()) {
audioTrack.write(buffer, 0, bufferSize);
}
...
}
}
/** On the UI-thread starting both tasks in parallel to hear
both sources on the speaker. **/
PlayerTask playerTask = new PlayerTask();
playerTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, new Null());
MicTask micTask = new MicTask();
micTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, new Null());
精彩评论