tags:

views:

18

answers:

0

I'm trying to make a real-time audio application on android.

As OnPlaybackPositionUpdateListener seems never working on any versions of android, I'm on a workaround using separate thread that keeps writing on a buffer of an AudioTrack instance. track.write() seems to be a blocking call and it doesn't insanely write data on the buffer.

Below is a simple program that repeats 12 notes from A to G#.

It makes all 12 kinds of sounds right after it launches, but within a minute it makes only 2 kinds of sounds (A# and F). track.getPlaybackHeadPosition() returns ~ 4,000,000 when it's playing 2 notes. It was reproduced on nexus one and emulator running froyo.

Would there be any workaround like resetting AudioTrack periodically?

public class Sound extends Activity 
{
    static final String TAG="Sound";
    AudioTrack track;

    float increment; 
    float angle = 0;
    float step = 0;
    short[] buffer;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        final int minSize = AudioTrack.getMinBufferSize( 48000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT );        
        buffer = new short[minSize];
        track = new AudioTrack( AudioManager.STREAM_MUSIC, 48000, 
                               AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, 
                               minSize, AudioTrack.MODE_STREAM);
        track.play();        

        new Thread(new Runnable() {
            public void run() {
                while(true) {
                    float frequency=880*(float)Math.pow(2.0,step);
                    increment = (float)(2*Math.PI) * frequency / 48000.0f; 
                    step+=1.0f/12;
                    if(step>=0.99) step=0;

                    for( int i = 0; i < buffer.length; i++, angle += increment) {
                        buffer[i] = (short)(Short.MAX_VALUE/2 * Math.sin( angle ));
                    }
                    track.flush();
                    track.write(buffer, 0, buffer.length);
                }
            }
        }).start();

    }

Thanks