2011-04-05 207 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實例?