Android Audio-Programmierung Albtraum - Soundpool, Audiotrack Arrghh?

Ich habe eine einfache Musiksequenzer-Android-App erstellt, die mehrere Audiodateien wiedergibt.

Ursprünglich verwendete ich SoundPool zum Abspielen von MP3-Dateien und es funktionierte perfekt auf 2.3.4 mit einem alten HTC Droid Incredible. Dann habe ich es auf einem Galaxy Nexus mit 4.3 getestet und die Leistung war horrend. Das Audio-Timing war überall und es gab Pannen / Klicks / Pops.

Daher habe ich mehrere Tage damit verbracht, einen Player mit AudioTrack einschließlich eines MP3-Decoders zu entwickeln, der sowohl auf dem Galaxy als auch auf dem HTC einwandfrei funktioniert. Jetzt habe ich es gerade auf einem Nexus 4 (mit 4.3) getestet und die Leistung ist schrecklich - das Timing ist allgegenwärtig. SoundPool bietet auf diesem Gerät sogar eine bessere Leistung.

Ich bin sehr frustriert und weiß nicht, was ich tun soll, um meine App fertigzustellen. Ich würde mich sehr freuen, wenn mir jemand helfen könnte. Ich habe einige Codebeispiele meines Audio-Players unten aufgeführt. Ich habe alles versucht, was mir einfällt, einschließlich der Änderung der Puffergröße mitAudioTrack.MODE_STATIC usw. Die neuen Google-Geräte haben eine geringe Audio-Latenz. Es ist also sehr merkwürdig, wie alles auf meinem alten Droiden besser funktioniert.

Danke im Voraus

/**
* Play note
*/
public void playNote(String note, float vol)
{
    PlayThread oldThread = threadMap.get(note);
    if(oldThread != null) {
        //Cancel timer
        if(oldThread.timer != null) {
            oldThread.timer.cancel();
            oldThread.timer.purge();
            oldThread.timer = null;
        }
        //Stop
        oldThread.requestStop();
        threadMap.remove(note);
    }

    //Play if within Polyphony
    if(threadMap.size() < POLYPHONY) {
        PlayThread thread = new PlayThread(note, vol);
        thread.start();
        threadMap.put(note, thread);
    }       
}


/**
* Stop note
*/
public void stopNote(String note, int fadeDurationInMs)
{   
    PlayThread thread = threadMap.get(note);
    if(thread != null) {
        thread.fadeOut(fadeDurationInMs);
        threadMap.remove(note);
    }
}


/**
* Stop all
*/
public void stopAllPlaying(int fadeDurationInMs)
{
    for(PlayThread thread : threadMap.values()) {
        if(thread != null) {
            thread.fadeOut(fadeDurationInMs);
        }
    }
    threadMap.clear();
}


/**
* PlayThread
*/
private class PlayThread extends Thread
{
    String note;
    float vol;
    float fadeVol;
    boolean stop;
    AudioTrack audioTrack;
    Timer timer;

    /**
    * Constructor
    */
    public PlayThread(String note, float vol)
    {
        super();
        this.note = note;
        this.vol = vol;
        this.fadeVol = vol;
    }

    /**
    * Run
    */
    public void run()
    {
        try {
            android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);

            //Create buffer
            int bufferSize = AudioTrack.getMinBufferSize(SAMPLE_RATE, CHANNELS, AudioFormat.ENCODING_PCM_16BIT);
            Log.v(Constants.TAG, "min buffersize = " + bufferSize);

            bufferSize = bufferSize * 2;

            byte[] buffer = new byte[bufferSize];

            //AudioTrack
            audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, SAMPLE_RATE, CHANNELS, AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM);
            audioTrack.setStereoVolume(vol, vol);
            audioTrack.play();

            //Get byte data
            byte[] byteData = sampleMap.get(note);

            //Convert to input stream
            InputStream input = new ByteArrayInputStream(byteData);

            //Write to audioTrack
            int bytesRead = 0;
            while(!stop && (bytesRead = input.read(buffer)) != -1) {
                    audioTrack.write(buffer, 0, bytesRead);
            }

            //When finished...
            audioTrack.stop();
            audioTrack.release();
            input.close();
            killThread(this);
        }
        catch(Exception e) {}
    }

    /**
    * Set volume
    */
    private synchronized void setVol(float newVol)
    {
        audioTrack.setStereoVolume(newVol, newVol);
    }

    /**
    * Update volume
    */
    private synchronized void lowerVol()
    {
        fadeVol -= 0.01;
        if(fadeVol < 0) vol = 0;
        audioTrack.setStereoVolume(fadeVol, fadeVol);
    }

    /**
    * Fade out
    */
    public synchronized void fadeOut(int fadeDurationInMs)
    {
        //Start decreasing volume
        if(fadeDurationInMs > 0) {
            timer = new Timer(true);
            TimerTask timerTask = new TimerTask()
            {
                @Override
                public void run()
                {
                    //If thread killed while running
                    try {
                        //Lower volume
                        lowerVol();
                    }
                    catch (Exception e) {}

                    //Stop when volume reaches 0
                    if(fadeVol <= 0) {
                        if(timer != null) {
                            timer.cancel();
                            timer.purge();
                        }
                        stop = true;
                    }
                }
            };

            //Calculate delay, set to 1 if zero
            int delay = (int) (fadeDurationInMs / (vol * 100)); 
            if(delay == 0) delay = 1;

            timer.schedule(timerTask, delay, delay);
        }
    }

    /**
    * Request stop
    */
    public synchronized void requestStop()
    {
        //Stop click/pop when stopping sample
        setVol(0.01f);
        setVol(0.005f);
        stop = true;
    }

    /**
    * Kill Thread
    */
    private synchronized void killThread(Thread theThread)
    {
        if(theThread != null) {
            theThread = null;
        }
    }

}

Antworten auf die Frage(3)

Ihre Antwort auf die Frage