好吧,我有一個頻率發生器,它使用AudioTrack發送PCM數據到硬件。下面是我使用的代碼:Android AudioTrack緩衝問題
private class playSoundTask extends AsyncTask<Void, Void, Void> {
float frequency;
float increment;
float angle = 0;
short samples[] = new short[1024];
@Override
protected void onPreExecute() {
int minSize = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
track = new AudioTrack(AudioManager.STREAM_MUSIC, 44100,
AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,
minSize, AudioTrack.MODE_STREAM);
track.play();
}
@Override
protected Void doInBackground(Void... params) {
while(Main.this.isPlaying)
{
for(int i = 0; i < samples.length; i++)
{
frequency = (float)Main.this.slider.getProgress();
increment = (float)(2*Math.PI) * frequency/44100;
samples[i] = (short)((float)Math.sin(angle)*Short.MAX_VALUE);
angle += increment;
}
track.write(samples, 0, samples.length);
}
return null;
}
}
頻率被綁定到一個滑動條,以及正確的值在樣本生成環被報告。當我啓動應用程序時,一切都很好。當您沿着滑動條拖動手指時,您會聽到清晰的聲音。但在大約10秒鐘後,音頻開始變得激動起來。而不是平滑的掃描,它是交錯的,並且只在每個1000Hz左右改變音調。任何想法可能會導致這種情況?
下面是情況下,所有的代碼問題出在別處:
public class Main extends Activity implements OnClickListener, OnSeekBarChangeListener {
AudioTrack track;
SeekBar slider;
ImageButton playButton;
TextView display;
boolean isPlaying=false;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
display = (TextView) findViewById(R.id.display);
display.setText("5000 Hz");
slider = (SeekBar) findViewById(R.id.slider);
slider.setMax(20000);
slider.setProgress(5000);
slider.setOnSeekBarChangeListener(this);
playButton = (ImageButton) findViewById(R.id.play);
playButton.setOnClickListener(this);
}
private class playSoundTask extends AsyncTask<Void, Void, Void> {
float frequency;
float increment;
float angle = 0;
short samples[] = new short[1024];
@Override
protected void onPreExecute() {
int minSize = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
track = new AudioTrack(AudioManager.STREAM_MUSIC, 44100,
AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,
minSize, AudioTrack.MODE_STREAM);
track.play();
}
@Override
protected Void doInBackground(Void... params) {
while(Main.this.isPlaying)
{
for(int i = 0; i < samples.length; i++)
{
frequency = (float)Main.this.slider.getProgress();
increment = (float)(2*Math.PI) * frequency/44100;
samples[i] = (short)((float)Math.sin(angle)*Short.MAX_VALUE);
angle += increment;
}
track.write(samples, 0, samples.length);
}
return null;
}
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
display.setText(""+progress+" Hz");
}
public void onClick(View v) {
if (isPlaying) {
stop();
} else {
start();
}
}
public void stop() {
isPlaying=false;
playButton.setImageResource(R.drawable.play);
}
public void start() {
isPlaying=true;
playButton.setImageResource(R.drawable.stop);
new playSoundTask().execute();
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onStop() {
super.onStop();
//Store state
stop();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
}
不直接回答你的問題,但作爲一個附註,請注意,有一個進度條和流的已知問題:http://code.google.com/p/android/issues/detail?id=4124 雖然你的問題不是進度條本身,而是音頻流。因此,不是針對您的問題的解決方案,但是由於您使用音頻流,因此您應該知道其中存在一個或多個開放的錯誤。 – 2010-07-22 04:35:32
我有完全相同的問題。緩衝區越大,越晚開始。在日誌中,我看到很多非常長的GC(GC在4200ms內清理了180個對象)。我沒有做任何分配。在DDMS分配跟蹤器中,似乎AudioTrack本身正在進行分配。不確定GC是否與跳躍有關。你有解決這個問題嗎? – 2011-02-26 11:35:49
你有沒有清理過你的「audiotrack」?它可能是一個內存相關的問題 – 2014-09-08 12:49:56