2011-04-05 137 views
1

我试图播放音频时单击按钮,但之间有一段时间之间,当我按下按钮,当音频实际播放。我得到这个错误:AudioFlinger(17396): write blocked for 162 msecs, 3 delayed writes, thread 0x15440这是我走到这一步:延迟在Android的音频

ImageButton i = (ImageButton)findViewById(R.id.button); 
     i.setOnTouchListener(new OnTouchListener() { 

      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       if(event.getAction() == MotionEvent.ACTION_DOWN){ 
        s = new AudioPlayer(getApplicationContext()); 
        s.playSound(R.raw.conga1); 
      } 
      return true; 
      } 
     }); 

AudioPlayer类

public class AudioPlayer { 

    private MediaPlayer mediaPlayer; 
    private final OnCompletionListener mediaPlayerListener = new MediaPlayerListener(); 
    private Context context = null; 

    public AudioPlayer(Context context) 
    { 
    this.context = context; 
    init(); 
    } 

    private void init() { 
    if (mediaPlayer == null) { 
     AudioManager am = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE); 
     int streamVolume = am.getStreamVolume(AudioManager.STREAM_MUSIC); 
     mediaPlayer = new MediaPlayer(); 
     mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); 
     mediaPlayer.setOnCompletionListener(mediaPlayerListener); 
     mediaPlayer.setVolume(streamVolume, streamVolume); 
    } 
    } 

    private void setSound(int id) { 
    if (mediaPlayer!=null) { 
     mediaPlayer.reset(); 
     AssetFileDescriptor file = context.getResources().openRawResourceFd(id); 
     try { 
     mediaPlayer.setDataSource(file.getFileDescriptor(), file.getStartOffset(), file.getLength()); 
     file.close(); 
     mediaPlayer.prepare(); 
     } catch (IOException e) { 
     mediaPlayer = null; 
     } 
    } 
    } 

    public void playSound(int id) { 
    if (mediaPlayer!=null) { 
     setSound(id); 
     mediaPlayer.start(); 
    } 
    } 

    private static class MediaPlayerListener implements OnCompletionListener { 
    public void onCompletion(MediaPlayer mediaPlayer) { 
     mediaPlayer.seekTo(0); 
    } 
    } 
} 

任何线索?

在此先感谢。

EDITS: 所以我添加了一个单身人士,它有帮助,但仍有延迟。这是怎么看起来像现在:

AudioPlayer:

public static synchronized AudioPlayer getSingletonObject(Context context, Uri pathToFile) { 
    if (audioPlayer == null) { 
     audioPlayer = new AudioPlayer(context, pathToFile); 
    } 
    return audioPlayer; 
} 

public void setSound(String pathToFile) { 
    if (mediaPlayer!=null) { 
     mediaPlayer.reset(); 

     try { 
      mediaPlayer.setDataSource(pathToFile); 
      mediaPlayer.prepareAsync(); 
     } //catch.... 
    } 
} 

public void playSound(String path) { 
    if (mediaPlayer!=null) { 
     mediaPlayer.reset(); 

     try { 
      mediaPlayer.setDataSource(path); 
      mediaPlayer.prepareAsync(); 
      mediaPlayer.start(); 
     } //catch... 
    } 
} 

主营:

final String path = "sdcard/myappsounds/snaredrum2.wav"; 
    final AudioPlayer s = AudioPlayer.getSingletonObject(getApplicationContext(), Uri.parse(path)); 
    s.setSound(path); 

    ImageButton i = (ImageButton)findViewById(R.id.button); 
    i.setOnTouchListener(new OnTouchListener() { 

     @Override 
     public boolean onTouch(View v, MotionEvent event) { 
      if(event.getAction() == MotionEvent.ACTION_DOWN){ 

       s.playSound(path); 
     } 
     return true; 
     } 
    }); 

任何想法?我想要做的就像鼓组,这就是为什么按钮必须正确响应。

回答

0

Android上的I/O是slow。音频子系统正在被迫等待它的数据,并提供足够的警告。

而不是给MediaPlayer一个原始的FileDescriptor(它没有应用缓冲)尝试使用file:// URI。运气好的话,文件系统内容提供商:会在你打开它的时候为你缓冲它。

+0

很想看到这方面的一些基准 - 我敢肯定你是对的 – 2011-04-05 14:10:15

+0

我试图做到这一点,因为你说没有运气。它仍然播放延迟。这是我得到的:'mediaPlayer.setDataSource(pathToFile); \t \t \t \t mediaPlayer.prepare();其中'pathToFile'是一个字符串。任何线索? – madcoderz 2011-04-06 12:13:43

+0

你给文件:// URI?如果这不起作用,请在按下按钮之前调用setDataSource()和prepare()。这意味着数据的所有准备就绪都是按下按钮。 – 2011-04-06 13:42:46

0

我并不真正了解Android,但是从这段代码看你可以尝试的是使用AudioPlayer作为单例并重用MediaPlayer实例?