开发者

Playing audio is too slow in Android

开发者 https://www.devze.com 2023-03-10 06:44 出处:网络
I\'m having a problem with Android\'s MediaPlayer in that it is too slow when calling the prepare method. I\'ve tried to simply keep a Vector of the few MediaPlayer objects (with their preloaded data

I'm having a problem with Android's MediaPlayer in that it is too slow when calling the prepare method. I've tried to simply keep a Vector of the few MediaPlayer objects (with their preloaded data sources) but calling .start() multiple times results in weird issues.

The first issue is it will skip every other play, and sometimes the play will be half (or less) as loud.

The tones played are very very s开发者_StackOverflow中文版hort but need to be played as quickly as possible. My source code is posted below.

Any help is greatly appreciated.

Kevin

package com.atClass.lemon;

import java.util.Vector;

import com.atClass.cardShoe.SettingTools.SETTING_PREF;
import com.atClass.cardShoe.SettingTools.SETTING_STUB;
import com.atClass.cardShoe.SettingTools.SETTING_VALUE;

import android.content.res.AssetFileDescriptor;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.util.Config;
import android.util.Log;

public class MediaHandler {
    public static int cRepeat;
    public static float cVolume = Integer.valueOf(Prefs.cPrefsGet.getString(SETTING_PREF.annunciator_volume.name()+SETTING_STUB._int.name(), PrefDefaults.getDefault(SETTING_PREF.annunciator_volume,SETTING_STUB._int)));
    public static boolean cVolumeEnabled = !(Prefs.cPrefsGet.getString(SETTING_PREF.annunciator_volume.name()+SETTING_STUB._value.name(),PrefDefaults.getDefault(SETTING_PREF.annunciator_volume)).equals(SETTING_VALUE.disabled.name()));

    static Vector <MediaPlayer> cQuickMediaPlayerList = new Vector<MediaPlayer>();

    public static enum AUDIO_CLIP {
        app_boot_sound(R.raw.windows_hardware_insert),
        app_results_sound(R.raw.windows_exclamation),
        app_warning_sound(R.raw.windows_hardware_fail),
        app_card_draw_sound(R.raw.fs_beep5),
        app_lid_open_sound(R.raw.windows_hardware_fail),
        app_top_tigger_overdraw_sound(R.raw.fs_beep6),
        test(R.raw.fs_beep4);

        private int enumResourceId;
        AUDIO_CLIP(int input){ enumResourceId = input;}
        int getItem(){return enumResourceId;}
    }

    public static int getAudioClipIndex(AUDIO_CLIP iAudioClip){
        for (int i=0; i<AUDIO_CLIP.values().length; i++){
            if (AUDIO_CLIP.values()[i] == iAudioClip){
                return i;
            }
        }

        return 0;
    }


    public static void setupQuickMediaPlayer(){
        cQuickMediaPlayerList.clear();
        for (int i=0; i<AUDIO_CLIP.values().length; i++){

            MediaPlayer lMediaPlayer = new MediaPlayer();
            final AssetFileDescriptor afd = Global.gContext.getResources().openRawResourceFd(AUDIO_CLIP.values()[i].getItem());
            try{
                lMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
                afd.close();
                lMediaPlayer.prepare();
            }catch(Exception e){}
            lMediaPlayer.setVolume(cVolume,cVolume);
            lMediaPlayer.setLooping(false);
            lMediaPlayer.setOnCompletionListener(new OnCompletionListener(){
                @Override
                public void onCompletion(MediaPlayer lMediaPlayer) {
                    lMediaPlayer.release();
                    try{lMediaPlayer.prepare();}catch(Exception e){e.printStackTrace();}
                }});
            cQuickMediaPlayerList.add(lMediaPlayer);
        }
    }

    public static void playAudio(AUDIO_CLIP iAudioClip){
        float volume = cVolume;

        volume++;
        volume /= 10;

        playAudio(iAudioClip,volume);
    }

    public static void playAudio(final AUDIO_CLIP iAudioClip, final float iVolume){

        Thread lThread = new Thread(new Runnable(){
            public void run() {
                //int resourceId = iAudioClip.getItem();                
                Log.d(Global.TAG,"--> Playing audio clip: " + iAudioClip.name() + "," + iAudioClip.getItem() + "," + getAudioClipIndex(iAudioClip));

                if (cVolumeEnabled == true){

                    //Log.d(Global.TAG,"--> Supplying volume: " + iVolume);
                    //Works but is too slow
//                  try {
//                      final MediaPlayer lMediaPlayer = new MediaPlayer();
//                      AssetFileDescriptor afd = Global.gContext.getResources().openRawResourceFd(iAudioClip.getItem());
//                      lMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
//                      afd.close();
//                      lMediaPlayer.prepare();
//                      lMediaPlayer.setVolume(iVolume,iVolume);
//                      lMediaPlayer.setLooping(false);
//                      lMediaPlayer.setOnCompletionListener(new OnCompletionListener(){
//                          @Override
//                          public void onCompletion(MediaPlayer arg0) {
//                              lMediaPlayer.release();
//                          }});
//                      lMediaPlayer.start();
//                  }catch(Exception e){}

                    try{
                        //Works half the time
                        cQuickMediaPlayerList.get(getAudioClipIndex(iAudioClip)).start();
                    }catch(Exception e){}
                }
            }
        });
        lThread.setPriority(Thread.MAX_PRIORITY);
        lThread.start();
    }
}


You should use SoundPool instead: http://developer.android.com/reference/android/media/SoundPool.html


In your onCompletionListener, you call release(), followed by prepare(). This is illegal, and is probably why you're having problems starting them multiple times. If you want to call it again, don't use release(), because that frees all the resources for the MP, and should only be called when you are done with it. Use stop() instead.

However, this still won't speed up the prepare(). You might want to try seekTo(0) instead, but even then it might not be as fast as you want. It really depends on how fast you're talking about.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号