2013-07-22 38 views
1

我正在實施一個Android應用程序來處理PCM聲音數據(對於很長的聲音即音樂曲目)。 我決定使用AudioTrack類來播放音樂,但它不能放在與活動相同的線程中,因爲阻止了整個應用程序 - 這裏是問題 - 我應該將AudioTrack操作放在單獨的線程中或在異步任務(或任何其他選項)?什麼是最好的方法? 我需要播放/暫停/停止並更改音樂文件。使用Android的最佳方式Audiotrack

現在我試圖通過java線程來管理它,並且它幾乎可以正常播放,幾乎可以暫停(它會「放棄」聲音的一部分),但是當我更改音樂文件時,以前是不停止和theres混合輸出(我認爲我的線程實現有問題)。

而且 - 不,我不能在這個應用程序中使用MediaPlayer(我想在運行中修改PCM數據)。

我正在尋找一些幫助谷歌和這裏在stackoverflow,但沒有任何幫助。

這是我目前的實現,如果有人想看看。

public class AudioPlayerManager { 

private AudioTrack track; 
private Thread thread; 
private AudioTrackThread trackThread = new AudioTrackThread(); 

public int getPlayState() { 
    return track.getPlayState(); 
} 

public int getAudioSession() { 
    return track.getAudioSessionId(); 
} 

class AudioTrackThread implements Runnable { 
    private String filePath = "/music/wav/musicfile.wav"; 

    @Override 
    public void run() { 
     try { 
      playWaveFile(); 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void playWaveFile() throws FileNotFoundException {  
     int minSize = AudioTrack.getMinBufferSize(44100, 
       AudioFormat.CHANNEL_OUT_STEREO, 
       AudioFormat.ENCODING_PCM_16BIT); 
     track = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, 
       AudioFormat.CHANNEL_OUT_STEREO, 
       AudioFormat.ENCODING_PCM_16BIT, minSize, 
       AudioTrack.MODE_STREAM); 

     File file = new File(FileListingUtils.getExternalStorageRootFile(), 
       filePath); 
     InputStream is = new FileInputStream(file); 

     byte[] music = new byte[512]; 
     track.play(); 

     try { 
      handleSound(is, music); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     track.stop(); 
     track.release(); 
    } 

    private void handleSound(InputStream is, byte[] music) 
      throws IOException { 
     int i; 
     while ((i = is.read(music)) != -1) { 
      track.write(music, 0, i); 
     } 
    } 
} 

public void playNew() { 
    if (track != null) { 
     track.stop(); 
     //track.flush(); 
     track.release(); 
    } 

    thread = new Thread(trackThread); 
    thread.start(); 
} 

public void playOrResume() { 
    this.track.play(); 
} 

public void pause() { 
    this.track.pause(); 
} 

}

感謝每一個幫助!

M.

回答

1

您的線程生命週期似乎並不正確。首先,每當播放停止或結束時,必須關閉(中斷)當前線程,並創建線程的新實例並關閉舊線程。

其次,您從線索外部呼叫track.stop()。您必須在您的線程中實施公共停止方法,然後在其中插入終止代碼,然後在您的playNew()方法中調用yourthread.stop()。

所以這裏是僞代碼:

public void playNew() { 

//the following if clause should go to thread's stop() method. 
    // if (track != null) { 
    // track.stop(); 
//track.flush(); 
// track.release(); 
// } 
    //create a new thread if its null 
if(thread ==null){ 
thread = new Thread(new AudioTrackThread()); 
thread.start();} 
//stop the current thread 
else{ 
thread.stop(); 
thread=null;} 
} 

你實現,冥冥中,我讀了播放音樂,服務和線程將有關android documentation服務和線程更好的option.Read。

+0

謝謝您的回覆!但不幸的是效果是一樣的。我已經改變了我的實現一點點,現在一切工作正常,除了加載下一個軌道。但我將來會回到這個問題上。 謝謝! – Michal

+0

不客氣。請張貼您可能對其他人有幫助的答案。 –

+1

請問答案在哪裏? –