Ok, tengo un generador de frecuencia que usa AudioTrack para enviar datos de PCM al hardware. Aquí está el código que estoy usando para ello:Problemas de almacenamiento en el búfer de AudioTrack de Android
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;
}
}
La frecuencia está ligada a una barra deslizante, y se notifica el valor correcto en el circuito de generación de muestra. Todo está bien y elegante cuando inicio la aplicación. Cuando arrastras el dedo por la barra deslizante obtienes un buen sonido de barrido. Pero después de unos 10 segundos de jugar con él, el audio comienza a ponerse nervioso. En lugar de un barrido suave, está escalonado, y solo cambia el tono alrededor de cada 1000 Hz más o menos. ¿Alguna idea de qué puede estar causando esto?
Aquí es todo el código en caso de que el problema radica en otro lugar:
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
}
}
no respondiendo directamente a su pregunta, pero como nota al margen, tenga en cuenta que existe un problema conocido con la barra de progreso y la transmisión: http://code.google.com/p/android/issues/detail?id=4124 Aunque su problema no está en la barra de progreso sino en la transmisión de audio. Por lo tanto, no es una solución a su problema, pero dado que trabaja con transmisión de audio, debe tener en cuenta que hay uno o más errores abiertos. –
Tengo exactamente el mismo problema. Cuanto más grande es el buffer, más tarde comienza el salto. En el registro veo muchos GC muy largos (GC limpió 180 objetos en 4200ms). No estoy haciendo ninguna asignación. En el rastreador de asignación DDMS parece que el AudioTrack mismo está haciendo asignaciones. No estoy seguro si los GC tienen que ver con el salto. ¿Has resuelto esto? –
¿alguna vez limpias tu "audiotrack"? puede ser un problema relacionado con la memoria –